diff --git a/Makefile.setting.in b/Makefile.setting.in
--- a/Makefile.setting.in
+++ b/Makefile.setting.in
@@ -5,73 +5,4 @@
 # OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 # See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
-SETTINGSGEN      = !!SETTINGSGEN!!
-ENDIAN_CHECK     = !!ENDIAN_CHECK!!
-SRC_DIR          = !!SRC_DIR!!
-CXX_BUILD        = !!CXX_BUILD!!
-CFLAGS_BUILD     = !!CFLAGS_BUILD!!
-LDFLAGS_BUILD    = !!LDFLAGS_BUILD!!
-STAGE            = !!STAGE!!
-SETTING_OBJS_DIR = !!SETTING_OBJS_DIR!!
-
-ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK)
-
-# Check if we want to show what we are doing
-ifdef VERBOSE
-	Q =
-	E = @true
-else
-	Q = @
-	E = @echo
-endif
-
-all: table/settings.h
-
-settingsgen.o: $(SRC_DIR)/settingsgen/settingsgen.cpp $(SRC_DIR)/string_func.h $(SRC_DIR)/strings_type.h $(SRC_DIR)/misc/getoptdata.h $(SRC_DIR)/ini_type.h $(SRC_DIR)/core/smallvec_type.hpp
-	$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
-	$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
-
-alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp endian_host.h
-	$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
-	$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
-
-getoptdata.o: $(SRC_DIR)/misc/getoptdata.cpp $(SRC_DIR)/misc/getoptdata.h
-	$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/misc/%.cpp=%.cpp)'
-	$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
-
-string.o: $(SRC_DIR)/string.cpp endian_host.h
-	$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
-	$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
-
-ini_load.o: $(SRC_DIR)/ini_load.cpp $(SRC_DIR)/core/alloc_func.hpp $(SRC_DIR)/core/mem_func.hpp $(SRC_DIR)/ini_type.h $(SRC_DIR)/string_func.h
-	$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
-	$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
-
-$(SETTINGSGEN): alloc_func.o string.o ini_load.o settingsgen.o getoptdata.o
-	$(E) '$(STAGE) Compiling and Linking $@'
-	$(Q)$(CXX_BUILD) $(LDFLAGS_BUILD) $^ -o $@
-
-table/settings.h: $(SETTINGSGEN) $(SRC_DIR)/table/settings.h.preamble $(SRC_DIR)/table/settings.h.postamble $(SRC_DIR)/table/*.ini
-	$(E) '$(STAGE) Generating $@'
-	@mkdir -p table
-	$(Q)./$(SETTINGSGEN) -o table/settings.h -b $(SRC_DIR)/table/settings.h.preamble -a $(SRC_DIR)/table/settings.h.postamble $(SRC_DIR)/table/*.ini
-
-# The targets to compile the endian-code
-
-endian_host.h: $(ENDIAN_CHECK)
-	$(E) '$(STAGE) Testing endianness for host'
-	$(Q)./$(ENDIAN_CHECK) > $@
-
-$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
-	$(E) '$(STAGE) Compiling and Linking $@'
-	$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $< -o $@
-
-depend:
-
-clean:
-	$(E) '$(STAGE) Cleaning up settings files'
-	$(Q)rm -f settingsgen.o alloc_func.o getoptdata.o ini_load.o $(SETTINGSGEN) $(ENDIAN_TARGETS) table/settings.h
-
-mrproper: clean
-
-.PHONY: all mrproper depend clean
+# thanks but no thanks for now.
diff --git a/Makefile.src.in b/Makefile.src.in
--- a/Makefile.src.in
+++ b/Makefile.src.in
@@ -23,7 +23,6 @@
 LANG_DIR       = !!LANG_DIR!!
 SRC_OBJS_DIR   = !!SRC_OBJS_DIR!!
 LANG_OBJS_DIR  = !!LANG_OBJS_DIR!!
-SETTING_OBJS_DIR= !!SETTING_OBJS_DIR!!
 SRC_DIR        = !!SRC_DIR!!
 SCRIPT_SRC_DIR = !!SCRIPT_SRC_DIR!!
 MEDIA_DIR      = !!MEDIA_DIR!!
@@ -58,8 +57,8 @@
 RES      := $(shell mkdir -p $(BIN_DIR) $(sort $(dir $(OBJS))))
 
 # Make sure endian_target.h is reasable as if it was in the src/ dir
-CFLAGS += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR)
-CFLAGS_MAKEDEP += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR)
+CFLAGS += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR)
+CFLAGS_MAKEDEP += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR)
 ifdef SCRIPT_SRC_DIR
 	CFLAGS_MAKEDEP += -I $(SCRIPT_SRC_DIR)
 endif
diff --git a/bin/data/Readme.txt b/bin/data/Readme.txt
new file mode 100644
--- /dev/null
+++ b/bin/data/Readme.txt
@@ -0,0 +1,39 @@
+For the patchpack to work correctly you need to copy the following grfs in your data folder (not in the newgrf folder):
+
+- the flat_blacktiles.grf,
+- the copypaste grf and
+- One of the trafficlights_xxx.grfs  and rename it to trafficlights.grf
+  (There are three versions. I have copied the light version and renamed it
+  correctly, but you can choose to use another by simply applying the correct name of it.
+  while removing the correctly named one first)
+- the speedsignals.grf
+- the progsiganals.grf
+
+You can choose to put them in the shared folder or near your executable file, both methods will work.
+Note: You should not put it in the download/data folder (this folder is to be used by bananas only).
+
+
+Credits and lisence for the attached grfs:
+
+- flat_blacktiles.grf : Sprites mikeel, code Chillcore.
+                        GPL lisence.
+- copypaste.grf       : Sprites and code Frostregen.
+                        GPL lisence.
+                        Besides changing the sprites to Dos I have not changed anything.
+- trafficlights.grf(s): Sprites and code Roujin.
+                        unknown lisence. (But as the sprites are meant to go into the openttd.grf assumed GPL.)
+                        Besides removing the debugging sprite and changing the sprites to DOS I have not changed anything.
+- speedsignals.grf    : Sprites and code ChillCore.
+                        GPL lisence.
+                        Poles extracted from the OpenGFX baseset, but repainted with DOS palette
+                        Offsets reused from the OpenGFX baseset.
+- progsignals.grf     : Sprites and code chillCore.
+                        GPL lisence.
+                        sprites extracted from the OpenGFX baseset, but repainted to DOS palette and added different colour to the boards.
+                        Offsets reused from the OpenGFX baseset.
+
+ChillCore.
+
+
+ps:
+See COPYING.txt for GPL liscence details and version.
diff --git a/bin/data/chipp_grf_sources/copypaste.nfo b/bin/data/chipp_grf_sources/copypaste.nfo
new file mode 100644
--- /dev/null
+++ b/bin/data/chipp_grf_sources/copypaste.nfo
@@ -0,0 +1,28 @@
+// Automatically generated by GRFCODEC. Do not modify!
+// (Info version 7)
+// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>>
+// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C
+// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D%
+// Format: spritenum pcxfile xpos ypos compression ysize xsize xrel yrel
+    0 sprites/copypaste.png 18 8 01 20 20 0 0
+    1 sprites/copypaste.png 50 8 01 20 20 0 0
+    2 sprites/copypaste.png 82 8 01 20 20 0 0
+    3 sprites/copypaste.png 114 8 01 20 20 0 0
+    4 sprites/copypaste.png 146 8 01 20 20 0 0
+    5 sprites/copypaste.png 178 8 01 20 20 0 0
+    6 sprites/copypaste.png 210 8 01 20 20 0 0
+    7 sprites/copypaste.png 242 8 01 20 20 0 0
+    8 sprites/copypaste.png 274 8 01 32 32 0 0
+    9 sprites/copypaste.png 322 8 01 32 32 0 0
+   10 sprites/copypaste.png 370 8 01 20 20 0 0
+   11 sprites/copypaste.png 402 8 01 20 20 0 0
+   12 sprites/copypaste.png 434 8 01 20 20 0 0
+   13 sprites/copypaste.png 466 8 01 20 20 0 0
+   14 sprites/copypaste.png 498 8 01 20 20 0 0
+   15 sprites/copypaste.png 530 8 01 20 20 0 0
+   16 sprites/copypaste.png 562 8 01 20 20 0 0
+   17 sprites/copypaste.png 594 8 01 20 20 0 0
+   18 sprites/copypaste.png 626 8 01 20 20 0 0
+   19 sprites/copypaste.png 658 8 01 20 20 0 0
+   20 sprites/copypaste.png 690 8 01 20 20 0 0
+   21 sprites/copypaste.png 722 8 01 20 20 0 0
diff --git a/bin/data/chipp_grf_sources/copypaste.png b/bin/data/chipp_grf_sources/copypaste.png
new file mode 100644
index 0000000000000000000000000000000000000000..55835fe4a5edc844bb2a9af975fd14b1ef4b6bd5
GIT binary patch
diff --git a/bin/data/chipp_grf_sources/flat_blacktiles.nfo b/bin/data/chipp_grf_sources/flat_blacktiles.nfo
new file mode 100644
--- /dev/null
+++ b/bin/data/chipp_grf_sources/flat_blacktiles.nfo
@@ -0,0 +1,25 @@
+// Automatically generated by GRFCODEC. Do not modify!
+// (Info version 7)
+// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>>
+// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C
+// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D%
+// Format: spritenum pcxfile xpos ypos compression ysize xsize xrel yrel
+    0 sprites/flat_blacktiles.png 18 8 09 31 64 -31 0
+    1 sprites/flat_blacktiles.png 98 8 09 31 64 -31 0
+    2 sprites/flat_blacktiles.png 178 8 09 23 64 -31 0
+    3 sprites/flat_blacktiles.png 258 8 09 23 64 -31 0
+    4 sprites/flat_blacktiles.png 338 8 09 31 64 -31 0
+    5 sprites/flat_blacktiles.png 418 8 09 31 64 -31 0
+    6 sprites/flat_blacktiles.png 498 8 09 23 64 -31 0
+    7 sprites/flat_blacktiles.png 578 8 09 23 64 -31 0
+    8 sprites/flat_blacktiles.png 658 8 09 39 64 -31 -8
+    9 sprites/flat_blacktiles.png 2 72 09 39 64 -31 -8
+   10 sprites/flat_blacktiles.png 82 72 09 31 64 -31 -8
+   11 sprites/flat_blacktiles.png 162 72 09 31 64 -31 -8
+   12 sprites/flat_blacktiles.png 242 72 09 39 64 -31 -8
+   13 sprites/flat_blacktiles.png 322 72 09 39 64 -31 -8
+   14 sprites/flat_blacktiles.png 402 72 09 31 64 -31 -8
+   15 sprites/flat_blacktiles.png 482 72 09 47 64 -31 -16
+   16 sprites/flat_blacktiles.png 562 72 09 15 64 -31 0
+   17 sprites/flat_blacktiles.png 642 72 09 31 64 -31 -8
+   18 sprites/flat_blacktiles.png 722 72 09 31 64 -31 -8
diff --git a/bin/data/chipp_grf_sources/flat_blacktiles.png b/bin/data/chipp_grf_sources/flat_blacktiles.png
new file mode 100644
index 0000000000000000000000000000000000000000..4cf8190194aee48593d00bbea628eb712f37873a
GIT binary patch
diff --git a/bin/data/chipp_grf_sources/progsignals.nfo b/bin/data/chipp_grf_sources/progsignals.nfo
new file mode 100644
--- /dev/null
+++ b/bin/data/chipp_grf_sources/progsignals.nfo
@@ -0,0 +1,38 @@
+// Automatically generated by GRFCODEC. Do not modify!
+// (Info version 7)
+// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>>
+// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C
+// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D%
+// Format: spritenum pcxfile xpos ypos compression ysize xsize xrel yrel
+    0 sprites/progsignals.png 18 8 01 21 11 -8 -19
+    1 sprites/progsignals.png 34 8 01 23 10 -8 -21
+    2 sprites/progsignals.png 50 8 01 23 10 -7 -21
+    3 sprites/progsignals.png 66 8 01 26 8 -5 -24
+    4 sprites/progsignals.png 82 8 01 21 11 -7 -19
+    5 sprites/progsignals.png 98 8 01 23 10 -6 -21
+    6 sprites/progsignals.png 114 8 01 23 10 1 -21
+    7 sprites/progsignals.png 130 8 01 26 8 1 -24
+    8 sprites/progsignals.png 146 8 01 23 5 0 -21
+    9 sprites/progsignals.png 162 8 01 26 5 0 -24
+   10 sprites/progsignals.png 178 8 01 21 5 -2 -19
+   11 sprites/progsignals.png 194 8 01 24 5 -2 -22
+   12 sprites/progsignals.png 210 8 01 21 12 0 -19
+   13 sprites/progsignals.png 242 8 01 24 9 0 -22
+   14 sprites/progsignals.png 258 8 01 21 12 -9 -19
+   15 sprites/progsignals.png 290 8 01 24 9 -6 -22
+   16 sprites/progsignals.png 306 8 01 20 3 -2 -20
+   17 sprites/progsignals.png 322 8 01 20 3 -2 -20
+   18 sprites/progsignals.png 338 8 01 20 4 -1 -20
+   19 sprites/progsignals.png 354 8 01 20 4 -1 -20
+   20 sprites/progsignals.png 370 8 01 20 4 -1 -20
+   21 sprites/progsignals.png 386 8 01 20 4 -1 -20
+   22 sprites/progsignals.png 402 8 01 20 3 -1 -20
+   23 sprites/progsignals.png 418 8 01 20 3 -1 -20
+   24 sprites/progsignals.png 434 8 01 20 4 -1 -20
+   25 sprites/progsignals.png 450 8 01 20 4 -1 -20
+   26 sprites/progsignals.png 466 8 01 20 4 -2 -20
+   27 sprites/progsignals.png 482 8 01 20 4 -2 -20
+   28 sprites/progsignals.png 498 8 01 20 4 -3 -20
+   29 sprites/progsignals.png 514 8 01 20 4 -3 -20
+   30 sprites/progsignals.png 530 8 01 20 4 -3 -20
+   31 sprites/progsignals.png 546 8 01 20 4 -3 -20
diff --git a/bin/data/chipp_grf_sources/progsignals.png b/bin/data/chipp_grf_sources/progsignals.png
new file mode 100644
index 0000000000000000000000000000000000000000..f3761a9417dac07bda7206a945844f268a14bf66
GIT binary patch
diff --git a/bin/data/chipp_grf_sources/speedsignals.nfo b/bin/data/chipp_grf_sources/speedsignals.nfo
new file mode 100644
--- /dev/null
+++ b/bin/data/chipp_grf_sources/speedsignals.nfo
@@ -0,0 +1,38 @@
+// Automatically generated by GRFCODEC. Do not modify!
+// (Info version 7)
+// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>>
+// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C
+// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D%
+// Format: spritenum pcxfile xpos ypos compression ysize xsize xrel yrel
+    0 sprites/speedsignals.png 18 8 01 22 5 -2 -20
+    1 sprites/speedsignals.png 34 8 01 22 5 -2 -20
+    2 sprites/speedsignals.png 50 8 01 22 4 -1 -20
+    3 sprites/speedsignals.png 66 8 01 22 4 -1 -20
+    4 sprites/speedsignals.png 82 8 01 22 4 -1 -20
+    5 sprites/speedsignals.png 98 8 01 22 4 -1 -20
+    6 sprites/speedsignals.png 114 8 01 22 5 -1 -20
+    7 sprites/speedsignals.png 130 8 01 22 5 -1 -20
+    8 sprites/speedsignals.png 146 8 01 22 5 -1 -20
+    9 sprites/speedsignals.png 162 8 01 22 5 -1 -20
+   10 sprites/speedsignals.png 178 8 01 22 5 -2 -20
+   11 sprites/speedsignals.png 194 8 01 22 5 -2 -20
+   12 sprites/speedsignals.png 210 8 01 22 6 -3 -20
+   13 sprites/speedsignals.png 226 8 01 22 6 -3 -20
+   14 sprites/speedsignals.png 242 8 01 22 6 -3 -20
+   15 sprites/speedsignals.png 258 8 01 22 6 -3 -20
+   16 sprites/speedsignals.png 274 8 01 22 5 -2 -20
+   17 sprites/speedsignals.png 290 8 01 22 5 -2 -20
+   18 sprites/speedsignals.png 306 8 01 22 4 -1 -20
+   19 sprites/speedsignals.png 322 8 01 22 4 -1 -20
+   20 sprites/speedsignals.png 338 8 01 22 4 -1 -20
+   21 sprites/speedsignals.png 354 8 01 22 4 -1 -20
+   22 sprites/speedsignals.png 370 8 01 22 5 -1 -20
+   23 sprites/speedsignals.png 386 8 01 22 5 -1 -20
+   24 sprites/speedsignals.png 402 8 01 22 5 -1 -20
+   25 sprites/speedsignals.png 418 8 01 22 5 -1 -20
+   26 sprites/speedsignals.png 434 8 01 22 5 -2 -20
+   27 sprites/speedsignals.png 450 8 01 22 5 -2 -20
+   28 sprites/speedsignals.png 466 8 01 22 6 -3 -20
+   29 sprites/speedsignals.png 482 8 01 22 6 -3 -20
+   30 sprites/speedsignals.png 498 8 01 22 6 -3 -20
+   31 sprites/speedsignals.png 514 8 01 22 6 -3 -20
diff --git a/bin/data/chipp_grf_sources/speedsignals.png b/bin/data/chipp_grf_sources/speedsignals.png
new file mode 100644
index 0000000000000000000000000000000000000000..c10f4e56fb90f8e4d11eaee9a79dda2fb940a046
GIT binary patch
diff --git a/bin/data/chipp_grf_sources/trafficlights_dark.nfo b/bin/data/chipp_grf_sources/trafficlights_dark.nfo
new file mode 100644
--- /dev/null
+++ b/bin/data/chipp_grf_sources/trafficlights_dark.nfo
@@ -0,0 +1,28 @@
+// Automatically generated by GRFCODEC. Do not modify!
+// (Info version 7)
+// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>>
+// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C
+// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D%
+// Format: spritenum pcxfile xpos ypos compression ysize xsize xrel yrel
+    0 sprites/trafficlights_dark.png 18 8 01 20 20 0 0
+    1 sprites/trafficlights_dark.png 50 8 01 31 31 0 0
+    2 sprites/trafficlights_dark.png 98 8 01 14 4 -4 -12
+    3 sprites/trafficlights_dark.png 114 8 01 14 4 -4 -12
+    4 sprites/trafficlights_dark.png 130 8 01 14 4 -4 -12
+    5 sprites/trafficlights_dark.png 146 8 01 14 4 -4 -12
+    6 sprites/trafficlights_dark.png 162 8 01 14 4 -4 -12
+    7 sprites/trafficlights_dark.png 178 8 01 14 4 -2 -12
+    8 sprites/trafficlights_dark.png 194 8 01 14 4 -2 -12
+    9 sprites/trafficlights_dark.png 210 8 01 14 4 -2 -12
+   10 sprites/trafficlights_dark.png 226 8 01 14 4 -2 -12
+   11 sprites/trafficlights_dark.png 242 8 01 14 4 -2 -12
+   12 sprites/trafficlights_dark.png 258 8 01 14 4 -4 -12
+   13 sprites/trafficlights_dark.png 274 8 01 14 4 -4 -12
+   14 sprites/trafficlights_dark.png 290 8 01 14 4 -4 -12
+   15 sprites/trafficlights_dark.png 306 8 01 14 4 -4 -12
+   16 sprites/trafficlights_dark.png 322 8 01 14 4 -4 -12
+   17 sprites/trafficlights_dark.png 338 8 01 14 4 -2 -12
+   18 sprites/trafficlights_dark.png 354 8 01 14 4 -2 -12
+   19 sprites/trafficlights_dark.png 370 8 01 14 4 -2 -12
+   20 sprites/trafficlights_dark.png 386 8 01 14 4 -2 -12
+   21 sprites/trafficlights_dark.png 402 8 01 14 4 -2 -12
diff --git a/bin/data/chipp_grf_sources/trafficlights_dark.png b/bin/data/chipp_grf_sources/trafficlights_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..b3db7424bee28824731f4fffa5ccf2cc87b205b7
GIT binary patch
diff --git a/bin/data/chipp_grf_sources/trafficlights_light.nfo b/bin/data/chipp_grf_sources/trafficlights_light.nfo
new file mode 100644
--- /dev/null
+++ b/bin/data/chipp_grf_sources/trafficlights_light.nfo
@@ -0,0 +1,28 @@
+// Automatically generated by GRFCODEC. Do not modify!
+// (Info version 7)
+// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>>
+// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C
+// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D%
+// Format: spritenum pcxfile xpos ypos compression ysize xsize xrel yrel
+    0 sprites/trafficlights_light.png 18 8 01 20 20 0 0
+    1 sprites/trafficlights_light.png 50 8 01 31 31 0 0
+    2 sprites/trafficlights_light.png 98 8 01 14 4 -4 -12
+    3 sprites/trafficlights_light.png 114 8 01 14 4 -4 -12
+    4 sprites/trafficlights_light.png 130 8 01 14 4 -4 -12
+    5 sprites/trafficlights_light.png 146 8 01 14 4 -4 -12
+    6 sprites/trafficlights_light.png 162 8 01 14 4 -4 -12
+    7 sprites/trafficlights_light.png 178 8 01 14 4 -2 -12
+    8 sprites/trafficlights_light.png 194 8 01 14 4 -2 -12
+    9 sprites/trafficlights_light.png 210 8 01 14 4 -2 -12
+   10 sprites/trafficlights_light.png 226 8 01 14 4 -2 -12
+   11 sprites/trafficlights_light.png 242 8 01 14 4 -2 -12
+   12 sprites/trafficlights_light.png 258 8 01 14 4 -4 -12
+   13 sprites/trafficlights_light.png 274 8 01 14 4 -4 -12
+   14 sprites/trafficlights_light.png 290 8 01 14 4 -4 -12
+   15 sprites/trafficlights_light.png 306 8 01 14 4 -4 -12
+   16 sprites/trafficlights_light.png 322 8 01 14 4 -4 -12
+   17 sprites/trafficlights_light.png 338 8 01 14 4 -2 -12
+   18 sprites/trafficlights_light.png 354 8 01 14 4 -2 -12
+   19 sprites/trafficlights_light.png 370 8 01 14 4 -2 -12
+   20 sprites/trafficlights_light.png 386 8 01 14 4 -2 -12
+   21 sprites/trafficlights_light.png 402 8 01 14 4 -2 -12
diff --git a/bin/data/chipp_grf_sources/trafficlights_light.png b/bin/data/chipp_grf_sources/trafficlights_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..de1dde26a49e7e9becd68e69ac9983fed6f94271
GIT binary patch
diff --git a/bin/data/chipp_grf_sources/trafficlights_wooden.nfo b/bin/data/chipp_grf_sources/trafficlights_wooden.nfo
new file mode 100644
--- /dev/null
+++ b/bin/data/chipp_grf_sources/trafficlights_wooden.nfo
@@ -0,0 +1,28 @@
+// Automatically generated by GRFCODEC. Do not modify!
+// (Info version 7)
+// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>>
+// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C
+// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D%
+// Format: spritenum pcxfile xpos ypos compression ysize xsize xrel yrel
+    0 sprites/trafficlights_wooden.png 18 8 01 20 20 0 0
+    1 sprites/trafficlights_wooden.png 50 8 01 31 31 0 0
+    2 sprites/trafficlights_wooden.png 98 8 01 14 4 -4 -12
+    3 sprites/trafficlights_wooden.png 114 8 01 14 4 -4 -12
+    4 sprites/trafficlights_wooden.png 130 8 01 14 4 -4 -12
+    5 sprites/trafficlights_wooden.png 146 8 01 14 4 -4 -12
+    6 sprites/trafficlights_wooden.png 162 8 01 14 4 -4 -12
+    7 sprites/trafficlights_wooden.png 178 8 01 14 4 -2 -12
+    8 sprites/trafficlights_wooden.png 194 8 01 14 4 -2 -12
+    9 sprites/trafficlights_wooden.png 210 8 01 14 4 -2 -12
+   10 sprites/trafficlights_wooden.png 226 8 01 14 4 -2 -12
+   11 sprites/trafficlights_wooden.png 242 8 01 14 4 -2 -12
+   12 sprites/trafficlights_wooden.png 258 8 01 14 4 -4 -12
+   13 sprites/trafficlights_wooden.png 274 8 01 14 4 -4 -12
+   14 sprites/trafficlights_wooden.png 290 8 01 14 4 -4 -12
+   15 sprites/trafficlights_wooden.png 306 8 01 14 4 -4 -12
+   16 sprites/trafficlights_wooden.png 322 8 01 14 4 -4 -12
+   17 sprites/trafficlights_wooden.png 338 8 01 14 4 -2 -12
+   18 sprites/trafficlights_wooden.png 354 8 01 14 4 -2 -12
+   19 sprites/trafficlights_wooden.png 370 8 01 14 4 -2 -12
+   20 sprites/trafficlights_wooden.png 386 8 01 14 4 -2 -12
+   21 sprites/trafficlights_wooden.png 402 8 01 14 4 -2 -12
diff --git a/bin/data/chipp_grf_sources/trafficlights_wooden.png b/bin/data/chipp_grf_sources/trafficlights_wooden.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb4b00d14913ebd9535ed085253d6a352738339d
GIT binary patch
diff --git a/bin/data/copypaste.grf b/bin/data/copypaste.grf
new file mode 100644
index 0000000000000000000000000000000000000000..be0664346a55995313316251ac068a0c1c62f866
GIT binary patch
diff --git a/bin/data/flat_blacktiles.grf b/bin/data/flat_blacktiles.grf
new file mode 100644
index 0000000000000000000000000000000000000000..7cea4e129cdaa80c83431e2b8a380fed205c095a
GIT binary patch
diff --git a/bin/data/progsignals.grf b/bin/data/progsignals.grf
new file mode 100644
index 0000000000000000000000000000000000000000..facb08c0a01f095229637d587da53116dffdb9a6
GIT binary patch
diff --git a/bin/data/speedsignals.grf b/bin/data/speedsignals.grf
new file mode 100644
index 0000000000000000000000000000000000000000..b5d6488f01f189f29540528440d704faeb85bfc0
GIT binary patch
diff --git a/bin/data/trafficlights.grf b/bin/data/trafficlights.grf
new file mode 100644
index 0000000000000000000000000000000000000000..def76c5420a4ff65a8ef13bd71405ddb9d881097
GIT binary patch
diff --git a/bin/data/trafficlights_dark.grf b/bin/data/trafficlights_dark.grf
new file mode 100644
index 0000000000000000000000000000000000000000..a68b99852c5f15bcec4a819e704694b8c8187445
GIT binary patch
diff --git a/bin/data/trafficlights_light.grf b/bin/data/trafficlights_light.grf
new file mode 100644
index 0000000000000000000000000000000000000000..def76c5420a4ff65a8ef13bd71405ddb9d881097
GIT binary patch
diff --git a/bin/data/trafficlights_wooden.grf b/bin/data/trafficlights_wooden.grf
new file mode 100644
index 0000000000000000000000000000000000000000..98e229436a2dfaa1512f6ee997492191c91113b1
GIT binary patch
diff --git a/chipp_changelog.txt b/chipp_changelog.txt
new file mode 100644
--- /dev/null
+++ b/chipp_changelog.txt
@@ -0,0 +1,918 @@
+Chill's Patchpack v13:
+---------------------
+
+About: A glimpse on what OpenTTD could look like in the future,
+       minus the bugs ofcourse ;)
+
+Why:   ChillCore having fun and giving something back to
+       a very generous community while learning C++ ...
+
+Big thank you goes to:
+       - OpenTTD Developers and patchwriters
+           Thank you for writing and maintaining all this great stuff,
+           also for the many assistance you have given me.
+       - Playtesters, bugreporters
+           Thank you for the many feedback and bugreports.
+       - Chris Saywer, Simon Foster and John Broomhall
+           Thank you for having made one of the greatest games ever.
+
+
+=========================================================================
+=     ¿BUGS?      http://www.tt-forums.net/viewtopic.php?f=33&t=47622   =
+=========================================================================
+
+
+Included patches:
+ ---------------
+          tags:     - Patch included (in some form) currently.
+          ----   T  - Made it to TRUNK. !!! Congrats to you !!!
+                 W  - not in the patchpack currently, needs work
+                      -> read: needs bumping to trunk and or fixing. 
+
+    - More height levels:                  http://www.tt-forums.net/viewtopic.php?f=33&t=40844&start=0  (By ic111, CommanderZ, Terkhen, ChillCore)
+    - Cargo distribution:                  http://www.tt-forums.net/viewtopic.php?f=33&t=41992&start=0  (By fonso)
+    - Automated timetable and seperation:  http://www.tt-forums.net/viewtopic.php?f=33&t=46391&start=0  (By Gathers)
+(T) - Improved Build Station GUI:          http://www.tt-forums.net/viewtopic.php?f=33&t=41222&start=0  (By Scoz) (Removed -> trunk in r21755)
+    - Larger maps :                        http://www.tt-forums.net/viewtopic.php?f=33&t=33137&start=0  (By Bilbo)
+    - Town rating colours:                 http://www.tt-forums.net/viewtopic.php?f=33&t=42598&start=0  (By Terkhen)
+    - Signals in tunnels and on bridges:   http://www.tt-forums.net/viewtopic.php?f=33&t=41260&start=0  (By hackalittlebit)
+    - Chunnel:                             http://www.tt-forums.net/viewtopic.php?f=33&t=41775&start=0  (By hackalittlebit)
+(T) - Diesel smoke:                        http://www.tt-forums.net/viewtopic.php?f=33&t=19896&start=0  (By Sirkoz)(Removed -> Trunk in r20376)
+    - Stuck trains:                        http://www.tt-forums.net/viewtopic.php?f=33&t=47095&start=0  (By Eddi)
+    - Sprinkles -> variable daylenght,
+          town cargo factor, misc, ...:    http://www.tt-forums.net/viewtopic.php?f=33&t=46399&start=0  (By SpComb)
+    - Programmable Signals:                http://www.tt-forums.net/viewtopic.php?f=33&t=47690&start=0  (By Owen)
+(T) - Build while paused in editor:        http://www.tt-forums.net/viewtopic.php?f=33&t=42790&start=0  (By Bilbo)(Removed -> Trunk in r21430)
+    - Show system time window:             http://www.tt-forums.net/viewtopic.php?f=33&t=46580&start=0  (By Panther)
+    - Copy_paste:                          http://www.tt-forums.net/viewtopic.php?f=33&t=41259&start=0  (By Frostregen)
+(W) - Split cargo and cargo subtypes
+          in refit window:                 http://www.tt-forums.net/viewtopic.php?f=33&t=48220&start=0  (By Terkhen) (Broken, removed removed in v9_9)
+(W) - Buy bigger area:                     http://www.tt-forums.net/viewtopic.php?f=33&t=29495&start=0  (By rfalke) (Broken, removed in v9)
+    - View and click vehicles in tunnels:  http://dev.openttdcoop.org/projects/clientpatches/repository (By SmatZ)
+    - Close adjacent level crossing:       http://www.tt-forums.net/viewtopic.php?f=33&t=46091&start=0  (By Eddi)
+(T) - Panorama screenshot:                 http://www.tt-forums.net/viewtopic.php?f=33&t=49362&start=0  (By Eddi) (Removed -> Trunk in r20508)
+    - Measurement tool:                    http://www.tt-forums.net/viewtopic.php?f=33&t=49212&start=0  (By Wolf01)
+    - Tree line height:                    http://www.tt-forums.net/viewtopic.php?f=33&t=46786&start=0  (By Loclahost)
+    - Watch other company's gui:           http://www.tt-forums.net/viewtopic.php?f=33&t=45221&start=0  (By Muxy)
+    - Reduced tree growth patch:           http://www.tt-forums.net/viewtopic.php?f=33&t=45502&start=0  (By Gedemon)
+(W) - Vehicle leasing patch:               http://www.tt-forums.net/viewtopic.php?f=33&t=49389&start=0  (By jemmyw) (Broken, removed in v9_9_4)
+    - Max_grf:                             http://www.tt-forums.net/viewtopic.php?f=31&t=37435&start=0  (By muzzy)
+    - Company_profile:                     http://www.tt-forums.net/viewtopic.php?f=33&t=40457&start=0  (By Antuvo)
+    - Departure boards + 24h clock:        http://www.tt-forums.net/viewtopic.php?f=33&t=49956&start=0  (By hthhs)
+    - Timetables_change_all_stations:      http://www.tt-forums.net/viewtopic.php?f=32&t=50274&start=0  (By sph)
+    - Departure_vehicletimetableskip1:     http://www.tt-forums.net/viewtopic.php?f=33&t=49956&start=0  (By hthhs)
+(T) - Natural sorting of strings:          http://bugs.openttd.org/task/4214                            (by MagicBuzz) (Removed -> Trunk in 21344)
+    - Group_info:                          http://www.tt-forums.net/viewtopic.php?f=33&t=33148&start=0  (By MagicBuzz)
+(T) - Partial refit:                       http://www.tt-forums.net/viewtopic.php?f=33&t=51211&start=0  (By Terkhen Removed -> Trunk in r21567)
+    - Cmd_all_ai:                          http://www.tt-forums.net/viewtopic.php?f=33&t=51180&start=0  (By MagicBuzz)
+    - Infrastucture Sharing:               http://www.tt-forums.net/viewtopic.php?f=33&t=42254&start=0  (By Hirundo)
+    - CTRL-cloning does not open new guis: http://bugs.openttd.org/task/4458                            (Idea by DJ Nekkid. Code ChillCore)
+    - Improved breakdowns:                 http://www.tt-forums.net/viewtopic.php?f=33&t=39518&start=0  (by Hirundu)
+    - Trafficlights:                       http://www.tt-forums.net/viewtopic.php?f=33&t=36261&start=0  (by Roujin)
+    - Towngrowth_needs_goods:              Modified patch. See added patches zip.                       (by ChillCore (original by ?))
+    - Configurable amount of desert tiles: See added patches zip                                        (by ChillCore)
+    - Configurable speed signals:          See added patches zip                                        (by hthhs. (extension to the progsig patch))
+    - CD_no oveload patch:                 See added patches zip                                        (by hthhs. (extension to the CargoDist Patch))
+
+Note: In the patchpack many of these patches have been retuned, extended and/or
+      have altered syntax, in some cases I do not use the latest version of
+      a patch. Keep this in mind when reporting bugs to one of the original
+      authors. See first post of my patchpack.
+
+Other features: (without separate patches)
+--------------
+- New seed only when clicking the random button or CTRL-NewGame.
+- Option to disable trains considering the back of a one-way signal as a safe
+  waiting point.
+- Easy difficulty setting replaced by Kidscorner.
+- Option to show the linkgraphs for all companies or only the own company.
+- Configurable tree build drag limit (20-128)
+- Option to display the townpopulation always in white instead of rating coloured 
+- Cheat option to not devide vehicle income bt daylength factor.
+-
+-
+-
+- ... there are more tweaks I have done that could be listed here.
+
+
+GRFs needed in the data folder: (! The patchpack will not run without them !)
+------------------------------
+- flat_blacktiles.grf http://www.tt-forums.net/viewtopic.php?f=33&t=47622
+- copy_paste.grf      http://www.tt-forums.net/viewtopic.php?f=33&t=p440743
+- trafficlights.grf   http://www.tt-forums.net/viewtopic.php?f=33&t=36261
+- speedsignals.grf    see needed grfs zip
+- progsignals.grf     see needed grfs zip
+
+
+New files:
+----------
+(As in the latest version, if compiling an older version check source.list)
+
+- In the src folder:
+    command_queue.h
+    command_queue.cpp
+    copy_paste.h
+    copy_paste.cpp
+    copy_paste_gui.cpp
+    departures.cpp
+    departures_func.h
+    departures_type.h
+    departures_gui.cpp
+    departures_gui.h
+    infrastructure.cpp
+    infrastructure_func.h
+    moving_average.h
+    moving_average.cpp
+    programmable_signals.cpp
+    programmable_signals.h
+    programmable_signals_gui.cpp
+    trafficlight.h
+    trafficlight.cpp
+    trafficlight_func.h
+    trafficlight_type.h
+    watch gui.h
+    watch_gui.cpp
+
+- In the src/core folder:
+    multimap.hpp
+
+- In the src/table folder:
+    settings.h
+
+- In the src/saveload folder:
+    linkgraph_sl.cpp
+    signal_sl.cpp
+
+-In the docs folder:
+    copy_paste_array.txt
+    linkgraph.txt
+
+- create a new folder in the src folder: linkgraph
+- Inside this new folder:
+    demands.cpp
+    flowmapper.cpp
+    linkgraph.cpp
+    mcf.cpp
+    demands.h
+    flowmapper.h
+    linkgraph.h
+    linkgraph_type.h
+    mcf.h
+
+In the main folder:
+    chipp_changelog.txt
+    chipp_todo.txt
+
+
+
+Changelog per version:
+---------------------
+v13_7:
+=====
+Updated:
+- Chunnel patch to v18.
+  Also I have removed the ability to terraform above tunnels. It could
+  Could problems that I was not aware of before.
+
+New files:
+- chipp_changelog.txt
+- chipp_todo.txt
+
+v13_6_7:
+=======
+Added:
+- Russian translation of the ingame strings. (Kraks)
+
+v13_6_6:
+=======
+Fixed:
+- Graphical glitches when updating to OpenGFX 0.3.7.
+
+v13_6_5:
+=======
+fixed:
+- Town gui did not resize when the towngrowth patch kicks in while the town gui
+  is open.
+- Cargodist -> poolsize of stations can shrink too.
+
+v13_6_4:
+=======
+Fixed:
+- hotfix for CargoDist (fonso)
+
+v13_6_3:
+=======
+Added:
+-  <)- Town ratings patch: Option to select white strings only for population
+       numbers.
+
+v13_6_2:
+=======
+Added:
+- configurable Tree drag limit form 20 to 128 in singleplayer
+
+v13_6_1:
+=======
+Reverted:
+- Adjecent Level Crossing patch to previous version ...
+  roadvehicles were running into trains themselves ...
+
+  edit before posting v13_6_7:
+  I will try it again and might re-add it, I did not really test properly.
+  (read: I kept my signals to close to the roqd crossing most likely)
+
+v13_6:
+=====
+Updated:
+- Adjecent level crossings to v3.
+
+Fixed:
+- Sometimes the cheat for not deviding vehicle income by daylenght facor would
+  be enabled even if the player did not enable it. (Most likely caused by
+  the code being confused with previous use of another cheat.)
+
+v13_5
+=====
+Updated:
+- Watch gui patch to v110_2. (compiler warning fixed.)
+
+New GRFs needed:
+- speedsignals.grf
+- progsignals.grf
+
+Fixed:
+- Silly mistake (in the patchpack) while updating the departureboards patch:
+  it was no longer possible no to set timetable start dates. (hthhs fixed it)
+- Wrong background colour was shown in the smallmap owner view when showing
+  heightlevels was disabled.
+
+New feature:
+- Allow to show the flood warning colour or not in the advanced options.
+- Cheat: Option to not devide vehicle income by daylenght factor.
+
+v13_1:
+=====
+Fixed:
+- The semaphore versions of the speed- and programmable signals had swapped
+  places in the gui. 
+
+v13:
+===
+Updated:
+- Trafficlights patch to extended version 06.
+
+New file:
+- trafficlight.h
+
+New feature:
+- option to select distance between trafficlights for synchronysing them
+
+Fixed:
+- Required GRFs decompiled and recompiled with DOS sprites. 
+- a few more strings in dutch.txt
+- Removing rail with exit signals on them is no longer allowed in one go to
+  prevent crashes with the programmable signals patch.
+  Todo: allow removing if there is no progsig dependancy on them, or if it is a
+  progsig does not depend on another signal.
+- Display the cargos correctly in the town gui if newgrf change the "goods" with
+  towngrowth effect. (FIRS, ECS) 
+
+v12_29:
+======
+Updated:
+- Chunnel patch to v16.
+- DepartureBoards patch to v19.
+
+Added:
+- Speedsignals (hthhs)
+- CD_no_overload (hthhs)
+  Prevents/reduces the linkgraph overloading when distributing cargo
+  (extension to CargoDist.)
+ 
+Added feature:
+- The heightlevel below which we allow the extra logic for industrie placement
+  (level more than 1 heightlevel) is now configurable in
+  Advanced Settings->Economy->Industries.
+
+changed:
+- Towns and cities have different demands
+  (number of "goods" required, not number of requiremnts).
+- Towns and cities can have different populations before having demands.
+- Towns and cities can have different dificulty settings in regards of amount
+  of demands for towngrowth.
+
+New known bug:
+- Some sprites of the Trafficlights and the Copypaste patch introduced are shown
+  in the Dos-pallete (the blacktiles that the moreheightlevels patch introduced
+  are forced to the windows pallete).
+
+v12_27:
+======
+Updated:
+- Departureboards patch to v18.
+- Chunnel patch to v15.
+
+Added feature:
+- Switch for displaying linkgraphs for all companies or only own company in the
+  smallmap. (Still need to integrate Cargodist's ingame overlay where you can
+  choose per company.)
+
+Fixed:
+- It was possible to set the trafficlights consist (synchronised trafficlights)
+  to off, setting it to this value effectively meant that there was no limit to
+  the size of the consist. (even 32 is already too much as it will slow down the
+  game extremely.)
+- Advanced setting for linkgraph recalculation graphic interval still showed the
+  value in days. Changed to "* 74 ticks" so that the line is always correct, even
+  with higher daylengh factors.
+- When loading old savegames/scenarios sometimes trafficlights were placed on
+  roadtiles (also on non-crossings). Added some code in afterload.cpp that iterates
+  over the map and removes all trafficlights (only for savegames that were created
+  before the trafficlights patch was included.).
+- The growthrate of towns was not multiplied by the transported ratio of all
+  requirements in the correct place.
+- Temporary fix for the crahsing in the train info tab when an Improved breakdown
+  occurs. (some info will not be available in the train information tab untill
+  fixed properly.)
+
+Changed:
+- Growth rate percent is now hidden in the town gui if the town is too small to
+  have demands. 
+- Max station classes (slots) extended to 96. (Max number of GRFs is still 255.)
+
+v12_17:
+======
+Updated:
+- Town growth patch to v020.
+
+Fixed:
+- Typo in towngrowth (growth rate would be two times too big for larger towns).
+- Displayed time in minutes was trunctated in timetable gui with larger fonts. (hthhs)
+- Mean value of required percentages for transported ratio (towngrowth).
+
+Changed:
+- Measurements hotkey default is now "SHIFT + R".
+- Default for townsize before needing goods set to 9000, max setting is 20000.
+- Demand for passengers and mail for towngrowth are now also adjusted according
+  to the town cargo generation factor.
+
+Extended:
+- More difficulty options for the towngrowth patch.
+
+v12:
+===
+New file:
+table/settings.h
+
+Added patches:
+- Town_growth based on transported goods (Has option to be turned off and select
+  difficulty).
+- Configurable amount of desert tiles/line. Now you can have as much desert/tropical
+  forests as you want.
+
+Fixed:
+- On mapgeneration trees were generated everywhere instead of only below the
+  treeline height used for mapgeneration.
+- Cargodist linkgraph recalculation ignores the daylenght factor now.
+- Missing message and resulting crash when resizing a heightmap too much (FS#4457).
+- Crash: Buttons for invalid companies were drawn in the watch_gui. When clicking
+  one the game crashed (Adjusted OnInvalidateData()).
+- Fix: Programmable signals gui was not updated when inserting programming
+  (Adjusted OnInvalidateData()).
+- Crash: Programmable signals crashed when removing an instruction (Same fix as above).
+
+Changed:
+- When deactivating the automated timetables times are preserved unless you hold
+  Ctrl while doing so.
+
+Extended:
+- Trafficlights now can look three tiles away for synchronising the green/red phase.
+  Also consists can have 32 signal now.
+
+v11_9_9_4:
+=========
+Updated:
+- CargoDist (partially ... again)
+
+Added patches:
+- Improved breakdowns
+- Trafficlights
+
+New files:
+- trafficlight.cpp
+- trafficlight_func.h
+- trafficlight_type.h
+
+Newgrf needed:
+- trafficlights.grf
+
+v11_9_9:
+=======
+Fixed:
+- Removed last remains of station_gui patch. (I thought it was still needed for
+  waypoints but I was wrong ...)
+
+New files removed:
+- station_type_matrix.cpp
+- station_type_matrix.h
+
+v11_9_7:
+========
+Updated:
+- Departureboardswallclock to v16
+
+Fixed:
+- Saving and loading company profile patch had two bugs in it (patch for fix by Lollipop.)
+- Ticks per minute is now saved in the savegame.
+
+New feature:
+- CTRL cloning does not open new guis FS#4458... (While CTRL-cloning: if you 
+  release CTRL before the vehicle appears in the depot the gui will open but the
+  vehicle is still cloned with shared orders correctly)
+
+New files:
+- New file: docs/linkgraph.txt (CargoDist)
+
+v11_9_6:
+=======
+Updated:
+- Departureboardswalclock to v15.
+
+Fixed:
+- Assert when building trees above game creation treeline.(instead we check the
+  ingame treeline now when adding trees ingame)
+- Setting snowline and treeline higher then the old max values was not possible
+  but in the scenario editor. (Now it does not respect the maximum when the
+  moreheightlevels patch is off ...)
+
+v11_9_5:
+=======
+Fixed:
+- Removed copypaste from scenario editor (Does not work correctly there anyway).
+- Adjusted maximum scrolling north of the map to
+  max_possible_tileheight + toolbar + 150 pixels for tall building (instead of 200).
+- Put back an assert in tree_cmd.cpp (after fixing conditions in CanPlantTreesOnTile()).
+- Company owner view in smallmap_gui.
+
+v11_8_3:
+=======
+- Bump to trunk
+- Added lots of TODOs, not all are bugs though.
+- Includes r18802 (breaks trunk compatibility even more but will be restored
+  after I break compatibility with previous versions).
+- Displaying vehicles in tunnels is now automatically disabled in the main menu
+  (can not be enabled).
+- Disabled experimental, not correct, cargo payment code and re-enabled pay 1 in
+  case of less than 1. (OwenP)
+
+v11_8_2: (testversion posted)
+=======
+- Bumped to r21816. (I was not yet done ... obviously) 
+- Includes an update for the departureboards patch -> to v13.
+- Includes the "three lines" change for the terraforming limit.
+- Includes outcommented code, testing and WIP -> fractional income (Do not bother
+  checking, it does not yet work, for the moment 1 is still returned in case of
+  income smaller than 1).
+- Has not yet all known todos marked as TODO.
+- Includes another code revert -> r21802 as savegame compatibility was broken
+  with previous versions of the patchpack. I first needed to find which codechange
+  had broken it before knowing what to fix. -> not yet re-reverted but marked as
+  todo (soon or when I break savegame compatibility with previous versions).
+- Broken terraforming is fixed? (Terraform limit does not yet work as it should)
+
+v11_8:
+=====
+Updated:
+- Improved station build gui partially removed. (Station part in trunk r21755)
+
+Fixed
+- Disable setting the start date in the vehicle timetable gui when autoseparation is on.
+
+v11_7:
+=====
+Updated:
+- Departureboards to r21699
+- CargoDist to r21666
+
+Fixed:
+- CopyPaste patch tilehighlighting caused crashes. (Thank you, Alberth)
+
+v11_6:
+=====
+Updated:
+- Cargodist to r21642
+- Partial refit reduced to the all button. (Trunk in r21567)
+
+Changed:
+- When vehicle income is too low to display due to the daylength factor pay 1. 
+    Todo:  Use fractional revenue.
+- Adjusted CopyPaste to trunk.
+- Adjusted Wallclock (departures gui patch) to trunk. (strgen_tables.h, strings.cpp)
+- Adjusted measurements tools to trunk.
+
+v11_5:
+=====
+Update:
+- Partial refit patch.
+- Departure boards wallclock patch to v10 (departure and arrival times can now
+  be on the same line in the gui).
+- CargoDist updated to r21511.
+
+Fixed:
+- Windows failed to compile. (MagicBuzz)
+- Fixed a bugsie with the refit selection box (Terkhen)
+- Infrastructure sharing, acc_cache -> gcache. (-> infrastructure.cpp)
+- Compiler warnings in viewport.cpp (oberhümer)
+
+Todo:
+- Adjust copy paste patch to TILE_AREA_LOOP and remove (re-introduced) TILE_LOOP.
+  (I had too because it was broken more than it was already, both template preview
+  and pasting, and did not feel much at fiddling much more at the time.)
+
+v11_4:
+=====
+Updated:
+- Updated the partial_refit patch to current version. No more crashes
+  when refitting aircraft.
+
+Fixed:
+- Bump to trunk. (Waypoint gui might need some more adjustment to use the new code
+  provided by trunk -> still need to check as I have kept the code as was before
+  to test first and get a new diff against trunk for easier comparing.)
+    False alarm, the gui did not resize because I had no additional depots loaded.
+- Adjusted vehicle income according to daylength.
+- Infrastructure sharing income was shown incorrectly.
+- Fixed the departureboards showing canceled.
+
+v11_3:
+=====
+Removed:
+- build_while_paused_in_scenario_editor patch (Trunk in r21430)
+
+v11_2:
+=====
+Added:
+- Infrastructure sharing (updated by MagicBuzz).
+
+Removed:
+- Natural sorting. In trunk in 21344.
+
+Updated:
+- Cargodist to r21370.
+- Partial refit to curent version.
+
+New files in the src folder:
+- infrastructure.cpp
+- infrastructure_func.h
+
+New files removed:
+- strnatcmp.cpp
+- strnatcmp.h
+
+Fixed:
+- Town shrinkage adjusted to daylength factor(Nickel_plate).
+- Exclusive rights counter adjusted to daylength.
+
+v11_1:
+=====
+Updated:
+- Natural sorting of strings (New files removed and code moved elsewhere).
+- Group_info_21293 (profit buttons in front of vehicles and a fix).
+
+Added:
+- Start/stop all AIs console commands r21218 (by MagicBuzz).
+
+v11:
+===
+Updated:
+- Departureboardswallclock8
+- Moreheightlevels_v32_9_1 + changes (changes will be exported to v33 ...)
+- CargoDist_r21293
+- Station-build-gui_v7
+
+Added:
+- Departure_vehicletimetableskip1.
+- Option in advanced settings to change treeline ingame so older savegames can
+  be fixed easily (Independant from mapgeneration.)(reported by NekoMaster).
+- Natural sorting of strings (Moved the new files to core folder).
+- Group_info_r21289.
+- Partial refit (Made the patchqueue 1 svn patch for easier inclusion/removal
+  if/when moved to trunk).
+
+New files in the widgets folder:
+- station_type_matrix.cpp
+- station_type_matrix.h
+
+New files in the core folder: (removed in v11_1)
+- strnatcmp.cpp
+- strnatcmp.h
+
+Fixed:
+- Partial fix for copypaste preview. Rails now show again.(Thank you Yexo).
+- Do the same fix for treeline as was done for snowline in r21078.
+- Aircraft entering the map at too low altitude (reported by Kogut).
+- Sometimes when selecting the treeline on new game generation, the up arrow
+  enabled/disabled state was not properly updated.
+- A few typos in dutch.txt.
+- 1 missing line added in programmable signals patch -> yapf_costrail.hpp.
+
+v10_7:
+=====
+Updated:
+- More Height Levels to v32_5_r21043 (lots of coding style, removed some debugging code).
+- Departuresboardwallclock v8b3_r21039.
+
+Fixed:
+- It was not possible to disable the automated timetable for vehicles that already
+  had automated timetables enabled,
+  when the setting was disabled in the Advanced Settings during playtime afterwards.
+- The advanced setting is removed but automated timetables can still be enabled
+  in the timetable gui.
+   Note: For vehicles that have automated timetables the following settings are
+   disabled while automation is enabled.
+   - Autofill the timetable.
+   - Change time (both travel time and waiting time at stations).
+   - Clear time (both travel time and waiting time at stations).
+   Extra notes:
+   I could have left the above settings enabled but they would have been overwriten anyway.
+
+v10_6:
+=====
+Updated:
+- More height levels to v32_3.
+- Departureboardswallclock2-r20920.
+
+Semi updated:
+- CargoDist to r20925 (linkgraphs is still at 20851).
+
+Fixed:
+- When saving the company profile the button was not visually pressed down.
+
+Added:
+- Timetables_change_all_stations: Change all waiting times for all stations at once.
+  Hold ctrl to activate.
+
+v10_2: (not posted)
+======
+updated:
+- Cargodist to r20851.
+- Departureboardswallclock1-r20851.
+
+v10_1:
+======
+updated:
+- Bigger maps patch to r20829 (Bugfix when clicking very large maps with
+  debugging tools on).
+- Cargodist to r20839 (Smallmap positioning bugfix).
+- More height levels to v31_2 (Land is already levelled bugfix,
+  new terrafoming code->closer to trunk).
+- Departures-clock to 0.83 (Departures board did not always work correctly).
+
+v10:
+====
+Updated:
+- Cargodist to r20802 (mostly coding style).
+- More height levels to v30_1 (minus smallmap positioning fix and missing
+  "is already levelled" message fix).
+
+Added:
+Departure boards- 24h clock patch.
+
+v9_9_9:
+=======
+Updated:
+- More height levels to v30_r20761.
+- CargoDist updated to r20762.
+
+Changed:
+- New mapgeneration seed only when you click the random button
+  (yes, CTRL + new Game still uses random seed too ;) ).
+
+v9_9_6:
+=======
+- Syntax change in copypaste patch.
+
+v9_9_5:
+=======
+- Cargodist updated. I made a misstake while bumping it myself.
+
+v9_9_4:
+=======
+- Cargodist updated to r20500.
+- More height levels updated to trunk. (No functional changes)
+- Leasing removed.
+
+v9_9_1:
+=======
+- Last version that had leasing patch.
+
+v9_9:
+=====
+- Bump to 20505.
+- Fixed the station build gui problem. It should work as before now.
+- Removed split refit temporarily. I will try to get it back in but I'd rather
+  fix one thing at a time ...
+
+v9_8:
+=====
+Updated:
+- Leasing patch updated to v3_r20424
+- Moreheightlevels updated to 27_10_r20481
+- Cargodist updated to r20479
+
+Added:
+- Max_grf_v0.2
+- Company_profile_20363_v02
+
+Changed:
+max station grfs = 64
+
+v9_3:
+====
+Updated:
+- Signals in tunnels and on bridges to r20363. No more crashing while
+  drag-removing signals from bridges and tunnels.
+
+Removed:
+Diesel smoke as it is in trunk now.
+
+v9:
+===
+Updated:
+- Diesel smoke is back, updated to v3_1.
+- Panorama screenshot updated to v3. Extended with console command.
+- Cargodist to r20274.
+
+Added:
+- Watch other company's gui patch.
+- Reduced tree growth patch.
+- Vehicle leasing.
+
+Changed:
+- r19896 breaks many of my savegames and interferes with my playingstyle.
+  IMHO the back of a one way signal is not a safe waiting place.
+  Sorry Devs but that is how I feel about it.
+  I have made it a switch in Advanced Settings->Vehicles->Routing so everybody is happy ...
+  Default is on. <- As trunk is now.
+
+Fixed:
+- Sometimes the refit options can not be selected until the gui is resized. (Kogut)
+- Crash when removing the wagons from an engine in the depot while the refit window
+  was open.
+- Right click on a station tile in the improved build station gui to show the
+  tooltips did not work properly. (Muzzy)
+
+v8:
+===
+Updated:
+- Moreheightlevels to r20202
+- Cargodist to r20211
+
+Added:
+- Close adjacent level crossing.
+- Panorama screenshot.
+- Measurement tool. (Extended to scenario editor.)
+- Configurable Treeline height. (Extended to all climates and adapted to fit the
+  moreheightlevels patch.)
+
+Removed:
+The extra hotkey for opening the cheat gui is gone. We have hotkeys.cfg now.
+
+Disabled for the moment:
+- Diesel smoke patch.
+  It causes a segmentation fault after loading some savegames. (eg. Coop's PublicServerGame_188)
+  If you want, you can enable it by following instructions in train_cmd.cpp.
+  (Search for "diesel smoke disabled for now ..." 1/4 to 4/4 and do as suggested
+  in TODO:, below each there is another TODO)
+  The segmentation fault does not seem to happen with new games nor does it happen
+  with all loaded savegames. A good reason for disabling it is that it also
+  crashed my long lasting savegame ... :(
+  Once I can figure out what causes the crash I might enable it again.
+
+v7:
+===
+Updated:
+- Cargodist updated to r20016.
+- More height levels updated to v27_4_r20026.
+
+v6_3:
+=====
+Updated:
+- Cargodist to r19884.
+- More height levels to v26_4_r19876
+
+Bugfixes:
+- Forgot to include a line in smallmap_gui. (patchpack against r19815.)
+- Litle bugfix in the smallmap aircraft position drawing (@see Cargodist thread.)
+- Vehicle would dissappear from the smallmap when zooming in. (@see Cargodist thread.)
+- Aircraft would crash into mountains instead of increasing altitude causing the
+  game to crash. (@see More height levels thread.)
+
+v6_2:
+=====
+Added:
+- Split refit r19699.
+- Buy bigger area r18518.
+- Vehicles in tunnels viewable and clickable. Patch by SmatZ that I have found
+  on the coopserver.
+
+Updated:
+- Progsigs to r19677.
+- Moreheightlevels to v25_06_r19815.
+- Cargodist to r19815.
+
+New shortcut
+- CTRL + SHIFT + C opens the cheat gui.
+  CTRL + ALT + C was not working on my pc and CTRL + ALT + WINDOWS + C neither.
+  I have not removed the old shortcut, only added another one.
+
+Retuned:
+- Larger map patch:
+  By request maximum mapsize is now 8192 * 8192 tiles. This means that if one side
+  is 32768 the other can be maximal 2048. (Until the previous version it was 32768 * 128 )
+  Be warned though. I have 1024 MB memory and when I try to generate a map of
+  size 8192 * 8192 my game crashes because of not having sufficient memory. Also
+  big maps cause a serious performance hit on the system,
+  even before you have build your first vehicle.
+
+v6:
+===
+Added:
+- Copy_paste:
+
+Updated:
+- Progsigs to r19677
+- Moreheightlevels to v25_2_r19692
+- Cargodist to r19733
+
+Needed grf
+- copypaste.grf in the data folder NOT in the newgrf folder
+  Get it here: viewtopic.php?p=440743#p440743
+
+v5:
+===
+Added and changed:
+- Sprinkles: variable daylenght, town cargo factor, more autosave options,
+  longer vehicle names, and more.
+- I have changed the running_ticks from byte to int16 to avoid them overflowing
+  when using higher daylenght settings then 3.
+
+Added:
+- Programmable Signals r19642. Thank you Cadde, for taking the time to merge the
+  programmable signals patch with the signal in tunnels and on bridges patch.
+- Build while pause in editor r19627.
+- Show system time window.
+
+Updated:
+- Cargodist to r19639
+
+v4_2:
+====
+Updated:
+- Cargodist updated to r19596.
+- More Height Levels to r19599.
+
+Retuned:
+- More Height Levels: While generating a map, IND_LEVELLING_MAX_HEIGHT is limited
+  to level 60 instead of level 20.
+- Signals in tunnels and bridges: Signal gap is 4 tiles instead of 6.
+
+v4:
+===
+Updated:
+- Cargodist to r19561. (demands_settings.h does no longer exist.)
+- Station build gui to v6.2_r19525
+
+Added and changed:
+- Diesel smoke
+- Stuck trains
+
+v3:
+===
+- Bumbedybump to r19477.
+- Added larger maps patch: Retuned! Maximum map size remains 2048 * 2048.
+  Maximum map side size is 32768.
+- Added town rating colours.
+- Added signals in tunnels and on bridges.
+- Added chunnel.
+- Updated automatic timetable and vehicle seperation.
+
+v2:
+===
+Added:
+- Improved Build Station GUI.
+
+Updated:
+- Cargodist: small bug fixed in smallmap , update in economy.cpp.
+- Moreheightlevels: smallmap heightlevelcolours updated.
+
+v1:
+===
+Added:
+- More height levels
+- Cargo distribution:
+- Automated timetable and seperation:
+
+v0:
+===
+- Trunk and nothing but trunk. ;)
diff --git a/chipp_todo.txt b/chipp_todo.txt
new file mode 100644
--- /dev/null
+++ b/chipp_todo.txt
@@ -0,0 +1,107 @@
+Known bugs:
+==========  (These require me to search and destroy. Read: May take time ...
+
+- Copy paste does not copy everything. (screenshot on page 4 of the thread)
+- Copy paste patch sometimes crashes when saving, loading or pasting templates.
+    Sometimes it works sometimes it does not.
+- Auto timetable and separation has a problem with waypoints.
+    Train and ship separation does not work correctly.
+- Some Measurement tools inconsistencies when selecting only one tile ... each
+  time the cursor moves it is recalculated ... ¿add a "move minimum x distance" check? 
+- Measurement tools never show 0 height difference except on first game start.
+  (Reset all values to 0 before making calculations or reset upon mouse release)
+- In the smallmap linkstats view, NARS gearing ratio shows up us cargo.
+  (If my understanding is correct this is because of NARS abusing a cargo bit)
+- When you click the smallmap, the positioning of the main viewport is a little
+  off when clicking high levels.
+- With higher daylength settings the date will overflow (statusbar and timetable_gui)
+  when using time in minutes in later years and might crash your game
+  -> year +-2050 with daylength factor 36 or 37 (happens later ingame with lower
+  daylength factors)  
+- Use fractional revenue for vehicle income.
+- Fix the information shown in the train gui information tab without the game
+  crashing. (improved breakdowns patch.)
+- Split the displaying of available industries correctly in the smallmap.
+- Track reservation is sometimes borked with speedsigns.
+- ...
+
+
+
+Todo: (Call 'm bugsies if you really want to)
+====   (These are easier to fix ... -> Just needs doing.
+
+inconvenient:
+-------------
+
+- The dark_green and violet smallmap colours for showing the elevation are
+  not quite finished.
+
+- Adjust copy paste patch to TILE_AREA_LOOP and remove (re-introduced) TILE_LOOP.
+  (-> I had too because it was broken more than it was already, both template
+  preview and pasting, and did not feel much at fiddling much more at the time.)
+
+- CargoDist: (not (very) urgent)
+  - ls.IsNull -> ls.HasCapacity
+  - Ingame overlay for linkgraphs
+  - savegamecode: CONDVAR -> VAR (Will most likely break savegamecompatibility
+    with previous versions.)
+  - frozen -> timeout
+
+- Move autoseparate to the vehicle gui and allow enabling/disabling per shared order group.
+
+- Adjust language strings (other then english and dutch) for towngrowth:
+  "required" -> "delivered / required".
+
+- Do not reset speedrestriction of train when visiting depot -> speedsigns.
+  (!!! make sure that improved breakdowns speed restriction is still reset !!!)
+
+-Heighmaps:
+  - Add option to save heightmaps for trunk or for the moreheightlevels patch
+   (flat and Alpinist). Add extension to heightmap name to diferentiate:
+    eg. mapname_trunk.png and mapname_mhl.png -> ¿maybe better _alp instead of _mhl?
+  - Disable option to select the generated height of a heightmap if the
+    moreheightlevels patch is off. ¿Default to Flat(16) or Alpinist(256)? 
+    Whether we load a heigtmap for 16 levels or 256, we want the terrain to look
+    the same as before exporting the heightmap.
+    Can perhaps be extended if correct extensions are added to heightmaps
+   -> ¿Maybe only available with scenario developer tools)
+
+- When CTRL-scrolling through the rail signals the speedsigns are skipped
+
+- CTRL cloning does not open new guis (FS#4458):
+   While CTRL-cloning: if you release CTRL before the vehicle appears in the depot
+   the gui will open but the vehicle is still cloned with shared orders correctly
+
+- Unpress the copypaste button in the landscape toolbar when the copypaste gui is closed.
+
+- Make stacked widgets of snow-/desertline in genworld gui.
+  ¿possibly needs re-alining with the riveramount button -> spacer?
+
+- Limit snowline and desert line to 15 if height levelspatch is off in the mapgeneration guis
+  (new game, scenario, load/play heightmap)
+
+
+
+savegamebreakers: (these will most likely be adressed when reatarting
+----------------  the patchpack but)
+
+- Restore savegame compatibility with recent trunk.
+  (Will break compatibility with previous versions of the patchpack.)
+- un-revert -> r21802 as savegame compatibility was broken with previous versions
+  of the patchpack. I first needed to find which codechange had broken it before
+  knowing what to fix. -> not yet re-reverted but marked as todo
+  (soon or when I break savegame compatibility with previous versions).
+- Includes r18802 (breaks trunk compatibility even more but will be restored after
+  I break compatibility with previous versions).
+
+
+Simple todos:
+------------
+
+- Remove last periods from language strings.
+- Import from Trunk: (not urgent)
+  - Settings ini files and remove table/setting.h
+    (not going to happen now but will be automatically done when restarting the patchpack)
+- Rename "Flat" option to read "Flat (trunk)"?
+- Alter the strings in the code so that it reads speedsigns instead of speedsignals everywhere in the game and the code
+
diff --git a/config.lib b/config.lib
--- a/config.lib
+++ b/config.lib
@@ -1288,9 +1288,6 @@
 			# sure that they will not happen. It furthermore complains
 			# about its own optimized code in some places.
 			flags="$flags -fno-strict-overflow"
-			# GCC 4.2 no longer includes -Wnon-virtual-dtor in -Wall.
-			# Enable it in order to be consistent with older GCC versions.
-			flags="$flags -Wnon-virtual-dtor"
 		fi
 
 		if [ $cc_version -ge 43 ]; then
@@ -1429,7 +1426,7 @@
 			LIBS="$LIBS -lws2_32 -lwinmm -lgdi32 -ldxguid -lole32"
 
 			if [ $cc_version -ge 44 ]; then
-				LDFLAGS_BUILD="$LDFLAGS_BUILD -static-libgcc -static-libstdc++"
+				LDFLAGS_BUILD="$LDFLAGS_BUILD -static-libgcc"
 			fi
 		fi
 	fi
@@ -3108,7 +3105,6 @@
 		s@!!SRC_OBJS_DIR!!@$SRC_OBJS_DIR@g;
 		s@!!LANG_OBJS_DIR!!@$LANG_OBJS_DIR@g;
 		s@!!GRF_OBJS_DIR!!@$GRF_OBJS_DIR@g;
-		s@!!SETTING_OBJS_DIR!!@$SETTING_OBJS_DIR@g;
 		s@!!SRC_DIR!!@$SRC_DIR@g;
 		s@!!SCRIPT_SRC_DIR!!@$SCRIPT_SRC_DIR@g;
 		s@!!OSXAPP!!@$OSXAPP@g;
@@ -3127,7 +3123,6 @@
 		s@!!STRGEN!!@$STRGEN@g;
 		s@!!ENDIAN_CHECK!!@$ENDIAN_CHECK@g;
 		s@!!DEPEND!!@$DEPEND@g;
-		s@!!SETTINGSGEN!!@$SETTINGSGEN@g;
 		s@!!ENDIAN_FORCE!!@$endian@g;
 		s@!!STAGE!!@$STAGE@g;
 		s@!!MAKEDEPEND!!@$makedepend@g;
@@ -3235,20 +3230,6 @@
 	echo "LANG_DIRS += $LANG_OBJS_DIR" >> Makefile.am
 }
 
-generate_settings() {
-	STAGE="[SETTING]"
-
-	make_sed
-
-	# Create the language file
-	mkdir -p $SETTING_OBJS_DIR
-
-	log 1 "Generating setting/Makefile..."
-	echo "# Auto-generated file from 'Makefile.settings.in' -- DO NOT EDIT" > $SETTING_OBJS_DIR/Makefile
-	< $ROOT_DIR/Makefile.setting.in sed "$SRC_REPLACE" >> $SETTING_OBJS_DIR/Makefile
-	echo "DIRS += $SETTING_OBJS_DIR" >> Makefile.am
-}
-
 generate_grf() {
 	STAGE="[GRF]"
 
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -48,7 +48,6 @@
 BASE_SRC_OBJS_DIR="$OBJS_DIR"
 LANG_OBJS_DIR="$OBJS_DIR/lang"
 GRF_OBJS_DIR="$OBJS_DIR/extra_grf"
-SETTING_OBJS_DIR="$OBJS_DIR/setting"
 BIN_DIR="$PREFIX"
 SRC_DIR="$ROOT_DIR/src"
 LANG_DIR="$SRC_DIR/lang"
@@ -83,7 +82,6 @@
 STRGEN="strgen$EXE"
 ENDIAN_CHECK="endian_check$EXE"
 DEPEND="depend$EXE"
-SETTINGSGEN="settings_gen$EXE"
 
 if [ -z "$sort" ]; then
 	PIPE_SORT="sed s@a@a@"
@@ -163,11 +161,10 @@
 	sort="$sort -u"
 fi
 
-CONFIGURE_FILES="$ROOT_DIR/configure $ROOT_DIR/config.lib $ROOT_DIR/Makefile.in $ROOT_DIR/Makefile.grf.in $ROOT_DIR/Makefile.lang.in $ROOT_DIR/Makefile.src.in $ROOT_DIR/Makefile.bundle.in $ROOT_DIR/Makefile.setting.in"
+CONFIGURE_FILES="$ROOT_DIR/configure $ROOT_DIR/config.lib $ROOT_DIR/Makefile.in $ROOT_DIR/Makefile.grf.in $ROOT_DIR/Makefile.lang.in $ROOT_DIR/Makefile.src.in $ROOT_DIR/Makefile.bundle.in"
 
 generate_main
 generate_lang
-generate_settings
 generate_grf
 generate_src
 
diff --git a/docs/copy_paste_array.txt b/docs/copy_paste_array.txt
new file mode 100644
--- /dev/null
+++ b/docs/copy_paste_array.txt
@@ -0,0 +1,62 @@
+m_tiletype:
+	bits 0..3: tiletype
+	bits 4..7: minor tiletype
+	
+m_heightmap:
+	storing height relative to the northern corner
+m_terrain_needed:
+	bit 0 set: paste height if terraform level is 1
+
+tiletypes:
+	CP_TILE_RAIL:
+		minor tiletype: RailTileType
+		m_railroad bits 6..7: RailType(monorail, maglev, electric, normal)
+		RailTileTypes:
+			RAIL_TILE_DEPOT:
+				m_railroad bits 0..1: depot direction
+			RAIL_TILE_WAYPOINT:
+				m_signals bits 0..7: waypoint grf id
+				m_railroad bits 0..1: waypoint direction
+			RAIL_TILE_SIGNALS:
+				m_signals bit 0 set: signal 1 present
+				m_signals bit 1 set: signal 2 present
+				m_signals bit 2 set: first signal is semaphore
+				m_signals bit 3 set: second signal is semaphore
+				m_signals bits 6..7 : first signal direction
+				m_signals bits 8..9 : second signal direction
+				m_signals bits 10..12: first signal type
+				m_signals bits 13..15: second signal type
+			RAIL_TILE_NORMAL and RAIL_TILE_SIGNALS:
+				m_railroad bits 0..5: trackbits
+
+	CP_TILE_ROAD:
+		minor tiletype: RoadTileType
+		RoadTileTypes:
+			ROAD_TILE_DEPOT:
+				m_railroad bits 0..1: depot direction
+				m_railroad bit 2 set: tram depot
+			ROAD_TILE_CROSSING, ROAD_TILE_NORMAL:
+				m_railroad bits 0..3: RoadBits normal road
+				m_railroad bits 4..7: RoadBits tram
+			ROAD_TILE_NORMAL:
+				m_signals bits 0..1: disallowed road directions
+			ROAD_TILE_CROSSING:
+				m_railroad bits 6..7: rail type
+
+	CP_TILE_TUNNELBRIDGE:
+		minor tiletype bit 0 set: tunnel
+		m_railroad bit 0..1: direction
+		m_railroad bit 2..3: transporttype
+		m_railroad bit 4 set: start
+		m_railroad bit 6..7: rail/roadtypes
+
+	CP_TILE_STATION:
+		minor tiletype: TileType (minor bits indicate station type)
+		TileType:
+			CP_TILE_ROAD:
+				m_railroad bits 0..1: direction
+				m_railroad bit 2 set: truck stop
+				m_railroad bit 3 set: drive through
+				(3..5 currently unused)
+				m_railroad bits 6..7: road type
+			CP_TILE_RAIL:
diff --git a/docs/linkgraph.txt b/docs/linkgraph.txt
new file mode 100644
--- /dev/null
+++ b/docs/linkgraph.txt
@@ -0,0 +1,30 @@
+Some clarifications about the link graph
+----------------------------------------
+
+InitializeLinkGraphs joins all threads, so if the game is abendoned
+with some threads still running, they're joined as soon as the next game
+(possibly the title game) is started. see also InitializeGame.
+
+The MCF algorithm can be quite CPU-hungry as it's NP-hard and takes
+exponential time (though with a very small constant factor) in the number
+of nodes.
+This is why it is run in a separate thread where possible. However after
+some time the thread is joined and if it hasn't finished by then the game
+will hang. This problem gets worse if we are running on a platform without
+threads. However, as those are usually the ones with less CPU power I
+assume the contention for the CPU would make the game hard to play even
+with threads or even without cargodist (autosave ...). I might be wrong,
+but I won't put any work into this before someone shows me some problem.
+
+You can configure the link graph recalculation interval. A link graph
+recalculation interval of X days means that each link graph job has X days
+to run before it is joined. The downside is that the flow stats won't be
+updated before the job is finished and thus a long interval means less
+updates and longer times until changes in capacities are accounted for.
+If you play a very large map with a complicated link graph you may want to
+raise the interval to avoid lags. The same holds for systems with slow
+CPUs.
+
+Another option to avoid excessive lags is to reduce the accuracy of link
+graph calculations. Generally the accurace is inversely correlated to the
+CPU requirements of the MCF algorithm.
diff --git a/projects/generate b/projects/generate
--- a/projects/generate
+++ b/projects/generate
@@ -77,7 +77,7 @@
 	done
 }
 
-grep '\.h' "$ROOT_DIR/source.list" | grep -v '../objs/langs/table/strings.h\|../objs/settings/table/settings.h' | sed 's/	//' | sort > tmp.headers.source.list
+grep '\.h' "$ROOT_DIR/source.list" | grep -v '../objs/langs/table/strings.h' | sed 's/	//' | sort > tmp.headers.source.list
 find "$ROOT_DIR/src" \( -iname "*.h" -or -iname "*.hpp" \) -and -not -ipath "*/.svn/*" | sed "s~$ROOT_DIR/src/~~" | sort > tmp.headers.src
 if [ -n "`diff tmp.headers.source.list tmp.headers.src`" ]; then
 	echo "The following headers are missing in source.list and not in /src/ or vice versa."
@@ -204,28 +204,6 @@
 	eval "$2=\"\$RES\""
 }
 
-load_settings_data() {
-	RES=""
-	RES2="
-#3..\\objs\\settings\\settings_gen.exe -o ..\\objs\\settings\\table\\settings.h -b ..\\src\\table\\settings.h.preamble -a ..\\src\\table\\settings.h.postamble"
-	for i in `ls $1`
-	do
-		i=`basename $i`
-		RES="$RES
-#1		<File
-#1			RelativePath=\"..\\src\\table\\"$i"\"
-#1			>
-#1		</File>
-#2    <None Include=\"..\\src\\table\\"$i"\" />
-#4    <None Include=\"..\\src\\table\\"$i"\">
-#4      <Filter>INI</Filter>
-#4    </None>"
-		RES2="$RES2 ..\\src\\table\\"$i
-	done
-
-	eval "$2=\"\$RES\$RES2\""
-}
-
 generate() {
 	echo "Generating $2..."
 	if [ $# -eq 3 ]; then
@@ -288,12 +266,6 @@
 langvcxproj=`echo "$lang" | grep "^#2" | sed "s~#2~~g"`
 lang=`echo "$lang" | grep "^#1" | sed "s~#1~~g"`
 
-load_settings_data "$ROOT_DIR/src/table/*.ini" settings
-settingsfiles=`echo "$settings" | grep "^#4" | sed "s~#4~~g"`
-settingscommand=`echo "$settings" | grep "^#3" | sed "s~#3~~g"`
-settingsvcxproj=`echo "$settings" | grep "^#2" | sed "s~#2~~g"`
-settings=`echo "$settings" | grep "^#1" | sed "s~#1~~g"`
-
 generate "$openttd" "openttd_vs80.vcproj"
 generate "$openttd" "openttd_vs90.vcproj"
 generate "$openttdvcxproj" "openttd_vs100.vcxproj"
@@ -301,7 +273,3 @@
 generate "$lang" "langs_vs80.vcproj"
 generate "$lang" "langs_vs90.vcproj"
 generate "$langvcxproj" "langs_vs100.vcxproj"
-generate "$settings" "settings_vs80.vcproj" "$settingscommand"
-generate "$settings" "settings_vs90.vcproj" "$settingscommand"
-generate "$settingsvcxproj" "settings_vs100.vcxproj" "$settingscommand"
-generate "$settingsfiles" "settings_vs100.vcxproj.filters"
diff --git a/projects/generate.vbs b/projects/generate.vbs
--- a/projects/generate.vbs
+++ b/projects/generate.vbs
@@ -113,7 +113,7 @@
 	Set file = FSO.OpenTextFile(filename, 1, 0, 0)
 	While Not file.AtEndOfStream
 		line = Replace(file.ReadLine, Chr(9), "") ' Remove tabs
-		If Len(line) > 0 And regexp.Test(line) And line <> "../objs/langs/table/strings.h" And line <> "../objs/settings/table/settings.h" Then
+		If Len(line) > 0 And regexp.Test(line) And line <> "../objs/langs/table/strings.h" Then
 			source_list_headers.Add line, line
 		End If
 	Wend
@@ -274,38 +274,6 @@
 	load_lang_data = res
 End Function
 
-Function load_settings_data(dir, ByRef vcxproj, ByRef command, ByRef files)
-	Dim res, folder, file, first_time
-	res = ""
-	command = "..\objs\settings\settings_gen.exe -o ..\objs\settings\table\settings.h -b ..\src\table\settings.h.preamble -a ..\src\table\settings.h.postamble"
-	Set folder = FSO.GetFolder(dir)
-	For Each file In folder.Files
-		file = FSO.GetFileName(file)
-		If FSO.GetExtensionName(file) = "ini" Then
-			if first_time <> 0 Then
-				res = res & vbCrLf
-				vcxproj = vcxproj & vbCrLf
-				files = files & vbCrLf
-			Else
-				first_time = 1
-			End If
-			res = res & _
-			"		<File" & vbCrLf & _
-			"			RelativePath=" & Chr(34) & "..\src\table\" & file & Chr(34) & vbCrLf & _
-			"			>" & vbCrLf & _
-			"		</File>"
-			vcxproj = vcxproj & _
-			"    <None Include=" & Chr(34) & "..\src\table\" & file & Chr(34) & " />"
-			command = command & " ..\src\table\" & file
-			files = files & _
-			"    <None Include=" & Chr(34) & "..\src\table\" & file & Chr(34) & ">" & vbCrLf & _
-			"      <Filter>INI</Filter>" & vbCrLf & _
-			"    </None>"
-		End If
-	Next
-	load_settings_data = res
-End Function
-
 Sub generate(data, dest, data2)
 	Dim srcfile, destfile, line
 	WScript.Echo "Generating " & FSO.GetFileName(dest) & "..."
@@ -369,10 +337,3 @@
 generate lang, ROOT_DIR & "/projects/langs_vs80.vcproj", Null
 generate lang, ROOT_DIR & "/projects/langs_vs90.vcproj", Null
 generate langvcxproj, ROOT_DIR & "/projects/langs_vs100.vcxproj", Null
-
-Dim settings, settingsvcxproj, settingscommand, settingsfiles
-settings = load_settings_data(ROOT_DIR & "/src/table", settingsvcxproj, settingscommand, settingsfiles)
-generate settings, ROOT_DIR & "/projects/settings_vs80.vcproj", settingscommand
-generate settings, ROOT_DIR & "/projects/settings_vs90.vcproj", settingscommand
-generate settingsvcxproj, ROOT_DIR & "/projects/settings_vs100.vcxproj", settingscommand
-generate settingsfiles, ROOT_DIR & "/projects/settings_vs100.vcxproj.filters", Null
diff --git a/projects/openttd_vs100.sln b/projects/openttd_vs100.sln
--- a/projects/openttd_vs100.sln
+++ b/projects/openttd_vs100.sln
@@ -1,10 +1,6 @@
 Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual C++ Express 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openttd", "openttd_vs100.vcxproj", "{668328A0-B40E-4CDB-BD72-D0064424414A}"
-	ProjectSection(ProjectDependencies) = postProject
-		{0817F629-589E-4A3B-B81A-8647BC571E35} = {0817F629-589E-4A3B-B81A-8647BC571E35}
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7} = {E9548DE9-F089-49B7-93A6-30BE2CC311C7}
-	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strgen", "strgen_vs100.vcxproj", "{A133A442-BD0A-4ADE-B117-AD7545E4BDD1}"
 EndProject
@@ -14,13 +10,6 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "generate", "generate_vs100.vcxproj", "{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settings", "settings_vs100.vcxproj", "{0817F629-589E-4A3B-B81A-8647BC571E35}"
-	ProjectSection(ProjectDependencies) = postProject
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7} = {E9548DE9-F089-49B7-93A6-30BE2CC311C7}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settingsgen", "settingsgen_vs100.vcxproj", "{E9548DE9-F089-49B7-93A6-30BE2CC311C7}"
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -65,22 +54,6 @@
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Debug|x64.ActiveCfg = Debug|Win32
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Release|Win32.ActiveCfg = Debug|Win32
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Release|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|Win32.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|Win32.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|x64.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|Win32.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|Win32.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|x64.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|Win32.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|Win32.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|x64.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|x64.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|Win32.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|Win32.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|x64.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|x64.Build.0 = Debug|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj
--- a/projects/openttd_vs100.vcxproj
+++ b/projects/openttd_vs100.vcxproj
@@ -101,7 +101,7 @@
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <ExceptionHandling>Sync</ExceptionHandling>
@@ -155,7 +155,7 @@
     <ClCompile>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -203,7 +203,7 @@
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <ExceptionHandling>Sync</ExceptionHandling>
@@ -255,7 +255,7 @@
     <ClCompile>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -300,13 +300,16 @@
     <ClCompile Include="..\src\cargotype.cpp" />
     <ClCompile Include="..\src\cheat.cpp" />
     <ClCompile Include="..\src\command.cpp" />
+    <ClCompile Include="..\src\command_queue.cpp" />
     <ClCompile Include="..\src\console.cpp" />
     <ClCompile Include="..\src\console_cmds.cpp" />
+    <ClCompile Include="..\src\copy_paste.cpp" />
     <ClCompile Include="..\src\crashlog.cpp" />
     <ClCompile Include="..\src\currency.cpp" />
     <ClCompile Include="..\src\date.cpp" />
     <ClCompile Include="..\src\debug.cpp" />
     <ClCompile Include="..\src\dedicated.cpp" />
+    <ClCompile Include="..\src\departures.cpp" />
     <ClCompile Include="..\src\depot.cpp" />
     <ClCompile Include="..\src\driver.cpp" />
     <ClCompile Include="..\src\economy.cpp" />
@@ -324,12 +327,17 @@
     <ClCompile Include="..\src\heightmap.cpp" />
     <ClCompile Include="..\src\highscore.cpp" />
     <ClCompile Include="..\src\hotkeys.cpp" />
+    <ClCompile Include="..\src\infrastructure.cpp" />
     <ClCompile Include="..\src\ini.cpp" />
-    <ClCompile Include="..\src\ini_load.cpp" />
     <ClCompile Include="..\src\landscape.cpp" />
+    <ClCompile Include="..\src\linkgraph\demands.cpp" />
+    <ClCompile Include="..\src\linkgraph\flowmapper.cpp" />
+    <ClCompile Include="..\src\linkgraph\linkgraph.cpp" />
+    <ClCompile Include="..\src\linkgraph\mcf.cpp" />
     <ClCompile Include="..\src\map.cpp" />
     <ClCompile Include="..\src\misc.cpp" />
     <ClCompile Include="..\src\mixer.cpp" />
+    <ClCompile Include="..\src\moving_average.cpp" />
     <ClCompile Include="..\src\music.cpp" />
     <ClCompile Include="..\src\network\network.cpp" />
     <ClCompile Include="..\src\network\network_admin.cpp" />
@@ -365,6 +373,7 @@
     <ClCompile Include="..\src\tile_map.cpp" />
     <ClCompile Include="..\src\tilearea.cpp" />
     <ClCompile Include="..\src\townname.cpp" />
+    <ClCompile Include="..\src\trafficlight.cpp" />
     <ClCompile Include="..\src\vehicle.cpp" />
     <ClCompile Include="..\src\vehiclelist.cpp" />
     <ClCompile Include="..\src\viewport.cpp" />
@@ -403,6 +412,8 @@
     <ClInclude Include="..\src\console_gui.h" />
     <ClInclude Include="..\src\console_internal.h" />
     <ClInclude Include="..\src\console_type.h" />
+    <ClInclude Include="..\src\copy_paste.h" />
+    <ClInclude Include="..\src\command_queue.h" />
     <ClInclude Include="..\src\crashlog.h" />
     <ClInclude Include="..\src\currency.h" />
     <ClInclude Include="..\src\date_func.h" />
@@ -410,6 +421,9 @@
     <ClInclude Include="..\src\date_type.h" />
     <ClInclude Include="..\src\debug.h" />
     <ClInclude Include="..\src\video\dedicated_v.h" />
+    <ClInclude Include="..\src\departures_func.h" />
+    <ClInclude Include="..\src\departures_gui.h" />
+    <ClInclude Include="..\src\departures_type.h" />
     <ClInclude Include="..\src\depot_base.h" />
     <ClInclude Include="..\src\depot_func.h" />
     <ClInclude Include="..\src\depot_map.h" />
@@ -452,14 +466,21 @@
     <ClInclude Include="..\src\industry.h" />
     <ClInclude Include="..\src\industry_type.h" />
     <ClInclude Include="..\src\industrytype.h" />
+    <ClInclude Include="..\src\infrastructure_func.h" />
     <ClInclude Include="..\src\ini_type.h" />
     <ClInclude Include="..\src\landscape.h" />
     <ClInclude Include="..\src\landscape_type.h" />
     <ClInclude Include="..\src\language.h" />
+    <ClInclude Include="..\src\linkgraph\demands.h" />
+    <ClInclude Include="..\src\linkgraph\flowmapper.h" />
+    <ClInclude Include="..\src\linkgraph\linkgraph.h" />
+    <ClInclude Include="..\src\linkgraph\linkgraph_type.h" />
+    <ClInclude Include="..\src\linkgraph\mcf.h" />
     <ClInclude Include="..\src\livery.h" />
     <ClInclude Include="..\src\map_func.h" />
     <ClInclude Include="..\src\map_type.h" />
     <ClInclude Include="..\src\mixer.h" />
+    <ClInclude Include="..\src\moving_average.h" />
     <ClInclude Include="..\src\network\network.h" />
     <ClInclude Include="..\src\network\network_admin.h" />
     <ClInclude Include="..\src\network\network_base.h" />
@@ -581,6 +602,9 @@
     <ClInclude Include="..\src\track_func.h" />
     <ClInclude Include="..\src\track_type.h" />
     <ClInclude Include="..\src\train.h" />
+    <ClInclude Include="..\src\trafficlight.h" />
+    <ClInclude Include="..\src\trafficlight_func.h" />
+    <ClInclude Include="..\src\trafficlight_type.h" />
     <ClInclude Include="..\src\transparency.h" />
     <ClInclude Include="..\src\transparency_gui.h" />
     <ClInclude Include="..\src\transport_type.h" />
@@ -593,6 +617,7 @@
     <ClInclude Include="..\src\vehiclelist.h" />
     <ClInclude Include="..\src\viewport_func.h" />
     <ClInclude Include="..\src\viewport_type.h" />
+    <ClInclude Include="..\src\watch_gui.h" />
     <ClInclude Include="..\src\water.h" />
     <ClInclude Include="..\src\waypoint_base.h" />
     <ClInclude Include="..\src\waypoint_func.h" />
@@ -621,6 +646,7 @@
     <ClCompile Include="..\src\core\math_func.cpp" />
     <ClInclude Include="..\src\core\math_func.hpp" />
     <ClInclude Include="..\src\core\mem_func.hpp" />
+    <ClInclude Include="..\src\core\multimap.hpp" />
     <ClInclude Include="..\src\core\overflowsafe_type.hpp" />
     <ClCompile Include="..\src\core\pool_func.cpp" />
     <ClInclude Include="..\src\core\pool_func.hpp" />
@@ -639,7 +665,9 @@
     <ClCompile Include="..\src\cheat_gui.cpp" />
     <ClCompile Include="..\src\company_gui.cpp" />
     <ClCompile Include="..\src\console_gui.cpp" />
+    <ClCompile Include="..\src\copy_paste_gui.cpp" />
     <ClCompile Include="..\src\date_gui.cpp" />
+    <ClCompile Include="..\src\departures_gui.cpp" />
     <ClCompile Include="..\src\depot_gui.cpp" />
     <ClCompile Include="..\src\dock_gui.cpp" />
     <ClCompile Include="..\src\engine_gui.cpp" />
@@ -662,6 +690,7 @@
     <ClCompile Include="..\src\object_gui.cpp" />
     <ClCompile Include="..\src\order_gui.cpp" />
     <ClCompile Include="..\src\osk_gui.cpp" />
+    <ClCompile Include="..\src\programmable_signals_gui.cpp" />
     <ClCompile Include="..\src\rail_gui.cpp" />
     <ClCompile Include="..\src\road_gui.cpp" />
     <ClCompile Include="..\src\roadveh_gui.cpp" />
@@ -681,6 +710,7 @@
     <ClCompile Include="..\src\tree_gui.cpp" />
     <ClCompile Include="..\src\vehicle_gui.cpp" />
     <ClCompile Include="..\src\viewport_gui.cpp" />
+    <ClCompile Include="..\src\watch_gui.cpp" />
     <ClCompile Include="..\src\waypoint_gui.cpp" />
     <ClCompile Include="..\src\widgets\dropdown.cpp" />
     <ClInclude Include="..\src\widgets\dropdown_func.h" />
@@ -727,6 +757,7 @@
     <ClCompile Include="..\src\saveload\group_sl.cpp" />
     <ClCompile Include="..\src\saveload\industry_sl.cpp" />
     <ClCompile Include="..\src\saveload\labelmaps_sl.cpp" />
+    <ClCompile Include="..\src\saveload\linkgraph_sl.cpp" />
     <ClCompile Include="..\src\saveload\map_sl.cpp" />
     <ClCompile Include="..\src\saveload\misc_sl.cpp" />
     <ClCompile Include="..\src\saveload\newgrf_sl.cpp" />
@@ -740,6 +771,7 @@
     <ClInclude Include="..\src\saveload\saveload.h" />
     <ClInclude Include="..\src\saveload\saveload_filter.h" />
     <ClInclude Include="..\src\saveload\saveload_internal.h" />
+    <ClCompile Include="..\src\saveload\signal_sl.cpp" />
     <ClCompile Include="..\src\saveload\signs_sl.cpp" />
     <ClCompile Include="..\src\saveload\station_sl.cpp" />
     <ClCompile Include="..\src\saveload\storage_sl.cpp" />
@@ -772,7 +804,7 @@
     <ClInclude Include="..\src\table\railtypes.h" />
     <ClInclude Include="..\src\table\road_land.h" />
     <ClInclude Include="..\src\table\roadveh_movement.h" />
-    <ClInclude Include="..\src\..\objs\settings\table\settings.h" />
+    <ClInclude Include="..\src\table\settings.h" />
     <ClInclude Include="..\src\table\sprites.h" />
     <ClInclude Include="..\src\table\station_land.h" />
     <ClInclude Include="..\src\table\strgen_tables.h" />
diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters
--- a/projects/openttd_vs100.vcxproj.filters
+++ b/projects/openttd_vs100.vcxproj.filters
@@ -120,12 +120,18 @@
     <ClCompile Include="..\src\command.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\command_queue.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\console.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\src\console_cmds.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\copy_paste.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\crashlog.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -141,6 +147,9 @@
     <ClCompile Include="..\src\dedicated.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\departures.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\depot.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -192,13 +201,25 @@
     <ClCompile Include="..\src\hotkeys.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\infrastructure.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\ini.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\ini_load.cpp">
+    <ClCompile Include="..\src\landscape.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\landscape.cpp">
+    <ClCompile Include="..\src\linkgraph\demands.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\linkgraph\flowmapper.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\linkgraph\linkgraph.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\linkgraph\mcf.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\src\map.cpp">
@@ -210,6 +231,9 @@
     <ClCompile Include="..\src\mixer.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\moving_average.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\music.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -252,6 +276,9 @@
     <ClCompile Include="..\src\progress.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\programmable_signals.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\rail.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -315,6 +342,9 @@
     <ClCompile Include="..\src\townname.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\trafficlight.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\vehicle.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -429,6 +459,12 @@
     <ClInclude Include="..\src\console_type.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\copy_paste.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\command_queue.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\crashlog.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -450,6 +486,15 @@
     <ClInclude Include="..\src\video\dedicated_v.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\departures_func.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\departures_gui.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\departures_type.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\depot_base.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -576,6 +621,9 @@
     <ClInclude Include="..\src\industrytype.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\infrastructure_func.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\ini_type.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -588,6 +636,21 @@
     <ClInclude Include="..\src\language.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\linkgraph\demands.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\linkgraph\flowmapper.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\linkgraph\linkgraph.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\linkgraph\linkgraph_type.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\linkgraph\mcf.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\livery.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -600,6 +663,9 @@
     <ClInclude Include="..\src\mixer.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\moving_average.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\network\network.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -768,6 +834,9 @@
     <ClInclude Include="..\src\progress.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\programmable_signals.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\querystring_gui.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -963,6 +1032,15 @@
     <ClInclude Include="..\src\train.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\trafficlight.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\trafficlight_func.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\trafficlight_type.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\transparency.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -999,6 +1077,9 @@
     <ClInclude Include="..\src\viewport_type.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\watch_gui.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\water.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -1083,6 +1164,9 @@
     <ClInclude Include="..\src\core\mem_func.hpp">
       <Filter>Core Source Code</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\core\multimap.hpp">
+      <Filter>Core Source Code</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\core\overflowsafe_type.hpp">
       <Filter>Core Source Code</Filter>
     </ClInclude>
@@ -1137,9 +1221,15 @@
     <ClCompile Include="..\src\console_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\copy_paste_gui.cpp">
+      <Filter>GUI Source Code</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\date_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\departures_gui.cpp">
+      <Filter>GUI Source Code</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\depot_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
@@ -1206,6 +1296,9 @@
     <ClCompile Include="..\src\osk_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\programmable_signals_gui.cpp">
+      <Filter>GUI Source Code</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\rail_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
@@ -1263,6 +1356,9 @@
     <ClCompile Include="..\src\viewport_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\watch_gui.cpp">
+      <Filter>GUI Source Code</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\waypoint_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
@@ -1401,6 +1497,9 @@
     <ClCompile Include="..\src\saveload\labelmaps_sl.cpp">
       <Filter>Save/Load handlers</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\saveload\linkgraph_sl.cpp">
+      <Filter>Save/Load handlers</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\saveload\map_sl.cpp">
       <Filter>Save/Load handlers</Filter>
     </ClCompile>
@@ -1440,6 +1539,9 @@
     <ClInclude Include="..\src\saveload\saveload_internal.h">
       <Filter>Save/Load handlers</Filter>
     </ClInclude>
+    <ClCompile Include="..\src\saveload\signal_sl.cpp">
+      <Filter>Save/Load handlers</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\saveload\signs_sl.cpp">
       <Filter>Save/Load handlers</Filter>
     </ClCompile>
@@ -1536,7 +1638,7 @@
     <ClInclude Include="..\src\table\roadveh_movement.h">
       <Filter>Tables</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\..\objs\settings\table\settings.h">
+    <ClInclude Include="..\src\table\settings.h">
       <Filter>Tables</Filter>
     </ClInclude>
     <ClInclude Include="..\src\table\sprites.h">
diff --git a/projects/openttd_vs100.vcxproj.in b/projects/openttd_vs100.vcxproj.in
--- a/projects/openttd_vs100.vcxproj.in
+++ b/projects/openttd_vs100.vcxproj.in
@@ -101,7 +101,7 @@
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <ExceptionHandling>Sync</ExceptionHandling>
@@ -155,7 +155,7 @@
     <ClCompile>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -203,7 +203,7 @@
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <ExceptionHandling>Sync</ExceptionHandling>
@@ -255,7 +255,7 @@
     <ClCompile>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\objs\langs;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
diff --git a/projects/openttd_vs80.sln b/projects/openttd_vs80.sln
--- a/projects/openttd_vs80.sln
+++ b/projects/openttd_vs80.sln
@@ -3,8 +3,8 @@
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openttd", "openttd_vs80.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}
 		{1A2B3C5E-1C23-41A5-9C9B-ACBA2AA75FEC} = {1A2B3C5E-1C23-41A5-9C9B-ACBA2AA75FEC}
-		{0817F629-589E-4A3B-B81A-8647BC571E35} = {0817F629-589E-4A3B-B81A-8647BC571E35}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strgen", "strgen_vs80.vcproj", "{A133A442-BD0A-4ADE-B117-AD7545E4BDD1}"
@@ -18,13 +18,6 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "generate", "generate_vs80.vcproj", "{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settings", "settings_vs80.vcproj", "{0817F629-589E-4A3B-B81A-8647BC571E35}"
-	ProjectSection(ProjectDependencies) = postProject
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7} = {E9548DE9-F089-49B7-93A6-30BE2CC311C7}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settings_gen", "settingsgen_vs80.vcproj", "{E9548DE9-F089-49B7-93A6-30BE2CC311C7}"
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -69,22 +62,6 @@
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Debug|x64.ActiveCfg = Debug|Win32
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Release|Win32.ActiveCfg = Debug|Win32
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Release|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|Win32.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|Win32.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|x64.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|Win32.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|Win32.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|x64.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|Win32.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|Win32.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|x64.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|x64.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|Win32.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|Win32.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|x64.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|x64.Build.0 = Debug|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -51,7 +51,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -155,7 +155,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -256,7 +256,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -361,7 +361,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -471,6 +471,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\command_queue.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\console.cpp"
 				>
 			</File>
@@ -483,6 +487,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\copy_paste.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\currency.cpp"
 				>
 			</File>
@@ -499,6 +507,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\departures.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\depot.cpp"
 				>
 			</File>
@@ -567,18 +579,34 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\ini_load.cpp"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\landscape.cpp"
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\linkgraph\demands.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\flowmapper.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\linkgraph.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\mcf.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\map.cpp"
 				>
 			</File>
@@ -591,6 +619,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\moving_average.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\music.cpp"
 				>
 			</File>
@@ -647,6 +679,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\programmable_signals.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\rail.cpp"
 				>
 			</File>
@@ -827,6 +863,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\copy_paste.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\command_queue.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\cheat_func.h"
 				>
 			</File>
@@ -915,6 +959,18 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\departures_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\departures_gui.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\departures_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\depot_base.h"
 				>
 			</File>
@@ -1083,6 +1139,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure_func.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini_type.h"
 				>
 			</File>
@@ -1099,6 +1159,26 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\linkgraph\demands.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\flowmapper.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\linkgraph.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\linkgraph_type.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\mcf.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\livery.h"
 				>
 			</File>
@@ -1115,6 +1195,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\moving_average.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\network\network.h"
 				>
 			</File>
@@ -1339,6 +1423,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\programmable_signals.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\querystring_gui.h"
 				>
 			</File>
@@ -1594,6 +1682,18 @@
 				RelativePath=".\..\src\track_type.h"
 				>
 			</File>
+ 			<File
+				RelativePath=".\..\src\trafficlight.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\trafficlight_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\trafficlight_type.h"
+				>
+			</File>
 			<File
 				RelativePath=".\..\src\train.h"
 				>
@@ -1651,6 +1751,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\watch_gui.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\waypoint_base.h"
 				>
 			</File>
@@ -1763,6 +1867,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\core\multimap.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\core\overflowsafe_type.hpp"
 				>
 			</File>
@@ -1843,6 +1951,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\copy_paste_gui.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\departures_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\depot_gui.cpp"
 				>
 			</File>
@@ -1931,6 +2047,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\programmable_signals_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\rail_gui.cpp"
 				>
 			</File>
@@ -2007,6 +2127,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\watch_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\waypoint_gui.cpp"
 				>
 			</File>
@@ -2203,6 +2327,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\saveload\linkgraph_sl.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\saveload\map_sl.cpp"
 				>
 			</File>
@@ -2255,6 +2383,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\saveload\signal_sl.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\saveload\signs_sl.cpp"
 				>
 			</File>
@@ -2387,7 +2519,7 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\..\objs\settings\table\settings.h"
+				RelativePath=".\..\src\table\settings.h"
 				>
 			</File>
 			<File
@@ -3123,6 +3255,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\trafficlight.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_vehicle.cpp"
 				>
 			</File>
diff --git a/projects/openttd_vs80.vcproj.in b/projects/openttd_vs80.vcproj.in
--- a/projects/openttd_vs80.vcproj.in
+++ b/projects/openttd_vs80.vcproj.in
@@ -51,7 +51,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -155,7 +155,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -256,7 +256,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -361,7 +361,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
diff --git a/projects/openttd_vs90.sln b/projects/openttd_vs90.sln
--- a/projects/openttd_vs90.sln
+++ b/projects/openttd_vs90.sln
@@ -3,7 +3,7 @@
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openttd", "openttd_vs90.vcproj", "{668328A0-B40E-4CDB-BD72-D0064424414A}"
 	ProjectSection(ProjectDependencies) = postProject
 		{0F066B23-18DF-4284-8265-F4A5E7E3B966} = {0F066B23-18DF-4284-8265-F4A5E7E3B966}
-		{0817F629-589E-4A3B-B81A-8647BC571E35} = {0817F629-589E-4A3B-B81A-8647BC571E35}
+		{A133A442-BD0A-4ADE-B117-AD7545E4BDD1} = {A133A442-BD0A-4ADE-B117-AD7545E4BDD1}
 		{1A2B3C5E-1C23-41A5-9C9B-ACBA2AA75FEC} = {1A2B3C5E-1C23-41A5-9C9B-ACBA2AA75FEC}
 	EndProjectSection
 EndProject
@@ -18,13 +18,6 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "generate", "generate_vs90.vcproj", "{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settings", "settings_vs90.vcproj", "{0817F629-589E-4A3B-B81A-8647BC571E35}"
-	ProjectSection(ProjectDependencies) = postProject
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7} = {E9548DE9-F089-49B7-93A6-30BE2CC311C7}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settingsgen", "settingsgen_vs90.vcproj", "{E9548DE9-F089-49B7-93A6-30BE2CC311C7}"
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -69,22 +62,6 @@
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Debug|x64.ActiveCfg = Debug|Win32
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Release|Win32.ActiveCfg = Debug|Win32
 		{2F31FD79-D1AC-43C4-89F3-B0D5E4E53E34}.Release|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|Win32.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|Win32.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Debug|x64.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|Win32.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|Win32.Build.0 = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|x64.ActiveCfg = Debug|Win32
-		{0817F629-589E-4A3B-B81A-8647BC571E35}.Release|x64.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|Win32.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|Win32.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|x64.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Debug|x64.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|Win32.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|Win32.Build.0 = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|x64.ActiveCfg = Debug|Win32
-		{E9548DE9-F089-49B7-93A6-30BE2CC311C7}.Release|x64.Build.0 = Debug|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -52,7 +52,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -154,7 +154,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -254,7 +254,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -358,7 +358,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -468,6 +468,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\command_queue.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\console.cpp"
 				>
 			</File>
@@ -480,6 +484,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\copy_paste.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\currency.cpp"
 				>
 			</File>
@@ -496,6 +504,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\departures.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\depot.cpp"
 				>
 			</File>
@@ -564,18 +576,34 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\ini_load.cpp"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\landscape.cpp"
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\linkgraph\demands.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\flowmapper.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\linkgraph.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\mcf.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\map.cpp"
 				>
 			</File>
@@ -588,6 +616,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\moving_average.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\music.cpp"
 				>
 			</File>
@@ -644,6 +676,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\programmable_signals.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\rail.cpp"
 				>
 			</File>
@@ -844,6 +880,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\command_queue.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\command_type.h"
 				>
 			</File>
@@ -888,6 +928,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\copy_paste.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\currency.h"
 				>
 			</File>
@@ -912,6 +956,18 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\departures_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\departures_gui.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\departures_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\depot_base.h"
 				>
 			</File>
@@ -1080,6 +1136,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure_func.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini_type.h"
 				>
 			</File>
@@ -1096,6 +1156,26 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\linkgraph\demands.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\flowmapper.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\linkgraph.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\linkgraph_type.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\linkgraph\mcf.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\livery.h"
 				>
 			</File>
@@ -1112,6 +1192,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\moving_average.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\network\network.h"
 				>
 			</File>
@@ -1336,6 +1420,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\programmable_signals.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\querystring_gui.h"
 				>
 			</File>
@@ -1591,6 +1679,18 @@
 				RelativePath=".\..\src\track_type.h"
 				>
 			</File>
+ 			<File
+				RelativePath=".\..\src\trafficlight.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\trafficlight_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\trafficlight_type.h"
+				>
+			</File>
 			<File
 				RelativePath=".\..\src\train.h"
 				>
@@ -1644,6 +1744,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\watch_gui.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\water.h"
 				>
 			</File>
@@ -1760,6 +1864,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\core\multimap.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\core\overflowsafe_type.hpp"
 				>
 			</File>
@@ -1840,6 +1948,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\copy_paste_gui.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\departures_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\depot_gui.cpp"
 				>
 			</File>
@@ -1928,6 +2044,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\programmable_signals_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\rail_gui.cpp"
 				>
 			</File>
@@ -2004,6 +2124,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\watch_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\waypoint_gui.cpp"
 				>
 			</File>
@@ -2200,6 +2324,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\saveload\linkgraph_sl.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\saveload\map_sl.cpp"
 				>
 			</File>
@@ -2252,6 +2380,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\saveload\signal_sl.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\saveload\signs_sl.cpp"
 				>
 			</File>
@@ -2384,7 +2516,7 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\..\objs\settings\table\settings.h"
+				RelativePath=".\..\src\table\settings.h"
 				>
 			</File>
 			<File
@@ -3120,6 +3252,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\trafficlight.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_vehicle.cpp"
 				>
 			</File>
diff --git a/projects/openttd_vs90.vcproj.in b/projects/openttd_vs90.vcproj.in
--- a/projects/openttd_vs90.vcproj.in
+++ b/projects/openttd_vs90.vcproj.in
@@ -52,7 +52,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -154,7 +154,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -254,7 +254,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="2"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64;WITH_ASSERT"
 				StringPooling="true"
 				ExceptionHandling="1"
@@ -358,7 +358,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/MP"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
+				AdditionalIncludeDirectories="..\objs\langs;..\src\3rdparty\squirrel\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;ENABLE_AI;WITH_PERSONAL_DIR;PERSONAL_DIR=\&quot;OpenTTD\&quot;;_SQ64"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
diff --git a/projects/settings_vs100.vcxproj b/projects/settings_vs100.vcxproj
--- a/projects/settings_vs100.vcxproj
+++ b/projects/settings_vs100.vcxproj
@@ -1,53 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>settings</ProjectName>
-    <ProjectGuid>{0817F629-589E-4A3B-B81A-8647BC571E35}</ProjectGuid>
-    <RootNamespace>settings</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros">
-    <SettingsCommandLine>
-..\objs\settings\settings_gen.exe -o ..\objs\settings\table\settings.h -b ..\src\table\settings.h.preamble -a ..\src\table\settings.h.postamble ..\src\table\company_settings.ini ..\src\table\currency_settings.ini ..\src\table\gameopt_settings.ini ..\src\table\misc_settings.ini ..\src\table\settings.ini ..\src\table\win32_settings.ini
-    </SettingsCommandLine>
-  </PropertyGroup>
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\table\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\table\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SettingsCommandLine)</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SettingsCommandLine)</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">del ..\objs\settings\table\settings.h</NMakeCleanCommandLine>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\table\settings.h</NMakeOutput>
-  </PropertyGroup>
-  <ItemGroup>
-    <None Include="..\src\table\company_settings.ini" />
-    <None Include="..\src\table\currency_settings.ini" />
-    <None Include="..\src\table\gameopt_settings.ini" />
-    <None Include="..\src\table\misc_settings.ini" />
-    <None Include="..\src\table\settings.ini" />
-    <None Include="..\src\table\win32_settings.ini" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\src\table\settings.h.postamble" />
-    <None Include="..\src\table\settings.h.preamble" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
diff --git a/projects/settings_vs100.vcxproj.filters b/projects/settings_vs100.vcxproj.filters
--- a/projects/settings_vs100.vcxproj.filters
+++ b/projects/settings_vs100.vcxproj.filters
@@ -1,32 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="INI">
-      <UniqueIdentifier>{21deca6c-8df4-4f34-9dad-17d7781cd5a0}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\src\table\company_settings.ini">
-      <Filter>INI</Filter>
-    </None>
-    <None Include="..\src\table\currency_settings.ini">
-      <Filter>INI</Filter>
-    </None>
-    <None Include="..\src\table\gameopt_settings.ini">
-      <Filter>INI</Filter>
-    </None>
-    <None Include="..\src\table\misc_settings.ini">
-      <Filter>INI</Filter>
-    </None>
-    <None Include="..\src\table\settings.ini">
-      <Filter>INI</Filter>
-    </None>
-    <None Include="..\src\table\win32_settings.ini">
-      <Filter>INI</Filter>
-    </None>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\src\table\settings.h.postamble" />
-    <None Include="..\src\table\settings.h.preamble" />
-  </ItemGroup>
-</Project>
diff --git a/projects/settings_vs100.vcxproj.filters.in b/projects/settings_vs100.vcxproj.filters.in
--- a/projects/settings_vs100.vcxproj.filters.in
+++ b/projects/settings_vs100.vcxproj.filters.in
@@ -1,15 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="INI">
-      <UniqueIdentifier>{21deca6c-8df4-4f34-9dad-17d7781cd5a0}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-!!FILES!!
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\src\table\settings.h.postamble" />
-    <None Include="..\src\table\settings.h.preamble" />
-  </ItemGroup>
-</Project>
diff --git a/projects/settings_vs100.vcxproj.in b/projects/settings_vs100.vcxproj.in
--- a/projects/settings_vs100.vcxproj.in
+++ b/projects/settings_vs100.vcxproj.in
@@ -1,48 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>settings</ProjectName>
-    <ProjectGuid>{0817F629-589E-4A3B-B81A-8647BC571E35}</ProjectGuid>
-    <RootNamespace>settings</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros">
-    <SettingsCommandLine>
-!!FILTERS!!
-    </SettingsCommandLine>
-  </PropertyGroup>
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\table\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\table\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SettingsCommandLine)</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SettingsCommandLine)</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">del ..\objs\settings\table\settings.h</NMakeCleanCommandLine>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\table\settings.h</NMakeOutput>
-  </PropertyGroup>
-  <ItemGroup>
-!!FILES!!
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\src\table\settings.h.postamble" />
-    <None Include="..\src\table\settings.h.preamble" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
diff --git a/projects/settings_vs80.vcproj b/projects/settings_vs80.vcproj
--- a/projects/settings_vs80.vcproj
+++ b/projects/settings_vs80.vcproj
@@ -1,83 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="settings"
-	ProjectGUID="{0817F629-589E-4A3B-B81A-8647BC571E35}"
-	RootNamespace="settings"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="..\objs\settings\table"
-			IntermediateDirectory="..\objs\settings\table"
-			ConfigurationType="10"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="Generating settings.h"
-				CommandLine="
-..\objs\settings\settings_gen.exe -o ..\objs\settings\table\settings.h -b ..\src\table\settings.h.preamble -a ..\src\table\settings.h.postamble ..\src\table\company_settings.ini ..\src\table\currency_settings.ini ..\src\table\gameopt_settings.ini ..\src\table\misc_settings.ini ..\src\table\settings.ini ..\src\table\win32_settings.ini
-				"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="INI"
-			>
-		<File
-			RelativePath="..\src\table\company_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\currency_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\gameopt_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\misc_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\win32_settings.ini"
-			>
-		</File>
-		</Filter>
-		<File
-			RelativePath="..\src\table\settings.h.postamble"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\settings.h.preamble"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/projects/settings_vs80.vcproj.in b/projects/settings_vs80.vcproj.in
--- a/projects/settings_vs80.vcproj.in
+++ b/projects/settings_vs80.vcproj.in
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="settings"
-	ProjectGUID="{0817F629-589E-4A3B-B81A-8647BC571E35}"
-	RootNamespace="settings"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="..\objs\settings\table"
-			IntermediateDirectory="..\objs\settings\table"
-			ConfigurationType="10"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="Generating settings.h"
-				CommandLine="
-!!FILTERS!!
-				"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="INI"
-			>
-!!FILES!!
-		</Filter>
-		<File
-			RelativePath="..\src\table\settings.h.postamble"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\settings.h.preamble"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/projects/settings_vs90.vcproj b/projects/settings_vs90.vcproj
--- a/projects/settings_vs90.vcproj
+++ b/projects/settings_vs90.vcproj
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="settings"
-	ProjectGUID="{0817F629-589E-4A3B-B81A-8647BC571E35}"
-	RootNamespace="settings"
-	TargetFrameworkVersion="131072"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="..\objs\settings\table"
-			IntermediateDirectory="..\objs\settings\table"
-			ConfigurationType="10"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="Generating settings.h"
-				CommandLine="
-..\objs\settings\settings_gen.exe -o ..\objs\settings\table\settings.h -b ..\src\table\settings.h.preamble -a ..\src\table\settings.h.postamble ..\src\table\company_settings.ini ..\src\table\currency_settings.ini ..\src\table\gameopt_settings.ini ..\src\table\misc_settings.ini ..\src\table\settings.ini ..\src\table\win32_settings.ini
-				"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="INI"
-			>
-		<File
-			RelativePath="..\src\table\company_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\currency_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\gameopt_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\misc_settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\settings.ini"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\win32_settings.ini"
-			>
-		</File>
-		</Filter>
-		<File
-			RelativePath="..\src\table\settings.h.postamble"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\settings.h.preamble"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/projects/settings_vs90.vcproj.in b/projects/settings_vs90.vcproj.in
--- a/projects/settings_vs90.vcproj.in
+++ b/projects/settings_vs90.vcproj.in
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="settings"
-	ProjectGUID="{0817F629-589E-4A3B-B81A-8647BC571E35}"
-	RootNamespace="settings"
-	TargetFrameworkVersion="131072"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="..\objs\settings\table"
-			IntermediateDirectory="..\objs\settings\table"
-			ConfigurationType="10"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="Generating settings.h"
-				CommandLine="
-!!FILTERS!!
-				"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="INI"
-			>
-!!FILES!!
-		</Filter>
-		<File
-			RelativePath="..\src\table\settings.h.postamble"
-			>
-		</File>
-		<File
-			RelativePath="..\src\table\settings.h.preamble"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/projects/settingsgen_vs100.vcxproj b/projects/settingsgen_vs100.vcxproj
--- a/projects/settingsgen_vs100.vcxproj
+++ b/projects/settingsgen_vs100.vcxproj
@@ -1,81 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>settingsgen</ProjectName>
-    <ProjectGuid>{E9548DE9-F089-49B7-93A6-30BE2CC311C7}</ProjectGuid>
-    <RootNamespace>settings</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\objs\settings\</IntDir>
-    <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">settings_gen</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <PreBuildEvent>
-      <Command>
-      </Command>
-    </PreBuildEvent>
-    <CustomBuildStep>
-      <Inputs>%(Inputs)</Inputs>
-    </CustomBuildStep>
-    <ClCompile>
-      <Optimization>MinSpace</Optimization>
-      <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
-      <PreprocessorDefinitions>SETTINGSGEN;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AssemblerOutput>All</AssemblerOutput>
-      <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-    </ClCompile>
-    <Link>
-      <OutputFile>$(OutDir)settings_gen.exe</OutputFile>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <SubSystem>Console</SubSystem>
-    </Link>
-    <PostBuildEvent>
-      <Command>
-      </Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\core\alloc_func.cpp" />
-    <ClCompile Include="..\src\misc\getoptdata.cpp" />
-    <ClCompile Include="..\src\ini_load.cpp" />
-    <ClCompile Include="..\src\settingsgen\settingsgen.cpp" />
-    <ClCompile Include="..\src\string.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\src\misc\getoptdata.h" />
-    <ClInclude Include="..\src\ini_type.h" />
-    <ClInclude Include="..\src\core\smallvec_type.hpp" />
-    <ClInclude Include="..\src\string_func.h" />
-    <ClInclude Include="..\src\strings_type.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/projects/settingsgen_vs100.vcxproj.filters b/projects/settingsgen_vs100.vcxproj.filters
--- a/projects/settingsgen_vs100.vcxproj.filters
+++ b/projects/settingsgen_vs100.vcxproj.filters
@@ -1,32 +0,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{a4678737-b3b3-4be5-9db1-fa6ccd164c59}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\core\alloc_func.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\src\misc\getoptdata.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\src\ini_load.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\src\settingsgen\settingsgen.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\src\string.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\src\misc\getoptdata.h" />
-    <ClInclude Include="..\src\ini_type.h" />
-    <ClInclude Include="..\src\core\smallvec_type.hpp" />
-    <ClInclude Include="..\src\string_func.h" />
-    <ClInclude Include="..\src\strings_type.h" />
-  </ItemGroup>
-</Project>
diff --git a/projects/settingsgen_vs80.vcproj b/projects/settingsgen_vs80.vcproj
--- a/projects/settingsgen_vs80.vcproj
+++ b/projects/settingsgen_vs80.vcproj
@@ -1,143 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8,00"
-	Name="settings_gen"
-	ProjectGUID="{E9548DE9-F089-49B7-93A6-30BE2CC311C7}"
-	RootNamespace="settings"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="..\objs\settings"
-			IntermediateDirectory="..\objs\settings"
-			ConfigurationType="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				CommandLine=""
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-				AdditionalDependencies=""
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="1"
-				FavorSizeOrSpeed="2"
-				PreprocessorDefinitions="SETTINGSGEN;WIN32;_DEBUG;_CONSOLE"
-				AssemblerOutput="2"
-				ProgramDataBaseFileName="$(IntDir)\$(TargetName).pdb"
-				WarningLevel="3"
-				WarnAsError="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\settings_gen.exe"
-				GenerateDebugInformation="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				Description=""
-				CommandLine=""
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			>
-			<File
-				RelativePath="..\src\core\alloc_func.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\misc\getoptdata.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\ini_load.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\settingsgen\settingsgen.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\string.cpp"
-				>
-			</File>
-		</Filter>
-		<File
-			RelativePath="..\src\misc\getoptdata.h"
-			>
-		</File>
-		<File
-			RelativePath="..\src\ini_type.h"
-			>
-		</File>
-		<File
-			RelativePath="..\src\core\smallvec_type.hpp"
-			>
-		</File>
-		<File
-			RelativePath="..\src\string_func.h"
-			>
-		</File>
-		<File
-			RelativePath="..\src\strings_type.h"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/projects/settingsgen_vs90.vcproj b/projects/settingsgen_vs90.vcproj
--- a/projects/settingsgen_vs90.vcproj
+++ b/projects/settingsgen_vs90.vcproj
@@ -1,142 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9,00"
-	Name="settingsgen"
-	ProjectGUID="{E9548DE9-F089-49B7-93A6-30BE2CC311C7}"
-	RootNamespace="settings"
-	TargetFrameworkVersion="131072"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="..\objs\settings"
-			IntermediateDirectory="..\objs\settings"
-			ConfigurationType="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				CommandLine=""
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-				AdditionalDependencies=""
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="1"
-				FavorSizeOrSpeed="2"
-				PreprocessorDefinitions="SETTINGSGEN;WIN32;_DEBUG;_CONSOLE"
-				AssemblerOutput="2"
-				ProgramDataBaseFileName="$(IntDir)\$(TargetName).pdb"
-				WarningLevel="3"
-				WarnAsError="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\settings_gen.exe"
-				GenerateDebugInformation="true"
-				RandomizedBaseAddress="1"
-				DataExecutionPrevention="0"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-				CommandLine=""
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			>
-			<File
-				RelativePath="..\src\core\alloc_func.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\misc\getoptdata.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\ini_load.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\settingsgen\settingsgen.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\src\string.cpp"
-				>
-			</File>
-		</Filter>
-		<File
-			RelativePath="..\src\misc\getoptdata.h"
-			>
-		</File>
-		<File
-			RelativePath="..\src\ini_type.h"
-			>
-		</File>
-		<File
-			RelativePath="..\src\core\smallvec_type.hpp"
-			>
-		</File>
-		<File
-			RelativePath="..\src\string_func.h"
-			>
-		</File>
-		<File
-			RelativePath="..\src\strings_type.h"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/projects/version_vs100.vcxproj b/projects/version_vs100.vcxproj
--- a/projects/version_vs100.vcxproj
+++ b/projects/version_vs100.vcxproj
@@ -30,7 +30,6 @@
     <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cscript "$(ProjectDir)/determineversion.vbs"</NMakeBuildCommandLine>
     <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cscript "$(ProjectDir)/determineversion.vbs"</NMakeReBuildCommandLine>
     <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\src\rev.cpp</NMakeOutput>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">del ..\src\rev.cpp</NMakeCleanCommandLine>
   </PropertyGroup>
   <ItemGroup>
     <None Include="..\src\os\windows\ottdres.rc.in" />
@@ -39,4 +38,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/source.list b/source.list
--- a/source.list
+++ b/source.list
@@ -8,13 +8,16 @@
 cargotype.cpp
 cheat.cpp
 command.cpp
+command_queue.cpp
 console.cpp
 console_cmds.cpp
+copy_paste.cpp
 crashlog.cpp
 currency.cpp
 date.cpp
 debug.cpp
 dedicated.cpp
+departures.cpp
 depot.cpp
 driver.cpp
 economy.cpp
@@ -32,12 +35,17 @@
 heightmap.cpp
 highscore.cpp
 hotkeys.cpp
+infrastructure.cpp
 ini.cpp
-ini_load.cpp
 landscape.cpp
+linkgraph/demands.cpp
+linkgraph/flowmapper.cpp
+linkgraph/linkgraph.cpp
+linkgraph/mcf.cpp
 map.cpp
 misc.cpp
 mixer.cpp
+moving_average.cpp
 music.cpp
 network/network.cpp
 network/network_admin.cpp
@@ -91,6 +99,7 @@
 		#end
 	#end
 #end
+trafficlight.cpp
 vehicle.cpp
 vehiclelist.cpp
 viewport.cpp
@@ -127,6 +136,7 @@
 cmd_helper.h
 command_func.h
 command_type.h
+command_queue.h
 company_base.h
 company_func.h
 company_gui.h
@@ -136,6 +146,7 @@
 console_gui.h
 console_internal.h
 console_type.h
+copy_paste.h
 crashlog.h
 currency.h
 date_func.h
@@ -143,6 +154,9 @@
 date_type.h
 debug.h
 video/dedicated_v.h
+departures_func.h
+departures_gui.h
+departures_type.h
 depot_base.h
 depot_func.h
 depot_map.h
@@ -185,14 +199,21 @@
 industry.h
 industry_type.h
 industrytype.h
+infrastructure_func.h
 ini_type.h
 landscape.h
 landscape_type.h
 language.h
+linkgraph/demands.h
+linkgraph/flowmapper.h
+linkgraph/linkgraph.h
+linkgraph/linkgraph_type.h
+linkgraph/mcf.h
 livery.h
 map_func.h
 map_type.h
 mixer.h
+moving_average.h
 network/network.h
 network/network_admin.h
 network/network_base.h
@@ -314,6 +335,9 @@
 track_func.h
 track_type.h
 train.h
+trafficlight.h
+trafficlight_func.h
+trafficlight_type.h
 transparency.h
 transparency_gui.h
 transport_type.h
@@ -326,6 +350,7 @@
 vehiclelist.h
 viewport_func.h
 viewport_type.h
+watch_gui.h
 water.h
 waypoint_base.h
 waypoint_func.h
@@ -371,6 +396,7 @@
 core/math_func.cpp
 core/math_func.hpp
 core/mem_func.hpp
+core/multimap.hpp
 core/overflowsafe_type.hpp
 core/pool_func.cpp
 core/pool_func.hpp
@@ -391,7 +417,9 @@
 cheat_gui.cpp
 company_gui.cpp
 console_gui.cpp
+copy_paste_gui.cpp
 date_gui.cpp
+departures_gui.cpp
 depot_gui.cpp
 dock_gui.cpp
 engine_gui.cpp
@@ -414,6 +442,7 @@
 object_gui.cpp
 order_gui.cpp
 osk_gui.cpp
+programmable_signals_gui.cpp
 rail_gui.cpp
 road_gui.cpp
 roadveh_gui.cpp
@@ -433,6 +462,7 @@
 tree_gui.cpp
 vehicle_gui.cpp
 viewport_gui.cpp
+watch_gui.cpp
 waypoint_gui.cpp
 
 # Widgets
@@ -485,6 +515,7 @@
 saveload/group_sl.cpp
 saveload/industry_sl.cpp
 saveload/labelmaps_sl.cpp
+saveload/linkgraph_sl.cpp
 saveload/map_sl.cpp
 saveload/misc_sl.cpp
 saveload/newgrf_sl.cpp
@@ -498,6 +529,7 @@
 saveload/saveload.h
 saveload/saveload_filter.h
 saveload/saveload_internal.h
+saveload/signal_sl.cpp
 saveload/signs_sl.cpp
 saveload/station_sl.cpp
 saveload/storage_sl.cpp
@@ -532,7 +564,7 @@
 table/railtypes.h
 table/road_land.h
 table/roadveh_movement.h
-../objs/settings/table/settings.h
+table/settings.h
 table/sprites.h
 table/station_land.h
 table/strgen_tables.h
diff --git a/src/ai/api/ai_tile.hpp b/src/ai/api/ai_tile.hpp
--- a/src/ai/api/ai_tile.hpp
+++ b/src/ai/api/ai_tile.hpp
@@ -259,7 +259,7 @@
 	 * The returned height is the height of the bare tile. A possible foundation on the tile does not influence this height.
 	 * @param tile The tile to check on.
 	 * @pre AIMap::IsValidTile(tile).
-	 * @return The height of the lowest corner of the tile, ranging from 0 to 15.
+	 * @return The height of the lowest corner of the tile, ranging from 0 to 15, or 0 to 255 in case of AllowMoreHeightlevels().
 	 */
 	static int32 GetMinHeight(TileIndex tile);
 
@@ -268,7 +268,7 @@
 	 * The returned height is the height of the bare tile. A possible foundation on the tile does not influence this height.
 	 * @param tile The tile to check on.
 	 * @pre AIMap::IsValidTile(tile).
-	 * @return The height of the highest corner of the tile, ranging from 0 to 15.
+	 * @return The height of the highest corner of the tile, ranging from 0 to 15, or 0 to 255 in case of AllowMoreHeightlevels().
 	 */
 	static int32 GetMaxHeight(TileIndex tile);
 
@@ -278,7 +278,7 @@
 	 * @param tile The tile to check on.
 	 * @param corner The corner to query.
 	 * @pre AIMap::IsValidTile(tile).
-	 * @return The height of the lowest corner of the tile, ranging from 0 to 15.
+	 * @return The height of the lowest corner of the tile, ranging from 0 to 15, or 0 to 255 in case of AllowMoreHeightlevels().
 	 */
 	static int32 GetCornerHeight(TileIndex tile, Corner corner);
 
diff --git a/src/aircraft.h b/src/aircraft.h
--- a/src/aircraft.h
+++ b/src/aircraft.h
@@ -15,6 +15,19 @@
 #include "station_map.h"
 #include "vehicle_base.h"
 
+/**
+ * Minimal, maximal and holding flying altitude above ground while a plane is in flight
+ * and not starting or landing, i.e. in the state SLOWTURN & NOSPDCLAMP.
+ * Under certain circumstances, the actual flying altitude is
+ * higher, because certain offsets are added.
+ */
+enum AircraftFlyingAltitude {
+	AIRCRAFT_MIN_FLYING_ALTITUDE        = 120, ///< minimal flying altitude above tile.
+	AIRCRAFT_MAX_FLYING_ALTITUDE        = 360, ///< maximal flying altitude above tile.
+	PLANE_HOLD_MAX_FLYING_ALTITUDE      = 150, ///< holding flying altitude above tile of planes.
+	HELICOPTER_HOLD_MAX_FLYING_ALTITUDE = 184  ///< holding flying altitude above tile of helicopters. // check if disaster vehicles behave the same. ifnot make it so ...
+};
+
 struct Aircraft;
 
 /** An aircraft can be one of those types. */
@@ -25,7 +38,6 @@
 	AIR_ROTOR      = 6  ///< rotor of an helicopter
 };
 
-
 void HandleAircraftEnterHangar(Aircraft *v);
 void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, EngineImageType image_type);
 void UpdateAirplanesOnNewStation(const Station *st);
@@ -49,6 +61,22 @@
 	byte number_consecutive_turns; ///< Protection to prevent the aircraft of making a lot of turns in order to reach a specific point.
 	byte turn_counter;             ///< Ticks between each turn to prevent > 45 degree turns.
 
+	/**
+	 * True if an only if the aircraft has touched its upper altitude limit
+	 * and currently corrects its altitude. Used in order to avoid the
+	 * aircraft "stairclimbing". When an aircraft starts correcting
+	 * altitude it should make a rather big correction in one step.
+	 */
+	bool in_max_height_correction;
+
+	/**
+	 * True if an only if the aircraft has touched its lower altitude limit
+	 * and currently corrects its altitude. Used in order to avoid the
+	 * aircraft "stairclimbing". When an aircraft starts correcting
+	 * altitude it should make a rather big correction in one step.
+	 */
+	bool in_min_height_correction;
+
 	/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
 	Aircraft() : SpecializedVehicleBase() {}
 	/** We want to 'destruct' the right class. */
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -16,6 +16,7 @@
 #include "aircraft.h"
 #include "landscape.h"
 #include "news_func.h"
+#include "tile_map.h"
 #include "vehicle_gui.h"
 #include "newgrf_engine.h"
 #include "newgrf_sound.h"
@@ -122,10 +123,15 @@
 	const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
 
 	FOR_ALL_STATIONS(st) {
-		if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT)) continue;
+		if (!IsInfraUsageAllowed(VEH_AIRCRAFT, v->owner, st->owner) || !(st->facilities & FACIL_AIRPORT)) continue;
 
 		const AirportFTAClass *afc = st->airport.GetFTA();
 		if (!st->airport.HasHangar() || (
+					/* The airport needs to have facilities for this plane type. */
+					(AircraftVehInfo(v->engine_type)->subtype & AIR_CTOL) ?
+					!(afc->flags & AirportFTAClass::AIRPLANES) :
+					!(afc->flags & AirportFTAClass::HELICOPTERS)
+					) || (
 					/* don't crash the plane if we know it can't land at the airport */
 					(afc->flags & AirportFTAClass::SHORT_STRIP) &&
 					(avi->subtype & AIR_FAST) &&
@@ -228,6 +234,14 @@
 	const AircraftVehicleInfo *avi = &e->u.air;
 	const Station *st = Station::GetByTile(tile);
 
+	/* Engines without valid cargo should not be available */
+	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
+
+	/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
+	if (flags & DC_QUERY_COST) return CommandCost();
+
+	if (!IsHangarTile(tile) || !IsInfraUsageAllowed(VEH_AIRCRAFT, _current_company, GetTileOwner(tile))) return CMD_ERROR;
+
 	/* Prevent building aircraft types at places which can't handle them */
 	if (!CanVehicleUseStation(e->index, st)) return CMD_ERROR;
 
@@ -267,6 +281,7 @@
 
 		v->name = NULL;
 		v->last_station_visited = INVALID_STATION;
+		v->last_loading_station = INVALID_STATION;
 
 		v->acceleration = avi->acceleration;
 		v->engine_type = e->index;
@@ -280,6 +295,9 @@
 
 		v->reliability = e->reliability;
 		v->reliability_spd_dec = e->reliability_spd_dec;
+		/* Higher speed means higher breakdown chance. */
+		/* To somewhat compensate for the fact that fast aircraft spend less time in the air. */
+		v->breakdown_chance = Clamp(64 + (AircraftVehInfo(v->engine_type)->max_speed >> 3), 0, 255);
 		v->max_age = e->GetLifeLengthInDays();
 
 		_new_vehicle_id = v->index;
@@ -289,6 +307,8 @@
 		v->state = HANGAR;
 		v->previous_pos = v->pos;
 		v->targetairport = GetStationIndex(tile);
+		v->in_min_height_correction = false;
+		v->in_max_height_correction = false;
 		v->SetNext(u);
 
 		v->service_interval = Company::Get(_current_company)->settings.vehicle.servint_aircraft;
@@ -341,7 +361,6 @@
 	return CommandCost();
 }
 
-
 bool Aircraft::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
 {
 	const Station *st = GetTargetAirportIfValid(this);
@@ -604,12 +623,14 @@
 	spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
 
 	/* adjust speed for broken vehicles */
-	if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN);
+	if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_AIRCRAFT_SPEED) spd = min(v->breakdown_severity << 3, spd);
 
 	/* updates statusbar only if speed have changed to save CPU time */
 	if (spd != v->cur_speed) {
 		v->cur_speed = spd;
-		SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
+		if (_settings_client.gui.vehicle_speed) {
+			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
+		}
 	}
 
 	/* Adjust distance moved by plane speed setting */
@@ -647,16 +668,93 @@
 		case DIR_NE:
 		case DIR_E:
 		case DIR_SE:
-			base_altitude += 10;
+			offset += 10;
 			break;
 
 		default: break;
 	}
 
 	/* Make faster planes fly higher so that they can overtake slower ones */
-	base_altitude += min(20 * (v->vcache.cached_max_speed / 200), 90);
+	offset += min(20 * (v->vcache.cached_max_speed / 200), 90);
+	return offset;
+}
 
-	return base_altitude;
+/**
+ * Get the tile height below the aircraft.
+ * This function is needed because aircraft can leave the mapborders.
+ * The game would crash if an aircraft leaves the northeast or southeast border.
+ * Just for completeness we check all four map edges.
+ *
+ * @param x_pos x position of the aircraft's shadow on the map.
+ * @param y_pos y position of the aircraft's shadow on the map.
+ * @return the tileheight below the aircaft's shadow.
+ */
+uint GetTileHeightBelowAircraft(int x_pos, int y_pos)
+{
+	TileIndex tile = TileVirtXY(x_pos, y_pos);
+	uint tile_height;
+
+	/* Check for being inside the map. If not call TileHeightOutsideMap() instead of TileHeight(). */
+	if (IsInsideMM(x_pos, 0, (int)MapSizeX() * (int)TILE_SIZE)
+			&& IsInsideMM(y_pos, 0, (int)MapSizeY() * (int)TILE_SIZE)) {
+		tile_height = TileHeight(tile) * TILE_HEIGHT;
+	} else {
+		tile_height = TileHeightOutsideMap(x_pos, y_pos) * TILE_HEIGHT + AIRCRAFT_MAX_FLYING_ALTITUDE;
+	}
+
+	return tile_height;
+}
+
+/**
+ * Get the height in pixels, from level 0, dependant on terrain below,
+ * at wich an aircraft should start increasing it's altitude,
+ * to prevent aircraft crashing in higher terrain ahead.
+ *
+ * @param x_pos x position of the aircraft's shadow on the map.
+ * @param y_pos y position of the aircraft's shadow on the map.
+ * @param offset offset to add to returned altitude.
+ * @return Minimal aircraft flying altitude above ground, while in normal flight, in pixels.
+ */
+uint GetAircraftMinAltitude(int x_pos, int y_pos, int offset)
+{
+	uint tile_height = GetTileHeightBelowAircraft(x_pos, y_pos);
+
+	return tile_height + AIRCRAFT_MIN_FLYING_ALTITUDE + offset;
+}
+
+/**
+ * Get the height in pixels, from level 0, dependant on terrain below,
+ * at wich an aircraft should start decreasing it's altitude,
+ * to prevent aircraft taking off to space.
+ *
+ * @param x_pos x position of the aircraft's shadow on the map.
+ * @param y_pos y position of the aircraft's shadow on the map.
+ * @param offset offset to add to returned altitude.
+ * @return Maximal aircraft flying altitude above ground, while in normal flight, in pixels.
+ */
+uint GetAircraftMaxAltitude(int x_pos, int y_pos, int offset)
+{
+	uint tile_height = GetTileHeightBelowAircraft(x_pos, y_pos);
+
+	return tile_height + AIRCRAFT_MAX_FLYING_ALTITUDE + offset;
+}
+
+/**
+ * Checks the flightpath height of the aircraft, in pixels, from level 0, dependant on terrain below,
+ * after adjusting height.
+ *
+ * @param v The aircraft that may or may not need to decrease its altitude.
+ * @return Maximal aircraft holding altitude, while in normal flight, in pixels.
+ */
+uint GetAircraftHoldMaxAltitude(const Aircraft *v)
+{
+	uint tile_height = GetTileHeightBelowAircraft(v->x_pos, v->y_pos);
+
+	if (v->subtype == AIR_HELICOPTER) {
+		return tile_height + HELICOPTER_HOLD_MAX_FLYING_ALTITUDE;
+	} else {
+		return tile_height + PLANE_HOLD_MAX_FLYING_ALTITUDE;
+	}
 }
 
 /**
@@ -671,7 +769,7 @@
  * @param v   The vehicle that is approaching the airport
  * @param apc The Airport Class being approached.
  * @param rotation The rotation of the airport.
- * @returns   The index of the entry point
+ * @return    The index of the entry point
  */
 static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
 {
@@ -748,7 +846,9 @@
 			UpdateAircraftCache(v);
 			AircraftNextAirportPos_and_Order(v);
 			/* get aircraft back on running altitude */
-			SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlyingAltitude(v));
+			int new_z_pos = GetAircraftMaxAltitude(v->x_pos, v->y_pos, GetAircraftFlyingAltitudeOffset(v));
+			SetAircraftPosition(v, v->x_pos, v->y_pos, new_z_pos);
+
 			return false;
 		}
 	}
@@ -846,6 +946,9 @@
 		if (!UpdateAircraftSpeed(v, SPEED_LIMIT_TAXI)) return false;
 
 		v->direction = ChangeDir(v->direction, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
+
+		DEBUG(misc, 9, "New direction: %i", (int)v->direction);
+
 		v->cur_speed >>= 1;
 
 		SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
@@ -933,11 +1036,63 @@
 		int z = v->z_pos;
 
 		if (amd.flag & AMED_TAKEOFF) {
-			z = min(z + 2, GetAircraftFlyingAltitude(v));
+			uint aircraft_max_altitude = GetAircraftMaxAltitude(v->x_pos, v->y_pos, GetAircraftFlyingAltitudeOffset(v));
+
+			if (aircraft_max_altitude >= z) {
+				/* The aircraft rises or has reached its flying altitude. */
+				z = min(z + 2, GetAircraftMaxAltitude(v->x_pos, v->y_pos, GetAircraftFlyingAltitudeOffset(v)));
+			} else {
+				/* Aircraft has reached its flying altitude, but then the terrain
+				 * gets lower. So, its flying altitude also decreases.
+				 * We ignore this effect here, as lowering altitude during takeoff
+				 * would be a bit strange. */
+			}
 		}
 
-		/* Let the plane drop from normal flight altitude to holding pattern altitude */
-		if ((amd.flag & AMED_HOLD) && (z > PLANE_HOLDING_ALTITUDE)) z--;
+		if ((amd.flag & AMED_SLOWTURN) && (amd.flag & AMED_NOSPDCLAMP)) {
+			/* Aircraft is in flight. We want to enforce it being somewhere
+			 * between the minimum and the maximum allowed altitude. */
+			uint aircraft_min_altitude = GetAircraftMinAltitude(v->x_pos, v->y_pos, GetAircraftFlyingAltitudeOffset(v));
+			uint aircraft_max_altitude = GetAircraftMaxAltitude(v->x_pos, v->y_pos, GetAircraftFlyingAltitudeOffset(v));
+			uint aircraft_middle_altitude = aircraft_min_altitude + ((uint)(aircraft_max_altitude - aircraft_min_altitude)) / 2;
+
+			/* If those assumptions would be violated, aircrafts would behave
+			 * fairly strange. */
+			assert(aircraft_min_altitude < aircraft_max_altitude);
+			assert(aircraft_min_altitude < aircraft_middle_altitude);
+			assert(aircraft_middle_altitude < aircraft_max_altitude);
+
+			if (z < aircraft_min_altitude
+					|| (v->in_min_height_correction && z < aircraft_middle_altitude)) {
+				/* Rise. And don't fly into that mountain right ahead.
+				 * And avoid our aircraft become a stairclimber, so if we start
+				 * correcting altitude, then we stop correction not too early. */
+				v->in_min_height_correction = true;
+				z += 2;
+
+			} else if (z > aircraft_max_altitude
+					|| (v->in_max_height_correction && z > aircraft_middle_altitude)) {
+				/* Fly lower. You are an aircraft, not an UFO.
+				 * And again, don't stop correcting altitude too early. */
+				v->in_max_height_correction = true;
+				z--;
+
+			} else if (v->in_min_height_correction && z >= aircraft_middle_altitude) {
+				/* Now, we have corrected altitude enough. */
+				v->in_min_height_correction = false;
+
+			} else if (v->in_max_height_correction && z <= aircraft_middle_altitude) {
+				/* Now, we have corrected altitude enough. */
+				v->in_max_height_correction = false;
+			}
+		}
+
+		if (amd.flag & AMED_HOLD) {
+			uint aircraft_max_hold_altitude = GetAircraftHoldMaxAltitude(v);
+			if (z > aircraft_max_hold_altitude) {
+				z--;
+			}
+		}
 
 		if (amd.flag & AMED_LAND) {
 			if (st->airport.tile == INVALID_TILE) {
@@ -946,7 +1101,8 @@
 				UpdateAircraftCache(v);
 				AircraftNextAirportPos_and_Order(v);
 				/* get aircraft back on running altitude */
-				SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));
+				int new_z_pos = GetAircraftMaxAltitude(v->x_pos, v->y_pos, GetAircraftFlyingAltitudeOffset(v));
+				SetAircraftPosition(v, gp.x, gp.y, new_z_pos);
 				continue;
 			}
 
@@ -961,6 +1117,9 @@
 			if (delta >= t) {
 				z -= CeilDiv(z - curz, t);
 			}
+
+			DEBUG(misc, 9, "AMED_LAND: New z is %i", z);
+
 			if (z < curz) z = curz;
 		}
 
@@ -982,6 +1141,39 @@
 }
 
 /**
+ * Send a broken plane that needs to visit a depot to the correct location.
+ * @param v Airplane in question.
+ */
+void FindBreakdownDestination(Aircraft *v)
+{
+	assert(v->type == VEH_AIRCRAFT && v->breakdown_ctr == 1);
+
+	DestinationID destination = INVALID_STATION;
+	if (v->breakdown_type == BREAKDOWN_AIRCRAFT_DEPOT) {
+		/* Go to a hangar, if possible at our current destination. */
+		v->FindClosestDepot(NULL, &destination, NULL);
+	} else if (v->breakdown_type == BREAKDOWN_AIRCRAFT_EM_LANDING) {
+		/* Go to the nearest airport with a hangar. */
+		destination = FindNearestHangar(v);
+	} else {
+		NOT_REACHED();
+	}
+
+	if(destination != INVALID_STATION) {
+		if(destination != v->current_order.GetDestination()) {
+			v->current_order.MakeGoToDepot(destination, ODTFB_BREAKDOWN);
+			AircraftNextAirportPos_and_Order(v);
+		} else {
+			v->current_order.MakeGoToDepot(destination, ODTFB_BREAKDOWN);
+		}
+	} else {
+		/* If no hangar was found, crash. */
+		v->targetairport = INVALID_STATION;
+		CrashAirplane(v);
+	}
+}
+
+/**
  * Handle crashed aircraft \a v.
  * @param v Crashed aircraft.
  */
@@ -995,7 +1187,7 @@
 	if (v->crashed_counter < 500 && st == NULL && ((v->crashed_counter % 3) == 0) ) {
 		int z = GetSlopePixelZ(v->x_pos, v->y_pos);
 		v->z_pos -= 1;
-		if (v->z_pos == z) {
+		if (v->z_pos == (int32)z) {
 			v->crashed_counter = 500;
 			v->z_pos++;
 		}
@@ -1056,7 +1248,8 @@
 
 	if (!(v->vehstatus & VS_AIRCRAFT_BROKEN)) return;
 
-	if (v->cur_speed < 10) {
+	/* Breakdown-related speed limits are lifted when we are on the ground. */
+	if(v->state != FLYING && v->state != LANDING && v->breakdown_type == BREAKDOWN_AIRCRAFT_SPEED) {
 		v->vehstatus &= ~VS_AIRCRAFT_BROKEN;
 		v->breakdown_ctr = 0;
 		return;
@@ -1172,13 +1365,18 @@
 	Station *st = Station::Get(v->targetairport);
 
 	/* FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports */
-	uint32 prob = (0x4000 << _settings_game.vehicle.plane_crashes);
+	uint32 prob = (_settings_game.vehicle.improved_breakdowns && _settings_game.difficulty.vehicle_breakdowns) ?
+			0x10000 / 10000 : 0x4000 << _settings_game.vehicle.plane_crashes;
+	
 	if ((st->airport.GetFTA()->flags & AirportFTAClass::SHORT_STRIP) &&
 			(AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
 			!_cheats.no_jetcrash.value) {
 		prob /= 20;
-	} else {
+	} else if (!_settings_game.vehicle.improved_breakdowns) {
 		prob /= 1500;
+	} else if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_AIRCRAFT_EM_LANDING) {
+		/* Airplanes that are attempting an emergency landing have a 2% chance to crash */
+		prob = 0x10000 / 50;
 	}
 
 	if (GB(Random(), 0, 22) > prob) return;
@@ -1200,9 +1398,9 @@
 static void AircraftEntersTerminal(Aircraft *v)
 {
 	if (v->current_order.IsType(OT_GOTO_DEPOT)) return;
+	v->last_station_visited = v->targetairport;
 
 	Station *st = Station::Get(v->targetairport);
-	v->last_station_visited = v->targetairport;
 
 	/* Check if station was ever visited before */
 	if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
@@ -1450,7 +1648,7 @@
 	Station *st = Station::Get(v->targetairport);
 
 	/* runway busy or not allowed to use this airstation, circle */
-	if (CanVehicleUseStation(v, st) && (st->owner == OWNER_NONE || st->owner == v->owner)) {
+	if (CanVehicleUseStation(v, st) && IsInfraUsageAllowed(VEH_AIRCRAFT, v->owner, st->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 */
diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp
--- a/src/autoreplace_cmd.cpp
+++ b/src/autoreplace_cmd.cpp
@@ -119,7 +119,7 @@
 			uint amount = min(src->cargo.Count(), dest->cargo_cap - dest->cargo.Count());
 			if (amount <= 0) continue;
 
-			src->cargo.MoveTo(&dest->cargo, amount, VehicleCargoList::MTA_UNLOAD, NULL);
+			src->cargo.MoveTo(&dest->cargo, amount);
 		}
 	}
 
diff --git a/src/bridge.h b/src/bridge.h
--- a/src/bridge.h
+++ b/src/bridge.h
@@ -75,6 +75,8 @@
 CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags = DC_NONE);
 int CalcBridgeLenCostFactor(int x);
 
+BridgeType GetFastestAvailableBridgeType(uint bridge_len);
+
 void ResetBridges();
 
 #endif /* BRIDGE_H */
diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp
--- a/src/cargopacket.cpp
+++ b/src/cargopacket.cpp
@@ -10,7 +10,9 @@
 /** @file cargopacket.cpp Implementation of the cargo packets. */
 
 #include "stdafx.h"
+#include "station_base.h"
 #include "core/pool_func.hpp"
+#include "core/random_func.hpp"
 #include "economy_base.h"
 
 /* Initialize the cargopacket-pool */
@@ -38,13 +40,13 @@
  * that, in contrary to all other pools, does not memset to 0.
  */
 CargoPacket::CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id) :
-	feeder_share(0),
-	count(count),
-	days_in_transit(0),
-	source_id(source_id),
-	source(source),
-	source_xy(source_xy),
-	loaded_at_xy(0)
+		feeder_share(0),
+		count(count),
+		days_in_transit(0),
+		source_id(source_id),
+		source(source),
+		source_xy(source_xy),
+		loaded_at_xy(0)
 {
 	assert(count != 0);
 	this->source_type  = source_type;
@@ -107,7 +109,7 @@
 /**
  * Invalidates (sets source_id to INVALID_SOURCE) all cargo packets from given source.
  * @param src_type Type of source.
- * @param src Index of source.
+ * @param src      Index of source.
  */
 /* static */ void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
 {
@@ -131,15 +133,15 @@
 
 /*
  *
- * Cargo list implementation
+ * Cargo list implementation.
  *
  */
 
 /**
  * Destroy the cargolist ("frees" all cargo packets).
  */
-template <class Tinst>
-CargoList<Tinst>::~CargoList()
+template <class Tinst, class Tcont>
+CargoList<Tinst, Tcont>::~CargoList()
 {
 	for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
 		delete *it;
@@ -150,8 +152,8 @@
  * Empty the cargo list, but don't free the cargo packets;
  * the cargo packets are cleaned by CargoPacket's CleanPool.
  */
-template <class Tinst>
-void CargoList<Tinst>::OnCleanPool()
+template <class Tinst, class Tcont>
+void CargoList<Tinst,Tcont>::OnCleanPool()
 {
 	this->packets.clear();
 }
@@ -161,8 +163,8 @@
  * Decreases count and days_in_transit.
  * @param cp Packet to be removed from cache.
  */
-template <class Tinst>
-void CargoList<Tinst>::RemoveFromCache(const CargoPacket *cp)
+template <class Tinst, class Tcont>
+void CargoList<Tinst, Tcont>::RemoveFromCache(const CargoPacket *cp)
 {
 	this->count                 -= cp->count;
 	this->cargo_days_in_transit -= cp->days_in_transit * cp->count;
@@ -173,8 +175,8 @@
  * Increases count and days_in_transit.
  * @param cp New packet to be inserted.
  */
-template <class Tinst>
-void CargoList<Tinst>::AddToCache(const CargoPacket *cp)
+template <class Tinst, class Tcont>
+void CargoList<Tinst, Tcont>::AddToCache(const CargoPacket *cp)
 {
 	this->count                 += cp->count;
 	this->cargo_days_in_transit += cp->days_in_transit * cp->count;
@@ -182,27 +184,28 @@
 
 /**
  * Appends the given cargo packet. Tries to merge it with another one in the
- * packets list. If no fitting packet is found, appends it.
+ * packets list. if no fitting packet is found, appends it.
  * @warning After appending this packet may not exist anymore!
  * @note Do not use the cargo packet anymore after it has been appended to this CargoList!
- * @param cp Cargo packet to add.
- * @pre cp != NULL
+ * @param cp           Cargo packet to add.
+ * @param Update_cache If false, the cache is not updated; used when loading from
+ *        the reservation list.
+ * @pre cp != NULL.
  */
-template <class Tinst>
-void CargoList<Tinst>::Append(CargoPacket *cp)
+void VehicleCargoList::Append(CargoPacket *cp, bool update_cache)
 {
-	assert(cp != NULL);
-	static_cast<Tinst *>(this)->AddToCache(cp);
+ 	assert(cp != NULL);
 
-	for (List::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
+	if (update_cache) this->AddToCache(cp);
+	for (CargoPacketList::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
 		CargoPacket *icp = *it;
-		if (Tinst::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
+		if (VehicleCargoList::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
 			icp->Merge(cp);
 			return;
 		}
 	}
 
-	/* The packet could not be merged with another one */
+	/* The packet could not be merged with another one. */
 	this->packets.push_back(cp);
 }
 
@@ -211,10 +214,10 @@
  * first count cargo entities and removes the rest.
  * @param max_remaining Maximum amount of entities to be in the list after the command.
  */
-template <class Tinst>
-void CargoList<Tinst>::Truncate(uint max_remaining)
+template <class Tinst, class Tcont>
+void CargoList<Tinst, Tcont>::Truncate(uint max_remaining)
 {
-	for (Iterator it(packets.begin()); it != packets.end(); /* done during loop*/) {
+	for (Iterator it(packets.begin()); it != packets.end(); /* Done during loop. */) {
 		CargoPacket *cp = *it;
 		if (max_remaining == 0) {
 			/* Nothing should remain, just remove the packets. */
@@ -353,6 +356,273 @@
 }
 
 /**
+ * Delete a vehicle cargo list and clear its reservation list.
+ */
+VehicleCargoList::~VehicleCargoList()
+{
+	for (Iterator it(this->reserved.begin()); it != this->reserved.end(); ++it) {
+		delete *it;
+	}
+}
+
+/**
+ * Deliver a specific packet or part of it to a station and handle payment. The
+ * given iterator is incremented in the process.
+ * @param it      Iterator pointing to the packet to be delivered.
+ * @param cap     Maximum amount of cargo to be unloaded.
+ * @param payment Payment object to use for payment.
+ * @return        Amount of cargo actually unloaded.
+ */
+uint VehicleCargoList::DeliverPacket(Iterator &it, uint cap, CargoPayment *payment)
+{
+	CargoPacket *p = *it;
+	uint unloaded = 0;
+	if (p->count <= cap) {
+		payment->PayFinalDelivery(p, p->count);
+		this->packets.erase(it++);
+		this->RemoveFromCache(p);
+		unloaded = p->count;
+		delete p;
+	} else {
+		payment->PayFinalDelivery(p, cap);
+		this->count -= cap;
+		this->cargo_days_in_transit -= cap * p->days_in_transit;
+		this->feeder_share -= p->feeder_share;
+		p->feeder_share = 0;
+		p->count -= cap;
+		unloaded = cap;
+		++it;
+	}
+	return unloaded;
+}
+
+/**
+ * Keep a packet in the vehicle while unloading by temporarily moving it to the
+ * reservation list. The given iterator is incremented in the process.
+ * @param it Iterator pointing to the packet.
+ * @return   Size of the packet.
+ */
+uint VehicleCargoList::KeepPacket(Iterator &it)
+{
+	CargoPacket *cp = *it;
+	this->reserved.push_back(cp);
+	this->reserved_count += cp->count;
+	this->packets.erase(it++);
+	return cp->count;
+}
+
+/**
+ * Transfer a packet to a station, but don't deliver it. Increment the given
+ * iterator in the process.
+ * @param it      Iterator pointing to a packet in the list.
+ * @param cap     Maximum amount of cargo to be transferred.
+ * @param dest    Cargo list of the station the cargo should be transferred to.
+ * @param payment Payment object to be updated with the resulting transfer
+ *                credits.
+ * @param next    ID of the station the cargo wants to go to next.
+ * @return        Amount of cargo actually moved.
+ */
+uint VehicleCargoList::TransferPacket(Iterator &it, uint cap, StationCargoList *dest, CargoPayment *payment, StationID next)
+{
+	CargoPacket *cp = this->RemovePacket(it, cap);
+	cp->feeder_share += payment->PayTransfer(cp, cp->count);
+	uint ret = cp->count;
+	dest->Append(next, cp);
+	return ret;
+}
+
+/**
+ * Determine what a cargo packet arriving at the station this list belongs to
+ * will do, using the "old", non-cargodist algorithm.
+ * @param flags  Unload flags telling if the cargo is accepted and what order
+ *               flags there are.
+ * @param source ID of the packets source station.
+ * @return       Unload type (deliver, transfer, keep) telling what to do with the
+ *               packet.
+ */
+UnloadType StationCargoList::WillUnloadOld(byte flags, StationID source)
+{
+	/* Try to unload cargo. */
+	bool move = (flags & (UL_DELIVER | UL_ACCEPTED | UL_TRANSFER)) != 0;
+	/* Try to deliver cargo if unloading. */
+	bool deliver = (flags & UL_ACCEPTED) && !(flags & UL_TRANSFER) && (source != this->station->index);
+	/* Transfer cargo if delivery was unsuccessful. */
+	bool transfer = (flags & (UL_TRANSFER | UL_DELIVER)) != 0;
+	if (move) {
+		if(deliver) {
+			return UL_DELIVER;
+		} else if (transfer) {
+			return UL_TRANSFER;
+		} else {
+			/* This case is for (non-)delivery to the source station without special flags.
+			 * Like the code in MoveTo did, we keep the packet in this case.
+			 */
+			return UL_KEEP;
+		}
+	} else {
+		return UL_KEEP;
+	}
+}
+
+/**
+ * Determine what a cargo packet arriving at the station this list belongs to
+ * will do, using the Cargodist algorithm.
+ * @param flags  Unload flags telling if the cargo is accepted and what order
+ *               flags there are.
+ * @param next   The station the vehicle the cargo is coming from will
+ *               visit next (or INVALID_STATION if unknown).
+ * @param via    The station the cargo wants to go to next. If that is this
+ *               station the cargo wants to be delivered.
+ * @param source ID of the packets source station.
+ * @return       Unload type (deliver, transfer, keep) telling what to do with the
+ *               packet.
+ */
+UnloadType StationCargoList::WillUnloadCargoDist(byte flags, StationID next, StationID via, StationID source)
+{
+	if (via == this->station->index) {
+		/* This is the final destination, deliver ... */
+		if (flags & UL_TRANSFER) {
+			/* .. except if explicitly told not to do so ... */
+			return UL_TRANSFER;
+		} else if (flags & UL_ACCEPTED) {
+			return UL_DELIVER;
+		} else if (flags & UL_DELIVER) {
+			/* .. or if the station suddenly doesn't accept our cargo, but we have an explicit deliver order... */
+			return UL_TRANSFER;
+		} else {
+			/* .. or else if it doesn't accept. */
+			return UL_KEEP;
+		}
+	} else {
+		/* Packet has to travel on, find out if it can stay on board. */
+		if (flags & UL_DELIVER) {
+			/* Order overrides cargodist:
+			 * play by the old loading rules here as player is interfering with cargodist.
+			 * Try to deliver, as move has been forced upon us. */
+			if ((flags & UL_ACCEPTED) && !(flags & UL_TRANSFER) && source != this->station->index) {
+				return UL_DELIVER;
+			} else {
+				/* Transfer cargo, as delivering didn't work. */
+				return UL_TRANSFER;
+			}
+		} else if (flags & UL_TRANSFER) {
+			/* Transfer forced. */
+			return UL_TRANSFER;
+		} else if (next == via && next != INVALID_STATION) {
+			/* Vehicle goes to the packet's next hop or has nondeterministic order: keep the packet. */
+			return UL_KEEP;
+		} else {
+			/* Vehicle goes somewhere else, transfer the packet. */
+			return UL_TRANSFER;
+		}
+	}
+}
+
+/**
+ * Swap the reserved and packets lists when starting to load cargo. Pull in the
+ *     "kept" packets which were stored in the reservation list so that we don't
+ *     have to iterate over them all the time.
+ * @pre this->packets.empty().
+ */
+void VehicleCargoList::SwapReserved()
+{
+	assert(this->packets.empty());
+	this->packets.swap(this->reserved);
+	this->reserved_count = 0;
+}
+
+/**
+ * Moves the given amount of cargo from a vehicle to a station.
+ * Depending on the value of flags the side effects of this function differ:
+ * 	- OUFB_UNLOAD_IF_POSSIBLE and dest->acceptance_pickup & GoodsEntry::GES_ACCEPTANCE:
+ *  	packets are accepted here and may be unloaded and/or delivered (=destroyed);
+ *  	If not using cargodist: all packets are unloaded and delivered.
+ *  	If using cargodist: only packets which have this station as final destination are unloaded and delivered.
+ *  	If using cargodist: other packets may or may not be unloaded, depending on next_station.
+ *  	If GoodsEntry::GES_ACCEPTANCE is not set and using cargodist: packets may still be unloaded, but not delivered.
+ *  - OUFB_UNLOAD: unload all packets unconditionally;
+ *  	If OUF_UNLOAD_IF_POSSIBLE set and OUFB_TRANSFER not set: also deliver packets (no matter if using cargodist).
+ *  - OUFB_TRANSFER: don't deliver any packets;
+ *  	Overrides delivering aspect of OUFB_UNLOAD_IF_POSSIBLE.
+ * @param source       Vehicle cargo list to take the cargo from.
+ * @param max_unload   Maximum amount of cargo entities to move.
+ * @param flags        How to handle the moving (side effects).
+ * @param next         Next unloading station in the vehicle's order list.
+ * @param has_stopped  Vehicle has stopped at this station before, so don't update the flow stats for kept cargo.
+ * @param payment      Payment object to be updated when delivering/transferring.
+ * @return             Number of cargo entities actually moved.
+ */
+uint StationCargoList::TakeFrom(VehicleCargoList *source, uint max_unload, OrderUnloadFlags order_flags, StationID next, bool has_stopped, CargoPayment *payment)
+{
+	uint remaining_unload = max_unload;
+	uint unloaded;
+	byte flags = this->GetUnloadFlags(order_flags);
+	GoodsEntry *dest = &this->station->goods[this->cargo];
+	UnloadType action;
+
+	for (VehicleCargoList::Iterator c = source->packets.begin(); c != source->packets.end() && remaining_unload > 0;) {
+		StationID cargo_source = (*c)->source;
+		FlowStatSet &flows = dest->flows[cargo_source];
+		FlowStatSet::iterator begin = flows.begin();
+		StationID via = (begin != flows.end() ? begin->Via() : INVALID_STATION);
+		if (via != INVALID_STATION) {
+			/* Use cargodist unloading. */
+			action = this->WillUnloadCargoDist(flags, next, via, cargo_source);
+		} else {
+			/* There is no plan: use normal unloading. */
+			action = WillUnloadOld(flags, cargo_source);
+		}
+
+		switch(action) {
+			case UL_DELIVER:
+				unloaded = source->DeliverPacket(c, remaining_unload, payment);
+				if (via != INVALID_STATION) {
+					if (via == this->station->index) {
+						dest->UpdateFlowStats(flows, begin, unloaded);
+					} else {
+						dest->UpdateFlowStats(flows, unloaded, this->station->index);
+					}
+				}
+				remaining_unload -= unloaded;
+				break;
+			case UL_TRANSFER:
+				/* TransferPacket may split the packet and return the transferred part. */
+				if (via == this->station->index) {
+					via = (++begin != flows.end()) ? begin->Via() : INVALID_STATION;
+				}
+				unloaded = source->TransferPacket(c, remaining_unload, this, payment, via);
+				if (via != INVALID_STATION) {
+					dest->UpdateFlowStats(flows, begin, unloaded);
+				}
+				remaining_unload -= unloaded;
+				break;
+			case UL_KEEP:
+				unloaded = source->KeepPacket(c);
+				if (via != INVALID_STATION && next != INVALID_STATION && !has_stopped) {
+					if (via == next) {
+						dest->UpdateFlowStats(flows, begin, unloaded);
+					} else {
+						dest->UpdateFlowStats(flows, unloaded, next);
+					}
+				}
+				break;
+			default:
+				NOT_REACHED();
+		}
+	}
+	return max_unload - remaining_unload;
+}
+
+/**
+ * Additionally empty the reservation list for vehicle cargo lists.
+ */
+void VehicleCargoList::OnCleanPool()
+{
+	this->reserved.clear();
+	this->Parent::OnCleanPool();
+}
+
+/**
  * Update the cached values to reflect the removal of this packet.
  * Decreases count, feeder share and days_in_transit.
  * @param cp Packet to be removed from cache.
@@ -375,6 +645,22 @@
 }
 
 /**
+ * Moves the given amount of cargo to another vehicle (during autoreplace).
+ * @param dest The destination to move the cargo to.
+ * @param cap  The maximum amount of cargo entities to move.
+ * @return     The amount of cargo actually moved.
+ */
+uint VehicleCargoList::MoveTo(VehicleCargoList *dest, uint cap)
+{
+	uint orig_cap = cap;
+	Iterator it = packets.begin();
+	while (it != packets.end() && cap > 0) {
+		cap -= MovePacket(dest, it, cap);
+	}
+	return orig_cap - cap;
+}
+
+/**
  * Ages the all cargo in this list.
  */
 void VehicleCargoList::AgeCargo()
@@ -389,22 +675,184 @@
 	}
 }
 
-/** Invalidates the cached data and rebuild it. */
+/*
+ *
+ * Station cargo list implementation.
+ *
+ */
+
+/**
+ * Build unload flags from order flags and station acceptance.
+ * @param order_flags Order flags to check for forced transfer/deliver.
+ * @return            Some combination of UL_ACCEPTED, UL_DELIVER and UL_TRANSFER.
+ */
+FORCEINLINE byte StationCargoList::GetUnloadFlags(OrderUnloadFlags order_flags)
+{
+	byte flags = 0;
+	if (HasBit(this->station->goods[this->cargo].acceptance_pickup, GoodsEntry::GES_ACCEPTANCE)) {
+		flags |= UL_ACCEPTED;
+	}
+	if (order_flags & OUFB_UNLOAD) {
+		flags |= UL_DELIVER;
+	}
+	if (order_flags & OUFB_TRANSFER) {
+		flags |= UL_TRANSFER;
+	}
+	return flags;
+}
+
+/**
+ * Appends the given cargo packet to the range of packets with the same next station.
+ * @warning After appending this packet may not exist anymore!
+ * @note Do not use the cargo packet anymore after it has been appended to this CargoList!
+ * @param next Next hop.
+ * @param cp   Cargo packet to add.
+ * @pre        cp != NULL
+ */
+void StationCargoList::Append(StationID next, CargoPacket *cp)
+{
+	assert(cp != NULL);
+	this->AddToCache(cp);
+
+	StationCargoPacketMap::List &list = this->packets[next];
+
+	for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin()); it != list.rend(); it++) {
+		CargoPacket *icp = *it;
+		if (StationCargoList::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
+			icp->Merge(cp);
+			return;
+		}
+	}
+
+	/* The packet could not be merged with another one. */
+	list.push_back(cp);
+}
+
+/**
+ * Move packets from a specific range in this list to a vehicle.
+ * @param dest    Cargo list the packets will be moved to.
+ * @param cap     Maximum amount of cargo to move.
+ * @param begin   Begin of the range to take packets from.
+ * @param end     End of the range to take packets from.
+ * @param reserve Should the packets be loaded on/reserved for the vehicle.
+ * @return        Amount of cargo that has been moved.
+ */
+uint StationCargoList::MovePackets(VehicleCargoList *dest, uint cap, Iterator begin, Iterator end, bool reserve)
+{
+	uint orig_cap = cap;
+	while (begin != end && cap > 0) {
+		cap -= this->MovePacket(dest, begin, cap, this->station->xy, reserve);
+	}
+	return orig_cap - cap;
+}
+
+/**
+ * Move suitable packets from this list to a vehicle.
+ * @param dest    Vehicle cargo list to move packets to.
+ * @param cap     Maximum amount of cargo to be moved.
+ * @param next    Next station the vehicle will stop at.
+ * @param reserve Should the packets be loaded on/reserved for the vehicle.
+ * @return        Amount of cargo that has been moved.
+ */
+uint StationCargoList::MoveTo(VehicleCargoList *dest, uint cap, StationID next, bool reserve)
+{
+	uint orig_cap = cap;
+	std::pair<Iterator, Iterator> bounds(this->packets.equal_range(next));
+	cap -= this->MovePackets(dest, cap, bounds.first, bounds.second, reserve);
+	if (next != INVALID_STATION && cap > 0) {
+		bounds = this->packets.equal_range(INVALID_STATION);
+		cap -= this->MovePackets(dest, cap, bounds.first, bounds.second, reserve);
+	}
+	return orig_cap - cap;
+}
+
+/**
+ * Route all packets with station "to" as next hop to a different place.
+ * @param to station to exclude from routing.
+ */
+void StationCargoList::RerouteStalePackets(StationID to)
+{
+	std::pair<Iterator, Iterator> range(this->packets.equal_range(to));
+	for (Iterator it(range.first); it != range.second && it.GetKey() == to;) {
+		CargoPacket *packet = *it;
+		this->packets.erase(it++);
+		StationID next = this->station->goods[this->cargo].UpdateFlowStatsTransfer(packet->source, packet->count, this->station->index);
+		assert(next != to);
+
+		/* Legal, as insert doesn't invalidate iterators in the MultiMap, however
+		 * this might insert the packet between range.first and range.second (which might be end())
+		 * This is why we check for GetKey above to avoid infinite loops.
+		 */
+		this->packets.Insert(next, packet);
+	}
+}
+
+/**
+ * Truncate where each destination loses roughly the same percentage of its cargo.
+ * This is done by randomizing the selection of packets to be removed. Also count
+ * the cargo by origin station.
+ * @param max_remaining    Maximum amount of cargo to keep in the station.
+ * @param cargo_per_source Container for counting the cargo by origin list.
+ */
+void StationCargoList::CountAndTruncate(uint max_remaining, StationCargoAmountMap &cargo_per_source)
+{
+	uint prev_count = this->count;
+	uint loop = 0;
+	while (this->count > max_remaining) {
+		for (Iterator it(this->packets.begin()); it != this->packets.end();) {
+			CargoPacket *packet = *it;
+			if (loop == 0) cargo_per_source[packet->source] += packet->count;
+
+			if (RandomRange(prev_count) < max_remaining) {
+				++it;
+				continue;
+			}
+
+			uint diff = this->count - max_remaining;
+			if (packet->count > diff) {
+				packet->count -= diff;
+				this->count = max_remaining;
+				this->cargo_days_in_transit -= packet->days_in_transit * diff;
+				if (loop > 0) {
+					return;
+				} else {
+					++it;
+				}
+			} else {
+				this->packets.erase(it++);
+				this->RemoveFromCache(packet);
+				delete packet;
+			}
+		}
+		loop++;
+	}
+}
+
+/** Invalidates the cached data and rebuilds it. */
 void VehicleCargoList::InvalidateCache()
 {
 	this->feeder_share = 0;
+	this->reserved_count = 0;
 	this->Parent::InvalidateCache();
+	for (ConstIterator it(this->reserved.begin()); it != this->reserved.end(); it++) {
+		this->AddToCache(*it);
+		this->reserved_count += (*it)->count;
+	}
 }
 
-/*
- * We have to instantiate everything we want to be usable.
+/**
+ * Assign the cargo list to a goods entry.
+ * @param station The station the cargo list is asigned to
+ * @param cargo The cargo the list is asigned to.
  */
-template class CargoList<VehicleCargoList>;
-template class CargoList<StationCargoList>;
+void StationCargoList::AssignTo(Station *station, CargoID cargo)
+{
+	assert(this->station == NULL);
+	assert(station != NULL && cargo != INVALID_CARGO);
+	this->station = station;
+	this->cargo = cargo;
+}
 
-/** Autoreplace Vehicle -> Vehicle 'transfer'. */
-template bool CargoList<VehicleCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
-/** Cargo unloading at a station. */
-template bool CargoList<VehicleCargoList>::MoveTo(StationCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
-/** Cargo loading at a station. */
-template bool CargoList<StationCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
+/** We have to instantiate everything we want to be usable. */
+template class CargoList<VehicleCargoList, CargoPacketList>;
+template class CargoList<StationCargoList, StationCargoPacketMap>;
diff --git a/src/cargopacket.h b/src/cargopacket.h
--- a/src/cargopacket.h
+++ b/src/cargopacket.h
@@ -15,8 +15,11 @@
 #include "core/pool_type.hpp"
 #include "economy_type.h"
 #include "station_type.h"
+#include "order_type.h"
 #include "cargo_type.h"
+#include "cargotype.h"
 #include "vehicle_type.h"
+#include "core/multimap.hpp"
 #include <list>
 
 /** Unique identifier for a single cargo packet. */
@@ -28,7 +31,9 @@
 /** The actual pool with cargo packets. */
 extern CargoPacketPool _cargopacket_pool;
 
-template <class Tinst> class CargoList;
+template <class Tinst, class Tcont> class CargoList;
+class StationCargoList; // forward-declare, so we can use it in VehicleCargoList::Unreserve
+class VehicleCargoList; // forward-declare, so we can use it in CargoList::MovePacket
 extern const struct SaveLoad *GetCargoPacketDesc();
 
 /**
@@ -46,7 +51,7 @@
 	TileIndex loaded_at_xy;     ///< Location where this cargo has been loaded into the vehicle.
 
 	/** The CargoList caches, thus needs to know about it. */
-	template <class Tinst> friend class CargoList;
+	template <class Tinst, class Tcont> friend class CargoList;
 	friend class VehicleCargoList;
 	friend class StationCargoList;
 	/** We want this to be saved, right? */
@@ -140,7 +145,6 @@
 		return this->loaded_at_xy;
 	}
 
-
 	static void InvalidateAllFrom(SourceType src_type, SourceID src);
 	static void InvalidateAllFrom(StationID sid);
 	static void AfterLoad();
@@ -159,38 +163,46 @@
  */
 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
 
+/** Kind of actions that could be done with packets on unloading */
+enum UnloadType {
+	UL_KEEP     = 0,      ///< Keep cargo on vehicle.
+	UL_DELIVER  = 1 << 0, ///< Deliver cargo.
+	UL_TRANSFER = 1 << 1, ///< Transfer cargo.
+	UL_ACCEPTED = 1 << 2, ///< Cargo is accepted.
+};
+
 /**
  * Simple collection class for a list of cargo packets.
  * @tparam Tinst Actual instantation of this cargo list.
  */
-template <class Tinst>
+template <class Tinst, class Tcont>
 class CargoList {
 public:
-	/** Container with cargo packets. */
-	typedef std::list<CargoPacket *> List;
-	/** The iterator for our container. */
-	typedef List::iterator Iterator;
-	/** The const iterator for our container. */
-	typedef List::const_iterator ConstIterator;
-
-	/** Kind of actions that could be done with packets on move. */
-	enum MoveToAction {
-		MTA_FINAL_DELIVERY, ///< "Deliver" the packet to the final destination, i.e. destroy the packet.
-		MTA_CARGO_LOAD,     ///< Load the packet onto a vehicle, i.e. set the last loaded station ID.
-		MTA_TRANSFER,       ///< The cargo is moved as part of a transfer.
-		MTA_UNLOAD,         ///< The cargo is moved as part of a forced unload.
-	};
+	/** Iterator for our container. */
+	typedef typename Tcont::iterator Iterator;
+	/** Const iterator for our container. */
+	typedef typename Tcont::const_iterator ConstIterator;
+	/** Reverse iterator for our container. */
+	typedef typename Tcont::reverse_iterator ReverseIterator;
+	/** Const reverse iterator for our container. */
+	typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
 
 protected:
-	uint count;                 ///< Cache for the number of cargo entities.
+	uint count;					///< Cache for the number of cargo entities.
 	uint cargo_days_in_transit; ///< Cache for the sum of number of days in transit of each entity; comparable to man-hours.
 
-	List packets;               ///< The cargo packets in this list.
+	Tcont packets;				///< The cargo packets in this list.
 
 	void AddToCache(const CargoPacket *cp);
 
 	void RemoveFromCache(const CargoPacket *cp);
 
+	CargoPacket *RemovePacket(Iterator &it, uint cap, TileIndex load_place = INVALID_TILE);
+
+	uint MovePacket(StationCargoList *dest, StationID next, Iterator &it, uint cap);
+
+	uint MovePacket(VehicleCargoList *dest, Iterator &it, uint cap, TileIndex load_place = INVALID_TILE, bool reserved = false);
+
 public:
 	/** Create the cargo list. */
 	CargoList() {}
@@ -203,7 +215,7 @@
 	 * Returns a pointer to the cargo packet list (so you can iterate over it etc).
 	 * @return Pointer to the packet list.
 	 */
-	FORCEINLINE const List *Packets() const
+	FORCEINLINE const Tcont *Packets() const
 	{
 		return &this->packets;
 	}
@@ -227,15 +239,6 @@
 	}
 
 	/**
-	 * Returns source of the first cargo packet in this list.
-	 * @return The before mentioned source.
-	 */
-	FORCEINLINE StationID Source() const
-	{
-		return this->Empty() ? INVALID_STATION : this->packets.front()->source;
-	}
-
-	/**
 	 * Returns average number of days in transit for a cargo entity.
 	 * @return The before mentioned number.
 	 */
@@ -244,35 +247,46 @@
 		return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
 	}
 
-
-	void Append(CargoPacket *cp);
+	void Append(CargoPacket *cp, bool update_cache = true);
 	void Truncate(uint max_remaining);
 
-	template <class Tother_inst>
-	bool MoveTo(Tother_inst *dest, uint count, MoveToAction mta, CargoPayment *payment, uint data = 0);
-
 	void InvalidateCache();
 };
 
+typedef std::list<CargoPacket *> CargoPacketList;
+
 /**
  * CargoList that is used for vehicles.
  */
-class VehicleCargoList : public CargoList<VehicleCargoList> {
+class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
 protected:
+
+	uint TransferPacket(Iterator &c, uint remaining_unload, StationCargoList *dest, CargoPayment *payment, StationID next);
+	uint DeliverPacket(Iterator &c, uint remaining_unload, CargoPayment *payment);
+	uint KeepPacket(Iterator &c);
+
 	/** The (direct) parent of this class. */
-	typedef CargoList<VehicleCargoList> Parent;
+	typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
 
-	Money feeder_share; ///< Cache for the feeder share.
+	CargoPacketList reserved; ///< Packets reserved for unloading in this list.
+	Money feeder_share;       ///< Cache for the feeder share.
+	uint reserved_count;      ///< Cache for the number of reserved cargo entities.
 
 	void AddToCache(const CargoPacket *cp);
 	void RemoveFromCache(const CargoPacket *cp);
 
 public:
-	/** The super class ought to know what it's doing. */
-	friend class CargoList<VehicleCargoList>;
+	/** The station cargo list needs to control the unloading. */
+	friend class StationCargoList;
+	/** The super class ought to know what it's doing */
+	friend class CargoList<VehicleCargoList, CargoPacketList>;
 	/** The vehicles have a cargo list (and we want that saved). */
 	friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
 
+	~VehicleCargoList();
+
+	void OnCleanPool();
+
 	/**
 	 * Returns total sum of the feeder share for all packets.
 	 * @return The before mentioned number.
@@ -282,10 +296,68 @@
 		return this->feeder_share;
 	}
 
+	void Append(CargoPacket *cp, bool update_cache = true);
+
+	/**
+	 * Returns sum of cargo on board the vehicle (ie not only
+	 * reserved).
+	 * @return Cargo on board the vehicle.
+	 */
+	FORCEINLINE uint OnboardCount() const
+	{
+		return this->count - this->reserved_count;
+	}
+
+	/**
+	 * Returns sum of cargo reserved for the vehicle.
+	 * @return Cargo reserved for the vehicle.
+	 */
+	FORCEINLINE uint ReservedCount() const
+	{
+		return this->reserved_count;
+	}
+
+	/**
+	 * Returns a pointer to the reserved cargo list.
+	 * @return Pointer to the reserved list.
+	 */
+	FORCEINLINE const CargoPacketList *Reserved() const
+	{
+		return &this->reserved;
+	}
+
+	/**
+	 * Returns source of the first cargo packet in this list
+	 * If the regular packets list is empty but there are packets
+	 * in the reservation list it returns the source of the first
+	 * reserved packet.
+	 * @return The before mentioned source.
+	 */
+	FORCEINLINE StationID Source() const
+	{
+		if (this->Empty()) {
+			return INVALID_STATION;
+		} else if (this->packets.empty()) {
+			return this->reserved.front()->source;
+		} else {
+			return this->packets.front()->source;
+		}
+	}
+
+	void Reserve(CargoPacket *cp);
+
+	void Unreserve(StationID next, StationCargoList *dest);
+
+	uint LoadReserved(uint count);
+
+	void SwapReserved();
+
 	void AgeCargo();
 
 	void InvalidateCache();
 
+	uint MoveTo(VehicleCargoList *dest, uint cap);
+
 	/**
 	 * Are two the two CargoPackets mergeable in the context of
 	 * a list of CargoPackets for a Vehicle?
@@ -303,16 +375,21 @@
 	}
 };
 
+typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
+typedef std::map<StationID, uint> StationCargoAmountMap;
+
 /**
  * CargoList that is used for stations.
  */
-class StationCargoList : public CargoList<StationCargoList> {
+class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
 public:
 	/** The super class ought to know what it's doing. */
-	friend class CargoList<StationCargoList>;
+	friend class CargoList<StationCargoList, StationCargoPacketMap>;
 	/** The stations, via GoodsEntry, have a CargoList. */
 	friend const struct SaveLoad *GetGoodsDesc();
 
+	StationCargoList() : station(NULL), cargo(INVALID_CARGO) {}
+
 	/**
 	 * Are two the two CargoPackets mergeable in the context of
 	 * a list of CargoPackets for a Vehicle?
@@ -327,6 +404,40 @@
 				cp1->source_type     == cp2->source_type &&
 				cp1->source_id       == cp2->source_id;
 	}
+
+	uint TakeFrom(VehicleCargoList *source, uint max_unload, OrderUnloadFlags flags, StationID next_station, bool has_stopped, CargoPayment *payment);
+
+	uint MoveTo(VehicleCargoList *dest, uint cap, StationID next_station, bool reserve = false);
+
+	void Append(StationID next, CargoPacket *cp);
+
+	void RerouteStalePackets(StationID to);
+
+	void CountAndTruncate(uint max_remaining, StationCargoAmountMap &cargo_per_source);
+
+	/**
+	 * Returns source of the first cargo packet in this list
+	 * @return The before mentioned source
+	 */
+	FORCEINLINE StationID Source() const
+	{
+		return this->Empty() ? INVALID_STATION : this->packets.begin()->second.front()->source;
+	}
+
+	void AssignTo(Station *station, CargoID cargo);
+
+	static void InvalidateAllFrom(SourceType src_type, SourceID src);
+
+protected:
+	Station *station; ///< Station this cargo list belongs to.
+	CargoID cargo;    ///< Cargo type this list holds.
+
+	byte GetUnloadFlags(OrderUnloadFlags order_flags);
+
+	UnloadType WillUnloadOld(byte flags, StationID source);
+	UnloadType WillUnloadCargoDist(byte flags, StationID next_station, StationID via, StationID source);
+
+	uint MovePackets(VehicleCargoList *dest, uint cap, Iterator begin, Iterator end, bool reserve);
 };
 
 #endif /* CARGOPACKET_H */
diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp
--- a/src/cheat_gui.cpp
+++ b/src/cheat_gui.cpp
@@ -133,6 +133,7 @@
 /** Available cheats. */
 enum CheatNumbers {
 	CHT_MONEY,           ///< Change amount of money.
+	CHT_DAYLENGTH_INCOME,///< Do not devide income by daylength factor
 	CHT_CHANGE_COMPANY,  ///< Switch company.
 	CHT_EXTRA_DYNAMITE,  ///< Dynamite anything.
 	CHT_CROSSINGTUNNELS, ///< Allow tunnels to cross each other.
@@ -166,6 +167,7 @@
  */
 static const CheatEntry _cheats_ui[] = {
 	{SLE_INT32, STR_CHEAT_MONEY,           &_money_cheat_amount,                    &_cheats.money.been_used,            &ClickMoneyCheat         },
+	{SLE_BOOL,  STR_CHEAT_DAYLENGHT_INCOME,&_cheats.daylength_income.value,         &_cheats.daylength_income.been_used, NULL                     },
 	{SLE_UINT8, STR_CHEAT_CHANGE_COMPANY,  &_local_company,                         &_cheats.switch_company.been_used,   &ClickChangeCompanyCheat },
 	{SLE_BOOL,  STR_CHEAT_EXTRA_DYNAMITE,  &_cheats.magic_bulldozer.value,          &_cheats.magic_bulldozer.been_used,  NULL                     },
 	{SLE_BOOL,  STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value,         &_cheats.crossing_tunnels.been_used, NULL                     },
diff --git a/src/cheat_type.h b/src/cheat_type.h
--- a/src/cheat_type.h
+++ b/src/cheat_type.h
@@ -29,6 +29,7 @@
 	Cheat magic_bulldozer;  ///< dynamite industries, objects
 	Cheat switch_company;   ///< change to another company
 	Cheat money;            ///< get rich or poor
+	Cheat daylength_income; ///< do not devide vehicle income by the daylength factor
 	Cheat crossing_tunnels; ///< allow tunnels that cross each other
 	Cheat dummy1;           ///< empty cheat (build while in pause mode)
 	Cheat no_jetcrash;      ///< no jet will crash on small airports anymore
diff --git a/src/clear_func.h b/src/clear_func.h
--- a/src/clear_func.h
+++ b/src/clear_func.h
@@ -17,4 +17,7 @@
 void DrawHillyLandTile(const TileInfo *ti);
 void DrawClearLandTile(const TileInfo *ti, byte set);
 
+/* copy_paste_gui.cpp */
+void ClearCopyArrays(uint32 w, uint32 h);
+
 #endif /* CLEAR_FUNC_H */
diff --git a/src/command.cpp b/src/command.cpp
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -27,6 +27,8 @@
 #include "signal_func.h"
 #include "core/backup_type.hpp"
 #include "object_base.h"
+#include "window_func.h"
+#include "watch_gui.h"
 
 #include "table/strings.h"
 
@@ -171,8 +173,18 @@
 CommandProc CmdChangeTimetable;
 CommandProc CmdSetVehicleOnTime;
 CommandProc CmdAutofillTimetable;
+CommandProc CmdAutomateTimetable;
 CommandProc CmdSetTimetableStart;
 
+CommandProc CmdInsertSignalInstruction;
+CommandProc CmdModifySignalInstruction;
+CommandProc CmdRemoveSignalInstruction;
+
+CommandProc CmdSetSignalSpeedLimit;
+
+CommandProc CmdBuildTrafficLights;
+CommandProc CmdRemoveTrafficLights;
+
 #define DEF_CMD(proc, flags, type) {proc, #proc, flags, type}
 
 /**
@@ -304,7 +316,14 @@
 	DEF_CMD(CmdChangeTimetable,                                0, CMDT_ROUTE_MANAGEMENT      ), // CMD_CHANGE_TIMETABLE
 	DEF_CMD(CmdSetVehicleOnTime,                               0, CMDT_ROUTE_MANAGEMENT      ), // CMD_SET_VEHICLE_ON_TIME
 	DEF_CMD(CmdAutofillTimetable,                              0, CMDT_ROUTE_MANAGEMENT      ), // CMD_AUTOFILL_TIMETABLE
+	DEF_CMD(CmdAutomateTimetable,                              0, CMDT_ROUTE_MANAGEMENT      ), // CMD_AUTOMATE_TIMETABLE
 	DEF_CMD(CmdSetTimetableStart,                              0, CMDT_ROUTE_MANAGEMENT      ), // CMD_SET_TIMETABLE_START
+	DEF_CMD(CmdInsertSignalInstruction,                        0, CMDT_OTHER_MANAGEMENT      ), // CMD_INSERT_SIGNAL_INSTRUCTION
+	DEF_CMD(CmdModifySignalInstruction,                        0, CMDT_OTHER_MANAGEMENT      ), // CMD_MODIFY_SIGNAL_INSTRUCTION
+	DEF_CMD(CmdRemoveSignalInstruction,                        0, CMDT_OTHER_MANAGEMENT      ), // CMD_REMOVE_SIGNAL_INSTRUCTION
+	DEF_CMD(CmdSetSignalSpeedLimit,                            0, CMDT_OTHER_MANAGEMENT      ), // CMD_SET_SIGNAL_SPEED_LIMIT
+	DEF_CMD(CmdBuildTrafficLights,                             0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_TRAFFICLIGHTS
+	DEF_CMD(CmdRemoveTrafficLights,						       0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_REMOVE_TRAFFICLIGHTS
 };
 
 /*!
@@ -714,6 +733,16 @@
 		if (c != NULL) c->last_build_coordinate = tile;
 	}
 
+	/* Send Tile Number to Watching Company Windows */
+	int watching_window = 0;
+	WatchCompany *wc;
+	wc = dynamic_cast<WatchCompany*>(FindWindowById(WC_WATCH_COMPANY, watching_window));
+	while (wc!=NULL) {
+		wc->OnDoCommand( _current_company, tile );
+		watching_window++;
+		wc = dynamic_cast<WatchCompany*>(FindWindowById(WC_WATCH_COMPANY, watching_window));
+	}
+
 	SubtractMoneyFromCompany(res2);
 
 	/* update signals if needed */
diff --git a/src/command_queue.cpp b/src/command_queue.cpp
new file mode 100644
--- /dev/null
+++ b/src/command_queue.cpp
@@ -0,0 +1,77 @@
+/* $Id: command_queue.cpp 4998 2006-05-30 16:15:17Z Frostregen $ */
+
+#include "stdafx.h"
+#include "tile_type.h"
+#include "command_type.h"
+#include "command_func.h"
+#include "debug.h"
+#include "copy_paste.h"
+#include "command_queue.h"
+#include "settings_type.h"
+#include "gfx_func.h"
+#include "date_func.h"
+
+CopyPasteCommandQueue::~CopyPasteCommandQueue()
+{
+	this->ClearCopyPasteCommandQueue();
+}
+
+/** Enqueue the given command.
+ * May be executed later by calling ExecuteNextCommand()
+ */
+void CopyPasteCommandQueue::CopyPasteQueueCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
+{
+	CommandContainer *cc = new CommandContainer;
+	
+	cc->tile = tile;
+	cc->p1   = p1;
+	cc->p2   = p2;
+	cc->callback = callback;
+	cc->cmd  = cmd;
+	
+	/* add it to the queue */
+	this->queue.push(cc);
+}
+
+/** Executes the next queued command, or does nothing if queue is emtpy
+ * Since DoCommandP checks for _shift_pressed,
+ * we have to store, unset und restore it.
+ */
+void CopyPasteCommandQueue::ExecuteNextCommand()
+{
+	/* Check if queue is not empty */
+	if (!this->queue.empty()) {
+		/* backup and unset _shift_pressed */
+		bool temp_shift_pressed = _shift_pressed;
+		_shift_pressed = false;
+		/* Get the command and execute it */
+		DoCommandP(this->queue.front());
+		/* restore _shift_pressed */
+		_shift_pressed = temp_shift_pressed;
+		/* delete this commandcontainer */
+		{
+			CommandContainer *cc = this->queue.front();
+			this->queue.pop();
+			delete cc;
+		}
+	}
+}
+
+/** Clears the CopyPasteCommandQueue
+ */
+void CopyPasteCommandQueue::ClearCopyPasteCommandQueue()
+{
+	while (!this->queue.empty()) {
+		this->queue.pop();
+	}
+}
+
+void CallCopyPasteCommandQueueTick()
+{
+	/* Process the command_queue */
+	if (_settings_client.gui.cp_paste_speed < 255) {
+		if ((_tick_counter % _settings_client.gui.cp_paste_speed) == 0) {
+			_copy_paste_command_queue.ExecuteNextCommand();
+		}
+	}
+}
diff --git a/src/command_queue.h b/src/command_queue.h
new file mode 100644
--- /dev/null
+++ b/src/command_queue.h
@@ -0,0 +1,28 @@
+/* $Id: command_queue.h 4998 2006-05-30 16:13:41Z Frostregen $ */
+
+#ifndef COMMAND_QUEUE_H
+#define COMMAND_QUEUE_H
+
+#include "map_type.h"
+#include "command_type.h"
+#include "settings_type.h"
+#include <queue>
+
+class CopyPasteCommandQueue {
+private:
+	std::queue<CommandContainer *> queue;
+
+public:
+	~CopyPasteCommandQueue();
+
+	void ClearCopyPasteCommandQueue();        ///< Clears the CommandQueue
+
+	void CopyPasteQueueCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd); ///< Enqueue the given command.
+	void ExecuteNextCommand();       ///< Executes the next queued command, or does nothing if queue is emtpy
+};
+
+extern CopyPasteCommandQueue _copy_paste_command_queue;
+
+void CallCopyPasteCommandQueueTick();
+
+#endif /* COMMAND_QUEUE_H */
diff --git a/src/command_type.h b/src/command_type.h
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -291,8 +291,18 @@
 	CMD_CHANGE_TIMETABLE,             ///< change the timetable for a vehicle
 	CMD_SET_VEHICLE_ON_TIME,          ///< set the vehicle on time feature (timetable)
 	CMD_AUTOFILL_TIMETABLE,           ///< autofill the timetable
+	CMD_AUTOMATE_TIMETABLE,           ///< automate the timetable
 	CMD_SET_TIMETABLE_START,          ///< set the date that a timetable should start
 
+	CMD_INSERT_SIGNAL_INSTRUCTION,    ///< insert a signal instruction
+	CMD_MODIFY_SIGNAL_INSTRUCTION,    ///< modifies a signal instruction
+	CMD_REMOVE_SIGNAL_INSTRUCTION,    ///< removes a signal instruction
+
+	CMD_SET_SIGNAL_SPEED_LIMIT,       ///< sets the value of a speed-signal
+
+	CMD_BUILD_TRAFFICLIGHTS,          ///< place traffic lights on a road crossing
+	CMD_REMOVE_TRAFFICLIGHTS,         ///< remove traffic lights
+
 	CMD_END                           ///< Must ALWAYS be on the end of this list!! (period)
 };
 
diff --git a/src/company_base.h b/src/company_base.h
--- a/src/company_base.h
+++ b/src/company_base.h
@@ -146,6 +146,30 @@
 	static void PostDestructor(size_t index);
 };
 
+struct CompanyProfile {
+	char president_name[MAX_LENGTH_PRESIDENT_NAME_CHARS];
+	char company_name[MAX_LENGTH_COMPANY_NAME_CHARS];
+	CompanyManagerFace face;
+	Livery livery[LS_END];
+
+	StringID error_id;
+
+	CompanyProfile()
+	{
+		this->error_id = STR_NULL;
+	}
+
+	CompanyProfile(StringID err)
+	{
+		this->error_id = err;
+	}
+};
+
+CompanyProfile GetCompanyProfile (const Company&);
+StringID       SetCompanyProfile (const CompanyProfile&);
+StringID       CompanyLoadProfile(CompanyProfile&);
+StringID       CompanySaveProfile(const CompanyProfile&);
+
 #define FOR_ALL_COMPANIES_FROM(var, start) FOR_ALL_ITEMS_FROM(Company, company_index, var, start)
 #define FOR_ALL_COMPANIES(var) FOR_ALL_COMPANIES_FROM(var, 0)
 
diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp
--- a/src/company_cmd.cpp
+++ b/src/company_cmd.cpp
@@ -63,6 +63,7 @@
 
 	for (uint j = 0; j < 4; j++) this->share_owners[j] = COMPANY_SPECTATOR;
 	InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY);
+	InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
 }
 
 /** Destructor. */
@@ -82,6 +83,7 @@
 	InvalidateWindowData(WC_GRAPH_LEGEND, 0, (int)index);
 	InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, (int)index);
 	InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0);
+	InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
 	/* If the currently shown error message has this company in it, then close it. */
 	InvalidateWindowData(WC_ERRMSG, 0);
 }
@@ -141,7 +143,8 @@
  * @param cmf the fact to check
  * @return true if and only if the face is valid
  */
-static bool IsValidCompanyManagerFace(CompanyManagerFace cmf)
+//static bool IsValidCompanyManagerFace(CompanyManagerFace cmf) // r20689 TODO: check
+bool IsValidCompanyManagerFace(CompanyManagerFace cmf) // revert r20689 to be able to compile company_info patch
 {
 	if (!AreCompanyManagerFaceBitsValid(cmf, CMFV_GEN_ETHN, GE_WM)) return false;
 
@@ -212,14 +215,16 @@
 	if (HasBit(1 << EXPENSES_TRAIN_INC    |
 	           1 << EXPENSES_ROADVEH_INC  |
 	           1 << EXPENSES_AIRCRAFT_INC |
-	           1 << EXPENSES_SHIP_INC, cost.GetExpensesType())) {
+	           1 << EXPENSES_SHIP_INC     |
+			   1 << EXPENSES_SHARING_INC, cost.GetExpensesType())) {
 		c->cur_economy.income -= cost.GetCost();
 	} else if (HasBit(1 << EXPENSES_TRAIN_RUN    |
 	                  1 << EXPENSES_ROADVEH_RUN  |
 	                  1 << EXPENSES_AIRCRAFT_RUN |
 	                  1 << EXPENSES_SHIP_RUN     |
 	                  1 << EXPENSES_PROPERTY     |
-	                  1 << EXPENSES_LOAN_INT, cost.GetExpensesType())) {
+	                  1 << EXPENSES_LOAN_INT     |
+					  1 << EXPENSES_SHARING_COST, cost.GetExpensesType())) {
 		c->cur_economy.expenses -= cost.GetCost();
 	}
 
@@ -563,6 +568,8 @@
 
 	if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
 
+	if (!is_ai) UpdateAllTownVirtCoords();
+
 	return c;
 }
 
@@ -1084,6 +1091,7 @@
 		free(c->name);
 		c->name = reset ? NULL : strdup(text);
 		MarkWholeScreenDirty();
+		InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
 		CompanyAdminUpdate(c);
 	}
 
diff --git a/src/company_gui.cpp b/src/company_gui.cpp
--- a/src/company_gui.cpp
+++ b/src/company_gui.cpp
@@ -54,6 +54,8 @@
 	EXPENSES_AIRCRAFT_INC,
 	EXPENSES_SHIP_INC,
 	EXPENSES_LOAN_INT,
+	EXPENSES_SHARING_INC,
+	EXPENSES_SHARING_COST,
 	EXPENSES_OTHER,
 };
 
@@ -63,6 +65,7 @@
 	EXPENSES_ROADVEH_INC,
 	EXPENSES_AIRCRAFT_INC,
 	EXPENSES_SHIP_INC,
+	EXPENSES_SHARING_INC,
 	INVALID_EXPENSES,
 	EXPENSES_TRAIN_RUN,
 	EXPENSES_ROADVEH_RUN,
@@ -70,6 +73,7 @@
 	EXPENSES_SHIP_RUN,
 	EXPENSES_PROPERTY,
 	EXPENSES_LOAN_INT,
+	EXPENSES_SHARING_COST,
 	INVALID_EXPENSES,
 	EXPENSES_CONSTRUCTION,
 	EXPENSES_NEW_VEHICLES,
@@ -1633,6 +1637,9 @@
 	CW_WIDGET_SELECT_RELOCATE,    ///< View/hide the 'Relocate HQ' button.
 	CW_WIDGET_RELOCATE_HQ,
 
+	CW_WIDGET_PROFILE_LOAD,       ///< Load a company profile
+	CW_WIDGET_PROFILE_SAVE,       ///< Save a company profile
+
 	CW_WIDGET_HAS_PASSWORD,       ///< Draw a lock when the company has a password
 	CW_WIDGET_SELECT_MULTIPLAYER, ///< Multiplayer selection panel.
 	CW_WIDGET_COMPANY_PASSWORD,
@@ -1679,6 +1686,9 @@
 							NWidget(WWT_TEXTBTN, COLOUR_GREY, CW_WIDGET_RELOCATE_HQ), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS),
 							NWidget(NWID_SPACER), SetMinimalSize(90, 0),
 						EndContainer(),
+						/* Company Profile buttons */
+						NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, CW_WIDGET_PROFILE_LOAD), SetFill(1, 0), SetDataTip(STR_COMPANY_PROFILE_LOAD_BUTTON, STR_COMPANY_PROFILE_LOAD_TOOLTIP),
+						NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, CW_WIDGET_PROFILE_SAVE), SetFill(1, 0), SetDataTip(STR_COMPANY_PROFILE_SAVE_BUTTON, STR_COMPANY_PROFILE_SAVE_TOOLTIP),
 						NWidget(NWID_SPACER), SetFill(0, 1),
 					EndContainer(),
 				EndContainer(),
@@ -1812,6 +1822,10 @@
 		}
 
 		if (!local) {
+			/* Not the current player, so disable profile loading/saving */
+			this->SetWidgetDisabledState(CW_WIDGET_PROFILE_LOAD, true);
+			this->SetWidgetDisabledState(CW_WIDGET_PROFILE_SAVE, true);
+
 			if (_settings_game.economy.allow_shares) { // Shares are allowed
 				/* If all shares are owned by someone (none by nobody), disable buy button */
 				this->SetWidgetDisabledState(CW_WIDGET_BUY_SHARE, GetAmountOwnedBy(c, INVALID_OWNER) == 0 ||
@@ -2014,6 +2028,45 @@
 				this->SetWidgetDirty(CW_WIDGET_RELOCATE_HQ);
 				break;
 
+			case CW_WIDGET_PROFILE_LOAD:	// When load is clicked we want to perform most of the operations from above!
+			{
+				StringID       error_id;
+				CompanyProfile company_profile;
+
+				if ((byte)this->window_number != _local_company) return;
+
+				this->LowerWidget(CW_WIDGET_PROFILE_LOAD);
+				//this->SetWidgetDirty(CW_WIDGET_PROFILE_LOAD);
+
+				error_id = CompanyLoadProfile(company_profile);
+				if (error_id == STR_NULL) error_id = SetCompanyProfile(company_profile); // No error, so try setting the profile
+				
+				/* If either CompanyProfileLoad or SetCompanyProfile have an error, they will be handled here */
+				if (error_id != STR_NULL) ShowErrorMessage(error_id, error_id, WL_INFO); 
+
+				this->LowerWidget(CW_WIDGET_PROFILE_LOAD);
+				//this->SetWidgetDirty(CW_WIDGET_PROFILE_LOAD);
+				break;
+			}
+
+			case CW_WIDGET_PROFILE_SAVE: 
+			{
+				StringID       error_id;
+				CompanyProfile company_profile;
+
+				if ((byte)this->window_number != _local_company) return;
+
+				this->LowerWidget(CW_WIDGET_PROFILE_SAVE);
+
+				company_profile = GetCompanyProfile(*_company_pool.Get(_local_company));
+				error_id = CompanySaveProfile(company_profile);
+
+				if (error_id != STR_NULL) ShowErrorMessage(error_id, error_id, WL_INFO);	
+
+				this->LowerWidget(CW_WIDGET_PROFILE_SAVE);
+				break;
+			}
+
 			case CW_WIDGET_BUY_SHARE:
 				DoCommandP(0, this->window_number, 0, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS));
 				break;
diff --git a/src/company_manager_face.h b/src/company_manager_face.h
--- a/src/company_manager_face.h
+++ b/src/company_manager_face.h
@@ -237,6 +237,7 @@
 	return _cmf_info[cmfv].first_sprite[ge] + GB(cmf, _cmf_info[cmfv].offset, _cmf_info[cmfv].length);
 }
 
+bool IsValidCompanyManagerFace(CompanyManagerFace cmf); // revert r20689 to be able to compile company_info patch
 void DrawCompanyManagerFace(CompanyManagerFace face, int colour, int x, int y);
 
 #endif /* COMPANY_MANAGER_FACE_H */
diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -1166,6 +1166,79 @@
 	return true;
 }
 
+DEF_CONSOLE_CMD(ConStartAllAI)
+{
+	if (argc == 0 || argc > 2) {
+		IConsoleHelp("Start all AI. Usage: 'start_ai [<AI count>]'");
+		IConsoleHelp("Start all AI. If <AI count> is given, it starts AIs up to reach this count of running AIs.");
+		IConsoleHelp("Otherwise, the competitor setting is used.");
+		return true;
+	}
+
+	if (_game_mode != GM_NORMAL) {
+		IConsoleWarning("AIs can only be managed in a game.");
+		return true;
+	}
+
+	if (Company::GetNumItems() == CompanyPool::MAX_SIZE) {
+		IConsoleWarning("Can't start a new AI (no more free slots).");
+		return true;
+	}
+
+	if (_networking && !_network_server) {
+		IConsoleWarning("Only the server can start a new AI.");
+		return true;
+	}
+
+	if (_networking && !_settings_game.ai.ai_in_multiplayer) {
+		IConsoleWarning("AIs are not allowed in multiplayer by configuration.");
+		IConsoleWarning("Switch AI -> AI in multiplayer to True.");
+		return true;
+	}
+
+	if (!AI::CanStartNew()) {
+		IConsoleWarning("Can't start a new AI.");
+		return true;
+	}
+
+	int total_ai_count;
+	if (argc == 2) {
+		uint32 result;
+		if (GetArgumentInteger(&result, argv[1]) && result < CompanyPool::MAX_SIZE) {
+			total_ai_count = (int)result;
+		} else {
+			IConsolePrintF(CC_DEFAULT, "AI count must be an number between 1 and %d", CompanyPool::MAX_SIZE - 1);
+			IConsoleWarning("Invalid AI count");
+			return true;
+		}
+	} else {
+		total_ai_count = (int)_settings_game.difficulty.max_no_competitors;
+	}
+
+	/* Total AI to start is total_ai_count - current running AIs count */
+	int new_ai_count = total_ai_count;
+	Company *c;
+	FOR_ALL_COMPANIES(c) {
+		if (Company::IsValidAiID(c->index)) {
+			new_ai_count--;
+		}
+	}
+
+	if (new_ai_count < 0) {
+		IConsolePrintF(CC_DEFAULT, "Desired a total if %d AIs. Already %d running AIs.", total_ai_count, total_ai_count - new_ai_count);
+		IConsoleWarning("There is already more AIs running than you requested for.");
+		return true;
+	}
+
+	/* Start the desired AIs */
+	IConsolePrintF(CC_DEFAULT, "Desired a total if %d AIs. Already %d running AIs, starting %d new AIs.", total_ai_count, total_ai_count - new_ai_count, new_ai_count);
+	for (int i = 0; i < new_ai_count; i++) {
+		DoCommandP(0, 1 | INVALID_COMPANY << 16, 0, CMD_COMPANY_CTRL);
+	}
+
+	return true;
+}
+
 DEF_CONSOLE_CMD(ConReloadAI)
 {
 	if (argc != 2) {
@@ -1203,6 +1276,34 @@
 	return true;
 }
 
+DEF_CONSOLE_CMD(ConReloadAllAI)
+{
+	if (_game_mode != GM_NORMAL) {
+		IConsoleWarning("AIs can only be managed in a game.");
+		return true;
+	}
+
+	if (_networking && !_network_server) {
+		IConsoleWarning("Only the server can reload an AI.");
+		return true;
+	}
+
+	CompanyID company_id;
+	Company *c;
+	FOR_ALL_COMPANIES(c) {
+		company_id = c->index;
+		if (Company::IsValidID(company_id) && !Company::IsHumanID(company_id)) {
+			/* First kill the company of the AI, then start a new one. This should start the current AI again */
+			DoCommandP(0, 2 | company_id << 16, 0, CMD_COMPANY_CTRL);
+			DoCommandP(0, 1 | company_id << 16, 0, CMD_COMPANY_CTRL);
+		}
+	}
+
+	IConsolePrint(CC_DEFAULT, "All AIs reloaded.");
+
+	return true;
+}
+
 DEF_CONSOLE_CMD(ConStopAI)
 {
 	if (argc != 2) {
@@ -1239,6 +1340,33 @@
 	return true;
 }
 
+DEF_CONSOLE_CMD(ConStopAllAI)
+{
+	if (_game_mode != GM_NORMAL) {
+		IConsoleWarning("AIs can only be managed in a game.");
+		return true;
+	}
+
+	if (_networking && !_network_server) {
+		IConsoleWarning("Only the server can stop an AI.");
+		return true;
+	}
+
+	CompanyID company_id;
+	Company *c;
+	FOR_ALL_COMPANIES(c) {
+		company_id = c->index;
+		if (Company::IsValidID(company_id) && !Company::IsHumanID(company_id)) {
+			/* Now kill the company of the AI. */
+			DoCommandP(0, 2 | company_id << 16, 0, CMD_COMPANY_CTRL);
+			IConsolePrintF(CC_DEFAULT, "AI stopped, company %d deleted.", company_id);
+		}
+
+	}
+
+	return true;
+}
+
 DEF_CONSOLE_CMD(ConRescanAI)
 {
 	if (argc == 0) {
@@ -1896,11 +2024,14 @@
 
 #ifdef ENABLE_AI
 	IConsoleCmdRegister("list_ai_libs", ConListAILibs);
-	IConsoleCmdRegister("list_ai",      ConListAI);
-	IConsoleCmdRegister("reload_ai",    ConReloadAI);
-	IConsoleCmdRegister("rescan_ai",    ConRescanAI);
-	IConsoleCmdRegister("start_ai",     ConStartAI);
-	IConsoleCmdRegister("stop_ai",      ConStopAI);
+	IConsoleCmdRegister("list_ai",       ConListAI);
+	IConsoleCmdRegister("reload_ai",     ConReloadAI);
+	IConsoleCmdRegister("reload_all_ai", ConReloadAllAI);
+	IConsoleCmdRegister("rescan_ai",     ConRescanAI);
+	IConsoleCmdRegister("start_ai",      ConStartAI);
+	IConsoleCmdRegister("start_all_ai",  ConStartAllAI);
+	IConsoleCmdRegister("stop_ai",       ConStopAI);
+	IConsoleCmdRegister("stop_all_ai",   ConStopAllAI);
 #endif /* ENABLE_AI */
 
 	/* networking functions */
diff --git a/src/copy_paste.cpp b/src/copy_paste.cpp
new file mode 100644
--- /dev/null
+++ b/src/copy_paste.cpp
@@ -0,0 +1,1759 @@
+/* $Id: copy_paste.cpp 5998 2006-05-28 07:45:14Z Frostregen $ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "table/sprites.h"
+#include "strings_type.h"
+#include "table/strings.h"
+#include "clear_func.h"
+#include "company_func.h"
+#include "tile_type.h"
+#include "window_type.h"
+#include "gui.h"
+#include "rail_map.h"
+#include "rail_gui.h"
+#include "gfx_func.h"
+#include "settings_type.h"
+#include "sound_type.h"
+#include "sound_func.h"
+#include "command_type.h"
+#include "command_func.h"
+#include "tunnel_map.h"
+#include "bridge_map.h"
+#include "tunnelbridge_map.h"
+#include "tunnelbridge.h"
+#include "waypoint_base.h"
+#include "debug.h"
+#include "depot_map.h"
+#include "saveload/saveload.h"
+#include "window_func.h"
+#include "strings_func.h"
+#include "slope_type.h"
+#include "network/network.h"
+#include "command_queue.h"
+#include "copy_paste.h"
+#include "core/alloc_func.hpp"
+#include "core/endian_func.hpp"
+
+/* Total Space used = 8 * COPY_MAX = ?kb */
+CopyPaste _copy_paste = CopyPaste();
+
+/* Major version for saved templates */
+extern const uint32 COPYPASTE_VERSION = 1;
+
+CopyPasteCommandQueue _copy_paste_command_queue = CopyPasteCommandQueue();
+
+StringID error_message;		///< error string, used by save/load
+StringID error_extra;		///< extra error message (or NULL)
+
+CopyPaste::CopyPaste()
+{
+	m_width     = 0;
+	m_height    = 0;
+	
+	m_copy_with_rail          = true;
+	m_copy_with_road          = true;
+	m_copy_with_other         = false;
+	m_paste_vacant_terrain    = 1;
+	m_convert_rail            = true;
+	m_clear_before_build      = true;
+	m_toggle_signal_direction = false;
+}
+
+void CopyPaste::AllocateMapArray(uint32 max_tiles)
+{
+	this->ClearCopyArrays();
+	m_heightmap      = CallocT< int8>(max_tiles);
+	m_terrain_needed = CallocT<uint8>(max_tiles);
+	m_tiletype       = CallocT<uint8>(max_tiles);
+	m_railroad       = CallocT<uint8>(max_tiles);
+	m_signals        = CallocT<uint16>(max_tiles);
+}
+
+CopyPaste::~CopyPaste()
+{
+	this->ClearCopyArrays();
+}
+
+/** Returns if something is currently copied 
+ */
+bool CopyPaste::IsSomethingCopied()
+{
+	return !((GetWidth() == 0) || (GetHeight() == 0));
+}
+
+/** Clears the Arrays which store the copied area.
+ */
+void CopyPaste::ClearCopyArrays()
+{
+	free(m_heightmap);
+	free(m_terrain_needed);
+	free(m_tiletype);
+	free(m_railroad);
+	free(m_signals);
+	m_width = 0;
+	m_height = 0;
+}
+
+
+/**
+ * SaveLoad function for templates
+ * TODO: Compression
+ * TODO: Better error handling (use goto for block error handling)
+ **/
+SaveOrLoadResult CopyPaste::SaveLoadTemplate(const char *filename, int mode)
+{
+	FILE* fh;
+	uint32 hdr[4];
+	uint32 tlen = GetWidth() * GetHeight();
+	uint32 blen = (GetWidth() - 1) * (GetHeight() - 1);
+	uint32 index;
+	uint16 tmp16;
+	uint16* ptmp16;
+	ptmp16 = &tmp16;
+	
+	uint32 version;
+
+	fh = (mode == SL_SAVE) ? fopen(filename, "wb") : fopen(filename, "rb");
+
+	switch(mode) {
+		case SL_SAVE:
+			hdr[0] = TO_BE32X('TMPL');
+			/* For now we only have a major version, but may use minor in future? */
+			hdr[1] = TO_BE32(COPYPASTE_VERSION);
+			hdr[2] = TO_BE32(GetWidth());
+			hdr[3] = TO_BE32(GetHeight());
+
+			if (fwrite(hdr, sizeof(hdr), 1, fh) != 1) {
+				fclose(fh);
+				SetError(STR_TEMPLATE_SAVE_FAILED, STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
+				return SL_ERROR;
+			}
+
+			if (fwrite(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto save_error;
+			if (fwrite(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto save_error;
+			if (fwrite(m_tiletype, sizeof(uint8), blen, fh) != blen) goto save_error;
+			if (fwrite(m_railroad, sizeof(uint8), blen, fh) != blen) goto save_error;
+
+			for (index = 0; index < blen; index++)
+			{
+				tmp16 = TO_BE16(m_signals[index]);
+				if (fwrite(ptmp16, sizeof(uint16), 1, fh) != 1) goto save_error;
+			}
+
+			break;
+
+		case SL_LOAD:
+			if (fread(hdr, sizeof(hdr), 1, fh) != 1) goto load_error;
+			if (FROM_BE32(hdr[0]) != 'TMPL') {
+				SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN);
+				return SL_ERROR;
+			}
+
+			version = FROM_BE32(hdr[1]);
+			DEBUG(sl, 1, "Loading template with version %d", version);
+
+			/* Check whether we can load this template */
+			if (version > COPYPASTE_VERSION) {
+				DEBUG(sl, 1, "Can't load template with version %d, too new!", version);
+				SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW);
+				return SL_ERROR;
+			}
+	DEBUG(sl, 1, "Getting bounds");
+
+			{
+				uint32 width = FROM_BE32(hdr[2]);
+				uint32 height = FROM_BE32(hdr[3]);
+				AllocateMapArray(width * height);
+				SetWidth(width);
+				SetHeight(height);
+			}
+
+			tlen = GetWidth() * GetHeight();
+			blen = (GetWidth() - 1) * (GetHeight() - 1);
+
+	DEBUG(sl, 1, "Allocated arrays, loading from file");
+
+			if (fread(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto load_error;
+			if (fread(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto load_error;
+			if (fread(m_tiletype, sizeof(uint8), blen, fh) != blen) goto load_error;
+			if (fread(m_railroad, sizeof(uint8), blen, fh) != blen) goto load_error;
+	DEBUG(sl, 1, "Reading signals");
+
+			for (index = 0; index < blen; index++) {
+				if (fread(ptmp16, sizeof(uint16), 1, fh) != 1) goto load_error;
+				m_signals[index] = FROM_BE16(tmp16);
+			}
+			SetWindowDirty(WC_COPY_PASTE, 0);
+			break;
+
+		default:
+			/* Not reached */
+			break;
+	}
+
+	fclose(fh);
+
+	return SL_OK;
+
+save_error:
+	SetError(STR_TEMPLATE_SAVE_FAILED);
+	fclose(fh);
+	return SL_ERROR;
+
+load_error:
+	SetError(STR_TEMPLATE_LOAD_FAILED);
+	fclose(fh);
+	return SL_ERROR;
+}
+
+/** Set the error string & an extra message */
+void CopyPaste::SetError(StringID message, StringID extra)
+{
+	error_message = message;
+	error_extra = extra;
+}
+
+/** Get the string representation of the error message */
+const char* CopyPaste::GetErrorString()
+{
+	//SetDParam(0, error_message);
+	SetDParam(0, error_extra);
+
+	static char str[512];
+	GetString(str, error_message, lastof(str));
+	return str;
+}
+
+/** DoCommand for Copy&Paste.
+ * If shift is pressed, a cost-estimate is displayed instead of executing the paste.
+ * 
+ * If we are in multiplayer the pasting is redirected to the command-queue,
+ * which delays execution, to prevent overflowing the network connection.
+ */
+void CopyPaste::CP_DoCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
+{
+	if (_shift_pressed) {
+		CommandCost res = DoCommand(tile, p1, p2, DC_QUERY_COST, cmd & 0xFF, "");
+		if (!res.Failed())
+			m_costs.AddCost(res);
+	}
+	else {
+#ifdef ENABLE_NETWORK
+		if (_networking) {
+			_copy_paste_command_queue.CopyPasteQueueCommand(tile, p1, p2, callback, cmd);
+		}
+		else
+#endif /* ENABLE_NETWORK */
+			DoCommandP(tile, p1, p2, cmd, callback);
+	}
+}
+
+/* *** Copy&Paste Helper functions. Mainly the same as the originals. Just without sound *** */
+
+/**
+ * @param tile The Tile to operate on 
+ * @param mode true means Raise, false means Lower
+ */
+void CopyPaste::CP_RaiseLowerLand(TileIndex tile, int mode)
+{
+	CP_DoCommand(tile, 8, (uint32)mode, NULL, CMD_TERRAFORM_LAND | CMD_MSG(mode ? STR_ERROR_CAN_T_RAISE_LAND_HERE : STR_ERROR_CAN_T_LOWER_LAND_HERE));
+}
+
+void CopyPaste::CP_PlaceRail(TileIndex tile, int cmd, uint32 railtype)
+{
+	CP_DoCommand(tile, railtype, cmd, NULL,
+		CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)
+	);
+}
+
+void CopyPaste::CP_PlaceSignals(TileIndex tile, Track track, SignalType type, uint direction, bool semaphore)
+{
+	if (IsPbsSignal(type) && direction > 0) direction--;
+	CP_DoCommand(tile, track | (semaphore ? 1 : 0) << 4 | type << 5 | direction << 15, 0, NULL,
+			CMD_BUILD_SIGNALS | CMD_MSG(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE));
+}
+
+void CopyPaste::CP_PlaceRoad(TileIndex tile, uint8 road_bits)
+{
+	CP_DoCommand(tile, road_bits, 0, NULL, CMD_BUILD_ROAD | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
+}
+
+void CopyPaste::CP_PlaceRoadStop(TileIndex tile, uint8 direction, uint8 roadtype, bool truck_stop, bool drive_through)
+{
+	CP_DoCommand(tile, direction, truck_stop | drive_through << 1 | roadtype << 2 | INVALID_STATION << 16, NULL, CMD_BUILD_ROAD_STOP | CMD_MSG(truck_stop ? STR_ERROR_CAN_T_BUILD_TRUCK_STATION : STR_ERROR_CAN_T_BUILD_BUS_STATION));
+}
+
+void CopyPaste::CP_PlaceRail_Tunnel(TileIndex tile, uint32 railtype)
+{
+	CP_DoCommand(tile, railtype, 0, NULL,
+		CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
+}
+
+void CopyPaste::CP_PlaceRoad_Tunnel(TileIndex tile, uint8 roadtype)
+{
+	CP_DoCommand(tile, 0x200 | roadtype, 0, NULL, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
+}
+
+void CopyPaste::CP_Build_Bridge(TileIndex start, TileIndex end, uint8 bridgetype, uint8 transport_type, uint8 rail_road_type)
+{
+	CP_DoCommand(end, start,
+		bridgetype | (rail_road_type << 8) | (transport_type << 15), NULL,
+		CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE));
+}
+
+void CopyPaste::CP_PlaceRail_Depot(TileIndex tile, uint8 railtype, uint8 direction)
+{
+	CP_DoCommand(tile, railtype, direction, NULL,
+		CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT));
+}
+
+void CopyPaste::CP_PlaceRoad_Depot(TileIndex tile, uint8 direction_type)
+{
+	CP_DoCommand(tile, direction_type, 0, NULL,
+		CMD_BUILD_ROAD_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
+}
+
+void CopyPaste::CP_PlaceWaypoint(TileIndex tile, uint8 waypoint_type)
+{
+	CP_DoCommand(tile, waypoint_type, 0, NULL, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT));
+}
+
+void CopyPaste::CP_ClearTile(TileIndex start_tile, TileIndex end_tile)
+{
+	CP_DoCommand(start_tile, end_tile, 0, NULL, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA));
+}
+
+uint8 CopyPaste::MirrorSignalDirection(uint8 direction)
+{
+	if (direction == 0) return direction;
+	return (direction == 1 ? 2 : 1);
+}
+
+DisallowedRoadDirections CopyPaste::MirrorOneWayRoadDirection(DisallowedRoadDirections drd)
+{
+	if (drd == DRD_NONE || drd == DRD_BOTH) return drd;
+	return drd == DRD_SOUTHBOUND ? DRD_NORTHBOUND : DRD_SOUTHBOUND;
+}
+
+void CopyPaste::SwapSignalInfo(uint index)
+{
+	uint16 signal = m_signals[index];
+	/* Clear bit 2-16 */
+	for (uint i = 2; i < 16; i++)
+		ClrBit(m_signals[index], i);
+	/* Set bit 2 to former 3 */
+	SB(m_signals[index], 2, 1, GB(signal, 3, 1));
+	/* Set bit 3 to former 2 */
+	SB(m_signals[index], 3, 1, GB(signal, 2, 1));
+	/* Set bit 6+7 to former 8+9 */
+	SB(m_signals[index], 6, 2, MirrorSignalDirection(GB(signal, 8, 2)));
+	/* Set bit 8+9 to former 6+7 */
+	SB(m_signals[index], 8, 2, MirrorSignalDirection(GB(signal, 6, 2)));
+	/* Exchange signal types too */
+	/* Set bit 10-12 to former 13-15 */
+	SB(m_signals[index], 10, 3, GB(signal, 13, 3));
+	/* Set bit 13-15 to former 10-12 */
+	SB(m_signals[index], 13, 3, GB(signal, 10, 3));
+}
+
+/** This function pastes landscape */
+void CopyPaste::PasteLandscape(TileIndex tile)
+{
+	TileIndex sx = TileX(tile);
+	TileIndex sy = TileY(tile);
+	uint size_x = GetWidth();
+	uint size_y = GetHeight();
+	int8 count, h_diff;
+	uint h_tile;
+
+	TileIndex index;
+	/* Base height level is from upper right tile. */
+	uint baseh = TileHeight(tile);
+	/* Bulldoze tiles which will be built on */
+	if (m_clear_before_build) {
+		index = 0;
+		TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
+
+			if (GetCPTileType(index) != CP_TILE_CLEAR) {
+				CP_ClearTile(tile, tile);
+			}
+			index++;
+
+		}
+	}
+
+	/* Check if we want to restore any terrain at all */
+	if (m_paste_vacant_terrain > 0) {
+		/* Restore terrain 
+		 * Please look into "CopyArea" for details on which bit is used for which information
+		 */
+		index = 0;
+		TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
+
+			if (HasBit(m_terrain_needed[index], 0) || (m_paste_vacant_terrain == 2)) {
+
+				/* Do special heightlevel calculations if we are networking,
+				 * since we cannot measure the heightlevel if we delay the execution.
+				 * Lowering/Raising land affects neighbour tiles too...
+				 * Else we just use the current tileheight we get from the map.
+				 */
+#ifdef ENABLE_NETWORK
+				if (_networking) {
+					h_tile = TileHeight(tile);
+					if ((cur_h != size_y) && (cur_w != size_x)) {
+						/* Look NE and NW */
+						h_tile = ClampToRight(index, baseh, h_tile);
+						h_tile = ClampToUp(index, baseh, h_tile, size_x);
+						/* use clamped height instead of actual height */
+						h_diff = GetHeight(baseh, index) - h_tile;
+					}
+					else {
+						if ((cur_h == size_y) && (cur_w == size_x)) {
+							/* First Tile is always at baseh */
+							h_diff = GetHeight(baseh, index) - TileHeight(tile);
+						}
+						else if (cur_w == size_x) {
+							/* Right Border, clamp to upper tile only */
+							h_tile = ClampToUp(index, baseh, h_tile, size_x);
+							h_diff = GetHeight(baseh, index) - h_tile;
+						}
+						else {
+							/* Upper Border, clamp to right tile only */
+							h_tile = ClampToRight(index, baseh, h_tile);
+							h_diff = GetHeight(baseh, index) - h_tile;
+						}
+					}
+				}
+				else
+#endif /* ENABLE_NETWORK */
+					h_diff = GetHeight(baseh, index) - TileHeight(tile);
+
+				/* Now raise/lower the tile according to our calculations */
+				if (h_diff > 0)	{
+					for (count = 0; count < h_diff; count++)
+						CP_RaiseLowerLand(tile, 1);
+				}
+				else if (h_diff < 0) {
+					for (count = h_diff; count < 0; count++)
+						CP_RaiseLowerLand(tile, 0);
+				}
+			}
+			index++;
+
+		}
+	}
+
+}
+
+/** This function pastes signals for a given index */
+void CopyPaste::PasteSignals(uint index, TileIndex tile)
+{
+	uint16 signal = m_signals[index];
+	if (m_toggle_signal_direction) {
+		SB(signal, 6, 2, MirrorSignalDirection(GB(signal, 6, 2)));
+		SB(signal, 8, 2, MirrorSignalDirection(GB(signal, 8, 2)));
+	}
+	bool firstrun = true;
+	for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
+		if (m_railroad[index] & TrackToTrackBits(t)) {
+			if (((IsDiagonalTrack(t) || t == TRACK_LEFT || t == TRACK_UPPER) &&
+				HasBit(signal, 0)) ||
+				((t == TRACK_RIGHT || t == TRACK_LOWER) && HasBit(signal, 1))) {
+				CP_PlaceSignals(tile, t, 
+					(SignalType)GB(signal, firstrun ? 10 : 13, 3),
+					GB(signal, firstrun ? 6 : 8, 2),
+					HasBit(signal, firstrun ? 2 : 3));
+					firstrun = false;
+			}
+		}
+	}
+}
+
+/** This function calculates the height,
+ * the given tile will have, after the neighbour(right) tile is restored.
+ * In OTTD adjacent tiles may only differ in height by 1 level.
+ */
+int8 CopyPaste::ClampToRight(TileIndex index, int8 baseh, int8 h_tile)
+{
+	int8 h_right = GetHeight(baseh, index - 1);
+
+	if (h_tile > (h_right + 1)) {
+		h_tile = h_right + 1;
+	}
+	else if (h_tile < (h_right - 1)) {
+		h_tile = h_right - 1;
+	}
+
+	return h_tile;
+}
+
+/** This function calculates the height,
+ * the given tile will have, after the neighbour(upper) tile is restored.
+ * In OTTD adjacent tiles may only differ in height by 1 level.
+ */
+int8 CopyPaste::ClampToUp(TileIndex index, int8 baseh, int8 h_tile, int32 size_x)
+{
+	int8 h_up = GetHeight(baseh, index - size_x);
+
+	if (h_tile > (h_up + 1)) {
+		h_tile = h_up + 1;
+	}
+	else if (h_tile < (h_up - 1)) {
+		h_tile = h_up - 1;
+	}
+
+	return h_tile;
+}
+
+/** Game command which pastes the copied content.
+ * The result depends on setting some variables:
+ * m_paste_vacant_terrain, m_convert_rail, m_clear_before_build and m_toggle_signal_direction
+ * @param tile upper right corner to paste to
+ */
+void CopyPaste::internal_PasteArea(TileIndex tile)
+{
+	int8 baseh;
+	TileIndex index = 0;
+	int32 size_x, size_y;
+	bool success = true;
+	TileIndex sx = TileX(tile);
+	TileIndex sy = TileY(tile);
+	TileIndex ex = sx + GetWidth();
+	TileIndex ey = sy + GetHeight();
+
+	/* Reset paste costs */
+	if (_shift_pressed) {
+		m_costs.MultiplyCost(0);
+	}
+
+	/* Nothing copied? exit... */
+	if (! IsSomethingCopied()) return;
+	
+	/* Paste out of map? exit... */
+	if ((ex >= MapSizeX()) || (ey >= MapSizeY())) return;
+
+	size_x = GetWidth();
+	size_y = GetHeight();
+
+	/* Base height level is from upper right tile. */
+	baseh = (int8)TileHeight(tile);
+	
+	/* Restore the landscape */
+	PasteLandscape(tile);
+	
+	/* Paste Rail, Depot, Tunnel, Road, Bridge: 
+	 * Please look into "CopyArea" for details on which bit is used for which information
+	 */
+	index = 0;
+	TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
+	
+		uint minortt = GetCPMinorTileType(index);
+
+		switch(GetCPTileType(index)) {
+			case CP_TILE_RAIL: {
+				uint rt = GB(m_railroad[index], 6, 2); //railtype
+				switch (minortt) {
+					case RAIL_TILE_NORMAL:
+					case RAIL_TILE_SIGNALS:
+//					case RAIL_TILE_WAYPOINT:
+						for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
+							if (m_railroad[index] & TrackToTrackBits(t)) CP_PlaceRail(tile, t, m_convert_rail ? (uint)_cur_railtype : rt);
+						}
+						break;
+
+					case RAIL_TILE_DEPOT:
+						CP_PlaceRail_Depot(tile, m_convert_rail ? (uint)_cur_railtype : rt, GB(m_railroad[index], 0, 2));
+						break;
+				}
+			} break;
+			case CP_TILE_ROAD: {
+				switch(minortt) {
+					case ROAD_TILE_CROSSING:
+						CP_PlaceRail(tile, GB(m_railroad[index], 0, 4) == ROAD_X ? TRACK_Y : TRACK_X, m_convert_rail ? (uint)_cur_railtype : GB(m_signals[index], 4, 2));
+					/* fallthrough */
+					case ROAD_TILE_NORMAL:
+						if (GB(m_railroad[index], 0, 4) > 0) CP_PlaceRoad(tile, GB(m_railroad[index], 0, 4) | (ROADTYPE_ROAD << 4) | (minortt == ROAD_TILE_NORMAL ? (GB(m_signals[index], 0, 2) << 6) : 0));
+						if (GB(m_railroad[index], 4, 4) > 0) CP_PlaceRoad(tile, GB(m_railroad[index], 4, 4) | (ROADTYPE_TRAM << 4));
+						break;
+					case ROAD_TILE_DEPOT:
+						CP_PlaceRoad_Depot(tile, GB(m_railroad[index], 0, 2) | HasBit(m_railroad[index], 2) << 2);
+						break;
+				}
+			} break;
+			case CP_TILE_STATION: 
+				switch(minortt) {
+					case CP_TILE_ROAD:
+						CP_PlaceRoadStop(tile, GB(m_railroad[index], 0, 2), GB(m_railroad[index], 6, 2), HasBit(m_railroad[index], 2), HasBit(m_railroad[index], 3));
+				}
+
+
+			case CP_TILE_TUNNELBRIDGE:
+				if (HasBit(minortt, 0)) {
+					/* Tunnels: 
+					* TODO: check if tunnel end will be at right place (=inside area)
+					* Same check as bridge? move into tunneldir, until tunneltile reached
+					*/
+					if (HasBit(m_railroad[index], 4)) {
+						if (GB(m_railroad[index], 2, 2) == TRANSPORT_ROAD) {
+							CP_PlaceRoad_Tunnel(tile, GB(m_railroad[index], 6, 2));
+						} else {
+							CP_PlaceRail_Tunnel(tile, m_convert_rail ? (uint) _cur_railtype : GB(m_railroad[index], 6, 2));
+						}
+					}
+				} else if (HasBit(m_railroad[index], 4)) {
+					/* Bridges: */
+					/* If we get here, there is a bridge start here. Now find the bridge end 
+					 * TODO Shorten code by setting up variables inside switch statement, and use them inside one loop at the end
+					 */
+					bool bridge_error = false;
+					TileIndex tmp_tile = tile;
+					uint rdd = ReverseDiagDir((DiagDirection)GB(m_railroad[index], 0, 2));
+					bool found = false;
+					TileIndex i;
+					switch (GB(m_railroad[index], 0, 2)) {
+						case DIAGDIR_NE:
+							/* -X */
+							i = 1;
+							while ((TileX(tile) - i) >= sx) {
+								if (GetCPTileType(index - i) == CP_TILE_TUNNELBRIDGE && 
+									!HasBit(GetCPMinorTileType(index - i), 0) &&
+									!HasBit(m_railroad[index - i], 4) &&
+									GB(m_railroad[index - i], 0, 2) == rdd) {
+									found = true;
+									break;
+								}
+								i++;
+							}
+							if ((TileX(tile) - i) < sx || !found)
+								bridge_error = true;
+							else
+								tmp_tile += TileDiffXY(0 - i, 0);
+							break;
+						case DIAGDIR_SW:
+							/* +X */
+							i = 1;
+							while ((TileX(tile) + i) < (sx + size_x - 1)) {
+								if (GetCPTileType(index + i) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index + i), 0) && !HasBit(m_railroad[index + i], 4) && GB(m_railroad[index + i], 0, 2) == rdd) {
+									found = true;
+									break;
+								}
+								i++;
+							}
+							if ((TileX(tile) + i) >= (sx + size_x - 1) || !found)
+								bridge_error = true;
+							else
+								tmp_tile += TileDiffXY(+i, 0);
+							break;
+						case DIAGDIR_SE:
+							/* +Y */
+							i = 1;
+							while ((TileY(tile) + i) < (sy + size_y - 1)) {
+								if (GetCPTileType(index + (i * (size_x - 1))) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index + (i * (size_x - 1))), 0) && !HasBit(m_railroad[index + (i * (size_x - 1))], 4) && GB(m_railroad[index + (i * (size_x - 1))], 0, 2) == rdd) {
+									found = true;
+									break;
+								}
+								i++;
+							}
+							if ((TileY(tile) + i) >= (sy + size_y - 1) || !found)
+								bridge_error = true;
+							else
+								tmp_tile += TileDiffXY(0, +i);
+							break;
+						case DIAGDIR_NW:
+							/* -Y */
+							i = 1;
+							while ((TileY(tile) + i) >= (sy + size_y - 1)) {
+								if (GetCPTileType(index - (i * (size_x - 1))) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index - (i * (size_x - 1))), 0) && !HasBit(m_railroad[index - (i * (size_x - 1))], 4) && GB(m_railroad[index - (i * (size_x - 1))], 0, 2) == rdd) {
+									found = true;
+									break;
+								}
+								i++;
+							}
+							if ((TileY(tile) - i) < sy || !found)
+								bridge_error = true;
+							else
+								tmp_tile += TileDiffXY(0, 0 - i);
+							break;
+					}
+					if (!bridge_error) {
+						if (GB(m_railroad[index], 2, 2) == TRANSPORT_RAIL) {
+							CP_Build_Bridge(tile, tmp_tile, m_convert_rail ? GetFastestAvailableBridgeType(GetTunnelBridgeLength(tile, tmp_tile)) : m_signals[index], TRANSPORT_RAIL, m_convert_rail ? (uint) _cur_railtype : ((m_railroad[index] >> 6) & 3U) );
+						} else {
+							CP_Build_Bridge(tile, tmp_tile, m_convert_rail ? GetFastestAvailableBridgeType(GetTunnelBridgeLength(tile, tmp_tile)) : m_signals[index], TRANSPORT_ROAD, ((m_railroad[index] >> 6) & 3U) );
+						}
+					}
+				}
+				break;
+			default: break;
+		}
+
+		index++;
+
+	}
+
+	/* Restore Signals and Waypoints (separated because they depend on underlying track) */
+	index = 0;
+	TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
+		if (GetCPTileType(index) == CP_TILE_RAIL) {
+			switch(GetCPMinorTileType(index)) {
+/*				case RAIL_TILE_WAYPOINT:
+					CP_PlaceWaypoint(tile, GB(m_signals[index], 0, 8));
+					break;*/
+				case RAIL_TILE_SIGNALS:
+					PasteSignals(index, tile);
+			}
+		}
+		index++;
+	}
+
+
+	/* If shift is pressed, show the cost estimate. Else play a sound on success */
+	if (_shift_pressed) {
+		ShowEstimatedCostOrIncome(m_costs.GetCost(), 100, 100);
+	}
+	else {
+		if (success) SndPlayTileFx(SND_1F_SPLAT, tile);
+	}
+}
+
+/**
+ * Safe Paste Command. 
+ * Checks CopyPasteCommandQueue-Size in network games
+ **/
+void CopyPaste::PasteArea(TileIndex tile)
+{
+	if (_settings_client.gui.cp_paste_speed != 0xFF) {
+		this->internal_PasteArea(tile);
+	}
+	else {
+		ShowErrorMessage(STR_COPY_PASTE_PASTE_DISABLED, INVALID_STRING_ID, WL_ERROR, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
+	}
+}
+
+/**
+ * Indicates this tile needs to be terraformed, in order to restore some building.
+ * Bit 0 indicates this tile is needed for terraforming,
+ * but is not directly build on.
+ * Bit 1 indicates this tile is beeing built on.
+ **/
+void CopyPaste::TerrainNeededAroundTile(TileIndex tindex, TileIndex bindex)
+{
+	/* always restore terrain on this tiles */
+	SetBit(m_terrain_needed[tindex], 0);
+	SetBit(m_terrain_needed[tindex + 1], 0);
+	SetBit(m_terrain_needed[tindex + GetWidth()], 0);
+	SetBit(m_terrain_needed[tindex + GetWidth() + 1], 0);
+}
+
+/**
+ * Game command which copies a selected area
+ **/
+void CopyPaste::CopyArea(TileIndex end, TileIndex start)
+{
+	int8 baseh;
+	TileIndex tindex = 0;
+	TileIndex bindex = 0;
+	int size_x, size_y;
+	bool success = false;
+	TileIndex sx = TileX(start);
+	TileIndex sy = TileY(start);
+	TileIndex ex = TileX(end);
+	TileIndex ey = TileY(end);
+	bool tunnelbridge_error;
+	int32 maxdiff, i;
+
+
+	if (ex < sx) Swap(ex, sx);
+	if (ey < sy) Swap(ey, sy);
+	/* add one tile, but just for heightmap */
+	ex++;
+	ey++;
+	size_x = (ex - sx) + 1;
+	size_y = (ey - sy) + 1;
+
+	this->AllocateMapArray(size_x * size_y);
+	SetWidth(size_x);
+	SetHeight(size_y);
+
+	/* Create a command DIFF to a flat Area */
+	/* Base level is from first tile. */
+	baseh = (int8)TileHeight(TileXY(sx, sy));
+	tindex = 0;
+	TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
+
+		m_heightmap[tindex] = ((int8)TileHeight(tile)) - baseh;
+		tindex++;
+
+		/* Dont Copy tracks/buildings on last x/y row */
+		if (cur_h == 1 || cur_w == 1) {
+			success = true;
+			continue;
+		}
+
+		/* Copy building/track here */
+		switch (GetTileType(tile)) {
+			case MP_RAILWAY:
+				/* Check if we want to copy this type of building */
+				if (!m_copy_with_rail) break;
+				if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
+				SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
+				SB(m_tiletype[bindex], 4, 4, GetRailTileType(tile));
+				TerrainNeededAroundTile(tindex - 1, bindex);
+				
+				/* Store Railway type in bits 6+7 */
+				SB(m_railroad[bindex], 6, 2, GetRailType(tile));
+				
+				switch (GetRailTileType(tile)) {
+					case RAIL_TILE_DEPOT:
+						/* Depot here */
+						/* store direction: bit 2+3 */
+						SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_RAIL));
+						break;
+/*					case RAIL_TILE_WAYPOINT:
+						// Waypoint here
+						// Store Waypoint custom gfx id
+						SB(m_signals[bindex], 0, 8, GetWaypointByTile(tile)->stat_id);
+						// Store axis
+						SB(m_railroad[bindex], 0, 2, AxisToTrackBits(GetWaypointAxis(tile)));
+						break;*/
+					case RAIL_TILE_SIGNALS: {
+						/* Signals: */
+						/* Store Signal:
+						 * Bit      0 : signal 1 present
+						 * Bit      1 : signal 2 present
+						 * Bit      2 : variant S1
+						 * Bit      3 : variant S2
+						 * Bits: 6- 7 : Direction S1 (Clicks to build)
+						 * Bits: 8- 9 : Direction S2 (Clicks to build)
+						 * Bits: 10-12: signal type S1
+						 * Bits: 13-15: signal type S2
+						 */
+						bool first_run = true;
+						for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
+							if (HasTrack(tile, t) && HasSignalOnTrack(tile, t)) {
+								if (t == TRACK_X || t == TRACK_Y || t == TRACK_LEFT || t == TRACK_UPPER) {
+									SetBit(m_signals[bindex], 0);
+								} else {
+									SetBit(m_signals[bindex], 1);
+								}
+								/* Store signal direction */
+								Trackdir td = TrackToTrackdir(t);
+								if (!(HasSignalOnTrackdir(tile, td) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)))) {
+									/* one way signal, not 2-way */
+									if (t == TRACK_LEFT || t == TRACK_RIGHT) td = ReverseTrackdir(td);
+									SB(m_signals[bindex], first_run ? 6 : 8, 2, HasSignalOnTrackdir(tile, td) ? 1 : 2);
+								}
+								/* Bit 2/3: signal variant(semaphore/electric) ToDo: find some place this can live with another one */
+								SB(m_signals[bindex], first_run ? 2 : 3, 1, GetSignalVariant(tile, t));
+								/* Bits 10 - 12/13-15: signal type */
+								SB(m_signals[bindex], first_run ? 10 : 13, 3, GetSignalType(tile, t));
+								first_run = false;
+							}
+						}
+					}
+					/* fallthrough */
+					case RAIL_TILE_NORMAL:
+						/* Store Railway tracks in bits 0 to 5: */
+						m_railroad[bindex] |= GetTrackBits(tile);
+						break;
+				}
+
+				break;
+			case MP_ROAD:
+				if (GetRoadTileType(tile) != ROAD_TILE_CROSSING && (!m_copy_with_road || !(m_copy_with_other || IsTileOwner(tile, _current_company)))) break;
+				SB(m_tiletype[bindex], 0, 4, CP_TILE_ROAD);
+				SB(m_tiletype[bindex], 4, 4, GetRoadTileType(tile));
+				switch (GetRoadTileType(tile)) {
+					case ROAD_TILE_CROSSING: {
+						/* Crossing: Get Axis, store railtype too 
+						 * TODO Unify...
+						 */
+						RoadBits roadbits = GetCrossingRoadBits(tile);
+						Track railtrack = GetCrossingRailTrack(tile);
+						bool should_copy_rail = m_copy_with_rail && (m_copy_with_other || IsTileOwner(tile, _current_company));
+						bool should_copy_road = m_copy_with_road;
+						if (should_copy_rail && !should_copy_road) {
+							SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
+							SB(m_tiletype[bindex], 4, 4, RAIL_TILE_NORMAL);
+							TerrainNeededAroundTile(tindex - 1, bindex);
+							/* Copy the rail */
+							m_railroad[bindex] |= TrackToTrackBits(railtrack);
+							SB(m_railroad[bindex], 6, 2, GetRailType(tile));
+						}
+						if (should_copy_road && !should_copy_rail) {
+							SB(m_tiletype[bindex], 4, 4, ROAD_TILE_NORMAL);
+						}
+						if (should_copy_road && should_copy_rail) {
+							SB(m_signals[bindex], 4, 2, GetRailType(tile));
+						}
+						if (should_copy_road) {
+							/* Copy the road */
+							for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
+								if ((m_copy_with_other || GetRoadOwner(tile, rt) == _current_company) && GetRoadTypes(tile) & RoadTypeToRoadTypes(rt)) {
+									TerrainNeededAroundTile(tindex - 1, bindex);
+									SB(m_railroad[bindex], rt * 4, 4, roadbits);
+								}
+							}
+						}
+						if (!should_copy_road && !should_copy_rail) {
+							SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
+						}
+						} break;
+
+					case ROAD_TILE_DEPOT:
+						/* Direction: bit 0+1 */
+						SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_ROAD));
+						/* Tram or Road? bit 2 */
+						if (GetRoadTypes(tile) != ROADTYPES_ROAD) SetBit(m_railroad[bindex], 2);
+						TerrainNeededAroundTile(tindex - 1, bindex);
+						break;
+
+					case ROAD_TILE_NORMAL:
+						for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
+							SB(m_railroad[bindex], rt * 4, 4, GetRoadBits(tile, rt));
+						}
+						TerrainNeededAroundTile(tindex - 1, bindex);
+						SB(m_signals[bindex], 0, 2, GetDisallowedRoadDirections(tile));
+						break;
+				}
+				break;
+
+			case MP_STATION:
+				/* Stations: currently partially supported */
+				SB(m_tiletype[bindex], 0, 4, CP_TILE_STATION);
+
+			
+				switch (GetStationType(tile)) {
+					/* Road stations */
+					case STATION_TRUCK:
+					case STATION_BUS:
+						SB(m_tiletype[bindex], 4, 4, CP_TILE_ROAD);
+
+						SB(m_railroad[bindex], 0, 2, GetRoadStopDir(tile));
+						if(GetStationType(tile) == STATION_TRUCK) SetBit(m_railroad[bindex], 2);
+						SB(m_railroad[bindex], 3, 1, IsDriveThroughStopTile(tile));
+						SB(m_railroad[bindex], 6, 2, GetRoadTypes(tile));
+						break;					
+	
+					/* Rail stations */
+					case STATION_RAIL:
+						SB(m_tiletype[bindex], 4, 4, CP_TILE_RAIL);
+
+						//GetStationSpec for newgrf info
+						break;
+
+					default:
+						/* Not reached */
+						break;
+
+				}
+				break;
+
+			case MP_TUNNELBRIDGE:
+				/* Check for tunnel or bridge 
+				 * TODO Try to unify bridges an tunnels, since error checking(start/endtile) is essentially the same
+				 */
+				if (IsTunnelTile(tile)) {
+					/* Storing Tunnel */
+					if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
+					if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
+					if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
+					tunnelbridge_error = false;
+					if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
+						int tilediff = 1;
+						/* Store tunnel direction in bit 0-1 */
+						SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
+						/* Store tunnel transport type in bit 2-3 */
+						SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
+						/* Store tunnel start in bit 4 */
+						SetBit(m_railroad[bindex], 4);
+						/* Store rail type too, if it is a railtunnel */
+						if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
+							m_railroad[bindex] |= (GetRailType(tile) << 6);
+						if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
+							m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
+						/* Now mark all tiles between tunnel start and end as needed 
+						 * TODO Unify... ;)
+						 */
+						switch (GetTunnelBridgeDirection(tile)) {
+							case DIAGDIR_SW:
+								maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
+								if (maxdiff <= 0) {
+									tunnelbridge_error = true;
+									break;
+								}
+								while ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) && (tilediff <= maxdiff)) { //InsideSelection, tunnelEndnotfound
+									tilediff++;
+								}
+								if ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) || (tilediff > maxdiff))
+									tunnelbridge_error = true;
+								if (!tunnelbridge_error) {
+									/* Mark Tiles as needed: */
+									for (i = 0; i <= tilediff; i++)
+										TerrainNeededAroundTile(tindex - 1 + i, bindex + i);
+
+									/* Set other TunnelEnd */
+									SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
+									SB(m_tiletype[bindex + tilediff], 4, 1, true);
+									/* Store tunnel direction in bit 1-2 */
+									m_railroad[bindex + tilediff] |= GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0));
+									/* Store tunnel transport type in bit 3 */
+									SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
+									/* Store tunnel start in bit 4 (No, this is tunnel End) */
+									/* Store rail type too, if railtunnel */
+									if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
+										m_railroad[bindex + tilediff] = (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
+								}
+								break;
+							case DIAGDIR_SE:
+								maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
+								if (maxdiff <= 0) {
+									tunnelbridge_error = true;
+									break;
+								}
+								while ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) && (tilediff <= maxdiff)) { //InsideSelection, tunnelEndnotfound
+									tilediff++;
+								}
+								if ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) || (tilediff > maxdiff))
+									tunnelbridge_error = true;
+								if (!tunnelbridge_error) {
+									/* Mark Tiles as needed: */
+									for (i = 0; i <= tilediff; i++)
+										TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));
+
+									/* Set other TunnelEnd */
+									SB(m_tiletype[bindex + tilediff * (size_x - 1)], 0, 4, CP_TILE_TUNNELBRIDGE);
+									SB(m_tiletype[bindex + tilediff * (size_x - 1)], 4, 1, true);
+									/* Store tunnel direction in bit 0-1 */
+									m_railroad[bindex + (tilediff * (size_x - 1))] |= GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff));
+									/* Store tunnel transport type in bit 3 */
+									SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
+									/* Store tunnel start in bit 4 (No, this is tunnel End) */
+									/* Store rail type too, if railtunnel */
+									if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
+										m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
+								}
+								break;
+							default:
+							break;
+						}
+						if (tunnelbridge_error) {
+							/* ResetBridge on Error */
+							m_railroad[bindex] = 0;
+						} else {
+							SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
+							SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
+						}
+					}
+					else {
+						/* Other directions: do nothing since we have everything copied already */
+					}
+				}
+				else {
+					/* Store bridge (Has to be in "else", since Tunnel is a "BridgeRamp" too) */
+					if (IsBridge(tile)) {
+						if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
+						if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
+						if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
+
+						tunnelbridge_error = false;
+						if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
+							int tilediff = 1;
+							/* Direction bit 0-1 */
+							SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
+							/* TransportType bit 3 */
+							SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
+							/* Store "IsBridge-Start" in Bit4 */
+							SetBit(m_railroad[bindex], 4);
+							/* BridgeType in m_signals */
+							m_signals[bindex] = GetBridgeType(tile);
+							/* Store Railtype */
+							if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
+								m_railroad[bindex] |= (GetRailType(tile) << 6);
+							if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
+								m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
+							/* Now mark all tiles between bridge start and end as needed 
+							 * TODO: Unify :)
+							 */
+							switch (GetTunnelBridgeDirection(tile)) {
+								TileIndex otherEnd;
+								case DIAGDIR_SW:
+									maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
+									if (maxdiff <= 0) {
+										tunnelbridge_error = true;
+										break;
+									}
+									otherEnd = GetOtherBridgeEnd(tile);
+									tilediff = DistanceManhattan(tile, otherEnd);
+									if (tilediff > maxdiff)
+										tunnelbridge_error = true;
+									
+									if (!tunnelbridge_error) {
+										/* Mark Tiles as needed: */
+										for (i = 0; i <= tilediff; i++)
+											TerrainNeededAroundTile(tindex - 1 + i, bindex + i);
+
+										/* Set other BridgeEnd */
+										SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
+										SB(m_tiletype[bindex + tilediff], 4, 1, IsTunnelTile(tile));
+										/* Direction bit 0-1 */
+										SB(m_railroad[bindex + tilediff], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0)));
+										/* TransportType bit 3 */
+										SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
+										/* Store "IsBridge-Start" in Bit4 (Nope, this is the Bridge-End) */
+										
+										/* BridgeType in m_signals */
+										m_signals[bindex + tilediff] = GetBridgeType(tile + TileDiffXY(tilediff, 0));
+										/* Store Railtype */
+										if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
+											m_railroad[bindex + tilediff] |= (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
+									}
+									break;
+								case DIAGDIR_SE:
+									maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
+									if (maxdiff <= 0) {
+										tunnelbridge_error = true;
+										break;
+									}
+									otherEnd = GetOtherBridgeEnd(tile);
+									tilediff = DistanceManhattan(tile, otherEnd);
+									if (tilediff > maxdiff)
+										tunnelbridge_error = true;
+									if (!tunnelbridge_error) {
+										/* Mark Tiles as needed: */
+										for (i = 0; i <= tilediff; i++)
+											TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));
+
+										/* Set other BridgeEnd */
+										SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 0, 4, CP_TILE_TUNNELBRIDGE);
+										SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 4, 1, IsTunnelTile(tile));
+										/* Direction bit 0-1 */
+										SB(m_railroad[bindex + tilediff * (size_x - 1)], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff)));
+										/* TransportType bit 3 */
+										SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
+										/* Store "IsBridge-Start" in Bit4 (Nope, this is the End) */
+										/* BridgeType  in m_signals */
+										m_signals[bindex + tilediff * (size_x - 1)] = GetBridgeType(tile + TileDiffXY(0, tilediff));
+										/* Store Railtype */
+										if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
+											m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
+									}
+									break;
+								default:
+									break;
+							}
+							if (tunnelbridge_error) {
+								/* ResetBridge on Error */
+								m_railroad[bindex] = 0;
+								m_signals[bindex] = 0;
+							} else {
+								SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
+								SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
+							}
+						}
+						else {
+							/* Other directions, do nothing, since we have copied everything already */
+						}
+					}
+				}
+				break;
+
+			default:
+				SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
+				/* Storing nothing */
+				break;
+		}
+		bindex++;
+		success = true;
+
+	}
+
+	if (success) SndPlayTileFx(SND_1F_SPLAT, end);
+}
+
+/* Get the height of a tile */
+uint CopyPaste::GetHeight(uint baseh, uint index)
+{
+	return baseh + m_heightmap[index];
+}
+
+Slope CopyPaste::GetSlope(uint index)
+{
+	int a = m_heightmap[index];
+	int min = a;
+	int b = m_heightmap[index + 1];
+	if (min > b) min = b;
+	int c = m_heightmap[index + GetWidth()];
+	if (min > c) min = c;
+	int d = m_heightmap[index + GetWidth() + 1];
+	if (min > d) min = d;
+	
+	uint r = SLOPE_FLAT;
+	
+	if (a -= min != 0) r += (--a << 4) + SLOPE_N;
+	if (c -= min != 0) r += (--c << 4) + SLOPE_E;
+	if (d -= min != 0) r += (--d << 4) + SLOPE_S;
+	if (b -= min != 0) r += (--b << 4) + SLOPE_W;
+	
+	return (Slope)r;
+}
+
+TrackBits CopyPaste::GetCPTrackBits(uint index)
+{
+	if (GetCPTileType(index) == CP_TILE_RAIL) {
+		if (GetCPMinorTileType(index) != RAIL_TILE_DEPOT) return (TrackBits)GB(m_railroad[index], 0, 6);
+	} else if (GetCPTileType(index) == CP_TILE_ROAD) {
+		if (GetCPMinorTileType(index) == ROAD_TILE_CROSSING) return GB(m_railroad[index], 0, 4) == ROAD_X ? TRACK_BIT_Y : TRACK_BIT_X;
+	}
+	return TRACK_BIT_NONE;
+}
+
+/** Get the major tiletype of a tile*/
+CopyPaste::CopyPasteTileType CopyPaste::GetCPTileType(uint index)
+{
+	return (CopyPasteTileType)GB(m_tiletype[index], 0, 4);
+}
+
+/** Get the minor tiletype of a tile*/
+uint CopyPaste::GetCPMinorTileType(uint index)
+{
+	return GB(m_tiletype[index], 4, 4);
+}
+/**
+ * Rotate an array.
+ * @param dir 1: rotate CW
+ *            -1: rotate CCW
+ **/
+template <typename T> 
+static void rotate(T* b, int w, int h, int dir)
+{
+	int i, len, x, y, src, target;
+
+	/* Allocate a temporary array */
+	len = w * h;
+	T* tmp = MallocT<T>(len);
+
+	/* Copy array to new allocated array: */
+	for (i = 0; i < len; i++)
+		tmp[i] = b[i];
+
+	/* Copy rotated values back to original array */
+	if (dir == 1) {
+		for (y = 0; y < h; y++) {
+			for (x = 0; x < w; x++) {
+				/*X index is now the old Y index
+				 * Y index is w - x
+				 */
+				src = (y * w) + x;
+				target = (((w - 1) - x) * h) + y;
+				b[target] = tmp[src];
+			}
+		}
+	}
+	else if (dir == -1) {
+			/* Copy rotated values back to original array */
+			for (y = 0; y < h; y++) {
+				for (x = 0; x < w; x++) {
+					/* X index is now the old Y index
+					 * Y index is w - x
+					 */
+					src = (y * w) + x;
+					target = (x * h) + (h - 1 - y);
+					b[target] = tmp[src];
+				}
+			}
+	}
+
+	/* Release temp array */
+	free(tmp);
+}
+
+/**
+ * Mirror array.
+ * @param axis 0: horizontal
+ *              1: vertical
+ **/
+template <typename T>
+static void mirror(T* b, int w, int h, Axis axis)
+{
+	int x, y;
+
+
+	switch (axis) {
+		case AXIS_X:
+			for (y = 0; y < h; y++) {
+				for (x = 0; x < (w / 2); x++) {
+					Swap<T>(b[x + (y * w)], b[(w - x - 1) + (y * w)]);
+				}
+			}
+		break;
+		case AXIS_Y:
+			for (y = 0; y < (h / 2); y++) {
+				for (x = 0; x < w; x++) {
+					Swap<T>(b[x + (y * w)], b[ x + ((h - y - 1) * w)]);
+				}
+			}
+		break;
+		default: NOT_REACHED();
+	}
+}
+
+/**
+ * Rotates the copied content ClockWise
+ * This is done by first rotating the array indices,
+ * then rotating the field contents
+ **/
+void CopyPaste::RotateSelectionCW()
+{
+	int w = GetWidth() - 1;
+	int h = GetHeight() - 1;
+	uint8 storelocation;
+	int index, len;
+
+	uint8 tmp8;
+	uint16 tmp16;
+
+	/* Rotate array indices */
+	rotate(m_heightmap, GetWidth(), GetHeight(), 1);
+	rotate(m_terrain_needed, GetWidth(), GetHeight(), 1);
+	rotate(m_tiletype, w, h, 1);
+	rotate(m_railroad,   w, h, 1);
+	rotate(m_signals,w, h, 1);
+
+	/* Rotate array content (tracks, depots etc..) */
+	len = w * h;
+	for (index = 0; index < len; index++) {
+
+		switch (GetCPTileType(index)) {
+			case CP_TILE_RAIL:
+				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
+					/* Depot */
+					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
+					break;
+				}
+				/* Rotate Tracks */
+				/* Copy tracks to temp variable */
+				tmp8 = m_railroad[index];
+				/* Clear Tracks: bits 0-5 */
+				m_railroad[index] &= ~((1 << 6) - 1);
+				/* Copy back + rotate 
+				 * TODO exchange with arithmetic or lookup-table version...shorten...
+				 */
+				if (tmp8 & TRACK_BIT_Y)     m_railroad[index] |= TRACK_BIT_X;
+				if (tmp8 & TRACK_BIT_X)     m_railroad[index] |= TRACK_BIT_Y;
+				if (tmp8 & TRACK_BIT_LEFT)  m_railroad[index] |= TRACK_BIT_UPPER;
+				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
+				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
+				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
+				
+				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
+					/* Signals */
+					/* copy original signals to temporary variable */
+					tmp16 = m_signals[index];
+					/* Clear Signals: Bits 0-2 */
+					ClrBit(m_signals[index], 0);
+					ClrBit(m_signals[index], 1);
+					/* Copy back + rotate position */
+					storelocation = 6;
+					/* We already rotated the rail, so the TRACK_BIT_xxxx are the rotated ones */
+					if ((m_railroad[index] & TRACK_BIT_Y) && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+					}
+					if ((m_railroad[index] & TRACK_BIT_X) && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+					}
+					if ((m_railroad[index] & TRACK_BIT_RIGHT) && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 1);
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						storelocation = 8;
+					}
+					if ((m_railroad[index] & TRACK_BIT_LEFT) && HasBit(tmp16, 1)) {
+						SetBit(m_signals[index], 0);
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						if (storelocation == 8) {
+							/* Exchange Storelocations */
+							SwapSignalInfo(index);
+						}
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+					}
+					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
+						SetBit(m_signals[index], 1);
+					}
+				
+				}
+				break;
+				
+			case CP_TILE_ROAD:
+				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
+					/* Depot */
+					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
+					break;
+				}
+
+				/* rotate one-way roads */
+				if (m_railroad[index] & ROAD_Y && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
+					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
+				}
+				/* Road: */
+				SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90RIGHT));
+				/* Trams: */
+				SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90RIGHT));
+
+			
+				break;
+
+				case CP_TILE_TUNNELBRIDGE:
+					/* tunnel/bridge */
+					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
+				
+					break;
+
+				default: break;
+		}
+
+	}
+
+	Swap(this->m_width, this->m_height);
+}
+
+/**
+ * Rotates the copied content CounterClockWise
+ * This is done by first rotating the array indices,
+ * then rotating the field contents
+ **/
+void CopyPaste::RotateSelectionCCW()
+{
+	int w = GetWidth() - 1;
+	int h = GetHeight() - 1;
+	uint8 storelocation;
+	int index, len;
+
+	uint8 tmp8;
+	uint16 tmp16;
+
+	/* Rotate array indices */
+	rotate(m_heightmap, GetWidth(), GetHeight(), -1);
+	rotate(m_terrain_needed, GetWidth(), GetHeight(), -1);
+	rotate(m_tiletype, w, h, -1);
+	rotate(m_railroad,   w, h, -1);
+	rotate(m_signals,w, h, -1);
+
+	/* Rotate array content (tracks, depots etc..) */
+	len = w * h;
+	for (index = 0; index < len; index++) {
+		switch (GetCPTileType(index)) {
+			case CP_TILE_RAIL:
+				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
+					//Depot
+					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
+					break;
+				}
+				tmp8 = m_railroad[index];
+				/* Clear Tracks: bits 0-5 */
+				m_railroad[index] &= ~63U;
+				/* Copy back + rotate */
+				if (tmp8 & TRACK_BIT_Y) m_railroad[index]     |= TRACK_BIT_X;
+				if (tmp8 & TRACK_BIT_X) m_railroad[index]     |= TRACK_BIT_Y;
+				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
+				if (tmp8 & TRACK_BIT_LEFT) m_railroad[index]  |= TRACK_BIT_LOWER;
+				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
+				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
+				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
+					//Signals
+					//Rotate position
+					tmp16 = m_signals[index];
+					/* Clear Signals: Bits 0-2 */
+					ClrBit(m_signals[index], 0);
+					ClrBit(m_signals[index], 1);
+					//Copy back + rotate position
+					storelocation = 6;
+					/* We already rotated the rail, so the TRACK_BIT_xxxx are the rotated ones */
+					if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+					}
+					if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+					}
+					if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
+						SetBit(m_signals[index], 1);
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 1);
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
+						SetBit(m_signals[index], 0);
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						if (storelocation == 8) {
+							/* Exchange Storelocations */
+							SwapSignalInfo(index);
+						}
+						storelocation = 8;
+					}
+				}
+				break;
+
+			case CP_TILE_ROAD:
+				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
+					//Depot
+					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
+					break;
+				}
+				if (m_railroad[index] & ROAD_X && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
+					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
+				}
+				//Road & Tram:
+				SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90LEFT));
+				SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90LEFT));
+
+				break;
+
+			case CP_TILE_TUNNELBRIDGE:
+				SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
+				break;
+			default: break;
+		}
+
+	}
+
+	Swap(this->m_height, this->m_width);
+}
+
+void CopyPaste::MirrorSelectionHorizontal()
+{
+	int w = GetWidth() - 1;
+	int h = GetHeight() - 1;
+	uint8 storelocation;
+	int index, len;
+
+	uint8 tmp8;
+	uint16 tmp16;
+
+	/* Mirror array indices */
+	mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_X);
+	mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_X);
+	mirror(m_tiletype, w, h, AXIS_X);
+	mirror(m_railroad,   w, h, AXIS_X);
+	mirror(m_signals,w, h, AXIS_X);
+
+	/* Mirror array content (left <-> right) */
+	len = w * h;
+	for (index = 0; index < len; index++) {
+		switch (GetCPTileType(index)) {
+			case CP_TILE_RAIL:
+				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
+					//Depot
+					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
+					if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
+					SB(m_railroad[index], 0, 2, tmp8); // set
+					break;
+				}
+				tmp8 = m_railroad[index];
+				/* Clear Tracks: Bits 0-5 */
+				m_railroad[index] &= ~63U;
+				/* Copy back + mirror */
+				if (tmp8 & TRACK_BIT_X)     m_railroad[index] |= TRACK_BIT_X;
+				if (tmp8 & TRACK_BIT_Y)     m_railroad[index] |= TRACK_BIT_Y;
+				if (tmp8 & TRACK_BIT_LEFT)  m_railroad[index] |= TRACK_BIT_UPPER;
+				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
+				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
+				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
+				
+				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
+					//Signals
+					//Mirror position
+					tmp16 = m_signals[index];
+					//Copy back + mirror position
+					storelocation = 6;
+					if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+					}
+					if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+						storelocation = 8;
+					}
+				}
+				break;
+
+			case CP_TILE_ROAD:
+				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
+					//Depot
+					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
+					if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
+					SB(m_railroad[index], 0, 2, tmp8); // set
+					break;
+				}
+				//Road:
+				//swap horizontal roadpieces
+				tmp8 = m_railroad[index];
+				m_railroad[index] &= ~(ROAD_NE | ROAD_SW  | ((ROAD_NE | ROAD_SW) << 4)); //Clear specific road bits
+				if ((tmp8 & ROAD_NE) > 0) m_railroad[index] |= ROAD_SW;
+				if ((tmp8 & ROAD_SW) > 0) m_railroad[index] |= ROAD_NE;
+				if ((tmp8 & (ROAD_NE << 4)) > 0) m_railroad[index] |= (ROAD_SW << 4);
+				if ((tmp8 & (ROAD_SW << 4)) > 0) m_railroad[index] |= (ROAD_NE << 4);
+				
+				if ((tmp8 & ROAD_X) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
+					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
+				}
+				
+				break;
+
+			case CP_TILE_TUNNELBRIDGE:
+				/* Tunnel/Bridge
+				 * just mirror direction
+				 */
+				tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 001
+				if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
+				SB(m_railroad[index], 0, 2, tmp8); // set
+			
+				break;
+
+			default: break;
+		}
+
+	}
+}
+
+void CopyPaste::MirrorSelectionVertical()
+{
+	int w = GetWidth() - 1;
+	int h = GetHeight() - 1;
+	uint8 storelocation;
+	int index, len;
+
+	uint8 tmp8;
+	uint16 tmp16;
+
+	//Mirror arrays
+	mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_Y);
+	mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_Y);
+	mirror(m_tiletype, w, h, AXIS_Y);
+	mirror(m_railroad,   w, h, AXIS_Y);
+	mirror(m_signals,w, h, AXIS_Y);
+
+	//Mirror array content (up <-> down)
+	len = w * h;
+	for (index = 0; index < len; index++) {
+		switch (GetCPTileType(index)) {
+			case CP_TILE_RAIL:
+				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
+					//Depot
+					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
+					if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
+					SB(m_railroad[index], 0, 2, tmp8); // set
+					break;
+				}
+				tmp8 = m_railroad[index];
+				//Clear Tracks
+				m_railroad[index] &= ~63U; //Clear bits 0-5
+				//Copy back + mirror
+				if (tmp8 & TRACK_BIT_X) m_railroad[index]     |= TRACK_BIT_X;
+				if (tmp8 & TRACK_BIT_Y) m_railroad[index]     |= TRACK_BIT_Y;
+				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
+				if (tmp8 & TRACK_BIT_LEFT) m_railroad[index]  |= TRACK_BIT_LOWER;
+				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
+				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
+				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
+					//Signals
+					//Mirror position
+					tmp16 = m_signals[index];
+					//Clear Signals
+					ClrBit(m_signals[index], 0);
+					ClrBit(m_signals[index], 1);
+					//Copy back + mirror position
+					storelocation = 6;
+					if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+					}
+					if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 0);
+						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
+					}
+					if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 1);
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 1)) {
+						SetBit(m_signals[index], 0);
+						if (storelocation == 8) {
+							/* Exchange Storelocations */
+							SwapSignalInfo(index);
+						}
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
+						SetBit(m_signals[index], 1);
+						storelocation = 8;
+					}
+					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
+						SetBit(m_signals[index], 0);
+						if (storelocation == 8) {
+							/* Exchange Storelocations */
+							SwapSignalInfo(index);
+						}
+						storelocation = 8;
+					}
+
+				}
+				break;
+
+			case CP_TILE_ROAD:
+				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
+					//Depot
+					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
+					if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
+					SB(m_railroad[index], 0, 2, tmp8); // set
+					break;
+				}
+				//Road:
+				//swap horizontal roadpieces
+				tmp8 = m_railroad[index];
+				m_railroad[index] &= ~(ROAD_NW | ROAD_SE  | ((ROAD_NW | ROAD_SE) << 4)); //Clear specific road bits
+				if ((tmp8 & ROAD_NW) > 0) m_railroad[index] |= ROAD_SE;
+				if ((tmp8 & ROAD_SE) > 0) m_railroad[index] |= ROAD_NW;
+				if ((tmp8 & (ROAD_NW << 4)) > 0) m_railroad[index] |= (ROAD_SE << 4);
+				if ((tmp8 & (ROAD_SE << 4)) > 0) m_railroad[index] |= (ROAD_NW << 4);
+				
+				if ((tmp8 & ROAD_Y) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
+					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
+				}
+				
+				break;
+
+			case CP_TILE_TUNNELBRIDGE:
+				/* Tunnel / Bridge */
+				tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 1-2
+				if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
+				SB(m_railroad[index], 0, 2, tmp8); // set
+				break;
+			default: break;
+		}
+
+	}
+}
+
+
diff --git a/src/copy_paste.h b/src/copy_paste.h
new file mode 100644
--- /dev/null
+++ b/src/copy_paste.h
@@ -0,0 +1,113 @@
+/* $Id: command_queue.h 4998 2006-05-30 16:13:41Z Frostregen $ */
+
+#ifndef COPY_PASTE_H
+#define COPY_PASTE_H
+
+#include "map_type.h"
+#include "command_type.h"
+#include "signal_type.h"
+#include "track_type.h"
+#include "slope_type.h"
+#include "road_map.h"
+#include "saveload/saveload.h"
+
+class CopyPaste {
+public:
+	bool  m_copy_with_rail;          ///< If rail should be copied
+	bool  m_copy_with_road;          ///< If road should be copied
+	bool  m_copy_with_other;         ///< If stuff owned by other players should be copied
+
+	uint8 m_paste_vacant_terrain;    ///< If empty terrain should be recreated. 0 = no terraform, 1 = terraform only needed, 2 = terraform all terrain
+	bool  m_convert_rail;            ///< If rails should be converted to currently selected railtype
+	bool  m_clear_before_build;      ///< If terrain should be bulldozed before we try to paste it
+	bool  m_toggle_signal_direction; ///< If signal direction should be toggled when pasting
+
+private:
+	uint32   m_width;
+	uint32   m_height;
+        StringID error_str;
+	char     *error_msg;
+
+	CommandCost m_costs; ///< Stores the costs needed for template paste - estimate
+
+	/** Storage space for copied area 
+	 * TODO: Convert to struct (saveload...)
+	 */
+	int8   *m_heightmap;      ///<  | Move terrain needed into this...
+	uint8  *m_terrain_needed; ///<  2Bit needed
+	uint8  *m_tiletype;       ///<  8Bit needed
+	uint8  *m_railroad;       ///<  8Bit needed
+	uint16 *m_signals;        ///< 15Bit needed
+	//TODO: uint8 *m_station;
+
+public:
+	enum CopyPasteTileType {
+		CP_TILE_CLEAR,
+		CP_TILE_RAIL,
+		CP_TILE_ROAD,
+		CP_TILE_TUNNELBRIDGE,
+		CP_TILE_STATION,
+	};
+	explicit CopyPaste();
+	~CopyPaste();
+
+	SaveOrLoadResult SaveLoadTemplate(const char *filename, int mode);
+	const char *GetErrorString();
+	bool IsSomethingCopied(); ///< Returns if something is in our copy buffer.
+	void AllocateMapArray(uint32 max_tiles); ///< allocate a map array
+	void ClearCopyArrays();   ///< Clears content of copy buffers for current width/height, but does NOT reset width/height.
+
+	void CopyArea(TileIndex end, TileIndex start); ///< Copies given area into copy buffer
+	void PasteArea(TileIndex tile);                ///< Paste copied content onto map, taking care of multiplayer/singleplayer environment.
+
+	void RotateSelectionCCW();
+	void RotateSelectionCW();
+	void MirrorSelectionHorizontal();
+	void MirrorSelectionVertical();
+	uint GetHeight(uint baseh, uint index);
+	Slope GetSlope(uint index);
+	CopyPasteTileType GetCPTileType(uint index);
+	uint GetCPMinorTileType(uint index);
+	TrackBits GetCPTrackBits(uint index);
+
+	FORCEINLINE uint32 GetWidth()  { return m_width;  };	///< Used by the GUI
+	FORCEINLINE uint32 GetHeight() { return m_height; };
+
+private:
+	void SetError(StringID message, StringID extra = INVALID_STRING_ID);
+
+	void internal_PasteArea(TileIndex tile); ///< internal PasteArea method
+
+	void CP_DoCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd); ///< Special DoCommand for CopyPaste
+
+	void CP_RaiseLowerLand  (TileIndex tile, int mode);
+	void CP_PlaceRail       (TileIndex tile, int cmd, uint32 railtype);
+	void CP_PlaceSignals    (TileIndex tile, Track track, SignalType type, uint direction, bool semaphore);
+	void CP_PlaceRoad       (TileIndex tile, uint8 road_bits);
+	void CP_PlaceRoadStop(TileIndex tile, uint8 direction, uint8 roadtype, bool truck_stop, bool drive_through);
+	void CP_PlaceRail_Tunnel(TileIndex tile, uint32 railtype);
+	void CP_PlaceRoad_Tunnel(TileIndex tile, uint8 roadtype);
+	void CP_Build_Bridge    (TileIndex start, TileIndex end, uint8 bridgetype, uint8 transport_type, uint8 rail_road_type);
+	void CP_PlaceRail_Depot (TileIndex tile, uint8 railtype, uint8 direction);
+	void CP_PlaceRoad_Depot (TileIndex tile, uint8 direction_type);
+	void CP_PlaceWaypoint   (TileIndex tile, uint8 waypoint_type);
+	void CP_ClearTile       (TileIndex start_tile, TileIndex end_tile);
+		
+	uint8 MirrorSignalDirection(uint8 direction);
+	DisallowedRoadDirections MirrorOneWayRoadDirection(DisallowedRoadDirections drd);
+	void SwapSignalInfo(uint index);
+	void PasteSignals(uint index, TileIndex tile);
+	void PasteLandscape(TileIndex tile);
+
+	void TerrainNeededAroundTile(TileIndex tindex, TileIndex bindex);
+	int8 ClampToRight(TileIndex index, int8 baseh, int8 h_tile);
+	int8 ClampToUp(TileIndex index, int8 baseh, int8 h_tile, int32 size_x);
+
+	FORCEINLINE void SetWidth(uint32 width)   { m_width  = width;  };
+	FORCEINLINE void SetHeight(uint32 height) { m_height = height; }; 
+};
+
+extern CopyPaste _copy_paste;
+
+#endif /* COPY_PASTE_H */
+
diff --git a/src/copy_paste_gui.cpp b/src/copy_paste_gui.cpp
new file mode 100644
--- /dev/null
+++ b/src/copy_paste_gui.cpp
@@ -0,0 +1,314 @@
+/* $Id: copy_paste_gui.cpp 4998 2006-05-28 07:45:14Z Frostregen $ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "gui.h"
+#include "window_gui.h"
+#include "viewport_type.h"
+#include "viewport_func.h"
+#include "gfx_func.h"
+#include "strings_type.h"
+#include "clear_func.h"
+#include "window_type.h"
+#include "window_func.h"
+#include "sound_type.h"
+#include "sound_func.h"
+#include "tilehighlight_type.h"
+#include "tilehighlight_func.h"
+#include "company_func.h"
+#include "tile_type.h"
+#include "rail_type.h"
+#include "rail_gui.h"
+#include "sprite.h"
+#include "fios.h"
+#include "copy_paste.h"
+#include "table/sprites.h"
+#include "table/strings.h"
+
+
+/** Current railtype. Used for autoconversion */
+static RailType _last_railtype = RAILTYPE_RAIL;
+
+/* **** GUI Code for Copy&Paste **** */
+
+/** Enum referring to the widgets of the copy paste window */
+enum CopyPasteWidgets {
+	CPW_CLOSEBOX = 0,
+	CPW_CAPTION,
+	CPW_STICKYBOX,
+	CPW_SPACER_1,
+	CPW_SPACER_2,
+	CPW_SPACER_3,
+	CPW_COPY,
+	CPW_PASTE,
+	CPW_LOAD,
+	CPW_SAVE,
+	CPW_ROTATE_LEFT,
+	CPW_ROTATE_RIGHT,
+	CPW_MIRROR_HORIZONTAL,
+	CPW_MIRROR_VERTICAL,
+	CPW_TERRAIN,
+	CPW_DYNAMITE,
+	CPW_RAIL,
+	CPW_ROAD,
+	CPW_REVERSE_SIGNALS,
+	CPW_CONVERT_RAILTYPE,
+	CPW_ONLY_OWN,
+
+	CPW_FIRST_CLICKABLE = CPW_COPY,
+	CPW_LAST_CLICKABLE = CPW_ONLY_OWN,
+};
+
+struct CopyPasteWindow : Window {
+int last_user_action; ///< Last started user action.
+public:
+	CopyPasteWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
+	{
+		this->InitNested(desc, window_number);
+		this->last_user_action = WIDGET_LIST_END;
+
+		/* Set the button states according to variable content */
+		if (_copy_paste.m_clear_before_build) this->LowerWidget(CPW_DYNAMITE);
+		if (_copy_paste.m_toggle_signal_direction) this->LowerWidget(CPW_REVERSE_SIGNALS);
+		if (_copy_paste.m_convert_rail)	  this->LowerWidget(CPW_CONVERT_RAILTYPE);
+		if (_copy_paste.m_copy_with_rail) this->LowerWidget(CPW_RAIL);
+		if (_copy_paste.m_copy_with_road) this->LowerWidget(CPW_ROAD);
+		if (_copy_paste.m_copy_with_other)this->LowerWidget(CPW_ONLY_OWN);
+	}
+
+	virtual void OnPaint()
+	{
+		SetWidgetsDisabledState(!_copy_paste.IsSomethingCopied(), CPW_PASTE, CPW_SAVE,
+				CPW_ROTATE_LEFT, CPW_ROTATE_RIGHT, CPW_MIRROR_HORIZONTAL, CPW_MIRROR_VERTICAL,
+				WIDGET_LIST_END);
+		/* Set image for tri-state button */
+		this->GetWidget<NWidgetCore>(CPW_TERRAIN)->widget_data = SPR_IMG_MINUS_TERRAIN + _copy_paste.m_paste_vacant_terrain;
+
+		this->DrawWidgets();
+
+		/* Draw CylinderGuy in CompanyColor, if unclicked */
+		if (!this->IsWidgetLowered(CPW_ONLY_OWN))
+			DrawSprite(SPR_IMG_ONLY_OWN, COMPANY_SPRITE_COLOUR(_current_company), this->GetWidget<NWidgetCore>(CPW_ONLY_OWN)->pos_x + 1, this->GetWidget<NWidgetCore>(CPW_ONLY_OWN)->pos_y + 1);
+	}
+
+	virtual void OnClick(Point pt, int widget, int click_count)
+	{
+		SetWidgetsDisabledState(!_copy_paste.IsSomethingCopied(), CPW_PASTE, CPW_SAVE,
+				CPW_ROTATE_LEFT, CPW_ROTATE_RIGHT, CPW_MIRROR_HORIZONTAL, CPW_MIRROR_VERTICAL,
+				WIDGET_LIST_END);
+		if (this->IsWidgetDisabled(widget)) return;
+		if ((widget >= CPW_FIRST_CLICKABLE) && (widget <= CPW_LAST_CLICKABLE)) {
+			if (widget != CPW_COPY && widget != CPW_PASTE && 
+				widget != CPW_DYNAMITE && widget != CPW_REVERSE_SIGNALS && 
+				widget != CPW_RAIL && widget !=  CPW_CONVERT_RAILTYPE && 
+				widget != CPW_ROAD && widget != CPW_ONLY_OWN) {
+				this->HandleButtonClick(widget);
+			}
+			SndPlayFx(SND_15_BEEP);
+			switch (widget) {
+				case CPW_COPY:
+					HandlePlacePushButton(this, CPW_COPY, SPR_CURSOR_COPY, HT_RECT);
+					this->last_user_action = widget;
+					break;
+
+				case CPW_PASTE:
+					HandlePlacePushButton(this, CPW_PASTE, SPR_CURSOR_PASTE, HT_PREVIEW);
+					this->last_user_action = widget;
+					break;
+
+				case CPW_LOAD:
+					_copy_paste.m_toggle_signal_direction = false;
+					/* fallthrough */
+
+				case CPW_SAVE:
+					ShowSaveLoadDialog(widget == CPW_SAVE ? SLD_SAVE_TEMPLATE : SLD_LOAD_TEMPLATE);
+					break;
+
+				case CPW_ROTATE_LEFT:
+				case CPW_ROTATE_RIGHT:
+					if (widget == CPW_ROTATE_LEFT)  _copy_paste.RotateSelectionCCW();
+					if (widget == CPW_ROTATE_RIGHT) _copy_paste.RotateSelectionCW();
+					break;
+
+				case CPW_MIRROR_HORIZONTAL:
+				case CPW_MIRROR_VERTICAL:
+					if (widget == CPW_MIRROR_HORIZONTAL) _copy_paste.MirrorSelectionHorizontal();
+					if (widget == CPW_MIRROR_VERTICAL)   _copy_paste.MirrorSelectionVertical();
+					
+					/* Toggle SignalDir */
+					this->OnClick(Point(), CPW_REVERSE_SIGNALS, 1);
+					break;
+
+				case CPW_TERRAIN:
+					_copy_paste.m_paste_vacant_terrain++;
+					if (_copy_paste.m_paste_vacant_terrain > 2) _copy_paste.m_paste_vacant_terrain = 0;
+					break;
+
+				case CPW_DYNAMITE: case CPW_REVERSE_SIGNALS:
+				case CPW_RAIL: case CPW_CONVERT_RAILTYPE:
+				case CPW_ROAD: case CPW_ONLY_OWN: {
+					this->SetDirty();
+					this->ToggleWidgetLoweredState(widget);
+					bool state = IsWidgetLowered(widget);
+					switch (widget) {
+						case CPW_DYNAMITE:	       _copy_paste.m_clear_before_build = state; break;
+						case CPW_RAIL:             _copy_paste.m_copy_with_rail = state; break;
+						case CPW_ROAD:             _copy_paste.m_copy_with_road = state; break;
+						case CPW_REVERSE_SIGNALS:  _copy_paste.m_toggle_signal_direction = state; break;
+						case CPW_CONVERT_RAILTYPE: _copy_paste.m_convert_rail = state; break;
+						case CPW_ONLY_OWN:         _copy_paste.m_copy_with_other = state; break;
+						default: NOT_REACHED();
+					}
+				} break;
+				default: break;
+			}
+
+			/* Set Selection size to Copy size */
+			if (this->IsWidgetLowered(CPW_PASTE)) {
+				if (_copy_paste.GetWidth() > 0)
+					SetTileSelectSize(_copy_paste.GetWidth() - 1, _copy_paste.GetHeight() - 1);
+			} else {
+				SetTileSelectSize(1, 1);
+			}
+		}
+	}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		switch (this->last_user_action) { 
+			case CPW_COPY:
+				VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_COPY_AREA);
+				VpSetPlaceSizingLimit(255);
+				break;
+
+			case CPW_PASTE:
+				_copy_paste.PasteArea(tile);
+				break;
+		}
+	}
+
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
+
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1) {
+			switch (select_proc) {
+				case DDSP_COPY_AREA:
+					_copy_paste.CopyArea(end_tile, start_tile);
+					/* Reset SignalDir */
+					if (_copy_paste.m_toggle_signal_direction) this->OnClick(Point(), CPW_REVERSE_SIGNALS, 1);
+					this->SetDirty();
+					break;
+				default:
+					break;
+			}
+		}
+	}
+
+	virtual void OnPlaceObjectAbort()
+	{
+		/* UnclickWindowButtons "copy" and "paste" */
+		this->RaiseWidget(CPW_COPY);
+		this->RaiseWidget(CPW_PASTE);
+
+		this->SetDirty();
+	}
+
+	virtual void OnTimeout()
+	{
+		this->RaiseWidget(CPW_LOAD);
+		this->RaiseWidget(CPW_SAVE);
+		this->RaiseWidget(CPW_ROTATE_LEFT);
+		this->RaiseWidget(CPW_ROTATE_RIGHT);
+		this->RaiseWidget(CPW_MIRROR_HORIZONTAL);
+		this->RaiseWidget(CPW_MIRROR_VERTICAL);
+		this->RaiseWidget(CPW_TERRAIN);
+		this->SetDirty();
+	}
+
+	virtual void OnTick()
+	{
+		/* If railtype has changed, we need to update our GUI */
+		if (_last_railtype != _cur_railtype) {
+			const RailtypeInfo *rti = GetRailTypeInfo(_cur_railtype);
+			_last_railtype = _cur_railtype;
+			this->GetWidget<NWidgetCore>(CPW_CONVERT_RAILTYPE)->widget_data = rti->gui_sprites.convert_rail;
+			this->SetDirty();
+		}
+	}
+};
+
+static const NWidgetPart _nested_copy_paste_widgets[] = {
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
+		NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_COPY_PASTE_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_COPY), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_COPY,              STR_COPY_PASTE_COPY_TOOLTIP),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_PASTE), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_PASTE,             STR_COPY_PASTE_PASTE_TOOLTIP),
+
+		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
+
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_LOAD), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_LOAD,              STR_COPY_PASTE_LOAD_TOOLTIP),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_SAVE), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_SAVE,              STR_COPY_PASTE_SAVE_TOOLTIP),
+
+		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
+
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_ROTATE_LEFT), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_ROTATE_LEFT,       STR_COPY_PASTE_ROTATE_LEFT_TOOLTIP),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_ROTATE_RIGHT), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_ROTATE_RIGHT,      STR_COPY_PASTE_ROTATE_RIGHT_TOOLTIP),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_MIRROR_HORIZONTAL), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_MIRROR_HORIZONTAL, STR_COPY_PASTE_MIRROR_HORIZONTAL_TOOLTIP),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_MIRROR_VERTICAL), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_MIRROR_VERTICAL,   STR_COPY_PASTE_MIRROR_VERTICAL_TOOLTIP),
+
+		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
+
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_TERRAIN), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_TERRAIN,     STR_COPY_PASTE_VACANT_TERRAIN_TOOLTIP),
+		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_DYNAMITE), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_DYNAMITE,    STR_COPY_PASTE_BULLDOZE_BEFORE_BUILD_TOOLTIP),
+		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_RAIL), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_NO_RAIL,           STR_COPY_PASTE_WITHOUT_RAIL_TOOLTIP),
+		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_ROAD), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_NO_ROAD,           STR_COPY_PASTE_WITHOUT_ROAD_TOOLTIP),
+		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_REVERSE_SIGNALS), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_SIGNAL,      STR_COPY_PASTE_TOGGLE_SIGNAL_DIRECTION_TOOLTIP),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_CONVERT_RAILTYPE), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_CONVERT_RAIL,      STR_COPY_PASTE_CONVERT_RAIL_TOOLTIP),
+		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_ONLY_OWN), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_ONLY_OWN,          STR_COPY_PASTE_ONLY_OWN_TOOLTIP),
+	EndContainer(),
+};
+
+static const WindowDesc _copy_paste_desc(
+	WDP_ALIGN_TOOLBAR, 0, 0,
+	WC_COPY_PASTE, WC_SCEN_LAND_GEN,
+	WDF_CONSTRUCTION,
+	_nested_copy_paste_widgets, lengthof(_nested_copy_paste_widgets)
+);
+
+void ShowCopyPasteToolbarGui() // When clicking the button in the terrain generation gui
+{
+	AllocateWindowDescFront<CopyPasteWindow>(&_copy_paste_desc, 0);
+}
+
+void ShowCopyPasteToolbar(int button) // When using a shortcut
+{
+	Window *w;
+	/* don't recreate the window if we're clicking on a button and the window exists. */
+	if (button < CPW_FIRST_CLICKABLE || !(w = FindWindowById(WC_COPY_PASTE, 0))) {
+		DeleteWindowByClass(WC_COPY_PASTE);
+		w = new CopyPasteWindow(&_copy_paste_desc, 0);
+	}
+	if (w != NULL) w->OnClick(Point(), button, 1);
+}
diff --git a/src/core/endian_type.hpp b/src/core/endian_type.hpp
--- a/src/core/endian_type.hpp
+++ b/src/core/endian_type.hpp
@@ -30,7 +30,7 @@
 	#define TTD_ENDIAN TTD_LITTLE_ENDIAN
 #elif !defined(TESTING)
 	/* Else include endian[target/host].h, which has the endian-type, autodetected by the Makefile */
-	#if defined(STRGEN) || defined(SETTINGSGEN)
+	#if defined(STRGEN)
 		#include "endian_host.h"
 	#else
 		#include "endian_target.h"
diff --git a/src/core/math_func.cpp b/src/core/math_func.cpp
--- a/src/core/math_func.cpp
+++ b/src/core/math_func.cpp
@@ -46,3 +46,24 @@
 	return a;
 
 }
+
+/**
+ * Deterministic approximate division.
+ * Cancels out division errors stemming from the integer nature of the division over multiple runs.
+ * @param a Dividend.
+ * @param b Divisor.
+ * @return a/b or (a/b)+1.
+ */
+int DivideApprox(int a, int b)
+{
+	int random_like = ((a + b) * (a - b)) % b;
+
+	int remainder = a % b;
+
+	int ret = a / b;
+	if (abs(random_like) < abs(remainder)) {
+		ret += ((a < 0) ^ (b < 0)) ? -1 : 1;
+	}
+
+	return ret;
+}
diff --git a/src/core/math_func.hpp b/src/core/math_func.hpp
--- a/src/core/math_func.hpp
+++ b/src/core/math_func.hpp
@@ -317,6 +317,7 @@
 
 int LeastCommonMultiple(int a, int b);
 int GreatestCommonDivisor(int a, int b);
+int DivideApprox(int a, int b);
 
 /**
  * Computes ceil(a / b) for non-negative a and b.
diff --git a/src/core/multimap.hpp b/src/core/multimap.hpp
new file mode 100644
--- /dev/null
+++ b/src/core/multimap.hpp
@@ -0,0 +1,249 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file multimap.hpp Multimap with deterministic ordering of items with equal keys. */
+
+#ifndef MULTIMAP_HPP_
+#define MULTIMAP_HPP_
+
+#include <map>
+#include <list>
+
+template<typename KEY, typename VALUE, typename COMPARE>
+class MultiMap;
+
+template<class MAP_ITER, class LIST_ITER, class KEY, class VALUE, class COMPARE>
+class MultiMapIterator {
+protected:
+	friend class MultiMap<KEY, VALUE, COMPARE>;
+	typedef MultiMapIterator<MAP_ITER, LIST_ITER, KEY, VALUE, COMPARE> Self;
+	LIST_ITER list_iter;
+	MAP_ITER map_iter;
+	bool list_valid;
+
+public:
+	MultiMapIterator() : list_valid(false) {}
+	template<class NONCONST>
+	MultiMapIterator(NONCONST mi) : map_iter(mi), list_valid(false) {}
+	MultiMapIterator(MAP_ITER mi, LIST_ITER li) : list_iter(li), map_iter(mi)
+	{
+		list_valid = (list_iter != map_iter->second.begin());
+	}
+
+	template<class NONCONST>
+	Self &operator=(NONCONST mi)
+	{
+		map_iter = mi;
+		list_valid = false;
+	}
+
+	VALUE &operator*() const
+	{
+		assert(!map_iter->second.empty());
+		if (list_valid) {
+			return list_iter.operator*();
+		} else {
+			return map_iter->second.begin().operator*();
+		}
+	}
+
+	VALUE *operator->() const
+	{
+		assert(!map_iter->second.empty());
+		if (list_valid) {
+			return list_iter.operator->();
+		} else {
+			return map_iter->second.begin().operator->();
+		}
+	}
+
+	FORCEINLINE const MAP_ITER &GetMapIter() const {return map_iter;}
+	FORCEINLINE const LIST_ITER &GetListIter() const {return list_iter;}
+	FORCEINLINE bool ListValid() const {return list_valid;}
+
+	const KEY &GetKey() const {return map_iter->first;}
+
+	Self &operator++()
+	{
+		assert(!map_iter->second.empty());
+		if (list_valid) {
+			if(++list_iter == map_iter->second.end()) {
+				++map_iter;
+				list_valid = false;
+			}
+		} else {
+			list_iter = ++(map_iter->second.begin());
+			if (list_iter == map_iter->second.end()) {
+				++map_iter;
+			} else {
+				list_valid = true;
+			}
+		}
+		return *this;
+	}
+
+	Self operator++(int)
+	{
+		Self tmp = *this;
+		this->operator++();
+		return tmp;
+	}
+
+	Self &operator--()
+	{
+		assert(!map_iter->second.empty());
+		if (!list_valid) {
+			--map_iter;
+			list_iter = map_iter->second.end();
+			assert(!map_iter->second.empty());
+		}
+
+		if(--list_iter == map_iter->second.begin()) {
+			list_valid = false;
+		} else {
+			list_valid = true;
+		}
+
+		return *this;
+	}
+
+	Self operator--(int)
+	{
+		Self tmp = *this;
+		this->operator--();
+		return tmp;
+	}
+};
+
+/* generic comparison functions for const/non-const multimap iterators and map iterators */
+
+template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class LIST_ITER2, class KEY, class VALUE1, class VALUE2, class COMPARE>
+bool operator==(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE1, COMPARE> &iter1, const MultiMapIterator<MAP_ITER2, LIST_ITER2, KEY, VALUE2, COMPARE> &iter2)
+{
+	if (iter1.ListValid()) {
+		if (!iter2.ListValid()) {
+			return false;
+		} else if (iter1.GetListIter() != iter2.GetListIter()) {
+			return false;
+		}
+	} else if (iter2.ListValid()) {
+		return false;
+	}
+	return (iter1.GetMapIter() == iter2.GetMapIter());
+}
+
+template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class LIST_ITER2, class KEY, class VALUE1, class VALUE2, class COMPARE>
+bool operator!=(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE1, COMPARE> &iter1, const MultiMapIterator<MAP_ITER2, LIST_ITER2, KEY, VALUE2, COMPARE> &iter2)
+{
+	return !(iter1 == iter2);
+}
+
+template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
+bool operator==(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1, const MAP_ITER2 &iter2)
+{
+	return !iter1.ListValid() && iter1.GetMapIter() == iter2;
+}
+
+template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
+bool operator!=(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1, const MAP_ITER2 &iter2)
+{
+	return iter1.ListValid() || iter1.GetMapIter() != iter2;
+}
+
+template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
+bool operator==(const MAP_ITER2 &iter2, const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1)
+{
+	return !iter1.ListValid() && iter1.GetMapIter() == iter2;
+}
+
+template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
+bool operator!=(const MAP_ITER2 &iter2, const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1)
+{
+	return iter1.ListValid() || iter1.GetMapIter() != iter2;
+}
+
+
+/**
+ * hand-rolled multimap as map of lists. behaves mostly like a list, but is sorted
+ * by KEY.
+ */
+template<typename KEY, typename VALUE, typename COMPARE = std::less<KEY> >
+class MultiMap : public std::map<KEY, std::list<VALUE>, COMPARE > {
+public:
+	typedef typename std::list<VALUE> List;
+	typedef typename List::iterator ListIterator;
+	typedef typename List::const_iterator ConstListIterator;
+
+	typedef typename std::map<KEY, List, COMPARE > Map;
+	typedef typename Map::iterator MapIterator;
+	typedef typename Map::const_iterator ConstMapIterator;
+
+	typedef MultiMapIterator<MapIterator, ListIterator, KEY, VALUE, COMPARE> iterator;
+	typedef MultiMapIterator<ConstMapIterator, ConstListIterator, KEY, const VALUE, COMPARE> const_iterator;
+
+	void erase(iterator it)
+	{
+		List &list = it.map_iter->second;
+		assert(!list.empty());
+		if (it.ListValid()) {
+			list.erase(it.list_iter);
+		} else {
+			list.erase(list.begin());
+		}
+
+		if (list.empty()) {
+			Map::erase(it.map_iter);
+		}
+	}
+
+	void Insert(const KEY &key, const VALUE &val)
+	{
+		List &list = (*this)[key];
+		list.push_back(val);
+		assert(!list.empty());
+	}
+
+	size_t size() const
+	{
+		size_t ret = 0;
+		for(ConstMapIterator it = Map::begin(); it != Map::end(); ++it) {
+			ret += it->second.size();
+		}
+		return ret;
+	}
+
+	size_t MapSize() const
+	{
+		return Map::size();
+	}
+
+	std::pair<iterator, iterator> equal_range(const KEY &key)
+	{
+		MapIterator begin(lower_bound(key));
+		if (begin != Map::end() && begin->first == key) {
+			MapIterator end = begin;
+			return std::make_pair(begin, ++end);
+		} else {
+			return std::make_pair(begin, begin);
+		}
+	}
+
+	std::pair<const_iterator, const_iterator> equal_range(const KEY &key) const
+	{
+		ConstMapIterator begin(lower_bound(key));
+		if (begin != Map::end() && begin->first == key) {
+			ConstMapIterator end = begin;
+			return std::make_pair(begin, ++end);
+		} else {
+			return std::make_pair(begin, begin);
+		}
+	}
+};
+
+#endif /* MULTIMAP_HPP_ */
diff --git a/src/core/overflowsafe_type.hpp b/src/core/overflowsafe_type.hpp
--- a/src/core/overflowsafe_type.hpp
+++ b/src/core/overflowsafe_type.hpp
@@ -96,6 +96,7 @@
 	FORCEINLINE OverflowSafeInt  operator /  (const OverflowSafeInt& divisor) const { OverflowSafeInt result = *this; result /= divisor.m_value; return result; }
 	FORCEINLINE OverflowSafeInt  operator /  (const int              divisor) const { OverflowSafeInt result = *this; result /= divisor; return result; }
 	FORCEINLINE OverflowSafeInt  operator /  (const uint             divisor) const { OverflowSafeInt result = *this; result /= (int)divisor; return result; }
+	FORCEINLINE OverflowSafeInt  operator /  (const uint8            divisor) const { OverflowSafeInt result = *this; result /= (int16)divisor; return result; }
 
 	/* Operators for modulo */
 	FORCEINLINE OverflowSafeInt& operator %= (const int  divisor)       { this->m_value %= divisor; return *this; }
diff --git a/src/date.cpp b/src/date.cpp
--- a/src/date.cpp
+++ b/src/date.cpp
@@ -25,6 +25,7 @@
 Date      _date;       ///< Current date in days (day counter)
 DateFract _date_fract; ///< Fractional part of the day.
 uint16 _tick_counter;  ///< Ever incrementing (and sometimes wrapping) tick counter for setting off various events
+uint8     _date_daylength_factor;	///< Setting for DAY_LENGTH
 
 /**
  * Set the date.
@@ -175,8 +176,10 @@
 
 
 /** Available settings for autosave intervals. */
-static const Month _autosave_months[] = {
+static const int _autosave_intervals[] = {
 	 0, ///< never
+	 1, ///< every day
+	 7, ///< every week
 	 1, ///< every month
 	 3, ///< every 3 months
 	 6, ///< every 6 months
@@ -226,7 +229,7 @@
  */
 static void OnNewMonth()
 {
-	if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
+	if (_settings_client.gui.autosave >= 3 && (_cur_month % _autosave_intervals[_settings_client.gui.autosave]) == 0) {
 		_do_autosave = true;
 		SetWindowDirty(WC_STATUS_BAR, 0);
 	}
@@ -248,6 +251,12 @@
  */
 static void OnNewDay()
 {
+	// XXX: use day-of-month?
+	if (_settings_client.gui.autosave != 0 && _settings_client.gui.autosave <= 2 && (_date % _autosave_intervals[_settings_client.gui.autosave]) == 0) {
+		_do_autosave = true;
+		SetWindowDirty(WC_STATUS_BAR, 0);
+	}
+
 #ifdef ENABLE_NETWORK
 	if (_network_server) NetworkServerDailyLoop();
 #endif /* ENABLE_NETWORK */
diff --git a/src/date_func.h b/src/date_func.h
--- a/src/date_func.h
+++ b/src/date_func.h
@@ -24,6 +24,8 @@
 void ConvertDateToYMD(Date date, YearMonthDay *ymd);
 Date ConvertYMDToDate(Year year, Month month, Day day);
 
+#define YMD_TO_DATE(ymd) (ConvertYMDToDate(ymd.year, ymd.month, ymd.day))
+
 /**
  * Checks whether the given year is a leap year or not.
  * @param yr The year to check.
diff --git a/src/date_gui.cpp b/src/date_gui.cpp
--- a/src/date_gui.cpp
+++ b/src/date_gui.cpp
@@ -16,6 +16,7 @@
 #include "window_gui.h"
 #include "date_gui.h"
 #include "core/geometry_func.hpp"
+#include "settings_type.h"
 
 #include "widgets/dropdown_type.h"
 
@@ -71,7 +72,7 @@
 	 * Helper function to construct the dropdown.
 	 * @param widget the dropdown widget to create the dropdown for
 	 */
-	void ShowDateDropDown(int widget)
+	virtual void ShowDateDropDown(int widget)
 	{
 		int selected;
 		DropDownList *list = new DropDownList();
@@ -156,7 +157,7 @@
 				break;
 
 			case SDW_SET_DATE:
-				if (this->callback != NULL) this->callback(this->parent, ConvertYMDToDate(this->date.year, this->date.month, this->date.day));
+				if (this->callback != NULL) this->callback(this->parent, ConvertYMDToDate(this->date.year, this->date.month, this->date.day) * DAY_TICKS);
 				delete this;
 				break;
 		}
@@ -181,6 +182,121 @@
 	}
 };
 
+struct SetMinutesWindow : SetDateWindow
+{
+	Minutes minutes;
+
+	/** Constructor. */
+	SetMinutesWindow(const WindowDesc *desc, WindowNumber window_number, Window *parent, DateTicks initial_date, Year min_year, Year max_year, SetDateCallback *callback) :
+			SetDateWindow(desc, window_number, parent, initial_date, min_year, max_year, callback),
+			minutes(initial_date / _settings_client.gui.ticks_per_minute)
+	{
+	}
+
+	/**
+	 * Helper function to construct the dropdown.
+	 * @param widget the dropdown widget to create the dropdown for
+	 */
+	virtual void ShowDateDropDown(int widget)
+	{
+		int selected;
+		DropDownList *list = new DropDownList();
+
+		switch (widget) {
+			default: NOT_REACHED();
+
+			case SDW_DAY:
+				for (uint i = 0; i < 60; i++) {
+					DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false);
+					item->SetParam(0, i);
+					list->push_back(item);
+				}
+				selected = MINUTES_MINUTE(minutes);
+				break;
+
+			case SDW_MONTH:
+				for (uint i = 0; i < 24; i++) {
+					DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false);
+					item->SetParam(0, i);
+					list->push_back(item);
+				}
+				selected = MINUTES_HOUR(minutes);
+				break;
+		}
+
+		ShowDropDownList(this, list, selected, widget);
+	}
+
+	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
+	{
+		Dimension d = {0, 0};
+		switch (widget) {
+			default: return;
+
+			case SDW_DAY:
+				for (uint i = 0; i < 60; i++) {
+					SetDParam(0, i);
+					d = maxdim(d, GetStringBoundingBox(STR_JUST_INT));
+				}
+				break;
+
+			case SDW_MONTH:
+				for (uint i = 0; i < 24; i++) {
+					SetDParam(0, i);
+					d = maxdim(d, GetStringBoundingBox(STR_JUST_INT));
+				}
+				break;
+		}
+
+		d.width += padding.width;
+		d.height += padding.height;
+		*size = d;
+	}
+
+	virtual void SetStringParameters(int widget) const
+	{
+		switch (widget) {
+			case SDW_DAY:   SetDParam(0, MINUTES_MINUTE(minutes)); break;
+			case SDW_MONTH: SetDParam(0, MINUTES_HOUR(minutes)); break;
+		}
+	}
+
+	virtual void OnClick(Point pt, int widget, int click_count)
+	{
+		switch (widget) {
+			case SDW_DAY:
+			case SDW_MONTH:
+			case SDW_YEAR:
+				ShowDateDropDown(widget);
+				break;
+
+			case SDW_SET_DATE:
+				if (this->callback != NULL) this->callback(this->parent, (DateTicks)minutes * _settings_client.gui.ticks_per_minute);
+				delete this;
+				break;
+		}
+	}
+
+	virtual void OnDropdownSelect(int widget, int index)
+	{
+		Minutes current = 0;
+		switch (widget) {
+			case SDW_DAY:
+				current = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), MINUTES_HOUR(minutes), index);
+				break;
+
+			case SDW_MONTH:
+				current = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), index, MINUTES_MINUTE(minutes));
+				break;
+		}
+
+		if (current < (CURRENT_MINUTE - 60)) current += 60 * 24;
+		minutes = current;
+
+		this->SetDirty();
+	}
+};
+
 /** Widgets for the date setting window. */
 static const NWidgetPart _nested_set_date_widgets[] = {
 	NWidget(NWID_HORIZONTAL),
@@ -203,6 +319,26 @@
 	EndContainer()
 };
 
+static const NWidgetPart _nested_set_minutes_widgets[] = {
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
+		NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_DATE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+	EndContainer(),
+	NWidget(WWT_PANEL, COLOUR_BROWN),
+		NWidget(NWID_VERTICAL), SetPIP(6, 6, 6),
+			NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(6, 6, 6),
+				NWidget(WWT_DROPDOWN, COLOUR_ORANGE, SDW_MONTH), SetFill(1, 0), SetDataTip(STR_JUST_INT, STR_DATE_MINUTES_MONTH_TOOLTIP),
+				NWidget(WWT_DROPDOWN, COLOUR_ORANGE, SDW_DAY), SetFill(1, 0), SetDataTip(STR_JUST_INT, STR_DATE_MINUTES_DAY_TOOLTIP),
+			EndContainer(),
+			NWidget(NWID_HORIZONTAL),
+				NWidget(NWID_SPACER), SetFill(1, 0),
+				NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, SDW_SET_DATE), SetMinimalSize(100, 12), SetDataTip(STR_DATE_SET_DATE, STR_DATE_SET_DATE_TOOLTIP),
+				NWidget(NWID_SPACER), SetFill(1, 0),
+			EndContainer(),
+		EndContainer(),
+	EndContainer()
+};
+
 /** Description of the date setting window. */
 static const WindowDesc _set_date_desc(
 	WDP_CENTER, 0, 0,
@@ -211,6 +347,13 @@
 	_nested_set_date_widgets, lengthof(_nested_set_date_widgets)
 );
 
+static const WindowDesc _set_minutes_desc(
+	WDP_CENTER, 0, 0,
+	WC_SET_DATE, WC_NONE,
+	WDF_UNCLICK_BUTTONS,
+	_nested_set_minutes_widgets, lengthof(_nested_set_minutes_widgets)
+);
+
 /**
  * Create the new 'set date' window
  * @param window_number number for the window
@@ -220,8 +363,13 @@
  * @param max_year the maximum year (inclusive) to show in the year dropdown
  * @param callback the callback to call once a date has been selected
  */
-void ShowSetDateWindow(Window *parent, int window_number, Date initial_date, Year min_year, Year max_year, SetDateCallback *callback)
+void ShowSetDateWindow(Window *parent, int window_number, DateTicks initial_date, Year min_year, Year max_year, SetDateCallback *callback)
 {
 	DeleteWindowByClass(WC_SET_DATE);
-	new SetDateWindow(&_set_date_desc, window_number, parent, initial_date, min_year, max_year, callback);
+
+	if (!_settings_client.gui.time_in_minutes) {
+		new SetDateWindow(&_set_date_desc, window_number, parent, initial_date / DAY_TICKS, min_year, max_year, callback);
+	} else {
+		new SetMinutesWindow(&_set_minutes_desc, window_number, parent, initial_date, min_year, max_year, callback);
+	}
 }
diff --git a/src/date_gui.h b/src/date_gui.h
--- a/src/date_gui.h
+++ b/src/date_gui.h
@@ -20,8 +20,8 @@
  * @param w the window that sends the callback
  * @param date the date that has been chosen
  */
-typedef void SetDateCallback(const Window *w, Date date);
+typedef void SetDateCallback(const Window *w, DateTicks date);
 
-void ShowSetDateWindow(Window *parent, int window_number, Date initial_date, Year min_year, Year max_year, SetDateCallback *callback);
+void ShowSetDateWindow(Window *parent, int window_number, DateTicks initial_date, Year min_year, Year max_year, SetDateCallback *callback);
 
 #endif /* DATE_GUI_H */
diff --git a/src/date_type.h b/src/date_type.h
--- a/src/date_type.h
+++ b/src/date_type.h
@@ -16,6 +16,8 @@
 typedef int32  Date;      ///< The type to store our dates in
 typedef uint16 DateFract; ///< The fraction of a date we're in, i.e. the number of ticks since the last date changeover
 typedef int32  Ticks;     ///< The type to store ticks in
+typedef int64 DateTicks;  ///< The type to store dates in when tick-precision is required
+typedef int32  Minutes;   ///< The type to store minutes in
 
 typedef int32  Year;  ///< Type for the year, note: 0 based, i.e. starts at the year 0.
 typedef uint8  Month; ///< Type for the month, note: 0 based, i.e. 0 = January, 11 = December.
@@ -27,17 +29,29 @@
  * 1 tick is approximately 30 ms.
  * 1 day is thus about 2 seconds (74 * 30 = 2220) on a machine that can run OpenTTD normally
  */
-static const int DAY_TICKS         =  74; ///< ticks per day
+static const int ORIG_DAY_TICKS    =  74; ///< unscaled ticks per day
 static const int DAYS_IN_YEAR      = 365; ///< days per year
 static const int DAYS_IN_LEAP_YEAR = 366; ///< sometimes, you need one day more...
 
+/**
+ * Scale factor for DAY_TICKS
+ */
+extern uint8 _date_daylength_factor;
+
+/**
+ * Day length in ticks, calculated using a configureable scale factor.
+ */
+#define DAY_TICKS (ORIG_DAY_TICKS * _date_daylength_factor)
+
+#define DATE_UNIT_SIZE (_settings_client.gui.time_in_minutes ? _settings_client.gui.ticks_per_minute : DAY_TICKS)
+
 static const int STATION_RATING_TICKS     = 185; ///< cycle duration for updating station rating
 static const int STATION_ACCEPTANCE_TICKS = 250; ///< cycle duration for updating station acceptance
 static const int CARGO_AGING_TICKS        = 185; ///< cycle duration for aging cargo
 static const int INDUSTRY_PRODUCE_TICKS   = 256; ///< cycle duration for industry production
-static const int TOWN_GROWTH_TICKS        = 70;  ///< cycle duration for towns trying to grow. (this originates from the size of the town array in TTD
 static const int INDUSTRY_CUT_TREE_TICKS  = INDUSTRY_PRODUCE_TICKS * 2; ///< cycle duration for lumber mill's extra action
 
+#define TOWN_GROWTH_TICKS (70 * _date_daylength_factor)  ///< cycle duration for towns trying to grow. (this originates from the size of the town array in TTD
 
 /*
  * ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR and DAYS_TILL_ORIGINAL_BASE_YEAR are
@@ -95,6 +109,21 @@
 /** The number of days till the last day */
 #define MAX_DAY (DAYS_TILL(MAX_YEAR + 1) - 1)
 
+/** The day when converting to minutes */
+#define MINUTES_DAY(minutes) (minutes / 1440)
+
+/** The hour when converting to minutes */
+#define MINUTES_HOUR(minutes) ((minutes / 60) % 24)
+
+/** The day when converting to minutes */
+#define MINUTES_MINUTE(minutes) (minutes % 60)
+
+/** Convert minutes to a date */
+#define MINUTES_DATE(day, hour, minute) ((day * 1440) + (hour * 60) + minute)
+
+/** Get the current date in minutes */
+#define CURRENT_MINUTE ((((DateTicks)_date * DAY_TICKS) + _date_fract) / _settings_client.gui.ticks_per_minute)
+
 /**
  * Data structure to convert between Date and triplet (year, month, and day).
  * @see ConvertDateToYMD(), ConvertYMDToDate()
diff --git a/src/departures.cpp b/src/departures.cpp
new file mode 100644
--- /dev/null
+++ b/src/departures.cpp
@@ -0,0 +1,590 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file departures.cpp Scheduled departures from a station. */
+
+#include "stdafx.h"
+#include "debug.h"
+#include "gui.h"
+#include "textbuf_gui.h"
+#include "strings_func.h"
+#include "window_func.h"
+#include "vehicle_func.h"
+#include "string_func.h"
+#include "window_gui.h"
+#include "timetable.h"
+#include "vehiclelist.h"
+#include "company_base.h"
+#include "date_func.h"
+#include "departures_gui.h"
+#include "station_base.h"
+#include "vehicle_gui_base.h"
+#include "vehicle_base.h"
+#include "vehicle_gui.h"
+#include "order_base.h"
+#include "settings_type.h"
+#include "core/smallvec_type.hpp"
+#include "date_type.h"
+#include "company_type.h"
+#include "cargo_type.h"
+#include "departures_func.h"
+#include "departures_type.h"
+
+/** A scheduled order. */
+typedef struct OrderDate
+{
+	const Order *order;      ///< The order
+	const Vehicle *v;        ///< The vehicle carrying out the order
+	DateTicks expected_date; ///< The date on which the order is expected to complete
+	Ticks lateness;          ///< How late this order is expected to finish
+	DepartureStatus status;  ///< Whether the vehicle has arrived to carry out the order yet
+} OrderDate;
+
+static FORCEINLINE bool IsDeparture(const Order *order, StationID station) {
+	return (order->GetType() == OT_GOTO_STATION &&
+			(StationID)order->GetDestination() == station &&
+			(order->GetLoadType() != OLFB_NO_LOAD ||
+			_settings_client.gui.departure_show_all_stops) &&
+			order->wait_time != 0);
+}
+
+static FORCEINLINE bool IsVia(const Order *order, StationID station) {
+	return ((order->GetType() == OT_GOTO_STATION ||
+			order->GetType() == OT_GOTO_WAYPOINT) &&
+			(StationID)order->GetDestination() == station &&
+			(order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
+			order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION));
+}
+
+static FORCEINLINE bool IsArrival(const Order *order, StationID station) {
+	return (order->GetType() == OT_GOTO_STATION &&
+			(StationID)order->GetDestination() == station &&
+			(order->GetUnloadType() != OUFB_NO_UNLOAD ||
+			_settings_client.gui.departure_show_all_stops) &&
+			order->wait_time != 0);
+}
+
+/**
+ * Compute an up-to-date list of departures for a station.
+ * @param station the station to compute the departures of
+ * @param show_vehicle_types the types of vehicles to include in the departure list
+ * @param type the type of departures to get (departures or arrivals)
+ * @param show_vehicles_via whether to include vehicles that have this station in their orders but do not stop at it
+ * @return a list of departures, which is empty if an error occurred
+ */
+DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], DepartureType type, bool show_vehicles_via)
+{
+	/* This function is the meat of the departure boards functionality. */
+	/* As an overview, it works by repeatedly considering the best possible next departure to show. */
+	/* By best possible we mean the one expected to arrive at the station first. */
+	/* However, we do not consider departures whose scheduled time is too far in the future, even if they are expected before some delayed ones. */
+	/* This code can probably be made more efficient. I haven't done so in order to keep both its (relative) simplicity and my (relative) sanity. */
+	/* Having written that, it's not exactly slow at the moment. */
+
+	/* The list of departures which will be returned as a result. */
+	SmallVector<Departure*, 32> *result = new SmallVector<Departure*, 32>();
+
+	/* A list of the next scheduled orders to be considered for inclusion in the departure list. */
+	SmallVector<OrderDate*, 32> next_orders;
+
+	/* The maximum possible date for departures to be scheduled to occur. */
+	DateTicks max_date = _settings_client.gui.max_departure_time * DAY_TICKS;
+
+	/* The scheduled order in next_orders with the earliest expected_date field. */
+	OrderDate *least_order = NULL;
+
+	/* Get all the vehicles stopping at this station. */
+	/* We do this to get the order which is the first time they will stop at this station. */
+	/* This order is stored along with some more information. */
+	/* We keep a pointer to the `least' order (the one with the soonest expected completion time). */
+	for (uint i = 0; i < 4; ++i) {
+		VehicleList vehicles;
+
+		if (!show_vehicle_types[i]) {
+			/* Don't show vehicles whose type we're not interested in. */
+			continue;
+		}
+
+        /* MAX_COMPANIES is probably the wrong thing to put here, but it works. GenerateVehicleSortList doesn't check the company when the type of list is VL_STATION_LIST (r20801). */
+		if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station).Pack())) {
+			/* Something went wrong: panic! */
+			return result;
+		}
+
+		/* Get the first order for each vehicle for the station we're interested in that doesn't have No Loading set. */
+		/* We find the least order while we're at it. */
+		for (const Vehicle **v = vehicles.Begin(); v != vehicles.End(); v++) {
+			if (_settings_client.gui.departure_only_passengers) {
+				bool carries_passengers = false;
+
+				const Vehicle *u = *v;
+				while (u != NULL) {
+					if (u->cargo_type == CT_PASSENGERS) {
+						carries_passengers = true;
+						break;
+					}
+					u = u->Next();
+				}
+
+				if (carries_passengers == false) {
+					continue;
+				}
+			}
+
+			const Order *order = (*v)->GetOrder((*v)->cur_implicit_order_index % (*v)->GetNumOrders());
+			DateTicks start_date = (DateTicks)_date_fract - (*v)->current_order_time;
+			DepartureStatus status = D_TRAVELLING;
+
+			/* If the vehicle is stopped in a depot, ignore it. */
+			if ((*v)->IsStoppedInDepot()) {
+				continue;
+			}
+
+			/* If the vehicle is heading for a depot to stop there, then its departures are cancelled. */
+			if ((*v)->current_order.IsType(OT_GOTO_DEPOT) && (*v)->current_order.GetDepotActionType() & ODATFB_HALT) {
+				status = D_CANCELLED;
+			}
+
+			if ((*v)->current_order.IsType(OT_LOADING)) {
+				/* Account for the vehicle having reached the current order and being in the loading phase. */
+				status = D_ARRIVED;
+				start_date -= order->travel_time + (((*v)->lateness_counter < 0) ? (*v)->lateness_counter : 0);
+			}
+
+			/* Loop through the vehicle's orders until we've found a suitable order or we've determined that no such order exists. */
+			/* We only need to consider each order at most once. */
+			bool foundOrder = false;
+			for (int i = (*v)->GetNumOrders(); i > 0; --i) {
+				start_date += order->travel_time + order->wait_time;
+
+				/* If the scheduled departure date is too far in the future, stop. */
+				if (start_date - (*v)->lateness_counter > max_date) {
+					break;
+				}
+
+				/* If the order is a conditional branch, handle it. */
+				if (order->IsType(OT_CONDITIONAL)) {
+					switch(_settings_client.gui.departure_conditionals) {
+							case 0: {
+								/* Give up */
+								break;
+							}
+							case 1: {
+								/* Take the branch */
+								if (status != D_CANCELLED) {
+									status = D_TRAVELLING;
+								}
+								order = (*v)->GetOrder(order->GetConditionSkipToOrder());
+								if (order == NULL) {
+									break;
+								}
+
+								start_date -= order->travel_time;
+
+								continue;
+							}
+							case 2: {
+								/* Do not take the branch */
+								if (status != D_CANCELLED) {
+									status = D_TRAVELLING;
+								}
+								order = (order->next == NULL) ? (*v)->GetFirstOrder() : order->next;
+								continue;
+							}
+					}
+				}
+
+				/* If an order doesn't have a travel time set, then stop. */
+				if (order->travel_time == 0) {
+					break;
+				}
+
+				/* Skip it if it's an implicit order. */
+				if (order->IsType(OT_IMPLICIT)) {
+					order = (order->next == NULL) ? (*v)->GetFirstOrder() : order->next;
+					continue;
+				}
+
+				/* If the vehicle will be stopping at and loading from this station, and its wait time is not zero, then it is a departure.
+				 * If the vehicle will be stopping at and unloading at this station, and its wait time is not zero, then it is an arrival. */
+				if ((type == D_DEPARTURE && IsDeparture(order, station)) ||
+						(type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
+						(type == D_ARRIVAL && IsArrival(order, station))) {
+					/* If the departure was scheduled to have already begun and has been cancelled, do not show it. */
+					if (start_date < 0 && status == D_CANCELLED) {
+						break;
+					}
+
+					OrderDate *od = new OrderDate();
+					od->order = order;
+					od->v = *v;
+					/* We store the expected date for now, so that vehicles will be shown in order of expected time. */
+					od->expected_date = start_date;
+					od->lateness = (*v)->lateness_counter > 0 ? (*v)->lateness_counter : 0;
+					od->status = status;
+
+					/* If we are early, use the scheduled date as the expected date. We also take lateness to be zero. */
+					if ((*v)->lateness_counter < 0 && !(*v)->current_order.IsType(OT_LOADING)) {
+						od->expected_date -= (*v)->lateness_counter;
+					}
+
+					/* Update least_order if this is the current least order. */
+					if (least_order == NULL) {
+						least_order = od;
+					} else if (least_order->expected_date - least_order->lateness - (type == D_ARRIVAL ? least_order->order->wait_time : 0) > od->expected_date - od->lateness - (type == D_ARRIVAL ? od->order->wait_time : 0)) {
+						least_order = od;
+					}
+
+					*(next_orders.Append(1)) = od;
+
+					foundOrder = true;
+					/* We're done with this vehicle. */
+					break;
+				} else {
+					/* Go to the next order in the list. */
+					if (status != D_CANCELLED) {
+						status = D_TRAVELLING;
+					}
+					order = (order->next == NULL) ? (*v)->GetFirstOrder() : order->next;
+				}
+			}
+		}
+	}
+
+	/* No suitable orders found? Then stop. */
+	if (next_orders.Length() == 0) {
+		return result;
+	}
+
+	/* We now find as many departures as we can. It's a little involved so I'll try to explain each major step. */
+	/* The countdown from 10000 is a safeguard just in case something nasty happens. 10000 seemed large enough. */
+	for(int i = 10000; i > 0; --i) {
+		/* I should probably try to convince you that this loop always terminates regardless of the safeguard. */
+		/* 1. next_orders contains at least one element. */
+		/* 2. The loop terminates if result->Length() exceeds a fixed (for this loop) value, or if the least order's scheduled date is later than max_date. */
+		/*    (We ignore the case that the least order's scheduled date has overflown, as it is a relative rather than absolute date.) */
+		/* 3. Every time we loop round, either result->Length() will have increased -OR- we will have increased the expected_date of one of the elements of next_orders. */
+		/* 4. Therefore the loop must eventually terminate. */
+
+		/* least_order is the best candidate for the next departure. */
+
+		/* First, we check if we can stop looking for departures yet. */
+		if (result->Length() >= _settings_client.gui.max_departures ||
+				least_order->expected_date - least_order->lateness > max_date) {
+			break;
+		}
+
+		/* We already know the least order and that it's a suitable departure, so make it into a departure. */
+		Departure *d = new Departure();
+		d->scheduled_date = (DateTicks)_date * DAY_TICKS + least_order->expected_date - least_order->lateness;
+		d->lateness = least_order->lateness;
+		d->status = least_order->status;
+		d->vehicle = least_order->v;
+		d->type = type;
+		d->order = least_order->order;
+
+		/* We'll be going through the order list later, so we need a separate variable for it. */
+		const Order *order = least_order->order;
+
+		if (type == D_DEPARTURE) {
+			/* Computing departures: */
+			/* We want to find out where it will terminate, making a list of the stations it calls at along the way. */
+			/* We only count stations where unloading happens as being called at - i.e. pickup-only stations are ignored. */
+			/* Where the vehicle terminates is defined as the last unique station called at by the vehicle from the current order. */
+
+			/* If the vehicle loops round to the current order without a terminus being found, then it terminates upon reaching its current order again. */
+
+			/* We also determine which station this departure is going via, if any. */
+			/* A departure goes via a station if it is the first station for which the vehicle has an order to go via or non-stop via. */
+			/* Multiple departures on the same journey may go via different stations. That a departure can go via at most one station is intentional. */
+
+			/* We keep track of potential via stations along the way. If we call at a station immediately after going via it, then it is the via station. */
+			StationID candidate_via = INVALID_STATION;
+
+			/* Go through the order list, looping if necessary, to find a terminus. */
+			/* Get the next order, which may be the vehicle's first order. */
+			order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+			/* We only need to consider each order at most once. */
+			bool found_terminus = false;
+			for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
+				/* If we reach the order at which the departure occurs again, then use the departure station as the terminus. */
+				if (order == least_order->order) {
+					/* If we're not calling anywhere, then skip this departure. */
+					found_terminus = (d->calling_at.Length() > 0);
+					break;
+				}
+
+				/* If the order is a conditional branch, handle it. */
+				if (order->IsType(OT_CONDITIONAL)) {
+					switch(_settings_client.gui.departure_conditionals) {
+							case 0: {
+								/* Give up */
+								break;
+							}
+							case 1: {
+								/* Take the branch */
+								order = least_order->v->GetOrder(order->GetConditionSkipToOrder());
+								if (order == NULL) {
+									break;
+								}
+								continue;
+							}
+							case 2: {
+								/* Do not take the branch */
+								order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+								continue;
+							}
+					}
+				}
+
+				/* If we reach the original station again, then use it as the terminus. */
+				if (order->GetType() == OT_GOTO_STATION &&
+						(StationID)order->GetDestination() == station &&
+						(order->GetUnloadType() != OUFB_NO_UNLOAD ||
+						_settings_client.gui.departure_show_all_stops) &&
+						order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
+						order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
+					/* If we're not calling anywhere, then skip this departure. */
+					found_terminus = (d->calling_at.Length() > 0);
+					break;
+				}
+
+				/* Check if we're going via this station. */
+				if ((order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
+						order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) &&
+						order->GetType() == OT_GOTO_STATION &&
+						d->via == INVALID_STATION) {
+					candidate_via = (StationID)order->GetDestination();
+				}
+
+				/* We're not interested in this order any further if we're not calling at it. */
+				if ((order->GetUnloadType() == OUFB_NO_UNLOAD &&
+						!_settings_client.gui.departure_show_all_stops) ||
+						(order->GetType() != OT_GOTO_STATION &&
+						order->GetType() != OT_IMPLICIT) ||
+						order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
+						order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) {
+					order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+					continue;
+				}
+
+				/* If this order's station is already in the calling, then the previous called at station is the terminus. */
+				if (d->calling_at.Contains((StationID)order->GetDestination())) {
+					found_terminus = true;
+					break;
+				}
+
+				/* If appropriate, add the station to the calling at list and make it the candidate terminus. */
+				if ((order->GetType() == OT_GOTO_STATION ||
+						order->GetType() == OT_IMPLICIT) &&
+						order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
+						order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
+					if (d->via == INVALID_STATION && candidate_via == (StationID)order->GetDestination()) {
+						d->via = (StationID)order->GetDestination();
+					}
+					d->terminus = (StationID)order->GetDestination();
+					*(d->calling_at.Append(1)) = d->terminus;
+				}
+
+				/* If we unload all at this station, then it is the terminus. */
+				if (order->GetType() == OT_GOTO_STATION &&
+						order->GetUnloadType() == OUFB_UNLOAD) {
+					if (d->calling_at.Length() > 0) {
+						found_terminus = true;
+					}
+					break;
+				}
+
+				/* Get the next order, which may be the vehicle's first order. */
+				order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+			}
+
+			if (found_terminus) {
+				/* Add the departure to the result list. */
+				*(result->Append(1)) = d;
+
+				/* If the vehicle is expected to be late, we want to know what time it will arrive rather than depart. */
+				/* This is done because it looked silly to me to have a vehicle not be expected for another few days, yet it be at the same time pulling into the station. */
+				if (d->status != D_ARRIVED &&
+						d->lateness > 0) {
+					d->lateness -= least_order->order->wait_time;
+				}
+			}
+		} else {
+			/* Computing arrivals: */
+			/* First we need to find the origin of the order. This is somewhat like finding a terminus, but a little more involved since order lists are singly linked. */
+			/* The next stage is simpler. We just need to add all the stations called at on the way to the current station. */
+			/* Again, we define a station as being called at if the vehicle loads from it. */
+
+			/* However, the very first thing we do is use the arrival time as the scheduled time instead of the departure time. */
+			d->scheduled_date -= order->wait_time;
+
+			const Order *candidate_origin = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+			bool found_origin = false;
+
+			while (candidate_origin != least_order->order) {
+				if ((candidate_origin->GetLoadType() != OLFB_NO_LOAD ||
+						_settings_client.gui.departure_show_all_stops) &&
+						(candidate_origin->GetType() == OT_GOTO_STATION ||
+						candidate_origin->GetType() == OT_IMPLICIT) &&
+						candidate_origin->GetDestination() != station) {
+					const Order *o = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
+					bool found_collision = false;
+
+					/* Check if the candidate origin's destination appears again before the original order or the station does. */
+					while (o != least_order->order) {
+						if (o->GetUnloadType() == OUFB_UNLOAD) {
+							found_collision = true;
+							break;
+						}
+
+						if ((o->GetType() == OT_GOTO_STATION ||
+								o->GetType() == OT_IMPLICIT) &&
+								(o->GetDestination() == candidate_origin->GetDestination() ||
+								o->GetDestination() == station)) {
+							found_collision = true;
+							break;
+						}
+
+						o = (o->next == NULL) ? least_order->v->GetFirstOrder() : o->next;
+					}
+
+					/* If it doesn't, then we have found the origin. */
+					if (!found_collision) {
+						found_origin = true;
+						break;
+					}
+				}
+
+				candidate_origin = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
+			}
+
+			order = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
+
+			while (order != least_order->order) {
+				if (order->GetType() == OT_GOTO_STATION &&
+						(order->GetLoadType() != OLFB_NO_LOAD ||
+						_settings_client.gui.departure_show_all_stops)) {
+					*(d->calling_at.Append(1)) = (StationID)order->GetDestination();
+				}
+
+				order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+			}
+
+			d->terminus = candidate_origin->GetDestination();
+
+			if (found_origin) {
+				*(result->Append(1)) = d;
+			}
+		}
+
+		/* Save on pointer dereferences in the coming loop. */
+		order = least_order->order;
+
+		/* Now we find the next suitable order for being a departure for this vehicle. */
+		/* We do this in a similar way to finding the first suitable order for the vehicle. */
+
+		/* Go to the next order so we don't add the current order again. */
+		order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+		least_order->expected_date += order->travel_time + order->wait_time;
+
+		/* Go through the order list to find the next candidate departure. */
+		/* We only need to consider each order at most once. */
+		bool found_next_order = false;
+		for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
+			/* If the order is a conditional branch, handle it. */
+			if (order->IsType(OT_CONDITIONAL)) {
+				switch(_settings_client.gui.departure_conditionals) {
+						case 0: {
+							/* Give up */
+							break;
+						}
+						case 1: {
+							/* Take the branch */
+							order = least_order->v->GetOrder(order->GetConditionSkipToOrder());
+							if (order == NULL) {
+								break;
+							}
+
+							least_order->expected_date += order->wait_time;
+
+							continue;
+						}
+						case 2: {
+							/* Do not take the branch */
+							order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+							least_order->expected_date += order->travel_time + order->wait_time;
+							continue;
+						}
+				}
+			}
+
+			/* Skip it if it's an implicit order. */
+			if (order->IsType(OT_IMPLICIT)) {
+				order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+				continue;
+			}
+
+			/* If an order doesn't have a travel time set, then stop. */
+			if (order->travel_time == 0) {
+				break;
+			}
+
+			/* If the departure is scheduled to be too late, then stop. */
+			if (least_order->expected_date - least_order->lateness > max_date) {
+				break;
+			}
+
+			/* If the order loads from this station (or unloads if we're computing arrivals) and has a wait time set, then it is suitable for being a departure. */
+			if ((type == D_DEPARTURE && IsDeparture(order, station)) ||
+						(type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
+						(type == D_ARRIVAL && IsArrival(order, station))) {
+				least_order->order = order;
+				found_next_order = true;
+				break;
+			}
+
+			order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
+			least_order->expected_date += order->travel_time + order->wait_time;
+		}
+
+		/* If we didn't find a suitable order for being a departure, then we can ignore this vehicle from now on. */
+		if (!found_next_order) {
+			/* Make sure we don't try to get departures out of this order. */
+			/* This is cheaper than deleting it from next_orders. */
+			/* If we ever get to a state where _date * DAY_TICKS is close to INT_MAX, then we'll have other problems anyway as departures' scheduled dates will wrap around. */
+			least_order->expected_date = INT64_MAX;
+		}
+
+		/* The vehicle can't possibly have arrived at its next candidate departure yet. */
+		if (least_order->status == D_ARRIVED) {
+			least_order->status = D_TRAVELLING;
+		}
+
+		/* Find the new least order. */
+		for (uint i = 0; i < next_orders.Length(); ++i) {
+			OrderDate *od = *(next_orders.Get(i));
+
+			DateTicks lod = least_order->expected_date - least_order->lateness;
+			DateTicks odd = od->expected_date - od->lateness;
+
+			if (type == D_ARRIVAL) {
+				lod -= least_order->order->wait_time;
+				odd -= od->order->wait_time;
+			}
+
+			if (lod > odd && od->expected_date - od->lateness < max_date) {
+				least_order = od;
+			}
+		}
+	}
+
+	/* Done. Phew! */
+	return result;
+}
diff --git a/src/departures_func.h b/src/departures_func.h
new file mode 100644
--- /dev/null
+++ b/src/departures_func.h
@@ -0,0 +1,21 @@
+/* $Id: departures_func.h $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file departures_func.h Functions related to departures. */
+
+#ifndef DEPARTURES_FUNC_H
+#define DEPARTURES_FUNC_H
+
+#include "station_base.h"
+#include "core/smallvec_type.hpp"
+#include "departures_type.h"
+
+DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[4], DepartureType type = D_DEPARTURE, bool show_vehicles_via = false);
+
+#endif /* DEPARTURES_FUNC_H */
diff --git a/src/departures_gui.cpp b/src/departures_gui.cpp
new file mode 100644
--- /dev/null
+++ b/src/departures_gui.cpp
@@ -0,0 +1,838 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file departures_gui.cpp Scheduled departures from a station. */
+
+#include "stdafx.h"
+#include "debug.h"
+#include "gui.h"
+#include "textbuf_gui.h"
+#include "strings_func.h"
+#include "window_func.h"
+#include "vehicle_func.h"
+#include "string_func.h"
+#include "window_gui.h"
+#include "timetable.h"
+#include "vehiclelist.h"
+#include "company_base.h"
+#include "date_func.h"
+#include "departures_gui.h"
+#include "station_base.h"
+#include "vehicle_gui_base.h"
+#include "vehicle_base.h"
+#include "vehicle_gui.h"
+#include "order_base.h"
+#include "settings_type.h"
+#include "core/smallvec_type.hpp"
+#include "date_type.h"
+#include "company_type.h"
+#include "departures_func.h"
+#include "cargotype.h"
+
+#include "table/sprites.h"
+#include "table/strings.h"
+
+static const NWidgetPart _nested_departures_list[] = {
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+		NWidget(WWT_CAPTION, COLOUR_GREY, DW_WIDGET_CAPTION), SetDataTip(STR_DEPARTURES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_SHADEBOX, COLOUR_GREY),
+		NWidget(WWT_STICKYBOX, COLOUR_GREY),
+	EndContainer(),
+
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_MATRIX, COLOUR_GREY, DW_WIDGET_LIST), SetMinimalSize(0, 0), SetFill(1, 0), SetResize(1, 1),
+		NWidget(NWID_VSCROLLBAR, COLOUR_GREY, DW_WIDGET_SCROLLBAR),
+	EndContainer(),
+
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetResize(1, 0), SetFill(1, 1), EndContainer(),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_ARRS), SetMinimalSize(6, 12), SetFill(0, 1), SetDataTip(STR_DEPARTURES_ARRIVALS, STR_DEPARTURES_ARRIVALS_TOOLTIP),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_DEPS), SetMinimalSize(6, 12), SetFill(0, 1), SetDataTip(STR_DEPARTURES_DEPARTURES, STR_DEPARTURES_DEPARTURES_TOOLTIP),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_VIA), SetMinimalSize(11, 12), SetFill(0, 1), SetDataTip(STR_DEPARTURES_VIA_BUTTON, STR_DEPARTURES_VIA_TOOLTIP),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_TRAINS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_TRAIN, STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_ROADVEHS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_LORRY, STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_SHIPS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_SHIP, STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, DW_SHOW_PLANES),  SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_PLANE, STR_STATION_VIEW_SCHEDULED_AIRCRAFT_TOOLTIP),
+		NWidget(WWT_RESIZEBOX, COLOUR_GREY),
+	EndContainer(),
+};
+
+static WindowDesc _departures_desc(
+	WDP_AUTO, 260, 246,
+	WC_DEPARTURES_BOARD, WC_NONE,
+	WDF_UNCLICK_BUTTONS,
+	_nested_departures_list, lengthof(_nested_departures_list)
+);
+
+static uint cached_date_width = 0;         ///< The cached maximum width required to display a date.
+static uint cached_status_width = 0;       ///< The cached maximum width required to show the status field.
+static uint cached_date_arrow_width = 0;   ///< The cached width of the red/green arrows that may be displayed alongside times.
+static bool cached_date_display_method;    ///< Whether the above cached values refers to original (d,m,y) dates or the 24h clock.
+static bool cached_arr_dep_display_method; ///< Whether to show departures and arrivals on a single line.
+
+template<bool Twaypoint = false>
+struct DeparturesWindow : public Window {
+protected:
+	StationID station;         ///< The station whose departures we're showing.
+	DepartureList *departures; ///< The current list of departures from this station.
+	DepartureList *arrivals;   ///< The current list of arrivals from this station.
+	uint entry_height;         ///< The height of an entry in the departures list.
+	uint tick_count;           ///< The number of ticks that have elapsed since the window was created. Used for scrolling text.
+	int calc_tick_countdown;   ///< The number of ticks to wait until recomputing the departure list. Signed in case it goes below zero.
+	bool show_types[4];        ///< The vehicle types to show in the departure list.
+	bool departure_types[3];   ///< The types of departure to show in the departure list.
+	uint min_width;            ///< The minimum width of this window.
+	Scrollbar *vscroll;
+
+	virtual uint GetMinWidth() const;
+	static void RecomputeDateWidth();
+	virtual void DrawDeparturesListItems(const Rect &r) const;
+	void DeleteDeparturesList(DepartureList* list);
+public:
+
+	DeparturesWindow(const WindowDesc *desc, WindowNumber window_number) : Window(),
+		station(window_number),
+		departures(new DepartureList()),
+		arrivals(new DepartureList()),
+		entry_height(1 + FONT_HEIGHT_NORMAL + 1 + (_settings_client.gui.departure_larger_font ? FONT_HEIGHT_NORMAL : FONT_HEIGHT_SMALL) + 1 + 1),
+		tick_count(0),
+		calc_tick_countdown(0),
+		min_width(400)
+	{
+		this->CreateNestedTree(desc);
+		this->vscroll = this->GetScrollbar(DW_WIDGET_SCROLLBAR);
+		this->FinishInitNested(desc, window_number);
+
+		/* By default, only show departures. */
+		departure_types[0] = true;
+		departure_types[1] = false;
+		departure_types[2] = false;
+		this->LowerWidget(DW_SHOW_DEPS);
+		this->RaiseWidget(DW_SHOW_ARRS);
+		this->RaiseWidget(DW_SHOW_VIA);
+
+		for (uint i = 0; i < 4; ++i) {
+			show_types[i] = true;
+			this->LowerWidget(DW_SHOW_TRAINS + i);
+		}
+
+		if (Twaypoint) {
+			this->GetWidget<NWidgetCore>(DW_WIDGET_CAPTION)->SetDataTip(STR_DEPARTURES_CAPTION_WAYPOINT, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
+
+			for (uint i = 0; i < 4; ++i) {
+				this->DisableWidget(DW_SHOW_TRAINS + i);
+			}
+
+			this->DisableWidget(DW_SHOW_ARRS);
+			this->DisableWidget(DW_SHOW_DEPS);
+			this->DisableWidget(DW_SHOW_VIA);
+
+			departure_types[2] = true;
+
+			this->LowerWidget(DW_SHOW_VIA);
+		}
+	}
+
+	virtual ~DeparturesWindow()
+	{
+		this->DeleteDeparturesList(departures);
+		this->DeleteDeparturesList(this->arrivals);
+	}
+
+	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
+	{
+		switch (widget) {
+			case DW_WIDGET_LIST:
+				resize->height = DeparturesWindow::entry_height;
+				size->height = 2 * resize->height;
+				break;
+		}
+	}
+
+	virtual void SetStringParameters(int widget) const
+	{
+		if (widget == DW_WIDGET_CAPTION) {
+			const Station *st = Station::Get(this->station);
+			SetDParam(0, st->index);
+		}
+	}
+
+	virtual void OnClick(Point pt, int widget, int click_count)
+	{
+		switch (widget) {
+			case DW_SHOW_TRAINS:   // Show trains to this station
+			case DW_SHOW_ROADVEHS: // Show road vehicles to this station
+			case DW_SHOW_SHIPS:    // Show ships to this station
+			case DW_SHOW_PLANES:   // Show aircraft to this station
+				this->show_types[widget - DW_SHOW_TRAINS] = !this->show_types[widget - DW_SHOW_TRAINS];
+				if (this->show_types[widget - DW_SHOW_TRAINS]) {
+					this->LowerWidget(widget);
+				} else {
+					this->RaiseWidget(widget);
+				}
+				/* We need to recompute the departures list. */
+				this->calc_tick_countdown = 0;
+				/* We need to redraw the button that was pressed. */
+				this->SetWidgetDirty(widget);
+				break;
+
+			case DW_SHOW_DEPS:
+			case DW_SHOW_ARRS:
+				if (_settings_client.gui.departure_show_both) break;
+				/* FALL THROUGH */
+
+			case DW_SHOW_VIA:
+
+				this->departure_types[widget - DW_SHOW_DEPS] = !this->departure_types[widget - DW_SHOW_DEPS];
+				if (this->departure_types[widget - DW_SHOW_DEPS]) {
+					this->LowerWidget(widget);
+				} else {
+					this->RaiseWidget(widget);
+				}
+
+				if (!this->departure_types[0]) {
+					this->RaiseWidget(DW_SHOW_VIA);
+					this->DisableWidget(DW_SHOW_VIA);
+				} else {
+					this->EnableWidget(DW_SHOW_VIA);
+
+					if (this->departure_types[2]) {
+						this->LowerWidget(DW_SHOW_VIA);
+					}
+				}
+				/* We need to recompute the departures list. */
+				this->calc_tick_countdown = 0;
+				/* We need to redraw the button that was pressed. */
+				this->SetWidgetDirty(widget);
+				break;
+
+			case DW_WIDGET_LIST:   // Matrix to show departures
+				/* We need to find the departure corresponding to where the user clicked. */
+				uint32 id_v = (pt.y - this->GetWidget<NWidgetBase>(DW_WIDGET_LIST)->pos_y) / this->entry_height;
+
+				if (id_v >= this->vscroll->GetCapacity()) return; // click out of bounds
+
+				id_v += this->vscroll->GetPosition();
+
+				if (id_v >= (this->departures->Length() + this->arrivals->Length())) return; // click out of list bound
+
+				uint departure = 0;
+				uint arrival = 0;
+
+				/* Draw each departure. */
+				for (uint i = 0; i <= id_v; ++i) {
+					const Departure *d;
+
+					if (arrival == this->arrivals->Length()) {
+						d = (*(this->departures))[departure++];
+					} else if (departure == this->departures->Length()) {
+						d = (*(this->arrivals))[arrival++];
+					} else {
+						d = (*(this->departures))[departure];
+						const Departure *a = (*(this->arrivals))[arrival];
+
+						if (a->scheduled_date < d->scheduled_date) {
+							d = a;
+							arrival++;
+						} else {
+							departure++;
+						}
+					}
+
+					if (i == id_v) {
+						ShowVehicleViewWindow(d->vehicle);
+						break;
+					}
+				}
+
+				break;
+		}
+	}
+
+	virtual void OnTick()
+	{
+		if (_pause_mode == PM_UNPAUSED) {
+			this->tick_count += 1;
+			this->calc_tick_countdown -= 1;
+		}
+
+		/* Recompute the minimum date display width if the cached one is no longer valid. */
+		if (cached_date_width == 0 ||
+				_settings_client.gui.time_in_minutes != cached_date_display_method ||
+				_settings_client.gui.departure_show_both != cached_arr_dep_display_method) {
+			this->RecomputeDateWidth();
+		}
+
+		/* We need to redraw the scrolling text in its new position. */
+		this->SetWidgetDirty(DW_WIDGET_LIST);
+
+		/* Recompute the list of departures if we're due to. */
+		if (this->calc_tick_countdown <= 0) {
+			this->calc_tick_countdown = _settings_client.gui.departure_calc_frequency;
+			this->DeleteDeparturesList(this->departures);
+			this->DeleteDeparturesList(this->arrivals);
+			this->departures = (this->departure_types[0] ? MakeDepartureList(this->station, this->show_types, D_DEPARTURE, Twaypoint || this->departure_types[2]) : new DepartureList());
+			this->arrivals   = (this->departure_types[1] && !_settings_client.gui.departure_show_both ? MakeDepartureList(this->station, this->show_types, D_ARRIVAL  ) : new DepartureList());
+			this->SetWidgetDirty(DW_WIDGET_LIST);
+		}
+
+		uint new_width = this->GetMinWidth();
+
+		if (new_width != this->min_width) {
+			NWidgetCore *n = this->GetWidget<NWidgetCore>(DW_WIDGET_LIST);
+			n->SetMinimalSize(new_width, 0);
+			this->ReInit();
+			this->min_width = new_width;
+		}
+
+		uint new_height = 1 + FONT_HEIGHT_NORMAL + 1 + (_settings_client.gui.departure_larger_font ? FONT_HEIGHT_NORMAL : FONT_HEIGHT_SMALL) + 1 + 1;
+
+		if (new_height != this->entry_height) {
+			this->entry_height = new_height;
+			this->SetWidgetDirty(DW_WIDGET_LIST);
+			this->ReInit();
+		}
+	}
+
+	virtual void OnPaint()
+	{
+		if (Twaypoint || _settings_client.gui.departure_show_both) {
+			this->DisableWidget(DW_SHOW_ARRS);
+			this->DisableWidget(DW_SHOW_DEPS);
+		} else {
+			this->EnableWidget(DW_SHOW_ARRS);
+			this->EnableWidget(DW_SHOW_DEPS);
+		}
+
+		this->vscroll->SetCount(min(_settings_client.gui.max_departures, this->departures->Length() + this->arrivals->Length()));
+		this->DrawWidgets();
+	}
+
+	virtual void DrawWidget(const Rect &r, int widget) const
+	{
+		switch (widget) {
+			case DW_WIDGET_LIST:
+				this->DrawDeparturesListItems(r);
+				break;
+		}
+	}
+
+	virtual void OnResize()
+	{
+		this->vscroll->SetCapacityFromWidget(this, DW_WIDGET_LIST);
+		this->GetWidget<NWidgetCore>(DW_WIDGET_LIST)->widget_data = (this->vscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
+	}
+};
+
+/**
+ * Shows a window of scheduled departures for a station.
+ * @param station the station to show a departures window for
+ */
+void ShowStationDepartures(StationID station)
+{
+	AllocateWindowDescFront<DeparturesWindow<> >(&_departures_desc, station);
+}
+
+/**
+ * Shows a window of scheduled departures for a station.
+ * @param station the station to show a departures window for
+ */
+void ShowWaypointDepartures(StationID waypoint)
+{
+	AllocateWindowDescFront<DeparturesWindow<true> >(&_departures_desc, waypoint);
+}
+
+template<bool Twaypoint>
+void DeparturesWindow<Twaypoint>::RecomputeDateWidth()
+{
+	cached_date_width = 0;
+	cached_status_width = 0;
+	cached_date_display_method = _settings_client.gui.time_in_minutes;
+	cached_arr_dep_display_method = _settings_client.gui.departure_show_both;
+
+	cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_ON_TIME)).width, cached_status_width);
+	cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_DELAYED)).width, cached_status_width);
+	cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_CANCELLED)).width, cached_status_width);
+
+	uint interval = cached_date_display_method ? _settings_client.gui.ticks_per_minute : DAY_TICKS;
+	uint count = cached_date_display_method ? 24*60 : 365;
+
+	for (uint i = 0; i < count; ++i) {
+		SetDParam(0, INT_MAX - (i*interval));
+		SetDParam(1, INT_MAX - (i*interval));
+		cached_date_width = max(GetStringBoundingBox(cached_arr_dep_display_method ? STR_DEPARTURES_TIME_BOTH : STR_DEPARTURES_TIME_DEP).width, cached_date_width);
+		cached_status_width = max((GetStringBoundingBox(STR_DEPARTURES_EXPECTED)).width, cached_status_width);
+	}
+
+	SetDParam(0, 0);
+	cached_date_arrow_width = GetStringBoundingBox(STR_DEPARTURES_TIME_DEP).width - GetStringBoundingBox(STR_DEPARTURES_TIME).width;
+
+	if (!_settings_client.gui.departure_show_both) {
+		cached_date_width -= cached_date_arrow_width;
+	}
+}
+
+template<bool Twaypoint>
+uint DeparturesWindow<Twaypoint>::GetMinWidth() const
+{
+	uint result = 0;
+
+	/* Time */
+	result = cached_date_width;
+
+	/* Vehicle type icon */
+	result += _settings_client.gui.departure_show_vehicle_type ? (GetStringBoundingBox(STR_DEPARTURES_TYPE_PLANE)).width : 0;
+
+	/* Status */
+	result += cached_status_width;
+
+	/* Find the maximum company name width. */
+	int toc_width = 0;
+
+	/* Find the maximum company name width. */
+	int group_width = 0;
+
+	/* Find the maximum vehicle name width. */
+	int veh_width = 0;
+
+	if (_settings_client.gui.departure_show_vehicle || _settings_client.gui.departure_show_company || _settings_client.gui.departure_show_group) {
+		for (uint i = 0; i < 4; ++i) {
+			VehicleList vehicles;
+
+			/* MAX_COMPANIES is probably the wrong thing to put here, but it works. GenerateVehicleSortList doesn't check the company when the type of list is VL_STATION_LIST (r20801). */
+			if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station).Pack())) {
+				/* Something went wrong: panic! */
+				continue;
+			}
+
+			for (const Vehicle **v = vehicles.Begin(); v != vehicles.End(); v++) {
+				SetDParam(0, (uint64)((*v)->index));
+				int width = (GetStringBoundingBox(STR_DEPARTURES_VEH)).width;
+				if (_settings_client.gui.departure_show_vehicle && width > veh_width) veh_width = width;
+
+				if ((*v)->group_id != INVALID_GROUP && (*v)->group_id != DEFAULT_GROUP) {
+					SetDParam(0, (uint64)((*v)->group_id));
+					width = (GetStringBoundingBox(STR_DEPARTURES_GROUP)).width;
+					if (_settings_client.gui.departure_show_group && width > group_width) group_width = width;
+				}
+
+				SetDParam(0, (uint64)((*v)->owner));
+				width = (GetStringBoundingBox(STR_DEPARTURES_TOC)).width;
+				if (_settings_client.gui.departure_show_company && width > toc_width) toc_width = width;
+			}
+		}
+	}
+
+	result += toc_width + veh_width + group_width;
+
+	return result + 140;
+}
+
+/**
+ * Deletes this window's departure list.
+ */
+template<bool Twaypoint>
+void DeparturesWindow<Twaypoint>::DeleteDeparturesList(DepartureList *list)
+{
+	/* SmallVector uses free rather than delete on its contents (which doesn't invoke the destructor), so we need to delete each departure manually. */
+	for (uint i = 0; i < list->Length(); ++i) {
+		Departure **d = list->Get(i);
+		delete *d;
+		/* Make sure a double free doesn't happen. */
+		*d = NULL;
+	}
+	list->Reset();
+	delete list;
+	list = NULL;
+}
+
+/**
+ * Draws a list of departures.
+ */
+template<bool Twaypoint>
+void DeparturesWindow<Twaypoint>::DrawDeparturesListItems(const Rect &r) const
+{
+	int left = r.left + WD_MATRIX_LEFT;
+	int right = r.right - WD_MATRIX_RIGHT;
+
+	bool rtl = _current_text_dir == TD_RTL;
+	bool ltr = !rtl;
+
+	int text_offset = WD_FRAMERECT_RIGHT;
+	int text_left  = left  + (rtl ?           0 : text_offset);
+	int text_right = right - (rtl ? text_offset :           0);
+
+	int y = r.top + 1;
+	uint max_departures = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->departures->Length() + this->arrivals->Length());
+
+	if (max_departures > _settings_client.gui.max_departures) {
+		max_departures = _settings_client.gui.max_departures;
+	}
+
+	byte small_font_size = _settings_client.gui.departure_larger_font ? FONT_HEIGHT_NORMAL : FONT_HEIGHT_SMALL;
+
+	/* Draw the black background. */
+	GfxFillRect(r.left + 1, r.top, r.right - 1, r.bottom, PC_BLACK);
+
+	/* Nothing selected? Then display the information text. */
+	bool none_selected[2] = {true, true};
+	for (uint i = 0; i < 4; ++i)
+	{
+		if (this->show_types[i]) {
+			none_selected[0] = false;
+			break;
+		}
+	}
+
+	for (uint i = 0; i < 2; ++i)
+	{
+		if (this->departure_types[i]) {
+			none_selected[1] = false;
+			break;
+		}
+	}
+
+	if (none_selected[0] || none_selected[1]) {
+		DrawString(text_left, text_right, y + 1, STR_DEPARTURES_NONE_SELECTED);
+		return;
+	}
+
+	/* No scheduled departures? Then display the information text. */
+	if (max_departures == 0) {
+		DrawString(text_left, text_right, y + 1, STR_DEPARTURES_EMPTY);
+		return;
+	}
+
+	/* Find the maximum possible width of the departure time and "Expt <time>" fields. */
+	int time_width = cached_date_width;
+
+	if (!_settings_client.gui.departure_show_both) {
+		time_width += (departure_types[0] && departure_types[1] ? cached_date_arrow_width : 0);
+	}
+
+	/* Vehicle type icon */
+	int type_width = _settings_client.gui.departure_show_vehicle_type ? (GetStringBoundingBox(STR_DEPARTURES_TYPE_PLANE)).width : 0;
+
+	/* Find the maximum width of the status field */
+	int status_width = cached_status_width;
+
+	/* Find the width of the "Calling at:" field. */
+	int calling_at_width = (GetStringBoundingBox(_settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT)).width;
+
+	/* Find the maximum company name width. */
+	int toc_width = 0;
+
+	/* Find the maximum group name width. */
+	int group_width = 0;
+
+	/* Find the maximum vehicle name width. */
+	int veh_width = 0;
+
+	if (_settings_client.gui.departure_show_vehicle || _settings_client.gui.departure_show_company || _settings_client.gui.departure_show_group) {
+		for (uint i = 0; i < 4; ++i) {
+			VehicleList vehicles;
+
+			/* MAX_COMPANIES is probably the wrong thing to put here, but it works. GenerateVehicleSortList doesn't check the company when the type of list is VL_STATION_LIST (r20801). */
+			if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station).Pack())) {
+				/* Something went wrong: panic! */
+				continue;
+			}
+
+			for (const Vehicle **v = vehicles.Begin(); v != vehicles.End(); v++) {
+				SetDParam(0, (uint64)((*v)->index));
+				int width = (GetStringBoundingBox(STR_DEPARTURES_VEH)).width;
+				if (_settings_client.gui.departure_show_vehicle && width > veh_width) veh_width = width;
+
+				if ((*v)->group_id != INVALID_GROUP && (*v)->group_id != DEFAULT_GROUP) {
+					SetDParam(0, (uint64)((*v)->group_id));
+					width = (GetStringBoundingBox(STR_DEPARTURES_GROUP)).width;
+					if (_settings_client.gui.departure_show_group && width > group_width) group_width = width;
+				}
+
+				SetDParam(0, (uint64)((*v)->owner));
+				width = (GetStringBoundingBox(STR_DEPARTURES_TOC)).width;
+				if (_settings_client.gui.departure_show_company && width > toc_width) toc_width = width;
+			}
+		}
+	}
+
+	uint departure = 0;
+	uint arrival = 0;
+
+	/* Draw each departure. */
+	for (uint i = 0; i < max_departures; ++i) {
+		const Departure *d;
+
+		if (arrival == this->arrivals->Length()) {
+			d = (*(this->departures))[departure++];
+		} else if (departure == this->departures->Length()) {
+			d = (*(this->arrivals))[arrival++];
+		} else {
+			d = (*(this->departures))[departure];
+			const Departure *a = (*(this->arrivals))[arrival];
+
+			if (a->scheduled_date < d->scheduled_date) {
+				d = a;
+				arrival++;
+			} else {
+				departure++;
+			}
+		}
+
+		if (i < this->vscroll->GetPosition()) {
+			continue;
+		}
+
+		/* If for some reason the departure is too far in the future or is at a negative time, skip it. */
+		if ((d->scheduled_date / DAY_TICKS) > (_date + _settings_client.gui.max_departure_time) ||
+			d->scheduled_date < 0) {
+			continue;
+		}
+
+		if (d->terminus == INVALID_STATION) continue;
+
+		StringID time_str = (departure_types[0] && departure_types[1]) ? (d->type == D_DEPARTURE ? STR_DEPARTURES_TIME_DEP : STR_DEPARTURES_TIME_ARR) : STR_DEPARTURES_TIME;
+
+		if (_settings_client.gui.departure_show_both) time_str = STR_DEPARTURES_TIME_BOTH;
+
+		/* Time */
+		SetDParam(0, d->scheduled_date);
+		SetDParam(1, d->scheduled_date - d->order->wait_time);
+		ltr ? DrawString(              text_left, text_left + time_width, y + 1, time_str)
+			: DrawString(text_right - time_width,             text_right, y + 1, time_str);
+
+		/* Vehicle type icon */
+		if (_settings_client.gui.departure_show_vehicle_type) {
+			StringID type = STR_DEPARTURES_TYPE_TRAIN;
+			int offset = (_settings_client.gui.departure_show_vehicle_color ? 1 : 0);
+
+			switch (d->vehicle->type) {
+				case VEH_TRAIN:
+					type = STR_DEPARTURES_TYPE_TRAIN;
+					break;
+				case VEH_ROAD:
+					type = IsCargoInClass(d->vehicle->cargo_type, CC_PASSENGERS) ? STR_DEPARTURES_TYPE_BUS : STR_DEPARTURES_TYPE_LORRY;
+					break;
+				case VEH_SHIP:
+					type = STR_DEPARTURES_TYPE_SHIP;
+					break;
+				case VEH_AIRCRAFT:
+					type = STR_DEPARTURES_TYPE_PLANE;
+					break;
+				default:
+					break;
+			}
+
+			type += offset;
+
+			DrawString(text_left + time_width + 3, text_left + time_width + type_width + 3, y, type);
+		}
+
+		/* The icons to show with the destination and via stations. */
+		StringID icon = STR_DEPARTURES_STATION_NONE;
+		StringID icon_via = STR_DEPARTURES_STATION_NONE;
+
+		if (_settings_client.gui.departure_destination_type) {
+			Station *t = Station::Get(d->terminus);
+
+			if (t->facilities & FACIL_DOCK &&
+					t->facilities & FACIL_AIRPORT &&
+					d->vehicle->type != VEH_SHIP &&
+					d->vehicle->type != VEH_AIRCRAFT) {
+				icon = STR_DEPARTURES_STATION_PORTAIRPORT;
+			} else if (t->facilities & FACIL_DOCK &&
+					d->vehicle->type != VEH_SHIP) {
+				icon = STR_DEPARTURES_STATION_PORT;
+			} else if (t->facilities & FACIL_AIRPORT &&
+					d->vehicle->type != VEH_AIRCRAFT) {
+				icon = STR_DEPARTURES_STATION_AIRPORT;
+			}
+		}
+
+		if (_settings_client.gui.departure_destination_type && d->via != INVALID_STATION) {
+			Station *t = Station::Get(d->via);
+
+			if (t->facilities & FACIL_DOCK &&
+					t->facilities & FACIL_AIRPORT &&
+					d->vehicle->type != VEH_SHIP &&
+					d->vehicle->type != VEH_AIRCRAFT) {
+				icon_via = STR_DEPARTURES_STATION_PORTAIRPORT;
+			} else if (t->facilities & FACIL_DOCK &&
+					d->vehicle->type != VEH_SHIP) {
+				icon_via = STR_DEPARTURES_STATION_PORT;
+			} else if (t->facilities & FACIL_AIRPORT &&
+					d->vehicle->type != VEH_AIRCRAFT) {
+				icon_via = STR_DEPARTURES_STATION_AIRPORT;
+			}
+		}
+
+		/* Destination */
+		if (d->via == INVALID_STATION) {
+			/* Only show the terminus. */
+			SetDParam(0, d->terminus);
+			SetDParam(1, icon);
+			ltr ? DrawString(              text_left + time_width + type_width + 6,   text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_TERMINUS)
+				: DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2,                 text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_TERMINUS);
+		} else {
+			/* Show the terminus and the via station. */
+			SetDParam(0, d->terminus);
+			SetDParam(1, icon);
+			SetDParam(2, d->via);
+			SetDParam(3, icon_via);
+			int text_width = (GetStringBoundingBox(STR_DEPARTURES_TERMINUS_VIA_STATION)).width;
+
+			if (text_width < text_right - status_width - (toc_width + veh_width + group_width + 2) - 2 - (text_left + time_width + type_width + 6)) {
+				/* They will both fit, so show them both. */
+				SetDParam(0, d->terminus);
+				SetDParam(1, icon);
+				SetDParam(2, d->via);
+				SetDParam(3, icon_via);
+				ltr ? DrawString(              text_left + time_width + type_width + 6, text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_TERMINUS_VIA_STATION)
+					: DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2,               text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_TERMINUS_VIA_STATION);
+			} else {
+				/* They won't both fit, so switch between showing the terminus and the via station approximately every 4 seconds. */
+				if (this->tick_count & (1 << 7)) {
+					SetDParam(0, d->via);
+					SetDParam(1, icon_via);
+					ltr ? DrawString(              text_left + time_width + type_width + 6, text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_VIA)
+						: DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2,               text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_VIA);
+				} else {
+					SetDParam(0, d->terminus);
+					SetDParam(1, icon);
+					ltr ? DrawString(              text_left + time_width + type_width + 6, text_right - status_width - (toc_width + veh_width + group_width + 2) - 2, y + 1, STR_DEPARTURES_TERMINUS_VIA)
+						: DrawString(text_left + status_width + (toc_width + veh_width + group_width + 2) + 2,               text_right - time_width - type_width - 6, y + 1, STR_DEPARTURES_TERMINUS_VIA);
+				}
+			}
+		}
+
+		/* Status */
+		{
+			int status_left = ltr ? text_right - status_width - 2 - (toc_width + veh_width + group_width + 2) : text_left + (toc_width + veh_width + group_width + 2) + 2;
+			int status_right = ltr ? text_right - (toc_width + veh_width + group_width + 2) + 2 : text_left + status_width + 2 + (toc_width + veh_width + group_width + 2);
+
+			if (d->status == D_ARRIVED) {
+				/* The vehicle has arrived. */
+				DrawString(status_left, status_right, y + 1, STR_DEPARTURES_ARRIVED);
+			} else if(d->status == D_CANCELLED) {
+				/* The vehicle has been cancelled. */
+				DrawString(status_left, status_right, y + 1, STR_DEPARTURES_CANCELLED);
+			} else {
+				if (d->lateness <= DAY_TICKS && d->scheduled_date > ((_date * DAY_TICKS) + _date_fract)) {
+					/* We have no evidence that the vehicle is late, so assume it is on time. */
+					DrawString(status_left, status_right, y + 1, STR_DEPARTURES_ON_TIME);
+				} else {
+					if ((d->scheduled_date + d->lateness) < ((_date * DAY_TICKS) + _date_fract)) {
+						/* The vehicle was expected to have arrived by now, even if we knew it was going to be late. */
+						/* We assume that the train stays at least a day at a station so it won't accidentally be marked as delayed for a fraction of a day. */
+						DrawString(status_left, status_right, y + 1, STR_DEPARTURES_DELAYED);
+					} else {
+						/* The vehicle is expected to be late and is not yet due to arrive. */
+						SetDParam(0, d->scheduled_date + d->lateness);
+						DrawString(status_left, status_right, y + 1, STR_DEPARTURES_EXPECTED);
+					}
+				}
+			}
+		}
+
+		/* Vehicle name */
+
+		if (_settings_client.gui.departure_show_vehicle) {
+			SetDParam(0, (uint64)(d->vehicle->index));
+			ltr ? DrawString(text_right - (toc_width + veh_width + group_width + 2),              text_right - toc_width - group_width - 2, y + 1, STR_DEPARTURES_VEH)
+				: DrawString(               text_left + toc_width + group_width + 2, text_left + (toc_width + veh_width + group_width + 2), y + 1, STR_DEPARTURES_VEH);
+		}
+
+		/* Group name */
+
+		if (_settings_client.gui.departure_show_group && d->vehicle->group_id != INVALID_GROUP && d->vehicle->group_id != DEFAULT_GROUP) {
+			SetDParam(0, (uint64)(d->vehicle->group_id));
+			ltr ? DrawString(text_right - (toc_width + group_width + 2),              text_right - toc_width - 2, y + 1, STR_DEPARTURES_GROUP)
+				: DrawString(               text_left + toc_width + 2, text_left + (toc_width + group_width + 2), y + 1, STR_DEPARTURES_GROUP);
+		}
+
+		/* Operating company */
+		if (_settings_client.gui.departure_show_company) {
+			SetDParam(0, (uint64)(d->vehicle->owner));
+			ltr ? DrawString(text_right - toc_width,            text_right, y + 1, STR_DEPARTURES_TOC, TC_FROMSTRING, SA_RIGHT)
+				: DrawString(             text_left, text_left + toc_width, y + 1, STR_DEPARTURES_TOC, TC_FROMSTRING, SA_LEFT);
+		}
+
+		int bottom_y = y + this->entry_height - small_font_size - (_settings_client.gui.departure_larger_font ? 1 : 3);
+
+		/* Calling at */
+		ltr ? DrawString(                    text_left,  text_left + calling_at_width, bottom_y, _settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT)
+			: DrawString(text_right - calling_at_width,                    text_right, bottom_y, _settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT);
+
+		/* List of stations */
+		/* RTL languages can be handled in the language file, e.g. by having the following: */
+		/* STR_DEPARTURES_CALLING_AT_STATION      :{STATION}, {RAW_STRING} */
+		/* STR_DEPARTURES_CALLING_AT_LAST_STATION :{STATION} & {RAW_STRING}*/
+		char buffer[512], scratch[512];
+
+		if (d->calling_at.Length() != 0) {
+			SetDParam(0, (uint64)(*d->calling_at.Get(0)));
+			GetString(scratch, STR_DEPARTURES_CALLING_AT_FIRST_STATION, lastof(scratch));
+
+			if (d->calling_at.Length() > 1) {
+				/* There's more than one stop. */
+
+				/* For all but the last station, write out ", <station>". */
+				for (uint i = 1; i < d->calling_at.Length() - 1; ++i) {
+					SetDParam(0, (uint64)scratch);
+					SetDParam(1, (uint64)(*d->calling_at.Get(i)));
+					GetString(buffer, STR_DEPARTURES_CALLING_AT_STATION, lastof(buffer));
+					strncpy(scratch, buffer, sizeof(scratch)); }
+
+				/* Finally, finish off with " & <station>". */
+				SetDParam(0, (uint64)scratch);
+				SetDParam(1, (uint64)(*d->calling_at.Get(d->calling_at.Length()-1)));
+				GetString(buffer, STR_DEPARTURES_CALLING_AT_LAST_STATION, lastof(buffer));
+				strncpy(scratch, buffer, sizeof(scratch));
+			}
+
+			SetDParam(0, (uint64)scratch);
+			GetString(buffer, _settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LIST_LARGE : STR_DEPARTURES_CALLING_AT_LIST, lastof(buffer));
+		} else {
+			buffer[0] = 0;
+			//SetDParam(0, d->terminus);
+			//GetString(scratch, STR_DEPARTURES_CALLING_AT_FIRST_STATION, lastof(scratch));
+		}
+
+		int list_width = (GetStringBoundingBox(buffer, _settings_client.gui.departure_larger_font ? FS_NORMAL : FS_SMALL)).width;
+
+		/* Draw the whole list if it will fit. Otherwise scroll it. */
+		if (list_width < text_right - (text_left + calling_at_width + 2)) {
+			ltr ? DrawString(text_left + calling_at_width + 2,                        text_right, bottom_y, buffer)
+				: DrawString(                       text_left, text_right - calling_at_width - 2, bottom_y, buffer);
+		} else {
+			DrawPixelInfo tmp_dpi;
+			if (ltr
+				? !FillDrawPixelInfo(&tmp_dpi, text_left + calling_at_width + 2, bottom_y, text_right - (text_left + calling_at_width + 2), small_font_size + 3)
+				: !FillDrawPixelInfo(&tmp_dpi, text_left                       , bottom_y, text_right - (text_left + calling_at_width + 2), small_font_size + 3)) {
+				y += this->entry_height;
+				continue;
+			}
+			DrawPixelInfo *old_dpi = _cur_dpi;
+			_cur_dpi = &tmp_dpi;
+
+			/* The scrolling text starts out of view at the right of the screen and finishes when it is out of view at the left of the screen. */
+			int pos = ltr
+				? text_right - (this->tick_count % (list_width + text_right - text_left))
+				:  text_left + (this->tick_count % (list_width + text_right - text_left));
+
+			ltr ? DrawString(       pos, INT16_MAX, 0, buffer, TC_FROMSTRING,  SA_LEFT | SA_FORCE)
+				: DrawString(-INT16_MAX,       pos, 0, buffer, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
+
+			_cur_dpi = old_dpi;
+		}
+
+		y += this->entry_height;
+	}
+}
diff --git a/src/departures_gui.h b/src/departures_gui.h
new file mode 100644
--- /dev/null
+++ b/src/departures_gui.h
@@ -0,0 +1,35 @@
+/* $Id: departures_gui.h $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file departures_gui.h */
+
+#ifndef DEPARTURES_GUI_H
+#define DEPARTURES_GUI_H
+
+#include "departures_type.h"
+#include "station_base.h"
+
+/** Enum for DeparturesView, referring to _nested_departures_list */
+enum DeparturesWindowWidgets {
+	DW_WIDGET_CAPTION,		///< Window caption
+	DW_WIDGET_LIST,			///< List of departures
+	DW_WIDGET_SCROLLBAR,	///< List scrollbar
+	DW_SHOW_DEPS,           ///< Toggle departures button
+	DW_SHOW_ARRS,           ///< Toggle arrivals button
+	DW_SHOW_VIA,            ///< Toggle via button
+	DW_SHOW_TRAINS,         ///< Toggle trains button
+	DW_SHOW_ROADVEHS,       ///< Toggle road vehicles button
+	DW_SHOW_SHIPS,          ///< Toggle ships button
+	DW_SHOW_PLANES,         ///< Toggle planes button
+};
+
+void ShowStationDepartures(StationID station);
+void ShowWaypointDepartures(StationID waypoint);
+
+#endif /* DEPARTURES_GUI_H */
diff --git a/src/departures_type.h b/src/departures_type.h
new file mode 100644
--- /dev/null
+++ b/src/departures_type.h
@@ -0,0 +1,51 @@
+/* $Id: departures_type.h $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file departures_type.h Types related to departures. */
+
+#ifndef DEPARTURES_TYPE_H
+#define DEPARTURES_TYPE_H
+
+#include "station_base.h"
+#include "order_base.h"
+
+/** Whether or not a vehicle has arrived for a departure. */
+typedef enum {
+	D_TRAVELLING = 0,
+	D_ARRIVED    = 1,
+	D_CANCELLED  = 2,
+} DepartureStatus;
+
+/** The type of departures. */
+typedef enum {
+	D_DEPARTURE = 0,
+	D_ARRIVAL   = 1,
+} DepartureType;
+
+/** A scheduled departure. */
+typedef struct Departure {
+	DateTicks scheduled_date;              ///< The date this departure is scheduled to finish on (i.e. when the vehicle leaves the station)
+	DateTicks lateness;                    ///< How delayed the departure is expected to be
+	StationID terminus;                    ///< The station at which the vehicle will terminate following this departure
+	StationID via;                         ///< The station the departure should list as going via
+	SmallVector<StationID, 32> calling_at; ///< The stations both called at and unloaded at by the vehicle after this departure before it terminates
+	DepartureStatus status;                ///< Whether the vehicle has arrived yet for this departure
+	DepartureType type;                    ///< The type of the departure (departure or arrival)
+	const Vehicle *vehicle;                ///< The vehicle performing this departure
+	const Order *order;                    ///< The order corresponding to this departure
+	Departure() : terminus(INVALID_STATION), via(INVALID_STATION), calling_at(), vehicle(NULL) { }
+	~Departure()
+	{
+		calling_at.Reset();
+	}
+} Departure;
+
+typedef SmallVector<Departure*, 32> DepartureList;
+
+#endif /* DEPARTURES_TYPE_H */
diff --git a/src/depot.cpp b/src/depot.cpp
--- a/src/depot.cpp
+++ b/src/depot.cpp
@@ -17,12 +17,32 @@
 #include "core/pool_func.hpp"
 #include "vehicle_gui.h"
 #include "vehiclelist.h"
+#include "road_map.h"
+#include "rail_map.h"
+#include "water_map.h"
+#include "station_map.h"
+#include "depot_map.h"
 
 /** All our depots tucked away in a pool. */
 DepotPool _depot_pool("Depot");
 INSTANTIATE_POOL_METHODS(Depot)
 
 /**
+ * Returns the direction the exit of the depot on the given tile is facing.
+ */
+DiagDirection GetDepotDirection(TileIndex tile, TransportType type)
+{
+	assert(IsDepotTypeTile(tile, type));
+
+	switch (type) {
+		case TRANSPORT_RAIL:  return GetRailDepotDirection(tile);
+		case TRANSPORT_ROAD:  return GetRoadDepotDirection(tile);
+		case TRANSPORT_WATER: return GetShipDepotDirection(tile);
+		default: return INVALID_DIAGDIR; /* Not reached */
+	}
+}
+
+/**
  * Clean up a depot
  */
 Depot::~Depot()
diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp
--- a/src/depot_gui.cpp
+++ b/src/depot_gui.cpp
@@ -28,6 +28,8 @@
 #include "window_gui.h"
 #include "vehiclelist.h"
 #include "order_backup.h"
+#include "company_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -141,7 +143,7 @@
 
 	const Vehicle *v = Vehicle::Get(_new_vehicle_id);
 
-	ShowVehicleViewWindow(v);
+	if (!_ctrl_pressed) ShowVehicleViewWindow(v);
 }
 
 static void TrainDepotMoveVehicle(const Vehicle *wagon, VehicleID sel, const Vehicle *head)
@@ -676,7 +678,7 @@
 
 		/* Setup disabled buttons. */
 		TileIndex tile = this->window_number;
-		this->SetWidgetsDisabledState(!IsTileOwner(tile, _local_company),
+		this->SetWidgetsDisabledState(!Company::IsValidID(_local_company) || !IsInfraTileUsageAllowed(this->type, _local_company, tile),
 			DEPOT_WIDGET_STOP_ALL,
 			DEPOT_WIDGET_START_ALL,
 			DEPOT_WIDGET_SELL,
@@ -715,7 +717,7 @@
 						SPR_CURSOR_CLONE_SHIP, SPR_CURSOR_CLONE_AIRPLANE
 					};
 
-					SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, HT_VEHICLE, this);
+					SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, HT_VEHICLE | HT_RECT, this);
 				} else {
 					ResetObjectToPlace();
 				}
diff --git a/src/depot_map.h b/src/depot_map.h
--- a/src/depot_map.h
+++ b/src/depot_map.h
@@ -55,4 +55,6 @@
 	return _m[t].m2;
 }
 
+DiagDirection GetDepotDirection(TileIndex tile, TransportType type);
+
 #endif /* DEPOT_MAP_H */
diff --git a/src/disaster_cmd.cpp b/src/disaster_cmd.cpp
--- a/src/disaster_cmd.cpp
+++ b/src/disaster_cmd.cpp
@@ -43,6 +43,7 @@
 #include "company_base.h"
 #include "core/random_func.hpp"
 #include "core/backup_type.hpp"
+#include "aircraft.h"
 
 #include "table/strings.h"
 
@@ -122,6 +123,24 @@
 	_disaster_images_4, _disaster_images_5,                     ///< small and big submarine sprites
 };
 
+static inline void AdjustFlyingDisasterVehicleHeight(DisasterVehicle *v)
+{
+	int min_altitude = GetAircraftMinAltitude(v->x_pos, v->y_pos, 0);
+	int max_altitude = GetAircraftMaxAltitude(v->x_pos, v->y_pos, 0);
+	int middle_altitude = min_altitude + ((uint)(max_altitude - min_altitude)) / 2;
+	if (v->z_pos < min_altitude || (v->in_min_height_correction && v->z_pos < middle_altitude)) {
+		v->in_min_height_correction = true;
+		v->z_pos += 2;
+	} else if (v->z_pos > max_altitude || (v->in_max_height_correction && v->z_pos > middle_altitude)) {
+		v->in_max_height_correction = true;
+		v->z_pos -= 2;
+	} else if (v->in_min_height_correction && v->z_pos >= middle_altitude) {
+		v->in_min_height_correction = false;
+	} else if (v->in_max_height_correction && v->z_pos <= middle_altitude) {
+		v->in_max_height_correction = false;
+	}
+}
+
 static void DisasterVehicleUpdateImage(DisasterVehicle *v)
 {
 	SpriteID img = v->image_override;
@@ -202,6 +221,7 @@
 
 		GetNewVehiclePosResult gp = GetNewVehiclePos(v);
 
+		AdjustFlyingDisasterVehicleHeight(v);
 		SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
 
 		if (v->current_order.GetDestination() == 1) {
@@ -298,6 +318,7 @@
 		if (Delta(x, v->x_pos) + Delta(y, v->y_pos) >= (int)TILE_SIZE) {
 			v->direction = GetDirectionTowards(v, x, y);
 			GetNewVehiclePosResult gp = GetNewVehiclePos(v);
+			AdjustFlyingDisasterVehicleHeight(v);
 			SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
 			return true;
 		}
@@ -337,6 +358,7 @@
 		uint dist = Delta(v->x_pos, u->x_pos) + Delta(v->y_pos, u->y_pos);
 
 		if (dist < TILE_SIZE && !(u->vehstatus & VS_HIDDEN) && u->breakdown_ctr == 0) {
+			u->breakdown_type = BREAKDOWN_CRITICAL;
 			u->breakdown_ctr = 3;
 			u->breakdown_delay = 140;
 		}
@@ -402,6 +424,7 @@
 	v->image_override = (v->current_order.GetDestination() == 1 && HasBit(v->tick_counter, 2)) ? image_override : 0;
 
 	GetNewVehiclePosResult gp = GetNewVehiclePos(v);
+	AdjustFlyingDisasterVehicleHeight(v);
 	SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
 
 	if ((leave_at_top && gp.x < (-10 * (int)TILE_SIZE)) || (!leave_at_top && gp.x > (int)(MapSizeX() * TILE_SIZE + 9 * TILE_SIZE) - 1)) {
@@ -499,6 +522,7 @@
 			v->direction = GetDirectionTowards(v, x, y);
 
 			GetNewVehiclePosResult gp = GetNewVehiclePos(v);
+			AdjustFlyingDisasterVehicleHeight(v);
 			SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
 			return true;
 		}
@@ -523,6 +547,7 @@
 				if (Delta(target->x_pos, v->x_pos) + Delta(target->y_pos, v->y_pos) <= 12 * (int)TILE_SIZE) {
 					target->breakdown_ctr = 5;
 					target->breakdown_delay = 0xF0;
+					target->breakdown_type = BREAKDOWN_CRITICAL;
 				}
 			}
 		}
@@ -554,6 +579,7 @@
 		if (Delta(x, v->x_pos) + Delta(y, v->y_pos) >= (int)TILE_SIZE) {
 			v->direction = GetDirectionTowards(v, x, y);
 			GetNewVehiclePosResult gp = GetNewVehiclePos(v);
+			AdjustFlyingDisasterVehicleHeight(v);
 			SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
 			return true;
 		}
@@ -589,6 +615,7 @@
 	v->tick_counter++;
 
 	GetNewVehiclePosResult gp = GetNewVehiclePos(v);
+	AdjustFlyingDisasterVehicleHeight(v);
 	SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
 
 	if (gp.x > (int)(MapSizeX() * TILE_SIZE + 9 * TILE_SIZE) - 1) {
@@ -704,7 +731,8 @@
 	}
 
 	DisasterVehicle *v = new DisasterVehicle();
-	InitializeDisasterVehicle(v, x, 0, INITIAL_DISASTER_VEHICLE_ZPOS, DIR_SE, ST_ZEPPELINER);
+	int z = GetAircraftMinAltitude(x, 0, 0);
+	InitializeDisasterVehicle(v, x, 0, z, DIR_SE, ST_ZEPPELINER);
 
 	/* Allocate shadow */
 	DisasterVehicle *u = new DisasterVehicle();
@@ -725,7 +753,8 @@
 	DisasterVehicle *v = new DisasterVehicle();
 	int x = TileX(Random()) * TILE_SIZE + TILE_SIZE / 2;
 
-	InitializeDisasterVehicle(v, x, 0, INITIAL_DISASTER_VEHICLE_ZPOS, DIR_SE, ST_SMALL_UFO);
+	int z = GetAircraftMinAltitude(x, 0, 0);
+	InitializeDisasterVehicle(v, x, 0, z, DIR_SE, ST_SMALL_UFO);
 	v->dest_tile = TileXY(MapSizeX() / 2, MapSizeY() / 2);
 	v->age = 0;
 
@@ -759,7 +788,8 @@
 	int x = (MapSizeX() + 9) * TILE_SIZE - 1;
 	int y = TileY(found->location.tile) * TILE_SIZE + 37;
 
-	InitializeDisasterVehicle(v, x, y, INITIAL_DISASTER_VEHICLE_ZPOS, DIR_NE, ST_AIRPLANE);
+	int z = GetAircraftMinAltitude(x, y, 0);
+	InitializeDisasterVehicle(v, x, y, z, DIR_NE, ST_AIRPLANE);
 
 	DisasterVehicle *u = new DisasterVehicle();
 	v->SetNext(u);
@@ -789,7 +819,8 @@
 	int x = -16 * (int)TILE_SIZE;
 	int y = TileY(found->location.tile) * TILE_SIZE + 37;
 
-	InitializeDisasterVehicle(v, x, y, INITIAL_DISASTER_VEHICLE_ZPOS, DIR_SW, ST_HELICOPTER);
+	int z = GetAircraftMinAltitude(x, y, 0);
+	InitializeDisasterVehicle(v, x, y, z, DIR_SW, ST_HELICOPTER);
 
 	DisasterVehicle *u = new DisasterVehicle();
 	v->SetNext(u);
@@ -798,7 +829,7 @@
 
 	DisasterVehicle *w = new DisasterVehicle();
 	u->SetNext(w);
-	InitializeDisasterVehicle(w, x, y, 140, DIR_SW, ST_HELICOPTER_ROTORS);
+	InitializeDisasterVehicle(w, x, y, z + 5, DIR_SW, ST_HELICOPTER_ROTORS);
 }
 
 
@@ -812,7 +843,8 @@
 	int x = TileX(Random()) * TILE_SIZE + TILE_SIZE / 2;
 	int y = MapMaxX() * TILE_SIZE - 1;
 
-	InitializeDisasterVehicle(v, x, y, INITIAL_DISASTER_VEHICLE_ZPOS, DIR_NW, ST_BIG_UFO);
+	int z = GetAircraftMinAltitude(x, y, 0);
+	InitializeDisasterVehicle(v, x, y, z, DIR_NW, ST_BIG_UFO);
 	v->dest_tile = TileXY(MapSizeX() / 2, MapSizeY() / 2);
 	v->age = 0;
 
diff --git a/src/economy.cpp b/src/economy.cpp
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -46,6 +46,8 @@
 #include "core/pool_func.hpp"
 #include "newgrf.h"
 #include "core/backup_type.hpp"
+#include "infrastructure_func.h"
+#include "cheat_type.h"
 
 #include "table/strings.h"
 #include "table/pricebase.h"
@@ -415,7 +417,8 @@
 		}
 	}
 
-	{
+	/* Change ownership of vehicles */
+	if (new_owner != INVALID_OWNER) {
 		FreeUnitIDGenerator unitidgen[] = {
 			FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD,     new_owner),
 			FreeUnitIDGenerator(VEH_SHIP,  new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
@@ -457,22 +460,14 @@
 			 * and signals were not propagated
 			 * Similiar with crossings - it is needed to bar crossings that weren't before
 			 * because of different owner of crossing and approaching train */
-			tile = 0;
-
-			do {
-				if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
-					TrackBits tracks = GetTrackBits(tile);
-					do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT
-						Track track = RemoveFirstTrack(&tracks);
-						if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_owner);
-					} while (tracks != TRACK_BIT_NONE);
-				} else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
-					UpdateLevelCrossing(tile);
-				}
-			} while (++tile != MapSize());
+			UpdateAllBlockSignals(new_owner);
+		} else if (_settings_game.economy.infrastructure_sharing[VEH_TRAIN]) {
+			/* tracks are being removed while sharing is enabled.
+			 * Thus, update all signals and crossings. */
+			UpdateAllBlockSignals();
 		}
 
-		/* update signals in buffer */
+		/* Update any signals in the buffer */
 		UpdateSignalsInBuffer();
 	}
 
@@ -990,8 +985,11 @@
 
 	/* Increase town's counter for some special goods types */
 	const CargoSpec *cs = CargoSpec::Get(cargo_type);
+	if (cs->town_effect == TE_PASSENGERS) st->town->new_act_pass += accepted;
+	if (cs->town_effect == TE_MAIL) st->town->new_act_mail += accepted;
 	if (cs->town_effect == TE_FOOD) st->town->new_act_food += accepted;
 	if (cs->town_effect == TE_WATER) st->town->new_act_water += accepted;
+	if (cs->town_effect == TE_GOODS) st->town->new_act_goods += accepted;
 
 	/* Determine profit */
 	Money profit = GetTransportedGoodsIncome(accepted, DistanceManhattan(source_tile, st->xy), days_in_transit, cargo_type);
@@ -1060,21 +1058,23 @@
 
 	this->front->cargo_payment = NULL;
 
-	if (this->visual_profit == 0) return;
+	if (this->visual_profit == 0 && this->visual_transfer == 0) return;
 
 	Backup<CompanyByte> cur_company(_current_company, this->front->owner, FILE_LINE);
 
 	SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
-	this->front->profit_this_year += this->visual_profit << 8;
+	this->front->profit_this_year += (this->visual_profit + this->visual_transfer) << 8;
 
-	if (this->route_profit != 0) {
-		if (IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) {
-			SndPlayVehicleFx(SND_14_CASHTILL, this->front);
-		}
+	if (this->route_profit != 0 && IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) {
+		SndPlayVehicleFx(SND_14_CASHTILL, this->front);
+	}
 
-		ShowCostOrIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, -this->visual_profit);
-	} else {
-		ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, this->visual_profit);
+	if (this->visual_transfer != 0){
+		ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos,
+				this->front->z_pos, this->visual_transfer, -this->visual_profit);
+	} else if (this->visual_profit) {
+		ShowCostOrIncomeAnimation(this->front->x_pos, this->front->y_pos,
+				this->front->z_pos, -this->visual_profit);
 	}
 
 	cur_company.Restore();
@@ -1091,8 +1091,32 @@
 		this->owner = Company::Get(this->front->owner);
 	}
 
-	/* Handle end of route payment */
+	/* Handle end of route payment */ //TODO: Adjust profit to daylength factor (fractional)
 	Money profit = DeliverGoods(count, this->ct, this->current_station, cp->SourceStationXY(), cp->DaysInTransit(), this->owner, cp->SourceSubsidyType(), cp->SourceSubsidyID());
+
+/* Devide profit by daylength and keep the restfraction for the next payment. */
+/* test 1 */
+//profit = (profit * 100) << 16;
+//daylength_money_fraction += profit;
+//daylength_money_payout = daylength_money_fraction / _date_daylength_factor;
+//daylength_money_fraction = daylength_money_fraction - daylength_money_payout * _date_daylength_factor;
+//profit = (daylength_money_payout / 100) >> 16;
+
+/* test 2*/
+//daylength_money_payout = profit / _date_daylength_factor;
+//daylength_money_fraction = daylength_money_fraction + profit - daylength_money_payout * _date_daylength_factor; // "(t - m * daylength)" is always < daylength so f is never big
+//daylength_money_payout = daylength_money_payout + daylength_money_fraction / _date_daylength_factor;
+//daylength_money_fraction = daylength_money_fraction - daylength_money_payout * _date_daylength_factor;
+//profit = daylength_money_payout;
+
+
+	/* Devide income by daylength factor. */
+	if (!_cheats.daylength_income.value) {
+		profit = profit / _date_daylength_factor;
+		/* Pay something when the income is too low after devision by daylength. */
+		if (_date_daylength_factor > 1 && profit < 1) profit = 1;
+	}
+
 	this->route_profit += profit;
 
 	/* The vehicle's profit is whatever route profit there is minus feeder shares. */
@@ -1112,27 +1136,67 @@
 			/* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
 			DistanceManhattan(cp->LoadedAtXY(), Station::Get(this->current_station)->xy),
 			cp->DaysInTransit(),
-			this->ct);
+			this->ct);  //TODO: Adjust profit to daylength factor (fractional)
+
+
+/* Devide profit by daylength and keep the restfraction for the next payment. */
+/* test 1*/
+//profit = (profit * 100) << 16;
+//daylength_money_fraction += profit;
+//daylength_money_payout = daylength_money_fraction / _date_daylength_factor;
+//daylength_money_fraction = daylength_money_fraction - daylength_money_payout * _date_daylength_factor;
+//profit = (daylength_money_payout / 100) >> 16;
+
+/*test 2*/
+//daylength_money_payout = profit / _date_daylength_factor;
+//daylength_money_fraction = daylength_money_fraction + profit - daylength_money_payout * _date_daylength_factor; // "(t - m * daylength)" is always < daylength so f is never big
+//daylength_money_payout = daylength_money_payout + daylength_money_fraction / _date_daylength_factor;
+//daylength_money_fraction = daylength_money_fraction - daylength_money_payout * _date_daylength_factor;
+//profit = daylength_money_payout;
+
+	/* Devide income by daylength factor. */
+	if (!_cheats.daylength_income.value) {
+		profit = profit / _date_daylength_factor;
+		/* Pay something when the income is too low after devision by daylength. */
+		if (_date_daylength_factor > 1 && profit < 1) profit = 1;
+	}
 
 	profit = profit * _settings_game.economy.feeder_payment_share / 100;
 
-	this->visual_profit += profit; // accumulate transfer profits for whole vehicle
+	this->visual_transfer += profit; // accumulate transfer profits for whole vehicle
 	return profit; // account for the (virtual) profit already made for the cargo packet
 }
 
 /**
  * Prepare the vehicle to be unloaded.
+ * @param curr_station the station where the consist is at the moment
  * @param front_v the vehicle to be unloaded
+ * @param next_station_id id of the station the consist will be traveling next
  */
-void PrepareUnload(Vehicle *front_v)
+void PrepareUnload(Station *curr_station, Vehicle *front_v, StationID next_station_id)
 {
 	/* At this moment loading cannot be finished */
 	ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
 
-	/* Start unloading in at the first possible moment */
+	/* Start unloading at the first possible moment */
 	front_v->load_unload_ticks = 1;
 
-	if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
+	if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) != 0) {
+		/* vehicle will keep all its cargo and LoadUnloadVehicle will never call MoveToStation,
+		 * so we have to update the flow stats here.
+		 */
+		if (next_station_id == INVALID_STATION) {
+			return;
+		} else {
+			for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
+				const CargoPacketList *packets = v->cargo.Packets();
+				for(VehicleCargoList::ConstIterator i(packets->begin()); i != packets->end(); ++i) {
+					curr_station->goods[v->cargo_type].UpdateFlowStats(
+							(*i)->SourceStation(), (*i)->Count(), next_station_id);
+				}
+			}
+		}
+	} else {
 		for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
 			if (v->cargo_cap > 0 && !v->cargo.Empty()) {
 				SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
@@ -1360,39 +1424,29 @@
 
 		/* If there's goods waiting at the station, and the vehicle
 		 * has capacity for it, load it on the vehicle. */
-		int cap_left = v->cargo_cap - v->cargo.Count();
-		if (!ge->cargo.Empty() && cap_left > 0) {
-			uint cap = cap_left;
-			uint count = ge->cargo.Count();
+		int cap_left = v->cargo_cap - v->cargo.OnboardCount();
+		if (cap_left > 0) {
+			if (_settings_game.order.gradual_loading) cap_left = min(cap_left, load_amount);
+			if (v->cargo.Empty()) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
 
-			/* Skip loading this vehicle if another train/vehicle is already handling
-			 * the same cargo type at this station */
-			if (_settings_game.order.improved_load && cargo_left[v->cargo_type] <= 0) {
-				SetBit(cargo_not_full, v->cargo_type);
-				continue;
+			int loaded = 0;
+
+			if (_settings_game.order.improved_load) {
+				loaded += v->cargo.LoadReserved(cap_left);
 			}
 
-			if (cap > count) cap = count;
-			if (_settings_game.order.gradual_loading) {
-				cap = min(cap, load_amount);
-				cap_left = min(cap_left, load_amount);
-			}
-			if (_settings_game.order.improved_load) {
-				/* Don't load stuff that is already 'reserved' for other vehicles */
-				cap = min((uint)cargo_left[v->cargo_type], cap);
-				count = cargo_left[v->cargo_type];
-				cargo_left[v->cargo_type] -= cap;
+			if (loaded < cap_left) {
+				assert(v->cargo.ReservedCount() == 0);
+				loaded += ge->cargo.MoveTo(&v->cargo, cap_left - loaded, next_station);
 			}
 
 			/* Store whether the maximum possible load amount was loaded or not.*/
-			if (count >= (uint)cap_left) {
+			if (loaded == cap_left) {
 				SetBit(full_load_amount, v->cargo_type);
 			} else {
 				ClrBit(full_load_amount, v->cargo_type);
 			}
 
-			if (v->cargo.Empty()) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
-
 			/* TODO: Regarding this, when we do gradual loading, we
 			 * should first unload all vehicles and then start
 			 * loading them. Since this will cause
@@ -1521,6 +1575,7 @@
 		st->MarkTilesDirty(true);
 		SetWindowDirty(WC_STATION_VIEW, last_visited);
 	}
+	return cargos_reserved;
 }
 
 /**
@@ -1555,13 +1610,11 @@
 	 */
 	if (last_loading == NULL) return;
 
-	int cargo_left[NUM_CARGO];
-
-	for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count();
+	uint cargos_reserved = 0;
 
 	for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
 		Vehicle *v = *iter;
-		if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
+		if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) cargos_reserved = LoadUnloadVehicle(v, cargos_reserved);
 		if (v == last_loading) break;
 	}
 
@@ -1583,6 +1636,7 @@
 		AddInflation();
 		RecomputePrices();
 	}
+
 	CompaniesPayInterest();
 	HandleEconomyFluctuations();
 }
diff --git a/src/economy_base.h b/src/economy_base.h
--- a/src/economy_base.h
+++ b/src/economy_base.h
@@ -24,9 +24,12 @@
  * Helper class to perform the cargo payment.
  */
 struct CargoPayment : CargoPaymentPool::PoolItem<&_cargo_payment_pool> {
-	Vehicle *front;      ///< The front vehicle to do the payment of
-	Money route_profit;  ///< The amount of money to add/remove from the bank account
-	Money visual_profit; ///< The visual profit to show
+	Vehicle *front;        ///< The front vehicle to do the payment of
+	Money route_profit;    ///< The amount of money to add/remove from the bank account
+	Money visual_profit;   ///< The visual profit to show
+	Money visual_transfer; ///< The transfer credits to be shown
+int daylength_money_payout;   ///< Amount of money to be paid out now.
+int daylength_money_fraction; ///< Amount of money we will keep for the next time.
 
 	/* Unsaved variables */
 	Company *owner;            ///< The owner of the vehicle
diff --git a/src/economy_func.h b/src/economy_func.h
--- a/src/economy_func.h
+++ b/src/economy_func.h
@@ -33,7 +33,7 @@
 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type);
 uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations);
 
-void PrepareUnload(Vehicle *front_v);
+void PrepareUnload(Station *curr_station, Vehicle *front_v, StationID next_station_id);
 void LoadUnloadStation(Station *st);
 
 Money GetPrice(Price index, uint cost_factor, const struct GRFFile *grf_file, int shift = 0);
diff --git a/src/economy_type.h b/src/economy_type.h
--- a/src/economy_type.h
+++ b/src/economy_type.h
@@ -155,6 +155,8 @@
 	EXPENSES_AIRCRAFT_INC,        ///< Income from aircrafts.
 	EXPENSES_SHIP_INC,            ///< Income from ships.
 	EXPENSES_LOAN_INT,            ///< Interest payments over the loan.
+	EXPENSES_SHARING_COST,        ///< Infrastructure sharing costs
+	EXPENSES_SHARING_INC,         ///< Infrastructure sharing income
 	EXPENSES_OTHER,               ///< Other expenses.
 	EXPENSES_END,                 ///< Number of expense types.
 	INVALID_EXPENSES      = 0xFF, ///< Invalid expense type.
diff --git a/src/fios.cpp b/src/fios.cpp
--- a/src/fios.cpp
+++ b/src/fios.cpp
@@ -135,6 +135,7 @@
 		case FIOS_TYPE_OLD_SCENARIO:
 		case FIOS_TYPE_PNG:
 		case FIOS_TYPE_BMP:
+		case FIOS_TYPE_TEMPLATE:
 			return item->name;
 	}
 
@@ -153,6 +154,13 @@
 {
 	const char *period;
 
+//<<<<<<< .mine  // Todo: remove after testing
+//	extension = (_game_mode == GM_EDITOR) ? ".scn" : ".sav";
+//	if (_saveload_mode == SLD_SAVE_TEMPLATE || _saveload_mode == SLD_LOAD_TEMPLATE) {
+//		extension = ".tmpl";
+//	}
+//=======
+//>>>>>>> .r22515
 	/* Don't append the extension if it is already there */
 	period = strrchr(name, '.');
 	if (period != NULL && strcasecmp(period, ext) == 0) ext = "";
@@ -181,7 +189,13 @@
  */
 void FiosMakeSavegameName(char *buf, const char *name, size_t size)
 {
-	const char *extension = (_game_mode == GM_EDITOR) ? ".scn" : ".sav";
+	const char *extension;
+
+	if (_saveload_mode == SLD_SAVE_TEMPLATE || _saveload_mode == SLD_LOAD_TEMPLATE) {
+		extension = ".tmpl";
+	} else {
+		extension = (_game_mode == GM_EDITOR) ? ".scn" : ".sav";
+	}
 
 	FiosMakeFilename(buf, _fios_path, name, extension, size);
 }
@@ -436,6 +450,45 @@
 }
 
 /**
+ * Callback for FiosGetFileList. It tells if a file is a template or not.
+ * @param mode Save/load mode.
+ * @param file Name of the file to check.
+ * @param ext A pointer to the extension identifier inside file
+ * @param title Buffer if a callback wants to lookup the title of the file
+ * @return a FIOS_TYPE_* type of the found file, FIOS_TYPE_INVALID if not a template
+ * @see FiosGetFileList
+ * @see FiosGetSavegameList
+ */
+static FiosType FiosGetTemplateListCallback(SaveLoadDialogMode mode, const char *file, const char *ext, char *title, const char *last)
+{
+	/* Show template files
+	 * .tmpl OpenTTD template */
+	if (strcasecmp(ext, ".tmpl") == 0) return FIOS_TYPE_TEMPLATE;
+
+	return FIOS_TYPE_INVALID;
+}
+
+/**
+ * Get a list of templates.
+ * @param mode Save/load mode.
+ * @return A pointer to an array of FiosItem representing all the files to be shown in the save/load dialog.
+ * @see FiosGetFileList
+ */
+void FiosGetTemplateList(SaveLoadDialogMode mode)
+{
+	static char *_fios_save_path = NULL;
+
+	if (_fios_save_path == NULL) {
+		_fios_save_path = MallocT<char>(MAX_PATH);
+		FioGetDirectory(_fios_save_path, MAX_PATH, SAVE_DIR);
+	}
+
+	_fios_path = _fios_save_path;
+
+	FiosGetFileList(mode, &FiosGetTemplateListCallback, NO_DIRECTORY);
+}
+
+/**
  * Callback for FiosGetFileList. It tells if a file is a scenario or not.
  * @param mode Save/load mode.
  * @param file Name of the file to check.
diff --git a/src/fios.h b/src/fios.h
--- a/src/fios.h
+++ b/src/fios.h
@@ -90,9 +90,11 @@
 	/** First slot useable for (New)GRFs used during the game. */
 	FIRST_GRF_SLOT =  2,
 	/** Last slot useable for (New)GRFs used during the game. */
-	LAST_GRF_SLOT  = 63,
+	LAST_GRF_SLOT  = 255,
 	/** Maximum number of slots. */
-	MAX_FILE_SLOTS = 64
+	MAX_FILE_SLOTS = 256,
+	/** Maximum number of slots for network game */
+	MAX_FILE_SLOTS_IN_NETWORK = 63
 };
 
 /** Mode of the file dialogue window. */
@@ -103,6 +105,9 @@
 	SLD_SAVE_SCENARIO,  ///< Save a scenario.
 	SLD_LOAD_HEIGHTMAP, ///< Load a heightmap.
 	SLD_SAVE_HEIGHTMAP, ///< Save a heightmap.
+	SLD_SAVE_TEMPLATE,
+	SLD_LOAD_TEMPLATE,
+	SLD_NEW_GAME,
 };
 
 /** The different types of files that the system knows about. */
@@ -124,6 +129,7 @@
 	FIOS_TYPE_DIRECT,
 	FIOS_TYPE_PNG,
 	FIOS_TYPE_BMP,
+	FIOS_TYPE_TEMPLATE,
 	FIOS_TYPE_INVALID = 255,
 };
 
@@ -162,7 +168,9 @@
 void FiosGetSavegameList(SaveLoadDialogMode mode);
 void FiosGetScenarioList(SaveLoadDialogMode mode);
 void FiosGetHeightmapList(SaveLoadDialogMode mode);
-
+/* Get a list of templates */
+void FiosGetTemplateList(SaveLoadDialogMode mode);
+/* Free the list of savegames */
 void FiosFreeSavegameList();
 const char *FiosBrowseTo(const FiosItem *item);
 
diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp
--- a/src/fios_gui.cpp
+++ b/src/fios_gui.cpp
@@ -36,7 +36,6 @@
 static bool _fios_path_changed;
 static bool _savegame_sort_dirty;
 
-
 /**
  * Reset read data.
  */
@@ -198,7 +197,7 @@
 /** Colours for fios types, indexed by #FiosType. */
 const TextColour _fios_colours[] = {
 	TC_LIGHT_BLUE, TC_DARK_GREEN,  TC_DARK_GREEN, TC_ORANGE, TC_LIGHT_BROWN,
-	TC_ORANGE,     TC_LIGHT_BROWN, TC_ORANGE,     TC_ORANGE, TC_YELLOW
+	TC_ORANGE,     TC_LIGHT_BROWN, TC_ORANGE,     TC_ORANGE, TC_YELLOW, TC_ORANGE
 };
 
 void BuildFileList()
@@ -213,6 +212,9 @@
 		case SLD_SAVE_HEIGHTMAP:
 		case SLD_LOAD_HEIGHTMAP:
 			FiosGetHeightmapList(_saveload_mode); break;
+		case SLD_LOAD_TEMPLATE: // TODO: fix saving/loading of templates (game crashes when trying to do so)
+		case SLD_SAVE_TEMPLATE:
+			FiosGetTemplateList(_saveload_mode); break;
 
 		default: FiosGetSavegameList(_saveload_mode); break;
 	}
@@ -265,6 +267,8 @@
 			STR_SAVELOAD_SAVE_SCENARIO,
 			STR_SAVELOAD_LOAD_HEIGHTMAP,
 			STR_SAVELOAD_SAVE_HEIGHTMAP,
+			STR_SAVELOAD_SAVE_COPY_PASTE_TEMPLATE,
+			STR_SAVELOAD_LOAD_COPY_PASTE_TEMPLATE,
 		};
 		assert((uint)mode < lengthof(saveload_captions));
 
@@ -273,6 +277,7 @@
 		switch (mode) {
 			case SLD_SAVE_GAME:     this->GenerateFileName(); break;
 			case SLD_SAVE_HEIGHTMAP:
+			case SLD_SAVE_TEMPLATE:
 			case SLD_SAVE_SCENARIO: strecpy(this->edit_str_buf, "UNNAMED", &this->edit_str_buf[edit_str_size - 1]); break;
 			default:                break;
 		}
@@ -302,6 +307,8 @@
 
 		o_dir.type = FIOS_TYPE_DIRECT;
 		switch (_saveload_mode) {
+			case SLD_SAVE_TEMPLATE:
+			case SLD_LOAD_TEMPLATE:
 			case SLD_SAVE_GAME:
 			case SLD_LOAD_GAME:
 				FioGetDirectory(o_dir.name, lengthof(o_dir.name), SAVE_DIR);
@@ -322,7 +329,7 @@
 		}
 
 		/* Focus the edit box by default in the save windows */
-		if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) {
+		if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP || _saveload_mode == SLD_SAVE_TEMPLATE) {
 			this->SetFocusedWidget(SLWW_SAVE_OSK_TITLE);
 		}
 	}
@@ -507,7 +514,7 @@
 		this->vscroll->SetCount(_fios_items.Length());
 		this->DrawWidgets();
 
-		if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) {
+		if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP || _saveload_mode == SLD_SAVE_TEMPLATE) {
 			this->DrawEditBox(SLWW_SAVE_OSK_TITLE);
 		}
 	}
@@ -573,7 +580,11 @@
 
 							this->InvalidateData(1);
 						}
-						if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) {
+					    if (_saveload_mode == SLD_LOAD_TEMPLATE) {
+							/* Load template file here */
+							_switch_mode = SM_LOAD_TEMPLATE;
+							ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
+						} else if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) {
 							/* Copy clicked name to editbox */
 							ttd_strlcpy(this->text.buf, file->title, this->text.max_bytes);
 							UpdateTextBufferSize(&this->text);
@@ -620,7 +631,7 @@
 
 	virtual void OnMouseLoop()
 	{
-		if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) {
+		if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP || _saveload_mode == SLD_SAVE_TEMPLATE) {
 			this->HandleEditBox(SLWW_SAVE_OSK_TITLE);
 		}
 	}
@@ -633,7 +644,7 @@
 		}
 
 		EventState state = ES_NOT_HANDLED;
-		if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) &&
+		if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP ||_saveload_mode == SLD_SAVE_TEMPLATE) &&
 				this->HandleEditBoxKey(SLWW_SAVE_OSK_TITLE, key, keycode, state) == HEBR_CONFIRM) {
 			this->HandleButtonClick(SLWW_SAVE_GAME);
 		}
@@ -645,7 +656,7 @@
 	{
 		/* This test protects against using widgets 11 and 12 which are only available
 		 * in those saveload modes. */
-		if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP)) return;
+		if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP || _saveload_mode == SLD_SAVE_TEMPLATE)) return;
 
 		if (this->IsWidgetLowered(SLWW_DELETE_SELECTION)) { // Delete button clicked
 			if (!FiosDelete(this->text.buf)) {
@@ -658,7 +669,11 @@
 
 			UpdateTextBufferSize(&this->text);
 		} else if (this->IsWidgetLowered(SLWW_SAVE_GAME)) { // Save button clicked
-			if (_saveload_mode  == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
+			if (_saveload_mode == SLD_SAVE_TEMPLATE) {
+				/* Do Template Saving here */
+				_switch_mode = SM_SAVE_TEMPLATE;
+				FiosMakeSavegameName(_file_to_saveload.name, this->text.buf, sizeof(_file_to_saveload.name));
+			} else if (_saveload_mode  == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
 				_switch_mode = SM_SAVE_GAME;
 				FiosMakeSavegameName(_file_to_saveload.name, this->text.buf, sizeof(_file_to_saveload.name));
 			} else {
@@ -759,6 +774,7 @@
 	const WindowDesc *sld;
 	switch (mode) {
 		case SLD_SAVE_GAME:
+		case SLD_SAVE_TEMPLATE:
 		case SLD_SAVE_SCENARIO:
 		case SLD_SAVE_HEIGHTMAP:
 			sld = &_save_dialog_desc; break;
diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp
--- a/src/genworld_gui.cpp
+++ b/src/genworld_gui.cpp
@@ -20,6 +20,7 @@
 #include "sound_func.h"
 #include "fios.h"
 #include "string_func.h"
+#include "gui.h"
 #include "widgets/dropdown_type.h"
 #include "widgets/dropdown_func.h"
 #include "landscape_type.h"
@@ -129,12 +130,13 @@
 				NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_MAPSIZE, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_LAND_GENERATOR, STR_NULL), SetFill(1, 1),
+					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_TREE_PLACER, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NUMBER_OF_TOWNS, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_TERRAIN_TYPE, STR_NULL), SetFill(1, 1),
+// TODO: put variety back after sea lakes after having created a stacked widget ... for snowline/desert_amount 
+					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_VARIETY, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_RANDOM_SEED, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_QUANTITY_OF_SEA_LAKES, STR_NULL), SetFill(1, 1),
-					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_TREE_PLACER, STR_NULL), SetFill(1, 1),
-					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_VARIETY, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_BORDER_TYPE, STR_NULL), SetFill(1, 1),
 				EndContainer(),
 				/* Widgets at the right of the labels. */
@@ -146,12 +148,13 @@
 						NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_MAPSIZE_Y_PULLDOWN), SetDataTip(STR_JUST_INT, STR_NULL), SetFill(1, 0),
 					EndContainer(),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_LANDSCAPE_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
+					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_TREE_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_TOWN_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_TERRAIN_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
+// TODO: put variety pulldown back after sea lakes after having created a stacked widget ... for snowline/desert_amount 
+					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_VARIETY_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 					NWidget(WWT_EDITBOX, COLOUR_WHITE, GLAND_RANDOM_EDITBOX), SetDataTip(STR_MAPGEN_RANDOM_SEED_OSKTITLE, STR_MAPGEN_RANDOM_SEED_HELP), SetFill(1, 1),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_WATER_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
-					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_TREE_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
-					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, GLAND_VARIETY_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 					NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, GLAND_BORDERS_RANDOM), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 				EndContainer(),
 			EndContainer(),
@@ -159,7 +162,10 @@
 				NWidget(NWID_HORIZONTAL), SetPIP(0, 3, 0),
 					NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0),
 						NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_DATE, STR_NULL), SetFill(1, 1),
+//TODO: make stacked widget snowline / desert_amount here (toggled between Tropic and Arctic)
 						NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SNOW_LINE_HEIGHT, STR_NULL), SetFill(1, 1),
+						NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_DESERT_AMOUNT, STR_NULL), SetFill(1, 1),
+						NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_TREE_LINE_HEIGHT, STR_NULL), SetFill(1, 1),
 						NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NUMBER_OF_INDUSTRIES, STR_NULL), SetFill(1, 1),
 						NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_SMOOTHNESS, STR_NULL), SetFill(1, 1),
 					EndContainer(),
@@ -325,12 +331,37 @@
 	if (confirmed) StartGeneratingLandscape((GenenerateLandscapeWindowMode)w->window_number);
 }
 
-static DropDownList *BuildMapsizeDropDown()
+/**
+ * Check if map size set lies in allowed boundaries.
+ * @param print_warning If set to true, messagebox with warning is printed out if size is outside limits.
+ * @return true if size is ok, false otherwise.
+ */
+static bool CheckMapSize(bool print_warning = true)
+ {
+	uint64 tiles = 1ULL << (_settings_newgame.game_creation.map_x + _settings_newgame.game_creation.map_y);
+
+	if (_settings_newgame.game_creation.map_x + _settings_newgame.game_creation.map_y > MAX_MAP_TILES_BITS) {
+		if (print_warning) {
+			SetDParam(0, MAX_MAP_TILES);
+			SetDParam(1, tiles);
+			ShowErrorMessage(STR_MAPGEN_TOO_MANY_TILES_MESSAGE, INVALID_STRING_ID, WL_ERROR, 0, 0);
+		}
+		return false;
+	}
+	return true;
+}
+
+/**
+ * Build dropdown list with map sizes
+ * Dimension selected in the other dropdown is used to suggest which choices are 'valid'
+ * @param other_dimension Dimension specified by the second dropdown.
+ */
+static DropDownList *BuildMapsizeDropDown(int other_dimension)
 {
 	DropDownList *list = new DropDownList();
 
 	for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) {
-		DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false);
+		DropDownListParamStringItem *item = new DropDownListParamStringItem((i + other_dimension > MAX_MAP_TILES_BITS) ? STR_RED_INT : STR_JUST_INT, i, false);
 		item->SetParam(0, 1 << i);
 		list->push_back(item);
 	}
@@ -358,6 +389,14 @@
 	char name[64];
 	GenenerateLandscapeWindowMode mode;
 
+	void SetDropDownColor()
+	{
+		/* Draw sizes in mapsize selection dropdowns in red if too large size is selected */
+		bool mapsize_valid = CheckMapSize(false);
+		this->GetWidget<NWidgetCore>(GLAND_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
+		this->GetWidget<NWidgetCore>(GLAND_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
+	}
+
 	GenerateLandscapeWindow(const WindowDesc *desc, WindowNumber number = 0) : QueryStringBaseWindow(11)
 	{
 		this->InitNested(desc, number);
@@ -372,6 +411,8 @@
 
 		this->mode = (GenenerateLandscapeWindowMode)this->window_number;
 
+		SetDropDownColor();
+
 		/* Disable town, industry and trees in SE */
 		this->SetWidgetDisabledState(GLAND_TOWN_PULLDOWN,     _game_mode == GM_EDITOR);
 		this->SetWidgetDisabledState(GLAND_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
@@ -380,7 +421,6 @@
 		this->OnInvalidateData();
 	}
 
-
 	virtual void SetStringParameters(int widget) const
 	{
 		switch (widget) {
@@ -388,10 +428,12 @@
 			case GLAND_MAPSIZE_X_PULLDOWN:  SetDParam(0, 1 << _settings_newgame.game_creation.map_x); break;
 			case GLAND_MAPSIZE_Y_PULLDOWN:  SetDParam(0, 1 << _settings_newgame.game_creation.map_y); break;
 			case GLAND_SNOW_LEVEL_TEXT:     SetDParam(0, _settings_newgame.game_creation.snow_line_height); break;
+			case GLAND_DESERT_AMOUNT_TEXT:  SetDParam(0, _settings_newgame.game_creation.desert_amount); break;
+			case GLAND_TREE_LEVEL_TEXT:     SetDParam(0, _settings_newgame.game_creation.tree_line_height); break;
 
 			case GLAND_TOWN_PULLDOWN:
 				if (_game_mode == GM_EDITOR) {
-					SetDParam(0, STR_CONFIG_SETTING_OFF);
+					SetDParam(0, STR_DISASTERS_OFF);
 				} else if (_settings_newgame.difficulty.number_towns == CUSTOM_TOWN_NUMBER_DIFFICULTY) {
 					SetDParam(0, STR_NUM_CUSTOM_NUMBER);
 					SetDParam(1, _settings_newgame.game_creation.custom_town_number);
@@ -400,7 +442,7 @@
 				}
 				break;
 
-			case GLAND_INDUSTRY_PULLDOWN:   SetDParam(0, _game_mode == GM_EDITOR ? STR_CONFIG_SETTING_OFF : _num_inds[_settings_newgame.difficulty.industry_density]); break;
+			case GLAND_INDUSTRY_PULLDOWN:   SetDParam(0, _game_mode == GM_EDITOR ? STR_DISASTERS_OFF : _num_inds[_settings_newgame.difficulty.industry_density]); break;
 			case GLAND_LANDSCAPE_PULLDOWN:  SetDParam(0, _landscape[_settings_newgame.game_creation.land_generator]); break;
 			case GLAND_TREE_PULLDOWN:       SetDParam(0, _tree_placer[_settings_newgame.game_creation.tree_placer]); break;
 			case GLAND_TERRAIN_PULLDOWN:    SetDParam(0, _elevations[_settings_newgame.difficulty.terrain_type]); break;
@@ -469,14 +511,20 @@
 					GLAND_TERRAIN_PULLDOWN, GLAND_WATER_PULLDOWN, WIDGET_LIST_END);
 		}
 
-		/* Disable snowline if not arctic */
+		/* Disable snowline if not arctic. */
 		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _settings_newgame.game_creation.landscape != LT_ARCTIC);
+		/* Disable desertline if not tropic. */
+		this->SetWidgetDisabledState(GLAND_DESERT_AMOUNT_TEXT, _settings_newgame.game_creation.landscape != LT_TROPIC);
 
-		/* Update availability of decreasing / increasing start date and snow level */
-		this->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR);
-		this->SetWidgetDisabledState(GLAND_START_DATE_UP,   _settings_newgame.game_creation.starting_year >= MAX_YEAR);
-		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _settings_newgame.game_creation.snow_line_height <= MIN_SNOWLINE_HEIGHT || _settings_newgame.game_creation.landscape != LT_ARCTIC);
-		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP,   _settings_newgame.game_creation.snow_line_height >= MAX_SNOWLINE_HEIGHT || _settings_newgame.game_creation.landscape != LT_ARCTIC);
+		/* Update availability of decreasing / increasing start date, snow level and treeline level */
+		this->SetWidgetDisabledState(GLAND_START_DATE_DOWN,    _settings_newgame.game_creation.starting_year <= MIN_YEAR);
+		this->SetWidgetDisabledState(GLAND_START_DATE_UP,      _settings_newgame.game_creation.starting_year >= MAX_YEAR);
+		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN,    _settings_newgame.game_creation.snow_line_height <= MIN_SNOWLINE_HEIGHT || _settings_newgame.game_creation.landscape != LT_ARCTIC);
+		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP,      _settings_newgame.game_creation.snow_line_height >= MAX_SNOWLINE_HEIGHT_EXTENDED/*GetMaxSnowlineHeight()*/ || _settings_newgame.game_creation.landscape != LT_ARCTIC);
+		this->SetWidgetDisabledState(GLAND_DESERT_AMOUNT_DOWN, _settings_newgame.game_creation.desert_amount <= MIN_DESERT_AMOUNT || _settings_newgame.game_creation.landscape != LT_TROPIC);
+		this->SetWidgetDisabledState(GLAND_DESERT_AMOUNT_UP,   _settings_newgame.game_creation.desert_amount >= MAX_DESERT_AMOUNT || _settings_newgame.game_creation.landscape != LT_TROPIC);
+		this->SetWidgetDisabledState(GLAND_TREE_LEVEL_DOWN,    _settings_newgame.game_creation.tree_line_height <= MIN_TREELINE_HEIGHT);
+		this->SetWidgetDisabledState(GLAND_TREE_LEVEL_UP,      _settings_newgame.game_creation.tree_line_height >= MAX_TREELINE_HEIGHT_EXTENDED/*GetMaxTreelineHeight()*/);
 
 		/* Do not allow a custom sea level with the original land generator. */
 		if (_settings_newgame.game_creation.land_generator == 0 &&
@@ -502,7 +550,17 @@
 				break;
 
 			case GLAND_SNOW_LEVEL_TEXT:
-				SetDParam(0, MAX_TILE_HEIGHT);
+				SetDParam(0, MAX_SNOWLINE_HEIGHT_EXTENDED/*GetMaxSnowlineHeight()*/);
+				*size = GetStringBoundingBox(STR_JUST_INT);
+				break;
+
+			case GLAND_DESERT_AMOUNT_TEXT:
+				SetDParam(0, MAX_DESERT_AMOUNT);
+				*size = GetStringBoundingBox(STR_JUST_INT);
+				break;
+
+			case GLAND_TREE_LEVEL_TEXT:
+				SetDParam(0, MAX_TREELINE_HEIGHT_EXTENDED/*GetMaxTreelineHeight()*/);
 				*size = GetStringBoundingBox(STR_JUST_INT);
 				break;
 
@@ -585,23 +643,23 @@
 				SetNewLandscapeType(widget - GLAND_TEMPERATE);
 				break;
 
-			case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X
-				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, GLAND_MAPSIZE_X_PULLDOWN);
+			case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X.
+				ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_y), _settings_newgame.game_creation.map_x, GLAND_MAPSIZE_X_PULLDOWN);
 				break;
 
-			case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y
-				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
+			case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y.
+				ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_x), _settings_newgame.game_creation.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
 				break;
 
-			case GLAND_TOWN_PULLDOWN: // Number of towns
+			case GLAND_TOWN_PULLDOWN: // Number of towns.
 				ShowDropDownMenu(this, _num_towns, _settings_newgame.difficulty.number_towns, GLAND_TOWN_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_INDUSTRY_PULLDOWN: // Number of industries
+			case GLAND_INDUSTRY_PULLDOWN: // Number of industries.
 				ShowDropDownMenu(this, _num_inds, _settings_newgame.difficulty.industry_density, GLAND_INDUSTRY_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_RANDOM_BUTTON: // Random seed
+			case GLAND_RANDOM_BUTTON: // Random seed.
 				_settings_newgame.game_creation.generation_seed = InteractiveRandom();
 				snprintf(this->edit_str_buf, this->edit_str_size, "%u", _settings_newgame.game_creation.generation_seed);
 				UpdateTextBufferSize(&this->text);
@@ -636,8 +694,8 @@
 			}
 
 			case GLAND_START_DATE_DOWN:
-			case GLAND_START_DATE_UP: // Year buttons
-				/* Don't allow too fast scrolling */
+			case GLAND_START_DATE_UP: // Year buttons.
+				/* Don't allow too fast scrolling. */
 				if ((this->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER) {
 					this->HandleButtonClick(widget);
 
@@ -647,47 +705,84 @@
 				_left_button_clicked = false;
 				break;
 
-			case GLAND_START_DATE_TEXT: // Year text
+			case GLAND_START_DATE_TEXT: // Year text.
 				this->widget_id = GLAND_START_DATE_TEXT;
 				SetDParam(0, _settings_newgame.game_creation.starting_year);
 				ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
 				break;
 
 			case GLAND_SNOW_LEVEL_DOWN:
-			case GLAND_SNOW_LEVEL_UP: // Snow line buttons
-				/* Don't allow too fast scrolling */
+			case GLAND_SNOW_LEVEL_UP: // Snow line buttons.
+				/* Don't allow too fast scrolling. */
 				if ((this->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER) {
 					this->HandleButtonClick(widget);
 
-					_settings_newgame.game_creation.snow_line_height = Clamp(_settings_newgame.game_creation.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, MIN_SNOWLINE_HEIGHT, MAX_SNOWLINE_HEIGHT);
+					_settings_newgame.game_creation.snow_line_height = Clamp(_settings_newgame.game_creation.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, MIN_SNOWLINE_HEIGHT, MAX_SNOWLINE_HEIGHT_EXTENDED/*GetMaxSnowlineHeight()*/);
 					this->InvalidateData();
 				}
 				_left_button_clicked = false;
 				break;
 
-			case GLAND_SNOW_LEVEL_TEXT: // Snow line text
+			case GLAND_SNOW_LEVEL_TEXT: // Snow line text.
 				this->widget_id = GLAND_SNOW_LEVEL_TEXT;
 				SetDParam(0, _settings_newgame.game_creation.snow_line_height);
-				ShowQueryString(STR_JUST_INT, STR_MAPGEN_SNOW_LINE_QUERY_CAPT, 3, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
+				ShowQueryString(STR_JUST_INT, STR_MAPGEN_SNOW_LINE_QUERY_CAPT, 4, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
 				break;
 
-			case GLAND_TREE_PULLDOWN: // Tree placer
+			case GLAND_DESERT_AMOUNT_DOWN:
+			case GLAND_DESERT_AMOUNT_UP: // Desert amount buttons.
+				/* Don't allow too fast scrolling. */
+				if ((this->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER) {
+					this->HandleButtonClick(widget);
+
+					_settings_newgame.game_creation.desert_amount = Clamp(_settings_newgame.game_creation.desert_amount + widget - GLAND_DESERT_AMOUNT_TEXT, MIN_DESERT_AMOUNT, MAX_DESERT_AMOUNT);
+					this->InvalidateData();
+				}
+				_left_button_clicked = false;
+				break;
+
+			case GLAND_DESERT_AMOUNT_TEXT: // Desert amount text.
+				this->widget_id = GLAND_DESERT_AMOUNT_TEXT;
+				SetDParam(0, _settings_newgame.game_creation.desert_amount);
+				ShowQueryString(STR_JUST_INT, STR_MAPGEN_DESERT_AMOUNT_QUERY_CAPT, 4, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
+				break;
+
+			case GLAND_TREE_LEVEL_DOWN:
+			case GLAND_TREE_LEVEL_UP: // Tree line buttons.
+				/* Don't allow too fast scrolling. */
+				if ((this->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER) {
+					this->HandleButtonClick(widget);
+					this->SetDirty();
+
+					_settings_newgame.game_creation.tree_line_height = Clamp(_settings_newgame.game_creation.tree_line_height + widget - GLAND_TREE_LEVEL_TEXT, MIN_TREELINE_HEIGHT, MAX_TREELINE_HEIGHT_EXTENDED/*GetMaxTreelineHeight()*/);
+					this->InvalidateData();
+				}
+				_left_button_clicked = false;
+				break;
+
+			case GLAND_TREE_LEVEL_TEXT: // Tree line text.
+				this->widget_id = GLAND_TREE_LEVEL_TEXT;
+				SetDParam(0, _settings_newgame.game_creation.tree_line_height);
+				ShowQueryString(STR_JUST_INT, STR_MAPGEN_TREE_LINE_QUERY_CAPT, 4, this, CS_NUMERAL, QSF_NONE);
+				break;			
+
+			case GLAND_TREE_PULLDOWN: // Tree placer.
 				ShowDropDownMenu(this, _tree_placer, _settings_newgame.game_creation.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator
+			case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator.
 				ShowDropDownMenu(this, _landscape, _settings_newgame.game_creation.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_HEIGHTMAP_ROTATION_PULLDOWN: // Heightmap rotation
+			case GLAND_HEIGHTMAP_ROTATION_PULLDOWN: // Heightmap rotation.
 				ShowDropDownMenu(this, _rotation, _settings_newgame.game_creation.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_TERRAIN_PULLDOWN: // Terrain type
+			case GLAND_TERRAIN_PULLDOWN: // Terrain type.
 				ShowDropDownMenu(this, _elevations, _settings_newgame.difficulty.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_WATER_PULLDOWN: { // Water quantity
+			case GLAND_WATER_PULLDOWN: { // Water quantity.
 				uint32 hidden_mask = 0;
 				/* Disable custom water level when the original map generator is active. */
 				if (_settings_newgame.game_creation.land_generator == 0) {
@@ -701,15 +796,15 @@
 				ShowDropDownMenu(this, _rivers, _settings_newgame.game_creation.amount_of_rivers, GLAND_RIVER_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness
+			case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness.
 				ShowDropDownMenu(this, _smoothness, _settings_newgame.game_creation.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0);
 				break;
 
-			case GLAND_VARIETY_PULLDOWN: // Map variety
+			case GLAND_VARIETY_PULLDOWN: // Map variety.
 				ShowDropDownMenu(this, _variety, _settings_newgame.game_creation.variety, GLAND_VARIETY_PULLDOWN, 0, 0);
 				break;
 
-			/* Freetype map borders */
+			/* Freetype map borders. */
 			case GLAND_WATER_NW:
 				_settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_NW);
 				this->InvalidateData();
@@ -739,7 +834,7 @@
 
 	virtual void OnTimeout()
 	{
-		static const int raise_widgets[] = {GLAND_START_DATE_DOWN, GLAND_START_DATE_UP, GLAND_SNOW_LEVEL_UP, GLAND_SNOW_LEVEL_DOWN, WIDGET_LIST_END};
+		static const int raise_widgets[] = {GLAND_START_DATE_DOWN, GLAND_START_DATE_UP, GLAND_SNOW_LEVEL_UP, GLAND_SNOW_LEVEL_DOWN, GLAND_DESERT_AMOUNT_UP, GLAND_DESERT_AMOUNT_DOWN, GLAND_TREE_LEVEL_UP, GLAND_TREE_LEVEL_DOWN, WIDGET_LIST_END};
 		for (const int *widget = raise_widgets; *widget != WIDGET_LIST_END; widget++) {
 			if (this->IsWidgetLowered(*widget)) {
 				this->RaiseWidget(*widget);
@@ -794,6 +889,12 @@
 				GameMode old_gm = _game_mode;
 				_game_mode = GM_MENU;
 				IConsoleSetSetting("difficulty.terrain_type", index);
+				/* If landgenerator is original and mountainous or alpinist terrain_type is selected, revert to hilly. */
+				/*TODO: instead of reverting on selection, grey out selections or use seperate array? */
+				if ((_settings_newgame.game_creation.land_generator == 0) &&
+						(_settings_newgame.difficulty.terrain_type == 5 || _settings_newgame.difficulty.terrain_type == 6)) {
+					_settings_newgame.difficulty.terrain_type = 4;
+				}
 				_game_mode = old_gm;
 				break;
 			}
@@ -826,7 +927,25 @@
 			/* An empty string means revert to the default */
 			switch (this->widget_id) {
 				case GLAND_START_DATE_TEXT: value = DEF_START_YEAR; break;
-				case GLAND_SNOW_LEVEL_TEXT: value = DEF_SNOWLINE_HEIGHT; break;
+
+				case GLAND_SNOW_LEVEL_TEXT:
+					if(AllowMoreHeightlevels()) {
+						value = DEF_SNOWLINE_HEIGHT_EXTENDED;
+					} else {
+						value = DEF_SNOWLINE_HEIGHT_OLD;
+					}
+					break;
+
+				case GLAND_DESERT_AMOUNT_TEXT: value = DEF_DESERT_AMOUNT; break;
+
+				case GLAND_TREE_LEVEL_TEXT:
+					if (AllowMoreHeightlevels()) {
+						value = DEF_TREELINE_HEIGHT_EXTENDED;
+					}else{
+						value = DEF_TREELINE_HEIGHT_OLD;
+					}
+					break;
+
 				case GLAND_TOWN_PULLDOWN:   value = 1; break;
 				case GLAND_WATER_PULLDOWN:  value = CUSTOM_SEA_LEVEL_MIN_PERCENTAGE; break;
 				default: NOT_REACHED();
@@ -841,7 +960,17 @@
 
 			case GLAND_SNOW_LEVEL_TEXT:
 				this->SetWidgetDirty(GLAND_SNOW_LEVEL_TEXT);
-				_settings_newgame.game_creation.snow_line_height = Clamp(value, MIN_SNOWLINE_HEIGHT, MAX_SNOWLINE_HEIGHT);
+				_settings_newgame.game_creation.snow_line_height = Clamp(value, MIN_SNOWLINE_HEIGHT, MAX_SNOWLINE_HEIGHT_EXTENDED/*GetMaxSnowlineHeight()*/);
+				break;
+
+			case GLAND_DESERT_AMOUNT_TEXT:
+				this->SetWidgetDirty(GLAND_DESERT_AMOUNT_TEXT);
+				_settings_newgame.game_creation.desert_amount = Clamp(value, MIN_DESERT_AMOUNT, MAX_DESERT_AMOUNT);
+				break;
+
+			case GLAND_TREE_LEVEL_TEXT:
+				this->SetWidgetDirty(GLAND_TREE_LEVEL_TEXT);
+				_settings_newgame.game_creation.tree_line_height = Clamp(value, MIN_TREELINE_HEIGHT, MAX_TREELINE_HEIGHT_EXTENDED/*GetMaxTreelineHeight()*/);
 				break;
 
 			case GLAND_TOWN_PULLDOWN:
@@ -878,8 +1007,8 @@
 
 	DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
 
-	/* Always give a new seed if not editor */
-	if (_game_mode != GM_EDITOR) _settings_newgame.game_creation.generation_seed = InteractiveRandom();
+	/* Always give a new seed if not editor */ // TODO: make this a setting in advanced settings
+//	if (_game_mode != GM_EDITOR) _settings_newgame.game_creation.generation_seed = InteractiveRandom();
 
 	if (mode == GLWM_HEIGHTMAP) {
 		/* If the function returns negative, it means there was a problem loading the heightmap */
@@ -950,10 +1079,19 @@
 {
 	uint widget_id;
 
+	void SetDropDownColor()
+	{
+		/* Draw sizes in mapsize selection dropdowns in red if too large size is selected */
+		bool mapsize_valid = CheckMapSize(false);
+		this->GetWidget<NWidgetCore>(CSCEN_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
+		this->GetWidget<NWidgetCore>(CSCEN_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
+	}
+
 	CreateScenarioWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
 	{
 		this->InitNested(desc, window_number);
 		this->LowerWidget(_settings_newgame.game_creation.landscape + CSCEN_TEMPERATE);
+		SetDropDownColor();
 	}
 
 	virtual void SetStringParameters(int widget) const
@@ -982,7 +1120,7 @@
 		this->SetWidgetDisabledState(CSCEN_START_DATE_DOWN,       _settings_newgame.game_creation.starting_year <= MIN_YEAR);
 		this->SetWidgetDisabledState(CSCEN_START_DATE_UP,         _settings_newgame.game_creation.starting_year >= MAX_YEAR);
 		this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _settings_newgame.game_creation.se_flat_world_height <= 0);
-		this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP,   _settings_newgame.game_creation.se_flat_world_height >= MAX_TILE_HEIGHT);
+		this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP,   _settings_newgame.game_creation.se_flat_world_height >= GetMaxTileHeight());
 
 		this->SetWidgetLoweredState(CSCEN_TEMPERATE, _settings_newgame.game_creation.landscape == LT_TEMPERATE);
 		this->SetWidgetLoweredState(CSCEN_ARCTIC,    _settings_newgame.game_creation.landscape == LT_ARCTIC);
@@ -1007,7 +1145,11 @@
 				break;
 
 			case CSCEN_FLAT_LAND_HEIGHT_TEXT:
-				SetDParam(0, MAX_TILE_HEIGHT);
+				if (AllowMoreHeightlevels()) {
+					SetDParam(0, MAX_TILE_HEIGHT_EXTENDED);
+				} else {
+					SetDParam(0, MAX_TILE_HEIGHT_OLD);
+				}
 				break;
 
 			default:
@@ -1030,18 +1172,20 @@
 				break;
 
 			case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X
-				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
+				ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_y), _settings_newgame.game_creation.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
 				break;
 
 			case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y
-				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
+				ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_x), _settings_newgame.game_creation.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
 				break;
 
 			case CSCEN_EMPTY_WORLD: // Empty world / flat world
+				if (!CheckMapSize()) break;
 				StartGeneratingLandscape(GLWM_SCENARIO);
 				break;
 
 			case CSCEN_RANDOM_WORLD: // Generate
+				if (!CheckMapSize()) break;
 				ShowGenerateLandscape();
 				break;
 
@@ -1070,7 +1214,7 @@
 					this->HandleButtonClick(widget);
 					this->SetDirty();
 
-					_settings_newgame.game_creation.se_flat_world_height = Clamp(_settings_newgame.game_creation.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
+					_settings_newgame.game_creation.se_flat_world_height = Clamp(_settings_newgame.game_creation.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, GetMaxTileHeight());
 				}
 				_left_button_clicked = false;
 				break;
@@ -1078,7 +1222,7 @@
 			case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
 				this->widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
 				SetDParam(0, _settings_newgame.game_creation.se_flat_world_height);
-				ShowQueryString(STR_JUST_INT, STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, this, CS_NUMERAL, QSF_NONE);
+				ShowQueryString(STR_JUST_INT, STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_QUERY_CAPT, 4, this, CS_NUMERAL, QSF_NONE);
 				break;
 		}
 	}
@@ -1100,6 +1244,8 @@
 			case CSCEN_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break;
 			case CSCEN_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
 		}
+		SetDropDownColor();
+
 		this->SetDirty();
 	}
 
@@ -1116,7 +1262,7 @@
 
 				case CSCEN_FLAT_LAND_HEIGHT_TEXT:
 					this->SetWidgetDirty(CSCEN_FLAT_LAND_HEIGHT_TEXT);
-					_settings_newgame.game_creation.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
+					_settings_newgame.game_creation.se_flat_world_height = Clamp(value, 0, GetMaxTileHeight());
 					break;
 			}
 
diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp
--- a/src/gfxinit.cpp
+++ b/src/gfxinit.cpp
@@ -158,6 +158,9 @@
 	_palette_remap_grf[i] = (PAL_DOS != used_set->palette);
 	LoadGrfFile(used_set->files[GFT_LOGOS].filename, 4793, i++);
 
+	/* Blacktileset comlete all slopes. */
+	LoadGrfFile("flat_blacktiles.grf", SPR_FLAT_BLACKTILES, i++);
+
 	/*
 	 * Load additional sprites for climates other than temperate.
 	 * This overwrites some of the temperate sprites, such as foundations
@@ -175,6 +178,17 @@
 	/* Initialize the unicode to sprite mapping table */
 	InitializeUnicodeGlyphMap();
 
+	/* Load CopyPaste graphics. */
+	LoadGrfFile("copypaste.grf", SPR_COPYPASTE_BASE, i++);
+
+	/* Load traffic lights graphics. */
+	LoadGrfFile("trafficlights.grf", SPR_TRAFFICLIGHTS_BASE, i++);
+
+    /* load speedsign graphcs. */
+	LoadGrfFile("speedsignals.grf", SPR_SPEEDSIGNAL_BASE, i++);
+
+    /* load speedsign graphcs. */
+	LoadGrfFile("progsignals.grf", SPR_PROGSIGNAL_BASE, i++);
 	/*
 	 * Load the base NewGRF with OTTD required graphics as first NewGRF.
 	 * However, we do not want it to show up in the list of used NewGRFs,
diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp
--- a/src/ground_vehicle.cpp
+++ b/src/ground_vehicle.cpp
@@ -15,6 +15,30 @@
 #include "vehicle_gui.h"
 #include "window_func.h"
 
+template <class T, VehicleType Type>
+void GroundVehicle<T, Type>::CalculatePower(uint32& total_power, uint32& max_te, bool breakdowns) const {
+
+	total_power = 0;
+	max_te = 0;
+    
+	const T *v = T::From(this);
+
+	for (const T *u = v; u != NULL; u = u->Next()) {
+		uint32 current_power = u->GetPower() + u->GetPoweredPartPower(u);
+		total_power += current_power;
+
+		/* Only powered parts add tractive effort. */
+		if (current_power > 0) max_te += u->GetWeight() * u->GetTractiveEffort();
+		
+		if (breakdowns && u->breakdown_ctr == 1 && u->breakdown_type == BREAKDOWN_LOW_POWER) {
+			total_power = total_power * u->breakdown_severity / 256;
+		}
+	}
+
+	max_te *= 10000; // Tractive effort in (tonnes * 1000 * 10 =) N.
+	max_te /= 256;   // Tractive effort is a [0-255] coefficient.
+}
+
 /**
  * Recalculates the cached total power of a vehicle. Should be called when the consist is changed.
  */
@@ -29,12 +53,9 @@
 	uint32 number_of_parts = 0;
 	uint16 max_track_speed = v->GetDisplayMaxSpeed();
 
+	this->CalculatePower(total_power, max_te, false);
+
 	for (const T *u = v; u != NULL; u = u->Next()) {
-		uint32 current_power = u->GetPower() + u->GetPoweredPartPower(u);
-		total_power += current_power;
-
-		/* Only powered parts add tractive effort. */
-		if (current_power > 0) max_te += u->GetWeight() * u->GetTractiveEffort();
 		number_of_parts++;
 
 		/* Get minimum max speed for this track. */
@@ -57,8 +78,6 @@
 
 	this->gcache.cached_air_drag = air_drag + 3 * air_drag * number_of_parts / 20;
 
-	max_te *= 10000; // Tractive effort in (tonnes * 1000 * 10 =) N.
-	max_te /= 256;   // Tractive effort is a [0-255] coefficient.
 	if (this->gcache.cached_power != total_power || this->gcache.cached_max_te != max_te) {
 		/* Stop the vehicle if it has no power. */
 		if (total_power == 0) this->vehstatus |= VS_STOPPED;
@@ -103,7 +122,7 @@
  * @return Current acceleration of the vehicle.
  */
 template <class T, VehicleType Type>
-int GroundVehicle<T, Type>::GetAcceleration() const
+int GroundVehicle<T, Type>::GetAcceleration()
 {
 	/* Templated class used for function calls for performance reasons. */
 	const T *v = T::From(this);
@@ -113,7 +132,8 @@
 	int32 mass = this->gcache.cached_weight;
 
 	/* Power is stored in HP, we need it in watts. */
-	int32 power = this->gcache.cached_power * 746;
+	uint32 power = this->gcache.cached_power * 746;
+	uint32 max_te = this->gcache.cached_max_te; // [N]
 
 	int32 resistance = 0;
 
@@ -134,13 +154,19 @@
 	/* This value allows to know if the vehicle is accelerating or braking. */
 	AccelStatus mode = v->GetAccelerationStatus();
 
-	const int max_te = this->gcache.cached_max_te; // [N]
+	/* Handle breakdown power reduction. */
+	if(  Type == VEH_TRAIN  && mode == AS_ACCEL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) {
+		/* TODO: We'd like to cache this, but changing cached_power has too many unwanted side-effects. */
+		this->CalculatePower(power, max_te, true);
+		power *= 746;
+	}
+	
 	int force;
 	if (speed > 0) {
 		if (!maglev) {
 			/* Conversion factor from km/h to m/s is 5/18 to get [N] in the end. */
 			force = power * 18 / (speed * 5);
-			if (mode == AS_ACCEL && force > max_te) force = max_te;
+			if (mode == AS_ACCEL && force > (int)max_te) force = max_te;
 		} else {
 			force = power / 25;
 		}
@@ -150,6 +176,33 @@
 		force = max(force, (mass * 8) + resistance);
 	}
 
+	/* If power is 0 because of a breakdown, we make the force 0 if accelerating. */
+	if ( Type == VEH_TRAIN && mode == AS_ACCEL && HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER) && power == 0) {
+		force = 0;
+	}
+
+	/* Calculate the breakdown chance. */
+	if (_settings_game.vehicle.improved_breakdowns) {
+		assert(this->gcache.cached_max_track_speed > 0);
+		/* First, calculate (resistance / force * current speed / max speed) << 16.
+		 * This yields a number x on a 0-1 scale, but shifted 16 bits to the left.
+		 * We then calculate 64 + 128x, clamped to 0-255, but still shifted 16 bits to the left.
+		 * Then we apply a correction for multiengine trains, and in the end we shift it 16 bits to the right to get a 0-255 number.
+		 * @note A seperate correction for multiheaded engines is done in CheckVehicleBreakdown. We can't do that here because it would affect the whole consist. */
+		uint64 breakdown_factor = (uint64)abs(resistance) * (uint64)(this->cur_speed << 16);
+		breakdown_factor /= (max(force, 100) * this->gcache.cached_max_track_speed);
+		breakdown_factor = min((64 << 16) + (breakdown_factor * 128), 255 << 16);
+		if ( Type == VEH_TRAIN && Train::From(this)->tcache.cached_num_engines > 1) {
+			/* For multiengine trains, breakdown chance is multiplied by 3 / (num_engines + 2). */
+			breakdown_factor *= 3;
+			breakdown_factor /= (Train::From(this)->tcache.cached_num_engines + 2);
+		}
+		/* Breakdown_chance is at least 5 (5 / 128 = ~4% of the normal chance). */
+		this->breakdown_chance = max(breakdown_factor >> 16, (uint64)5);
+	} else {
+		this->breakdown_chance = 128;
+	}
+
 	if (mode == AS_ACCEL) {
 		/* Easy way out when there is no acceleration. */
 		if (force == resistance) return 0;
@@ -160,7 +213,25 @@
 		 * a hill will never speed up enough to (eventually) get back to the
 		 * same (maximum) speed. */
 		int accel = (force - resistance) / (mass * 4);
-		return force < resistance ? min(-1, accel) : max(1, accel);
+		accel = force < resistance ? min(-1, accel) : max(1, accel);
+		if (this->type == VEH_TRAIN ) {
+			if(_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL &&
+				HasBit(Train::From(this)->flags, VRF_BREAKDOWN_POWER)) {
+				/* We need to apply the power reducation for non-realistic acceleration here. */
+				CalculatePower(power, max_te, true);
+				accel = accel * power / this->gcache.cached_power;
+				accel -= this->acceleration >> 1;
+			}
+
+			if ( this->IsFrontEngine() && !(this->current_order_time & 0x1FF) &&
+				!(this->current_order.IsType(OT_LOADING)) &&
+				!(Train::From(this)->flags & (VRF_IS_BROKEN | (1 << VRF_TRAIN_STUCK))) &&
+				this->cur_speed < 3 && accel < 5) {
+				SetBit(Train::From(this)->flags, VRF_TO_HEAVY);
+			}
+		}
+
+		return accel;
 	} else {
 		return min(-force - resistance, -10000) / mass;
 	}
diff --git a/src/ground_vehicle.hpp b/src/ground_vehicle.hpp
--- a/src/ground_vehicle.hpp
+++ b/src/ground_vehicle.hpp
@@ -90,7 +90,8 @@
 
 	void PowerChanged();
 	void CargoChanged();
-	int GetAcceleration() const;
+	void CalculatePower(uint32& power, uint32& max_te, bool breakdowns) const;
+	int GetAcceleration();
 
 	/**
 	 * Common code executed for crashed ground vehicles
@@ -229,9 +230,9 @@
 	 * @param turned Indicates if the vehicle has turned.
 	 * @return Old height of the vehicle.
 	 */
-	FORCEINLINE byte UpdateInclination(bool new_tile, bool turned)
+	FORCEINLINE int32 UpdateInclination(bool new_tile, bool turned)
 	{
-		byte old_z = this->z_pos;
+		int32 old_z = this->z_pos;
 
 		if (new_tile) {
 			this->UpdateZPositionAndInclination();
@@ -367,7 +368,23 @@
 
 		/* When we are going faster than the maximum speed, reduce the speed
 		 * somewhat gradually. But never lower than the maximum speed. */
-		int tempmax = max_speed;
+		int tempmax = ((this->breakdown_ctr == 1) ? this->cur_speed : max_speed);
+
+		if (this->breakdown_ctr == 1) {
+			if (this->breakdown_type == BREAKDOWN_LOW_POWER) {
+				if((this->tick_counter & 0x7) == 0) {
+					if(this->cur_speed > (this->breakdown_severity * max_speed) >> 8) {
+						tempmax = this->cur_speed - (this->cur_speed / 10) - 1;
+					} else {
+						tempmax = (this->breakdown_severity * max_speed) >> 8;
+					}
+				}
+			}
+
+			if(this->breakdown_type == BREAKDOWN_LOW_SPEED)
+				tempmax = min(max_speed, this->breakdown_severity);
+		}
+
 		if (this->cur_speed > max_speed) {
 			tempmax = max(this->cur_speed - (this->cur_speed / 10) - 1, max_speed);
 		}
diff --git a/src/group_gui.cpp b/src/group_gui.cpp
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -51,6 +51,7 @@
 	GRP_WIDGET_DELETE_GROUP,
 	GRP_WIDGET_RENAME_GROUP,
 	GRP_WIDGET_REPLACE_PROTECTION,
+	GRP_WIDGET_GROUP_INFO,
 };
 
 static const NWidgetPart _nested_group_widgets[] = {
@@ -71,6 +72,7 @@
 						SetFill(1, 0), SetResize(0, 1), SetScrollbar(GRP_WIDGET_LIST_GROUP_SCROLLBAR),
 				NWidget(NWID_VSCROLLBAR, COLOUR_GREY, GRP_WIDGET_LIST_GROUP_SCROLLBAR),
 			EndContainer(),
+			NWidget(WWT_PANEL, COLOUR_GREY, GRP_WIDGET_GROUP_INFO), SetMinimalSize(200, 25), SetFill(1, 1), EndContainer(),
 			NWidget(NWID_HORIZONTAL),
 				NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, GRP_WIDGET_CREATE_GROUP), SetMinimalSize(24, 25), SetFill(0, 1),
 						SetDataTip(SPR_GROUP_CREATE_TRAIN, STR_GROUP_CREATE_TOOLTIP),
@@ -323,6 +325,40 @@
 		*this->sorting = this->vehicles.GetListing();
 	}
 
+	/** draw the group profit button in the group list window. */
+	virtual void DrawGroupProfitButton(int x, int y, GroupID gid, VehicleType vtype) const
+	{
+		Date max_age = 0;                                   ///< Age of the oldest vehicle in the group
+		Money this_year_profit = 0;                         ///< Total profit for the group this year
+		int vehicle_count = 0;                              ///< Vehicle count in the group
+
+		const Vehicle *v;
+		FOR_ALL_VEHICLES(v) {
+			if (v->owner == this->owner) {
+				if ((gid == ALL_GROUP  && v->type == vtype)|| v->group_id == gid) {
+					this_year_profit += v->GetDisplayProfitLastYear();
+					if (v->age > max_age) max_age = v->age;
+					vehicle_count++;
+				}
+			}
+		}
+
+		/* Draw button */
+		SpriteID spr;
+
+		/* draw profit-based coloured icons */
+		if (max_age <= DAYS_IN_YEAR * 2) {
+			spr = SPR_PROFIT_NA;
+		} else if (this_year_profit < 0) {
+			spr = SPR_PROFIT_NEGATIVE;
+		} else if (this_year_profit < 10000 * vehicle_count) {
+			spr = SPR_PROFIT_SOME;
+		} else {
+			spr = SPR_PROFIT_LOT;
+		}
+		DrawSprite(spr, PAL_NONE, x, y);
+	}
+
 	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
 	{
 		switch (widget) {
diff --git a/src/gui.h b/src/gui.h
--- a/src/gui.h
+++ b/src/gui.h
@@ -18,6 +18,7 @@
 #include "tile_type.h"
 #include "strings_type.h"
 #include "transport_type.h"
+#include "rail.h"
 
 struct Window;
 
@@ -45,9 +46,14 @@
 void ShowGenerateLandscape();
 void ShowHeightmapLoad();
 
+/* copy_paste_gui.cpp */
+void ShowCopyPasteToolbarGui();        // Using the buttons in terraform_gui.cpp
+void ShowCopyPasteToolbar(int button); // Using the shortcuts
+
 /* misc_gui.cpp */
 void ShowLandInfo(TileIndex tile);
 void ShowAboutWindow();
+void ShowSystemTimeWindow();
 void ShowBuildTreesToolbar();
 void ShowTownDirectory();
 void ShowIndustryDirectory();
diff --git a/src/heightmap.cpp b/src/heightmap.cpp
--- a/src/heightmap.cpp
+++ b/src/heightmap.cpp
@@ -361,8 +361,14 @@
 				assert(img_row < img_height);
 				assert(img_col < img_width);
 
-				/* Colour scales from 0 to 255, OpenTTD height scales from 0 to 15 */
-				SetTileHeight(tile, map[img_row * img_width + img_col] / 16);
+				/* Colour scales from 0 to 255, OpenTTD height scales from 0 to 15.
+				 * Heightlevelspatch scales according to terrain_type selected in difficulty settings.(0-255)
+				 * @see _max_heightmap_height[] in heightmap.h */
+				if (AllowMoreHeightlevels()) {
+					SetTileHeight(tile, map[img_row * img_width + img_col] / (_max_heightmap_height[_settings_game.difficulty.terrain_type]));
+				} else {
+					SetTileHeight(tile, map[img_row * img_width + img_col] / 16);
+				}
 			}
 			/* Only clear the tiles within the map area. */
 			if (TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY() &&
@@ -390,7 +396,7 @@
 	/* Top and left edge */
 	for (row = 0; (uint)row < height; row++) {
 		for (col = 0; (uint)col < width; col++) {
-			current_tile = MAX_TILE_HEIGHT;
+			current_tile = GetMaxTileHeight();
 			if (col != 0) {
 				/* Find lowest tile; either the top or left one */
 				current_tile = TileHeight(TileXY(col - 1, row)); // top edge
@@ -412,7 +418,7 @@
 	/* Bottom and right edge */
 	for (row = height - 1; row >= 0; row--) {
 		for (col = width - 1; col >= 0; col--) {
-			current_tile = MAX_TILE_HEIGHT;
+			current_tile = GetMaxTileHeight();
 			if ((uint)col != width - 1) {
 				/* Find lowest tile; either the bottom and right one */
 				current_tile = TileHeight(TileXY(col + 1, row)); // bottom edge
diff --git a/src/heightmap.h b/src/heightmap.h
--- a/src/heightmap.h
+++ b/src/heightmap.h
@@ -21,6 +21,19 @@
 	HM_CLOCKWISE,         ///< Rotate the map clockwise 45 degrees
 };
 
+/** 
+ * Desired maximum height when generating a heightmap.
+ */
+static const uint8 _max_heightmap_height[7] = {
+64, ///< Fallen
+32, ///< Very flat
+16, ///< Flat
+8,  ///< Hilly
+4,  ///< Bumpy
+2,  ///< Mountainous
+1,  ///< Alpinist
+};
+
 bool GetHeightmapDimensions(char *filename, uint *x, uint *y);
 void LoadHeightmap(char *filename);
 void FlatEmptyWorld(byte tile_height);
diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -39,6 +39,7 @@
 #include "subsidy_func.h"
 #include "core/backup_type.hpp"
 #include "object_base.h"
+#include "tgp.h"
 
 #include "table/strings.h"
 #include "table/industry_land.h"
@@ -1457,6 +1458,22 @@
 
 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
 {
+	/* Max. allowed delta when levelling land.
+	 * @see comment in industry_type.h for more information why we need this. */
+	uint max_delta;
+
+	if (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world) {
+		if (_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_VERY_ROUGH) {
+			max_delta = IND_MAX_LEVELLING_VERY_ROUGH;
+		} else if (_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_CEREALLY_ROUGH) {
+			max_delta = IND_MAX_LEVELLING_CEREALLY_ROUGH;
+		} else {
+			max_delta = IND_MAX_LEVELLING_NORMAL;
+		}
+	} else {
+		max_delta = IND_MAX_LEVELLING_NORMAL;
+	}
+
 	/* Check if we don't leave the map */
 	if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
 
@@ -1467,7 +1484,11 @@
 		if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
 
 		/* Don't allow too big of a change if this is the sub-tile check */
-		if (internal != 0 && Delta(curh, height) > 1) return false;
+		uint8 IND_LEVELLING_MAX_HEIGHT  = _settings_game.construction.extra_industry_placement_logic; ///< Height limit for applying the extra logic.
+		if (internal != 0 && ((height < IND_LEVELLING_MAX_HEIGHT && Delta(curh, height) > max_delta)
+				||  (height >= IND_LEVELLING_MAX_HEIGHT && Delta(curh, height) > IND_MAX_LEVELLING_NORMAL))) {
+			return false;
+		}
 
 		/* Different height, so the surrounding tiles of this tile
 		 *  has to be correct too (in level, or almost in level)
diff --git a/src/industry_type.h b/src/industry_type.h
--- a/src/industry_type.h
+++ b/src/industry_type.h
@@ -33,4 +33,19 @@
 
 static const int INDUSTRY_COMPLETED = 3; ///< final stage of industry construction.
 
+/**
+ * When building a new industry, the game tries to level an appropriate place,
+ * if and only if there is no need to change the height of any tile by more
+ * than some given number of heightlevels. This number is defined here.
+ * Why do we need values > 1? Because when generating very rough maps, the game
+ * may run out of appropriate places for industries.
+ * And finally, to prevent industries at unrealistic heightlevels, we apply
+ * this extra logic only if we are below the heightlevel set in Advanced settings->Economy->Industries.
+ */
+enum IndustryMaxLevelling {
+	IND_MAX_LEVELLING_NORMAL         = 1,  ///< Usual behaviour
+	IND_MAX_LEVELLING_VERY_ROUGH     = 3,  ///< When generating a very rough map using TerraGenesis
+	IND_MAX_LEVELLING_CEREALLY_ROUGH = 4,  ///< When generating a cereally rough map using TerraGenesis
+};
+
 #endif /* INDUSTRY_TYPE_H */
diff --git a/src/infrastructure.cpp b/src/infrastructure.cpp
new file mode 100644
--- /dev/null
+++ b/src/infrastructure.cpp
@@ -0,0 +1,330 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file infrastructure.cpp Implementation of infrastructure sharing */
+
+#include "stdafx.h"
+#include "infrastructure_func.h"
+#include "train.h"
+#include "aircraft.h"
+#include "vehicle_func.h"
+#include "station_base.h"
+#include "depot_base.h"
+#include "pbs.h"
+#include "signal_func.h"
+#include "window_func.h"
+#include "gui.h"
+#include "pathfinder/yapf/yapf_cache.h"
+#include "company_base.h"
+
+#include "table/strings.h"
+
+/**
+ * Helper function for transferring sharing fees
+ * @param v The vehicle involved
+ * @param infra_owner The owner of the infrastructure
+ * @param cost Amount to transfer as money fraction (shifted 8 bits to the left)
+ */
+static void PaySharingFee(Vehicle *v, Owner infra_owner, Money cost)
+{
+	Company *c = Company::Get(v->owner);
+	if (!_settings_game.economy.sharing_payment_in_debt) {
+		/* Do not allow fee payment to drop (money - loan) below 0. */
+		cost = min(cost, (c->money - c->current_loan) << 8);
+		if (cost <= 0) return;
+	}
+	v->profit_this_year -= cost;
+	SubtractMoneyFromCompanyFract(v->owner, CommandCost(EXPENSES_SHARING_COST, cost));
+	SubtractMoneyFromCompanyFract(infra_owner, CommandCost(EXPENSES_SHARING_INC, -cost));
+}
+
+/**
+ * Pay the fee for spending a single tick inside a station.
+ * @param v The vehicle that is using the station.
+ * @param st The station that it uses.
+ */
+void PayStationSharingFee(Vehicle *v, const Station *st)
+{
+	if (v->owner == st->owner || st->owner == OWNER_NONE || v->type == VEH_TRAIN) return;
+	Money cost = _settings_game.economy.sharing_fee[v->type];
+	PaySharingFee(v, st->owner, (cost << 8) / DAY_TICKS);
+}
+
+/**
+ * Pay the daily fee for trains on foreign tracks.
+ * @param v The vehicle to pay the fee for.
+ */
+void PayDailyTrackSharingFee(Train *v)
+{
+	Owner owner = GetTileOwner(v->tile);
+	if (owner == v->owner) return;
+	Money cost = _settings_game.economy.sharing_fee[VEH_TRAIN] << 8;
+	/* Cost is calculated per 1000 tonnes */
+	cost = cost * v->gcache.cached_weight / 1000;
+	/* Only pay the required fraction */
+	cost = cost * v->running_ticks / DAY_TICKS;
+	if (cost != 0) PaySharingFee(v, owner, cost);
+}
+
+/**
+ * Check whether a vehicle is in an allowed position.
+ * @param v     The vehicle to check.
+ * @param owner Owner whose infrastructure is not allowed, because the company will be removed. Ignored if INVALID_OWNER.
+ * @return      True if the vehicle is compeletely in an allowed position.
+ */
+static bool VehiclePositionIsAllowed(const Vehicle *v, Owner owner = INVALID_OWNER)
+{
+	switch (v->type) {
+		case VEH_TRAIN:
+			for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+				if (!IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, u->tile) || GetTileOwner(u->tile) == owner) return false;
+			}
+			return true;
+		case VEH_ROAD:
+			for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+				if (IsRoadDepotTile(u->tile) || IsStandardRoadStopTile(u->tile)) {
+					if (!IsInfraTileUsageAllowed(VEH_ROAD, v->owner, u->tile) || GetTileOwner(u->tile) == owner) return false;
+				}
+			}
+			return true;
+		case VEH_SHIP:
+			if (IsShipDepotTile(v->tile) && v->IsStoppedInDepot()) {
+				if (!IsInfraTileUsageAllowed(VEH_SHIP, v->owner, v->tile) || GetTileOwner(v->tile) == owner) return false;
+			}
+			return true;
+		case VEH_AIRCRAFT: {
+			const Aircraft *a = Aircraft::From(v);
+			if (a->state != FLYING && Station::IsValidID(a->targetairport)) {
+				Owner station_owner = Station::Get(a->targetairport)->owner;
+				if (!IsInfraUsageAllowed(VEH_AIRCRAFT, a->owner, station_owner) || station_owner == owner) return false;
+			}
+			return true;
+		}
+		default: return true;
+	}
+}
+
+/**
+ * Check whether an order has a destination that is allowed.
+ * I.e. it refers to a station/depot/waypoint the vehicle is allowed to visit.
+ * @param order The order to check
+ * @param v     The vehicle this order belongs to.
+ * @param owner Owner whose infrastructure is not allowed, because the company will be removed. Ignored if INVALID_OWNER.
+ * @return      True if the order has an allowed destination.
+ */
+static bool OrderDestinationIsAllowed(const Order *order, const Vehicle *v, Owner owner = INVALID_OWNER)
+{
+	Owner dest_owner;
+	switch (order->GetType()) {
+		case OT_GOTO_STATION:
+		case OT_GOTO_WAYPOINT: dest_owner = BaseStation::Get(order->GetDestination())->owner; break;
+		case OT_GOTO_DEPOT:    dest_owner = (v->type == VEH_AIRCRAFT) ? Station::Get(order->GetDestination())->owner : GetTileOwner(Depot::Get(order->GetDestination())->xy); break;
+		case OT_LOADING:       dest_owner = Station::Get(v->last_station_visited)->owner; break;
+		default: return true;
+	}
+	return dest_owner != owner && IsInfraUsageAllowed(v->type, v->owner, dest_owner);
+}
+
+/**
+ * Sell a vehicle, no matter where it may be.
+ * @param v The vehicle to sell
+ * @param give_money Do we actually need to give money to the vehicle owner?
+ */
+static void RemoveAndSellVehicle(Vehicle *v, bool give_money)
+{
+	assert(v->Previous() == NULL);
+
+	if (give_money) {
+		/* compute total value and give that to the owner */
+		Money value = 0;
+		for (Vehicle *u = v->First(); u != NULL; u = u->Next()) {
+			value += v->value;
+		}
+		CompanyID old = _current_company;
+		_current_company = v->owner;
+		SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -value));
+		_current_company = old;
+	}
+
+	/* take special measures for trains, but not when sharing is disabled or when the train is a free wagon chain */
+	if (_settings_game.economy.infrastructure_sharing[VEH_TRAIN] && v->type == VEH_TRAIN && Train::From(v)->IsFrontEngine()) {
+ 		DeleteVisibleTrain(Train::From(v));
+	} else {
+		delete v;
+	}
+}
+
+/**
+ * Check all path reservations, and reserve a new path if the current path is invalid.
+ */
+static void FixAllReservations()
+{
+	/* if this function is called, we can safely assume that sharing of rails is being switched off */
+	assert(!_settings_game.economy.infrastructure_sharing[VEH_TRAIN]);
+	Train *v;
+	FOR_ALL_TRAINS(v) {
+		if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0) continue;
+		/* It might happen that the train reserved additional tracks,
+		 * but FollowTrainReservation can't detect those because they are no longer reachable.
+		 * detect this by first finding the end of the reservation,
+		 * then switch sharing on and try again. If these two ends differ,
+		 * unreserve the path, switch sharing off and try to reserve a new path */
+		PBSTileInfo end_tile_info = FollowTrainReservation(v);
+
+		/* first do a quick test to determine whether the next tile has any reservation at all */
+		TileIndex next_tile = end_tile_info.tile + TileOffsByDiagDir(TrackdirToExitdir(end_tile_info.trackdir));
+		/* If the next tile doesn't have a reservation at all, the reservation surely ends here. Thus all is well */
+		if (GetReservedTrackbits(next_tile) == TRACK_BIT_NONE) continue;
+
+		/* change sharing setting temporarily */
+		_settings_game.economy.infrastructure_sharing[VEH_TRAIN] = true;
+		PBSTileInfo end_tile_info2 = FollowTrainReservation(v);
+		/* if these two reservation ends differ, unreserve the path and try to reserve a new path */
+		if (end_tile_info.tile != end_tile_info2.tile || end_tile_info.trackdir != end_tile_info2.trackdir) {
+			FreeTrainTrackReservation(v);
+			_settings_game.economy.infrastructure_sharing[VEH_TRAIN] = false;
+			TryPathReserve(v, true);
+		} else {
+			_settings_game.economy.infrastructure_sharing[VEH_TRAIN] = false;
+		}
+	}
+}
+
+/**
+ * Check if a sharing change is possible.
+ * If vehicles are still on others' infrastructure or using others' stations,
+ * The change is not possible and false is returned.
+ * @param type The type of vehicle whose setting will be changed.
+ * @return True if the change can take place, false otherwise.
+ */
+bool CheckSharingChangePossible(VehicleType type)
+{
+	if (type != VEH_AIRCRAFT) YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
+	/* Only do something when sharing is being disabled */
+	if (_settings_game.economy.infrastructure_sharing[type]) return true;
+
+	StringID error_message = STR_NULL;
+	Vehicle *v;
+	FOR_ALL_VEHICLES(v) {
+		if (type != v->type) continue;
+		if (v->Previous() != NULL) continue;
+
+		/* Check vehicle positiion */
+		if (!VehiclePositionIsAllowed(v)) {
+			error_message = STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES;
+			/* Break immediately, this error message takes precedence over the others. */
+			break;
+		}
+
+		/* Check current order */
+		if (!OrderDestinationIsAllowed(&v->current_order, v)) {
+			error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
+		}
+
+		/* Check order list */
+		if (v->FirstShared() != v) continue;
+		Order *o;
+		FOR_VEHICLE_ORDERS(v, o) {
+			if (!OrderDestinationIsAllowed(o, v)) {
+				error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
+			}
+		}
+	}
+
+	if (error_message != STR_NULL) {
+		ShowErrorMessage(error_message, INVALID_STRING_ID, WL_ERROR);
+		return false;
+	}
+
+	if (type == VEH_TRAIN) FixAllReservations();
+
+	return true;
+}
+
+/**
+ * Handle the removal (through reset_company or bankruptcy) of a company.
+ * i.e. remove all vehicles owned by that company or on its infrastructure,
+ * and delete all now-invalid orders.
+ * @param Owner the company to be removed.
+ */
+void HandleSharingCompanyDeletion(Owner owner)
+{
+	YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
+
+	Vehicle *v;
+	FOR_ALL_VEHICLES(v) {
+		if (!IsCompanyBuildableVehicleType(v) || v->Previous() != NULL) continue;
+		/* vehicle position */
+		if (v->owner == owner || !VehiclePositionIsAllowed(v, owner)) {
+			RemoveAndSellVehicle(v, v->owner != owner);
+			continue;
+		}
+		/* current order */
+		if (!OrderDestinationIsAllowed(&v->current_order, v, owner)) {
+			if (v->current_order.IsType(OT_LOADING)) {
+				v->LeaveStation();
+			} else {
+				v->current_order.MakeDummy();
+			}
+			SetWindowDirty(WC_VEHICLE_VIEW, v->index);
+		}
+
+		/* order list */
+		if (v->FirstShared() != v) continue;
+
+		Order *o;
+		int id = -1;
+		FOR_VEHICLE_ORDERS(v, o) {
+			id++;
+			if (OrderDestinationIsAllowed(o, v, owner)) continue;
+
+			o->MakeDummy();
+			for (const Vehicle *w = v; w != NULL; w = w->NextShared()) {
+				/* In GUI, simulate by removing the order and adding it back */
+				InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8));
+				InvalidateVehicleOrder(w, (id << 8) | INVALID_VEH_ORDER_ID);
+			}
+		}
+	}
+}
+
+/**
+ * Update all block signals on the map.
+ * To be called after the setting for sharing of rails changes.
+ * @param owner Owner whose signals to update. If INVALID_OWNER, update everything.
+ */
+void UpdateAllBlockSignals(Owner owner)
+{
+	Owner last_owner = INVALID_OWNER;
+	TileIndex tile = 0;
+	do {
+		if (IsTileType(tile, MP_RAILWAY) && HasSignals(tile)) {
+			Owner track_owner = GetTileOwner(tile);
+			if (owner != INVALID_OWNER && track_owner != owner) continue;
+
+			if (!IsOneSignalBlock(track_owner, last_owner)) {
+				/* Cannot update signals of two different companies in one run,
+				 * if these signal blocks are not joined */
+				UpdateSignalsInBuffer();
+				last_owner = track_owner;
+			}
+			TrackBits bits = GetTrackBits(tile);
+			do {
+				Track track = RemoveFirstTrack(&bits);
+				if (HasSignalOnTrack(tile, track)) {
+					AddTrackToSignalBuffer(tile, track, track_owner);
+				}
+			} while (bits != TRACK_BIT_NONE);
+		} else if (IsLevelCrossingTile(tile) && (owner == INVALID_OWNER || GetTileOwner(tile) == owner)) {
+			UpdateLevelCrossing(tile);
+		}
+	} while (++tile != MapSize());
+
+	UpdateSignalsInBuffer();
+}
diff --git a/src/infrastructure_func.h b/src/infrastructure_func.h
new file mode 100644
--- /dev/null
+++ b/src/infrastructure_func.h
@@ -0,0 +1,105 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file infrastructure_func.h Functions for access to (shared) infrastructure */
+
+#ifndef INFRASTRUCTURE_FUNC_H
+#define INFRASTRUCTURE_FUNC_H
+
+#include "vehicle_base.h"
+#include "command_type.h"
+#include "company_func.h"
+#include "tile_cmd.h"
+
+void PayStationSharingFee(Vehicle *v, const Station *st);
+void PayDailyTrackSharingFee(Train *v);
+
+bool CheckSharingChangePossible(VehicleType type);
+void HandleSharingCompanyDeletion(Owner owner);
+void UpdateAllBlockSignals(Owner owner = INVALID_OWNER);
+
+/**
+ * Check whether a vehicle of a given owner and type can use the infrastrucutre of a given company.
+ * @param type        Type of vehicle we are talking about.
+ * @param veh_owner   Owner of the vehicle in question.
+ * @param infra_owner The owner of the infrastructure.
+ * @return            True if infrastructure usage is allowed, false otherwise.
+ */
+static FORCEINLINE bool IsInfraUsageAllowed(VehicleType type, Owner veh_owner, Owner infra_owner)
+{
+	return infra_owner == veh_owner || infra_owner == OWNER_NONE || _settings_game.economy.infrastructure_sharing[type];
+}
+
+/**
+ * Check whether a vehicle of a given owner and type can use the infrastrucutre on a given tile.
+ * @param type        Type of vehicle we are talking about.
+ * @param veh_owner   Owner of the vehicle in question.
+ * @param tile        The tile that may or may not be used.
+ * @return            True if infrastructure usage is allowed, false otherwise.
+ */
+static FORCEINLINE bool IsInfraTileUsageAllowed(VehicleType type, Owner veh_owner, TileIndex tile)
+{
+	return IsInfraUsageAllowed(type, veh_owner, GetTileOwner(tile));
+}
+
+/**
+ * Is a vehicle owned by _current_company allowed to use the infrastructure of infra_owner?
+ * If this is not allowed, this function provides the appropriate error message.
+ * @see IsInfraUsageAllowed
+ * @see CheckOwnership
+ * @param type        Type of vehicle.
+ * @param infra_owner Owner of the infrastructure.
+ * @param tile        Tile of the infrastructure.
+ * @return            CommandCost indicating success or failure.
+ */
+static FORCEINLINE CommandCost CheckInfraUsageAllowed(VehicleType type, Owner infra_owner, TileIndex tile = 0)
+{
+	if (infra_owner == OWNER_NONE || _settings_game.economy.infrastructure_sharing[type]) return CommandCost();
+	return CheckOwnership(infra_owner, tile);
+}
+
+/**
+ * Check whether a given company can control this vehicle.
+ * Controlling a vehicle means permission to start, stop or reverse it or to make it ignore signals.
+ * @param v The vehicle which may or may not be controlled.
+ * @param o The company which may or may not control this vehicle.
+ * @return  True if the given company is allowed to control this vehicle.
+ */
+static FORCEINLINE bool IsVehicleControlAllowed(const Vehicle *v, Owner o)
+{
+	return v->owner == o || (v->type == VEH_TRAIN && IsTileOwner(v->tile, o));
+}
+
+/**
+ * Check whether _current_company can control this vehicle.
+ * If this is not allowed, this function provides the appropriate error message.
+ * @see IsVehicleControlAllowed
+ * @param v The vehicle which may or may not be controlled.
+ * @return  CommandCost indicating success or failure.
+ */
+static FORCEINLINE CommandCost CheckVehicleControlAllowed(const Vehicle *v)
+{
+	if (v->type == VEH_TRAIN && IsTileOwner(v->tile, _current_company)) return CommandCost();
+	return CheckOwnership(v->owner);
+}
+
+/**
+ * Do signal states propagate from the tracks of one owner to the other?
+ * @note This function should be consistent, so if it returns true for (a, b) and (b, c),
+ * it should also return true for (a, c).
+ * @param o1 First track owner.
+ * @param o2 Second track owner.
+ * @return   True if tracks of the two owners are part of the same signal block.
+ */
+static FORCEINLINE bool IsOneSignalBlock(Owner o1, Owner o2)
+{
+	return o1 == o2 || _settings_game.economy.infrastructure_sharing[VEH_TRAIN];
+}
+
+#endif /* INFRASTRUCTURE_FUNC_H */
diff --git a/src/ini.cpp b/src/ini.cpp
--- a/src/ini.cpp
+++ b/src/ini.cpp
@@ -10,6 +10,8 @@
 /** @file ini.cpp Definition of the IniItem class, related to reading/writing '*.ini' files. */
 
 #include "stdafx.h"
+#include "core/alloc_func.hpp"
+#include "core/mem_func.hpp"
 #include "debug.h"
 #include "ini_type.h"
 #include "string_func.h"
@@ -22,15 +24,297 @@
 
 #ifdef WIN32
 # include <shellapi.h>
-# include "core/mem_func.hpp"
 #endif
 
 /**
- * Create a new ini file with given group names.
- * @param list_group_names A \c NULL terminated list with group names that should be loaded as lists instead of variables. @see IGT_LIST
+ * Construct a new in-memory item of an Ini file.
+ * @param parent the group we belong to
+ * @param name   the name of the item
+ * @param len    the length of the name of the item
  */
-IniFile::IniFile(const char * const *list_group_names) : IniLoadFile(list_group_names)
+IniItem::IniItem(IniGroup *parent, const char *name, size_t len) : next(NULL), value(NULL), comment(NULL)
 {
+	if (len == 0) len = strlen(name);
+
+	this->name = strndup(name, len);
+	*parent->last_item = this;
+	parent->last_item = &this->next;
+}
+
+/** Free everything we loaded. */
+IniItem::~IniItem()
+{
+	free(this->name);
+	free(this->value);
+	free(this->comment);
+
+	delete this->next;
+}
+
+/**
+ * Replace the current value with another value.
+ * @param value the value to replace with.
+ */
+void IniItem::SetValue(const char *value)
+{
+	free(this->value);
+	this->value = strdup(value);
+}
+
+/**
+ * Construct a new in-memory group of an Ini file.
+ * @param parent the file we belong to
+ * @param name   the name of the group
+ * @param len    the length of the name of the group
+ */
+IniGroup::IniGroup(IniFile *parent, const char *name, size_t len) : next(NULL), type(IGT_VARIABLES), item(NULL), comment(NULL)
+{
+	if (len == 0) len = strlen(name);
+
+	this->name = strndup(name, len);
+	this->last_item = &this->item;
+	*parent->last_group = this;
+	parent->last_group = &this->next;
+
+	if (parent->list_group_names == NULL) return;
+
+	for (uint i = 0; parent->list_group_names[i] != NULL; i++) {
+		if (strcmp(this->name, parent->list_group_names[i]) == 0) {
+			this->type = IGT_LIST;
+			return;
+		}
+	}
+}
+
+/** Free everything we loaded. */
+IniGroup::~IniGroup()
+{
+	free(this->name);
+	free(this->comment);
+
+	delete this->item;
+	delete this->next;
+}
+
+/**
+ * Get the item with the given name, and if it doesn't exist
+ * and create is true it creates a new item.
+ * @param name   name of the item to find.
+ * @param create whether to create an item when not found or not.
+ * @return the requested item or NULL if not found.
+ */
+IniItem *IniGroup::GetItem(const char *name, bool create)
+{
+	for (IniItem *item = this->item; item != NULL; item = item->next) {
+		if (strcmp(item->name, name) == 0) return item;
+	}
+
+	if (!create) return NULL;
+
+	/* otherwise make a new one */
+	return new IniItem(this, name, strlen(name));
+}
+
+/**
+ * Clear all items in the group
+ */
+void IniGroup::Clear()
+{
+	delete this->item;
+	this->item = NULL;
+	this->last_item = &this->item;
+}
+
+/**
+ * Construct a new in-memory Ini file representation.
+ * @param list_group_names A NULL terminated list with groups that should be
+ *                         loaded as lists instead of variables.
+ */
+IniFile::IniFile(const char * const *list_group_names) : group(NULL), comment(NULL), list_group_names(list_group_names)
+{
+	this->last_group = &this->group;
+}
+
+/** Free everything we loaded. */
+IniFile::~IniFile()
+{
+	free(this->comment);
+	delete this->group;
+}
+
+/**
+ * Get the group with the given name, and if it doesn't exist
+ * create a new group.
+ * @param name name of the group to find.
+ * @param len  the maximum length of said name.
+ * @return the requested group.
+ */
+IniGroup *IniFile::GetGroup(const char *name, size_t len)
+{
+	if (len == 0) len = strlen(name);
+
+	/* does it exist already? */
+	for (IniGroup *group = this->group; group != NULL; group = group->next) {
+		if (!strncmp(group->name, name, len) && group->name[len] == 0) {
+			return group;
+		}
+	}
+
+	/* otherwise make a new one */
+	IniGroup *group = new IniGroup(this, name, len);
+	group->comment = strdup("\n");
+	return group;
+}
+
+/**
+ * Remove the group with the given name.
+ * @param name name of the group to remove.
+ */
+void IniFile::RemoveGroup(const char *name)
+{
+	size_t len = strlen(name);
+	IniGroup *prev = NULL;
+	IniGroup *group;
+	/* does it exist already? */
+	for (group = this->group; group != NULL; prev = group, group = group->next) {
+		if (strncmp(group->name, name, len) == 0) {
+			break;
+		}
+	}
+
+	if (group == NULL) return;
+
+	if (prev != NULL) {
+		prev->next = prev->next->next;
+		if (this->last_group == &group->next) this->last_group = &prev->next;
+	} else {
+		this->group = this->group->next;
+		if (this->last_group == &group->next) this->last_group = &this->group;
+	}
+
+	group->next = NULL;
+	delete group;
+}
+
+/**
+ * Load the Ini file's data from the disk.
+ * @param filename the file to load.
+ * @pre nothing has been loaded yet.
+ */
+void IniFile::LoadFromDisk(const char *filename)
+{
+	assert(this->last_group == &this->group);
+
+	char buffer[1024];
+	IniGroup *group = NULL;
+
+	char *comment = NULL;
+	uint comment_size = 0;
+	uint comment_alloc = 0;
+
+	size_t end;
+	/*
+	 * Now we are going to open a file that contains no more than simple
+	 * plain text. That would raise the question: "why open the file as
+	 * if it is a binary file?". That's simple... Microsoft, in all
+	 * their greatness and wisdom decided it would be useful if ftell
+	 * is aware of '\r\n' and "sees" that as a single character. The
+	 * easiest way to test for that situation is by searching for '\n'
+	 * and decrease the value every time you encounter a '\n'. This will
+	 * thus also make ftell "see" the '\r' when it is not there, so the
+	 * result of ftell will be highly unreliable. So to work around this
+	 * marvel of wisdom we have to open in as a binary file.
+	 */
+	FILE *in = FioFOpenFile(filename, "rb", DATA_DIR, &end);
+	if (in == NULL) return;
+
+	end += ftell(in);
+
+	/* for each line in the file */
+	while ((size_t)ftell(in) < end && fgets(buffer, sizeof(buffer), in)) {
+		char c, *s;
+		/* trim whitespace from the left side */
+		for (s = buffer; *s == ' ' || *s == '\t'; s++) {}
+
+		/* trim whitespace from right side. */
+		char *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 == ';' || *s == '\0') {
+			uint ns = comment_size + (e - s + 1);
+			uint a = comment_alloc;
+			/* add to comment */
+			if (ns > a) {
+				a = max(a, 128U);
+				do a *= 2; while (a < ns);
+				comment = ReallocT(comment, comment_alloc = a);
+			}
+			uint 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'", buffer);
+			} else {
+				e--;
+			}
+			s++; // skip [
+			group = new IniGroup(this, s, e - s);
+			if (comment_size != 0) {
+				group->comment = strndup(comment, comment_size);
+				comment_size = 0;
+			}
+		} else if (group != NULL) {
+			char *t;
+			/* find end of keyname */
+			if (*s == '\"') {
+				s++;
+				for (t = s; *t != '\0' && *t != '\"'; t++) {}
+				if (*t == '\"') *t = ' ';
+			} else {
+				for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++) {}
+			}
+
+			/* it's an item in an existing group */
+			IniItem *item = new IniItem(group, s, t - s);
+			if (comment_size != 0) {
+				item->comment = strndup(comment, comment_size);
+				comment_size = 0;
+			}
+
+			/* find start of parameter */
+			while (*t == '=' || *t == ' ' || *t == '\t') t++;
+
+			bool quoted = (*t == '\"');
+			/* remove starting quotation marks */
+			if (*t == '\"') t++;
+			/* remove ending quotation marks */
+			e = t + strlen(t);
+			if (e > t && e[-1] == '\"') e--;
+			*e = '\0';
+
+			/* If the value was not quoted and empty, it must be NULL */
+			item->value = (!quoted && e == t) ? NULL : strndup(t, e - t);
+		} else {
+			/* it's an orphan item */
+			ShowInfoF("ini: '%s' outside of group", buffer);
+		}
+	}
+
+	if (comment_size > 0) {
+		this->comment = strndup(comment, comment_size);
+		comment_size = 0;
+	}
+
+	free(comment);
+	fclose(in);
 }
 
 /**
diff --git a/src/ini_type.h b/src/ini_type.h
--- a/src/ini_type.h
+++ b/src/ini_type.h
@@ -18,7 +18,6 @@
 enum IniGroupType {
 	IGT_VARIABLES = 0, ///< Values of the form "landscape = hilly".
 	IGT_LIST      = 1, ///< A list of values, separated by \n and terminated by the next group block.
-	IGT_SEQUENCE  = 2, ///< A list of uninterpreted lines, terminated by the next group block.
 };
 
 /** A single "line" in an ini file. */
diff --git a/src/landscape.cpp b/src/landscape.cpp
--- a/src/landscape.cpp
+++ b/src/landscape.cpp
@@ -540,7 +540,7 @@
  * @param table the 12 * 32 byte table containing the snowline for each day
  * @ingroup SnowLineGroup
  */
-void SetSnowLine(byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
+void SetSnowLine(uint16 table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
 {
 	_snow_line = CallocT<SnowLine>(1);
 	_snow_line->lowest_value = 0xFF;
@@ -559,7 +559,7 @@
  * @return the snow line height.
  * @ingroup SnowLineGroup
  */
-byte GetSnowLine()
+uint16 GetSnowLine()
 {
 	if (_snow_line == NULL) return _settings_game.game_creation.snow_line_height;
 
@@ -573,7 +573,7 @@
  * @return the highest snow line height.
  * @ingroup SnowLineGroup
  */
-byte HighestSnowLine()
+uint16 HighestSnowLine()
 {
 	return _snow_line == NULL ? _settings_game.game_creation.snow_line_height : _snow_line->highest_value;
 }
@@ -583,7 +583,7 @@
  * @return the lowest snow line height.
  * @ingroup SnowLineGroup
  */
-byte LowestSnowLine()
+uint16 LowestSnowLine()
 {
 	return _snow_line == NULL ? _settings_game.game_creation.snow_line_height : _snow_line->lowest_value;
 }
@@ -886,10 +886,11 @@
 
 		if (!IsValidTile(tile)) continue;
 
+		/* Amount of tiles that become desert, excluding those too close to watertiles.*/
 		for (data = _make_desert_or_rainforest_data;
 				data != endof(_make_desert_or_rainforest_data); ++data) {
 			TileIndex t = AddTileIndexDiffCWrap(tile, *data);
-			if (t != INVALID_TILE && (TileHeight(t) >= 4 || IsTileType(t, MP_WATER))) break;
+			if (t != INVALID_TILE && (TileHeight(t) >= _settings_newgame.game_creation.desert_amount || IsTileType(t, MP_WATER))) break;
 		}
 		if (data == endof(_make_desert_or_rainforest_data)) {
 			SetTropicZone(tile, TROPICZONE_DESERT);
@@ -907,6 +908,7 @@
 
 		if (!IsValidTile(tile)) continue;
 
+		/* All "land" tiles that are not assigned as desert above become rainforest here. */
 		for (data = _make_desert_or_rainforest_data;
 				data != endof(_make_desert_or_rainforest_data); ++data) {
 			TileIndex t = AddTileIndexDiffCWrap(tile, *data);
@@ -1285,6 +1287,7 @@
 void OnTick_Industry();
 
 void OnTick_Companies();
+void OnTick_LinkGraph();
 
 void CallLandscapeTick()
 {
@@ -1294,4 +1297,5 @@
 	OnTick_Industry();
 
 	OnTick_Companies();
+	OnTick_LinkGraph();
 }
diff --git a/src/landscape.h b/src/landscape.h
--- a/src/landscape.h
+++ b/src/landscape.h
@@ -23,16 +23,16 @@
  * @ingroup SnowLineGroup
  */
 struct SnowLine {
-	byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS]; ///< Height of the snow line each day of the year
-	byte highest_value; ///< Highest snow line of the year
-	byte lowest_value;  ///< Lowest snow line of the year
+	uint16 table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS]; ///< Height of the snow line each day of the year
+	uint16 highest_value;                           ///< Highest snow line of the year
+	uint16 lowest_value;                            ///< Lowest snow line of the year
 };
 
 bool IsSnowLineSet();
-void SetSnowLine(byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS]);
-byte GetSnowLine();
-byte HighestSnowLine();
-byte LowestSnowLine();
+void SetSnowLine(uint16 table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS]);
+uint16 GetSnowLine();
+uint16 HighestSnowLine();
+uint16 LowestSnowLine();
 void ClearSnowLine();
 
 int GetSlopeZInCorner(Slope tileh, Corner corner);
diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt
--- a/src/lang/afrikaans.txt
+++ b/src/lang/afrikaans.txt
@@ -1082,18 +1082,6 @@
 STR_CONFIG_SETTING_ON                                           :Aan
 STR_CONFIG_SETTING_DISABLED                                     :gestrem
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Af
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eie maatskappy
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alle maatskappye
-
-STR_CONFIG_SETTING_NONE                                         :Geen
-STR_CONFIG_SETTING_ORIGINAL                                     :Oorspronlik
-STR_CONFIG_SETTING_REALISTIC                                    :Realisties
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Links
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Senter
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Regs
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Laat bou op skuinstes en kusse toe: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Laat terraforming toe onder geboue, spoore, ens. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Laat meer realisties grootte opvangsgebied toe: {ORANGE}{STRING}
@@ -1320,9 +1308,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}Dorpe
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}Nywerhede
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Aanbevole)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Padvinder vir treine: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Padvinder vir pad voertuie: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Padvinder vir skepe: {ORANGE}{STRING}
@@ -2427,9 +2412,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (City)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Populasie: {ORANGE}{COMMA}{BLACK}  Huise: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passasiers verlede maand: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Pos verlede maand: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Vrag nodig om dorp te laat groei:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passasiers verlede maand: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Pos verlede maand: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Vrag nodig om dorp te laat groei:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} vereis
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} vereis in winter
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} gelewer laas maand
diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt
--- a/src/lang/arabic_egypt.txt
+++ b/src/lang/arabic_egypt.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :فتح
 STR_CONFIG_SETTING_DISABLED                                     :غير مفعل
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :بدون
-STR_CONFIG_SETTING_COMPANIES_OWN                                :لشركتك
-STR_CONFIG_SETTING_COMPANIES_ALL                                :كل الشركات
-
-STR_CONFIG_SETTING_NONE                                         :بدون
-STR_CONFIG_SETTING_ORIGINAL                                     :اصلي
-STR_CONFIG_SETTING_REALISTIC                                    :واقعي
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :يسار
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :متوسط
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :يمين
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}السماح بالبناء على المنحدرات و السواحل: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}السماح باعادة بناء التلال تحت المباني, الطرق, الخ .-الانحدار الذاتي- {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}السماح بحدود اكثر واقعية للمحطات بحسب الحجم: {ORANGE}{STRING}
@@ -2526,9 +2514,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} - مدينة -
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}السكان:  {ORANGE}{COMMA}{BLACK}   المنازل:     {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}الركاب الشهر الماضي: {ORANGE}{COMMA}{BLACK}  الأقصى: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}طرود البريد الشهر الماضي: {ORANGE}{COMMA}{BLACK}  الأقصى: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK} نمو المدينة يتطلب بضائع
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}الركاب الشهر الماضي: {ORANGE}{COMMA}{BLACK}  الأقصى: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}طرود البريد الشهر الماضي: {ORANGE}{COMMA}{BLACK}  الأقصى: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK} نمو المدينة يتطلب بضائع
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} مطلوب
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK}مطلوب في الشتاء
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} اوصل الشهر الماضي
diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt
--- a/src/lang/belarusian.txt
+++ b/src/lang/belarusian.txt
@@ -1412,18 +1412,6 @@
 STR_CONFIG_SETTING_ON                                           :так
 STR_CONFIG_SETTING_DISABLED                                     :адключана
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :не
-STR_CONFIG_SETTING_COMPANIES_OWN                                :для сваёй кампаніі
-STR_CONFIG_SETTING_COMPANIES_ALL                                :для ўсіх кампаніяў
-
-STR_CONFIG_SETTING_NONE                                         :няма
-STR_CONFIG_SETTING_ORIGINAL                                     :арыгiнальная
-STR_CONFIG_SETTING_REALISTIC                                    :рэалістычная
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :леваруч
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :ў цэнтры
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :праваруч
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Дазволіць будаўніцтва на сьхілах і на беразе: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Дазволіць зьмену ляндшафту пад будынкамі, дарогамі й г. д. (аўтаспускі): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Зона пакрыцьця залежыць ад тыпу станцыі: {ORANGE}{STRING}
@@ -2894,9 +2882,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Мэгаполіс)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Насельніцтва: {ORANGE}{COMMA}{BLACK}  Будынкаў: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Пасажыраў за мінулы месяц: {ORANGE}{COMMA}{BLACK} Макс.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Пошты за мінулы месяц: {ORANGE}{COMMA}{BLACK}  Макс.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Груз, неабходны для росту горада:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Пасажыраў за мінулы месяц: {ORANGE}{COMMA}{BLACK} Макс.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Пошты за мінулы месяц: {ORANGE}{COMMA}{BLACK}  Макс.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Груз, неабходны для росту горада:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} патрабу{G 0 е e e ю}цца
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} патрабу{G 0 е e e ю}цца ўзімку
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} дастаўлена ў мінулым месяцы
diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt
--- a/src/lang/brazilian_portuguese.txt
+++ b/src/lang/brazilian_portuguese.txt
@@ -1096,18 +1096,6 @@
 STR_CONFIG_SETTING_ON                                           :On
 STR_CONFIG_SETTING_DISABLED                                     :desativado
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Desligado
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Própria empresa
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Todas as empresas
-
-STR_CONFIG_SETTING_NONE                                         :Nenhum
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realístico
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Esquerda
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centro
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Direita
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Permitir a construção em declives e encostas: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Permitir paisagismo sob edifícios, ruas, etc. (auto nivelação): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Permitir dimensionamento mais realista das áreas de abrangência: {ORANGE}{STRING}
@@ -2527,9 +2515,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Cidade)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}População: {ORANGE}{COMMA}{BLACK}  Casas: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passageiros no mês passado: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Cartas no mês passado: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Carga necessária para prover o crescimento:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passageiros no mês passado: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Cartas no mês passado: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Carga necessária para prover o crescimento:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} necessário(a)
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} necessário no inverno
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} entregue no mes passado
diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt
--- a/src/lang/bulgarian.txt
+++ b/src/lang/bulgarian.txt
@@ -1084,26 +1084,6 @@
 STR_CONFIG_SETTING_ON                                           :включено
 STR_CONFIG_SETTING_DISABLED                                     :изключено
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :изключен
-STR_CONFIG_SETTING_COMPANIES_OWN                                :само за собствената компания
-STR_CONFIG_SETTING_COMPANIES_ALL                                :за всички компании
-
-STR_CONFIG_SETTING_NONE                                         :Без
-STR_CONFIG_SETTING_ORIGINAL                                     :Оригинално
-STR_CONFIG_SETTING_ORIGINAL.m                                   :Оригинален
-STR_CONFIG_SETTING_ORIGINAL.f                                   :Оригинална
-STR_CONFIG_SETTING_ORIGINAL.n                                   :Оригинално
-STR_CONFIG_SETTING_ORIGINAL.p                                   :Оригинални
-STR_CONFIG_SETTING_REALISTIC                                    :{G=m}Реалистично
-STR_CONFIG_SETTING_REALISTIC.m                                  :Реалистичен
-STR_CONFIG_SETTING_REALISTIC.f                                  :Реалистична
-STR_CONFIG_SETTING_REALISTIC.n                                  :Реалистична
-STR_CONFIG_SETTING_REALISTIC.p                                  :Реалистични
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :ляво
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :център
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :дясно
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Строене на склонове и брегове: {ORANGE}{STRING.n}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Тераформиране под постройки (autoslope): {ORANGE}{STRING.n}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}По-реалистична зона за обслужване: {ORANGE}{STRING}
@@ -1335,9 +1315,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}Градове
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}Индустрии
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(препоръчва се)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Пътенамирач за влакове: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Пътенамирач за автомобили: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Пътенамирач за кораби: {ORANGE}{STRING}
@@ -2493,9 +2470,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Град)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Население: {ORANGE}{COMMA}{BLACK}  Жилища: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Пътници през последния месец: {ORANGE}{COMMA}{BLACK}  максимум: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Поща през последния месец: {ORANGE}{COMMA}{BLACK}  максимум: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Товар нужен за растеж на града:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Пътници през последния месец: {ORANGE}{COMMA}{BLACK}  максимум: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Поща през последния месец: {ORANGE}{COMMA}{BLACK}  максимум: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Товар нужен за растеж на града:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} необходим
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} необходим през зимата
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} доставено миналия месец
diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt
--- a/src/lang/catalan.txt
+++ b/src/lang/catalan.txt
@@ -1096,18 +1096,6 @@
 STR_CONFIG_SETTING_ON                                           :Actiu
 STR_CONFIG_SETTING_DISABLED                                     :desactivat
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Inactiu
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Pròpia companyia
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Totes les companyies
-
-STR_CONFIG_SETTING_NONE                                         :Cap
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realístic
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Esquerra
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centre
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Dreta
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Permet construir en desnivells i costes: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Permet modelar el terreny sota edificis, rails, etc. (autopendent): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Permet una mida més real de l'àrea d'influència: {ORANGE}{STRING}
@@ -2527,9 +2515,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Ciutat)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Població: {ORANGE}{COMMA}{BLACK}  Cases: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passatgers el darrer mes: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Correu el darrer mes: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Càrrega requerida per tal de que el poble creixi:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passatgers el darrer mes: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Correu el darrer mes: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Càrrega requerida per tal de que el poble creixi:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} requerides
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} requerit a l'hivern
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} lliurades el darrer mes
diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt
--- a/src/lang/croatian.txt
+++ b/src/lang/croatian.txt
@@ -1191,18 +1191,6 @@
 STR_CONFIG_SETTING_ON                                           :Uključeno
 STR_CONFIG_SETTING_DISABLED                                     :onemogućeno
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Isključeno
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Vlastita tvrtka
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Sve tvrtke
-
-STR_CONFIG_SETTING_NONE                                         :Nema
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realističan
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Lijevo
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Sredina
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Desno
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Dopusti izgradnju na kosinama i obalama: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Dopusti modeliranje zemlje ispod građevina, tračnica, itd (autonagib): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Dopusti realističnije veličine područja zahvaćanja: {ORANGE}{STRING}
@@ -2655,9 +2643,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Metropola)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Stanovništvo: {ORANGE}{COMMA}{BLACK}  Kuće: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Putnika prošli mjesec: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Pošte prošli mjesec: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Potrebno tereta za rast grada:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Putnika prošli mjesec: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Pošte prošli mjesec: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Potrebno tereta za rast grada:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} potrebno
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} potrebno zimi
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} isporučeno prošli mjesec
diff --git a/src/lang/czech.txt b/src/lang/czech.txt
--- a/src/lang/czech.txt
+++ b/src/lang/czech.txt
@@ -1177,18 +1177,6 @@
 STR_CONFIG_SETTING_ON                                           :zapnuto
 STR_CONFIG_SETTING_DISABLED                                     :vypnuto
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :ne
-STR_CONFIG_SETTING_COMPANIES_OWN                                :u vlastní společnosti
-STR_CONFIG_SETTING_COMPANIES_ALL                                :u všech společností
-
-STR_CONFIG_SETTING_NONE                                         :Žádný
-STR_CONFIG_SETTING_ORIGINAL                                     :Originální
-STR_CONFIG_SETTING_REALISTIC                                    :Realistický
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :vlevo
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :uprostřed
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :vpravo
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Povolit výstavbu na svazích kopců a na pobřežích: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Srovnání terénu pod budovami, kolejemi atd. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Povolit u oblasti pokrytí realističtější velikost: {ORANGE}{STRING}
@@ -2614,9 +2602,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (velkoměsto)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Populace: {ORANGE}{COMMA}{BLACK} Domů: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Cestujících minulý měsíc: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Pošta za minulý měsíc: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Množství doručeného nákladu potřebného pro rozvoj města:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Cestujících minulý měsíc: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Pošta za minulý měsíc: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Množství doručeného nákladu potřebného pro rozvoj města:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{BLACK}Je potřeba {ORANGE}{STRING}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} vyžadováno v zimě
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} dovezeno minulý měsíc
diff --git a/src/lang/danish.txt b/src/lang/danish.txt
--- a/src/lang/danish.txt
+++ b/src/lang/danish.txt
@@ -1091,18 +1091,6 @@
 STR_CONFIG_SETTING_ON                                           :Til
 STR_CONFIG_SETTING_DISABLED                                     :deaktiveret
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Fra
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eget firma
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alle firmaer
-
-STR_CONFIG_SETTING_NONE                                         :Ingen
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realistisk
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Venstre
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Center
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Højre
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Tillad bygning på skråninger og kyster: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Tillad landskabsformning under bygninger, spor, etc. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Tillad mere realistisk størrelse på stationernes opland: {ORANGE}{STRING}
@@ -2515,9 +2503,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (by)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Indbyggere: {ORANGE}{COMMA}{BLACK}  Huse: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passagerer sidste måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Post sidste måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Nødvendig godsmængde for at byen kan vokse:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passagerer sidste måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Post sidste måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Nødvendig godsmængde for at byen kan vokse:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} krævet
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} kræves om vinteren
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} leveret seneste måned
diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt
--- a/src/lang/dutch.txt
+++ b/src/lang/dutch.txt
@@ -23,6 +23,7 @@
 STR_EMPTY                                                       :
 STR_UNDEFINED                                                   :(ongedefinieerde string)
 STR_JUST_NOTHING                                                :Niets
+STR_TINY_NOTHING                                                :{TINYFONT}Niets
 
 # Cargo related strings
 # Plural cargo name
@@ -220,6 +221,7 @@
 STR_LIST_FILTER_OSKTITLE                                        :{BLACK}Voer filtertekst in
 STR_LIST_FILTER_TOOLTIP                                         :{BLACK}Geef een woord waarop gefilterd kan worden in de lijst
 
+STR_TOOLTIP_GROUP_ORDER                                         :{BLACK}Selecteer groep sorteerrichting
 STR_TOOLTIP_SORT_ORDER                                          :{BLACK}Selecteer sorteerrichting (aflopend/oplopend)
 STR_TOOLTIP_SORT_CRITERIA                                       :{BLACK}Selecteer sorteercriteria
 STR_TOOLTIP_FILTER_CRITERIA                                     :{BLACK}Kies filtercriteria
@@ -252,7 +254,7 @@
 STR_MEASURE_AREA                                                :{BLACK}Gebied: {NUM} x {NUM}
 STR_MEASURE_LENGTH_HEIGHTDIFF                                   :{BLACK}Lengte: {NUM}{}Hoogteverschil: {HEIGHT}
 STR_MEASURE_AREA_HEIGHTDIFF                                     :{BLACK}Gebied: {NUM} x {NUM}{}Hoogteverschil: {HEIGHT}
-
+STR_MEASURE_DIST_HEIGHTDIFF                                     :{BLACK}Manhattan afstand: {NUM}{}Vogelvlucht asfstand: {NUM}{}Afstand tot de dichtstse kaartrand: {NUM}{}Hoogteverschil vanaf zeeniveau: {HEIGHT}{}Hoogteverschil: {HEIGHT}
 
 # These are used in buttons
 STR_SORT_BY_CAPTION_POPULATION                                  :{BLACK}Inwoners
@@ -373,6 +375,7 @@
 STR_MAP_MENU_MAP_OF_WORLD                                       :Kaart
 STR_MAP_MENU_EXTRA_VIEW_PORT                                    :Extra kijkvenster
 STR_MAP_MENU_SIGN_LIST                                          :Bordenlijst
+STR_MAP_MENU_WATCH_COMPANY                                      :Bekijk bedrijf
 ############ range for town menu starts, yet the town directory is shown in the map menu in the scenario editor
 STR_TOWN_MENU_TOWN_DIRECTORY                                    :Stedenlijst
 ############ end of the 'Display map' dropdown
@@ -446,6 +449,7 @@
 STR_ABOUT_MENU_SCREENSHOT                                       :Screenshot
 STR_ABOUT_MENU_ZOOMIN_SCREENSHOT                                :Ingezoomd screenshot
 STR_ABOUT_MENU_GIANT_SCREENSHOT                                 :Screenshot van hele kaart
+STR_ABOUT_MENU_SHOW_SYTEM_TIME                                  :Toon systeem tijd
 STR_ABOUT_MENU_ABOUT_OPENTTD                                    :Over 'OpenTTD'
 STR_ABOUT_MENU_SPRITE_ALIGNER                                   :Sprite uitlijner
 STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES                            :Schakel selectiekaders
@@ -655,17 +659,20 @@
 STR_SMALLMAP_TYPE_CONTOURS                                      :Contouren
 STR_SMALLMAP_TYPE_VEHICLES                                      :Voertuigen
 STR_SMALLMAP_TYPE_INDUSTRIES                                    :Industrieën
+STR_SMALLMAP_TYPE_ROUTEMAP                                      :Link Statistieken
 STR_SMALLMAP_TYPE_ROUTES                                        :Routes
 STR_SMALLMAP_TYPE_VEGETATION                                    :Begroeiïng
 STR_SMALLMAP_TYPE_OWNERS                                        :Eigenaren
 STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP                  :{BLACK}Toon landcontouren op de kaart
 STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP                       :{BLACK}Toon voertuigen op de kaart
 STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP                     :{BLACK}Toon industrieën op de kaart
+STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP                     :{BLACK}Toon link statistieken op de kaart
 STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON                   :{BLACK}Toon transportroutes op de kaart
 STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP                     :{BLACK}Toon begroeiïng op de kaart
 STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP                    :{BLACK}Toon landeigenaren op de kaart
-STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION                         :{BLACK}Klik op een industriesoort om deze weer te geven. Ctrl+klik verbergt alle andere industriesoorten behalve de geselecteerde. Nogmaals Ctrl+klik geeft opnieuw alle industriesoorten weer.
-STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION                          :{BLACK}Klik op een bedrijf om de bedrijfseigendommen weer te geven. Ctrl+klik verbergt alle andere bedrijven behalve de geselecteerde. Nogmaals Ctrl+klik geeft opnieuw alle bedrijven weer.
+STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION                         :{BLACK}Klik op een industriesoort om deze weer te geven. Ctrl+klik verbergt alle andere industriesoorten behalve de geselecteerde. Nogmaals Ctrl+klik geeft opnieuw alle industriesoorten weer
+STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION                          :{BLACK}Klik op een bedrijf om de bedrijfseigendommen weer te geven. Ctrl+klik verbergt alle andere bedrijven behalve de geselecteerde. Nogmaals Ctrl+klik geeft opnieuw alle bedrijven weer
+STR_SMALLMAP_TOOLTIP_LINK_STATS_SELECTION                       :{BLACK}Klik op een cargotype om deze weer the geven. Ctrl+klick verbergt alle andere linkstatistieken behalve de geselecteerde. Nogmaals Ctrl+klick geeft opnieuw alle linkstats weer
 
 STR_SMALLMAP_LEGENDA_ROADS                                      :{TINYFONT}{BLACK}Wegen
 STR_SMALLMAP_LEGENDA_RAILROADS                                  :{TINYFONT}{BLACK}Spoorwegen
@@ -695,11 +702,27 @@
 STR_SMALLMAP_LEGENDA_INDUSTRIES                                 :{TINYFONT}{BLACK}Industrieën
 STR_SMALLMAP_LEGENDA_DESERT                                     :{TINYFONT}{BLACK}Woestijn
 STR_SMALLMAP_LEGENDA_SNOW                                       :{TINYFONT}{BLACK}Sneeuw
+STR_SMALLMAP_LEGENDA_CAPACITY                                   :{TINYFONT}{BLACK}Capaciteit
+STR_SMALLMAP_LEGENDA_USAGE                                      :{TINYFONT}{BLACK}Gebruik
+STR_SMALLMAP_LEGENDA_PLANNED                                    :{TINYFONT}{BLACK}Geplande flow
+STR_SMALLMAP_LEGENDA_SENT                                       :{TINYFONT}{BLACK}Verzonden cargo
+STR_SMALLMAP_LEGENDA_SHOW_TEXT                                  :{TINYFONT}{BLACK}Als text
+STR_SMALLMAP_LEGENDA_SHOW_GRAPH                                 :{TINYFONT}{BLACK}Als grafieken
+ 
+STR_SMALLMAP_SUPPLY_CAPTION                                     :{BLACK}Maandelijkse levering aan {STATION}
+STR_SMALLMAP_SUPPLY                                             :{TINYFONT}{CARGO}
+STR_SMALLMAP_LINK_CAPTION                                       :{BLACK}Maandelijkse traffiek van {STATION} naar {STATION}
+STR_SMALLMAP_LINK                                               :{TINYFONT}{STRING} -
+STR_SMALLMAP_LINK_CAPACITY                                      :{TINYFONT}  cap: {NUM}
+STR_SMALLMAP_LINK_USAGE                                         :{TINYFONT}  gebr: {NUM}
+STR_SMALLMAP_LINK_PLANNED                                       :{TINYFONT}  gepl: {NUM}
+STR_SMALLMAP_LINK_SENT                                          :{TINYFONT}  verz: {NUM}
 
 STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF                   :{BLACK}Plaatsnamen op de kaart aan/uit
 STR_SMALLMAP_CENTER                                             :{BLACK}Centreer de kaart op huidige positie
 STR_SMALLMAP_INDUSTRY                                           :{TINYFONT}{STRING} ({NUM})
 STR_SMALLMAP_COMPANY                                            :{TINYFONT}{COMPANY}
+STR_SMALLMAP_LINKSTATS                                          :{TINYFONT}{STRING}
 STR_SMALLMAP_TOWN                                               :{TINYFONT}{WHITE}{TOWN}
 STR_SMALLMAP_DISABLE_ALL                                        :{BLACK}Alles uitschakelen
 STR_SMALLMAP_ENABLE_ALL                                         :{BLACK}Alles inschakelen
@@ -709,6 +732,8 @@
 STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT                                :{BLACK}Schakel tonen van hoogte aan/uit
 STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES                      :{BLACK}Verberg bedrijfseigendommen op de kaart
 STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES                       :{BLACK}Toon alle bedrijfseigendommen op de kaart
+STR_SMALLMAP_TOOLTIP_DISABLE_ALL_LINK_STATS                     :{BLACK}Toon geen linkstatistieken op de kaart
+STR_SMALLMAP_TOOLTIP_ENABLE_ALL_LINK_STATS                      :{BLACK}Toon alle linkstatistieken op de kaart
 
 # Status bar messages
 STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS                            :{BLACK}Toon laatste (nieuws)bericht
@@ -934,6 +959,8 @@
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP                      :{BLACK}Kies interval tussen automatisch opgeslagen spellen
 
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF                          :Uit
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_DAY                  :Iedere dag
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_WEEK                 :Iedere week
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH                :Iedere maand
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS               :Iedere 3 maanden
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS               :Iedere 6 maanden
@@ -998,7 +1025,7 @@
 STR_DIFFICULTY_LEVEL_CAPTION                                    :{WHITE}Moeilijkheidsgraad
 
 ############ range for difficulty levels starts
-STR_DIFFICULTY_LEVEL_EASY                                       :{BLACK}Gemakkelijk
+STR_DIFFICULTY_LEVEL_EASY                                       :{BLACK}Speelplaats
 STR_DIFFICULTY_LEVEL_MEDIUM                                     :{BLACK}Gemiddeld
 STR_DIFFICULTY_LEVEL_HARD                                       :{BLACK}Moeilijk
 STR_DIFFICULTY_LEVEL_CUSTOM                                     :{BLACK}Aangepast
@@ -1070,10 +1097,13 @@
 STR_SUBSIDY_X3                                                  :x3
 STR_SUBSIDY_X4                                                  :x4
 
+STR_TERRAIN_TYPE_FALLEN                                         :Buikschuiver
 STR_TERRAIN_TYPE_VERY_FLAT                                      :Zeer Vlak
 STR_TERRAIN_TYPE_FLAT                                           :Vlak
+STR_TERRAIN_TYPE_BUMPY                                          :Hobbelig
 STR_TERRAIN_TYPE_HILLY                                          :Heuvelachtig
 STR_TERRAIN_TYPE_MOUNTAINOUS                                    :Bergachtig
+STR_TERRAIN_TYPE_ALPINIST                                       :Alpinist
 
 STR_ECONOMY_STEADY                                              :Stabiel
 STR_ECONOMY_FLUCTUATING                                         :Schommelend
@@ -1081,6 +1111,9 @@
 STR_REVERSE_AT_END_OF_LINE_AND_AT_STATIONS                      :Aan het eind van het spoor, en in stations
 STR_REVERSE_AT_END_OF_LINE_ONLY                                 :Aan het eind van het spoor
 
+STR_DISASTERS_OFF                                               :Uit
+STR_DISASTERS_ON                                                :Aan
+
 STR_CITY_APPROVAL_PERMISSIVE                                    :Toegeeflijk
 STR_CITY_APPROVAL_TOLERANT                                      :Tolerant
 STR_CITY_APPROVAL_HOSTILE                                       :Vijandig
@@ -1095,26 +1128,22 @@
 STR_CONFIG_SETTING_ON                                           :Aan
 STR_CONFIG_SETTING_DISABLED                                     :uitgeschakeld
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Uit
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eigen bedrijf
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alle bedrijven
-
-STR_CONFIG_SETTING_NONE                                         :Geen
-STR_CONFIG_SETTING_ORIGINAL                                     :Origineel
-STR_CONFIG_SETTING_REALISTIC                                    :Realistisch
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Links
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Midden
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Rechts
-
+STR_CONFIG_SETTING_VEHICLESPEED                                 :{LTBLUE}Geef voertuigsnelheid weer in statusbalk: {ORANGE}{STRING}
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Bouwen op hellingen en kusten toestaan: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Omgeving aanpassen onder gebouwen, spoorwegen, enz. toestaan (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Gebruik meer realistische handelsgebieden: {ORANGE}{STRING}
 STR_CONFIG_SETTING_EXTRADYNAMITE                                :{LTBLUE}Sta verwijderen van meer stedelijke wegen, bruggen en tunnels toe: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TRAIN_LENGTH                                 :{LTBLUE}Maximum lengte van treinen: {ORANGE}{STRING} vakje{P 0:1 "" s}
 STR_CONFIG_SETTING_SMOKE_AMOUNT                                 :{LTBLUE}Hoeveelheid rook/vonken: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SMOKE_AMOUNT_NONE                            :Geen
+STR_CONFIG_SETTING_SMOKE_AMOUNT_ORIGINAL                        :Origineel
+STR_CONFIG_SETTING_SMOKE_AMOUNT_REALISTIC                       :Realistisch
 STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL                     :{LTBLUE}Trein acceleratie model: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_ORIGINAL            :Origineel
+STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_REALISTIC           :Realistisch
 STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL              :{LTBLUE}Wegvoertuig acceleratie model: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_ORIGINAL     :Origineel
+STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_REALISTIC    :Realistisch
 STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS                        :{LTBLUE}Hellingsgraad voor treinen {ORANGE}{STRING}%
 STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS                 :{LTBLUE}Hellingsgraad voor wegvoertuigen {ORANGE}{STRING}%
 STR_CONFIG_SETTING_FORBID_90_DEG                                :{LTBLUE}Verbied treinen en schepen om 90° te draaien: {ORANGE}{STRING}
@@ -1125,11 +1154,13 @@
 STR_CONFIG_SETTING_SELECTGOODS                                  :{LTBLUE}Vracht alleen bezorgen aan een station als er vraag naar is: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH                            :{LTBLUE}Maximum brug lengte: {ORANGE}{STRING} vakje{P 0:1 "" s}
 STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH                            :{LTBLUE}Maximum tunnel lengte: {ORANGE}{STRING} vakje{P 0:1 "" s}
+STR_CONFIG_SETTING_GOTODEPOT                                    :{LTBLUE}Sta 'Ga naar depot' order toe: {ORANGE}{STRING}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD             :{LTBLUE}Handmatige bouwmethode voor primaire industrieën: {ORANGE}{STRING}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE        :geen
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL      :zoals andere industrieën
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :proberen
 STR_CONFIG_SETTING_INDUSTRY_PLATFORM                            :{LTBLUE}Vlakke omgeving rond industrieën: {ORANGE}{STRING} tegel{P 0:1 "" s}
+STR_CONFIG_SETTING_EXTRA_INDUSTRY_PLACEMENT_LOGIC               :{LTBLUE}Laat vlakmaken van meer dan 1 hoogteverschil toe voor het plaatsen van industrieën onder hoogte: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MULTIPINDTOWN                                :{LTBLUE}Meerdere vergelijkbare industrieën per stad toestaan: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SIGNALSIDE                                   :{LTBLUE}Seinen aan rijzijde plaatsen: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SHOWFINANCES                                 :{LTBLUE}Financieel overzicht aan het einde van het jaar weergeven: {ORANGE}{STRING}
@@ -1155,6 +1186,8 @@
 STR_CONFIG_SETTING_ADJACENT_STATIONS                            :{LTBLUE}Bouwen van aangrenzende stations toestaan: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES                              :{LTBLUE}Maak het mogelijk om meerdere NewGRF-voertuigsets te gebruiken: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES            :{WHITE}Deze instelling kan niet gewijzigd worden als er voertuigen zijn
+STR_CONFIG_SETTING_MAX_SIGNAL_EVALUATIONS                       :{LTBLUE}Maximum aantal tegelijkertijd toegelaten programmeerbare signaal veranderingen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_BACK_ONE_WAY_PBS_SAFE_WAITING                :{LTBLUE}Achterzijde van eenrichtings pbs signaal is veilig wachtpunt: {ORANGE}{STRING}
 
 STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS                        :{LTBLUE}Vliegvelden verlopen niet: {ORANGE}{STRING}
 
@@ -1171,18 +1204,24 @@
 STR_CONFIG_SETTING_ERRMSG_DURATION                              :{LTBLUE}Duur van foutmeldingen: {ORANGE}{STRING} seconde{P 0:1 "" n}
 STR_CONFIG_SETTING_HOVER_DELAY                                  :{LTBLUE}Toon tooltips: {ORANGE}Muis-over voor {STRING} seconde{P 0:1 "" n}
 STR_CONFIG_SETTING_HOVER_DELAY_DISABLED                         :{LTBLUE}Toon tooltips: {ORANGE}Rechts klikken
-STR_CONFIG_SETTING_POPULATION_IN_LABEL                          :{LTBLUE}Geef het inwoneraantal bij een stad weer: {ORANGE}{STRING}
+STR_CONFIG_SETTING_POPULATION_IN_LABEL                          :{LTBLUE}Geef extra info bij stadslabels weer: {ORANGE}{STRING}
+STR_CONFIG_SETTING_POPULATION_IN_LABEL_COLOURED                 :{LTBLUE}<)- Pas rating kleur toe op extra info bij stadslabels: {ORANGE}{STRING}
 
 STR_CONFIG_SETTING_LAND_GENERATOR                               :{LTBLUE}Landgenerator: {ORANGE}{STRING}
 STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL                      :Origineel
 STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS                 :TerraGenesis
 STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Max afstand van de rand voor olierafinaderijen {ORANGE}{STRING} tegel{P 0:1 "" s}
-STR_CONFIG_SETTING_SNOWLINE_HEIGHT                              :{LTBLUE}Sneeuwhoogte: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SNOWLINE_HEIGHT                              :{LTBLUE}Sneeuwgrens hoogte: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DESERT_AMOUNT                                :{LTBLUE}Hoeveelheid woestijn: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TREELINE_HEIGHT                              :{LTBLUE}Boomgrens hoogte: {ORANGE}{STRING}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN                         :{LTBLUE}Ruwheid van het terrein (alleen TerraGenesis) : {ORANGE}{STRING}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH             :Erg glad
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH                  :Glad
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH                   :Ruig
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH              :Erg ruig
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_CEREALLY_ROUGH          :Serieus ruig
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_COMMUTORZ               :ForenZen
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_GO_WITH_THE_FLOW        :Gaan met die banaan
 STR_CONFIG_SETTING_TREE_PLACER                                  :{LTBLUE}Algoritme voor plaatsing van bomen: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TREE_PLACER_NONE                             :Geen
 STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL                         :Origineel
@@ -1202,6 +1241,7 @@
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN                   :Groen
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN              :Donker groen
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET                  :Violet
+STR_CONFIG_SETTING_SMALLMAP_FLOOD_WARNING                       :{LTBLUE}Schakel overstromingsgevaar kleur in in de kleine kaart hoogtekleuren: {ORANGE}{STRING}
 STR_CONFIG_SETTING_REVERSE_SCROLLING                            :{LTBLUE}Omgekeerde scrollrichting: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SMOOTH_SCROLLING                             :{LTBLUE}Vloeiend scrollen kijkvenster: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MEASURE_TOOLTIP                              :{LTBLUE}Toon dimensie-informatie bij het gebruik van diverse bouwgereedschappen: {ORANGE}{STRING}
@@ -1239,8 +1279,24 @@
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING      :alles behalve landschapsaanpassingen
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS              :alle mogelijkheden
 STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Gebruik de geavanceerde voertuigenlijst: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OFF                   :Uit
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OWN                   :Eigen bedrijf
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_ALL                   :Alle bedrijven
 STR_CONFIG_SETTING_LOADING_INDICATORS                           :{LTBLUE}Gebruik laadindicatoren: {ORANGE}{STRING}
+STR_CONFIG_SETTING_LOADING_INDICATORS_OFF                       :Uit
+STR_CONFIG_SETTING_LOADING_INDICATORS_OWN                       :Eigen bedrijf
+STR_CONFIG_SETTING_LOADING_INDICATORS_ALL                       :Alle bedrijven
+STR_CONFIG_SETTING_TIMETABLE_ALLOW                              :{LTBLUE}Activeer dienstregeling voor voertuigen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIMETABLE_AUTOMATED                          :{LTBLUE}Automatische dienstregeling: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIME_IN_MINUTES                              :{LTBLUE}Toon dienstregeling in minuten ipv in dagen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TICKS_PER_MINUTE                             :{LTBLUE}Ticks per minuut: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DATE_WITH_TIME                               :{LTBLUE}Toon datum met tijd in status bar: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DATE_WITH_TIME_NONE                          :Geen
+STR_CONFIG_SETTING_DATE_WITH_TIME_Y                             :Jaar
+STR_CONFIG_SETTING_DATE_WITH_TIME_YM                            :Maand en jaar
+STR_CONFIG_SETTING_DATE_WITH_TIME_YMD                           :volledige datum
 STR_CONFIG_SETTING_TIMETABLE_IN_TICKS                           :{LTBLUE}Toon dienstregeling in tikken ipv in dagen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIMETABLE_SEPARATION                         :{LTBLUE}Gebruik dienstregeling om voertuigen te scheiden: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE             :{LTBLUE}Toon aankomst- en vertrektijden in dienstregeling: {ORANGE}{STRING}
 STR_CONFIG_SETTING_QUICKGOTO                                    :{LTBLUE}Snel voertuigorders maken: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE                            :{LTBLUE}Standaard spoorsoort (bij nieuw of opgeslagen spel): {ORANGE}{STRING}
@@ -1265,6 +1321,18 @@
 STR_CONFIG_SETTING_AI_IN_MULTIPLAYER                            :{LTBLUE}Laat computerspelers toe in netwerkspel: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AI_MAX_OPCODES                               :{LTBLUE}aantal opcodes voordat computerspeler tijdelijk wordt gestopt: {ORANGE}{STRING}
 
+STR_CONFIG_SETTING_SHARING_RAIL                                 :{LTBLUE}Sta delen van spoorwegen toe: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_ROAD                                 :{LTBLUE}Sta delen van bus/truck haltes an depots toe: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_WATER                                :{LTBLUE}Sta delen van haven en schip hangars toe: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_AIR                                  :{LTBLUE}Sta delen van luchthavens toe: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_FEE_RAIL                             :{LTBLUE}Dagelijkse spoortol voor treinen: {ORANGE}{STRING} per 1000 ton
+STR_CONFIG_SETTING_SHARING_FEE_ROAD                             :{LTBLUE}Halte tol voor road weg voertuigen: {ORANGE}{STRING} per dag
+STR_CONFIG_SETTING_SHARING_FEE_WATER                            :{LTBLUE}Hangar tol voor schepen: {ORANGE}{STRING} per dag
+STR_CONFIG_SETTING_SHARING_FEE_AIR                              :{LTBLUE}Luchthaven tol voor vliegtuigen: {ORANGE}{STRING} per dag
+STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT                      :{LTBLUE}Sta tol toe voor bedrijven met schulden: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES                     :{WHITE}Kan deze instelling niet veranderen, voertuigen aanwezig op gedeelde infrastructuur.
+STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS                     :{WHITE}Kan deze instelling niet veranderen, voertuigen hebben orders naar gedeelde infrastructuur bestemmingen.
+
 STR_CONFIG_SETTING_SERVINT_ISPERCENT                            :{LTBLUE}Interval tussen onderhoud is een percentage: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SERVINT_TRAINS                               :{LTBLUE}Standaard interval tussen onderhoud voor treinen: {ORANGE}{STRING} dag{P 0:1 "" en}/%
 STR_CONFIG_SETTING_SERVINT_TRAINS_DISABLED                      :{LTBLUE}Standaard interval tussen onderhoud voor treinen: {ORANGE}uit
@@ -1275,6 +1343,7 @@
 STR_CONFIG_SETTING_SERVINT_SHIPS                                :{LTBLUE}Standaard interval tussen onderhoud voor schepen: {ORANGE}{STRING} dag{P 0:1 "" en}/%
 STR_CONFIG_SETTING_SERVINT_SHIPS_DISABLED                       :{LTBLUE}Standaard interval tussen onderhoud voor schepen: {ORANGE}uit
 STR_CONFIG_SETTING_NOSERVICE                                    :{LTBLUE}Schakel onderhoud uit wanneer defecten uit staan: {ORANGE}{STRING}
+STR_CONFIG_SETTING_IMPROVED_BREAKDOWNS                          :{LTBLUE}Schakel verbeterde defecten aan: {ORANGE}{STRING}
 STR_CONFIG_SETTING_WAGONSPEEDLIMITS                             :{LTBLUE}Schakel snelheidslimieten voor wagons aan: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DISABLE_ELRAILS                              :{LTBLUE}Schakel elektrische sporen uit: {ORANGE}{STRING}
 
@@ -1309,13 +1378,32 @@
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED                        :toestaan
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT          :toestaan, eigen wegpatroon
 
+STR_CONFIG_SETTING_DAYLENGTH_FACTOR                             :{LTBLUE}Daglengte factor: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_CARGO_FACTOR                            :{LTBLUE}Stadscargo generatie factor (minder < 0 < meer): {ORANGE}{STRING}
+
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT                         :{LTBLUE}Plaatsing van bomen in het spel: {ORANGE}{STRING}
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NONE                    :geen {RED}(houtzagerij werkt niet)
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_RAINFOREST              :alleen in regenwouden
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_ALL                     :overal
 
+STR_CONFIG_SETTING_TREE_PLACEMENT_DRAG_LIMIT                    :{LTBLUE}Sleep limiet tijdens bomen planten: {ORANGE}{STRING}
+
+STR_CONFIG_SETTING_INGAME_TREELINE_HEIGHT                       :{LTBLUE}Ingame boomgrens: {ORANGE}{STRING}
+
+STR_CONFIG_SETTING_TREE_GROWTH                                  :{LTBLUE}Bomen groei snelheid: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TREE_GROWTH_NORMAL                           :Normaal
+STR_CONFIG_SETTING_TREE_GROWTH_SLOW                             :Traag
+STR_CONFIG_SETTING_TREE_GROWTH_VERY_SLOW                        :Zeer traag
+STR_CONFIG_SETTING_TREE_GROWTH_EXTREMLY_SLOW                    :Extreem traag
+
 STR_CONFIG_SETTING_TOOLBAR_POS                                  :{LTBLUE}Positie van algemene knoppenbalk: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOOLBAR_POS_LEFT                             :Links
+STR_CONFIG_SETTING_TOOLBAR_POS_CENTER                           :Midden
+STR_CONFIG_SETTING_TOOLBAR_POS_RIGHT                            :Rechts
 STR_CONFIG_SETTING_STATUSBAR_POS                                :{LTBLUE}Positie van de statusbalk: {ORANGE}{STRING}
+STR_CONFIG_SETTING_STATUSBAR_POS_LEFT                           :Links
+STR_CONFIG_SETTING_STATUSBAR_POS_CENTER                         :Midden
+STR_CONFIG_SETTING_STATUSBAR_POS_RIGHT                          :Rechts
 STR_CONFIG_SETTING_SNAP_RADIUS                                  :{LTBLUE}Vensterklikradius: {ORANGE}{STRING} pixel{P 0:1 "" s}
 STR_CONFIG_SETTING_SNAP_RADIUS_DISABLED                         :{LTBLUE}Vensterklikradius: {ORANGE}uit
 STR_CONFIG_SETTING_SOFT_LIMIT                                   :{LTBLUE}Maximum aantal (niet-sticky) vensters: {ORANGE}{STRING}
@@ -1329,19 +1417,76 @@
 STR_CONFIG_SETTING_LARGER_TOWNS                                 :{LTBLUE}Verhouding van steden die groeisteden worden: {ORANGE}1 in {STRING}
 STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED                        :{LTBLUE}Verhouding van steden die groeisteden worden: {ORANGE}Niet
 STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER                         :{LTBLUE}Stadsgroei-indicator: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO                            :{LTBLUE}Dorpssgroei gebaseerd op geleverde passagiers/post/goederen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_OFF                        :Uit
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_VERY_EASY                  :Heel Makkelijk
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_EASY                       :Makkelijk
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_AVERAGE                    :Gemiddeld
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_HARD                       :Moeilijk
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_VERY_HARD                  :Heel Moeilijk
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_INSANE                     :Maak me gek
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO                     :{LTBLUE}Stadsgroei gebaseerd op geleverde passagiers/post/goederen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_OFF                 :Uit
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_VERY_EASY           :Heel Makkelijk
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_EASY                :Makkelijk
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_AVERAGE             :Gemiddeld
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_HARD                :Moeilijk
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_VERY_HARD           :Heel Moeilijk
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_INSANE              :Maak me gek
+STR_CONFIG_SETTING_TOWN_GROWTH_MAX_POP_WO_GOODS                 :{LTBLUE}Max dorpsspopulatie alvorens goederen nodig zijn voor groei: {ORANGE}{STRING}
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_MAX_POP_WO_GOODS          :{LTBLUE}Max stadspopulatie alvorens goederen nodig zijn voor groei: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MODIFIED_ROAD_REBUILD                        :{LTBLUE}Verwijder rare weg-elementen tijdens het repareren van de weg: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TRAFFIC_LIGHTS                               :{LTBLUE}Schakel verkeerslichten aan: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWNS_BUILD_TRAFFIC_LIGHTS                   :{LTBLUE}Steden bouwen verkeerslichten tijdens het repareren van wegen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ALLOW_BUILDING_TLS_ON_TOWN_ROADS             :{LTBLUE}Laat bouwen en verwijderen van verkeerslichten op stedelijke wegen toe: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TRAFFIC_LIGHTS_GREEN_PHASE                   :{LTBLUE}Lengte van groene fase verkeerslicht: {ORANGE}{STRING}
+STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_SIZE               :{LTBLUE}Maximum grootte van samengestelde verkeerslichten: {ORANGE}{STRING} {RED}Waarschuwing: Hoge instellingen vertragen het spel
+STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_DISTANCE           :{LTBLUE}Maximum afstand tussen samengestelde verkeerslichten: {ORANGE}{STRING} tegels. {RED}Waarschuwing: Hoge instellingen vertragen het spel
+
+STR_CONFIG_SETTING_LINKGRAPH_INTERVAL                           :{LTBLUE}Link grafiek herberekeningsinterval: {ORANGE}{STRING} * 74 ticks
+STR_CONFIG_SETTING_DISTRIBUTION_PAX                             :{LTBLUE}Distributie voor passagiers: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_SYMMETRIC                   :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_ASYMMETRIC                  :asymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_MANUAL                      :manueel
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL                            :{LTBLUE}Distributie voor post: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_SYMMETRIC                  :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_ASYMMETRIC                 :asymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_MANUAL                     :manueel
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS                         :{LTBLUE}Distributie voor EXPRESS cargo klasse: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_SYMMETRIC               :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_ASYMMETRIC              :asymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_MANUAL                  :manueel
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED                        :{LTBLUE}Distributie voor GEPANDSERDE cargo klasse: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_SYMMETRIC              :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_ASYMMETRIC             :asymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_MANUAL                 :manueel
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT                         :{LTBLUE}Distributie voor andere cargo klassen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_SYMMETRIC               :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_ASYMMETRIC              :asymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_MANUAL                  :manueel
+STR_CONFIG_SETTING_LINKGRAPH_ACCURACY                           :{LTBLUE}Nauwkeurigheid linkgrafiek berekening: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DEMAND_DISTANCE                              :{LTBLUE}Effect van afstand op vraag: {ORANGE}{STRING}%
+STR_CONFIG_SETTING_DEMAND_SIZE                                  :{LTBLUE}Effect van ander station's populariteit op symmetrische vraag: {ORANGE}{STRING}%
+STR_CONFIG_SETTING_SHORT_PATH_SATURATION                        :{LTBLUE}Verzadiging van korte routes alvorens ruimere routes te gebruiken: {ORANGE}{STRING}%
+STR_CONFIG_SETTING_NO_OVERLOAD_LINKS                            :{LTBLUE}Probeer linkgrafieken niet te overladen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SMALLMAP_LINKGRAPH_COMPANIES                 :{LTBLUE}Toon linkgrafiek in de smallmap voor: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHOW_SMALLMAP_LINKGRAPH_OWN_ONLY             :enkel eigen bedrijf
+STR_CONFIG_SETTING_SHOW_SMALLMAP_LINKGRAPH_ALL_COMPANIES        :alle bedrijven
 
 STR_CONFIG_SETTING_GUI                                          :{ORANGE}Interface
 STR_CONFIG_SETTING_CONSTRUCTION                                 :{ORANGE}Constructie
 STR_CONFIG_SETTING_VEHICLES                                     :{ORANGE}Voertuigen
 STR_CONFIG_SETTING_STATIONS                                     :{ORANGE}Stations
 STR_CONFIG_SETTING_ECONOMY                                      :{ORANGE}Economie
+STR_CONFIG_SETTING_LINKGRAPH                                    :{ORANGE}Link grafiek
 STR_CONFIG_SETTING_AI                                           :{ORANGE}Tegenstanders
 STR_CONFIG_SETTING_DISPLAY_OPTIONS                              :{ORANGE}Weergave-opties
 STR_CONFIG_SETTING_INTERACTION                                  :{ORANGE}Interactie
 STR_CONFIG_SETTING_CONSTRUCTION_SIGNALS                         :{ORANGE}Seinen
+STR_CONFIG_SETTING_CONSTRUCTION_TRAFFIC_LIGHTS                  :{ORANGE}Verkeerslichten
 STR_CONFIG_SETTING_STATIONS_CARGOHANDLING                       :{ORANGE}Vrachtafhandeling
 STR_CONFIG_SETTING_AI_NPC                                       :{ORANGE}Computerspelers
+STR_CONFIG_SETTING_SHARING                                      :{ORANGE}Infrastructuur delen
 STR_CONFIG_SETTING_VEHICLES_AUTORENEW                           :{ORANGE}Automatisch vervangen
 STR_CONFIG_SETTING_VEHICLES_SERVICING                           :{ORANGE}Onderhoud
 STR_CONFIG_SETTING_VEHICLES_ROUTING                             :{ORANGE}Routebepaling
@@ -1354,10 +1499,20 @@
 STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Aanbevolen)
 
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Routezoeker voor treinen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_NPF                    :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_YAPF                   :YAPF {BLUE}(Aanbevolen)
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Routezoeker voor wegvoertuigen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_NPF             :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_YAPF            :YAPF {BLUE}(Aanbevolen)
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Routezoeker voor schepen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_OPF                     :Origineel
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_NPF                     :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_YAPF                    :YAPF {BLUE}(Aanbevolen)
 STR_CONFIG_SETTING_REVERSE_AT_SIGNALS                           :{LTBLUE}Automatisch omdraaien bij seinen: {ORANGE}{STRING}
 
+STR_CONFIG_SETTING_MORE_HEIGHTLEVELS                            :{LTBLUE}Laat terreinhoogte hoger dan 16 toe: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ERROR_NO_CHANGE_TO_OLD_POSSIBLE              :{WHITE}Je probeert de insteling te veranderen die terreinhoogte hoger dan 16 hoog toelaat. Helaas zijn er nog bergen hoger dan 16 hoog op de kaart. Sorry, dit is niet mogelijk.
+
 STR_CONFIG_SETTING_QUERY_CAPTION                                :{WHITE}Verander waarde
 
 # Intro window
@@ -1428,6 +1583,7 @@
 STR_CHEATS_TOOLTIP                                              :{BLACK}Keuzevakjes geven aan of je deze cheat eerder hebt gebruikt
 STR_CHEATS_WARNING                                              :{BLACK}Waarschuwing! Je staat op het punt je medespelers te verraden. Bedenk dat zo'n schande eeuwig wordt onthouden
 STR_CHEAT_MONEY                                                 :{LTBLUE}Verhoog geld met {CURRENCY}
+STR_CHEAT_DAYLENGHT_INCOME                                      :{LTBLUE}Deel voertuig inkomsten niet door daglengte factor: {ORANGE}{STRING}
 STR_CHEAT_CHANGE_COMPANY                                        :{LTBLUE}Spelen als bedrijf: {ORANGE}{COMMA}
 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}
@@ -1886,6 +2042,7 @@
 STR_TRANSPARENT_STRUCTURES_TOOLTIP                              :{BLACK}Schakel transparantie voor gebouwen zoals vuurtorens en antennes aan/uit. Ctrl+klik om vast te zetten
 STR_TRANSPARENT_CATENARY_TOOLTIP                                :{BLACK}Schakel transparantie voor bovenleiding aan/uit. Ctrl+klik voor onthouden
 STR_TRANSPARENT_LOADING_TOOLTIP                                 :{BLACK}Schakel transparantie voor laadindicatoren aan/uit. Ctrl+klik om vast te zetten
+STR_TRANSPARENT_TUNNELS_TOOLTIP                                 :{BLACK}Schakel transparentie voor voertuigen in tunnels aan/uit. Ctrl+Klik om vast te zetten.
 STR_TRANSPARENT_INVISIBLE_TOOLTIP                               :{BLACK}Maak objecten onzichtbaar in plaats van transparant
 
 # Base for station construction window(s)
@@ -1957,12 +2114,16 @@
 STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP                        :{BLACK}Ingangssein (semafoor){}Groen zolang als er één of meer groene uitgangsseinen zijn volgend na dit sein. Anders is deze rood
 STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP                         :{BLACK}Uitgangssein (armsein){}Gedraagt zich hetzelfde als een gewoon bloksein, maar is nodig om ingangs- en combinatieseinen te sturen
 STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP                        :{BLACK}Combinatiesein (armsein){}Het combinatiesein gedraagt zich als zowel ingangs- als uitgangssein. Zo kun je grote netwerken van beginseinen maken
+STR_BUILD_SIGNAL_SEMAPHORE_PROG_TOOLTIP                         :{BLACK}Programmeerbaar sein (armsein){}Het programmameerbaar sein is een combombinatie sein dat kan geprogrammeerd worden om zich op een complexe manier te gedragen
+STR_BUILD_SIGNAL_SEMAPHORE_SPEED_TOOLTIP                        :{BLACK}Snelheidssein (armsein){}Het snelheidssein stelt de maximum snelheid in die een trein mag rijden tot het een ander snelheidssein tegenkomt
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP                          :{BLACK}Routesein (armsein){}Een routesein laat meer dan één trein tegelijk in een seinblok toe, als de trein een route kan reserveren naar een veilige stopplaats. Routeseinen kunnen van achteren worden gepasseerd
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP                     :{BLACK}Eenrichtingsrouteseinen (armsein){}Een routesein laat meer dan één trein tegelijk in een seinblok toe, als de trein een route kan reserveren naar een veilige stopplaats. Eenrichtingsrouteseinen kunnen niet van achteren worden gepasseerd
 STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP                          :{BLACK}Standaard sein (elektrisch){}Seinen zijn nodig om te voorkomen dat treinen botsen bij netwerken met meer dan één trein
 STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP                         :{BLACK}Ingangssein (electrisch){}Groen als er meer dan één groen uitgangssein is in het volgende traject. Anders is deze rood
 STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP                          :{BLACK}Uitgangssein (elektrisch){}Gedraagt zich hetzelfde als een standaard sein, maar is nodig om ingangs- & combinatie-seinen aan te sturen
 STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP                         :{BLACK}Combinatiesein (electric){}Het combinatiesein gedraagt zicht als zowel ingangs- als uitgangs-sein. Zo kun je grote netwerken van beginseinen maken
+STR_BUILD_SIGNAL_ELECTRIC_PROG_TOOLTIP                          :{BLACK}Programmeerbaar sein (electrisch){}Het programmameerbaar sein is een combombinatie sein dat kan geprogrammeerd worden om zich op een complexe manier te gedragen
+STR_BUILD_SIGNAL_ELECTRIC_SPEED_TOOLTIP                         :{BLACK}Snelheidssein (electrisch){}Het snelheidssein stelt de maximum snelheid in die een trein mag rijden tot het een ander snelheidssein tegenkomt.
 STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP                           :{BLACK}Routeseinen (elektrisch){}Een routesein laat meer dan één trein tegelijk op een seinblok toe, als de trein een route kan reserveren naar een veilige stopplaats. Routeseinen kunnen van achteren worden gepasseerd
 STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP                      :{BLACK}Eenrichtingsrouteseinen (elektrisch){}Een routesein laat meer dan één trein tegelijk op een seinblok toe, als de trein een route kan reserveren naar een veilige stopplaats. Eenrichtingsrouteseinen kunnen niet van achteren worden gepasseerd
 STR_BUILD_SIGNAL_CONVERT_TOOLTIP                                :{BLACK}Sein ombouwen{}Indien geselecteerd, zal door te klikken op een bestaand sein deze worden omgebouwd naar het geselecteerde seintype en variant, Ctrl+klik verandert de bestaande variant (armsein/elektrisch). Shift+klik toont de geschatte ombouwkosten
@@ -1970,6 +2131,73 @@
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP          :{BLACK}Verklein dichtheid van seinen bij het slepen
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP          :{BLACK}Vergroot dichtheid van seinen bij het slepen
 
+# Programmable Signals
+STR_PROGRAM_SIGNAL_TOOLTIP                                      :{BLACK}Programmeerbaar sein
+
+STR_ERR_PROGSIG_INVALID_INSTRUCTION                             :{WHITE}Instructie kan niet ingevoegd worden na instructie met ongeldige ID
+STR_ERR_PROGSIG_INVALID_OPCODE                                  :{WHITE}Instructie met deze opcode kan niet ingevoegd worden
+STR_ERR_PROGSIG_NOT_THERE                                       :{WHITE}Er is geen programmeerbaar sein hier
+STR_ERR_PROGSIG_INVALID_SIGNAL_STATE                            :{WHITE}Deze sein status is ongeldig
+STR_ERR_PROGSIG_INVALID_CONDITION                               :{WHITE}Deze conditie is ongeldig
+STR_ERR_PROGSIG_INVALID_CONDITION_FIELD                         :{WHITE}Dit veld is ongeldig voor deze conditie
+STR_ERR_PROGSIG_INVALID_COMPARATOR                              :{WHITE}Deze vergelijking is ongeldig
+STR_ERR_PROGSIG_INVALID_SIGNAL                                  :{WHITE}Ongeldig sein geselecteerd
+
+STR_PROGSIG_CAPTION                                             :{WHITE}Sein Programma
+STR_PROGSIG_COND_VARIABLE_TOOLTIP                               :{BLACK}Conditie om te vergelijken
+STR_PROGSIG_COND_COMPARATOR_TOOLTIP                             :{BLACK}Operator om variable te vergelijken
+STR_PROGSIG_COND_VALUE_TOOLTIP                                  :{BLACK}Waarde om variable tegen te vergelijken
+STR_PROGSIG_SIGNAL_STATE_TOOLTIP                                :{BLACK}Stel sein status in
+STR_PROGSIG_COND_SET_SIGNAL                                     :{BLACK}Stel sein in
+STR_PROGSIG_COND_SET_SIGNAL_TOOLTIP                             :{BLACK}Kies het sein om te evalueren
+STR_PROGSIG_GOTO_SIGNAL                                         :{BLACK}Ga naar sein
+STR_PROGSIG_GOTO_SIGNAL_TOOLTIP                                 :{BLACK}Ga naar dit sein
+STR_PROGSIG_INSERT_TOOLTIP                                      :{BLACK}Voeg instructie in
+STR_PROGSIG_REMOVE_TOOLTIP                                      :{BLACK}Verwijder de geselecteerde instructie
+
+STR_PROGSIG_REMOVE                                              :{BLACK}Verwijder
+STR_PROGSIG_INSERT                                              :Voeg in
+STR_PROGSIG_INSERT_IF                                           :Conditie
+STR_PROGSIG_INSERT_SET_SIGNAL                                   :Stel sein status in
+
+STR_PROGSIG_FIRST                                               :Start
+STR_PROGSIG_LAST                                                :Einde
+
+STR_PROGSIG_IF                                                  :Als {STRING} dan
+STR_PROGSIG_ELSE                                                :Anders
+STR_PROGSIG_ENDIF                                               :Einde Als
+
+STR_PROGSIG_SET_SIGNAL                                          :Maak sein {STRING}
+
+STR_PROGSIG_COND_ALWAYS                                         :altijd
+STR_PROGSIG_COND_NEVER                                          :nooit
+STR_PROGSIG_COND_COMPARE                                        :{STRING} {STRING} {NUM}
+STR_PROGSIG_COND_SIGNAL_STATE                                   :sein status
+STR_PROGSIG_CONDVAR_SIGNAL_STATE                                :{STRING} is groen
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_SPECIFIED                      :gespecifieerd sein
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_UNSPECIFIED                    :{RED}onspecifieerd sein{STRING}
+STR_PROGSIG_CONDVAR_NUM_RED                                     :rode seinen
+STR_PROGSIG_CONDVAR_NUM_GREEN                                   :groene seinen
+
+STR_PROGSIG_CONDITION_VALUE_CAPT                                :{WHITE}Conditie waarde
+
+STR_ERROR_CAN_T_INSERT_INSTRUCTION                              :{WHITE}Kan instructie niet invoegen
+STR_ERROR_CAN_T_MODIFY_INSTRUCTION                              :{WHITE}Kan instructie niet wijzigen
+STR_ERROR_CAN_T_REMOVE_INSTRUCTION                              :{WHITE}Kan instructie niet verwijderen
+STR_ERROR_CAN_T_GOTO_UNDEFINED_SIGNAL                           :{WHITE}Kan niet naar ondefinieerd sein gaan
+STR_ERROR_NOT_AN_EXIT_SIGNAL                                    :{WHITE}Is geen uitgangs sein
+STR_ERROR_CAN_T_DEPEND_UPON_BIDIRECTIONAL_SIGNALS               :{WHITE}Kan niet conditioneel afhangen van tweerichtings sein
+STR_ERROR_INVALID_SIGNAL                                        :{WHITE}Ongeldig sein
+
+STR_SPEEDSIG_CAPTION                                            :{WHITE}Snelheids Limiet
+
+STR_SPEEDSIG_VALUE_NONE                                         :{WHITE}Geen snelheids limiet
+STR_SPEEDSIG_VALUE                                              :{WHITE}{VELOCITY}
+STR_SPEEDSIG_CLEAR                                              :{BLACK}Verwijder
+STR_SPEEDSIG_CHANGE                                             :{BLACK}Verander
+
+STR_ERROR_CAN_T_SET_SPEED                                       :{WHITE}Kan snelheids limiet niet instellen
+
 # Bridge selection window
 STR_SELECT_RAIL_BRIDGE_CAPTION                                  :{WHITE}Kies type spoorbrug
 STR_SELECT_ROAD_BRIDGE_CAPTION                                  :{WHITE}Kies type brug
@@ -2000,6 +2228,7 @@
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY                :{BLACK}Bouw vrachtwagenlaadhal. Houd Ctrl ingedrukt om samen te voegen met ander station. Shift schakelt tussen bouwen/inschatting van de kosten
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION               :{BLACK}Bouw vrachttramhalte. Houd Ctrl ingedrukt om samen te voegen met ander station. Shift schakelt tussen bouwen/inschatting van de kosten
 STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD                    :{BLACK}Activeer/Deactiveer eenrichtingsverkeer
+STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAFFIC_LIGHT                    :{BLACK}Bouw verkeerslichten
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE                      :{BLACK}Bouw viaduct. Shift schakelt tussen bouwen/inschatting van de kosten
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE                   :{BLACK}Bouw brug voor tramrails. Shift schakelt tussen bouwen/inschatting van de kosten
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL                      :{BLACK}Bouw wegtunnel. Shift schakelt tussen bouwen/inschatting van de kosten
@@ -2075,6 +2304,29 @@
 STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND                  :{BLACK}Verhoog een hoek van het land. Slepen verhoogt de eerste geselecteerde hoek en brengt het geselecteerde gebied naar de hoogte van die hoek. Ctrl selecteert het gebied diagonaal. Shift maakt een inschatting van de kosten
 STR_LANDSCAPING_LEVEL_LAND_TOOLTIP                              :{BLACK}Egaliseer land naar de hoogte van de eerst geselecteerde hoek. Ctrl selecteert een diagonaal gebied. Shift+klik wisselt tussen bouwen/tonen verwachte kosten
 STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND                           :{BLACK}Koop land voor toekomstig gebruik. Shift+klik wisselt tussen bouwen/tonen verwachte kosten
+STR_LANDSCAPING_TOOLTIP_RULER_TOOL                              :{BLACK}Gebruik een virtuele meetlat om afstand en hoogte te meten
+ 
+# Copy Paste
+STR_COPY_PASTE_TOOLBAR                                          :{WHITE}Kopieer
+STR_COPY_PASTE_TOOLTIP                                          :{BLACK}Kopieer & Plak
+STR_COPY_PASTE_COPY_TOOLTIP                                     :{BLACK}Kopieer het geselecteerde gebied
+STR_COPY_PASTE_PASTE_TOOLTIP                                    :{BLACK}Plak het gekopieerde gebied
+STR_COPY_PASTE_ROTATE_LEFT_TOOLTIP                              :{BLACK}Draai 90 graden in wijzerszin
+STR_COPY_PASTE_ROTATE_RIGHT_TOOLTIP                             :{BLACK}Draai 90 graden in tegenwijzerszin
+STR_COPY_PASTE_VACANT_TERRAIN_TOOLTIP                           :{BLACK}Als vrij plak terrein ook.
+STR_COPY_PASTE_LOAD_TOOLTIP                                     :{BLACK}Laad een voorheen opgeslagen sjabloon
+STR_COPY_PASTE_SAVE_TOOLTIP                                     :{BLACK}Sla het momenteel geselecteerde gebied op naar een sjabloon
+STR_COPY_PASTE_MIRROR_HORIZONTAL_TOOLTIP                        :{BLACK}Spiegel het momenteel geselecteerde gebied rond de horizontale as
+STR_COPY_PASTE_MIRROR_VERTICAL_TOOLTIP                          :{BLACK}Spiegel het momenteel geselecteerde gebied rond de verticale as
+STR_COPY_PASTE_BULLDOZE_BEFORE_BUILD_TOOLTIP                    :{BLACK}Sloop niet vrij terrein alvorens te plakken
+STR_COPY_PASTE_TOGGLE_SIGNAL_DIRECTION_TOOLTIP                  :{BLACK}Verander de sein richting tijdens het plakken
+STR_COPY_PASTE_CONVERT_RAIL_TOOLTIP                             :{BLACK}Verander spoortype naar momenteel geselcteerd spoortype tijdens het plakken
+STR_COPY_PASTE_WITHOUT_RAIL_TOOLTIP                             :{BLACK}Indien aktief zal spoor worden gepopieerd
+STR_COPY_PASTE_WITHOUT_ROAD_TOOLTIP                             :{BLACK}Indien aktief zal weg worden gekopieerd
+STR_COPY_PASTE_ONLY_OWN_TOOLTIP                                 :{BLACK}Indien aktief zal alleen jou eigen infrastuctuur worden gekopieerd
+
+STR_COPY_PASTE_PASTE_DISABLED                                   :{WHITE}Plakken is uitgeschakeld...
+STR_CONFIG_PATCHES_CP_PASTE_SPEED                               :{LTBLUE}Plaksnelheid in multiplayer. (255 = uit): {ORANGE}{STRING}
 
 # Object construction window
 STR_OBJECT_BUILD_CAPTION                                        :{WHITE}Keuze van object
@@ -2176,6 +2428,7 @@
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Gemeente: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Geen
 STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coördinaten: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_HEIGHT                       :{BLACK}Hoogte: {LTBLUE}{NUM}
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Bouwjaar: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stationsklasse: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stationstype: {LTBLUE}{STRING}
@@ -2225,6 +2478,7 @@
 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD                        :Weg met bomenrij
 STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT                     :Garage
 STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING               :Gelijkvloerse overweg
+STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_TRAFFIC_LIGHTS               :Weg met verkeerslichten
 STR_LAI_ROAD_DESCRIPTION_TRAMWAY                                :Tramrails
 
 # Houses come directly from their building names
@@ -2253,8 +2507,10 @@
 # Industries come directly from their industry names
 
 STR_LAI_TUNNEL_DESCRIPTION_RAILROAD                             :Spoortunnel
+STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_SIGNAL                      :Spoorweg tunnel met sein simulatie
 STR_LAI_TUNNEL_DESCRIPTION_ROAD                                 :Wegtunnel
 
+STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL                      :Spoorwegbrug met sein simulatie
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL                :Stalen hangbrug (spoor)
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL                    :Stalen kokerbrug (spoor)
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL                :Stalen cantileverbrug (spoor)
@@ -2284,6 +2540,9 @@
 STR_ABOUT_VERSION                                               :{BLACK}OpenTTD versie {REV}
 STR_ABOUT_COPYRIGHT_OPENTTD                                     :{BLACK}OpenTTD {COPYRIGHT} 2002-2011 Het OpenTTD team
 
+# System time window
+STR_SYSTEM_TIME                                                 :{WHITE}Systeem tijd
+
 # Save/load game/scenario
 STR_SAVELOAD_SAVE_CAPTION                                       :{WHITE}Spel Opslaan
 STR_SAVELOAD_LOAD_CAPTION                                       :{WHITE}Spel Laden
@@ -2291,6 +2550,8 @@
 STR_SAVELOAD_LOAD_SCENARIO                                      :{WHITE}Scenario Laden
 STR_SAVELOAD_LOAD_HEIGHTMAP                                     :{WHITE}Laad Hoogtekaart
 STR_SAVELOAD_SAVE_HEIGHTMAP                                     :{WHITE}Hoogtekaart Opslaan
+STR_SAVELOAD_SAVE_COPY_PASTE_TEMPLATE                           :{WHITE}Sla sjabloon op
+STR_SAVELOAD_LOAD_COPY_PASTE_TEMPLATE                           :{WHITE}Laad sjabloon
 STR_SAVELOAD_HOME_BUTTON                                        :{BLACK}Klik hier om naar de standaard bewaar-/laadmap te gaan
 STR_SAVELOAD_BYTES_FREE                                         :{BLACK}{BYTES} vrij
 STR_SAVELOAD_LIST_TOOLTIP                                       :{BLACK}Lijst van schijven, mappen en opgeslagen spellen
@@ -2307,6 +2568,10 @@
 STR_SAVELOAD_DETAIL_GRFSTATUS                                   :{SILVER}NewGRF: {WHITE}{STRING}
 
 STR_SAVELOAD_OSKTITLE                                           :{BLACK}Voer een naam in voor het spel dat moet worden opgeslagen
+STR_TEMPLATE_LOAD_FAILED                                        :{WHITE}Sjabloon laden mislukt{}{STRING}
+STR_TEMPLATE_SAVE_FAILED                                        :{WHITE}Sjabloon opslaan mislukt{}{STRING}
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW                        :Sjabloon is gemaakt met nieuwere versie
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN                         :Sjabloon is ongeldig
 
 # World generation
 STR_MAPGEN_WORLD_GENERATION_CAPTION                             :{WHITE}Wereldontwikkeling
@@ -2318,6 +2583,12 @@
 STR_MAPGEN_SNOW_LINE_HEIGHT                                     :{BLACK}Hoogte van sneeuwgrens:
 STR_MAPGEN_SNOW_LINE_UP                                         :{BLACK}Verschuif de sneeuwgrens één omhoog
 STR_MAPGEN_SNOW_LINE_DOWN                                       :{BLACK}Verschuif de sneeuwgrens één omlaag
+STR_MAPGEN_DESERT_AMOUNT                                        :{BLACK}Hoeveelheid woestijn:
+STR_MAPGEN_DESERT_AMOUNT_UP                                     :{BLACK}Verhoog de hoeveelheid woestijn tegels op de kaart
+STR_MAPGEN_DESERT_AMOUNT_DOWN                                   :{BLACK}Verlaag de hoeveelheid woestijn tegels op de kaart
+STR_MAPGEN_TREE_LINE_HEIGHT                                     :{BLACK}Hoogte van boomgrens:
+STR_MAPGEN_TREE_LINE_UP                                         :{BLACK}Verschuif de boomgrens één omoog
+STR_MAPGEN_TREE_LINE_DOWN                                       :{BLACK}Verschuif de boomgrens één omhoog
 STR_MAPGEN_RANDOM_SEED                                          :{BLACK}Willekeurig getal:
 STR_MAPGEN_RANDOM_SEED_HELP                                     :{BLACK}Klik om een willekeurig getal in te voeren
 STR_MAPGEN_RANDOM                                               :{BLACK}Willekeurig maken
@@ -2350,6 +2621,8 @@
 
 STR_MAPGEN_RANDOM_SEED_OSKTITLE                                 :{BLACK}Voer een willekeurig getal in
 STR_MAPGEN_SNOW_LINE_QUERY_CAPT                                 :{WHITE}Verander hoogte van sneeuwgrens
+STR_MAPGEN_DESERT_AMOUNT_QUERY_CAPT                             :{WHITE}Verander hoeveelheid van woestijn
+STR_MAPGEN_TREE_LINE_QUERY_CAPT                                 :{WHITE}Verander hoogte van boomgrens
 STR_MAPGEN_START_DATE_QUERY_CAPT                                :{WHITE}Verander beginjaar
 
 # SE Map generation
@@ -2559,12 +2832,35 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Groeistad)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Bevolking: {ORANGE}{COMMA}{BLACK}  Huizen: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passagiers afgelopen maand: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Post afgelopen maand: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Vracht nodig voor groei van stad:
+STR_TOWN_VIEW_GENERATED_CARGO_LAST_MONTH                        :{BLACK}Gegenereerde cargo vorige maand:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passagiers: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Post: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Cargo geleverd / gevraagd voor stads groei deze maand:
+STR_TOWN_VIEW_PASSENGERS_THIS_MONTH_MAX                         :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Nodig voor 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_MAIL_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Nodig voor 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_FOOD_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Nodig voor 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_WATER_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Nodig voor 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GOODS_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Nodig voor 100%: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} noodzakelijk
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} noodzakelijk in de winter
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} afgelopen maand afgeleverd
+STR_TOWN_VIEW_GROWTH_RATE_LAST_MONTH                            :{BLACK}Groeisnelheid vorige maand: {ORANGE}{COMMA}{BLACK} %
+STR_TOWN_VIEW_GROWTH_SPEED_DISABLED                             :{RED}Groeisnelheid steden is ingesteld op niet! Geen groei mogelijk.
+STR_TOWN_VIEW_TRANSPORTED_RATE_LAST_MONTH                       :{BLACK}Voldane groeivoorwaarden vorige maand: {ORANGE}{COMMA} %
+STR_TOWN_VIEW_CARGO_DEMAND_LAST_MONTH                           :{BLACK}Meest gevraagd vorige maand: {ORANGE}{STRING}
+STR_TOWN_VIEW_GROWTH_STANDARD                                   :Nog niet berekend
+STR_TOWN_VIEW_GROWTH_NEED_STATION                               :Meer bediende stations
+STR_TOWN_VIEW_GROWTH_NEED_MORE_PASS                             :Meer {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_MAIL                             :Meer {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_FOOD                             :Meer {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_WATER                            :Meer {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_GOODS                            :Meer {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_PASS                                  :{STRING} distributie
+STR_TOWN_VIEW_GROWTH_NEED_MAIL                                  :{STRING} distributie
+STR_TOWN_VIEW_GROWTH_NEED_FOOD                                  :{STRING} distributie
+STR_TOWN_VIEW_GROWTH_NEED_WATER                                 :{STRING} distributie
+STR_TOWN_VIEW_GROWTH_NEED_GOODS                                 :{STRING} distributie
+STR_TOWN_VIEW_GROWTH_SATISFIED                                  :Hou vol !
 STR_TOWN_VIEW_NOISE_IN_TOWN                                     :{BLACK}Geluidslimiet in stad: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CENTER_TOOLTIP                                    :{BLACK}Centreer het scherm op de locatie van de stad. Ctrl+klik opent een nieuw kijkvenster op de locatie van de stad
 STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON                            :{BLACK}Gemeente
@@ -2637,8 +2933,35 @@
 
 STR_STATION_VIEW_RATINGS_BUTTON                                 :{BLACK}Rangen
 STR_STATION_VIEW_RATINGS_TOOLTIP                                :{BLACK}Bekijk stationsreputaties
-STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Lokale rang van de vervoerdienst:
+STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Maandelijkse bevoorrading en locale reputatie:
 STR_STATION_VIEW_CARGO_RATING                                   :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA}%)
+STR_STATION_VIEW_CARGO_SUPPLY_RATING                            :{WHITE}{STRING}: {YELLOW}{COMMA} / {STRING} ({COMMA}%)
+ 
+STR_STATION_VIEW_DEPARTURES_BUTTON                              :{BLACK}Vertrektijden
+STR_STATION_VIEW_DEPARTURES_TOOLTIP                             :{BLACK}Toon lijst van geplande vertrektijden
+
+STR_STATION_VIEW_GROUP                                          :{BLACK}Groepeer volgens
+STR_STATION_VIEW_WAITING_STATION                                :Station: Wachtend
+STR_STATION_VIEW_WAITING_AMOUNT                                 :Hoeveelheid: Wachtend
+STR_STATION_VIEW_PLANNED_STATION                                :Station: Gepland
+STR_STATION_VIEW_PLANNED_AMOUNT                                 :Hoeveelheid: Gepland
+STR_STATION_VIEW_FROM                                           :{YELLOW}{SHORTCARGO} van {STATION}
+STR_STATION_VIEW_VIA                                            :{YELLOW}{SHORTCARGO} via {STATION}
+STR_STATION_VIEW_TO                                             :{YELLOW}{SHORTCARGO} naar {STATION}
+STR_STATION_VIEW_FROM_ANY                                       :{RED}{SHORTCARGO} van onbekend station
+STR_STATION_VIEW_TO_ANY                                         :{RED}{SHORTCARGO} naar eender welk station
+STR_STATION_VIEW_VIA_ANY                                        :{RED}{SHORTCARGO} via eender welk station
+STR_STATION_VIEW_FROM_HERE                                      :{GREEN}{SHORTCARGO} van dit station
+STR_STATION_VIEW_VIA_HERE                                       :{GREEN}{SHORTCARGO} stopt in dit station
+STR_STATION_VIEW_TO_HERE                                        :{GREEN}{SHORTCARGO} naar dit station
+STR_STATION_VIEW_NONSTOP                                        :{YELLOW}{SHORTCARGO} non-stop
+
+STR_STATION_VIEW_GROUP_S_V_D                                    :Bron-Via-Destinatie
+STR_STATION_VIEW_GROUP_S_D_V                                    :Bron-Destinatie-Via
+STR_STATION_VIEW_GROUP_V_S_D                                    :Via-Bron-Destinatie
+STR_STATION_VIEW_GROUP_V_D_S                                    :Via-Destinatie-Bron
+STR_STATION_VIEW_GROUP_D_S_V                                    :Destinatie-Bron-Via
+STR_STATION_VIEW_GROUP_D_V_S                                    :Destinatie-Via-Bron
 
 ############ range for rating starts
 STR_CARGO_RATING_APPALLING                                      :Teleurstellend
@@ -2661,6 +2984,79 @@
 
 STR_STATION_VIEW_RENAME_STATION_CAPTION                         :Hernoem station/laadgebied
 
+# Departures window
+STR_DEPARTURES_CAPTION                                          :{WHITE}{STATION} Vertrek/Aankomst Tijdstabel
+STR_DEPARTURES_CAPTION_WAYPOINT                                 :{WHITE}{WAYPOINT} Vertrek/Aankomst Tijdstabel
+STR_DEPARTURES_DEPARTURES                                       :{BLACK}{TINYFONT}D
+STR_DEPARTURES_ARRIVALS                                         :{BLACK}{TINYFONT}A
+STR_DEPARTURES_VIA_BUTTON                                       :{BLACK}{TINYFONT}Via
+STR_DEPARTURES_DEPARTURES_TOOLTIP                               :{BLACK}Toon vertrek tijdstabellen
+STR_DEPARTURES_ARRIVALS_TOOLTIP                                 :{BLACK}Toon aankomst tijdstabellen
+STR_DEPARTURES_VIA_TOOLTIP                                      :{BLACK}Toon voertuigen met tijdstabellen die hier niet stoppen
+STR_DEPARTURES_EMPTY                                            :{ORANGE}Momenteel gebruiken geen voertuigen vertrekkend van dit station tijdstabellen
+STR_DEPARTURES_NONE_SELECTED                                    :{ORANGE}Geen tijdstabel informatie is opgevraagd
+STR_DEPARTURES_TIME                                             :{ORANGE}{DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_TIME_DEP                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TIME_ARR                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {RED}{DOWNARROW}
+STR_DEPARTURES_TIME_BOTH                                        :{ORANGE}{1:DATE_WALLCLOCK_TINY} {RED}{DOWNARROW} {ORANGE}{0:DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TERMINUS                                         :{ORANGE}{STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA_STATION                             :{ORANGE}{STATION}{STRING} via {STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA                                     :{ORANGE}{STATION}{STRING} via
+STR_DEPARTURES_VIA                                              :{ORANGE}via {STATION}{STRING}
+STR_DEPARTURES_TOC                                              :{ORANGE}{COMPANY}
+STR_DEPARTURES_GROUP                                            :{ORANGE}{GROUP}
+STR_DEPARTURES_VEH                                              :{ORANGE}{VEHICLE}
+STR_DEPARTURES_CALLING_AT                                       :{TINYFONT}{ORANGE}Stopt in:
+STR_DEPARTURES_CALLING_AT_LARGE                                 :{ORANGE}Stopt in:
+STR_DEPARTURES_CALLING_AT_FIRST_STATION                         :{STATION}
+STR_DEPARTURES_CALLING_AT_STATION                               :{STRING}, {STATION}
+STR_DEPARTURES_CALLING_AT_LAST_STATION                          :{STRING} en {STATION}
+STR_DEPARTURES_CALLING_AT_LIST                                  :{TINYFONT}{ORANGE}{STRING}
+STR_DEPARTURES_CALLING_AT_LIST_LARGE                            :{ORANGE}{STRING}
+
+STR_DEPARTURES_TYPE_TRAIN                                       :{ORANGE}{TRAIN}
+STR_DEPARTURES_TYPE_TRAIN_SILVER                                :{SILVER}{TRAIN}
+STR_DEPARTURES_TYPE_BUS                                         :{ORANGE}{BUS}
+STR_DEPARTURES_TYPE_BUS_SILVER                                  :{SILVER}{BUS}
+STR_DEPARTURES_TYPE_LORRY                                       :{ORANGE}{LORRY}
+STR_DEPARTURES_TYPE_LORRY_SILVER                                :{SILVER}{LORRY}
+STR_DEPARTURES_TYPE_PLANE                                       :{ORANGE}{PLANE}
+STR_DEPARTURES_TYPE_PLANE_SILVER                                :{SILVER}{PLANE}
+STR_DEPARTURES_TYPE_SHIP                                        :{ORANGE}{SHIP}
+STR_DEPARTURES_TYPE_SHIP_SILVER                                 :{SILVER}{SHIP}
+
+STR_DEPARTURES_STATION_NONE                                     :
+STR_DEPARTURES_STATION_PORT                                     :{ORANGE} {SHIP}
+STR_DEPARTURES_STATION_AIRPORT                                  :{ORANGE} {PLANE}
+STR_DEPARTURES_STATION_PORTAIRPORT                              :{ORANGE} {SHIP} {PLANE}
+
+############ mogelijke start statussen
+STR_DEPARTURES_ON_TIME                                          :{GREEN}Op tijd
+STR_DEPARTURES_ARRIVED                                          :{GREEN}Aangekomen
+STR_DEPARTURES_DELAYED                                          :{YELLOW}Vertraagd
+STR_DEPARTURES_EXPECTED                                         :{YELLOW}Aankomst {DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_CANCELLED                                        :{RED}Geannuleerd
+
+############ config settings
+STR_CONFIG_SETTING_DEPARTUREBOARDS                              :{ORANGE}Vertek/Aankomst Tijdstabellen
+STR_CONFIG_MAX_DEPARTURES                                       :{LTBLUE}Toon maximaal {ORANGE}{STRING}{LTBLUE} vertrektijden voor elk station
+STR_CONFIG_MAX_DEPARTURE_TIME                                   :{LTBLUE}Toon vertrektijden maximaal {ORANGE}{STRING}{LTBLUE} dagen op voorhand
+STR_CONFIG_DEPARTURE_CALC_FREQUENCY                             :{LTBLUE}Bereken vertrektijden elke {ORANGE}{STRING}{LTBLUE} ticks
+STR_CONFIG_DEPARTURE_VEHICLE_NAME                               :{LTBLUE}Toon voertuignamen bij vertrektijden: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_GROUP_NAME                                 :{LTBLUE}Toon groep naam bij vertrektijden: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_COMPANY_NAME                               :{LTBLUE}Toon bedrijfsnaam bij vertrektijden: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_VEHICLE_TYPE                               :{LTBLUE}Toon voertuig type icoon bij vertrektijden: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_VEHICLE_COLOR                              :{LTBLUE}Toon voertuig type icoon in zilver: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_LARGER_FONT                                :{LTBLUE}Gebruik groter lettertype voor stations in vertrektijdstabellen : {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_DESTINATION_TYPE                           :{LTBLUE}Toon iconen voor bestemmingen die havens of vliegvelden zijn: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_SHOW_BOTH                                  :{LTBLUE}Toon aankomst en vertrek tijden op dezelfde lijn: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_ONLY_PASSENGERS                            :{LTBLUE}Toon vertektijden alleen voor passagiers voertuigen: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_CONDITIONALS                               :{LTBLUE}Behandeling van conditionele orders: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_CONDITIONALS_1                             :geef op
+STR_CONFIG_DEPARTURE_CONDITIONALS_2                             :verondersteld dat ze gebruikt worden
+STR_CONFIG_DEPARTURE_CONDITIONALS_3                             :verondersteld dat ze niet gebruikt worden
+STR_CONFIG_DEPARTURE_SHOW_ALL_STOPS                             :{LTBLUE}Toon alle stopplaatsen ongeacht laadorders: {ORANGE}{STRING}
+
 # Waypoint/buoy view window
 STR_WAYPOINT_VIEW_CAPTION                                       :{WHITE}{WAYPOINT}
 STR_WAYPOINT_VIEW_CENTER_TOOLTIP                                :{BLACK}Centreer scherm op de locatie van de controlepost. Ctrl+klik opent een nieuw venster op de locatie van de controlepost
@@ -2686,6 +3082,8 @@
 STR_FINANCES_SECTION_AIRCRAFT_INCOME                            :{GOLD}Vliegtuiginkomsten
 STR_FINANCES_SECTION_SHIP_INCOME                                :{GOLD}Schipinkomsten
 STR_FINANCES_SECTION_LOAN_INTEREST                              :{GOLD}Rente van lening
+STR_FINANCES_SECTION_INFRASTRUCTURE_COSTS                       :{GOLD}Kosten van infrastructuur delen
+STR_FINANCES_SECTION_INFRASTRUCTURE_INCOME                      :{GOLD}Inkomsten van infrastructuur delen
 STR_FINANCES_SECTION_OTHER                                      :{GOLD}Overig
 STR_FINANCES_NEGATIVE_INCOME                                    :{BLACK}-{CURRENCY}
 STR_FINANCES_POSITIVE_INCOME                                    :{BLACK}+{CURRENCY}
@@ -2721,6 +3119,11 @@
 STR_COMPANY_VIEW_RELOCATE_HQ                                    :{BLACK}Verplaats bedrijfshoofdkwartier
 STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS                  :{BLACK}Herbouw bedrijfshoofdkwartier ergens anders voor 1% van de bedrijfswaarde. Shift+klik toont verwachte kosten zonder HQ te verplaatsen
 
+STR_COMPANY_PROFILE_LOAD_BUTTON                                 :{BLACK}Laad bedrijfsprofiel
+STR_COMPANY_PROFILE_LOAD_TOOLTIP                                :{BLACK}Laad een bedrijfsprofiel
+STR_COMPANY_PROFILE_SAVE_BUTTON                                 :{BLACK}Bewaar bedrijfsprofiel
+STR_COMPANY_PROFILE_SAVE_TOOLTIP                                :{BLACK}Bewaar huidig bedrijfsprofiel
+
 STR_COMPANY_VIEW_NEW_FACE_BUTTON                                :{BLACK}Nieuw gezicht
 STR_COMPANY_VIEW_NEW_FACE_TOOLTIP                               :{BLACK}Kies nieuw gezicht voor directeur
 STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON                           :{BLACK}Kleurenschema
@@ -2827,6 +3230,9 @@
 
 STR_GROUP_RENAME_CAPTION                                        :{BLACK}Hernoem een groep
 
+STR_GROUP_PROFIT_THIS_YEAR                                      :{BLACK}Winst dit jaar: {CURRENCY}
+STR_GROUP_PROFIT_LAST_YEAR                                      :{BLACK}Winst vorig jaar: {CURRENCY}
+
 # Build vehicle window
 STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION                              :Nieuwe railvoertuigen
 STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION                            :Nieuwe elektrische railvoertuigen
@@ -3058,15 +3464,30 @@
 STR_VEHICLE_STATUS_LEAVING                                      :{LTBLUE}Vertrekt van
 STR_VEHICLE_STATUS_CRASHED                                      :{RED}Gecrasht!
 STR_VEHICLE_STATUS_BROKEN_DOWN                                  :{RED}Motorpech
+STR_VEHICLE_STATUS_BROKEN_DOWN_VEL                              :{RED}Motorpech - {STRING}, {LTBLUE} {VELOCITY}
 STR_VEHICLE_STATUS_STOPPED                                      :{RED}Gestopt
+STR_VEHICLE_STATUS_TRAIN_STOPPING                               :{RED}Aan het stoppen
 STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL                           :{RED}Aan het stoppen, {VELOCITY}
 STR_VEHICLE_STATUS_TRAIN_NO_POWER                               :{RED}Geen stroom
 STR_VEHICLE_STATUS_TRAIN_STUCK                                  :{ORANGE}Wacht op vrije route
 
+STR_BREAKDOWN_TYPE_CRITICAL                                     :Mechanisch defect
+STR_BREAKDOWN_TYPE_EM_STOP                                      :Noodstop
+STR_BREAKDOWN_TYPE_LOW_SPEED                                    :Gelimiteerd tot {VELOCITY}
+STR_BREAKDOWN_TYPE_LOW_POWER                                    :{COMMA}% kracht
+STR_BREAKDOWN_TYPE_DEPOT                                        :Onderweg naar {STATION} depot voor reparaties
+STR_BREAKDOWN_TYPE_LANDING                                      :Onderweg naar {STATION} voor noodlanding
+STR_ERROR_TRAIN_TOO_HEAVY                                       :{WHITE}{VEHICLE} is te zwaar
+
+STR_VEHICLE_STATUS_HEADING_FOR_STATION                          :{LTBLUE}Op weg naar {STATION}
 STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL                      :{LTBLUE}Op weg naar {STATION}, {VELOCITY}
+STR_VEHICLE_STATUS_NO_ORDERS                                    :{LTBLUE}Geen orders
 STR_VEHICLE_STATUS_NO_ORDERS_VEL                                :{LTBLUE}Geen orders, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT                         :{LTBLUE}Op weg naar {WAYPOINT}
 STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL                     :{LTBLUE}Op weg naar {WAYPOINT}, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_DEPOT                            :{ORANGE}Onderweg naar {DEPOT}
 STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL                        :{ORANGE}Onderweg naar {DEPOT}, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE                    :{LTBLUE}Onderhoud in {DEPOT}
 STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL                :{LTBLUE}Onderhoud in {DEPOT}, {VELOCITY}
 
 # Vehicle stopped/started animations
@@ -3085,6 +3506,11 @@
 STR_VEHICLE_DETAILS_AIRCRAFT_RENAME                             :{BLACK}Hernoem vliegtuig
 
 STR_VEHICLE_INFO_AGE_RUNNING_COST_YR                            :{BLACK}Leeftijd: {LTBLUE}{STRING}{BLACK}   Gebruikskosten: {LTBLUE}{CURRENCY}/yr
+
+STR_RUNNING                                                     :{LTBLUE}Operationeel
+STR_NEED_REPAIR                                                 :{ORANGE}Trein heeft reparaties nodig - max snelheid beperkt tot {VELOCITY}
+STR_CURRENT_STATUS                                              :{BLACK}Huidige status: {STRING}
+
 # The next two need to stay in this order
 STR_VEHICLE_INFO_AGE                                            :{COMMA} ja{P ar ren} ({COMMA})
 STR_VEHICLE_INFO_AGE_RED                                        :{RED}{COMMA} ja{P ar ren} ({COMMA})
@@ -3116,7 +3542,9 @@
 
 # Extra buttons for train details windows
 STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE                :{LTBLUE}{ENGINE}{BLACK}   Gebouwd: {LTBLUE}{NUM}{BLACK} Waarde: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE_AND_SPEED      :{LTBLUE}{ENGINE}{BLACK}   Gebouwd: {LTBLUE}{NUM}{BLACK} Waarde: {LTBLUE}{CURRENCY} {BLACK}Max. snelheid: {LTBLUE}{VELOCITY}
 STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE                           :{LTBLUE}{ENGINE}{BLACK}   Waarde: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_AND_SPEED                 :{LTBLUE}{ENGINE}{BLACK}   Waarde: {LTBLUE}{CURRENCY} {BLACK}Max. snelheid: {LTBLUE}{VELOCITY}
 
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT                   :{BLACK}Totale lading (capaciteit) van deze trein:
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY                        :{LTBLUE}- {CARGO} ({SHORTCARGO})
@@ -3139,6 +3567,9 @@
 
 # Vehicle refit
 STR_REFIT_CAPTION                                               :{WHITE}{VEHICLE} (Ombouwen)
+STR_REFIT_VEHICLE_SELECT_ALL                                    :{BLACK}{TINYFONT}ALLE
+STR_REFIT_VEHICLE_SELECT_ALL_TOOLTIP                            :{BLACK}Selecteer het volledige voertuig
+STR_REFIT_VEHICLE_SELECTION_TITLE                               :{GOLD}Selecteer delen an de voertuigen om om te bouwen:
 STR_REFIT_TITLE                                                 :{GOLD}Selecteer goederentype om te vervoeren:
 STR_REFIT_NEW_CAPACITY_COST_OF_REFIT                            :{BLACK}Nieuwe capaciteit: {GOLD}{CARGO}{}{BLACK}Ombouwkosten: {GOLD}{CURRENCY}
 STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT                   :{BLACK}Nieuwe capaciteit: {GOLD}{CARGO}, {GOLD}{CARGO}{}{BLACK}Ombouwkosten: {GOLD}{CURRENCY}
@@ -3327,6 +3758,7 @@
 STR_TIMETABLE_AND_TRAVEL_FOR                                    :en rijd naar {STRING}
 STR_TIMETABLE_DAYS                                              :{COMMA} dag{P "" en}
 STR_TIMETABLE_TICKS                                             :{COMMA} tik{P "" ken}
+STR_TIMETABLE_MINUTES                                           :{COMMA} minuut{P "" s}
 
 STR_TIMETABLE_TOTAL_TIME                                        :{BLACK}Dit tijdschema duurt {STRING} om te volbrengen
 STR_TIMETABLE_TOTAL_TIME_INCOMPLETE                             :{BLACK}Dit tijdschema duurt minstens {STRING} om te volbrengen (niet alles geselecteerd)
@@ -3341,7 +3773,7 @@
 STR_TIMETABLE_STARTING_DATE_TOOLTIP                             :{BLACK}Kies een datum als beginpunt voor deze dienstregeling
 
 STR_TIMETABLE_CHANGE_TIME                                       :{BLACK}Verander de tijd
-STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Verander de tijdsduur die de geselecteerde order mag duren
+STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Verander de tijdsduur die de geselecteerde order mag duren. Ctrl+Klick laat toe om de wachtijden voor alle stations ineens te veranderen
 
 STR_TIMETABLE_CLEAR_TIME                                        :{BLACK}Verwijder tijd
 STR_TIMETABLE_CLEAR_TIME_TOOLTIP                                :{BLACK}Verwijder de tijdsduur die de geselecteerde order mag duren
@@ -3352,6 +3784,9 @@
 STR_TIMETABLE_AUTOFILL                                          :{BLACK}Auto-aanvullen
 STR_TIMETABLE_AUTOFILL_TOOLTIP                                  :{BLACK}Vul de dienstregeling automatisch in aan de hand van de volgende reis (Ctrl+klik om proberen wachttijden te bewaren)
 
+STR_TIMETABLE_AUTOMATE                                          :{BLACK}Automatiseer
+STR_TIMETABLE_AUTOMATE_TOOLTIP                                  :{BLACK}Beheer de tijdstabel automatisch door de waardes van elke reis bij te stellen. Ontklik om het voortdurend bijstellen van de tijden te stoppen en de huidige tijdstabel te bewaren. Ctrl+Ontklik maakt de huidige tijdstabel leeg.
+
 STR_TIMETABLE_EXPECTED                                          :{BLACK}Verwacht
 STR_TIMETABLE_SCHEDULED                                         :{BLACK}Volgens dienstregeling
 STR_TIMETABLE_EXPECTED_TOOLTIP                                  :{BLACK}Wissel tussen verwacht en volgens dienstregeling
@@ -3367,6 +3802,8 @@
 STR_DATE_DAY_TOOLTIP                                            :{BLACK}Selecteer dag
 STR_DATE_MONTH_TOOLTIP                                          :{BLACK}Selecteer maand
 STR_DATE_YEAR_TOOLTIP                                           :{BLACK}Selecteer jaar
+STR_DATE_MINUTES_DAY_TOOLTIP                                    :{BLACK}Selecteer minuut
+STR_DATE_MINUTES_MONTH_TOOLTIP                                  :{BLACK}Selecteer uur
 
 
 # AI debug window
@@ -3444,6 +3881,10 @@
 STR_INCOME_FLOAT_INCOME                                         :{GREEN}Inkomsten: {CURRENCY}
 STR_FEEDER_TINY                                                 :{TINYFONT}{YELLOW}Overladen: {CURRENCY}
 STR_FEEDER                                                      :{YELLOW}Overladen: {CURRENCY}
+STR_FEEDER_INCOME_TINY                                          :{TINYFONT}{YELLOW}Overladen: {CURRENCY}{WHITE} / {GREEN}Inkomsten: {CURRENCY}
+STR_FEEDER_INCOME                                               :{YELLOW}Overladen: {CURRENCY}{WHITE} / {GREEN}Inkomsten: {CURRENCY}
+STR_FEEDER_COST_TINY                                            :{TINYFONT}{YELLOW}Transfer: {CURRENCY}{WHITE} / {RED}Kosten: {CURRENCY}
+STR_FEEDER_COST                                                 :{YELLOW}Overladen: {CURRENCY}{WHITE} / {RED}Kosten: {CURRENCY}
 STR_MESSAGE_ESTIMATED_COST                                      :{WHITE}Verwachte kosten: {CURRENCY}
 STR_MESSAGE_ESTIMATED_INCOME                                    :{WHITE}Verwachte inkomsten: {CURRENCY}
 
@@ -3463,6 +3904,11 @@
 STR_GAME_SAVELOAD_NOT_AVAILABLE                                 :<niet beschikbaar>
 STR_WARNING_LOADGAME_REMOVED_TRAMS                              :{WHITE}Spel was opgeslagen in een versie zonder tram-ondersteuning. Alle trams zijn verwijderd
 
+STR_PROFILE_LOAD_ERROR                                          :{WHITE}Profiel laden mislukt
+STR_PROFILE_SAVE_ERROR                                          :{WHITE}Profiel opslaan mislukt
+STR_PROFILE_FACE_ERROR                                          :{WHITE}Ongeldig bedrijfsprofiel gezicht
+STR_PROFILE_COLOUR_ERROR                                        :{WHITE}Ongeldige bedrijfskleur
+
 # Map generation messages
 STR_ERROR_COULD_NOT_CREATE_TOWN                                 :{WHITE}Kaartmaken afgebroken...{}... geen geschikte dorpslokaties
 STR_ERROR_NO_TOWN_IN_SCENARIO                                   :{WHITE}... er is geen stad in dit scenario
@@ -3479,6 +3925,7 @@
 
 STR_WARNING_HEIGHTMAP_SCALE_CAPTION                             :{WHITE}Schaalwaarschuwing
 STR_WARNING_HEIGHTMAP_SCALE_MESSAGE                             :{YELLOW}Het aanpassen van de grootte van een bronkaart is niet aan te bevelen. Toch doorgaan?
+STR_MAPGEN_TOO_MANY_TILES_MESSAGE                               :{YELLOW}Te veel tegels in de kaart. Maximum aantal tegels is {NUM}, je hebt {NUM} tegels geselecteerd
 
 # Soundset messages
 STR_WARNING_FALLBACK_SOUNDSET                                   :{WHITE}Alleen backup geluid is gevonden. Als je geluid wilt, installeer dan een geluiddsset via het downloadsysteem
@@ -3524,6 +3971,7 @@
 STR_ERROR_ALREADY_AT_SEA_LEVEL                                  :{WHITE}... al op zeeniveau
 STR_ERROR_TOO_HIGH                                              :{WHITE}... te hoog
 STR_ERROR_ALREADY_LEVELLED                                      :{WHITE}... al vlak
+STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND                      :{WHITE}Nadien zou de brug erboven te hoog zijn.
 
 # Company related errors
 STR_ERROR_CAN_T_CHANGE_COMPANY_NAME                             :{WHITE}Kan bedrijfsnaam niet veranderen...
@@ -3662,6 +4110,7 @@
 # Rail construction errors
 STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION                          :{WHITE}Onmogelijke spoorcombinatie
 STR_ERROR_MUST_REMOVE_SIGNALS_FIRST                             :{WHITE}Sein moet eerst worden verwijderd
+STR_ERROR_MUST_REMOVE_EXIT_SIGNALS_FIRST                        :{WHITE}Uitgangsein moet eerst worden verwijderd
 STR_ERROR_NO_SUITABLE_RAILROAD_TRACK                            :{WHITE}Geen bruikbaar spoor
 STR_ERROR_MUST_REMOVE_RAILROAD_TRACK                            :{WHITE}Bestaand spoor moet eerst weggehaald worden
 STR_ERROR_CROSSING_ON_ONEWAY_ROAD                               :{WHITE}Weg is eenrichtingsverkeer of geblokkeerd
@@ -3676,6 +4125,8 @@
 
 STR_ERROR_CAN_T_CONVERT_RAIL                                    :{WHITE}Kan railtype hier niet veranderen...
 
+STR_ERROR_SIGNAL_CHANGES                                        :{WHITE}Aantal programmeerbare sein evaluaties limiet overschreden
+
 # Road construction errors
 STR_ERROR_MUST_REMOVE_ROAD_FIRST                                :{WHITE}Moet weg eerst weghalen
 STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION                      :{WHITE}... eenrichtingswegen kunnen geen kruisingen hebben
@@ -3683,6 +4134,13 @@
 STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE                              :{WHITE}Kan hier geen tramrails bouwen...
 STR_ERROR_CAN_T_REMOVE_ROAD_FROM                                :{WHITE}Kan hier geen weg weghalen...
 STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM                             :{WHITE}Kan de tramrails hier niet verwijderen...
+STR_ERROR_CAN_T_REMOVE_TRAFFIC_LIGHTS_FROM                      :{WHITE}Kan verkeerslichten hier niet verwijderen ...
+STR_ERROR_MUST_REMOVE_TRAFFIC_LIGHTS_FIRST                      :{WHITE}... eerst moeten de verkeerslichten worden verwijderd
+STR_ERROR_TRAFFIC_LIGHT_CONSIST_TOO_BIG                         :{WHITE}... te veel samengestelde vekeerslichten
+STR_ERROR_CAN_T_PLACE_TRAFFIC_LIGHTS                            :{WHITE}Kan verkeerslichten hier niet plaatsen ...
+STR_ERROR_CAN_ONLY_BE_PLACED_ON_ROAD_JUNCTIONS                  :{WHITE}... kan alleen op kruispunten worden gebouwd
+STR_ERROR_BUILDING_TRAFFIC_LIGHTS_DISABLED                      :{WHITE}... bouwen van vekeerslichten is uitgeschakeld, schakel het in in Geavanceerde instellingen -> Constructie -> Verkeerslichten
+STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS              :{WHITE}... bouwen van verkeerslichen op stedelijke wegen is uitgeschakeld, schakel het in in Geavanceerde instellingen -> Constructie -> Verkeerslichten
 STR_ERROR_THERE_IS_NO_ROAD                                      :{WHITE}...er is geen weg
 STR_ERROR_THERE_IS_NO_TRAMWAY                                   :{WHITE}...er is geen tramlijn
 
@@ -3702,6 +4160,7 @@
 STR_ERROR_TREE_ALREADY_HERE                                     :{WHITE}... er staat hier al een boom
 STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE                      :{WHITE}... verkeerde ondergrond voor dit type bomen
 STR_ERROR_CAN_T_PLANT_TREE_HERE                                 :{WHITE}Kan hier geen boom planten...
+STR_ERROR_TREE_ABOVE_TREE_LINE                                  :{WHITE}... land is boven boomgrens
 
 # Bridge related errors
 STR_ERROR_CAN_T_BUILD_BRIDGE_HERE                               :{WHITE}Kan hier geen brug bouwen...
@@ -3709,6 +4168,7 @@
 STR_ERROR_CAN_T_START_AND_END_ON                                :{WHITE}Kan niet beginnen en eindigen op dezelfde plaats
 STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT                           :{WHITE}Begin van bruggen niet op hetzelfde niveau
 STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN                            :{WHITE}Brug is te laag voor dit terrein
+STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN                           :{WHITE}Brug is te hoog voor dit terrein.
 STR_ERROR_START_AND_END_MUST_BE_IN                              :{WHITE}Begin en einde moeten op een lijn staan
 STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH                              :{WHITE}... uiteinden van brug moeten beiden op land zijn
 STR_ERROR_BRIDGE_TOO_LONG                                       :{WHITE}... brug te lang
@@ -4213,6 +4673,11 @@
 STR_FORMAT_DATE_LONG                                            :{STRING} {STRING} {NUM}
 STR_FORMAT_DATE_ISO                                             :{2:NUM}-{1:STRING}-{0:STRING}
 
+STR_FORMAT_DATE_MINUTES                                         :{0:STRING}:{1:STRING}
+STR_FORMAT_DATE_MINUTES_WITH_Y                                  :{0:STRING}:{1:STRING} / {2:NUM}
+STR_FORMAT_DATE_MINUTES_WITH_YM                                 :{0:STRING}:{1:STRING} / {2:DATE_SHORT}
+STR_FORMAT_DATE_MINUTES_WITH_YMD                                :{0:STRING}:{1:STRING} / {2:DATE_LONG}
+
 STR_FORMAT_BUOY_NAME                                            :{TOWN} Boei
 STR_FORMAT_BUOY_NAME_SERIAL                                     :{TOWN} Boei #{COMMA}
 STR_FORMAT_COMPANY_NUM                                          :(Bedrijf {COMMA})
@@ -4237,10 +4702,18 @@
 STR_SAVEGAME_NAME_SPECTATOR                                     :Toeschouwer, {1:STRING}
 
 # Viewport strings
+STR_VIEWPORT_TOWN_POP_VERY_POOR_RATING                          :{WHITE}{TOWN} {RED}({COMMA})
+STR_VIEWPORT_TOWN_POP_MEDIOCRE_RATING                           :{WHITE}{TOWN} {ORANGE}({COMMA})
+STR_VIEWPORT_TOWN_POP_GOOD_RATING                               :{WHITE}{TOWN} {YELLOW}({COMMA})
 STR_VIEWPORT_TOWN_POP                                           :{WHITE}{TOWN} ({COMMA})
+STR_VIEWPORT_TOWN_POP_EXCELLENT_RATING                          :{WHITE}{TOWN} {GREEN}({COMMA})
 STR_VIEWPORT_TOWN                                               :{WHITE}{TOWN}
 STR_VIEWPORT_TOWN_TINY_BLACK                                    :{TINYFONT}{BLACK}{TOWN}
+STR_VIEWPORT_TOWN_TINY_VERY_POOR_RATING                         :{TINYFONT}{RED}{TOWN}
+STR_VIEWPORT_TOWN_TINY_MEDIOCRE_RATING                          :{TINYFONT}{ORANGE}{TOWN}
+STR_VIEWPORT_TOWN_TINY_GOOD_RATING                              :{TINYFONT}{YELLOW}{TOWN}
 STR_VIEWPORT_TOWN_TINY_WHITE                                    :{TINYFONT}{WHITE}{TOWN}
+STR_VIEWPORT_TOWN_TINY_EXCELLENT_RATING                         :{TINYFONT}{GREEN}{TOWN}
 
 STR_VIEWPORT_SIGN_SMALL_BLACK                                   :{TINYFONT}{BLACK}{SIGN}
 STR_VIEWPORT_SIGN_SMALL_WHITE                                   :{TINYFONT}{WHITE}{SIGN}
@@ -4275,6 +4748,10 @@
 STR_JUST_DATE_SHORT                                             :{DATE_SHORT}
 STR_JUST_DATE_LONG                                              :{DATE_LONG}
 STR_JUST_DATE_ISO                                               :{DATE_ISO}
+STR_JUST_DATE_WALLCLOCK_TINY                                    :{DATE_WALLCLOCK_TINY}
+STR_JUST_DATE_WALLCLOCK_SHORT                                   :{DATE_WALLCLOCK_SHORT}
+STR_JUST_DATE_WALLCLOCK_LONG                                    :{DATE_WALLCLOCK_LONG}
+STR_JUST_DATE_WALLCLOCK_ISO                                     :{DATE_WALLCLOCK_ISO}
 STR_JUST_STRING                                                 :{STRING}
 STR_JUST_STRING_SPACE_STRING                                    :{STRING} {STRING}
 STR_JUST_RAW_STRING                                             :{STRING}
@@ -4290,12 +4767,16 @@
 STR_BLACK_DATE_LONG                                             :{BLACK}{DATE_LONG}
 STR_BLACK_CROSS                                                 :{BLACK}{CROSS}
 STR_SILVER_CROSS                                                :{SILVER}{CROSS}
+STR_WHITE_DATE_SHORT                                            :{WHITE}{DATE_SHORT}
 STR_WHITE_DATE_LONG                                             :{WHITE}{DATE_LONG}
+STR_WHITE_DATE_WALLCLOCK_LONG                                   :{WHITE}{DATE_WALLCLOCK_LONG}
+STR_WHITE_DATE_WALLCLOCK_SHORT                                  :{WHITE}{DATE_WALLCLOCK_SHORT}
 STR_SHORT_DATE                                                  :{WHITE}{DATE_TINY}
 STR_DATE_LONG_SMALL                                             :{TINYFONT}{BLACK}{DATE_LONG}
 STR_TINY_GROUP                                                  :{TINYFONT}{GROUP}
 STR_BLACK_INT                                                   :{BLACK}{NUM}
 STR_ORANGE_INT                                                  :{ORANGE}{NUM}
+STR_RED_INT                                                     :{RED}{NUM}
 STR_WHITE_SIGN                                                  :{WHITE}{SIGN}
 STR_TINY_BLACK_STATION                                          :{TINYFONT}{BLACK}{STATION}
 STR_BLACK_STRING                                                :{BLACK}{STRING}
@@ -4308,6 +4789,8 @@
 STR_TINY_BLACK_VEHICLE                                          :{TINYFONT}{BLACK}{VEHICLE}
 STR_TINY_RIGHT_ARROW                                            :{TINYFONT}{RIGHTARROW}
 
+STR_WHITE                                                       :{WHITE}
+STR_BLACK                                                       :{BLACK}
 STR_BLACK_1                                                     :{BLACK}1
 STR_BLACK_2                                                     :{BLACK}2
 STR_BLACK_3                                                     :{BLACK}3
@@ -4323,3 +4806,12 @@
 STR_SHIP                                                        :{BLACK}{SHIP}
 
 STR_TOOLBAR_RAILTYPE_VELOCITY                                   :{STRING} ({VELOCITY})
+
+STR_NUM                                                         :{NUM}
+STR_NUM_RELATION_2                                              :{NUM}/{NUM}
+STR_NUM_RELATION_3                                              :{NUM}/{NUM}/{NUM}
+STR_NUM_RELATION_4                                              :{NUM}/{NUM}/{NUM}/{NUM}
+
+STR_WATCH_WINDOW_TITLE                                          :{WHITE}Gluren bij de buren {STRING}.
+STR_WATCH_CLICK_TO_WATCH_COMPANY                                :{BLACK}Klik hier om bedrijf te zien bouwen
+STR_WATCH_CLICK_NEW_WINDOW                                      :{BLACK}Klik hier om bedrijfsobservatie venster te openen
diff --git a/src/lang/english.txt b/src/lang/english.txt
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -23,6 +23,7 @@
 STR_EMPTY                                                       :
 STR_UNDEFINED                                                   :(undefined string)
 STR_JUST_NOTHING                                                :Nothing
+STR_TINY_NOTHING                                                :{TINYFONT}Nothing
 
 # Cargo related strings
 # Plural cargo name
@@ -220,6 +221,7 @@
 STR_LIST_FILTER_OSKTITLE                                        :{BLACK}Enter filter string
 STR_LIST_FILTER_TOOLTIP                                         :{BLACK}Enter a keyword to filter the list for
 
+STR_TOOLTIP_GROUP_ORDER                                         :{BLACK}Select grouping order
 STR_TOOLTIP_SORT_ORDER                                          :{BLACK}Select sorting order (descending/ascending)
 STR_TOOLTIP_SORT_CRITERIA                                       :{BLACK}Select sorting criteria
 STR_TOOLTIP_FILTER_CRITERIA                                     :{BLACK}Select filtering criteria
@@ -252,7 +254,7 @@
 STR_MEASURE_AREA                                                :{BLACK}Area: {NUM} x {NUM}
 STR_MEASURE_LENGTH_HEIGHTDIFF                                   :{BLACK}Length: {NUM}{}Height difference: {HEIGHT}
 STR_MEASURE_AREA_HEIGHTDIFF                                     :{BLACK}Area: {NUM} x {NUM}{}Height difference: {HEIGHT}
-
+STR_MEASURE_DIST_HEIGHTDIFF                                     :{BLACK}Manhattan Distance: {NUM}{}Bird Fly Distance: {NUM}{}Distance from the nearest edge: {NUM}{}Height from sea level: {HEIGHT}{}Height difference: {HEIGHT}
 
 # These are used in buttons
 STR_SORT_BY_CAPTION_POPULATION                                  :{BLACK}Population
@@ -373,6 +375,7 @@
 STR_MAP_MENU_MAP_OF_WORLD                                       :Map of world
 STR_MAP_MENU_EXTRA_VIEW_PORT                                    :Extra viewport
 STR_MAP_MENU_SIGN_LIST                                          :Sign list
+STR_MAP_MENU_WATCH_COMPANY                                      :Watch Company
 ############ range for town menu starts, yet the town directory is shown in the map menu in the scenario editor
 STR_TOWN_MENU_TOWN_DIRECTORY                                    :Town directory
 ############ end of the 'Display map' dropdown
@@ -655,17 +658,20 @@
 STR_SMALLMAP_TYPE_CONTOURS                                      :Contours
 STR_SMALLMAP_TYPE_VEHICLES                                      :Vehicles
 STR_SMALLMAP_TYPE_INDUSTRIES                                    :Industries
+STR_SMALLMAP_TYPE_ROUTEMAP                                      :Link Statistics
 STR_SMALLMAP_TYPE_ROUTES                                        :Routes
 STR_SMALLMAP_TYPE_VEGETATION                                    :Vegetation
 STR_SMALLMAP_TYPE_OWNERS                                        :Owners
 STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP                  :{BLACK}Show land contours on map
 STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP                       :{BLACK}Show vehicles on map
 STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP                     :{BLACK}Show industries on map
+STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP                     :{BLACK}Show link statistics on map
 STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON                   :{BLACK}Show transport routes on map
 STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP                     :{BLACK}Show vegetation on map
 STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP                    :{BLACK}Show land owners on map
 STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION                         :{BLACK}Click on an industry type to toggle displaying it. Ctrl+Click disables all types except the selected one. Ctrl+Click on it again to enable all industry types
 STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION                          :{BLACK}Click on a company to toggle displaying its property. Ctrl+Click disables all companies except the selected one. Ctrl+Click on it again to enable all companies
+STR_SMALLMAP_TOOLTIP_LINK_STATS_SELECTION                       :{BLACK}Click on a cargo to toggle displaying its property. Ctrl+Click disables all linkstats except the selected one. Ctrl+Click on it again to enable all linkstats
 
 STR_SMALLMAP_LEGENDA_ROADS                                      :{TINYFONT}{BLACK}Roads
 STR_SMALLMAP_LEGENDA_RAILROADS                                  :{TINYFONT}{BLACK}Railways
@@ -695,11 +701,27 @@
 STR_SMALLMAP_LEGENDA_INDUSTRIES                                 :{TINYFONT}{BLACK}Industries
 STR_SMALLMAP_LEGENDA_DESERT                                     :{TINYFONT}{BLACK}Desert
 STR_SMALLMAP_LEGENDA_SNOW                                       :{TINYFONT}{BLACK}Snow
+STR_SMALLMAP_LEGENDA_CAPACITY                                   :{TINYFONT}{BLACK}Capacity
+STR_SMALLMAP_LEGENDA_USAGE                                      :{TINYFONT}{BLACK}Usage
+STR_SMALLMAP_LEGENDA_PLANNED                                    :{TINYFONT}{BLACK}Planned Flow
+STR_SMALLMAP_LEGENDA_SENT                                       :{TINYFONT}{BLACK}Sent Cargo
+STR_SMALLMAP_LEGENDA_SHOW_TEXT                                  :{TINYFONT}{BLACK}As Text
+STR_SMALLMAP_LEGENDA_SHOW_GRAPH                                 :{TINYFONT}{BLACK}As Graphs
+
+STR_SMALLMAP_SUPPLY_CAPTION                                     :{BLACK}Monthly supply at {STATION}
+STR_SMALLMAP_SUPPLY                                             :{TINYFONT}{CARGO}
+STR_SMALLMAP_LINK_CAPTION                                       :{BLACK}Monthly traffic from {STATION} to {STATION}
+STR_SMALLMAP_LINK                                               :{TINYFONT}{STRING} -
+STR_SMALLMAP_LINK_CAPACITY                                      :{TINYFONT}  cap: {NUM}
+STR_SMALLMAP_LINK_USAGE                                         :{TINYFONT}  usg: {NUM}
+STR_SMALLMAP_LINK_PLANNED                                       :{TINYFONT}  pln: {NUM}
+STR_SMALLMAP_LINK_SENT                                          :{TINYFONT}  snt: {NUM}
 
 STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF                   :{BLACK}Toggle town names on/off on map
 STR_SMALLMAP_CENTER                                             :{BLACK}Centre the smallmap on the current position
 STR_SMALLMAP_INDUSTRY                                           :{TINYFONT}{STRING} ({NUM})
 STR_SMALLMAP_COMPANY                                            :{TINYFONT}{COMPANY}
+STR_SMALLMAP_LINKSTATS                                          :{TINYFONT}{STRING}
 STR_SMALLMAP_TOWN                                               :{TINYFONT}{WHITE}{TOWN}
 STR_SMALLMAP_DISABLE_ALL                                        :{BLACK}Disable all
 STR_SMALLMAP_ENABLE_ALL                                         :{BLACK}Enable all
@@ -709,6 +731,8 @@
 STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT                                :{BLACK}Toggle display of heightmap
 STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES                      :{BLACK}Display no company property on the map
 STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES                       :{BLACK}Display all company property on the map
+STR_SMALLMAP_TOOLTIP_DISABLE_ALL_LINK_STATS                     :{BLACK}Display no linkstats on the map
+STR_SMALLMAP_TOOLTIP_ENABLE_ALL_LINK_STATS                      :{BLACK}Display all linkstats on the map
 
 # Status bar messages
 STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS                            :{BLACK}Show last message or news report
@@ -934,6 +958,8 @@
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP                      :{BLACK}Select interval between automatic game saves
 
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF                          :Off
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_DAY                  :Every day
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_WEEK                 :Every week
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH                :Every month
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS               :Every 3 months
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS               :Every 6 months
@@ -998,7 +1024,7 @@
 STR_DIFFICULTY_LEVEL_CAPTION                                    :{WHITE}Difficulty Level
 
 ############ range for difficulty levels starts
-STR_DIFFICULTY_LEVEL_EASY                                       :{BLACK}Easy
+STR_DIFFICULTY_LEVEL_EASY                                       :{BLACK}Kidscorner
 STR_DIFFICULTY_LEVEL_MEDIUM                                     :{BLACK}Medium
 STR_DIFFICULTY_LEVEL_HARD                                       :{BLACK}Hard
 STR_DIFFICULTY_LEVEL_CUSTOM                                     :{BLACK}Custom
@@ -1070,10 +1096,13 @@
 STR_SUBSIDY_X3                                                  :x3
 STR_SUBSIDY_X4                                                  :x4
 
+STR_TERRAIN_TYPE_FALLEN                                         :Fallen ... cant get up
 STR_TERRAIN_TYPE_VERY_FLAT                                      :Very Flat
 STR_TERRAIN_TYPE_FLAT                                           :Flat
+STR_TERRAIN_TYPE_BUMPY                                          :Bumpy
 STR_TERRAIN_TYPE_HILLY                                          :Hilly
 STR_TERRAIN_TYPE_MOUNTAINOUS                                    :Mountainous
+STR_TERRAIN_TYPE_ALPINIST                                       :Alpinist
 
 STR_ECONOMY_STEADY                                              :Steady
 STR_ECONOMY_FLUCTUATING                                         :Fluctuating
@@ -1081,6 +1110,9 @@
 STR_REVERSE_AT_END_OF_LINE_AND_AT_STATIONS                      :At end of line, and at stations
 STR_REVERSE_AT_END_OF_LINE_ONLY                                 :At end of line only
 
+STR_DISASTERS_OFF                                               :Off
+STR_DISASTERS_ON                                                :On
+
 STR_CITY_APPROVAL_PERMISSIVE                                    :Permissive
 STR_CITY_APPROVAL_TOLERANT                                      :Tolerant
 STR_CITY_APPROVAL_HOSTILE                                       :Hostile
@@ -1125,11 +1157,13 @@
 STR_CONFIG_SETTING_SELECTGOODS                                  :{LTBLUE}Deliver cargo to a station only when there is a demand: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH                            :{LTBLUE}Maximum bridge length: {ORANGE}{STRING1} tile{P 0:1 "" s}
 STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH                            :{LTBLUE}Maximum tunnel length: {ORANGE}{STRING1} tile{P 0:1 "" s}
+STR_CONFIG_SETTING_GOTODEPOT                                    :{LTBLUE}Allow goto depot orders: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD             :{LTBLUE}Manual primary industry construction method: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE        :none
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL      :as other industries
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :prospecting
 STR_CONFIG_SETTING_INDUSTRY_PLATFORM                            :{LTBLUE}Flat area around industries: {ORANGE}{STRING1} tile{P 0:1 "" s}
+STR_CONFIG_SETTING_EXTRA_INDUSTRY_PLACEMENT_LOGIC               :{LTBLUE}Allow more than 1 heightlevel to be leveled for placement below level: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_MULTIPINDTOWN                                :{LTBLUE}Allow multiple similar industries per town: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_SIGNALSIDE                                   :{LTBLUE}Show signals on the drive side: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_SHOWFINANCES                                 :{LTBLUE}Show finances window at the end of the year: {ORANGE}{STRING1}
@@ -1155,6 +1189,8 @@
 STR_CONFIG_SETTING_ADJACENT_STATIONS                            :{LTBLUE}Allow building adjacent stations: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES                              :{LTBLUE}Enable multiple NewGRF engine sets: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES            :{WHITE}Changing this setting is not possible when there are vehicles
+STR_CONFIG_SETTING_MAX_SIGNAL_EVALUATIONS                       :{LTBLUE}Maximum number of programmable signal changes permitted at once: {ORANGE}{STRING}
+STR_CONFIG_SETTING_BACK_ONE_WAY_PBS_SAFE_WAITING                :{LTBLUE}Back of one-way pbs signal is safe waiting point: {ORANGE}{STRING1}
 
 STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS                        :{LTBLUE}Airports never expire: {ORANGE}{STRING1}
 
@@ -1171,18 +1207,24 @@
 STR_CONFIG_SETTING_ERRMSG_DURATION                              :{LTBLUE}Duration of error message: {ORANGE}{STRING1} second{P 0:1 "" s}
 STR_CONFIG_SETTING_HOVER_DELAY                                  :{LTBLUE}Show tooltips: {ORANGE}Hover for {STRING1} second{P 0:1 "" s}
 STR_CONFIG_SETTING_HOVER_DELAY_DISABLED                         :{LTBLUE}Show tooltips: {ORANGE}Right click
-STR_CONFIG_SETTING_POPULATION_IN_LABEL                          :{LTBLUE}Show town population in the town name label: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_POPULATION_IN_LABEL                          :{LTBLUE}Show extra info in the town name label: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_POPULATION_IN_LABEL_COLOURED                 :{LTBLUE}Apply rating colours to extra info in the town label: {ORANGE}{STRING1}
 
 STR_CONFIG_SETTING_LAND_GENERATOR                               :{LTBLUE}Land generator: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL                      :Original
 STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS                 :TerraGenesis
 STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Max distance from edge for Oil Refineries: {ORANGE}{STRING1} tile{P 0:1 "" s}
 STR_CONFIG_SETTING_SNOWLINE_HEIGHT                              :{LTBLUE}Snow line height: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DESERT_AMOUNT                                :{LTBLUE}Amount of desert: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TREELINE_HEIGHT                              :{LTBLUE}Tree line height: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN                         :{LTBLUE}Roughness of terrain (TerraGenesis only) : {ORANGE}{STRING1}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH             :Very Smooth
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH                  :Smooth
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH                   :Rough
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH              :Very Rough
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_CEREALLY_ROUGH          :Cereally rough
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_COMMUTORZ               :CommutorZ
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_GO_WITH_THE_FLOW        :Go with the flow
 STR_CONFIG_SETTING_TREE_PLACER                                  :{LTBLUE}Tree placer algorithm: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_TREE_PLACER_NONE                             :None
 STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL                         :Original
@@ -1202,6 +1244,7 @@
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN                   :Green
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN              :Dark green
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET                  :Violet
+STR_CONFIG_SETTING_SMALLMAP_FLOOD_WARNING                       :{LTBLUE}Enable flood colour warning in smallmap heightcolours: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_REVERSE_SCROLLING                            :{LTBLUE}Reverse scroll direction: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_SMOOTH_SCROLLING                             :{LTBLUE}Smooth viewport scrolling: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_MEASURE_TOOLTIP                              :{LTBLUE}Show a measurement tooltip when using various build-tools: {ORANGE}{STRING1}
@@ -1239,8 +1282,24 @@
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING      :all but landscape modifying actions
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS              :all actions
 STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Use the advanced vehicle list: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OFF                   :Off
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OWN                   :Own company
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_ALL                   :All companies
 STR_CONFIG_SETTING_LOADING_INDICATORS                           :{LTBLUE}Use loading indicators: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_LOADING_INDICATORS_OFF                       :Off
+STR_CONFIG_SETTING_LOADING_INDICATORS_OWN                       :Own company
+STR_CONFIG_SETTING_LOADING_INDICATORS_ALL                       :All companies
+STR_CONFIG_SETTING_TIMETABLE_ALLOW                              :{LTBLUE}Enable timetabling for vehicles: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TIMETABLE_AUTOMATED                          :{LTBLUE}Automatically managed timetables: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TIME_IN_MINUTES                              :{LTBLUE}Show time in minutes rather than days: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TICKS_PER_MINUTE                             :{LTBLUE}Ticks per minute: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DATE_WITH_TIME                               :{LTBLUE}Show date with time in status bar: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DATE_WITH_TIME_NONE                          :None
+STR_CONFIG_SETTING_DATE_WITH_TIME_Y                             :Year
+STR_CONFIG_SETTING_DATE_WITH_TIME_YM                            :Month and year
+STR_CONFIG_SETTING_DATE_WITH_TIME_YMD                           :Full date
 STR_CONFIG_SETTING_TIMETABLE_IN_TICKS                           :{LTBLUE}Show timetable in ticks rather than days: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TIMETABLE_SEPARATION                         :{LTBLUE}Use timetable to ensure vehicles separation: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE             :{LTBLUE}Show arrival and departure in timetables: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_QUICKGOTO                                    :{LTBLUE}Quick creation of vehicle orders: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE                            :{LTBLUE}Default rail type (after new game/game load): {ORANGE}{STRING1}
@@ -1265,6 +1324,18 @@
 STR_CONFIG_SETTING_AI_IN_MULTIPLAYER                            :{LTBLUE}Allow AIs in multiplayer: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_AI_MAX_OPCODES                               :{LTBLUE}#opcodes before AI is suspended: {ORANGE}{STRING1}
 
+STR_CONFIG_SETTING_SHARING_RAIL                                 :{LTBLUE}Enable sharing of railways: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_ROAD                                 :{LTBLUE}Enable sharing of road stops and depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_WATER                                :{LTBLUE}Enable sharing of docks and ship depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_AIR                                  :{LTBLUE}Enable sharing of airports: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_FEE_RAIL                             :{LTBLUE}Daily track toll for trains: {ORANGE}{STRING1} per 1000 tonnes
+STR_CONFIG_SETTING_SHARING_FEE_ROAD                             :{LTBLUE}Stopping fee for road vehicles: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_FEE_WATER                            :{LTBLUE}Docking fee for ships: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_FEE_AIR                              :{LTBLUE}Terminal fee for aircraft: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT                      :{LTBLUE}Allow companies in debt to pay sharing fees: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES                     :{WHITE}Can't change this setting, vehicles are using shared infrastructure.
+STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS                     :{WHITE}Can't change this setting, vehicles have orders to destinations of others.
+
 STR_CONFIG_SETTING_SERVINT_ISPERCENT                            :{LTBLUE}Service intervals are in percents: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_SERVINT_TRAINS                               :{LTBLUE}Default service interval for trains: {ORANGE}{STRING1} day{P 0:1 "" s}/%
 STR_CONFIG_SETTING_SERVINT_TRAINS_DISABLED                      :{LTBLUE}Default service interval for trains: {ORANGE}disabled
@@ -1275,6 +1346,7 @@
 STR_CONFIG_SETTING_SERVINT_SHIPS                                :{LTBLUE}Default service interval for ships: {ORANGE}{STRING1} day{P 0:1 "" s}/%
 STR_CONFIG_SETTING_SERVINT_SHIPS_DISABLED                       :{LTBLUE}Default service interval for ships: {ORANGE}disabled
 STR_CONFIG_SETTING_NOSERVICE                                    :{LTBLUE}Disable servicing when breakdowns set to none: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_IMPROVED_BREAKDOWNS                          :{LTBLUE}Enable improved breakdowns: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_WAGONSPEEDLIMITS                             :{LTBLUE}Enable wagon speed limits: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_DISABLE_ELRAILS                              :{LTBLUE}Disable electric rails: {ORANGE}{STRING1}
 
@@ -1309,13 +1381,33 @@
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED                        :allowed
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT          :allowed, custom town layout
 
+STR_CONFIG_SETTING_DAYLENGTH_FACTOR                             :{LTBLUE}Day length factor: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_CARGO_FACTOR                            :{LTBLUE}Town cargo generation factor (less < 0 < more): {ORANGE}{STRING1}
+
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT                         :{LTBLUE}In game placement of trees: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NONE                    :none {RED}(breaks lumber mill)
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_RAINFOREST              :only in rain forests
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_ALL                     :everywhere
 
+STR_CONFIG_SETTING_TREE_PLACEMENT_DRAG_LIMIT                    :{LTBLUE}Drag limit when planting trees: {ORANGE}{STRING}
+
+STR_CONFIG_SETTING_INGAME_TREELINE_HEIGHT                       :{LTBLUE}Ingame tree line height: {ORANGE}{STRING1}
+
+STR_CONFIG_SETTING_TREE_GROWTH                                  :{LTBLUE}Trees growth speed: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TREE_GROWTH_NORMAL                           :Normal
+STR_CONFIG_SETTING_TREE_GROWTH_SLOW                             :Slow
+STR_CONFIG_SETTING_TREE_GROWTH_VERY_SLOW                        :Very slow
+STR_CONFIG_SETTING_TREE_GROWTH_EXTREMLY_SLOW                    :Extremly slow
+
+
 STR_CONFIG_SETTING_TOOLBAR_POS                                  :{LTBLUE}Position of main toolbar: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TOOLBAR_POS_LEFT                             :Left
+STR_CONFIG_SETTING_TOOLBAR_POS_CENTER                           :Centre
+STR_CONFIG_SETTING_TOOLBAR_POS_RIGHT                            :Right
 STR_CONFIG_SETTING_STATUSBAR_POS                                :{LTBLUE}Position of statusbar: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_STATUSBAR_POS_LEFT                           :Left
+STR_CONFIG_SETTING_STATUSBAR_POS_CENTER                         :Centre
+STR_CONFIG_SETTING_STATUSBAR_POS_RIGHT                          :Right
 STR_CONFIG_SETTING_SNAP_RADIUS                                  :{LTBLUE}Window snap radius: {ORANGE}{STRING1} pixel{P 0:1 "" s}
 STR_CONFIG_SETTING_SNAP_RADIUS_DISABLED                         :{LTBLUE}Window snap radius: {ORANGE}disabled
 STR_CONFIG_SETTING_SOFT_LIMIT                                   :{LTBLUE}Maximum number of non-sticky windows: {ORANGE}{STRING1}
@@ -1329,19 +1421,76 @@
 STR_CONFIG_SETTING_LARGER_TOWNS                                 :{LTBLUE}Proportion of towns that will become cities: {ORANGE}1 in {STRING1}
 STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED                        :{LTBLUE}Proportion of towns that will become cities: {ORANGE}None
 STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER                         :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO                            :{LTBLUE}Town growth based on passenger/mail/goods transportation: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_OFF                        :off
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_VERY_EASY                  :Very Easy
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_EASY                       :Easy
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_AVERAGE                    :Average
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_HARD                       :Hard
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_VERY_HARD                  :Very Hard
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_INSANE                     :Drive me nuts please
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO                     :{LTBLUE}City growth based on passenger/mail/goods transportation: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_OFF                 :off
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_VERY_EASY           :Very Easy
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_EASY                :Easy
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_AVERAGE             :Average
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_HARD                :Hard
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_VERY_HARD           :Very Hard
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_INSANE              :Drive me nuts please
+STR_CONFIG_SETTING_TOWN_GROWTH_MAX_POP_WO_GOODS                 :{LTBLUE}Max town population before needing goods for growth: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_MAX_POP_WO_GOODS          :{LTBLUE}Max city population before needing goods for growth: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_MODIFIED_ROAD_REBUILD                        :{LTBLUE}Remove absurd road-elements during the road construction: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TRAFFIC_LIGHTS                               :{LTBLUE}Enable traffic lights: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TOWNS_BUILD_TRAFFIC_LIGHTS                   :{LTBLUE}Towns build traffic lights during road construction: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_ALLOW_BUILDING_TLS_ON_TOWN_ROADS             :{LTBLUE}Allow building and removing traffic lights on town roads: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TRAFFIC_LIGHTS_GREEN_PHASE                   :{LTBLUE}Length of traffic lights' green phase: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_SIZE               :{LTBLUE}Maximum TL consist size: {ORANGE}{STRING1}. {RED}Warning: High setting slows game
+STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_DISTANCE           :{LTBLUE}Maximum distance between trafficlights for synchronising: {ORANGE}{STRING1} tiles. {RED}Warning: High setting slows game
+
+STR_CONFIG_SETTING_LINKGRAPH_INTERVAL                           :{LTBLUE}Link graph recalculation interval: {ORANGE}{STRING1} * 74 ticks
+STR_CONFIG_SETTING_DISTRIBUTION_PAX                             :{LTBLUE}Distribution for passengers: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_SYMMETRIC                   :symmetric
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_ASYMMETRIC                  :asymmetric
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_MANUAL                      :manual
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL                            :{LTBLUE}Distribution for mail: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_SYMMETRIC                  :symmetric
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_ASYMMETRIC                 :asymmetric
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_MANUAL                     :manual
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS                         :{LTBLUE}Distribution for the EXPRESS cargo class: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_SYMMETRIC               :symmetric
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_ASYMMETRIC              :asymmetric
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_MANUAL                  :manual
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED                        :{LTBLUE}Distribution for the ARMOURED cargo class: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_SYMMETRIC              :symmetric
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_ASYMMETRIC             :asymmetric
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_MANUAL                 :manual
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT                         :{LTBLUE}Distribution for other cargo classes: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_SYMMETRIC               :symmetric
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_ASYMMETRIC              :asymmetric
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_MANUAL                  :manual
+STR_CONFIG_SETTING_LINKGRAPH_ACCURACY                           :{LTBLUE}Accuracy when calculating things on the link graph: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_DEMAND_DISTANCE                              :{LTBLUE}Effect of distance on demands: {ORANGE}{STRING1}%
+STR_CONFIG_SETTING_DEMAND_SIZE                                  :{LTBLUE}Effect of remote station's popularity on symmetric demands: {ORANGE}{STRING1}%
+STR_CONFIG_SETTING_SHORT_PATH_SATURATION                        :{LTBLUE}Saturation of short paths before using capacious paths: {ORANGE}{STRING1}%
+STR_CONFIG_SETTING_NO_OVERLOAD_LINKS                            :{LTBLUE}Try not to overload links: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SMALLMAP_LINKGRAPH_COMPANIES                 :{LTBLUE}Show linkgraphs in smallmap for: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHOW_SMALLMAP_LINKGRAPH_OWN_ONLY             :only own company
+STR_CONFIG_SETTING_SHOW_SMALLMAP_LINKGRAPH_ALL_COMPANIES        :all companies
 
 STR_CONFIG_SETTING_GUI                                          :{ORANGE}Interface
 STR_CONFIG_SETTING_CONSTRUCTION                                 :{ORANGE}Construction
 STR_CONFIG_SETTING_VEHICLES                                     :{ORANGE}Vehicles
 STR_CONFIG_SETTING_STATIONS                                     :{ORANGE}Stations
 STR_CONFIG_SETTING_ECONOMY                                      :{ORANGE}Economy
+STR_CONFIG_SETTING_LINKGRAPH                                    :{ORANGE}Link graph
 STR_CONFIG_SETTING_AI                                           :{ORANGE}Competitors
 STR_CONFIG_SETTING_DISPLAY_OPTIONS                              :{ORANGE}Display options
 STR_CONFIG_SETTING_INTERACTION                                  :{ORANGE}Interaction
 STR_CONFIG_SETTING_CONSTRUCTION_SIGNALS                         :{ORANGE}Signals
+STR_CONFIG_SETTING_CONSTRUCTION_TRAFFIC_LIGHTS                  :{ORANGE}Traffic lights
 STR_CONFIG_SETTING_STATIONS_CARGOHANDLING                       :{ORANGE}Cargo handling
 STR_CONFIG_SETTING_AI_NPC                                       :{ORANGE}Computer players
+STR_CONFIG_SETTING_SHARING                                      :{ORANGE}Infrastructure sharing
 STR_CONFIG_SETTING_VEHICLES_AUTORENEW                           :{ORANGE}Autorenew
 STR_CONFIG_SETTING_VEHICLES_SERVICING                           :{ORANGE}Servicing
 STR_CONFIG_SETTING_VEHICLES_ROUTING                             :{ORANGE}Routing
@@ -1354,10 +1503,20 @@
 STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Recommended)
 
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Pathfinder for trains: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_NPF                    :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_YAPF                   :YAPF {BLUE}(Recommended)
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Pathfinder for road vehicles: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_NPF             :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_YAPF            :YAPF {BLUE}(Recommended)
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Pathfinder for ships: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_OPF                     :Original
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_NPF                     :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_YAPF                    :YAPF {BLUE}(recommended)
 STR_CONFIG_SETTING_REVERSE_AT_SIGNALS                           :{LTBLUE}Automatic reversing at signals: {ORANGE}{STRING1}
 
+STR_CONFIG_SETTING_MORE_HEIGHTLEVELS                            :{LTBLUE}Allow more than 16 heightlevels: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_ERROR_NO_CHANGE_TO_OLD_POSSIBLE              :{WHITE}You try to change from allowing more than 16 heightlevels to less than. Unfortunately, there is a mountain of height more than 16 on the map. So sorry, but this is not possible.
+
 STR_CONFIG_SETTING_QUERY_CAPTION                                :{WHITE}Change setting value
 
 # Intro window
@@ -1428,6 +1587,7 @@
 STR_CHEATS_TOOLTIP                                              :{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 {CURRENCY}
+STR_CHEAT_DAYLENGHT_INCOME                                      :{LTBLUE}Do not devide vehicle income by daylength factor: {ORANGE}{STRING1}
 STR_CHEAT_CHANGE_COMPANY                                        :{LTBLUE}Playing as company: {ORANGE}{COMMA}
 STR_CHEAT_EXTRA_DYNAMITE                                        :{LTBLUE}Magic bulldozer (remove industries, unmovable objects): {ORANGE}{STRING1}
 STR_CHEAT_CROSSINGTUNNELS                                       :{LTBLUE}Tunnels may cross each other: {ORANGE}{STRING1}
@@ -1886,6 +2046,7 @@
 STR_TRANSPARENT_STRUCTURES_TOOLTIP                              :{BLACK}Toggle transparency for structures like lighthouses and antennas. Ctrl+Click to lock
 STR_TRANSPARENT_CATENARY_TOOLTIP                                :{BLACK}Toggle transparency for catenary. Ctrl+Click to lock
 STR_TRANSPARENT_LOADING_TOOLTIP                                 :{BLACK}Toggle transparency for loading indicators. Ctrl+Click to lock
+STR_TRANSPARENT_TUNNELS_TOOLTIP                                 :{BLACK}Toggle transparency for vehicles in tunnels. Ctrl+Click to lock.
 STR_TRANSPARENT_INVISIBLE_TOOLTIP                               :{BLACK}Set objects invisible instead of transparent
 
 # Base for station construction window(s)
@@ -1957,12 +2118,16 @@
 STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP                        :{BLACK}Entry-Signal (semaphore){}Green as long as there is one or more green exit-signal from the following section of track. Otherwise it shows red
 STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP                         :{BLACK}Exit-Signal (semaphore){}Behaves in the same way as a block signal but is necessary to trigger the correct colour on entry & combo pre-signals
 STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP                        :{BLACK}Combo-Signal (semaphore){}The combo signal simply acts as both an entry and exit signal. This allows you to build large "trees" of pre-signals
+STR_BUILD_SIGNAL_SEMAPHORE_PROG_TOOLTIP                         :{BLACK}Programmable-Signal (semaphore){}The programmable signal is a combo-signal which can be programmed to behave in complex ways
+STR_BUILD_SIGNAL_SEMAPHORE_SPEED_TOOLTIP                        :{BLACK}Speed-Signal (semaphore){}The speed-signal sets the maximum speed at which a train may travel until it encounters another speed-signal
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP                          :{BLACK}Path Signal (semaphore){}A path signal allows more than one train to enter a signal block at the same time, if the train can reserve a path to a safe stopping point. Standard path signals can be passed from the back side
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP                     :{BLACK}One-way Path Signal (semaphore){}A path signal allows more than one train to enter a signal block at the same time, if the train can reserve a path to a safe stopping point. One-way path signals can't be passed from the back side
 STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP                          :{BLACK}Block Signal (electric){}This is the most basic type of signal, allowing only one train to be in the same block at the same time
 STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP                         :{BLACK}Entry-Signal (electric){}Green as long as there is one or more green exit-signal from the following section of track. Otherwise it shows red
 STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP                          :{BLACK}Exit-Signal (electric){}Behaves in the same way as a block signal but is necessary to trigger the correct colour on entry & combo pre-signals
 STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP                         :{BLACK}Combo-Signal (electric){}The combo signal simply acts as both an entry and exit signal. This allows you to build large "trees" of pre-signals
+STR_BUILD_SIGNAL_ELECTRIC_PROG_TOOLTIP                          :{BLACK}Programmable-Signal (electric){}The programmable signal is a combo-signal which can be programmed to behave in complex ways
+STR_BUILD_SIGNAL_ELECTRIC_SPEED_TOOLTIP                         :{BLACK}Speed-Signal (electric){}The speed-signal sets the maximum speed at which a train may travel until it encounters another speed-signal
 STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP                           :{BLACK}Path Signal (electric){}A path signal allows more than one train to enter a signal block at the same time, if the train can reserve a path to a safe stopping point. Standard path signals can be passed from the back side
 STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP                      :{BLACK}One-way Path Signal (electric){}A path signal allows more than one train to enter a signal block at the same time, if the train can reserve a path to a safe stopping point. One-way path signals can't be passed from the back side
 STR_BUILD_SIGNAL_CONVERT_TOOLTIP                                :{BLACK}Signal Convert{}When selected, clicking an existing signal will convert it to the selected signal type and variant, Ctrl+Click will toggle the existing variant. Shift+Click shows estimated conversion cost
@@ -1970,6 +2135,73 @@
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP          :{BLACK}Decrease dragging signal density
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP          :{BLACK}Increase dragging signal density
 
+# Programmable Signals
+STR_PROGRAM_SIGNAL_TOOLTIP                                      :{BLACK}Program signal
+
+STR_ERR_PROGSIG_INVALID_INSTRUCTION                             :{WHITE}Cannot insert instruction after instruction with invalid ID
+STR_ERR_PROGSIG_INVALID_OPCODE                                  :{WHITE}Cannot insert an instruction of that opcode
+STR_ERR_PROGSIG_NOT_THERE                                       :{WHITE}There is no programmable signal there
+STR_ERR_PROGSIG_INVALID_SIGNAL_STATE                            :{WHITE}That signal state is invalid
+STR_ERR_PROGSIG_INVALID_CONDITION                               :{WHITE}That condition is invalid
+STR_ERR_PROGSIG_INVALID_CONDITION_FIELD                         :{WHITE}That field is not valid for the condition
+STR_ERR_PROGSIG_INVALID_COMPARATOR                              :{WHITE}That comparator is not valid
+STR_ERR_PROGSIG_INVALID_SIGNAL                                  :{WHITE}Invalid signal selected
+
+STR_PROGSIG_CAPTION                                             :{WHITE}Signal Program
+STR_PROGSIG_COND_VARIABLE_TOOLTIP                               :{BLACK}Condition to compare upon
+STR_PROGSIG_COND_COMPARATOR_TOOLTIP                             :{BLACK}Operator to use to compare variable
+STR_PROGSIG_COND_VALUE_TOOLTIP                                  :{BLACK}Value to compare variable against
+STR_PROGSIG_SIGNAL_STATE_TOOLTIP                                :{BLACK}Set signal to state
+STR_PROGSIG_COND_SET_SIGNAL                                     :{BLACK}Set signal
+STR_PROGSIG_COND_SET_SIGNAL_TOOLTIP                             :{BLACK}Set the signal to be looked at
+STR_PROGSIG_GOTO_SIGNAL                                         :{BLACK}Goto signal
+STR_PROGSIG_GOTO_SIGNAL_TOOLTIP                                 :{BLACK}Go to this signal
+STR_PROGSIG_INSERT_TOOLTIP                                      :{BLACK}Insert an instruction
+STR_PROGSIG_REMOVE_TOOLTIP                                      :{BLACK}Remove the selected instruction
+
+STR_PROGSIG_REMOVE                                              :{BLACK}Remove
+STR_PROGSIG_INSERT                                              :Insert
+STR_PROGSIG_INSERT_IF                                           :Condition
+STR_PROGSIG_INSERT_SET_SIGNAL                                   :Set signal state
+
+STR_PROGSIG_FIRST                                               :Start
+STR_PROGSIG_LAST                                                :End
+
+STR_PROGSIG_IF                                                  :If {RAW_STRING} Then
+STR_PROGSIG_ELSE                                                :Else
+STR_PROGSIG_ENDIF                                               :End If
+
+STR_PROGSIG_SET_SIGNAL                                          :Make signal {STRING}
+
+STR_PROGSIG_COND_ALWAYS                                         :always
+STR_PROGSIG_COND_NEVER                                          :never
+STR_PROGSIG_COND_COMPARE                                        :{STRING} {STRING} {NUM}
+STR_PROGSIG_COND_SIGNAL_STATE                                   :signal state
+STR_PROGSIG_CONDVAR_SIGNAL_STATE                                :{STRING1} is green
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_SPECIFIED                      :specified signal
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_UNSPECIFIED                    :{RED}unspecified signal{STRING}
+STR_PROGSIG_CONDVAR_NUM_RED                                     :red signals
+STR_PROGSIG_CONDVAR_NUM_GREEN                                   :green signals
+
+STR_PROGSIG_CONDITION_VALUE_CAPT                                :{WHITE}Condition value
+
+STR_ERROR_CAN_T_INSERT_INSTRUCTION                              :{WHITE}Can't insert instruction
+STR_ERROR_CAN_T_MODIFY_INSTRUCTION                              :{WHITE}Can't modify instruction
+STR_ERROR_CAN_T_REMOVE_INSTRUCTION                              :{WHITE}Can't remove instruction
+STR_ERROR_CAN_T_GOTO_UNDEFINED_SIGNAL                           :{WHITE}Can't go to undefined signal
+STR_ERROR_NOT_AN_EXIT_SIGNAL                                    :{WHITE}Not a exit signal
+STR_ERROR_CAN_T_DEPEND_UPON_BIDIRECTIONAL_SIGNALS               :{WHITE}Cannot conditionally depend upon bidirectional signals
+STR_ERROR_INVALID_SIGNAL                                        :{WHITE}Invalid signal
+
+STR_SPEEDSIG_CAPTION                                            :{WHITE}Speed Limit
+
+STR_SPEEDSIG_VALUE_NONE                                         :{WHITE}No speed limit
+STR_SPEEDSIG_VALUE                                              :{WHITE}{VELOCITY}
+STR_SPEEDSIG_CLEAR                                              :{BLACK}Clear
+STR_SPEEDSIG_CHANGE                                             :{BLACK}Change
+
+STR_ERROR_CAN_T_SET_SPEED                                       :{WHITE}Can't set speed limit
+
 # Bridge selection window
 STR_SELECT_RAIL_BRIDGE_CAPTION                                  :{WHITE}Select Rail Bridge
 STR_SELECT_ROAD_BRIDGE_CAPTION                                  :{WHITE}Select Road Bridge
@@ -2000,6 +2232,7 @@
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY                :{BLACK}Build lorry loading bay. Ctrl enables joining stations. Shift toggles building/showing cost estimate
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION               :{BLACK}Build freight tram station. Ctrl enables joining stations. Shift toggles building/showing cost estimate
 STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD                    :{BLACK}Activate/Deactivate one way roads
+STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAFFIC_LIGHT                    :{BLACK}Build traffic light
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE                      :{BLACK}Build road bridge. Shift toggles building/showing cost estimate
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE                   :{BLACK}Build tramway bridge. Shift toggles building/showing cost estimate
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL                      :{BLACK}Build road tunnel. Shift toggles building/showing cost estimate
@@ -2075,6 +2308,29 @@
 STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND                  :{BLACK}Raise a corner of land. Dragging raises the first selected corner and levels the selected area to the new corner height. Ctrl selects the area diagonally. Shift toggles building/showing cost estimate
 STR_LANDSCAPING_LEVEL_LAND_TOOLTIP                              :{BLACK}Level an area of land to the height of the first selected corner. Ctrl selects the area diagonally. Shift toggles building/showing cost estimate
 STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND                           :{BLACK}Purchase land for future use. Shift toggles building/showing cost estimate
+STR_LANDSCAPING_TOOLTIP_RULER_TOOL                              :{BLACK}Use a virtual ruler to measure distance and height
+
+# copy paste
+STR_COPY_PASTE_TOOLBAR                                          :{WHITE}Copy
+STR_COPY_PASTE_TOOLTIP                                          :{BLACK}Copy & Paste
+STR_COPY_PASTE_COPY_TOOLTIP                                     :{BLACK}Copies the selected area
+STR_COPY_PASTE_PASTE_TOOLTIP                                    :{BLACK}Pastes the copied area
+STR_COPY_PASTE_ROTATE_LEFT_TOOLTIP                              :{BLACK}Rotate 90 Degree CCW
+STR_COPY_PASTE_ROTATE_RIGHT_TOOLTIP                             :{BLACK}Rotate 90 Degree CW
+STR_COPY_PASTE_VACANT_TERRAIN_TOOLTIP                           :{BLACK}If vacant Terrain should be pasted
+STR_COPY_PASTE_LOAD_TOOLTIP                                     :{BLACK}Load a previously saved template
+STR_COPY_PASTE_SAVE_TOOLTIP                                     :{BLACK}Save the current selection to a template
+STR_COPY_PASTE_MIRROR_HORIZONTAL_TOOLTIP                        :{BLACK}Mirror the current selection at the horizontal axis
+STR_COPY_PASTE_MIRROR_VERTICAL_TOOLTIP                          :{BLACK}Mirror the current selection at the vertical axis
+STR_COPY_PASTE_BULLDOZE_BEFORE_BUILD_TOOLTIP                    :{BLACK}Bulldoze non-vacant terrain before pasting
+STR_COPY_PASTE_TOGGLE_SIGNAL_DIRECTION_TOOLTIP                  :{BLACK}Toggle the signal direction when pasting
+STR_COPY_PASTE_CONVERT_RAIL_TOOLTIP                             :{BLACK}Converts used Rail to current railtype when pasting
+STR_COPY_PASTE_WITHOUT_RAIL_TOOLTIP                             :{BLACK}If enabled, Rail will be copied
+STR_COPY_PASTE_WITHOUT_ROAD_TOOLTIP                             :{BLACK}If enabled, Road will be copied
+STR_COPY_PASTE_ONLY_OWN_TOOLTIP                                 :{BLACK}If disabled, only your own items will be copied
+
+STR_COPY_PASTE_PASTE_DISABLED                                   :{WHITE}Pasting is disabled...
+STR_CONFIG_PATCHES_CP_PASTE_SPEED                               :{LTBLUE}Pasting speed in multiplayer. (255 = off): {ORANGE}{STRING1}
 
 # Object construction window
 STR_OBJECT_BUILD_CAPTION                                        :{WHITE}Object Selection
@@ -2176,6 +2432,7 @@
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Local authority: {LTBLUE}{STRING1}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :None
 STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinates: {LTBLUE}{NUM} x {NUM} x {NUM} ({RAW_STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_HEIGHT                       :{BLACK}Height: {LTBLUE}{NUM}
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Built: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Station class: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Station type: {LTBLUE}{STRING}
@@ -2225,6 +2482,7 @@
 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD                        :Tree-lined road
 STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT                     :Road vehicle depot
 STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING               :Road/rail level crossing
+STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_TRAFFIC_LIGHTS               :Road with traffic lights
 STR_LAI_ROAD_DESCRIPTION_TRAMWAY                                :Tramway
 
 # Houses come directly from their building names
@@ -2253,8 +2511,10 @@
 # Industries come directly from their industry names
 
 STR_LAI_TUNNEL_DESCRIPTION_RAILROAD                             :Railway tunnel
+STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_SIGNAL                      :Railway tunnel with signal simulation
 STR_LAI_TUNNEL_DESCRIPTION_ROAD                                 :Road tunnel
 
+STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL                      :Railway bridge with signal simulation
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL                :Steel suspension rail bridge
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL                    :Steel girder rail bridge
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL                :Steel cantilever rail bridge
@@ -2284,6 +2544,9 @@
 STR_ABOUT_VERSION                                               :{BLACK}OpenTTD version {REV}
 STR_ABOUT_COPYRIGHT_OPENTTD                                     :{BLACK}OpenTTD {COPYRIGHT} 2002-2011 The OpenTTD team
 
+# System time window
+STR_SYSTEM_TIME                                                 :{WHITE}System time
+
 # Save/load game/scenario
 STR_SAVELOAD_SAVE_CAPTION                                       :{WHITE}Save Game
 STR_SAVELOAD_LOAD_CAPTION                                       :{WHITE}Load Game
@@ -2291,6 +2554,8 @@
 STR_SAVELOAD_LOAD_SCENARIO                                      :{WHITE}Load Scenario
 STR_SAVELOAD_LOAD_HEIGHTMAP                                     :{WHITE}Load Heightmap
 STR_SAVELOAD_SAVE_HEIGHTMAP                                     :{WHITE}Save Heightmap
+STR_SAVELOAD_SAVE_COPY_PASTE_TEMPLATE                           :{WHITE}Save Template
+STR_SAVELOAD_LOAD_COPY_PASTE_TEMPLATE                           :{WHITE}Load Template
 STR_SAVELOAD_HOME_BUTTON                                        :{BLACK}Click here to jump to the current default save/load directory
 STR_SAVELOAD_BYTES_FREE                                         :{BLACK}{BYTES} free
 STR_SAVELOAD_LIST_TOOLTIP                                       :{BLACK}List of drives, directories and saved-game files
@@ -2307,6 +2572,10 @@
 STR_SAVELOAD_DETAIL_GRFSTATUS                                   :{SILVER}NewGRF: {WHITE}{STRING}
 
 STR_SAVELOAD_OSKTITLE                                           :{BLACK}Enter a name for the savegame
+STR_TEMPLATE_LOAD_FAILED                                        :{WHITE}Loading template failed{}{STRING}
+STR_TEMPLATE_SAVE_FAILED                                        :{WHITE}Saving template failed{}{STRING}
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW                        :Template made with newer version
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN                         :Template is invalid
 
 # World generation
 STR_MAPGEN_WORLD_GENERATION_CAPTION                             :{WHITE}World Generation
@@ -2318,6 +2587,12 @@
 STR_MAPGEN_SNOW_LINE_HEIGHT                                     :{BLACK}Snow line height:
 STR_MAPGEN_SNOW_LINE_UP                                         :{BLACK}Move the snow line height one up
 STR_MAPGEN_SNOW_LINE_DOWN                                       :{BLACK}Move the snow line height one down
+STR_MAPGEN_DESERT_AMOUNT                                        :{BLACK}Amount of desert:
+STR_MAPGEN_DESERT_AMOUNT_UP                                     :{BLACK}Increase the amount of desert tiles
+STR_MAPGEN_DESERT_AMOUNT_DOWN                                   :{BLACK}Decrease the amount of desert tiles
+STR_MAPGEN_TREE_LINE_HEIGHT                                     :{BLACK}Tree line height:
+STR_MAPGEN_TREE_LINE_UP                                         :{BLACK}Move the tree line height one up
+STR_MAPGEN_TREE_LINE_DOWN                                       :{BLACK}Move the tree line height one down
 STR_MAPGEN_RANDOM_SEED                                          :{BLACK}Random seed:
 STR_MAPGEN_RANDOM_SEED_HELP                                     :{BLACK}Click to enter a random seed
 STR_MAPGEN_RANDOM                                               :{BLACK}Randomise
@@ -2350,6 +2625,8 @@
 
 STR_MAPGEN_RANDOM_SEED_OSKTITLE                                 :{BLACK}Enter a random seed
 STR_MAPGEN_SNOW_LINE_QUERY_CAPT                                 :{WHITE}Change snow line height
+STR_MAPGEN_DESERT_AMOUNT_QUERY_CAPT                             :{WHITE}Change amount of desert tiles
+STR_MAPGEN_TREE_LINE_QUERY_CAPT                                 :{WHITE}Change tree line height
 STR_MAPGEN_START_DATE_QUERY_CAPT                                :{WHITE}Change starting year
 
 # SE Map generation
@@ -2559,12 +2836,35 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (City)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Population: {ORANGE}{COMMA}{BLACK}  Houses: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passengers last month: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Mail last month: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Cargo needed for town growth:
+STR_TOWN_VIEW_GENERATED_CARGO_LAST_MONTH                        :{BLACK}Generated cargo last month:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passengers: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Mail: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Cargo delivered / required for town growth this month:
+STR_TOWN_VIEW_PASSENGERS_THIS_MONTH_MAX                         :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Needed for 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_MAIL_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Needed for 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_FOOD_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Needed for 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_WATER_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Needed for 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GOODS_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Needed for 100%: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} required
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} required in winter
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} delivered last month
+STR_TOWN_VIEW_GROWTH_RATE_LAST_MONTH                            :{BLACK}Growth rate last month: {ORANGE}{COMMA}{BLACK} %
+STR_TOWN_VIEW_GROWTH_SPEED_DISABLED                             :{RED}Town growth speed set to none! No growth possible.
+STR_TOWN_VIEW_TRANSPORTED_RATE_LAST_MONTH                       :{BLACK}Town growth requirements met last month: {ORANGE}{COMMA} %
+STR_TOWN_VIEW_CARGO_DEMAND_LAST_MONTH                           :{BLACK}Most demanded last month: {ORANGE}{STRING}
+STR_TOWN_VIEW_GROWTH_STANDARD                                   :Not yet calculated
+STR_TOWN_VIEW_GROWTH_NEED_STATION                               :More serviced stations
+STR_TOWN_VIEW_GROWTH_NEED_MORE_PASS                             :More {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_MAIL                             :More {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_FOOD                             :More {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_WATER                            :More {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_GOODS                            :More {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_PASS                                  :{STRING} service
+STR_TOWN_VIEW_GROWTH_NEED_MAIL                                  :{STRING} service
+STR_TOWN_VIEW_GROWTH_NEED_FOOD                                  :{STRING} service
+STR_TOWN_VIEW_GROWTH_NEED_WATER                                 :{STRING} service
+STR_TOWN_VIEW_GROWTH_NEED_GOODS                                 :{STRING} service
+STR_TOWN_VIEW_GROWTH_SATISFIED                                  :Keep it up !
 STR_TOWN_VIEW_NOISE_IN_TOWN                                     :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CENTER_TOOLTIP                                    :{BLACK}Centre the main view on town location. Ctrl+Click opens a new viewport on town location
 STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON                            :{BLACK}Local authority
@@ -2637,8 +2937,35 @@
 
 STR_STATION_VIEW_RATINGS_BUTTON                                 :{BLACK}Ratings
 STR_STATION_VIEW_RATINGS_TOOLTIP                                :{BLACK}Show station ratings
-STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Local rating of transport service:
+STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Monthly supply and local rating:
 STR_STATION_VIEW_CARGO_RATING                                   :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA}%)
+STR_STATION_VIEW_CARGO_SUPPLY_RATING                            :{WHITE}{STRING}: {YELLOW}{COMMA} / {STRING} ({COMMA}%)
+
+STR_STATION_VIEW_DEPARTURES_BUTTON                              :{BLACK}Departures
+STR_STATION_VIEW_DEPARTURES_TOOLTIP                             :{BLACK}Show list of scheduled departures
+
+STR_STATION_VIEW_GROUP                                          :{BLACK}Group by
+STR_STATION_VIEW_WAITING_STATION                                :Station: Waiting
+STR_STATION_VIEW_WAITING_AMOUNT                                 :Amount: Waiting
+STR_STATION_VIEW_PLANNED_STATION                                :Station: Planned
+STR_STATION_VIEW_PLANNED_AMOUNT                                 :Amount: Planned
+STR_STATION_VIEW_FROM                                           :{YELLOW}{SHORTCARGO} from {STATION}
+STR_STATION_VIEW_VIA                                            :{YELLOW}{SHORTCARGO} via {STATION}
+STR_STATION_VIEW_TO                                             :{YELLOW}{SHORTCARGO} to {STATION}
+STR_STATION_VIEW_FROM_ANY                                       :{RED}{SHORTCARGO} from unknown station
+STR_STATION_VIEW_TO_ANY                                         :{RED}{SHORTCARGO} to any station
+STR_STATION_VIEW_VIA_ANY                                        :{RED}{SHORTCARGO} via any station
+STR_STATION_VIEW_FROM_HERE                                      :{GREEN}{SHORTCARGO} from this station
+STR_STATION_VIEW_VIA_HERE                                       :{GREEN}{SHORTCARGO} stopping at this station
+STR_STATION_VIEW_TO_HERE                                        :{GREEN}{SHORTCARGO} to this station
+STR_STATION_VIEW_NONSTOP                                        :{YELLOW}{SHORTCARGO} non-stop
+
+STR_STATION_VIEW_GROUP_S_V_D                                    :Source-Via-Destination
+STR_STATION_VIEW_GROUP_S_D_V                                    :Source-Destination-Via
+STR_STATION_VIEW_GROUP_V_S_D                                    :Via-Source-Destination
+STR_STATION_VIEW_GROUP_V_D_S                                    :Via-Destination-Source
+STR_STATION_VIEW_GROUP_D_S_V                                    :Destination-Source-Via
+STR_STATION_VIEW_GROUP_D_V_S                                    :Destination-Via-Source
 
 ############ range for rating starts
 STR_CARGO_RATING_APPALLING                                      :Appalling
@@ -2661,6 +2988,79 @@
 
 STR_STATION_VIEW_RENAME_STATION_CAPTION                         :Rename station/loading area
 
+# Departures window
+STR_DEPARTURES_CAPTION                                          :{WHITE}{STATION} Live Travel Information
+STR_DEPARTURES_CAPTION_WAYPOINT                                 :{WHITE}{WAYPOINT} Live Travel Information
+STR_DEPARTURES_DEPARTURES                                       :{BLACK}{TINYFONT}D
+STR_DEPARTURES_ARRIVALS                                         :{BLACK}{TINYFONT}A
+STR_DEPARTURES_VIA_BUTTON                                       :{BLACK}{TINYFONT}via
+STR_DEPARTURES_DEPARTURES_TOOLTIP                               :{BLACK}Show timetabled departures
+STR_DEPARTURES_ARRIVALS_TOOLTIP                                 :{BLACK}Show timetabled arrivals
+STR_DEPARTURES_VIA_TOOLTIP                                      :{BLACK}Show timetabled vehicles that do not stop here
+STR_DEPARTURES_NONE_SELECTED                                    :{ORANGE}No timetable information has been requested.
+STR_DEPARTURES_EMPTY                                            :{ORANGE}No vehicles are currently timetabled to depart from this station.
+STR_DEPARTURES_TIME                                             :{ORANGE}{DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_TIME_DEP                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TIME_ARR                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {RED}{DOWNARROW}
+STR_DEPARTURES_TIME_BOTH                                        :{ORANGE}{1:DATE_WALLCLOCK_TINY} {RED}{DOWNARROW} {ORANGE}{0:DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TERMINUS                                         :{ORANGE}{STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA_STATION                             :{ORANGE}{STATION}{STRING} via {STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA                                     :{ORANGE}{STATION}{STRING} via
+STR_DEPARTURES_VIA                                              :{ORANGE}via {STATION}{STRING}
+STR_DEPARTURES_TOC                                              :{ORANGE}{COMPANY}
+STR_DEPARTURES_GROUP                                            :{ORANGE}{GROUP}
+STR_DEPARTURES_VEH                                              :{ORANGE}{VEHICLE}
+STR_DEPARTURES_CALLING_AT                                       :{TINYFONT}{ORANGE}Calling at:
+STR_DEPARTURES_CALLING_AT_LARGE                                 :{ORANGE}Calling at:
+STR_DEPARTURES_CALLING_AT_FIRST_STATION                         :{STATION}
+STR_DEPARTURES_CALLING_AT_STATION                               :{RAW_STRING}, {STATION}
+STR_DEPARTURES_CALLING_AT_LAST_STATION                          :{RAW_STRING} and {STATION}
+STR_DEPARTURES_CALLING_AT_LIST                                  :{TINYFONT}{ORANGE}{RAW_STRING}.
+STR_DEPARTURES_CALLING_AT_LIST_LARGE                            :{ORANGE}{RAW_STRING}.
+
+STR_DEPARTURES_TYPE_TRAIN                                       :{ORANGE}{TRAIN}
+STR_DEPARTURES_TYPE_TRAIN_SILVER                                :{SILVER}{TRAIN}
+STR_DEPARTURES_TYPE_BUS                                         :{ORANGE}{BUS}
+STR_DEPARTURES_TYPE_BUS_SILVER                                  :{SILVER}{BUS}
+STR_DEPARTURES_TYPE_LORRY                                       :{ORANGE}{LORRY}
+STR_DEPARTURES_TYPE_LORRY_SILVER                                :{SILVER}{LORRY}
+STR_DEPARTURES_TYPE_PLANE                                       :{ORANGE}{PLANE}
+STR_DEPARTURES_TYPE_PLANE_SILVER                                :{SILVER}{PLANE}
+STR_DEPARTURES_TYPE_SHIP                                        :{ORANGE}{SHIP}
+STR_DEPARTURES_TYPE_SHIP_SILVER                                 :{SILVER}{SHIP}
+
+STR_DEPARTURES_STATION_NONE                                     :
+STR_DEPARTURES_STATION_PORT                                     :{ORANGE} {SHIP}
+STR_DEPARTURES_STATION_AIRPORT                                  :{ORANGE} {PLANE}
+STR_DEPARTURES_STATION_PORTAIRPORT                              :{ORANGE} {SHIP} {PLANE}
+
+############ possible statuses start
+STR_DEPARTURES_ON_TIME                                          :{GREEN}On time
+STR_DEPARTURES_ARRIVED                                          :{GREEN}Arrived
+STR_DEPARTURES_DELAYED                                          :{YELLOW}Delayed
+STR_DEPARTURES_EXPECTED                                         :{YELLOW}Expt {DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_CANCELLED                                        :{RED}Cancelled
+
+############ config settings
+STR_CONFIG_SETTING_DEPARTUREBOARDS                              :{ORANGE}Departure boards
+STR_CONFIG_MAX_DEPARTURES                                       :{LTBLUE}Show at most {ORANGE}{STRING1}{LTBLUE} departures at each station
+STR_CONFIG_MAX_DEPARTURE_TIME                                   :{LTBLUE}Show departures at most {ORANGE}{STRING1}{LTBLUE} days in advance
+STR_CONFIG_DEPARTURE_CALC_FREQUENCY                             :{LTBLUE}Calculate departures every {ORANGE}{STRING1}{LTBLUE} ticks
+STR_CONFIG_DEPARTURE_VEHICLE_NAME                               :{LTBLUE}Show vehicle name with departures: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_GROUP_NAME                                 :{LTBLUE}Show group name with departures: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_COMPANY_NAME                               :{LTBLUE}Show company name with departures: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_VEHICLE_TYPE                               :{LTBLUE}Show vehicle type icon with departures: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_VEHICLE_COLOR                              :{LTBLUE}Show vehicle type icon in silver: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_LARGER_FONT                                :{LTBLUE}Use larger font for stations called at on departure boards: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_DESTINATION_TYPE                           :{LTBLUE}Show icons for destinations that are docks or airports: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_SHOW_BOTH                                  :{LTBLUE}Show arrival and departure times on the same line: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_ONLY_PASSENGERS                            :{LTBLUE}Only show departures for vehicles that can carry passengers: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_CONDITIONALS                               :{LTBLUE}Handle conditional order jumps by: {ORANGE}{STRING1}
+STR_CONFIG_DEPARTURE_CONDITIONALS_1                             :giving up
+STR_CONFIG_DEPARTURE_CONDITIONALS_2                             :assuming they will be taken
+STR_CONFIG_DEPARTURE_CONDITIONALS_3                             :assuming they will not be taken
+STR_CONFIG_DEPARTURE_SHOW_ALL_STOPS                             :{LTBLUE}Show all stations called at regardless of loading/unloading: {ORANGE}{STRING1}
+
 # Waypoint/buoy view window
 STR_WAYPOINT_VIEW_CAPTION                                       :{WHITE}{WAYPOINT}
 STR_WAYPOINT_VIEW_CENTER_TOOLTIP                                :{BLACK}Centre main view on waypoint location. Ctrl+Click opens a new viewport on waypoint location
@@ -2670,6 +3070,7 @@
 
 STR_EDIT_WAYPOINT_NAME                                          :{WHITE}Edit waypoint name
 
+# Do not change orders of these strings
 # Finances window
 STR_FINANCES_CAPTION                                            :{WHITE}{COMPANY} Finances {BLACK}{COMPANYNUM}
 STR_FINANCES_EXPENDITURE_INCOME_TITLE                           :{WHITE}Expenditure/Income
@@ -2686,6 +3087,8 @@
 STR_FINANCES_SECTION_AIRCRAFT_INCOME                            :{GOLD}Aircraft Income
 STR_FINANCES_SECTION_SHIP_INCOME                                :{GOLD}Ship Income
 STR_FINANCES_SECTION_LOAN_INTEREST                              :{GOLD}Loan Interest
+STR_FINANCES_SECTION_INFRASTRUCTURE_COSTS                       :{GOLD}Infrastructure Sharing Costs
+STR_FINANCES_SECTION_INFRASTRUCTURE_INCOME                      :{GOLD}Infrastructure Sharing Income
 STR_FINANCES_SECTION_OTHER                                      :{GOLD}Other
 STR_FINANCES_NEGATIVE_INCOME                                    :{BLACK}-{CURRENCY}
 STR_FINANCES_POSITIVE_INCOME                                    :{BLACK}+{CURRENCY}
@@ -2721,6 +3124,11 @@
 STR_COMPANY_VIEW_RELOCATE_HQ                                    :{BLACK}Relocate HQ
 STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS                  :{BLACK}Rebuild company headquarters elsewhere for 1% cost of company value. Shift+Click shows estimated cost without relocating HQ
 
+STR_COMPANY_PROFILE_LOAD_BUTTON                                 :{BLACK}Load Profile
+STR_COMPANY_PROFILE_LOAD_TOOLTIP                                :{BLACK}Load a company profile
+STR_COMPANY_PROFILE_SAVE_BUTTON                                 :{BLACK}Save Profile
+STR_COMPANY_PROFILE_SAVE_TOOLTIP                                :{BLACK}Save current company profile
+
 STR_COMPANY_VIEW_NEW_FACE_BUTTON                                :{BLACK}New Face
 STR_COMPANY_VIEW_NEW_FACE_TOOLTIP                               :{BLACK}Select new face for manager
 STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON                           :{BLACK}Colour Scheme
@@ -2827,6 +3235,9 @@
 
 STR_GROUP_RENAME_CAPTION                                        :{BLACK}Rename a group
 
+STR_GROUP_PROFIT_THIS_YEAR                                      :{BLACK}Profit this year: {CURRENCY}
+STR_GROUP_PROFIT_LAST_YEAR                                      :{BLACK}Profit last year: {CURRENCY}
+
 # Build vehicle window
 STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION                              :New Rail Vehicles
 STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION                            :New Electric Rail Vehicles
@@ -3058,15 +3469,30 @@
 STR_VEHICLE_STATUS_LEAVING                                      :{LTBLUE}Leaving
 STR_VEHICLE_STATUS_CRASHED                                      :{RED}Crashed!
 STR_VEHICLE_STATUS_BROKEN_DOWN                                  :{RED}Broken down
+STR_VEHICLE_STATUS_BROKEN_DOWN_VEL                              :{RED}Broken down - {STRING1}, {LTBLUE} {VELOCITY}
 STR_VEHICLE_STATUS_STOPPED                                      :{RED}Stopped
+STR_VEHICLE_STATUS_TRAIN_STOPPING                               :{RED}Stopping
 STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL                           :{RED}Stopping, {VELOCITY}
 STR_VEHICLE_STATUS_TRAIN_NO_POWER                               :{RED}No power
 STR_VEHICLE_STATUS_TRAIN_STUCK                                  :{ORANGE}Waiting for free path
 
+STR_BREAKDOWN_TYPE_CRITICAL                                     :Mechanical failure
+STR_BREAKDOWN_TYPE_EM_STOP                                      :Emergency stop
+STR_BREAKDOWN_TYPE_LOW_SPEED                                    :Limited to {VELOCITY}
+STR_BREAKDOWN_TYPE_LOW_POWER                                    :{COMMA}% Power
+STR_BREAKDOWN_TYPE_DEPOT                                        :Heading to {STATION} hangar for repairs
+STR_BREAKDOWN_TYPE_LANDING                                      :Heading to {STATION} for emergency landing
+STR_ERROR_TRAIN_TOO_HEAVY                                       :{WHITE}{VEHICLE} is too heavy
+
+STR_VEHICLE_STATUS_HEADING_FOR_STATION                          :{LTBLUE}Heading for {STATION}
 STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL                      :{LTBLUE}Heading for {STATION}, {VELOCITY}
+STR_VEHICLE_STATUS_NO_ORDERS                                    :{LTBLUE}No orders
 STR_VEHICLE_STATUS_NO_ORDERS_VEL                                :{LTBLUE}No orders, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT                         :{LTBLUE}Heading for {WAYPOINT}
 STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL                     :{LTBLUE}Heading for {WAYPOINT}, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_DEPOT                            :{ORANGE}Heading for {DEPOT}
 STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL                        :{ORANGE}Heading for {DEPOT}, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE                    :{LTBLUE}Service at {DEPOT}
 STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL                :{LTBLUE}Service at {DEPOT}, {VELOCITY}
 
 # Vehicle stopped/started animations
@@ -3085,6 +3511,11 @@
 STR_VEHICLE_DETAILS_AIRCRAFT_RENAME                             :{BLACK}Name aircraft
 
 STR_VEHICLE_INFO_AGE_RUNNING_COST_YR                            :{BLACK}Age: {LTBLUE}{STRING2}{BLACK}   Running Cost: {LTBLUE}{CURRENCY}/yr
+
+STR_RUNNING                                                     :{LTBLUE}Running
+STR_NEED_REPAIR                                                 :{ORANGE}Train needs repair - max speed reduced to {VELOCITY}
+STR_CURRENT_STATUS                                              :{BLACK}Current status: {STRING2}
+
 # The next two need to stay in this order
 STR_VEHICLE_INFO_AGE                                            :{COMMA} year{P "" s} ({COMMA})
 STR_VEHICLE_INFO_AGE_RED                                        :{RED}{COMMA} year{P "" s} ({COMMA})
@@ -3116,7 +3547,9 @@
 
 # Extra buttons for train details windows
 STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE                :{LTBLUE}{ENGINE}{BLACK}   Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE_AND_SPEED      :{LTBLUE}{ENGINE}{BLACK}   Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY} {BLACK}Max. speed: {LTBLUE}{VELOCITY}
 STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE                           :{LTBLUE}{ENGINE}{BLACK}   Value: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_AND_SPEED                 :{LTBLUE}{ENGINE}{BLACK}   Value: {LTBLUE}{CURRENCY} {BLACK}Max. speed: {LTBLUE}{VELOCITY}
 
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT                   :{BLACK}Total cargo capacity of this train:
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY                        :{LTBLUE}- {CARGO} ({SHORTCARGO})
@@ -3139,10 +3572,13 @@
 
 # Vehicle refit
 STR_REFIT_CAPTION                                               :{WHITE}{VEHICLE} (Refit)
+STR_REFIT_VEHICLE_SELECTION_TITLE                               :{GOLD}Select parts of the vehicle to refit:
+STR_REFIT_VEHICLE_SELECT_ALL                                    :{BLACK}{TINYFONT}ALL
+STR_REFIT_VEHICLE_SELECT_ALL_TOOLTIP                            :{BLACK}Select the whole vehicle
 STR_REFIT_TITLE                                                 :{GOLD}Select cargo type to carry:
 STR_REFIT_NEW_CAPACITY_COST_OF_REFIT                            :{BLACK}New capacity: {GOLD}{CARGO}{}{BLACK}Cost of refit: {GOLD}{CURRENCY}
 STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT                   :{BLACK}New capacity: {GOLD}{CARGO}, {GOLD}{CARGO}{}{BLACK}Cost of refit: {GOLD}{CURRENCY}
-STR_REFIT_SELECT_VEHICLES_TOOLTIP                               :{BLACK}Select the vehicles to refit. Dragging with the mouse allows to select multiple vehicles. Clicking on an empty space will select the whole vehicle. Ctrl+Click will select a vehicle and the following chain
+STR_REFIT_SELECT_VEHICLES_TOOLTIP                               :{BLACK}Select the vehicles to refit. Dragging with the mouse allows to select multiple vehicles. Clicking on an empty space will select the whole vehicle. Ctrl+Click will select a vehicle and the following chain.
 
 STR_REFIT_TRAIN_LIST_TOOLTIP                                    :{BLACK}Select type of cargo for train to carry
 STR_REFIT_ROAD_VEHICLE_LIST_TOOLTIP                             :{BLACK}Select type of cargo for road vehicle to carry
@@ -3327,6 +3763,7 @@
 STR_TIMETABLE_AND_TRAVEL_FOR                                    :and travel for {STRING1}
 STR_TIMETABLE_DAYS                                              :{COMMA} day{P "" s}
 STR_TIMETABLE_TICKS                                             :{COMMA} tick{P "" s}
+STR_TIMETABLE_MINUTES                                           :{COMMA} minute{P "" s}
 
 STR_TIMETABLE_TOTAL_TIME                                        :{BLACK}This timetable will take {STRING1} to complete
 STR_TIMETABLE_TOTAL_TIME_INCOMPLETE                             :{BLACK}This timetable will take at least {STRING1} to complete (not all timetabled)
@@ -3341,7 +3778,7 @@
 STR_TIMETABLE_STARTING_DATE_TOOLTIP                             :{BLACK}Select a date as starting point of this timetable
 
 STR_TIMETABLE_CHANGE_TIME                                       :{BLACK}Change Time
-STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Change the amount of time that the highlighted order should take
+STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Change the amount of time that the highlighted order should take. Ctrl+click allows to change the waiting time for all stations at once.
 
 STR_TIMETABLE_CLEAR_TIME                                        :{BLACK}Clear Time
 STR_TIMETABLE_CLEAR_TIME_TOOLTIP                                :{BLACK}Clear the amount of time for the highlighted order
@@ -3352,6 +3789,9 @@
 STR_TIMETABLE_AUTOFILL                                          :{BLACK}Autofill
 STR_TIMETABLE_AUTOFILL_TOOLTIP                                  :{BLACK}Fill the timetable automatically with the values from the next journey (Ctrl+Click to try to keep waiting times)
 
+STR_TIMETABLE_AUTOMATE                                          :{BLACK}Automate
+STR_TIMETABLE_AUTOMATE_TOOLTIP                                  :{BLACK}Manage the timetable automatically by updating the values for each journey. Unclick to stop adjusting the timetable continuously and keep current timetable. Ctrl+Unclick clears the curent timetable.
+
 STR_TIMETABLE_EXPECTED                                          :{BLACK}Expected
 STR_TIMETABLE_SCHEDULED                                         :{BLACK}Scheduled
 STR_TIMETABLE_EXPECTED_TOOLTIP                                  :{BLACK}Switch between expected and schedule
@@ -3367,6 +3807,8 @@
 STR_DATE_DAY_TOOLTIP                                            :{BLACK}Select day
 STR_DATE_MONTH_TOOLTIP                                          :{BLACK}Select month
 STR_DATE_YEAR_TOOLTIP                                           :{BLACK}Select year
+STR_DATE_MINUTES_DAY_TOOLTIP                                    :{BLACK}Select minute
+STR_DATE_MINUTES_MONTH_TOOLTIP                                  :{BLACK}Select hour
 
 
 # AI debug window
@@ -3444,6 +3886,10 @@
 STR_INCOME_FLOAT_INCOME                                         :{GREEN}Income: {CURRENCY}
 STR_FEEDER_TINY                                                 :{TINYFONT}{YELLOW}Transfer: {CURRENCY}
 STR_FEEDER                                                      :{YELLOW}Transfer: {CURRENCY}
+STR_FEEDER_INCOME_TINY                                          :{TINYFONT}{YELLOW}Transfer: {CURRENCY}{WHITE} / {GREEN}Income: {CURRENCY}
+STR_FEEDER_INCOME                                               :{YELLOW}Transfer: {CURRENCY}{WHITE} / {GREEN}Income: {CURRENCY}
+STR_FEEDER_COST_TINY                                            :{TINYFONT}{YELLOW}Transfer: {CURRENCY}{WHITE} / {RED}Cost: {CURRENCY}
+STR_FEEDER_COST                                                 :{YELLOW}Transfer: {CURRENCY}{WHITE} / {RED}Cost: {CURRENCY}
 STR_MESSAGE_ESTIMATED_COST                                      :{WHITE}Estimated Cost: {CURRENCY}
 STR_MESSAGE_ESTIMATED_INCOME                                    :{WHITE}Estimated Income: {CURRENCY}
 
@@ -3463,6 +3909,11 @@
 STR_GAME_SAVELOAD_NOT_AVAILABLE                                 :<not available>
 STR_WARNING_LOADGAME_REMOVED_TRAMS                              :{WHITE}Game was saved in version without tram support. All trams have been removed
 
+STR_PROFILE_LOAD_ERROR                                          :{WHITE}Failed to load profile
+STR_PROFILE_SAVE_ERROR                                          :{WHITE}Failed to save profile
+STR_PROFILE_FACE_ERROR                                          :{WHITE}Invalid company face
+STR_PROFILE_COLOUR_ERROR                                        :{WHITE}Invalid company colour
+
 # Map generation messages
 STR_ERROR_COULD_NOT_CREATE_TOWN                                 :{WHITE}Map generation aborted...{}... no suitable town locations
 STR_ERROR_NO_TOWN_IN_SCENARIO                                   :{WHITE}... there is no town in this scenario
@@ -3479,6 +3930,7 @@
 
 STR_WARNING_HEIGHTMAP_SCALE_CAPTION                             :{WHITE}Scale warning
 STR_WARNING_HEIGHTMAP_SCALE_MESSAGE                             :{YELLOW}Resizing source map too much is not recommended. Continue with the generation?
+STR_MAPGEN_TOO_MANY_TILES_MESSAGE                               :{YELLOW}Too many tiles in map. Maximum number of tiles is {NUM}, you have selected {NUM}
 
 # Soundset messages
 STR_WARNING_FALLBACK_SOUNDSET                                   :{WHITE}Only a fallback sound set was found. If you want sounds, install a sound set via the content download system
@@ -3524,6 +3976,7 @@
 STR_ERROR_ALREADY_AT_SEA_LEVEL                                  :{WHITE}... already at sea level
 STR_ERROR_TOO_HIGH                                              :{WHITE}... too high
 STR_ERROR_ALREADY_LEVELLED                                      :{WHITE}... already flat
+STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND                      :{WHITE}Afterwards the bridge above it would be too high.
 
 # Company related errors
 STR_ERROR_CAN_T_CHANGE_COMPANY_NAME                             :{WHITE}Can't change company name...
@@ -3662,6 +4115,7 @@
 # Rail construction errors
 STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION                          :{WHITE}Impossible track combination
 STR_ERROR_MUST_REMOVE_SIGNALS_FIRST                             :{WHITE}Must remove signals first
+STR_ERROR_MUST_REMOVE_EXIT_SIGNALS_FIRST                        :{WHITE}Must remove exit signals first
 STR_ERROR_NO_SUITABLE_RAILROAD_TRACK                            :{WHITE}No suitable railway track
 STR_ERROR_MUST_REMOVE_RAILROAD_TRACK                            :{WHITE}Must remove railway track first
 STR_ERROR_CROSSING_ON_ONEWAY_ROAD                               :{WHITE}Road is one way or blocked
@@ -3676,6 +4130,8 @@
 
 STR_ERROR_CAN_T_CONVERT_RAIL                                    :{WHITE}Can't convert railtype here...
 
+STR_ERROR_SIGNAL_CHANGES                                        :{WHITE}Number of programmable signal evaluations exceeded limit
+
 # Road construction errors
 STR_ERROR_MUST_REMOVE_ROAD_FIRST                                :{WHITE}Must remove road first
 STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION                      :{WHITE}... one way roads can't have junctions
@@ -3683,6 +4139,13 @@
 STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE                              :{WHITE}Can't build tramway here...
 STR_ERROR_CAN_T_REMOVE_ROAD_FROM                                :{WHITE}Can't remove road from here...
 STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM                             :{WHITE}Can't remove tramway from here...
+STR_ERROR_CAN_T_REMOVE_TRAFFIC_LIGHTS_FROM                      :{WHITE}Can't remove traffic lights from here...
+STR_ERROR_MUST_REMOVE_TRAFFIC_LIGHTS_FIRST                      :{WHITE}... must remove traffic lights first
+STR_ERROR_TRAFFIC_LIGHT_CONSIST_TOO_BIG                         :{WHITE}... traffic light consist too big
+STR_ERROR_CAN_T_PLACE_TRAFFIC_LIGHTS                            :{WHITE}Can't place traffic lights...
+STR_ERROR_CAN_ONLY_BE_PLACED_ON_ROAD_JUNCTIONS                  :{WHITE}... can only be placed on road junctions
+STR_ERROR_BUILDING_TRAFFIC_LIGHTS_DISABLED                      :{WHITE}... building trafficlights is disabled, enable it in Advanced settings -> Construction -> Traffic lights
+STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS              :{WHITE}... building trafficlights on town roads is disabled, enable it in Advanced settings -> Construction -> Traffic lights
 STR_ERROR_THERE_IS_NO_ROAD                                      :{WHITE}... there is no road
 STR_ERROR_THERE_IS_NO_TRAMWAY                                   :{WHITE}... there is no tramway
 
@@ -3702,6 +4165,7 @@
 STR_ERROR_TREE_ALREADY_HERE                                     :{WHITE}... tree already here
 STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE                      :{WHITE}... wrong terrain for tree type
 STR_ERROR_CAN_T_PLANT_TREE_HERE                                 :{WHITE}Can't plant tree here...
+STR_ERROR_TREE_ABOVE_TREE_LINE                                  :{WHITE}... tile is above max tree line.
 
 # Bridge related errors
 STR_ERROR_CAN_T_BUILD_BRIDGE_HERE                               :{WHITE}Can't build bridge here...
@@ -3709,6 +4173,7 @@
 STR_ERROR_CAN_T_START_AND_END_ON                                :{WHITE}Can't start and end in the same spot
 STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT                           :{WHITE}Bridge heads not at the same level
 STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN                            :{WHITE}Bridge is too low for the terrain
+STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN                           :{WHITE}Bridge is too high for this terrain.
 STR_ERROR_START_AND_END_MUST_BE_IN                              :{WHITE}Start and end must be in line
 STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH                              :{WHITE}... ends of bridge must both be on land
 STR_ERROR_BRIDGE_TOO_LONG                                       :{WHITE}... bridge too long
@@ -4213,6 +4678,11 @@
 STR_FORMAT_DATE_LONG                                            :{STRING} {STRING} {NUM}
 STR_FORMAT_DATE_ISO                                             :{2:NUM}-{1:RAW_STRING}-{0:RAW_STRING}
 
+STR_FORMAT_DATE_MINUTES                                         :{0:RAW_STRING}:{1:RAW_STRING}
+STR_FORMAT_DATE_MINUTES_WITH_Y                                  :{0:RAW_STRING}:{1:RAW_STRING} / {2:NUM}
+STR_FORMAT_DATE_MINUTES_WITH_YM                                 :{0:RAW_STRING}:{1:RAW_STRING} / {2:DATE_SHORT}
+STR_FORMAT_DATE_MINUTES_WITH_YMD                                :{0:RAW_STRING}:{1:RAW_STRING} / {2:DATE_LONG}
+
 STR_FORMAT_BUOY_NAME                                            :{TOWN} Buoy
 STR_FORMAT_BUOY_NAME_SERIAL                                     :{TOWN} Buoy #{COMMA}
 STR_FORMAT_COMPANY_NUM                                          :(Company {COMMA})
@@ -4237,10 +4707,18 @@
 STR_SAVEGAME_NAME_SPECTATOR                                     :Spectator, {1:STRING1}
 
 # Viewport strings
+STR_VIEWPORT_TOWN_POP_VERY_POOR_RATING                          :{WHITE}{TOWN} {RED}({COMMA})
+STR_VIEWPORT_TOWN_POP_MEDIOCRE_RATING                           :{WHITE}{TOWN} {ORANGE}({COMMA})
+STR_VIEWPORT_TOWN_POP_GOOD_RATING                               :{WHITE}{TOWN} {YELLOW}({COMMA})
 STR_VIEWPORT_TOWN_POP                                           :{WHITE}{TOWN} ({COMMA})
+STR_VIEWPORT_TOWN_POP_EXCELLENT_RATING                          :{WHITE}{TOWN} {GREEN}({COMMA})
 STR_VIEWPORT_TOWN                                               :{WHITE}{TOWN}
 STR_VIEWPORT_TOWN_TINY_BLACK                                    :{TINYFONT}{BLACK}{TOWN}
+STR_VIEWPORT_TOWN_TINY_VERY_POOR_RATING                         :{TINYFONT}{RED}{TOWN}
+STR_VIEWPORT_TOWN_TINY_MEDIOCRE_RATING                          :{TINYFONT}{ORANGE}{TOWN}
+STR_VIEWPORT_TOWN_TINY_GOOD_RATING                              :{TINYFONT}{YELLOW}{TOWN}
 STR_VIEWPORT_TOWN_TINY_WHITE                                    :{TINYFONT}{WHITE}{TOWN}
+STR_VIEWPORT_TOWN_TINY_EXCELLENT_RATING                         :{TINYFONT}{GREEN}{TOWN}
 
 STR_VIEWPORT_SIGN_SMALL_BLACK                                   :{TINYFONT}{BLACK}{SIGN}
 STR_VIEWPORT_SIGN_SMALL_WHITE                                   :{TINYFONT}{WHITE}{SIGN}
@@ -4275,6 +4753,10 @@
 STR_JUST_DATE_SHORT                                             :{DATE_SHORT}
 STR_JUST_DATE_LONG                                              :{DATE_LONG}
 STR_JUST_DATE_ISO                                               :{DATE_ISO}
+STR_JUST_DATE_WALLCLOCK_TINY                                    :{DATE_WALLCLOCK_TINY}
+STR_JUST_DATE_WALLCLOCK_SHORT                                   :{DATE_WALLCLOCK_SHORT}
+STR_JUST_DATE_WALLCLOCK_LONG                                    :{DATE_WALLCLOCK_LONG}
+STR_JUST_DATE_WALLCLOCK_ISO                                     :{DATE_WALLCLOCK_ISO}
 STR_JUST_STRING                                                 :{STRING}
 STR_JUST_STRING_SPACE_STRING                                    :{STRING} {STRING}
 STR_JUST_RAW_STRING                                             :{RAW_STRING}
@@ -4290,12 +4772,16 @@
 STR_BLACK_DATE_LONG                                             :{BLACK}{DATE_LONG}
 STR_BLACK_CROSS                                                 :{BLACK}{CROSS}
 STR_SILVER_CROSS                                                :{SILVER}{CROSS}
+STR_WHITE_DATE_SHORT                                            :{WHITE}{DATE_SHORT}
 STR_WHITE_DATE_LONG                                             :{WHITE}{DATE_LONG}
+STR_WHITE_DATE_WALLCLOCK_LONG                                   :{WHITE}{DATE_WALLCLOCK_LONG}
+STR_WHITE_DATE_WALLCLOCK_SHORT                                  :{WHITE}{DATE_WALLCLOCK_SHORT}
 STR_SHORT_DATE                                                  :{WHITE}{DATE_TINY}
 STR_DATE_LONG_SMALL                                             :{TINYFONT}{BLACK}{DATE_LONG}
 STR_TINY_GROUP                                                  :{TINYFONT}{GROUP}
 STR_BLACK_INT                                                   :{BLACK}{NUM}
 STR_ORANGE_INT                                                  :{ORANGE}{NUM}
+STR_RED_INT                                                     :{RED}{NUM}
 STR_WHITE_SIGN                                                  :{WHITE}{SIGN}
 STR_TINY_BLACK_STATION                                          :{TINYFONT}{BLACK}{STATION}
 STR_BLACK_STRING                                                :{BLACK}{STRING}
@@ -4308,6 +4794,8 @@
 STR_TINY_BLACK_VEHICLE                                          :{TINYFONT}{BLACK}{VEHICLE}
 STR_TINY_RIGHT_ARROW                                            :{TINYFONT}{RIGHTARROW}
 
+STR_WHITE                                                       :{WHITE}
+STR_BLACK                                                       :{BLACK}
 STR_BLACK_1                                                     :{BLACK}1
 STR_BLACK_2                                                     :{BLACK}2
 STR_BLACK_3                                                     :{BLACK}3
@@ -4323,3 +4811,12 @@
 STR_SHIP                                                        :{BLACK}{SHIP}
 
 STR_TOOLBAR_RAILTYPE_VELOCITY                                   :{STRING} ({VELOCITY})
+
+STR_NUM                                                         :{NUM}
+STR_NUM_RELATION_2                                              :{NUM}/{NUM}
+STR_NUM_RELATION_3                                              :{NUM}/{NUM}/{NUM}
+STR_NUM_RELATION_4                                              :{NUM}/{NUM}/{NUM}/{NUM}
+
+STR_WATCH_WINDOW_TITLE                                          :{WHITE}Watching {RAW_STRING}.
+STR_WATCH_CLICK_TO_WATCH_COMPANY                                :{BLACK}Click here to watch company building
+STR_WATCH_CLICK_NEW_WINDOW                                      :{BLACK}Click here to open new watching window
diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt
--- a/src/lang/english_US.txt
+++ b/src/lang/english_US.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :On
 STR_CONFIG_SETTING_DISABLED                                     :disabled
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Off
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Own company
-STR_CONFIG_SETTING_COMPANIES_ALL                                :All companies
-
-STR_CONFIG_SETTING_NONE                                         :None
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realistic
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Left
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Center
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Right
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Allow building on slopes and coasts: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Allow terraforming under buildings, tracks, etc. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Allow more realistically sized catchment areas: {ORANGE}{STRING}
@@ -2559,9 +2547,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (City)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Population: {ORANGE}{COMMA}{BLACK}  Houses: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passengers last month: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Mail last month: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Cargo needed for town growth:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passengers last month: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Mail last month: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Cargo needed for town growth:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} required
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} required in winter
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} delivered last month
diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt
--- a/src/lang/esperanto.txt
+++ b/src/lang/esperanto.txt
@@ -1086,18 +1086,6 @@
 STR_CONFIG_SETTING_ON                                           :Aktiva
 STR_CONFIG_SETTING_DISABLED                                     :malaktiva
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Ne
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Propra kompanio
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Ĉiuj kompanioj
-
-STR_CONFIG_SETTING_NONE                                         :Neniu
-STR_CONFIG_SETTING_ORIGINAL                                     :Originale
-STR_CONFIG_SETTING_REALISTIC                                    :Reala
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Maldekstre
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centre
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Dekstre
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Permesu konstrui sur kliniĝoj kaj bordoj: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Permesu terecigon sub konstruaĵoj, trakoj, ktp. (aŭtodeklivo): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Permesu pli realgrandaj kaptoregionoj: {ORANGE}{STRING}
@@ -2466,9 +2454,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Urbo)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Enloĝantoj: {ORANGE}{COMMA}{BLACK}  Domoj: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Pasaĝeroj lastmonate: {ORANGE}{COMMA}{BLACK}  maksimume: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Poŝto lastmonate: {ORANGE}{COMMA}{BLACK}  maksimume: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Kargo bezonata por kreskigi urbon:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Pasaĝeroj lastmonate: {ORANGE}{COMMA}{BLACK}  maksimume: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Poŝto lastmonate: {ORANGE}{COMMA}{BLACK}  maksimume: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Kargo bezonata por kreskigi urbon:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} bezonatas
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} bezonatas en vintro
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} liveriĝis lastan monaton
diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt
--- a/src/lang/estonian.txt
+++ b/src/lang/estonian.txt
@@ -1152,18 +1152,6 @@
 STR_CONFIG_SETTING_ON                                           :Sees
 STR_CONFIG_SETTING_DISABLED                                     :väljas
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Väljas
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Oma ettevõte
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Kõik ettevõtted
-
-STR_CONFIG_SETTING_NONE                                         :Pole
-STR_CONFIG_SETTING_ORIGINAL                                     :Originaal
-STR_CONFIG_SETTING_REALISTIC                                    :Reaalne
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Vasakul
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Keskel
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Paremal
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Nõlvadele ja kallastele ehitamine: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Maastikukujundus majade, rööbaste jms. all (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Reaalsemad veekogud: {ORANGE}{STRING}
@@ -2583,9 +2571,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Linn)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Rahvaarv: {ORANGE}{COMMA}{BLACK}  Ehitisi: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Reisijaid eelmisel kuul: {ORANGE}{COMMA}{BLACK}  Enim: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Posti eelmisel kuul: {ORANGE}{COMMA}{BLACK}  Enim: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Veoseid linna kasvamiseks:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Reisijaid eelmisel kuul: {ORANGE}{COMMA}{BLACK}  Enim: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Posti eelmisel kuul: {ORANGE}{COMMA}{BLACK}  Enim: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Veoseid linna kasvamiseks:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} vajalik
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} on talvel vajalik
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} toimetatud eelmisel kuul
diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt
--- a/src/lang/finnish.txt
+++ b/src/lang/finnish.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :päällä
 STR_CONFIG_SETTING_DISABLED                                     :pois käytöstä
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Pois
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Oma yhtiö
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Kaikki yhtiöt
-
-STR_CONFIG_SETTING_NONE                                         :Ei yhtään
-STR_CONFIG_SETTING_ORIGINAL                                     :Alkuperäinen
-STR_CONFIG_SETTING_REALISTIC                                    :Realistinen
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :vasemmalla
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :keskellä
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :oikealla
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Rakentaminen rinteisiin ja rannikolle sallittu: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Salli maaston muokkaaminen rakennusten, raiteiden jne. juurella (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Realistisemman kokoiset vaikutusalueet: {ORANGE}{STRING}
@@ -2559,9 +2547,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (City)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Asukasluku: {ORANGE}{COMMA}{BLACK}  Taloja: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Matkustajia viime kuussa: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Postia viime kuussa: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Kaupungin kasvuun tarvittava rahti:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Matkustajia viime kuussa: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Postia viime kuussa: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Kaupungin kasvuun tarvittava rahti:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} vaadittu
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} vaaditaan talvella
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} kuljetettu viime kuussa
diff --git a/src/lang/french.txt b/src/lang/french.txt
--- a/src/lang/french.txt
+++ b/src/lang/french.txt
@@ -1096,18 +1096,6 @@
 STR_CONFIG_SETTING_ON                                           :Activé
 STR_CONFIG_SETTING_DISABLED                                     :Inactif
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Désactivé
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Propre compagnie
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Toutes les compagnies
-
-STR_CONFIG_SETTING_NONE                                         :Aucune
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Réaliste
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :À gauche
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centrée
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :À droite
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Construction côtière et sur pentes{NBSP}: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Terrassement sous les bâtiments, voies, etc. (Autoslope){NBSP}: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Autoriser des zones de desserte plus réalistes{NBSP}: {ORANGE}{STRING}
@@ -2560,9 +2548,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Métropole)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Population{NBSP}: {ORANGE}{COMMA}{BLACK}  Maisons{NBSP}: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passagers le mois dernier{NBSP}: {ORANGE}{COMMA}{BLACK}  max{NBSP}: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Courrier le mois dernier{NBSP}: {ORANGE}{COMMA}{BLACK}  max{NBSP}: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Cargaison nécessaire à la croissance de la ville{NBSP}:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passagers le mois dernier{NBSP}: {ORANGE}{COMMA}{BLACK}  max{NBSP}: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Courrier le mois dernier{NBSP}: {ORANGE}{COMMA}{BLACK}  max{NBSP}: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Cargaison nécessaire à la croissance de la ville{NBSP}:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} requis
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} requis en hiver
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} livré le mois dernier
diff --git a/src/lang/galician.txt b/src/lang/galician.txt
--- a/src/lang/galician.txt
+++ b/src/lang/galician.txt
@@ -1062,18 +1062,6 @@
 STR_CONFIG_SETTING_ON                                           :On
 STR_CONFIG_SETTING_DISABLED                                     :deshabilitado
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Off
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Propia Compañía
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Tódalas compañías
-
-STR_CONFIG_SETTING_NONE                                         :Ningún
-STR_CONFIG_SETTING_ORIGINAL                                     :Orixinal
-STR_CONFIG_SETTING_REALISTIC                                    :Realista
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Esquerda
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centro
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Dereita
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Permiti-la construción en rampas e costas: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Permitir terraformación baixo edificios, pistas, etc. (autopendente): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Permitir áreas de captura máis realistas: {ORANGE}{STRING}
@@ -1274,9 +1262,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}Cidades
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}Industrias
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Recomendado)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Buscador de ruta para trens: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Buscador de ruta para vehículos de estrada: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Buscador de ruta para barcos: {ORANGE}{STRING}
@@ -2363,9 +2348,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Cidade)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Poboación: {ORANGE}{COMMA}{BLACK}  Casas: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Pasaxeiros último mes: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Correo último mes: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Carga necesaria para o crecemento:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Pasaxeiros último mes: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Correo último mes: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Carga necesaria para o crecemento:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} necesario{P "" s}
 STR_TOWN_VIEW_NOISE_IN_TOWN                                     :{BLACK}Límite de ruído na cidade: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CENTER_TOOLTIP                                    :{BLACK}Centrar a vista principal na localización da cidade. CTRL+Click abre una nova fiestra na localización da cidade
diff --git a/src/lang/german.txt b/src/lang/german.txt
--- a/src/lang/german.txt
+++ b/src/lang/german.txt
@@ -24,6 +24,7 @@
 STR_EMPTY                                                       :
 STR_UNDEFINED                                                   :(nicht definierter Text)
 STR_JUST_NOTHING                                                :Nichts
+STR_TINY_NOTHING                                                :{TINYFONT}Nichts
 
 # Cargo related strings
 # Plural cargo name
@@ -221,6 +222,7 @@
 STR_LIST_FILTER_OSKTITLE                                        :{BLACK}Filter eingeben
 STR_LIST_FILTER_TOOLTIP                                         :{BLACK}Stichwort eingeben, mit dem die Liste gefiltert werden soll
 
+STR_TOOLTIP_GROUP_ORDER                                         :{BLACK}Wähle Gruppierungs-Reihenfolge
 STR_TOOLTIP_SORT_ORDER                                          :{BLACK}Sortierreihenfolge auswählen (absteigend/aufsteigend)
 STR_TOOLTIP_SORT_CRITERIA                                       :{BLACK}Sortierkriterium auswählen
 STR_TOOLTIP_FILTER_CRITERIA                                     :{BLACK}Filterkriterien auswählen
@@ -253,6 +255,7 @@
 STR_MEASURE_AREA                                                :{BLACK}Gebiet: {NUM} × {NUM}
 STR_MEASURE_LENGTH_HEIGHTDIFF                                   :{BLACK}Länge: {NUM}{}Höhenunterschied: {HEIGHT}
 STR_MEASURE_AREA_HEIGHTDIFF                                     :{BLACK}Gebiet: {NUM} × {NUM}{}Höhenunterschied: {HEIGHT}
+STR_MEASURE_DIST_HEIGHTDIFF                                     :{BLACK}Entfernung: {NUM}{}Luftlinie: {NUM}{}Abstand zum nächsten Kartenrand: {NUM}{}Höhe vom Meeresspiegel: {HEIGHT}{}Höhenunterschied: {HEIGHT}
 
 
 # These are used in buttons
@@ -374,6 +377,7 @@
 STR_MAP_MENU_MAP_OF_WORLD                                       :Weltkarte
 STR_MAP_MENU_EXTRA_VIEW_PORT                                    :Zusatzansicht
 STR_MAP_MENU_SIGN_LIST                                          :Schilderliste
+STR_MAP_MENU_WATCH_COMPANY                                      :Beobachte Firma
 ############ range for town menu starts, yet the town directory is shown in the map menu in the scenario editor
 STR_TOWN_MENU_TOWN_DIRECTORY                                    :Städteverzeichnis
 ############ end of the 'Display map' dropdown
@@ -447,6 +451,7 @@
 STR_ABOUT_MENU_SCREENSHOT                                       :Screenshot (Standard: Strg+S)
 STR_ABOUT_MENU_ZOOMIN_SCREENSHOT                                :Hereingezoomter Screenshot
 STR_ABOUT_MENU_GIANT_SCREENSHOT                                 :Riesiger Screenshot (Standard: Strg+G)
+STR_ABOUT_MENU_SHOW_SYTEM_TIME                                  :Zeige Systemzeit
 STR_ABOUT_MENU_ABOUT_OPENTTD                                    :Über 'OpenTTD'
 STR_ABOUT_MENU_SPRITE_ALIGNER                                   :Sprite-Ausrichtung
 STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES                            :Hüllquader anzeigen/ausblenden
@@ -656,17 +661,20 @@
 STR_SMALLMAP_TYPE_CONTOURS                                      :Höhenrelief
 STR_SMALLMAP_TYPE_VEHICLES                                      :Fahrzeuge
 STR_SMALLMAP_TYPE_INDUSTRIES                                    :Industrien
+STR_SMALLMAP_TYPE_ROUTEMAP                                      :Verbindungsstatistik
 STR_SMALLMAP_TYPE_ROUTES                                        :Strecken
 STR_SMALLMAP_TYPE_VEGETATION                                    :Vegetation
 STR_SMALLMAP_TYPE_OWNERS                                        :Eigentümer
 STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP                  :{BLACK}Höhenlinien auf der Weltkarte anzeigen
 STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP                       :{BLACK}Fahrzeuge auf der Weltkarte anzeigen
 STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP                     :{BLACK}Industrien auf der Weltkarte anzeigen
+STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP                     :{BLACK}Zeige Verbindungsstatistik auf der Karte
 STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON                   :{BLACK}Transportwege auf der Weltkarte anzeigen
 STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP                     :{BLACK}Vegetation auf der Weltkarte anzeigen
 STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP                    :{BLACK}Landeigentümer auf der Weltkarte anzeigen
 STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION                         :{BLACK}Anzeige einer Industrie umschalten durch Klick. Strg+Klick zeigt alle an außer die Industrie. Neuerliches Strg+Klick zeigt alle Industrien
 STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION                          :{BLACK}Anzeigeeigenschaften mit Klick auf Firma ändern. Strg+Klick deaktiviert alle Firmen außer die ausgewählte. Wiederholtes Strg+Klick aktiviert alle Firmen
+STR_SMALLMAP_TOOLTIP_LINK_STATS_SELECTION                       :{BLACK}Klicke auf eine Fracht um die Darstellung seiner Eigenschaften zu wechseln. Strg+Klick deaktiviert alle Verbindungsstatistiken außer der Gewählten. Drücke Strg und klicke, um wieder alle Statistiken zu aktivieren.
 
 STR_SMALLMAP_LEGENDA_ROADS                                      :{TINYFONT}{BLACK}Straßen
 STR_SMALLMAP_LEGENDA_RAILROADS                                  :{TINYFONT}{BLACK}Gleise
@@ -696,11 +704,27 @@
 STR_SMALLMAP_LEGENDA_INDUSTRIES                                 :{TINYFONT}{BLACK}Industrien
 STR_SMALLMAP_LEGENDA_DESERT                                     :{TINYFONT}{BLACK}Wüste
 STR_SMALLMAP_LEGENDA_SNOW                                       :{TINYFONT}{BLACK}Schnee
+STR_SMALLMAP_LEGENDA_CAPACITY                                   :{TINYFONT}{BLACK}Kapazität
+STR_SMALLMAP_LEGENDA_USAGE                                      :{TINYFONT}{BLACK}Benutzung
+STR_SMALLMAP_LEGENDA_PLANNED                                    :{TINYFONT}{BLACK}Geplanter Verkehr
+STR_SMALLMAP_LEGENDA_SENT                                       :{TINYFONT}{BLACK}Transportierte Güter
+STR_SMALLMAP_LEGENDA_SHOW_TEXT                                  :{TINYFONT}{BLACK}Als Text
+STR_SMALLMAP_LEGENDA_SHOW_GRAPH                                 :{TINYFONT}{BLACK}Als Grafik
+
+STR_SMALLMAP_SUPPLY_CAPTION                                     :{BLACK}Monatliche Güter in {STATION}
+STR_SMALLMAP_SUPPLY                                             :{TINYFONT}{CARGO}
+STR_SMALLMAP_LINK_CAPTION                                       :{BLACK}Monatlicher Verkehr von {STATION} nach {STATION}
+STR_SMALLMAP_LINK                                               :{TINYFONT}{STRING} -
+STR_SMALLMAP_LINK_CAPACITY                                      :{TINYFONT}  Kap: {NUM}
+STR_SMALLMAP_LINK_USAGE                                         :{TINYFONT}  Benutzung: {NUM}
+STR_SMALLMAP_LINK_PLANNED                                       :{TINYFONT}  Plan: {NUM}
+STR_SMALLMAP_LINK_SENT                                          :{TINYFONT}  transportiert: {NUM}
 
 STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF                   :{BLACK}Städtenamen anzeigen ein/aus
 STR_SMALLMAP_CENTER                                             :{BLACK}Zusatzansicht zur akutellen Position scrollen
 STR_SMALLMAP_INDUSTRY                                           :{TINYFONT}{STRING} ({NUM})
 STR_SMALLMAP_COMPANY                                            :{TINYFONT}{COMPANY}
+STR_SMALLMAP_LINKSTATS                                          :{TINYFONT}{STRING}
 STR_SMALLMAP_TOWN                                               :{TINYFONT}{WHITE}{TOWN}
 STR_SMALLMAP_DISABLE_ALL                                        :{BLACK}Alles deaktivieren
 STR_SMALLMAP_ENABLE_ALL                                         :{BLACK}Alles aktivieren
@@ -710,6 +734,8 @@
 STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT                                :{BLACK}Anzeige des Höhenreliefs umschalten
 STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES                      :{BLACK}Zeige kein Eigentum des Unternehmens auf der Karte
 STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES                       :{BLACK}Zeige das ganze Eigentum des Unternehmens auf der Karte
+STR_SMALLMAP_TOOLTIP_DISABLE_ALL_LINK_STATS                     :{BLACK}Zeige keine Verbindungsstatistiken auf der Karte
+STR_SMALLMAP_TOOLTIP_ENABLE_ALL_LINK_STATS                      :{BLACK}Zeige alle Verbindungsstatistiken auf der Karte
 
 # Status bar messages
 STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS                            :{BLACK}Letzte Nachricht oder letzten Bericht anzeigen
@@ -935,6 +961,8 @@
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP                      :{BLACK}Abstand zwischen den automatischen Spielesicherungen wählen
 
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF                          :Aus
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_DAY                  :Jeden Tag
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_WEEK                 :Jede Woche
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH                :Jeden Monat
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS               :Alle 3 Monate
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS               :Alle 6 Monate
@@ -999,7 +1027,7 @@
 STR_DIFFICULTY_LEVEL_CAPTION                                    :{WHITE}Schwierigkeitsgrad
 
 ############ range for difficulty levels starts
-STR_DIFFICULTY_LEVEL_EASY                                       :{BLACK}Leicht
+STR_DIFFICULTY_LEVEL_EASY                                       :{BLACK}Sandkasten
 STR_DIFFICULTY_LEVEL_MEDIUM                                     :{BLACK}Normal
 STR_DIFFICULTY_LEVEL_HARD                                       :{BLACK}Schwer
 STR_DIFFICULTY_LEVEL_CUSTOM                                     :{BLACK}benutzerdef.
@@ -1071,10 +1099,13 @@
 STR_SUBSIDY_X3                                                  :x3
 STR_SUBSIDY_X4                                                  :x4
 
+STR_TERRAIN_TYPE_FALLEN                                         :Extrem flach
 STR_TERRAIN_TYPE_VERY_FLAT                                      :Sehr flach
 STR_TERRAIN_TYPE_FLAT                                           :Flach
+STR_TERRAIN_TYPE_BUMPY                                          :Uneben
 STR_TERRAIN_TYPE_HILLY                                          :Hügelig
 STR_TERRAIN_TYPE_MOUNTAINOUS                                    :Bergig
+STR_TERRAIN_TYPE_ALPINIST                                       :Gebirge
 
 STR_ECONOMY_STEADY                                              :Ruhig
 STR_ECONOMY_FLUCTUATING                                         :Schwankend
@@ -1082,6 +1113,9 @@
 STR_REVERSE_AT_END_OF_LINE_AND_AT_STATIONS                      :Am Streckenende und in Bahnhöfen
 STR_REVERSE_AT_END_OF_LINE_ONLY                                 :Nur am Streckenende
 
+STR_DISASTERS_OFF                                               :Aus
+STR_DISASTERS_ON                                                :An
+
 STR_CITY_APPROVAL_PERMISSIVE                                    :Hoch
 STR_CITY_APPROVAL_TOLERANT                                      :Mäßig
 STR_CITY_APPROVAL_HOSTILE                                       :Gering
@@ -1096,26 +1130,22 @@
 STR_CONFIG_SETTING_ON                                           :An
 STR_CONFIG_SETTING_DISABLED                                     :ausgeschaltet
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Aus
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eigene Firma
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alle Firmen
-
-STR_CONFIG_SETTING_NONE                                         :Keine
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realistisch
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Links
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Mitte
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Rechts
-
+STR_CONFIG_SETTING_VEHICLESPEED                                 :{LTBLUE}Zeige Fahrzeuggeschwindigkeit in der Fahrzeug Statusleiste: {ORANGE}{STRING}
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Das Bauen an Hängen und Küsten erlauben: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Landschaftsbau unter Gebäuden, Gleisen, usw. erlauben: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Verschiedene Stationstypen haben unterschiedlich große Einzugsgebiete: {ORANGE}{STRING}
 STR_CONFIG_SETTING_EXTRADYNAMITE                                :{LTBLUE}Entfernung von weiteren Straßen, Brücken, usw. erlauben: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TRAIN_LENGTH                                 :{LTBLUE}Maximale Länge von Zügen: {ORANGE}{STRING} Feld{P 0:1 "" er}
 STR_CONFIG_SETTING_SMOKE_AMOUNT                                 :{LTBLUE}Menge an Rauch / Funken von Lokomotiven: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SMOKE_AMOUNT_NONE                            :Nichts
+STR_CONFIG_SETTING_SMOKE_AMOUNT_ORIGINAL                        :Original
+STR_CONFIG_SETTING_SMOKE_AMOUNT_REALISTIC                       :Realistisch
 STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL                     :{LTBLUE}Beschleunigungsmodell für Züge: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_ORIGINAL            :Original
+STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_REALISTIC           :Realistisch
 STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL              :{LTBLUE}Beschleunigungsmodell für Straßenfahrzeuge: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_ORIGINAL     :Original
+STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_REALISTIC    :Realistisch
 STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS                        :{LTBLUE}Stärke von Steigungen für Züge: {ORANGE}{STRING}%
 STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS                 :{LTBLUE}Stärke von Steigungen für Straßenfahrzeuge: {ORANGE}{STRING}%
 STR_CONFIG_SETTING_FORBID_90_DEG                                :{LTBLUE}Zügen und Schiffen 90°-Kurven verbieten: {ORANGE}{STRING}
@@ -1126,11 +1156,13 @@
 STR_CONFIG_SETTING_SELECTGOODS                                  :{LTBLUE}Industrien beliefern nur Stationen mit passendem Transport: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH                            :{LTBLUE}Maximale Brückenlänge: {ORANGE}{STRING} Feld{P 0:1 "" er}
 STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH                            :{LTBLUE}Maximale Tunnellänge: {ORANGE}{STRING} Feld{P 0:1 "" er}
+STR_CONFIG_SETTING_GOTODEPOT                                    :{LTBLUE}Erlaube "Fahre zu Depot" Aufträge: {ORANGE}{STRING}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD             :{LTBLUE}Manueller Bau von Rohstoffindustrien: {ORANGE}{STRING}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE        :Nicht erlaubt
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL      :Wie andere Industrien
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :Durch Prospektion
 STR_CONFIG_SETTING_INDUSTRY_PLATFORM                            :{LTBLUE}Ebenes Gelände um Industrien: {ORANGE}{STRING} Feld{P 0:1 "" er}
+STR_CONFIG_SETTING_EXTRA_INDUSTRY_PLACEMENT_LOGIC               :{LTBLUE}Erlaube die veränderung von mehr als einem Höhenlevel, wenn das Fundament für die Industrie gelegt werden soll: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MULTIPINDTOWN                                :{LTBLUE}Mehrere gleichartige Industrien pro Stadt erlauben: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SIGNALSIDE                                   :{LTBLUE}Signale auf der Seite der Straßenverkehrsrichtung anzeigen: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SHOWFINANCES                                 :{LTBLUE}Zeige Firmenfinanzen am Ende des Jahres: {ORANGE}{STRING}
@@ -1156,6 +1188,8 @@
 STR_CONFIG_SETTING_ADJACENT_STATIONS                            :{LTBLUE}Bau angrenzender Stationen erlauben: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES                              :{LTBLUE}Mehrere NewGRF-Fahrzeugsets erlauben: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES            :{WHITE}Diese Einstellung kann nicht geändert werden solange Fahrzeuge im Spiel sind
+STR_CONFIG_SETTING_MAX_SIGNAL_EVALUATIONS                       :{LTBLUE}Maximale Anzahl an Änderungen bei program. Signalen auf einmal: {ORANGE}{STRING}
+STR_CONFIG_SETTING_BACK_ONE_WAY_PBS_SAFE_WAITING                :{LTBLUE}Rückseite der einseitigen Pfadsignale ist sichere Warteposition: {ORANGE}{STRING}
 
 STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS                        :{LTBLUE}Flughäfen veralten nie: {ORANGE}{STRING}
 
@@ -1172,18 +1206,24 @@
 STR_CONFIG_SETTING_ERRMSG_DURATION                              :{LTBLUE}Dauer der Fehlermeldungen: {ORANGE}{STRING} Sekunde{P 0:1 "" n}
 STR_CONFIG_SETTING_HOVER_DELAY                                  :{LTBLUE}Anzeige von Hilfstexten: {ORANGE}Mit der Maus {STRING} Sekunde{P 0:1 "" n} verweilen
 STR_CONFIG_SETTING_HOVER_DELAY_DISABLED                         :{LTBLUE}Anzeige von Hilfstexten: {ORANGE}Per Rechtsklick
-STR_CONFIG_SETTING_POPULATION_IN_LABEL                          :{LTBLUE}Zeige die Einwohnerzahl von Städten neben ihrem Namen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_POPULATION_IN_LABEL                          :{LTBLUE}Zeige extra Informationen im Stadt-Label: {ORANGE}{STRING}
+STR_CONFIG_SETTING_POPULATION_IN_LABEL_COLOURED                 :{LTBLUE}Füge Stadtbewertung zum Stadt-Label hinzu: {ORANGE}{STRING}
 
 STR_CONFIG_SETTING_LAND_GENERATOR                               :{LTBLUE}Algorithmus zur Landschaftserzeugung: {ORANGE}{STRING}
 STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL                      :Original
 STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS                 :TerraGenesis
 STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Maximaler Abstand der Ölraffinerien vom Spielfeldrand: {ORANGE}{STRING} Feld{P 0:1 "" er}
 STR_CONFIG_SETTING_SNOWLINE_HEIGHT                              :{LTBLUE}Schneegrenze auf: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DESERT_AMOUNT                                :{LTBLUE}Wüstenanteil: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TREELINE_HEIGHT                              :{LTBLUE}Baumwuchshöhe: {ORANGE}{STRING}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN                         :{LTBLUE}Rauheit (nur TerraGenesis): {ORANGE}{STRING}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH             :Sehr eben
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH                  :Eben
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH                   :Rau
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH              :Sehr rau
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_CEREALLY_ROUGH          :Extrem rau
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_COMMUTORZ               :Mittel
+STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_GO_WITH_THE_FLOW        :Glatt
 STR_CONFIG_SETTING_TREE_PLACER                                  :{LTBLUE}Algorithmus zur Baumplatzierung: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TREE_PLACER_NONE                             :Keiner
 STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL                         :Original
@@ -1203,6 +1243,7 @@
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN                   :Grün
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN              :Dunkelgrün
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET                  :Lila
+STR_CONFIG_SETTING_SMALLMAP_FLOOD_WARNING                       :{LTBLUE}Färbe überflutungsgefährdete Flächen auf der Weltkarte violett: {ORANGE}{STRING}
 STR_CONFIG_SETTING_REVERSE_SCROLLING                            :{LTBLUE}Scrollrichtung invertieren: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SMOOTH_SCROLLING                             :{LTBLUE}Weicher Bildlauf beim Springen zu einer Position: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MEASURE_TOOLTIP                              :{LTBLUE}Beim Bauen Tooltip mit Abmessungen anzeigen: {ORANGE}{STRING}
@@ -1240,8 +1281,24 @@
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING      :Alle Tätigkeiten außer Landschaftsbau
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS              :Alle Tätigkeiten
 STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Erweiterte Fahrzeugliste benutzen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OFF                   :Aus
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OWN                   :Eigene Firma
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_ALL                   :Alle Firmen
 STR_CONFIG_SETTING_LOADING_INDICATORS                           :{LTBLUE}Ladestandanzeiger verwenden: {ORANGE}{STRING}
+STR_CONFIG_SETTING_LOADING_INDICATORS_OFF                       :Aus
+STR_CONFIG_SETTING_LOADING_INDICATORS_OWN                       :Eigene Firma
+STR_CONFIG_SETTING_LOADING_INDICATORS_ALL                       :Alle Firmen
+STR_CONFIG_SETTING_TIMETABLE_ALLOW                              :{LTBLUE}Erlaube das Erstellen von Fahrplänen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIMETABLE_AUTOMATED                          :{LTBLUE}Automatisch angepasste Fahrpläne: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIME_IN_MINUTES                              :{LTBLUE}Zeige die Zeit in Minuten anstelle von Tagen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TICKS_PER_MINUTE                             :{LTBLUE}Ticks pro Minute: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DATE_WITH_TIME                               :{LTBLUE}Zeige das Datum mit der Uhrzeit in der Statusbar: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DATE_WITH_TIME_NONE                          :Nicht
+STR_CONFIG_SETTING_DATE_WITH_TIME_Y                             :Jahr
+STR_CONFIG_SETTING_DATE_WITH_TIME_YM                            :Monat und Jahr
+STR_CONFIG_SETTING_DATE_WITH_TIME_YMD                           :Ganzes Datum
 STR_CONFIG_SETTING_TIMETABLE_IN_TICKS                           :{LTBLUE}Zeitpläne in Ticks anstatt in Tagen anzeigen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIMETABLE_SEPARATION                         :{LTBLUE}Nutze Fahrplan um den Abstand festzulegen: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE             :{LTBLUE}Zeige Ankunft und Abfahrt im Fahrplan: {ORANGE}{STRING}
 STR_CONFIG_SETTING_QUICKGOTO                                    :{LTBLUE}Schnelle Erzeugung von Aufträgen für Fahrzeuge: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE                            :{LTBLUE}Gleistyp bei Spielbeginn/geladenem Spiel: {ORANGE}{STRING}
@@ -1266,6 +1323,18 @@
 STR_CONFIG_SETTING_AI_IN_MULTIPLAYER                            :{LTBLUE}KI im Mehrspielermodus erlauben: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AI_MAX_OPCODES                               :{LTBLUE}Anzahl Rechenschritte bevor KI unterbrochen wird: {ORANGE}{STRING}
 
+STR_CONFIG_SETTING_SHARING_RAIL                                 :{LTBLUE}Erlaube gemeinsame Nutzung von Schienenwegen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_ROAD                                 :{LTBLUE}Erlaube gemeinsame Nutzung von Bushaltestellen, Ladeplätzen und Depots: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_WATER                                :{LTBLUE}Erlaube gemeinsame Nutzung von Häfen und Werften: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_AIR                                  :{LTBLUE}Erlaube gemeinsame Nutzung von Flughäfen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_FEE_RAIL                             :{LTBLUE}Tägliche Nutzungsgebühr für Schienenwege: {ORANGE}{STRING} pro 1000 Tonnen
+STR_CONFIG_SETTING_SHARING_FEE_ROAD                             :{LTBLUE}Haltegebühren für Straßenfahrzeuge: {ORANGE}{STRING} pro Tag
+STR_CONFIG_SETTING_SHARING_FEE_WATER                            :{LTBLUE}Haltegebühren für Schiffe: {ORANGE}{STRING} pro Tag
+STR_CONFIG_SETTING_SHARING_FEE_AIR                              :{LTBLUE}Haltegebühren für Flugzeuge: {ORANGE}{STRING} pro Tag
+STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT                      :{LTBLUE}Erlaube verschuldeten Firmen, Nutzungsgebühren zu zahlen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES                     :{WHITE}Die Einstellung kann nicht geändert werden, da sich Züge auf fremden Schienennetz befinden.
+STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS                     :{WHITE}Die Einstellung kann nicht geändert werden, da Züge Aufträge zu fremden Stationen haben.
+
 STR_CONFIG_SETTING_SERVINT_ISPERCENT                            :{LTBLUE}Wartungsintervalle in Prozent: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SERVINT_TRAINS                               :{LTBLUE}Vorgegebenes Wartungsintervall für Züge: {ORANGE}{STRING} Tag{P 0:1 "" e}/%
 STR_CONFIG_SETTING_SERVINT_TRAINS_DISABLED                      :{LTBLUE}Vorgegebenes Wartungsintervall für Züge: {ORANGE}abgeschaltet
@@ -1276,6 +1345,7 @@
 STR_CONFIG_SETTING_SERVINT_SHIPS                                :{LTBLUE}Vorgegebenes Wartungsintervall für Schiffe: {ORANGE}{STRING} Tag{P 0:1 "" e}e/%
 STR_CONFIG_SETTING_SERVINT_SHIPS_DISABLED                       :{LTBLUE}Vorgegebenes Wartungsintervall für Schiffe: {ORANGE}abgeschaltet
 STR_CONFIG_SETTING_NOSERVICE                                    :{LTBLUE}Wartung deaktivieren, wenn Pannen abgeschaltet: {ORANGE}{STRING}
+STR_CONFIG_SETTING_IMPROVED_BREAKDOWNS                          :{LTBLUE}Aktiviere verbesserte Pannen: {ORANGE}{STRING}
 STR_CONFIG_SETTING_WAGONSPEEDLIMITS                             :{LTBLUE}Berücksichtige Waggonhöchstgeschwindigkeit: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DISABLE_ELRAILS                              :{LTBLUE}Deaktiviere elektrifizierte Strecken: {ORANGE}{STRING}
 
@@ -1310,13 +1380,32 @@
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED                        :erlaubt
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT          :erlaubt mit wählbarem Straßenbauplan
 
+STR_CONFIG_SETTING_DAYLENGTH_FACTOR                             :{LTBLUE}Tageslängen-Faktor: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_CARGO_FACTOR                            :{LTBLUE}Frachtgenerierungsfaktor für Städte (weniger < 0 < mehr): {ORANGE}{STRING}
+
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT                         :{LTBLUE}Platzierung von Bäumen während des Spiels: {ORANGE}{STRING}
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NONE                    :nirgends {RED}(macht Holzmühle nutzlos)
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_RAINFOREST              :nur im Regenwald
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_ALL                     :überall
 
+STR_CONFIG_SETTING_TREE_PLACEMENT_DRAG_LIMIT                    :{LTBLUE}Flächenlimit für das Baumpflanztool: {ORANGE}{STRING}
+
+STR_CONFIG_SETTING_INGAME_TREELINE_HEIGHT                       :{LTBLUE}Baumwuchshöhe im Spiel: {ORANGE}{STRING}
+
+STR_CONFIG_SETTING_TREE_GROWTH                                  :{LTBLUE}Baumwuchsgeschwindigkeit: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TREE_GROWTH_NORMAL                           :Normal
+STR_CONFIG_SETTING_TREE_GROWTH_SLOW                             :Langsam
+STR_CONFIG_SETTING_TREE_GROWTH_VERY_SLOW                        :Sehr langsam
+STR_CONFIG_SETTING_TREE_GROWTH_EXTREMLY_SLOW                    :Extrem langsam
+
 STR_CONFIG_SETTING_TOOLBAR_POS                                  :{LTBLUE}Position der Werkzeugleiste: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOOLBAR_POS_LEFT                             :Links
+STR_CONFIG_SETTING_TOOLBAR_POS_CENTER                           :Mitte
+STR_CONFIG_SETTING_TOOLBAR_POS_RIGHT                            :Rechts
 STR_CONFIG_SETTING_STATUSBAR_POS                                :{LTBLUE}Position der Statuszeile: {ORANGE}{STRING}
+STR_CONFIG_SETTING_STATUSBAR_POS_LEFT                           :Links
+STR_CONFIG_SETTING_STATUSBAR_POS_CENTER                         :Mitte
+STR_CONFIG_SETTING_STATUSBAR_POS_RIGHT                          :Rechts
 STR_CONFIG_SETTING_SNAP_RADIUS                                  :{LTBLUE}Fenster schnappen aneinander, wenn näher als: {ORANGE}{STRING} Pixel
 STR_CONFIG_SETTING_SNAP_RADIUS_DISABLED                         :{LTBLUE}Fenster schnappen aneinander, wenn näher als: {ORANGE}ausgeschaltet
 STR_CONFIG_SETTING_SOFT_LIMIT                                   :{LTBLUE}Maximale Fensteranzahl (nicht angepinnte): {ORANGE}{STRING}
@@ -1330,19 +1419,76 @@
 STR_CONFIG_SETTING_LARGER_TOWNS                                 :{LTBLUE}Anteil der Großstädte: {ORANGE}1 / {STRING}.
 STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED                        :{LTBLUE}Anteil der Großstädte: {ORANGE}keine
 STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER                         :{LTBLUE}Größe von Großstädten bei Spielbeginn: {ORANGE}{STRING}x
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO                            :{LTBLUE}Städtewachstum abhängig von Passagier-, Post- und Warentransport: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_OFF                        :aus
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_VERY_EASY                  :Sehr einfach
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_EASY                       :Einfach
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_AVERAGE                    :Durchschnittlich
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_HARD                       :Schwer
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_VERY_HARD                  :Sehr schwer
+STR_CONFIG_SETTING_TOWN_GROWTH_CARGO_INSANE                     :Unglaublich schwer
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO                     :{LTBLUE}Wachstum großer Städte abhängig von Passagier-, Post- und Warentransport: {ORANGE}{STRING}
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_OFF                 :aus
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_VERY_EASY           :Sehr einfach
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_EASY                :Einfach
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_AVERAGE             :Durchschnittlich
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_HARD                :Schwer
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_VERY_HARD           :Sehr schwer
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO_INSANE              :Unglaublich schwer
+STR_CONFIG_SETTING_TOWN_GROWTH_MAX_POP_WO_GOODS                 :{LTBLUE}Maximale Einwohnerzahl von Städten, bevor Waren zum Wachstum benötigt werden: {ORANGE}{STRING}
+STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_MAX_POP_WO_GOODS          :{LTBLUE}Maximale Einwohnerzahl von Großstädten, bevor Waren zum Wachstum benötigt werden: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MODIFIED_ROAD_REBUILD                        :{LTBLUE}Entferne absurde Straßenteile während Straßenreparaturen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TRAFFIC_LIGHTS                               :{LTBLUE}Aktiviere Ampeln: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWNS_BUILD_TRAFFIC_LIGHTS                   :{LTBLUE}Städte bauen während dem Straßenbau Ampeln: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ALLOW_BUILDING_TLS_ON_TOWN_ROADS             :{LTBLUE}Erlaube das Bauen und Abreißen von Ampeln auf städtischen Straßen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TRAFFIC_LIGHTS_GREEN_PHASE                   :{LTBLUE}Länge der Grünphase von Ampeln: {ORANGE}{STRING}
+STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_SIZE               :{LTBLUE}Maximale Felderlängen Größe: {ORANGE}{STRING}. {RED}Warnung: Hohe Werte verlangsamen das Spiel
+STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_DISTANCE           :{LTBLUE}Maximaler Abstand zwischen Ampeln, um diese zu synchronisieren: {ORANGE}{STRING} Felder. {RED}Warnung: Hohe Werte verlangsamen das Spiel
+
+STR_CONFIG_SETTING_LINKGRAPH_INTERVAL                           :{LTBLUE}Aktualisierungsrate von den Verbindungsgrafiken: {ORANGE}{STRING} * 74 Ticks
+STR_CONFIG_SETTING_DISTRIBUTION_PAX                             :{LTBLUE}Verteilung für Passagieren: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_SYMMETRIC                   :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_ASYMMETRIC                  :unsymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_PAX_MANUAL                      :manuell
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL                            :{LTBLUE}Verteilung für Post: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_SYMMETRIC                  :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_ASYMMETRIC                 :unsymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_MAIL_MANUAL                     :manuell
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS                         :{LTBLUE}Verteilung für EXPRESS-Güter: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_SYMMETRIC               :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_ASYMMETRIC              :unsymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS_MANUAL                  :manuell
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED                        :{LTBLUE}Verteilung für Wertsachen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_SYMMETRIC              :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_ASYMMETRIC             :unsymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_MANUAL                 :manuell
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT                         :{LTBLUE}Verteilung für andere Güter: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_SYMMETRIC               :symmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_ASYMMETRIC              :unsymmetrisch
+STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_MANUAL                  :manuell
+STR_CONFIG_SETTING_LINKGRAPH_ACCURACY                           :{LTBLUE}Genauigkeit bei der Berechnung von Verbindungsgrafiken: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DEMAND_DISTANCE                              :{LTBLUE}Effekt der Entfernung auf Nachfrage: {ORANGE}{STRING}%
+STR_CONFIG_SETTING_DEMAND_SIZE                                  :{LTBLUE}Effekt der Stionsbewertung auf symetrische Verbindungen: {ORANGE}{STRING}%
+STR_CONFIG_SETTING_SHORT_PATH_SATURATION                        :{LTBLUE}Auslastung von kurzen Verbindungen bevor Kapazitätsreiche Verbindungen genutzt werden: {ORANGE}{STRING}%
+STR_CONFIG_SETTING_NO_OVERLOAD_LINKS                            :{LTBLUE}Versuche die Verbindungen nicht zu überladens: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SMALLMAP_LINKGRAPH_COMPANIES                 :{LTBLUE}Zeige Verbindungsgrafiken in der Weltkarte für: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHOW_SMALLMAP_LINKGRAPH_OWN_ONLY             :nur eigene Firma
+STR_CONFIG_SETTING_SHOW_SMALLMAP_LINKGRAPH_ALL_COMPANIES        :alle Firmen
 
 STR_CONFIG_SETTING_GUI                                          :{ORANGE}Oberfläche
 STR_CONFIG_SETTING_CONSTRUCTION                                 :{ORANGE}Konstruktion
 STR_CONFIG_SETTING_VEHICLES                                     :{ORANGE}Fahrzeuge
 STR_CONFIG_SETTING_STATIONS                                     :{ORANGE}Bahnhöfe
 STR_CONFIG_SETTING_ECONOMY                                      :{ORANGE}Wirtschaft
+STR_CONFIG_SETTING_LINKGRAPH                                    :{ORANGE}Verbindungsgrafik
 STR_CONFIG_SETTING_AI                                           :{ORANGE}Gegenspieler
 STR_CONFIG_SETTING_DISPLAY_OPTIONS                              :{ORANGE}Darstellung
 STR_CONFIG_SETTING_INTERACTION                                  :{ORANGE}Interaktion
 STR_CONFIG_SETTING_CONSTRUCTION_SIGNALS                         :{ORANGE}Signale
+STR_CONFIG_SETTING_CONSTRUCTION_TRAFFIC_LIGHTS                  :{ORANGE}Ampeln
 STR_CONFIG_SETTING_STATIONS_CARGOHANDLING                       :{ORANGE}Frachtbehandlung
 STR_CONFIG_SETTING_AI_NPC                                       :{ORANGE}Computerspieler
+STR_CONFIG_SETTING_SHARING                                      :{ORANGE}gemeinsame Nutzung von Infrastruktur
 STR_CONFIG_SETTING_VEHICLES_AUTORENEW                           :{ORANGE}Automatische Erneuerung
 STR_CONFIG_SETTING_VEHICLES_SERVICING                           :{ORANGE}Wartung
 STR_CONFIG_SETTING_VEHICLES_ROUTING                             :{ORANGE}Wegsuche
@@ -1355,10 +1501,20 @@
 STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(empfohlen)
 
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Pathfinder für Züge: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_NPF                    :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_YAPF                   :YAPF {BLUE}(Recommended)
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Pathfinder für Straßenfahrzeuge: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_NPF             :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_YAPF            :YAPF {BLUE}(Recommended)
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Pathfinder für Schiffe: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_OPF                     :Original
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_NPF                     :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_YAPF                    :YAPF {BLUE}(recommended)
 STR_CONFIG_SETTING_REVERSE_AT_SIGNALS                           :{LTBLUE}Automatisches Umdrehen an Signalen: {ORANGE}{STRING}
 
+STR_CONFIG_SETTING_MORE_HEIGHTLEVELS                            :{LTBLUE}Erlaube mehr als 16 Höhenstufen: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ERROR_NO_CHANGE_TO_OLD_POSSIBLE              :{WHITE}Die Konfigurationsaenderung von mehr als 16 erlaubten Höhenstufen zu weniger ist leider nicht moeglich.  Grund: Es befindet sich ein Berg, der höher als 16 Höhenstufen ist, auf der Karte.
+
 STR_CONFIG_SETTING_QUERY_CAPTION                                :{WHITE}Wert der Einstellung ändern
 
 # Intro window
@@ -1429,6 +1585,7 @@
 STR_CHEATS_TOOLTIP                                              :{BLACK}Die Kontrollkästchen zeigen an, ob dieser Cheat schonmal verwendet worden ist
 STR_CHEATS_WARNING                                              :{BLACK}Achtung! Hiermit betrügt man seine Mitspieler. Man sollte bedenken, dass sie das niemals verzeihen werden
 STR_CHEAT_MONEY                                                 :{LTBLUE}Kontostand um {CURRENCY} erhöhen
+STR_CHEAT_DAYLENGHT_INCOME                                      :{LTBLUE}Teile das Fahrzeugeinkommen nicht durch den Tageslängenfaktor: {ORANGE}{STRING}
 STR_CHEAT_CHANGE_COMPANY                                        :{LTBLUE}Spiele die Firma: {ORANGE}{COMMA}
 STR_CHEAT_EXTRA_DYNAMITE                                        :{LTBLUE}Mächtigeres Abrisswerkzeug (entfernt Industrien und unbewegliche Objekte): {ORANGE}{STRING}
 STR_CHEAT_CROSSINGTUNNELS                                       :{LTBLUE}Tunnel dürfen sich kreuzen: {ORANGE}{STRING}
@@ -1887,6 +2044,7 @@
 STR_TRANSPARENT_STRUCTURES_TOOLTIP                              :{BLACK}Transparenz für Bauten wie Leuchttürme und Sendemasten einstellen. Strg+Klick, um Umschalten zu verhindern
 STR_TRANSPARENT_CATENARY_TOOLTIP                                :{BLACK}Transparenz für Oberleitungen. Strg+Klick, um Umschalten zu verhindern
 STR_TRANSPARENT_LOADING_TOOLTIP                                 :{BLACK}Transparenz für Ladestandsanzeige einstellen. Strg+Klick, um Umschalten zu verhindern
+STR_TRANSPARENT_TUNNELS_TOOLTIP                                 :{BLACK}Wechsle Transparenz für Fahrzeuge in Tunneln. Strg+Klick sichert diese Einstellung.
 STR_TRANSPARENT_INVISIBLE_TOOLTIP                               :{BLACK}Objekte unsichtbar statt transparent machen
 
 # Base for station construction window(s)
@@ -1958,12 +2116,16 @@
 STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP                        :{BLACK}Einfahrsignal (Formsignal){}Zeigt grün, wenn im nächsten Block mindestens ein Ausfahrsignal grün zeigt. Andernfalls zeigt es rot
 STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP                         :{BLACK}Ausfahrsignal (Formsignal){}Verhält sich wie ein Blocksignal, wird jedoch benötigt, um den Einfahr- oder Kombinationssignalen des Blockes "frei" zu melden
 STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP                        :{BLACK}Kombinationssignal (Formsignal){}Das Kombinationssignal ist gleichzeitig Aus- und Einfahrsignal. Somit werden umfangreiche Signalverschaltungen möglich
+STR_BUILD_SIGNAL_SEMAPHORE_PROG_TOOLTIP                         :{BLACK}Programmierbare Flügelsignale{}Das programmierbare Signal ist ein Kombisignal, das in vielfältiger Weise programmiert werden kann
+STR_BUILD_SIGNAL_SEMAPHORE_SPEED_TOOLTIP                        :{BLACK}Geschwindigkeitsbeschränkende Flügelsignale{}Das Signal legt die Höchstgeschwindigkeit für den passierenden Zug fest, bis dieser ein weiteres solches Signal passiert
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP                          :{BLACK}Pfadsignal (Formsignal){}Erlaubt mehreren Zügen gleichzeitig, einen Signalabschnitt zu befahren, sofern sie separate Gleisabschnitte belegen können. Pfadsignale können von hinten durchfahren werden
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP                     :{BLACK}Einseitiges Pfadsignal (Formsignal):{}Erlaubt mehreren Zügen, einen Signalabschnitt zu befahren, sofern sie separate Gleisabschnitte belegen können. Einseitige Pfadsignale können nicht von hinten durchfahren werden
 STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP                          :{BLACK}Blocksignal (Lichtsignal){}Signale ermöglichen den unfallfreien Betrieb mehrerer Züge in einem Gleissystem
 STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP                         :{BLACK}Einfahrsignal (Lichtsignal){}Zeigt grün, wenn im folgenden Block mindestens ein Ausfahrsignal grün zeigt. Andernfalls zeigt es rot
 STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP                          :{BLACK}Ausfahrsignal (Lichtsignal){}Verhält sich wie ein Blocksignal, gibt jedoch das Signal an Einfahr- und Kombinationssignale im vorherliegenden Block weiter
 STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP                         :{BLACK}Kombinationssignal (Lichtsignal){}Das Kombinationssignal ist gleichzeitig Aus- und Einfahrsignal. Somit werden umfangreiche Signalverschaltungen möglich
+STR_BUILD_SIGNAL_ELECTRIC_PROG_TOOLTIP                          :{BLACK}Programmierbare Lichtsignale{}Das programmierbare Signal ist ein Kombisignal, das in vielfältiger Weise programmiert werden kann
+STR_BUILD_SIGNAL_ELECTRIC_SPEED_TOOLTIP                         :{BLACK}Geschwindigkeitsbeschränkende Lichtsignale{}Das Signal legt die Höchstgeschwindigkeit für den passierenden Zug fest, bis dieser ein weiteres solches Signal passiert
 STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP                           :{BLACK}Pfadsignal (Lichtsignal){}Erlaubt mehreren Zügen gleichzeitig, einen Signalbereich zu befahren, sofern sie separate Gleisabschnitte belegen können. Normale Pfadsignale können von hinten durchfahren werden
 STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP                      :{BLACK}Einseitiges Pfadsignal (Lichtsignal):{}Erlaubt mehreren Zügen, einen Signalbereich zu befahren, sofern sie separate Gleisabschnitte belegen können. Einseitige Pfadsignale können nicht von hinten durchfahren werden
 STR_BUILD_SIGNAL_CONVERT_TOOLTIP                                :{BLACK}Signalumbau{}Wenn ausgewählt, werden bestehende Signale durch Anklicken zum ausgewählten Signaltyp umgebaut. Strg+Klick ändert die bestehende Bauform. Shift+Klick zeigt Kostenvoranschlag
@@ -1971,6 +2133,73 @@
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP          :{BLACK}Signalabstand verringern
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP          :{BLACK}Signalabstand erhöhen
 
+# Programmable Signals
+STR_PROGRAM_SIGNAL_TOOLTIP                                      :{BLACK}Programmierbares Signal
+
+STR_ERR_PROGSIG_INVALID_INSTRUCTION                             :{WHITE}Kann keinen Befehl nach einem Befehl mit einer ungültigen ID einfügen
+STR_ERR_PROGSIG_INVALID_OPCODE                                  :{WHITE}Kann keinen Befehl mit diesem OpCode einfügen
+STR_ERR_PROGSIG_NOT_THERE                                       :{WHITE}Hier ist kein programmierbares Signal
+STR_ERR_PROGSIG_INVALID_SIGNAL_STATE                            :{WHITE}Dieser Signalstatus ist ungültig
+STR_ERR_PROGSIG_INVALID_CONDITION                               :{WHITE}Diese Bedingung ist ungültig
+STR_ERR_PROGSIG_INVALID_CONDITION_FIELD                         :{WHITE}Diese Feld ist für diese Bedingung nicht gültig
+STR_ERR_PROGSIG_INVALID_COMPARATOR                              :{WHITE}Dieser Vergleich ist nicht gültig
+STR_ERR_PROGSIG_INVALID_SIGNAL                                  :{WHITE}Ungültiges Signal gewählt
+
+STR_PROGSIG_CAPTION                                             :{WHITE}Signal Programm
+STR_PROGSIG_COND_VARIABLE_TOOLTIP                               :{BLACK}Bedingung, mit der verglichen werden soll
+STR_PROGSIG_COND_COMPARATOR_TOOLTIP                             :{BLACK}Operator, der verwendet werden soll, um die Variable zu vergleichen
+STR_PROGSIG_COND_VALUE_TOOLTIP                                  :{BLACK}Wert, mit dem die Variable verglichen werden soll
+STR_PROGSIG_SIGNAL_STATE_TOOLTIP                                :{BLACK}Setze den Signalstatus
+STR_PROGSIG_COND_SET_SIGNAL                                     :{BLACK}Setze das Signal
+STR_PROGSIG_COND_SET_SIGNAL_TOOLTIP                             :{BLACK}Set the signal to be looked at
+STR_PROGSIG_GOTO_SIGNAL                                         :{BLACK}Gehe zum Signal
+STR_PROGSIG_GOTO_SIGNAL_TOOLTIP                                 :{BLACK}Gehe zu diesem Signal
+STR_PROGSIG_INSERT_TOOLTIP                                      :{BLACK}Füge einen Befehl ein
+STR_PROGSIG_REMOVE_TOOLTIP                                      :{BLACK}Entferne den gewählten Befehl
+
+STR_PROGSIG_REMOVE                                              :{BLACK}Entferne
+STR_PROGSIG_INSERT                                              :Einfügen
+STR_PROGSIG_INSERT_IF                                           :Bedingung
+STR_PROGSIG_INSERT_SET_SIGNAL                                   :Setze Signalstatus
+
+STR_PROGSIG_FIRST                                               :Start
+STR_PROGSIG_LAST                                                :Ende
+
+STR_PROGSIG_IF                                                  :Wenn {STRING} dann
+STR_PROGSIG_ELSE                                                :Andernfalls
+STR_PROGSIG_ENDIF                                               :Ende, falls
+
+STR_PROGSIG_SET_SIGNAL                                          :Mache Signal {STRING}
+
+STR_PROGSIG_COND_ALWAYS                                         :immer
+STR_PROGSIG_COND_NEVER                                          :nie
+STR_PROGSIG_COND_COMPARE                                        :{STRING} {STRING} {NUM}
+STR_PROGSIG_COND_SIGNAL_STATE                                   :Signalstatus
+STR_PROGSIG_CONDVAR_SIGNAL_STATE                                :{STRING} ist grün
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_SPECIFIED                      :spezifiziertes Signal
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_UNSPECIFIED                    :{RED}unspezifiziertes signal{STRING}
+STR_PROGSIG_CONDVAR_NUM_RED                                     :rote Signale
+STR_PROGSIG_CONDVAR_NUM_GREEN                                   :grüne signale
+
+STR_PROGSIG_CONDITION_VALUE_CAPT                                :{WHITE}Bedingungswert
+
+STR_ERROR_CAN_T_INSERT_INSTRUCTION                              :{WHITE}Kann den Befehl nicht einfügen
+STR_ERROR_CAN_T_MODIFY_INSTRUCTION                              :{WHITE}Kann den Befehl nicht ändern
+STR_ERROR_CAN_T_REMOVE_INSTRUCTION                              :{WHITE}Kann den Befehl nicht entfernen
+STR_ERROR_CAN_T_GOTO_UNDEFINED_SIGNAL                           :{WHITE}Kann nicht zu undefiniertem Signal gehen
+STR_ERROR_NOT_AN_EXIT_SIGNAL                                    :{WHITE}Kein Ausfahrsignal
+STR_ERROR_CAN_T_DEPEND_UPON_BIDIRECTIONAL_SIGNALS               :{WHITE}Kann bei Zweirichtungssignalen nicht bedingt abhängig sein
+STR_ERROR_INVALID_SIGNAL                                        :{WHITE}Ungültiges Signal
+
+STR_SPEEDSIG_CAPTION                                            :{WHITE}Geschwindigkeitsbegrenzung
+
+STR_SPEEDSIG_VALUE_NONE                                         :{WHITE}Keine Geschwindigkeitsbegrenzung
+STR_SPEEDSIG_VALUE                                              :{WHITE}{VELOCITY}
+STR_SPEEDSIG_CLEAR                                              :{BLACK}Leere
+STR_SPEEDSIG_CHANGE                                             :{BLACK}Ändere
+
+STR_ERROR_CAN_T_SET_SPEED                                       :{WHITE}Kann keine Geschwindigkeitsbegrenzung setzen
+
 # Bridge selection window
 STR_SELECT_RAIL_BRIDGE_CAPTION                                  :{WHITE}Eisenbahnbrücke auswählen
 STR_SELECT_ROAD_BRIDGE_CAPTION                                  :{WHITE}Straßenbrücke wählen
@@ -2001,6 +2230,7 @@
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY                :{BLACK}Lkw-Ladeplatz bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION               :{BLACK}Güterstraßenbahnhaltestelle bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um
 STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD                    :{BLACK}Aktiviere/Deaktiviere Einbahnstraßenbau
+STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAFFIC_LIGHT                    :{BLACK}Baue Ampeln
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE                      :{BLACK}Straßenbrücke bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE                   :{BLACK}Straßenbahnbrücke bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL                      :{BLACK}Straßentunnel bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um
@@ -2076,6 +2306,29 @@
 STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND                  :{BLACK}Land anheben. Shift schaltet zwischen Bauen und Kostenvoranschlag um
 STR_LANDSCAPING_LEVEL_LAND_TOOLTIP                              :{BLACK}Höhe ausgleichen. Shift schaltet zwischen Bauen und Kostenvoranschlag um
 STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND                           :{BLACK}Land für künftige Nutzung kaufen. Shift schaltet zwischen Bauen und Kostenvoranschlag um
+STR_LANDSCAPING_TOOLTIP_RULER_TOOL                              :{BLACK}Benutze ein virtuelles Lineal, um Distanz und Höhe zu messen
+
+# Copy Paste
+STR_COPY_PASTE_TOOLBAR                                          :{WHITE}Kopieren
+STR_COPY_PASTE_TOOLTIP                                          :{BLACK}Kopieren & Einfügen
+STR_COPY_PASTE_COPY_TOOLTIP                                     :{BLACK}Kopiert die gewählte Landschaft
+STR_COPY_PASTE_PASTE_TOOLTIP                                    :{BLACK}Fügt die zuvor kopierte Landschaft ein
+STR_COPY_PASTE_ROTATE_LEFT_TOOLTIP                              :{BLACK}Kopie um 90 Grad nach links drehen
+STR_COPY_PASTE_ROTATE_RIGHT_TOOLTIP                             :{BLACK}Kopie um 90 Grad nach rechts drehen
+STR_COPY_PASTE_VACANT_TERRAIN_TOOLTIP                           :{BLACK}Ob unbebautes Gelände wiederhergestellt werden soll
+STR_COPY_PASTE_LOAD_TOOLTIP                                     :{BLACK}Lädt eine Vorlage
+STR_COPY_PASTE_SAVE_TOOLTIP                                     :{BLACK}Speichert die momentane Selektion in eine Vorlage
+STR_COPY_PASTE_MIRROR_HORIZONTAL_TOOLTIP                        :{BLACK}Spiegelt die momentane Selektion an der horizontalen Achse
+STR_COPY_PASTE_MIRROR_VERTICAL_TOOLTIP                          :{BLACK}Spiegelt die momentane Selektion an der vertikalen Achse
+STR_COPY_PASTE_BULLDOZE_BEFORE_BUILD_TOOLTIP                    :{BLACK}Ob bebautes Gelände vor dem Einfügen geräumt werden soll
+STR_COPY_PASTE_TOGGLE_SIGNAL_DIRECTION_TOOLTIP                  :{BLACK}Dreht die Signalrichtung beim Einfügen um
+STR_COPY_PASTE_CONVERT_RAIL_TOOLTIP                             :{BLACK}Wandelt den Gleistyp beim Einfügen in den zuletzt benutzten um
+STR_COPY_PASTE_WITHOUT_RAIL_TOOLTIP                             :{BLACK}Ob Gleise mitkopiert werden sollen
+STR_COPY_PASTE_WITHOUT_ROAD_TOOLTIP                             :{BLACK}Ob Strassen mitkopiert werden sollen
+STR_COPY_PASTE_ONLY_OWN_TOOLTIP                                 :{BLACK}Ob nur eigene Objekte kopiert werden sollen
+
+STR_COPY_PASTE_PASTE_DISABLED                                   :{WHITE}Einfügen nicht erlaubt ...
+STR_CONFIG_PATCHES_CP_PASTE_SPEED                               :{LTBLUE}Einfügegeschwindigkeit im Mehrspielermodus (255 = aus): {ORANGE}{STRING}
 
 # Object construction window
 STR_OBJECT_BUILD_CAPTION                                        :{WHITE}Objektauswahl
@@ -2177,6 +2430,7 @@
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Gehört zur Gemeinde: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Keine
 STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaten: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_HEIGHT                       :{BLACK}Höhe: {LTBLUE}{NUM}
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Errichtet am: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stationsklasse: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stationstyp: {LTBLUE}{STRING}
@@ -2226,6 +2480,7 @@
 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD                        :Straße mit Bäumen
 STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT                     :Fahrzeugdepot
 STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING               :Bahnübergang
+STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_TRAFFIC_LIGHTS               :Straße mit Ampeln
 STR_LAI_ROAD_DESCRIPTION_TRAMWAY                                :Straßenbahn
 
 # Houses come directly from their building names
@@ -2254,8 +2509,10 @@
 # Industries come directly from their industry names
 
 STR_LAI_TUNNEL_DESCRIPTION_RAILROAD                             :Eisenbahntunnel
+STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_SIGNAL                      :Eisenbahntunnel mit Signalsimulation
 STR_LAI_TUNNEL_DESCRIPTION_ROAD                                 :Straßentunnel
 
+STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL                      :Eisenbahnbrücke mit Signalsimulation
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL                :Stahlhängebrücke
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL                    :Stahlträgerbrücke
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL                :Auslegerbrücke (Stahl)
@@ -2285,6 +2542,9 @@
 STR_ABOUT_VERSION                                               :{BLACK}OpenTTD Version {REV}
 STR_ABOUT_COPYRIGHT_OPENTTD                                     :{BLACK}OpenTTD {COPYRIGHT} 2002-2011 OpenTTD-Team
 
+# System time window
+STR_SYSTEM_TIME                                                 :{WHITE}Systemzeit
+
 # Save/load game/scenario
 STR_SAVELOAD_SAVE_CAPTION                                       :{WHITE}Spiel speichern
 STR_SAVELOAD_LOAD_CAPTION                                       :{WHITE}Spiel laden
@@ -2292,6 +2552,8 @@
 STR_SAVELOAD_LOAD_SCENARIO                                      :{WHITE}Szenario laden
 STR_SAVELOAD_LOAD_HEIGHTMAP                                     :{WHITE}Reliefkarte laden
 STR_SAVELOAD_SAVE_HEIGHTMAP                                     :{WHITE}Reliefkarte speichern
+STR_SAVELOAD_SAVE_COPY_PASTE_TEMPLATE                           :{WHITE}Vorlage speichern
+STR_SAVELOAD_LOAD_COPY_PASTE_TEMPLATE                           :{WHITE}Vorlage laden
 STR_SAVELOAD_HOME_BUTTON                                        :{BLACK}Hier klicken, um zum Standardverzeichnis für Spielstände zu gehen
 STR_SAVELOAD_BYTES_FREE                                         :{BLACK}{BYTES} frei
 STR_SAVELOAD_LIST_TOOLTIP                                       :{BLACK}Liste der Laufwerke, Verzeichnisse und gespeicherten Spiele
@@ -2308,6 +2570,10 @@
 STR_SAVELOAD_DETAIL_GRFSTATUS                                   :{SILVER}NewGRF: {WHITE}{STRING}
 
 STR_SAVELOAD_OSKTITLE                                           :{BLACK}Namen für den Spielstand eingeben
+STR_TEMPLATE_LOAD_FAILED                                        :{WHITE}Laden der Vorlage fehlgeschlagen{}{STRING}
+STR_TEMPLATE_SAVE_FAILED                                        :{WHITE}Speichern der Vorlage fehlgeschlagen{}{STRING}
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW                        :Vorlage wurde mit neuerer Version erstellt
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN                         :Vorlage ist ungültig
 
 # World generation
 STR_MAPGEN_WORLD_GENERATION_CAPTION                             :{WHITE}Welterstellung
@@ -2319,6 +2585,12 @@
 STR_MAPGEN_SNOW_LINE_HEIGHT                                     :{BLACK}Schneegrenze:
 STR_MAPGEN_SNOW_LINE_UP                                         :{BLACK}Schneegrenze um eine Stufe erhöhen
 STR_MAPGEN_SNOW_LINE_DOWN                                       :{BLACK}Schneegrenze um eine Stufe senken
+STR_MAPGEN_DESERT_AMOUNT                                        :{BLACK}Wüstenanteil:
+STR_MAPGEN_DESERT_AMOUNT_UP                                     :{BLACK}Erhöhe die Menge der Wüstenteile
+STR_MAPGEN_DESERT_AMOUNT_DOWN                                   :{BLACK}Verringere die Menge der Wüstenteile
+STR_MAPGEN_TREE_LINE_HEIGHT                                     :{BLACK}Baumwuchshöhe:
+STR_MAPGEN_TREE_LINE_UP                                         :{BLACK}Erhöhe die Baumwuchshöhe um eins
+STR_MAPGEN_TREE_LINE_DOWN                                       :{BLACK}Verringere die Baumwuchshöhe um eins
 STR_MAPGEN_RANDOM_SEED                                          :{BLACK}Zufallsstartwert:
 STR_MAPGEN_RANDOM_SEED_HELP                                     :{BLACK}Zufallsstartwert eingeben
 STR_MAPGEN_RANDOM                                               :{BLACK}Zufällig
@@ -2351,6 +2623,8 @@
 
 STR_MAPGEN_RANDOM_SEED_OSKTITLE                                 :{BLACK}Zufallsstartwert eingeben
 STR_MAPGEN_SNOW_LINE_QUERY_CAPT                                 :{WHITE}Höhe der Schneegrenze ändern
+STR_MAPGEN_DESERT_AMOUNT_QUERY_CAPT                             :{WHITE}Ändere den Wüstenanteil
+STR_MAPGEN_TREE_LINE_QUERY_CAPT                                 :{WHITE}Ändere die Baumwuchshöhe
 STR_MAPGEN_START_DATE_QUERY_CAPT                                :{WHITE}Startjahr ändern
 
 # SE Map generation
@@ -2558,12 +2832,35 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Großstadt)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Bevölkerung: {ORANGE}{COMMA}{BLACK}  Häuser: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passagiere letzten Monat: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Postsäcke letzten Monat: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Für Stadtwachstum benötigte Fracht:
+STR_TOWN_VIEW_GENERATED_CARGO_LAST_MONTH                        :{BLACK}Generierte Fracht des letzten Monats:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passagiere letzten Monat: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Postsäcke letzten Monat: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Für Stadtwachstum benötigte Fracht:
+STR_TOWN_VIEW_PASSENGERS_THIS_MONTH_MAX                         :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Benötigt für 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_MAIL_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Benötigt für 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_FOOD_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Benötigt für 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_WATER_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Benötigt für 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GOODS_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Benötigt für 100%: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} benötigt
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} im Winter benötigt
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} angeliefert im letzten Monat
+STR_TOWN_VIEW_GROWTH_RATE_LAST_MONTH                            :{BLACK}Wachstumsrate des letzten Monats: {ORANGE}{COMMA}{BLACK} %
+STR_TOWN_VIEW_GROWTH_SPEED_DISABLED                             :{RED}Städtewachstumsgeschwindigkeit auf 0 gesetzt. Kein Wachstum möglich!
+STR_TOWN_VIEW_TRANSPORTED_RATE_LAST_MONTH                       :{BLACK}Städtewachstumsbedingungen waren im letzten Monat erfüllt: {ORANGE}{COMMA} %
+STR_TOWN_VIEW_CARGO_DEMAND_LAST_MONTH                           :{BLACK}Größte Nachfrage im letzten Monat: {ORANGE}{STRING}
+STR_TOWN_VIEW_GROWTH_STANDARD                                   :Noch nicht berechnet
+STR_TOWN_VIEW_GROWTH_NEED_STATION                               :Weitere bediente Stationen
+STR_TOWN_VIEW_GROWTH_NEED_MORE_PASS                             :Mehr {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_MAIL                             :Mehr {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_FOOD                             :Mehr {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_WATER                            :Mehr {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_GOODS                            :Mehr {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_PASS                                  :{STRING} Bedienung
+STR_TOWN_VIEW_GROWTH_NEED_MAIL                                  :{STRING} Bedienung
+STR_TOWN_VIEW_GROWTH_NEED_FOOD                                  :{STRING} Bedienung
+STR_TOWN_VIEW_GROWTH_NEED_WATER                                 :{STRING} Bedienung
+STR_TOWN_VIEW_GROWTH_NEED_GOODS                                 :{STRING} Bedienung
+STR_TOWN_VIEW_GROWTH_SATISFIED                                  :Behalte diesen Zustand!
 STR_TOWN_VIEW_NOISE_IN_TOWN                                     :{BLACK}Lärmbelastung in der Stadt: {ORANGE}{COMMA}{BLACK}  Grenzwert: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CENTER_TOOLTIP                                    :{BLACK}Hauptansicht zur Stadt scrollen. Strg+Klick öffnet neue Zusatzansicht bei der Stadt
 STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON                            :{BLACK}Stadtverwaltung
@@ -2635,9 +2932,35 @@
 STR_STATION_VIEW_ACCEPTS_CARGO                                  :{BLACK}Akzeptiert: {WHITE}{STRING}
 
 STR_STATION_VIEW_RATINGS_BUTTON                                 :{BLACK}Bewertung
-STR_STATION_VIEW_RATINGS_TOOLTIP                                :{BLACK}Stationsbewertung anzeigen
-STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Örtliche Bewertung der Dienstleistungen:
+STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Monatliche Versorgung und lokale Bewertung:
 STR_STATION_VIEW_CARGO_RATING                                   :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA}%)
+STR_STATION_VIEW_CARGO_SUPPLY_RATING                            :{WHITE}{STRING}: {YELLOW}{COMMA} / {STRING} ({COMMA}%)
+
+STR_STATION_VIEW_DEPARTURES_BUTTON                              :{BLACK}Abfahrtszeiten
+STR_STATION_VIEW_DEPARTURES_TOOLTIP                             :{BLACK}Zeige Liste der Abfahrtszeiten
+
+STR_STATION_VIEW_GROUP                                          :{BLACK}Gruppe mit
+STR_STATION_VIEW_WAITING_STATION                                :Station: Wartend
+STR_STATION_VIEW_WAITING_AMOUNT                                 :Menge: Wartend
+STR_STATION_VIEW_PLANNED_STATION                                :Station: Geplant
+STR_STATION_VIEW_PLANNED_AMOUNT                                 :Menge: Geplant
+STR_STATION_VIEW_FROM                                           :{YELLOW}{SHORTCARGO} von {STATION}
+STR_STATION_VIEW_VIA                                            :{YELLOW}{SHORTCARGO} über {STATION}
+STR_STATION_VIEW_TO                                             :{YELLOW}{SHORTCARGO} nach {STATION}
+STR_STATION_VIEW_FROM_ANY                                       :{RED}{SHORTCARGO} von unbekannter Station
+STR_STATION_VIEW_TO_ANY                                         :{RED}{SHORTCARGO} zu irgendeiner Station
+STR_STATION_VIEW_VIA_ANY                                        :{RED}{SHORTCARGO} über irgendeine Station
+STR_STATION_VIEW_FROM_HERE                                      :{GREEN}{SHORTCARGO} von dieser Station
+STR_STATION_VIEW_VIA_HERE                                       :{GREEN}{SHORTCARGO} an dieser Station haltend
+STR_STATION_VIEW_TO_HERE                                        :{GREEN}{SHORTCARGO} zu dieser Station
+STR_STATION_VIEW_NONSTOP                                        :{YELLOW}{SHORTCARGO} Non-Stop
+
+STR_STATION_VIEW_GROUP_S_V_D                                    :Von-Über-Nach
+STR_STATION_VIEW_GROUP_S_D_V                                    :Von-Nach-Über
+STR_STATION_VIEW_GROUP_V_S_D                                    :Über-Von-Nach
+STR_STATION_VIEW_GROUP_V_D_S                                    :Über-Nach-Von
+STR_STATION_VIEW_GROUP_D_S_V                                    :Nach-Von-Über
+STR_STATION_VIEW_GROUP_D_V_S                                    :Nach-Über-Von
 
 ############ range for rating starts
 STR_CARGO_RATING_APPALLING                                      :Furchtbar
@@ -2660,6 +2983,79 @@
 
 STR_STATION_VIEW_RENAME_STATION_CAPTION                         :Station/Ladeplatz umbenennen
 
+# Departures window
+STR_DEPARTURES_CAPTION                                          :{WHITE}{STATION} Aktuelle Reiseinformationen
+STR_DEPARTURES_CAPTION_WAYPOINT                                 :{WHITE}{WAYPOINT} Aktuelle Reiseinformationen
+STR_DEPARTURES_DEPARTURES                                       :{BLACK}{TINYFONT}Ab
+STR_DEPARTURES_ARRIVALS                                         :{BLACK}{TINYFONT}An
+STR_DEPARTURES_VIA_BUTTON                                       :{BLACK}{TINYFONT}über
+STR_DEPARTURES_DEPARTURES_TOOLTIP                               :{BLACK}Zeige fahrplanmäßige Abfahrt
+STR_DEPARTURES_ARRIVALS_TOOLTIP                                 :{BLACK}Zeige fahrplanmäßige Ankunft
+STR_DEPARTURES_VIA_TOOLTIP                                      :{BLACK}Zeige Fahrzeuge die hier fahrplanmäßig nicht halten
+STR_DEPARTURES_NONE_SELECTED                                    :{ORANGE}Keine Fahrplaninformationen wurden abgefragt.
+STR_DEPARTURES_EMPTY                                            :{ORANGE}Zurzeit fahren von hier keine fahrplanmäßigen Fahrzeuge ab.
+STR_DEPARTURES_TIME                                             :{ORANGE}{DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_TIME_DEP                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TIME_ARR                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {RED}{DOWNARROW}
+STR_DEPARTURES_TIME_BOTH                                        :{ORANGE}{1:DATE_WALLCLOCK_TINY} {RED}{DOWNARROW} {ORANGE}{0:DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TERMINUS                                         :{ORANGE}{STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA_STATION                             :{ORANGE}{STATION}{STRING} über {STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA                                     :{ORANGE}{STATION}{STRING} über
+STR_DEPARTURES_VIA                                              :{ORANGE}über {STATION}{STRING}
+STR_DEPARTURES_TOC                                              :{ORANGE}{COMPANY}
+STR_DEPARTURES_GROUP                                            :{ORANGE}{GROUP}
+STR_DEPARTURES_VEH                                              :{ORANGE}{VEHICLE}
+STR_DEPARTURES_CALLING_AT                                       :{TINYFONT}{ORANGE}Hält in:
+STR_DEPARTURES_CALLING_AT_LARGE                                 :{ORANGE}Hält in:
+STR_DEPARTURES_CALLING_AT_FIRST_STATION                         :{STATION}
+STR_DEPARTURES_CALLING_AT_STATION                               :{STRING}, {STATION}
+STR_DEPARTURES_CALLING_AT_LAST_STATION                          :{STRING} und {STATION}
+STR_DEPARTURES_CALLING_AT_LIST                                  :{TINYFONT}{ORANGE}{STRING}.
+STR_DEPARTURES_CALLING_AT_LIST_LARGE                            :{ORANGE}{STRING}.
+
+STR_DEPARTURES_TYPE_TRAIN                                       :{ORANGE}{TRAIN}
+STR_DEPARTURES_TYPE_TRAIN_SILVER                                :{SILVER}{TRAIN}
+STR_DEPARTURES_TYPE_BUS                                         :{ORANGE}{BUS}
+STR_DEPARTURES_TYPE_BUS_SILVER                                  :{SILVER}{BUS}
+STR_DEPARTURES_TYPE_LORRY                                       :{ORANGE}{LORRY}
+STR_DEPARTURES_TYPE_LORRY_SILVER                                :{SILVER}{LORRY}
+STR_DEPARTURES_TYPE_PLANE                                       :{ORANGE}{PLANE}
+STR_DEPARTURES_TYPE_PLANE_SILVER                                :{SILVER}{PLANE}
+STR_DEPARTURES_TYPE_SHIP                                        :{ORANGE}{SHIP}
+STR_DEPARTURES_TYPE_SHIP_SILVER                                 :{SILVER}{SHIP}
+
+STR_DEPARTURES_STATION_NONE                                     :
+STR_DEPARTURES_STATION_PORT                                     :{ORANGE} {SHIP}
+STR_DEPARTURES_STATION_AIRPORT                                  :{ORANGE} {PLANE}
+STR_DEPARTURES_STATION_PORTAIRPORT                              :{ORANGE} {SHIP} {PLANE}
+
+############ possible statuses start
+STR_DEPARTURES_ON_TIME                                          :{GREEN}Pünktlich
+STR_DEPARTURES_ARRIVED                                          :{GREEN}Angekommen
+STR_DEPARTURES_DELAYED                                          :{YELLOW}Verspätet
+STR_DEPARTURES_EXPECTED                                         :{YELLOW}Wird erwartet um {DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_CANCELLED                                        :{RED}Fällt aus
+
+############ config settings
+STR_CONFIG_SETTING_DEPARTUREBOARDS                              :{ORANGE}Abfahrtszeiten
+STR_CONFIG_MAX_DEPARTURES                                       :{LTBLUE}Zeige mindestens {ORANGE}{STRING}{LTBLUE} Abfahrtszeiten an jeder Station
+STR_CONFIG_MAX_DEPARTURE_TIME                                   :{LTBLUE}Zeige Abfahrtszeiten mindestens {ORANGE}{STRING}{LTBLUE} Tage im Vorraus
+STR_CONFIG_DEPARTURE_CALC_FREQUENCY                             :{LTBLUE}Berechne Abfahrtszeiten jede {ORANGE}{STRING}{LTBLUE} Ticks
+STR_CONFIG_DEPARTURE_VEHICLE_NAME                               :{LTBLUE}Zeige Fahrzeugname mit Abfahrtszeit: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_GROUP_NAME                                 :{LTBLUE}Zeige Fahrzeuggruppenname mit Abfahrtszeit: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_COMPANY_NAME                               :{LTBLUE}Zeige Firmenname mit Abfahrtszeit: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_VEHICLE_TYPE                               :{LTBLUE}Zeige Fahrzeugsymbol mit Abfahrtszeit: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_VEHICLE_COLOR                              :{LTBLUE}Zeige Fahrzeugsymbol in silber mit Abfahrtszeit: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_LARGER_FONT                                :{LTBLUE}Benutze größere Schriftgröße für weitere Halte in der Abfahrtszeitenliste: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_DESTINATION_TYPE                           :{LTBLUE}Zeige Symbole für Ziele die Häfen oder Flughäfen sind: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_SHOW_BOTH                                  :{LTBLUE}Zeige Ankunfts- und Abfahrtszeiten in der selben Zeile: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_ONLY_PASSENGERS                            :{LTBLUE}Zeige nur Zeiten für Fahrzeuge, die Passagiere transportieren: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_CONDITIONALS                               :{LTBLUE}Behandle vertauschte Reihenfolge mit: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_CONDITIONALS_1                             :gebe sie auf
+STR_CONFIG_DEPARTURE_CONDITIONALS_2                             :nehme an, sie werden wahrgenommen
+STR_CONFIG_DEPARTURE_CONDITIONALS_3                             :nehme an, sie werden nicht wahrgenommen
+STR_CONFIG_DEPARTURE_SHOW_ALL_STOPS                             :{LTBLUE}Zeige alle Halte, egal ob geladen oder entladen wird: {ORANGE}{STRING}
+
 # Waypoint/buoy view window
 STR_WAYPOINT_VIEW_CAPTION                                       :{WHITE}{WAYPOINT}
 STR_WAYPOINT_VIEW_CENTER_TOOLTIP                                :{BLACK}Hauptansicht auf den Wegpunkt zentrieren. Strg+Klick öffnet neue Zusatzansicht beim Wegpunkt
@@ -2685,6 +3081,8 @@
 STR_FINANCES_SECTION_AIRCRAFT_INCOME                            :{GOLD}Einnahmen Flugzeuge
 STR_FINANCES_SECTION_SHIP_INCOME                                :{GOLD}Einnahmen Schiffe
 STR_FINANCES_SECTION_LOAN_INTEREST                              :{GOLD}Kreditzinsen
+STR_FINANCES_SECTION_INFRASTRUCTURE_COSTS                       :{GOLD}Kosten für gemeinsame Nutzung von Infrastruktur
+STR_FINANCES_SECTION_INFRASTRUCTURE_INCOME                      :{GOLD}Einkommen von gemeinsamer Nutzung von Infrastruktur
 STR_FINANCES_SECTION_OTHER                                      :{GOLD}Sonstiges
 STR_FINANCES_NEGATIVE_INCOME                                    :{BLACK}-{CURRENCY}
 STR_FINANCES_POSITIVE_INCOME                                    :{BLACK}+{CURRENCY}
@@ -2720,6 +3118,11 @@
 STR_COMPANY_VIEW_RELOCATE_HQ                                    :{BLACK}Verlegen
 STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS                  :{BLACK}Errichte Firmensitz für 1% des Firmenwertes an anderer Stelle neu. Shift+Klick zeigt einen Kostenvoranschlag
 
+STR_COMPANY_PROFILE_LOAD_BUTTON                                 :{BLACK}Lade ein Profil
+STR_COMPANY_PROFILE_LOAD_TOOLTIP                                :{BLACK}Lade ein Firmenprofil
+STR_COMPANY_PROFILE_SAVE_BUTTON                                 :{BLACK}Speichere das Profil
+STR_COMPANY_PROFILE_SAVE_TOOLTIP                                :{BLACK}Speichere das aktuelle Firmenprofil
+
 STR_COMPANY_VIEW_NEW_FACE_BUTTON                                :{BLACK}Neues Gesicht
 STR_COMPANY_VIEW_NEW_FACE_TOOLTIP                               :{BLACK}Neues Portrait für Manager aussuchen
 STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON                           :{BLACK}Farbschema
@@ -2826,6 +3229,9 @@
 
 STR_GROUP_RENAME_CAPTION                                        :{BLACK}Gruppe umbenennen
 
+STR_GROUP_PROFIT_THIS_YEAR                                      :{BLACK}Gewinn dieses Jahres: {CURRENCY}
+STR_GROUP_PROFIT_LAST_YEAR                                      :{BLACK}Gewinn des letzten Jahres: {CURRENCY}
+
 # Build vehicle window
 STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION                              :Neues Schienenfahrzeug
 STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION                            :Neue elektrische Schienenfahrzeuge
@@ -3057,15 +3463,30 @@
 STR_VEHICLE_STATUS_LEAVING                                      :{LTBLUE}Abfahrt
 STR_VEHICLE_STATUS_CRASHED                                      :{RED}Unfall!
 STR_VEHICLE_STATUS_BROKEN_DOWN                                  :{RED}Panne
+STR_VEHICLE_STATUS_BROKEN_DOWN_VEL                              :{RED}Panne - {STRING}, {LTBLUE} {VELOCITY}
 STR_VEHICLE_STATUS_STOPPED                                      :{RED}Angehalten
+STR_VEHICLE_STATUS_TRAIN_STOPPING                               :{RED}Bremst
 STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL                           :{RED}Halte an, {VELOCITY}
 STR_VEHICLE_STATUS_TRAIN_NO_POWER                               :{RED}Keine Energie
 STR_VEHICLE_STATUS_TRAIN_STUCK                                  :{ORANGE}Warte auf freie Wege
 
+STR_BREAKDOWN_TYPE_CRITICAL                                     :Technischer Fehler
+STR_BREAKDOWN_TYPE_EM_STOP                                      :Nothalt
+STR_BREAKDOWN_TYPE_LOW_SPEED                                    :Maximal {VELOCITY}
+STR_BREAKDOWN_TYPE_LOW_POWER                                    :{COMMA}% Leistung
+STR_BREAKDOWN_TYPE_DEPOT                                        :Steuert {STATION} für Reparaturarbeiten an
+STR_BREAKDOWN_TYPE_LANDING                                      :Steuert {STATION} für eine Notlandung an
+STR_ERROR_TRAIN_TOO_HEAVY                                       :{WHITE}{VEHICLE} ist zu schwer
+
+STR_VEHICLE_STATUS_HEADING_FOR_STATION                          :{LTBLUE}Fährt nach {STATION}
 STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL                      :{LTBLUE}Unterwegs nach {STATION}, {VELOCITY}
+STR_VEHICLE_STATUS_NO_ORDERS                                    :{LTBLUE}Keine Aufträge
 STR_VEHICLE_STATUS_NO_ORDERS_VEL                                :{LTBLUE}Keine Aufträge, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT                         :{LTBLUE}Fährt über {WAYPOINT}
 STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL                     :{LTBLUE}Fahre zu {WAYPOINT}, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_DEPOT                            :{ORANGE}Fährt zu {DEPOT}
 STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL                        :{ORANGE}Fährt zu {DEPOT}, {VELOCITY}
+STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE                    :{LTBLUE}Wird gewartet in {DEPOT}
 STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL                :{LTBLUE}Wartung in {DEPOT}, {VELOCITY}
 
 # Vehicle stopped/started animations
@@ -3084,6 +3505,11 @@
 STR_VEHICLE_DETAILS_AIRCRAFT_RENAME                             :{BLACK}Flugzeugname
 
 STR_VEHICLE_INFO_AGE_RUNNING_COST_YR                            :{BLACK}Alter: {LTBLUE}{STRING}{BLACK}   Betriebskosten: {LTBLUE}{CURRENCY}/Jahr
+
+STR_RUNNING                                                     :{LTBLUE}Fährt
+STR_NEED_REPAIR                                                 :{ORANGE}Zug muss repariert werden - Höchstgeschwindigkeit reduziert auf {VELOCITY}
+STR_CURRENT_STATUS                                              :{BLACK}Aktueller Status: {STRING}
+
 # The next two need to stay in this order
 STR_VEHICLE_INFO_AGE                                            :{COMMA} Jahr{P "" e} ({COMMA})
 STR_VEHICLE_INFO_AGE_RED                                        :{RED}{COMMA} Jahr{P "" e} ({COMMA})
@@ -3115,7 +3541,9 @@
 
 # Extra buttons for train details windows
 STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE                :{LTBLUE}{ENGINE}{BLACK}   Gebaut: {LTBLUE}{NUM}{BLACK}  Wert: {LTBLUE}{CURRENCY}
-STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE                           :{LTBLUE}{ENGINE}{BLACK} Wert: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE_AND_SPEED      :{LTBLUE}{ENGINE}{BLACK}   Gebaut: {LTBLUE}{NUM}{BLACK} Wert: {LTBLUE}{CURRENCY} {BLACK}Höchstgeschwindigkeit: {LTBLUE}{VELOCITY}
+STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE                           :{LTBLUE}{ENGINE}{BLACK}   Wert: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_AND_SPEED                 :{LTBLUE}{ENGINE}{BLACK}   Wert: {LTBLUE}{CURRENCY} {BLACK}Höchstgeschwindigkeit: {LTBLUE}{VELOCITY}
 
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT                   :{BLACK}Frachtkapazität dieses Zuges:
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY                        :{LTBLUE}{CARGO} ({SHORTCARGO})
@@ -3138,10 +3566,13 @@
 
 # Vehicle refit
 STR_REFIT_CAPTION                                               :{WHITE}{VEHICLE} (Umrüsten)
+STR_REFIT_VEHICLE_SELECTION_TITLE                               :{GOLD}Wähle die Fahrzeuge, die umgerüstet werden sollen:
+STR_REFIT_VEHICLE_SELECT_ALL                                    :{BLACK}{TINYFONT}Alle
+STR_REFIT_VEHICLE_SELECT_ALL_TOOLTIP                            :{BLACK}Wähle den ganzen Zug
 STR_REFIT_TITLE                                                 :{GOLD}Neue Fracht wählen:
 STR_REFIT_NEW_CAPACITY_COST_OF_REFIT                            :{BLACK}Neue Kapazität: {GOLD}{CARGO}{}{BLACK}Kosten der Umrüstung: {GOLD}{CURRENCY}
 STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT                   :{BLACK}Neue Kapazität: {GOLD}{CARGO}, {GOLD}{CARGO}{}{BLACK}Kosten für Umrüstung: {GOLD}{CURRENCY}
-STR_REFIT_SELECT_VEHICLES_TOOLTIP                               :{BLACK}Fahrzeug zum Umrüsten auswählen. Ziehen mit der Maus erlaubt das Auswählen mehrerer Fahrzeuge gleichzeitig. Freifläche anklicken wählt das gesamte Fahrzeug aus. Strg+Klick wählt das Fahrzeug und alle nachfolgenden aus.
+STR_REFIT_SELECT_VEHICLES_TOOLTIP                               :{BLACK}Wähle die Fahrzeuge, die umgerüstet werden sollen. Das Ziehen der Maus wählt mehrere Fahrzeuge aus. Das Klicken auf freien Raum wählt den ganzen Zug aus. Strg+Klick wählt das Fahrzeug und alle folgenden Fahrzeuge aus.
 
 STR_REFIT_TRAIN_LIST_TOOLTIP                                    :{BLACK}Die Fracht auswählen, die der Zug befördern soll
 STR_REFIT_ROAD_VEHICLE_LIST_TOOLTIP                             :{BLACK}Die Fracht auswählen, die das Straßenfahrzeug befördern soll
@@ -3326,6 +3757,7 @@
 STR_TIMETABLE_AND_TRAVEL_FOR                                    :und {STRING} lang unterwegs
 STR_TIMETABLE_DAYS                                              :{COMMA} Tag{P "" e}
 STR_TIMETABLE_TICKS                                             :{COMMA} Tick{P "" s}
+STR_TIMETABLE_MINUTES                                           :{COMMA} Minute{P "" n}
 
 STR_TIMETABLE_TOTAL_TIME                                        :{BLACK}Dieser Fahrplan benötigt {STRING}
 STR_TIMETABLE_TOTAL_TIME_INCOMPLETE                             :{BLACK}Dieser Fahrplan benötigt mindestens {STRING} (nicht alle geplant)
@@ -3340,7 +3772,7 @@
 STR_TIMETABLE_STARTING_DATE_TOOLTIP                             :{BLACK}Wähle ein Anfangsdatum für den Fahrplan
 
 STR_TIMETABLE_CHANGE_TIME                                       :{BLACK}Zeit ändern
-STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Zeitrahmen für den markierten Auftrag ändern
+STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Ändere die Dauer, die der hervorgehobene Auftrag benötigt. Strg+Klick ändert die Dauer von allen Aufträgen auf einmal.
 
 STR_TIMETABLE_CLEAR_TIME                                        :{BLACK}Zeit löschen
 STR_TIMETABLE_CLEAR_TIME_TOOLTIP                                :{BLACK}Zeitrahmen für den markierten Auftrag löschen
@@ -3351,6 +3783,9 @@
 STR_TIMETABLE_AUTOFILL                                          :{BLACK}Erfassen
 STR_TIMETABLE_AUTOFILL_TOOLTIP                                  :{BLACK}Zeiten automatisch bei der nächsten Fahrt eintragen (Mit Strg+Klick wird versucht, die aktuellen Wartezeiten beizubehalten)
 
+STR_TIMETABLE_AUTOMATE                                          :{BLACK}Automatisch
+STR_TIMETABLE_AUTOMATE_TOOLTIP                                  :{BLACK}Führe den Fahrplan automatisch, indem die Dauer der Aufträge jede Runde angepasst werden. Klicke nochmal um dies wieder zu deaktivieren und die aktuellen Werte beizubehalten. Strg+ Klick löscht alle Werte.
+
 STR_TIMETABLE_EXPECTED                                          :{BLACK}Voraussichtlich
 STR_TIMETABLE_SCHEDULED                                         :{BLACK}Geplant
 STR_TIMETABLE_EXPECTED_TOOLTIP                                  :{BLACK}Umschalten zwischen erwarteter Ankunftszeit und Fahrplan
@@ -3366,6 +3801,8 @@
 STR_DATE_DAY_TOOLTIP                                            :{BLACK}Tag auswählen
 STR_DATE_MONTH_TOOLTIP                                          :{BLACK}Monat auswählen
 STR_DATE_YEAR_TOOLTIP                                           :{BLACK}Jahr auswählen
+STR_DATE_MINUTES_DAY_TOOLTIP                                    :{BLACK}Wähle die Minute
+STR_DATE_MINUTES_MONTH_TOOLTIP                                  :{BLACK}Wähle die Stunde
 
 
 # AI debug window
@@ -3443,6 +3880,10 @@
 STR_INCOME_FLOAT_INCOME                                         :{GREEN}Einnahmen: {CURRENCY}
 STR_FEEDER_TINY                                                 :{TINYFONT}{YELLOW}Umladen: {CURRENCY}
 STR_FEEDER                                                      :{YELLOW}Umladen: {CURRENCY}
+STR_FEEDER_INCOME_TINY                                          :{TINYFONT}{YELLOW}Umladen: {CURRENCY}{WHITE} / {GREEN}Einkommen: {CURRENCY}
+STR_FEEDER_INCOME                                               :{YELLOW}Umladen: {CURRENCY}{WHITE} / {GREEN}Einkommen: {CURRENCY}
+STR_FEEDER_COST_TINY                                            :{TINYFONT}{YELLOW}Umladen: {CURRENCY}{WHITE} / {RED}Kosten: {CURRENCY}
+STR_FEEDER_COST                                                 :{YELLOW}Umladen: {CURRENCY}{WHITE} / {RED}Kosten: {CURRENCY}
 STR_MESSAGE_ESTIMATED_COST                                      :{WHITE}Geschätzte Kosten: {CURRENCY}
 STR_MESSAGE_ESTIMATED_INCOME                                    :{WHITE}Geschätzte Einnahmen: {CURRENCY}
 
@@ -3462,6 +3903,11 @@
 STR_GAME_SAVELOAD_NOT_AVAILABLE                                 :<nicht verfügbar>
 STR_WARNING_LOADGAME_REMOVED_TRAMS                              :{WHITE}Spiel wurde in einer Version ohne Straßenbahnunterstützung gespeichert. Alle Straßenbahnen wurden entfernt
 
+STR_PROFILE_LOAD_ERROR                                          :{WHITE}Kann das Profil nicht laden
+STR_PROFILE_SAVE_ERROR                                          :{WHITE}Kann das Profil nicht laden
+STR_PROFILE_FACE_ERROR                                          :{WHITE}Ungültiges Managergesicht
+STR_PROFILE_COLOUR_ERROR                                        :{WHITE}Ungültige Firmenfarbe
+
 # Map generation messages
 STR_ERROR_COULD_NOT_CREATE_TOWN                                 :{WHITE}Spielfeldgenerierung wurde abgebrochen...{}... kein geeigneter Platz für eine Stadt gefunden
 STR_ERROR_NO_TOWN_IN_SCENARIO                                   :{WHITE}... in diesem Szenario gibt es keine Stadt
@@ -3478,6 +3924,7 @@
 
 STR_WARNING_HEIGHTMAP_SCALE_CAPTION                             :{WHITE}Skalierungswarnung
 STR_WARNING_HEIGHTMAP_SCALE_MESSAGE                             :{YELLOW}Zu starke Skalierung des Spielfeldes wird nicht empfohlen. Generierung dennoch fortsetzen?
+STR_MAPGEN_TOO_MANY_TILES_MESSAGE                               :{YELLOW}Zu viele Felder auf der Karte. Maximal mögliche Anzahl der Teile ist {NUM}, gewählt sind {NUM}
 
 # Soundset messages
 STR_WARNING_FALLBACK_SOUNDSET                                   :{WHITE}Nur ein Notbehelfs-Soundset wurde gefunden. Sounds können bei Bedarf als Erweiterung heruntergeladen werden (siehe Hauptmenü)
@@ -3522,6 +3969,7 @@
 STR_ERROR_ALREADY_AT_SEA_LEVEL                                  :{WHITE}... ist bereits auf Meereshöhe
 STR_ERROR_TOO_HIGH                                              :{WHITE}... zu hoch
 STR_ERROR_ALREADY_LEVELLED                                      :{WHITE}... ist schon flach
+STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND                      :{WHITE}Danach wäre die Brücke zu hoch
 
 # Company related errors
 STR_ERROR_CAN_T_CHANGE_COMPANY_NAME                             :{WHITE}Firmenname kann nicht geändert werden...
@@ -3660,6 +4108,7 @@
 # Rail construction errors
 STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION                          :{WHITE}Unmögliche Gleisverbindung
 STR_ERROR_MUST_REMOVE_SIGNALS_FIRST                             :{WHITE}Signal muß zuerst entfernt werden
+STR_ERROR_MUST_REMOVE_EXIT_SIGNALS_FIRST                        :{WHITE}Das Ausfahrsignal muss zuerst entfernt werden
 STR_ERROR_NO_SUITABLE_RAILROAD_TRACK                            :{WHITE}Keine geeigneten Gleise
 STR_ERROR_MUST_REMOVE_RAILROAD_TRACK                            :{WHITE}Gleise müssen erst abgerissen werden
 STR_ERROR_CROSSING_ON_ONEWAY_ROAD                               :{WHITE}Einbahnstraße oder blockierter Weg
@@ -3674,6 +4123,8 @@
 
 STR_ERROR_CAN_T_CONVERT_RAIL                                    :{WHITE}Gleistyp kann hier nicht verändert werden...
 
+STR_ERROR_SIGNAL_CHANGES                                        :{WHITE}Anzahl der programmierbaren Signale überschreitet das Limit
+
 # Road construction errors
 STR_ERROR_MUST_REMOVE_ROAD_FIRST                                :{WHITE}Straße muss erst entfernt werden
 STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION                      :{WHITE}... Einbahnstraßen können keine Abzweigung haben
@@ -3681,6 +4132,13 @@
 STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE                              :{WHITE}Straßenbahngleise können hier nicht gebaut werden...
 STR_ERROR_CAN_T_REMOVE_ROAD_FROM                                :{WHITE}Diese Straße kann nicht entfernt werden...
 STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM                             :{WHITE}Straßenbahngleise können hier nicht entfernt werden...
+STR_ERROR_CAN_T_REMOVE_TRAFFIC_LIGHTS_FROM                      :{WHITE}Kann die Ampeln nicht entfernen...
+STR_ERROR_MUST_REMOVE_TRAFFIC_LIGHTS_FIRST                      :{WHITE}... muss zuerst die Ampeln entfernen
+STR_ERROR_TRAFFIC_LIGHT_CONSIST_TOO_BIG                         :{WHITE}... Ampel-Wert ist zu groß
+STR_ERROR_CAN_T_PLACE_TRAFFIC_LIGHTS                            :{WHITE}Kann die Ampeln nicht aufstellen...
+STR_ERROR_CAN_ONLY_BE_PLACED_ON_ROAD_JUNCTIONS                  :{WHITE}... können nur auf Straßenkreuzungen platziert werden
+STR_ERROR_BUILDING_TRAFFIC_LIGHTS_DISABLED                      :{WHITE}... das Bauen von Ampeln ist deaktiviert. Aktiviere es in "Erweiterte Einstellungen" -> "Konstruktion" -> "Ampeln"
+STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS              :{WHITE}... das Bauen von Ampeln auf städtischen Kreuzungen ist deaktiviert. Aktiviere es in "Erweiterte Einstellungen" -> "Konstruktion" -> "Ampeln"
 STR_ERROR_THERE_IS_NO_ROAD                                      :{WHITE}...hier ist keine Straße
 STR_ERROR_THERE_IS_NO_TRAMWAY                                   :{WHITE}...hier ist kein Straßenbahngleis
 
@@ -3700,6 +4158,7 @@
 STR_ERROR_TREE_ALREADY_HERE                                     :{WHITE}... hier sind bereits Bäume
 STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE                      :{WHITE}... falsches Gelände für die Baumart
 STR_ERROR_CAN_T_PLANT_TREE_HERE                                 :{WHITE}Baum kann hier nicht gepflanzt werden...
+STR_ERROR_TREE_ABOVE_TREE_LINE                                  :{WHITE}... Feld ist über der Baumwuchslinie.
 
 # Bridge related errors
 STR_ERROR_CAN_T_BUILD_BRIDGE_HERE                               :{WHITE}Brücke kann hier nicht gebaut werden...
@@ -3707,6 +4166,7 @@
 STR_ERROR_CAN_T_START_AND_END_ON                                :{WHITE}Anfang und Ende können nicht im selben Feld liegen
 STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT                           :{WHITE}Brückenköpfe nicht auf einer Höhe
 STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN                            :{WHITE}Die Brücke ist zu niedrig für diese Umgebung
+STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN                           :{WHITE}Die Brücke ist zu hoch für diese Umgebung.
 STR_ERROR_START_AND_END_MUST_BE_IN                              :{WHITE}Anfang und Ende müssen auf einer Linie liegen
 STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH                              :{WHITE}... Brücke muss an beiden Seiten auf Land enden
 STR_ERROR_BRIDGE_TOO_LONG                                       :{WHITE}... Brücke zu lang
@@ -4211,6 +4671,11 @@
 STR_FORMAT_DATE_LONG                                            :{STRING} {STRING} {NUM}
 STR_FORMAT_DATE_ISO                                             :{2:NUM}-{1:STRING}-{0:STRING}
 
+STR_FORMAT_DATE_MINUTES                                         :{0:STRING}:{1:STRING}
+STR_FORMAT_DATE_MINUTES_WITH_Y                                  :{0:STRING}:{1:STRING} / {2:NUM}
+STR_FORMAT_DATE_MINUTES_WITH_YM                                 :{0:STRING}:{1:STRING} / {2:DATE_SHORT}
+STR_FORMAT_DATE_MINUTES_WITH_YMD                                :{0:STRING}:{1:STRING} / {2:DATE_LONG}
+
 STR_FORMAT_BUOY_NAME                                            :{TOWN} Boje
 STR_FORMAT_BUOY_NAME_SERIAL                                     :{TOWN} Boje #{COMMA}
 STR_FORMAT_COMPANY_NUM                                          :(Firma {COMMA})
@@ -4235,10 +4700,18 @@
 STR_SAVEGAME_NAME_SPECTATOR                                     :Zuschauer, {1:STRING}
 
 # Viewport strings
+STR_VIEWPORT_TOWN_POP_VERY_POOR_RATING                          :{WHITE}{TOWN} {RED}({COMMA})
+STR_VIEWPORT_TOWN_POP_MEDIOCRE_RATING                           :{WHITE}{TOWN} {ORANGE}({COMMA})
+STR_VIEWPORT_TOWN_POP_GOOD_RATING                               :{WHITE}{TOWN} {YELLOW}({COMMA})
 STR_VIEWPORT_TOWN_POP                                           :{WHITE}{TOWN} ({COMMA})
+STR_VIEWPORT_TOWN_POP_EXCELLENT_RATING                          :{WHITE}{TOWN} {GREEN}({COMMA})
 STR_VIEWPORT_TOWN                                               :{WHITE}{TOWN}
 STR_VIEWPORT_TOWN_TINY_BLACK                                    :{TINYFONT}{BLACK}{TOWN}
+STR_VIEWPORT_TOWN_TINY_VERY_POOR_RATING                         :{TINYFONT}{RED}{TOWN}
+STR_VIEWPORT_TOWN_TINY_MEDIOCRE_RATING                          :{TINYFONT}{ORANGE}{TOWN}
+STR_VIEWPORT_TOWN_TINY_GOOD_RATING                              :{TINYFONT}{YELLOW}{TOWN}
 STR_VIEWPORT_TOWN_TINY_WHITE                                    :{TINYFONT}{WHITE}{TOWN}
+STR_VIEWPORT_TOWN_TINY_EXCELLENT_RATING                         :{TINYFONT}{GREEN}{TOWN}
 
 STR_VIEWPORT_SIGN_SMALL_BLACK                                   :{TINYFONT}{BLACK}{SIGN}
 STR_VIEWPORT_SIGN_SMALL_WHITE                                   :{TINYFONT}{WHITE}{SIGN}
@@ -4273,6 +4746,10 @@
 STR_JUST_DATE_SHORT                                             :{DATE_SHORT}
 STR_JUST_DATE_LONG                                              :{DATE_LONG}
 STR_JUST_DATE_ISO                                               :{DATE_ISO}
+STR_JUST_DATE_WALLCLOCK_TINY                                    :{DATE_WALLCLOCK_TINY}
+STR_JUST_DATE_WALLCLOCK_SHORT                                   :{DATE_WALLCLOCK_SHORT}
+STR_JUST_DATE_WALLCLOCK_LONG                                    :{DATE_WALLCLOCK_LONG}
+STR_JUST_DATE_WALLCLOCK_ISO                                     :{DATE_WALLCLOCK_ISO}
 STR_JUST_STRING                                                 :{STRING}
 STR_JUST_STRING_SPACE_STRING                                    :{STRING} {STRING}
 STR_JUST_RAW_STRING                                             :{STRING}
@@ -4288,12 +4765,16 @@
 STR_BLACK_DATE_LONG                                             :{BLACK}{DATE_LONG}
 STR_BLACK_CROSS                                                 :{BLACK}{CROSS}
 STR_SILVER_CROSS                                                :{SILVER}{CROSS}
+STR_WHITE_DATE_SHORT                                            :{WHITE}{DATE_SHORT}
 STR_WHITE_DATE_LONG                                             :{WHITE}{DATE_LONG}
+STR_WHITE_DATE_WALLCLOCK_LONG                                   :{WHITE}{DATE_WALLCLOCK_LONG}
+STR_WHITE_DATE_WALLCLOCK_SHORT                                  :{WHITE}{DATE_WALLCLOCK_SHORT}
 STR_SHORT_DATE                                                  :{WHITE}{DATE_TINY}
 STR_DATE_LONG_SMALL                                             :{TINYFONT}{BLACK}{DATE_LONG}
 STR_TINY_GROUP                                                  :{TINYFONT}{GROUP}
 STR_BLACK_INT                                                   :{BLACK}{NUM}
 STR_ORANGE_INT                                                  :{ORANGE}{NUM}
+STR_RED_INT                                                     :{RED}{NUM}
 STR_WHITE_SIGN                                                  :{WHITE}{SIGN}
 STR_TINY_BLACK_STATION                                          :{TINYFONT}{BLACK}{STATION}
 STR_BLACK_STRING                                                :{BLACK}{STRING}
@@ -4306,6 +4787,8 @@
 STR_TINY_BLACK_VEHICLE                                          :{TINYFONT}{BLACK}{VEHICLE}
 STR_TINY_RIGHT_ARROW                                            :{TINYFONT}{RIGHTARROW}
 
+STR_WHITE                                                       :{WHITE}
+STR_BLACK                                                       :{BLACK}
 STR_BLACK_1                                                     :{BLACK}1
 STR_BLACK_2                                                     :{BLACK}2
 STR_BLACK_3                                                     :{BLACK}3
@@ -4321,3 +4804,12 @@
 STR_SHIP                                                        :{BLACK}{SHIP}
 
 STR_TOOLBAR_RAILTYPE_VELOCITY                                   :{STRING} ({VELOCITY})
+
+STR_NUM                                                         :{NUM}
+STR_NUM_RELATION_2                                              :{NUM}/{NUM}
+STR_NUM_RELATION_3                                              :{NUM}/{NUM}/{NUM}
+STR_NUM_RELATION_4                                              :{NUM}/{NUM}/{NUM}/{NUM}
+
+STR_WATCH_WINDOW_TITLE                                          :{WHITE}Beobachtet {STRING}.
+STR_WATCH_CLICK_TO_WATCH_COMPANY                                :{BLACK}Klicke hier, um den Firmensitz anzusehen
+STR_WATCH_CLICK_NEW_WINDOW                                      :{BLACK}Klicke hier, um eine neue Zusatzansicht zu öffnen 
diff --git a/src/lang/greek.txt b/src/lang/greek.txt
--- a/src/lang/greek.txt
+++ b/src/lang/greek.txt
@@ -1187,18 +1187,6 @@
 STR_CONFIG_SETTING_ON                                           :Ενεργό
 STR_CONFIG_SETTING_DISABLED                                     :απενεργοποιημένο
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :όχι
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Η εταιρία μου
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Όλες οι εταιρίες
-
-STR_CONFIG_SETTING_NONE                                         :Κανένα
-STR_CONFIG_SETTING_ORIGINAL                                     :Γνήσιο
-STR_CONFIG_SETTING_REALISTIC                                    :Ρεαλιστικό
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Αριστερά
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Κέντρο
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Δεξιά
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Επιτρέπεται το χτίσιμο σε πλαγιές και ακτές: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Να επιτρέπεται η διαμόρφωση εδάφους κάτω από κτίρια, γραμμές, κλπ. (αυτόματη κλίση): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Επιτρέπονται πιο ρεαλιστικά ταξινομημένες περιοχές συλλογής : {ORANGE}{STRING}
@@ -2613,9 +2601,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Πόλη)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Πληθυσμός: {ORANGE}{COMMA}{BLACK}  Σπίτια: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Επιβάτες τον προηγούμενο μήνα: {ORANGE}{COMMA}{BLACK}  μεγ: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Αλληλογραφία τον προηγούμενο μήνα: {ORANGE}{COMMA}{BLACK}  μεγ: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Εμπορεύματα που χρειάζονται για την ανάπτυξη της πόλης:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Επιβάτες τον προηγούμενο μήνα: {ORANGE}{COMMA}{BLACK}  μεγ: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Αλληλογραφία τον προηγούμενο μήνα: {ORANGE}{COMMA}{BLACK}  μεγ: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Εμπορεύματα που χρειάζονται για την ανάπτυξη της πόλης:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} απαιτείται
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} απαιτείται τον χειμώνα
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} παραδόθηκε τον τελευταίο μήνα
diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt
--- a/src/lang/hebrew.txt
+++ b/src/lang/hebrew.txt
@@ -1090,15 +1090,6 @@
 STR_CONFIG_SETTING_ON                                           :דלוק
 STR_CONFIG_SETTING_DISABLED                                     :מבוטל
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :כבוי
-STR_CONFIG_SETTING_COMPANIES_OWN                                :עבור החברה שלי
-STR_CONFIG_SETTING_COMPANIES_ALL                                :עבור כל החברות
-
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :שמאל
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :מרכז
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :ימין
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}אפשר לבנות על מידרונות וחופים: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{ORANGE}{STRING}{LTBLUE} :'אפשר יצירת מילוי עפר תחת מבנים, פסי רכבת וכו
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}אפשר לאזורי אגירת מים להיראות יותר ריאליסטיים: {ORANGE}{STRING}
@@ -1322,9 +1313,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}ערים
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}תעשיות
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(מומלץ)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{ORANGE}{STRING}{LTBLUE} :אלגורתם איתור נתיב לרכבות
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{ORANGE}{STRING}{LTBLUE} :אלגורתם איתור נתיב לרכבים
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{ORANGE}{STRING}{LTBLUE} :אלגורתם איתור נתיב לכלי שייט
@@ -2436,9 +2424,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (עיר)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{ORANGE}{1:COMMA}{BLACK} :בתים {ORANGE}{0:COMMA}{BLACK} :אוכלוסיה
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{ORANGE}{1:COMMA}{BLACK} :מספר מירבי {ORANGE}{0:COMMA}{BLACK} :נוסעים בחודש שעבר
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{ORANGE}{1:COMMA}{BLACK} :מספר מירבי {ORANGE}{0:COMMA}{BLACK} :שקי דואר בחודש שעבר
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}המטען שצריך בשביל גידול עיר
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{ORANGE}{1:COMMA}{BLACK} :מספר מירבי {ORANGE}{0:COMMA}{BLACK} :נוסעים בחודש שעבר
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{ORANGE}{1:COMMA}{BLACK} :מספר מירבי {ORANGE}{0:COMMA}{BLACK} :שקי דואר בחודש שעבר
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}המטען שצריך בשביל גידול עיר
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} דרוש
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} דרוש בחורף
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} נמסרו בחודש שעבר
diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt
--- a/src/lang/hungarian.txt
+++ b/src/lang/hungarian.txt
@@ -1159,18 +1159,6 @@
 STR_CONFIG_SETTING_ON                                           :Be
 STR_CONFIG_SETTING_DISABLED                                     :kikapcsolva
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Kikapcsolva
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Saját vállalat
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Minden vállalat
-
-STR_CONFIG_SETTING_NONE                                         :Nincs
-STR_CONFIG_SETTING_ORIGINAL                                     :Eredeti
-STR_CONFIG_SETTING_REALISTIC                                    :Valósághű
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Balra
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Középen
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Jobbra
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Lejtőre és partokra építés: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Épületek, vágányok, stb. alatti tereprendezés engedélyezése (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Élethűbben méretezett állomási vonzáskörzetek bekapcsolása: {ORANGE}{STRING}
@@ -2590,9 +2578,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Város)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Lakosság: {ORANGE}{COMMA}{BLACK} Házak: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Utasok az előző hónapban: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Levélcsomagok az előző hónapban: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}A város növekedéséhez szükséges rakomány:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Utasok az előző hónapban: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Levélcsomagok az előző hónapban: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}A város növekedéséhez szükséges rakomány:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} szükséges
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} szükséges télen
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} szállítva a múlt hónapban
diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt
--- a/src/lang/icelandic.txt
+++ b/src/lang/icelandic.txt
@@ -1077,18 +1077,6 @@
 STR_CONFIG_SETTING_ON                                           :Já
 STR_CONFIG_SETTING_DISABLED                                     :óvirkt
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Af
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eigin fyrirtækis
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Allra fyrirtækja
-
-STR_CONFIG_SETTING_NONE                                         :Enginn
-STR_CONFIG_SETTING_ORIGINAL                                     :Upphaflegt
-STR_CONFIG_SETTING_REALISTIC                                    :Raunverulegt
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Vinstri
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Miðja
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Hægri
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Leyfilegt að byggja í halla og á strönd: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Leyfa landslagsbreytingar undir byggingum, teinum o.fl. (landfylling): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Raunverulegri stærð svæðis sem stöðvar ná yfir: {ORANGE}{STRING}
@@ -1316,9 +1304,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}Bæir
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}Iðnaðuð
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Ráðlegt)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Leiðsagnarkerfi lesta: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Leiðsögukerfi bifreiða: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Leiðsögukerfi skipa: {ORANGE}{STRING}
@@ -2471,9 +2456,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Borg)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Íbúafjöldi: {ORANGE}{COMMA}{BLACK}  Hús: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Farþegar síðasta mánaðar: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Póstur síðasta mánaðar: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Nauðsynlegur farmur fyrir stækkun bæjarins:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Farþegar síðasta mánaðar: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Póstur síðasta mánaðar: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Nauðsynlegur farmur fyrir stækkun bæjarins:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} nauðsynlegt
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} nauðsynlegt á veturnar
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} flutt í síðasta mánuði
diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt
--- a/src/lang/indonesian.txt
+++ b/src/lang/indonesian.txt
@@ -1087,18 +1087,6 @@
 STR_CONFIG_SETTING_ON                                           :Ya
 STR_CONFIG_SETTING_DISABLED                                     :Non-aktifkan
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Non-aktifkan
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Perusahaan sendiri
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Semua perusahaan
-
-STR_CONFIG_SETTING_NONE                                         :Tidak ada
-STR_CONFIG_SETTING_ORIGINAL                                     :Orisinil
-STR_CONFIG_SETTING_REALISTIC                                    :Realistis
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Kiri
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Tengah
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Kanan
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Ijinkan pembangunan di lereng dan pantai: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Ijinkan pembentukan slop dibawah bangunan, rel, dsb. (otomatiskan): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Ijinkan ukuran jangkauan wilayah lebih realistik: {ORANGE}{STRING}
@@ -1338,9 +1326,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}Kota
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}Industri
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Recommended)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Pencari jejak untuk kereta: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Pencari jejak untuk kendaraan jalan raya: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Pencari jejak untuk kapal : {ORANGE}{STRING}
@@ -2500,9 +2485,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (City)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Populasi: {ORANGE}{COMMA}{BLACK}  Rumah: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Penumpang bulan lalu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Dokumen bulan lalu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Kargo untuk pertumbuhan kota:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Penumpang bulan lalu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Dokumen bulan lalu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Kargo untuk pertumbuhan kota:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{BLACK} Butuh {ORANGE}{STRING}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} dibutuhkan saat musim dingin
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{BLACK} Bulan lalu terima {ORANGE}{CARGO}
diff --git a/src/lang/irish.txt b/src/lang/irish.txt
--- a/src/lang/irish.txt
+++ b/src/lang/irish.txt
@@ -1085,18 +1085,6 @@
 STR_CONFIG_SETTING_ON                                           :Air
 STR_CONFIG_SETTING_DISABLED                                     :díchumasaithe
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :As
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Do chuideachta féin
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Gach cuideachta
-
-STR_CONFIG_SETTING_NONE                                         :Deatach ar bith
-STR_CONFIG_SETTING_ORIGINAL                                     :Bunaidh
-STR_CONFIG_SETTING_REALISTIC                                    :Réalaíoch
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Ar chlé
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Sa lár
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Ar dheis
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Ceadaigh tógáil a dhéanamh ar fhánaí agus ar chóstaí: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Ceadaigh athrú talún faoi fhoirgnimh, ráillí iarnróid srl. (uathfhánú): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Ceadaigh ceantair stáisiún ar mhéid níos realaíoch: {ORANGE}{STRING}
@@ -1335,9 +1323,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}Bailte
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}Tionscail
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Molta)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Aimsitheoir bealaigh do thraenacha: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Aimsitheoir bealaigh d'fheithiclí bóthair: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Aimsitheoir bealaigh do longa: {ORANGE}{STRING}
@@ -2497,9 +2482,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Cathair)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Daonra: {ORANGE}{COMMA}{BLACK}  Tithe: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Paisinéirí an mhí seo caite: {ORANGE}{COMMA}{BLACK}  Uasmhéid: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Post an mhí seo caite: {ORANGE}{COMMA}{BLACK}  uasmhéid: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Lastas atá ag teastáil le go bhfásfaidh an baile:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Paisinéirí an mhí seo caite: {ORANGE}{COMMA}{BLACK}  Uasmhéid: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Post an mhí seo caite: {ORANGE}{COMMA}{BLACK}  uasmhéid: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Lastas atá ag teastáil le go bhfásfaidh an baile:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} ag teastáil
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} ag teastáil sa Gheimhreadh
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} seachadta an mhí seo caite
diff --git a/src/lang/italian.txt b/src/lang/italian.txt
--- a/src/lang/italian.txt
+++ b/src/lang/italian.txt
@@ -1109,28 +1109,6 @@
 STR_CONFIG_SETTING_DISABLED.fs                                  :Disabilitata
 STR_CONFIG_SETTING_DISABLED.fp                                  :Disabilitate
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Off
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Propria compagnia
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Tutte le compagnie
-
-STR_CONFIG_SETTING_NONE                                         :Nessuno
-STR_CONFIG_SETTING_NONE.ms                                      :Nessuno
-STR_CONFIG_SETTING_NONE.fs                                      :Nessuna
-STR_CONFIG_SETTING_ORIGINAL                                     :Originale
-STR_CONFIG_SETTING_ORIGINAL.ms                                  :Originale
-STR_CONFIG_SETTING_ORIGINAL.mp                                  :Originali
-STR_CONFIG_SETTING_ORIGINAL.fs                                  :Originale
-STR_CONFIG_SETTING_ORIGINAL.fp                                  :Originali
-STR_CONFIG_SETTING_REALISTIC                                    :Realistico
-STR_CONFIG_SETTING_REALISTIC.ms                                 :Realistico
-STR_CONFIG_SETTING_REALISTIC.mp                                 :Realistici
-STR_CONFIG_SETTING_REALISTIC.fs                                 :Realistica
-STR_CONFIG_SETTING_REALISTIC.fp                                 :Realistiche
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Sinistra
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centro
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Destra
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Consenti la costruzione su pendii e coste: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Consenti rimodellazione terreno sotto a edifici, rotaie, etc.: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Consenti aree di copertura più realistiche: {ORANGE}{STRING}
@@ -2587,9 +2565,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Metropoli)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Popolazione: {ORANGE}{COMMA}{BLACK}  Case: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passeggeri il mese scorso: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Posta il mese scorso: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Carichi richiesti per la crescita della città:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passeggeri il mese scorso: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Posta il mese scorso: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Carichi richiesti per la crescita della città:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} richiesto
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} richiesto in inverno
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :Consegnato il mese scorso: {ORANGE}{CARGO}{BLACK}
diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt
--- a/src/lang/japanese.txt
+++ b/src/lang/japanese.txt
@@ -1094,18 +1094,6 @@
 STR_CONFIG_SETTING_ON                                           :入
 STR_CONFIG_SETTING_DISABLED                                     :切
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :切
-STR_CONFIG_SETTING_COMPANIES_OWN                                :自分
-STR_CONFIG_SETTING_COMPANIES_ALL                                :すべて
-
-STR_CONFIG_SETTING_NONE                                         :なし
-STR_CONFIG_SETTING_ORIGINAL                                     :オリジナル
-STR_CONFIG_SETTING_REALISTIC                                    :リアルな
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :左
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :中位
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :右
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}傾斜地／海岸上の建設を許容：{ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}建物、道路、鉄道などの下の地形変更を許容：{ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}より現実的な受入れ地域を許容：{ORANGE}{STRING}
@@ -2524,9 +2512,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN}（市）
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}人口：{ORANGE}{COMMA}人{BLACK}　建物：{ORANGE}{COMMA}戸
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}先月の旅客：{ORANGE}{COMMA}人{BLACK}　最大：{ORANGE}{COMMA}人
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}先月の郵便袋：{ORANGE}{COMMA}袋{BLACK}　最大：{ORANGE}{COMMA}袋
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}町の成長に必要な貨物：
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}先月の旅客：{ORANGE}{COMMA}人{BLACK}　最大：{ORANGE}{COMMA}人
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}先月の郵便袋：{ORANGE}{COMMA}袋{BLACK}　最大：{ORANGE}{COMMA}袋
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}町の成長に必要な貨物：
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} required
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} が冬に必要です
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :先月 {ORANGE}{CARGO}{BLACK} が配送された
diff --git a/src/lang/korean.txt b/src/lang/korean.txt
--- a/src/lang/korean.txt
+++ b/src/lang/korean.txt
@@ -1096,18 +1096,6 @@
 STR_CONFIG_SETTING_ON                                           :켬
 STR_CONFIG_SETTING_DISABLED                                     :사용불가
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :끄기
-STR_CONFIG_SETTING_COMPANIES_OWN                                :내 회사만
-STR_CONFIG_SETTING_COMPANIES_ALL                                :모든 회사에
-
-STR_CONFIG_SETTING_NONE                                         :없음
-STR_CONFIG_SETTING_ORIGINAL                                     :오리지널
-STR_CONFIG_SETTING_REALISTIC                                    :현실적
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :왼쪽
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :가운데
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :오른쪽
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}경사/해안가 건설을 허용 : {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}건물, 트랙 등의 하부 지형 편집 허용 (자동 슬로프): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}좀더 현실적인 역세권 지정 : {ORANGE}{STRING}
@@ -2527,9 +2515,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (대도시)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}인구: {ORANGE}{COMMA}{BLACK}  가구수: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}지난달 승객수: {ORANGE}{COMMA}{BLACK}  최고: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}지난달 우편수: {ORANGE}{COMMA}{BLACK}  최고: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}도시가 성장하기 위해 필요한 화물:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}지난달 승객수: {ORANGE}{COMMA}{BLACK}  최고: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}지난달 우편수: {ORANGE}{COMMA}{BLACK}  최고: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}도시가 성장하기 위해 필요한 화물:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK}{G 0 "이" "가"} 필요함
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :냉대 기후에서 {ORANGE}{STRING}{BLACK}가 필요합니다.
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK}{G 0 "이" "가"} 지난달에 수송됨
diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt
--- a/src/lang/latvian.txt
+++ b/src/lang/latvian.txt
@@ -1097,18 +1097,6 @@
 STR_CONFIG_SETTING_ON                                           :Ieslēgts
 STR_CONFIG_SETTING_DISABLED                                     :atspējots
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Izslēgts
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Paša uzņēmums
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Visi uzņēmumi
-
-STR_CONFIG_SETTING_NONE                                         :Nekāds
-STR_CONFIG_SETTING_ORIGINAL                                     :Oriģinālais
-STR_CONFIG_SETTING_REALISTIC                                    :Reālistisks
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Pa kreisi
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centrā
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Pa labi
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Atļaut celt uz nelīdzenas zemes un krastiem: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Atļaut zemes transformācijas zem ekām, ceļiem, utt.: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Atļaut realistiskākas, palielinātas apkalpojamās platības: {ORANGE}{STRING}
@@ -2525,9 +2513,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Pilsēta)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Iedzīvotāji: {ORANGE}{COMMA}{BLACK}  Mājas: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Pasažieru sk. pagājušā mēnesī: {ORANGE}{COMMA}{BLACK}  Maks. sk.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Pasts pagājušā mēnesī: {ORANGE}{COMMA}{BLACK}  Maks. apjoms: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Krava nepieciešama pilsētas attīstībai:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Pasažieru sk. pagājušā mēnesī: {ORANGE}{COMMA}{BLACK}  Maks. sk.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Pasts pagājušā mēnesī: {ORANGE}{COMMA}{BLACK}  Maks. apjoms: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Krava nepieciešama pilsētas attīstībai:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} nepieciešams
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} nepieciešams ziemā
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} pagājušajā mēnesī piegādātas
diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt
--- a/src/lang/lithuanian.txt
+++ b/src/lang/lithuanian.txt
@@ -1170,18 +1170,6 @@
 STR_CONFIG_SETTING_ON                                           :Įjungta
 STR_CONFIG_SETTING_DISABLED                                     :išjungta
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Išjungta
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Nuosava įmonė
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Visos įmonės
-
-STR_CONFIG_SETTING_NONE                                         :Joks
-STR_CONFIG_SETTING_ORIGINAL                                     :Originalus
-STR_CONFIG_SETTING_REALISTIC                                    :Tikroviškas
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Kairėje
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centruoti
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Dešinėje
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Leisti statyti pastatus pakrantėse ir ant šlaitų: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Leisti keisti reljefą po pastatais, bėgiais, ir t.t.. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Kurti tikroviškesnio dydžio mikrorajonus: {ORANGE}{STRING}
@@ -2601,9 +2589,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Miestas)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Populiacija: {ORANGE}{COMMA}{BLACK}  Namų skaičius: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Praėjusio mėnesio keleivių sk.: {ORANGE}{COMMA}{BLACK}  Daugiausia: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Praėjusio mėnesio pašto siuntų sk.: {ORANGE}{COMMA}{BLACK}  Daugiausia: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Kad miestas augtų reikalingi kroviniai:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Praėjusio mėnesio keleivių sk.: {ORANGE}{COMMA}{BLACK}  Daugiausia: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Praėjusio mėnesio pašto siuntų sk.: {ORANGE}{COMMA}{BLACK}  Daugiausia: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Kad miestas augtų reikalingi kroviniai:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} reikia
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} reikalingas žiemą
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} pervežta praeitą mėnesį
diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt
--- a/src/lang/luxembourgish.txt
+++ b/src/lang/luxembourgish.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :Un
 STR_CONFIG_SETTING_DISABLED                                     :ausgeschalt
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Aus
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eegen Firma
-STR_CONFIG_SETTING_COMPANIES_ALL                                :All Firmen
-
-STR_CONFIG_SETTING_NONE                                         :Keen
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realistësch
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Lénks
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Zentréiert
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Riets
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Erlaabt d'Bauen op Küsten an op Ofhäng: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Erlaabt Landforumung ënnert Gebaier, Stroossen, etc. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Erlaabt méi realistësch Staugréisstplazen: {ORANGE}{STRING}
@@ -2526,9 +2514,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Stad)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Bewunnerunzuel: {ORANGE}{COMMA}{BLACK}  Haiser: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passagéier leschten Mount: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Post leschten Mount: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Luedungen gebraucht fir Stadwuestum:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passagéier leschten Mount: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Post leschten Mount: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Luedungen gebraucht fir Stadwuestum:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} gebraucht
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} gebraucht am Wanter
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} leschten Mount geliwwert
diff --git a/src/lang/malay.txt b/src/lang/malay.txt
--- a/src/lang/malay.txt
+++ b/src/lang/malay.txt
@@ -1081,18 +1081,6 @@
 STR_CONFIG_SETTING_ON                                           :Hidupkan
 STR_CONFIG_SETTING_DISABLED                                     :tiada
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Matikan
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Syarikat sendiri
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Semua syarikat
-
-STR_CONFIG_SETTING_NONE                                         :Tiada
-STR_CONFIG_SETTING_ORIGINAL                                     :Asli
-STR_CONFIG_SETTING_REALISTIC                                    :Realistik
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Kiri
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Tengah
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Kanan
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Benarkan pembinaan di tepi pantai dan cerun bukit: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Benarkan pengubahsuaian tanah di bawah bangunan, landasan, dan sebagainya (autocerun): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Benarkan kawasan tangkapan yang lebih realistik: {ORANGE}{STRING}
@@ -1324,9 +1312,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}Bandar-bandar
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}Industri-industri
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Disyorkan)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Pencari laluan untuk keretapi: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Pencari laluan untuk kenderaan jalanraya: {ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Pencari laluan untuk kapal: {ORANGE}{STRING}
@@ -2472,9 +2457,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Bandaraya)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Jumlah penduduk: {ORANGE}{COMMA}{BLACK}  Rumah: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Penumpang bulan lalu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Beg surat bulan lepas: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Kargi yang diperlukan untuk pembesaran bandar:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Penumpang bulan lalu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Beg surat bulan lepas: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Kargi yang diperlukan untuk pembesaran bandar:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} diperlukan
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} diperlukan sewaktu musim sejuk
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} dihantar bulan lepas
diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt
--- a/src/lang/norwegian_bokmal.txt
+++ b/src/lang/norwegian_bokmal.txt
@@ -1090,18 +1090,6 @@
 STR_CONFIG_SETTING_ON                                           :På
 STR_CONFIG_SETTING_DISABLED                                     :deaktivert
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Av
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eget firma
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alle firmaer
-
-STR_CONFIG_SETTING_NONE                                         :Ingen
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realistisk
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Venstre
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Midtstilt
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Høyre
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Tillat bygging på skråninger og i vannkanten: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Tillat landskapsendring under bygninger, spor, osv.: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Mer realistisk størrelse på oppfangingsområder: {ORANGE}{STRING}
@@ -2509,9 +2497,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (By)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Innbyggertall: {ORANGE}{COMMA}{BLACK}  Antall hus: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passasjerer forrige måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Post forrige måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Varebehov for byvekst:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passasjerer forrige måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Post forrige måned: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Varebehov for byvekst:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} påkrevd
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} nødvendig om vinteren
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} levert sist måned
diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt
--- a/src/lang/norwegian_nynorsk.txt
+++ b/src/lang/norwegian_nynorsk.txt
@@ -1090,18 +1090,6 @@
 STR_CONFIG_SETTING_ON                                           :På
 STR_CONFIG_SETTING_DISABLED                                     :deaktivert
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Av
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eige firma
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alle firma
-
-STR_CONFIG_SETTING_NONE                                         :Ingen
-STR_CONFIG_SETTING_ORIGINAL                                     :Opprinneleg
-STR_CONFIG_SETTING_REALISTIC                                    :Realistisk
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Venstre
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Midtstilt
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Høgre
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Tillet bygging på skråningar og i vasskanten: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Tillet landskapsendringar under bygningar, spor o.s.b.: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Meir realistisk storleik på oppfangingsområde: {ORANGE}{STRING}
@@ -2505,9 +2493,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (By)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Innbyggjartal: {ORANGE}{COMMA}{BLACK}  Antal hus: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passasjerar førre månad: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Post førre månad: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Varer naudsynt for folketalsauke:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passasjerar førre månad: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Post førre månad: {ORANGE}{COMMA}{BLACK}  maks.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Varer naudsynt for folketalsauke:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} naudsynt
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} naudsynt om vinteren
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} levert forrige månad
diff --git a/src/lang/polish.txt b/src/lang/polish.txt
--- a/src/lang/polish.txt
+++ b/src/lang/polish.txt
@@ -1475,18 +1475,6 @@
 STR_CONFIG_SETTING_ON                                           :wł.
 STR_CONFIG_SETTING_DISABLED                                     :niedostępne
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :wył.
-STR_CONFIG_SETTING_COMPANIES_OWN                                :dla własnej firmy
-STR_CONFIG_SETTING_COMPANIES_ALL                                :dla wszystkich firm
-
-STR_CONFIG_SETTING_NONE                                         :brak
-STR_CONFIG_SETTING_ORIGINAL                                     :oryginalnie
-STR_CONFIG_SETTING_REALISTIC                                    :realistycznie
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :z lewej strony
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :wyśrodkowany
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :z prawej strony
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Pozwól budować na pochyłym terenie i wybrzeżach: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Pozwól na zmiany terenu pod budynkami, torami itp. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Pozwól na bardziej realistyczny zasięg obejmowania: {ORANGE}{STRING}
@@ -2906,9 +2894,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Miasto)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Populacja: {ORANGE}{COMMA}{BLACK}  Domów: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Pasażerów w zeszłym miesiącu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Poczta w zeszłym miesiącu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Towar potrzebny do rozwoju miasta:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Pasażerów w zeszłym miesiącu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Poczta w zeszłym miesiącu: {ORANGE}{COMMA}{BLACK}  maks: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Towar potrzebny do rozwoju miasta:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{BLACK}Wymaganych {ORANGE}{STRING}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} wymagane zimą
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} dowiezionych w zeszłym miesiącu
diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt
--- a/src/lang/portuguese.txt
+++ b/src/lang/portuguese.txt
@@ -1096,18 +1096,6 @@
 STR_CONFIG_SETTING_ON                                           :Ligado
 STR_CONFIG_SETTING_DISABLED                                     :desactivado
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Desligado
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Sua empresa
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Todas as empresas
-
-STR_CONFIG_SETTING_NONE                                         :Nenhum
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realista
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Esquerda
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centro
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Direita
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Permitir a construção em declives e encostas: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Permitir formação de terra sob os edifícios, vias, etc. (auto-declive): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Dimensionamento mais realista de áreas de abrangência: {ORANGE}{STRING}
@@ -2527,9 +2515,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Metrópole)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}População: {ORANGE}{COMMA}{BLACK}  Casas: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passageiros no último mês: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Correio no último mês: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Mercadoria necessária para o seu desenvolvimento:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passageiros no último mês: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Correio no último mês: {ORANGE}{COMMA}{BLACK}  máx: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Mercadoria necessária para o seu desenvolvimento:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{BLACK}É necessário {ORANGE}{STRING}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{BLACK}No inverno, é necessário {ORANGE}{STRING}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} entregues no mês passado
diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt
--- a/src/lang/romanian.txt
+++ b/src/lang/romanian.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :Activ
 STR_CONFIG_SETTING_DISABLED                                     :dezactivat
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Oprit
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Propria companie
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Toate companiile
-
-STR_CONFIG_SETTING_NONE                                         :Deloc
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realist
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :stânga
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :centru
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :dreapta
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Permite construirea pe coastă şi în pantă: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Permite terra-formarea sub clădiri, şine, etc. (auto-pante): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Permite arii de cuprindere mai realiste: {ORANGE}{STRING}
@@ -2533,9 +2521,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Metropolă)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Populaţia: {ORANGE}{COMMA}{BLACK}  Locuinţe: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Călători luna trecută: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Colete poştale luna trecută: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Transporturi necesare dezvoltării oraşului:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Călători luna trecută: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Colete poştale luna trecută: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Transporturi necesare dezvoltării oraşului:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} necesare
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} necesare iarna
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} livrat luna trecută
diff --git a/src/lang/russian.txt b/src/lang/russian.txt
--- a/src/lang/russian.txt
+++ b/src/lang/russian.txt
@@ -25,6 +25,7 @@
 STR_EMPTY                                                       :
 STR_UNDEFINED                                                   :(неопределено)
 STR_JUST_NOTHING                                                :Ничего
+STR_TINY_NOTHING                                                :{TINYFONT}Ничего
 
 # Cargo related strings
 # Plural cargo name
@@ -346,6 +347,7 @@
 STR_LIST_FILTER_OSKTITLE                                        :{BLACK}Введите строку фильтра
 STR_LIST_FILTER_TOOLTIP                                         :{BLACK}Введите ключевое слово для фильтрации списка
 
+STR_TOOLTIP_GROUP_ORDER                                         :{BLACK}Смена критерия группировки
 STR_TOOLTIP_SORT_ORDER                                          :{BLACK}Смена направления сортировки (убывание/возрастание)
 STR_TOOLTIP_SORT_CRITERIA                                       :{BLACK}Смена критерия сортировки
 STR_TOOLTIP_FILTER_CRITERIA                                     :{BLACK}Выберите фильтр
@@ -499,6 +501,7 @@
 STR_MAP_MENU_MAP_OF_WORLD                                       :Карта мира
 STR_MAP_MENU_EXTRA_VIEW_PORT                                    :Доп. окно просмотра
 STR_MAP_MENU_SIGN_LIST                                          :Список табличек
+STR_MAP_MENU_WATCH_COMPANY                                      :Наблюдать за компанией
 ############ range for town menu starts, yet the town directory is shown in the map menu in the scenario editor
 STR_TOWN_MENU_TOWN_DIRECTORY                                    :Список городов
 ############ end of the 'Display map' dropdown
@@ -572,6 +575,7 @@
 STR_ABOUT_MENU_SCREENSHOT                                       :Снимок экрана
 STR_ABOUT_MENU_ZOOMIN_SCREENSHOT                                :Снимок экрана в обычном масштабе
 STR_ABOUT_MENU_GIANT_SCREENSHOT                                 :Снимок всей карты
+STR_ABOUT_MENU_SHOW_SYTEM_TIME                                  :Показать системное время
 STR_ABOUT_MENU_ABOUT_OPENTTD                                    :Об игре
 STR_ABOUT_MENU_SPRITE_ALIGNER                                   :Выравнивание спрайтов
 STR_ABOUT_MENU_TOGGLE_BOUNDING_BOXES                            :Переключить ограничивающие рамки
@@ -840,11 +844,27 @@
 STR_SMALLMAP_LEGENDA_INDUSTRIES                                 :{TINYFONT}{BLACK}Предприятия
 STR_SMALLMAP_LEGENDA_DESERT                                     :{TINYFONT}{BLACK}Пустыня
 STR_SMALLMAP_LEGENDA_SNOW                                       :{TINYFONT}{BLACK}Снег
+STR_SMALLMAP_LEGENDA_CAPACITY                                   :{TINYFONT}{BLACK}Вместимость
+STR_SMALLMAP_LEGENDA_USAGE                                      :{TINYFONT}{BLACK}Использование
+STR_SMALLMAP_LEGENDA_PLANNED                                    :{TINYFONT}{BLACK}Планируемый поток
+STR_SMALLMAP_LEGENDA_SENT                                       :{TINYFONT}{BLACK}Отправленный груз
+STR_SMALLMAP_LEGENDA_SHOW_TEXT                                  :{TINYFONT}{BLACK}как текст
+STR_SMALLMAP_LEGENDA_SHOW_GRAPH                                 :{TINYFONT}{BLACK}как график
+ 
+STR_SMALLMAP_SUPPLY_CAPTION                                     :{BLACK}Месячное снабжение на {STATION}
+STR_SMALLMAP_SUPPLY                                             :{TINYFONT}{CARGO}
+STR_SMALLMAP_LINK_CAPTION                                       :{BLACK}Месячное движение с {STATION} на {STATION}
+STR_SMALLMAP_LINK                                               :{TINYFONT}{STRING} -
+STR_SMALLMAP_LINK_CAPACITY                                      :{TINYFONT}  вмс: {NUM}
+STR_SMALLMAP_LINK_USAGE                                         :{TINYFONT}  исп: {NUM}
+STR_SMALLMAP_LINK_PLANNED                                       :{TINYFONT}  плн: {NUM}
+STR_SMALLMAP_LINK_SENT                                          :{TINYFONT}  отп: {NUM}
 
 STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF                   :{BLACK}Включить/выключить названия городов
 STR_SMALLMAP_CENTER                                             :{BLACK}Центрировать миникарту по этой позиции
 STR_SMALLMAP_INDUSTRY                                           :{TINYFONT}{STRING} ({NUM})
 STR_SMALLMAP_COMPANY                                            :{TINYFONT}{COMPANY}
+STR_SMALLMAP_LINKSTATS                                          :{TINYFONT}{STRING}
 STR_SMALLMAP_TOWN                                               :{TINYFONT}{WHITE}{TOWN}
 STR_SMALLMAP_DISABLE_ALL                                        :{BLACK}Выключить все
 STR_SMALLMAP_ENABLE_ALL                                         :{BLACK}Включить все
@@ -854,6 +874,8 @@
 STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT                                :{BLACK}Отображение рельефа на карте
 STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES                      :{BLACK}Скрыть собственность всех компаний
 STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES                       :{BLACK}Показать собственность всех компаний на карте
+STR_SMALLMAP_TOOLTIP_DISABLE_ALL_LINK_STATS                     :{BLACK}Скрыть все связи на карте
+STR_SMALLMAP_TOOLTIP_ENABLE_ALL_LINK_STATS                      :{BLACK}Показать все связи на карте
 
 # Status bar messages
 STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS                            :{BLACK}Показать последнее сообщение или новость
@@ -1079,6 +1101,8 @@
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP                      :{BLACK}Интервал автосохранения игры
 
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF                          :Отключено
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_DAY                  :Ежедневно
+STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_WEEK                 :Еженедельно
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH                :Каждый месяц
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS               :Каждые 3 месяца
 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS               :Каждые 6 месяцев
@@ -1224,10 +1248,13 @@
 STR_SUBSIDY_X3                                                  :x3
 STR_SUBSIDY_X4                                                  :x4
 
+STR_TERRAIN_TYPE_FALLEN                                         :Упавший ... не может подняться
 STR_TERRAIN_TYPE_VERY_FLAT                                      :Очень плоский
 STR_TERRAIN_TYPE_FLAT                                           :Плоский
+STR_TERRAIN_TYPE_BUMPY                                          :Бугристый
 STR_TERRAIN_TYPE_HILLY                                          :Холмистый
 STR_TERRAIN_TYPE_MOUNTAINOUS                                    :Гористый
+STR_TERRAIN_TYPE_ALPINIST                                       :Альпинистский
 
 STR_ECONOMY_STEADY                                              :Стабильная
 STR_ECONOMY_FLUCTUATING                                         :Неустойчивая
@@ -1235,6 +1262,9 @@
 STR_REVERSE_AT_END_OF_LINE_AND_AT_STATIONS                      :В конце линий и на станциях
 STR_REVERSE_AT_END_OF_LINE_ONLY                                 :Только в конце линий
 
+STR_DISASTERS_OFF                                               :Выкл.
+STR_DISASTERS_ON                                                :Вкл.
+
 STR_CITY_APPROVAL_PERMISSIVE                                    :Дозволяющее
 STR_CITY_APPROVAL_TOLERANT                                      :Терпимое
 STR_CITY_APPROVAL_HOSTILE                                       :Враждебное
@@ -1249,28 +1279,22 @@
 STR_CONFIG_SETTING_ON                                           :да
 STR_CONFIG_SETTING_DISABLED                                     :отключено
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :нет
-STR_CONFIG_SETTING_COMPANIES_OWN                                :для своей компании
-STR_CONFIG_SETTING_COMPANIES_ALL                                :для всех компаний
-
-STR_CONFIG_SETTING_NONE                                         :нет
-STR_CONFIG_SETTING_ORIGINAL                                     :оригинальное
-STR_CONFIG_SETTING_ORIGINAL.f                                   :оригинальная
-STR_CONFIG_SETTING_REALISTIC                                    :реалистичное
-STR_CONFIG_SETTING_REALISTIC.f                                  :реалистичная
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :слева
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :посередине
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :справа
-
+STR_CONFIG_SETTING_VEHICLESPEED                                 :{LTBLUE}Показать скорость транспорта в строке состояния: {ORANGE}{STRING}
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Разрешить строительство на склонах и на берегу: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Разрешить изм. ландшафта под зданиями, дорогами и т. д. (автоспуски): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Зона покрытия зависит от типа станции: {ORANGE}{STRING}
 STR_CONFIG_SETTING_EXTRADYNAMITE                                :{LTBLUE}Разрешить снос (почти) всех городских объектов: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TRAIN_LENGTH                                 :{LTBLUE}Максимальная длина состава: {ORANGE}{STRING} клет{P 0:1 ка ки ок}
 STR_CONFIG_SETTING_SMOKE_AMOUNT                                 :{LTBLUE}Количество дыма/искр у локомотивов: {ORANGE}{STRING}
-STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL                     :{LTBLUE}Модель ускорения поездов: {ORANGE}{STRING.f}
-STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL              :{LTBLUE}Модель ускорения автотранспорта: {ORANGE}{STRING.f}
+STR_CONFIG_SETTING_SMOKE_AMOUNT_NONE                            :нет
+STR_CONFIG_SETTING_SMOKE_AMOUNT_ORIGINAL                        :оригинальное
+STR_CONFIG_SETTING_SMOKE_AMOUNT_REALISTIC                       :реалистичное
+STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL                     :{LTBLUE}Модель ускорения поездов: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_ORIGINAL            :оригинальная
+STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_REALISTIC           :реалистичная
+STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL              :{LTBLUE}Модель ускорения автотранспорта: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_ORIGINAL     :оригинальная
+STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_REALISTIC    :реалистичная
 STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS                        :{LTBLUE}Крутизна склонов (для поездов): {ORANGE}{STRING}%
 STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS                 :{LTBLUE}Крутизна склонов (для автотранспорта): {ORANGE}{STRING}%
 STR_CONFIG_SETTING_FORBID_90_DEG                                :{LTBLUE}Запретить 90-градусные повороты на ж/д и море: {ORANGE}{STRING}
@@ -1281,11 +1305,13 @@
 STR_CONFIG_SETTING_SELECTGOODS                                  :{LTBLUE}Поставлять груз на станцию, только если на него был спрос: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH                            :{LTBLUE}Максимальная длина мостов: {ORANGE}{STRING} клет{P 0:1 ка ки ок}
 STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH                            :{LTBLUE}Максимальная длина туннелей: {ORANGE}{STRING} клет{P 0:1 ка ки ок}
+STR_CONFIG_SETTING_GOTODEPOT                                    :{LTBLUE}Разрешить приказы отправки в депо: {ORANGE}{STRING}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD             :{LTBLUE}Способ создания сырьевых предприятий: {ORANGE}{STRING}
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE        :не создавать
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL      :как и остальные
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :геологоразведка
 STR_CONFIG_SETTING_INDUSTRY_PLATFORM                            :{LTBLUE}Ровная область вокруг предприятий: {ORANGE}{STRING} клет{P 0:1 ка ки ок}
+STR_CONFIG_SETTING_EXTRA_INDUSTRY_PLACEMENT_LOGIC               :{LTBLUE}Разрешить изменение более 1 уровня высоты для расположения ниже уровня: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MULTIPINDTOWN                                :{LTBLUE}Разрешить несколько предприятий одного типа на город: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SIGNALSIDE                                   :{LTBLUE}Показывать сигналы на стороне движения: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SHOWFINANCES                                 :{LTBLUE}Показывать финансовую статистику каждый год: {ORANGE}{STRING}
@@ -1311,6 +1337,8 @@
 STR_CONFIG_SETTING_ADJACENT_STATIONS                            :{LTBLUE}Разрешить строительство смежных станций: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES                              :{LTBLUE}Включить поддержку нескольких наборов NewGRF с транспортом: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES            :{WHITE}Изменение этого параметра невозможно, если в игре есть транспортные средства.
+STR_CONFIG_SETTING_MAX_SIGNAL_EVALUATIONS                       :{LTBLUE}Максимальное количество изменений программируемых сигналов за раз: {ORANGE}{STRING}
+STR_CONFIG_SETTING_BACK_ONE_WAY_PBS_SAFE_WAITING                :{LTBLUE}Безопасная точка ожидания за односторонним маршрутным сигналом: {ORANGE}{STRING}
 
 STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS                        :{LTBLUE}Аэропорты не устаревают: {ORANGE}{STRING}
 
@@ -1358,6 +1386,7 @@
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN                   :зелёный
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN              :тёмно-зелёный
 STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET                  :фиолетовый
+STR_CONFIG_SETTING_SMALLMAP_FLOOD_WARNING                       :{LTBLUE}Включить цветное предупреждение о потопе в высотах миникарты: {ORANGE}{STRING}
 STR_CONFIG_SETTING_REVERSE_SCROLLING                            :{LTBLUE}Обратить направление перемещения обзора мышью: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SMOOTH_SCROLLING                             :{LTBLUE}Плавный скроллинг окна просмотра: {ORANGE}{STRING}
 STR_CONFIG_SETTING_MEASURE_TOOLTIP                              :{LTBLUE}Показывать замеры при строительстве: {ORANGE}{STRING}
@@ -1395,8 +1424,24 @@
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING      :все действия, кроме изменения ландшафта
 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS              :все действия
 STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Использовать расширенный список транспорта: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OFF                   :нет
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_OWN                   :для своей компании
+STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_ALL                   :для всех компаний
 STR_CONFIG_SETTING_LOADING_INDICATORS                           :{LTBLUE}Показывать индикатор загрузки: {ORANGE}{STRING}
+STR_CONFIG_SETTING_LOADING_INDICATORS_OFF                       :нет
+STR_CONFIG_SETTING_LOADING_INDICATORS_OWN                       :у своего транспорта
+STR_CONFIG_SETTING_LOADING_INDICATORS_ALL                       :у всего транспорта
+STR_CONFIG_SETTING_TIMETABLE_ALLOW                              :{LTBLUE}Включить расписания для транспорта: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIMETABLE_AUTOMATED                          :{LTBLUE}Управлять расписаниями автоматически: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIME_IN_MINUTES                              :{LTBLUE}Показывать время в минутах, а не в днях: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TICKS_PER_MINUTE                             :{LTBLUE}«Тиков» в минуте: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DATE_WITH_TIME                               :{LTBLUE}Показывать месяц и день со временем в строке состояния: {ORANGE}{STRING}
+STR_CONFIG_SETTING_DATE_WITH_TIME_NONE                          :нет
+STR_CONFIG_SETTING_DATE_WITH_TIME_Y                             :год
+STR_CONFIG_SETTING_DATE_WITH_TIME_YM                            :месяц и год
+STR_CONFIG_SETTING_DATE_WITH_TIME_YMD                           :полная дата
 STR_CONFIG_SETTING_TIMETABLE_IN_TICKS                           :{LTBLUE}Показывать расписание в «тиках», а не днях: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TIMETABLE_SEPARATION                         :{LTBLUE}Использовать расписание для обеспечения разделения транспорта: {ORANGE}{STRING}
 STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE             :{LTBLUE}Показывать время прибытия и отправления в графиках: {ORANGE}{STRING}
 STR_CONFIG_SETTING_QUICKGOTO                                    :{LTBLUE}Быстрое создание заданий транспорта: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE                            :{LTBLUE}Тип рельсов по умолчанию (после старта/загрузки): {ORANGE}{STRING}
@@ -1421,6 +1466,18 @@
 STR_CONFIG_SETTING_AI_IN_MULTIPLAYER                            :{LTBLUE}Разрешить ИИ в сетевой игре: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AI_MAX_OPCODES                               :{LTBLUE}Количество тактов перед остановкой ИИ: {ORANGE}{STRING}
 
+STR_CONFIG_SETTING_SHARING_RAIL                                 :{LTBLUE}Включить совместное использование железной дороги: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_ROAD                                 :{LTBLUE}Включить совместное использование автомобильных остановок и депо: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_WATER                                :{LTBLUE}Включить совместное использование причалов и доков: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_AIR                                  :{LTBLUE}Включить совместное использование аэропортов: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_FEE_RAIL                             :{LTBLUE}Дневная пошлина для поездов: {ORANGE}{STRING} на 1000 тонн
+STR_CONFIG_SETTING_SHARING_FEE_ROAD                             :{LTBLUE}Плата за остановку для автотранспорта: {ORANGE}{STRING} в день
+STR_CONFIG_SETTING_SHARING_FEE_WATER                            :{LTBLUE}Плата за причал для кораблей: {ORANGE}{STRING} в день
+STR_CONFIG_SETTING_SHARING_FEE_AIR                              :{LTBLUE}Плата за терминал аэропорта для авиатранспорта: {ORANGE}{STRING} в день
+STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT                      :{LTBLUE}Разрешить компаниям с долгами платить за совместное использование: {ORANGE}{STRING}
+STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES                     :{WHITE}Нельзя изменить эту настройку, т.к. транспорт использует совместную инфраструктуру.
+STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS                     :{WHITE}Нельзя изменить эту настройку, т.к. у транспорта в маршрутах задано использование совместной инфраструктуры.
+
 STR_CONFIG_SETTING_SERVINT_ISPERCENT                            :{LTBLUE}Интервал обслуживания в процентах: {ORANGE}{STRING}
 STR_CONFIG_SETTING_SERVINT_TRAINS                               :{LTBLUE}Интервал обслуживания поездов: {ORANGE}{STRING} д{P 0:1 ень ня ней}/%
 STR_CONFIG_SETTING_SERVINT_TRAINS_DISABLED                      :{LTBLUE}Обслуживание поездов по умолчанию: {ORANGE}не обслуживаются
@@ -1431,6 +1488,7 @@
 STR_CONFIG_SETTING_SERVINT_SHIPS                                :{LTBLUE}Интервал обслуживания кораблей: {ORANGE}{STRING} д{P 0:1 ень ня ней}/%
 STR_CONFIG_SETTING_SERVINT_SHIPS_DISABLED                       :{LTBLUE}Обслуживание кораблей: {ORANGE}не обслуживаются
 STR_CONFIG_SETTING_NOSERVICE                                    :{LTBLUE}Не обслуживать транспорт, если отключены поломки: {ORANGE}{STRING}
+STR_CONFIG_SETTING_IMPROVED_BREAKDOWNS                          :{LTBLUE}Включить улучшенные поломки: {ORANGE}{STRING}
 STR_CONFIG_SETTING_WAGONSPEEDLIMITS                             :{LTBLUE}Учитывать ограничение скорости у вагонов: {ORANGE}{STRING}
 STR_CONFIG_SETTING_DISABLE_ELRAILS                              :{LTBLUE}Выключить электрифицированную железную дорогу: {ORANGE}{STRING}
 
@@ -1465,13 +1523,32 @@
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED                        :разрешено
 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT          :разрешено с выбором сети дорог
 
+STR_CONFIG_SETTING_DAYLENGTH_FACTOR                             :{LTBLUE}Коэффициент длительности дня: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOWN_CARGO_FACTOR                            :{LTBLUE}Коэффициент генерации грузов городом (меньше < 0 < больше): {ORANGE}{STRING}
+
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT                         :{LTBLUE}Высадка деревьев в игре: {ORANGE}{STRING}
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NONE                    :отключена {RED}(лесопилки не смогут работать)
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_RAINFOREST              :только в лесах
 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_ALL                     :везде
 
+STR_CONFIG_SETTING_TREE_PLACEMENT_DRAG_LIMIT                    :{LTBLUE}Ограничение протягивания при высадке деревьев: {ORANGE}{STRING}
+
+STR_CONFIG_SETTING_INGAME_TREELINE_HEIGHT                       :{LTBLUE}Высота линии лесов в игре: {ORANGE}{STRING}
+
+STR_CONFIG_SETTING_TREE_GROWTH                                  :{LTBLUE}Скорость роста деревьев: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TREE_GROWTH_NORMAL                           :норма
+STR_CONFIG_SETTING_TREE_GROWTH_SLOW                             :медленно
+STR_CONFIG_SETTING_TREE_GROWTH_VERY_SLOW                        :очень медленно
+STR_CONFIG_SETTING_TREE_GROWTH_EXTREMLY_SLOW                    :чрезвычайно медленно
+
 STR_CONFIG_SETTING_TOOLBAR_POS                                  :{LTBLUE}Положение главной панели инструментов: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TOOLBAR_POS_LEFT                             :слева
+STR_CONFIG_SETTING_TOOLBAR_POS_CENTER                           :посередине
+STR_CONFIG_SETTING_TOOLBAR_POS_RIGHT                            :справа
 STR_CONFIG_SETTING_STATUSBAR_POS                                :{LTBLUE}Расположение строки состояния: {ORANGE}{STRING}
+STR_CONFIG_SETTING_STATUSBAR_POS_LEFT                           :слева
+STR_CONFIG_SETTING_STATUSBAR_POS_CENTER                         :посередине
+STR_CONFIG_SETTING_STATUSBAR_POS_RIGHT                          :справа
 STR_CONFIG_SETTING_SNAP_RADIUS                                  :{LTBLUE}Радиус прилипания окон: {ORANGE}{STRING} пикс.
 STR_CONFIG_SETTING_SNAP_RADIUS_DISABLED                         :{LTBLUE}Радиус прилипания окон: {ORANGE}отключено
 STR_CONFIG_SETTING_SOFT_LIMIT                                   :{LTBLUE}Макс. количество открытых окон (не «приклеенных»): {ORANGE}{STRING}
@@ -1510,10 +1587,20 @@
 STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(Рекомендуется)
 
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}Алгоритм поиска пути для поездов: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_NPF                    :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_YAPF                   :YAPF {BLUE}(Рекомендуется)
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}Алгоритм поиска пути для автотранспорта: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_NPF             :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_YAPF            :YAPF {BLUE}(Рекомендуется)
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}Алгоритм поиска пути для кораблей: {ORANGE}{STRING}
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_OPF                     :Оригинальный
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_NPF                     :NPF
+STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_YAPF                    :YAPF {BLUE}(Рекомендуется)
 STR_CONFIG_SETTING_REVERSE_AT_SIGNALS                           :{LTBLUE}Автоматический разворот у сигналов: {ORANGE}{STRING}
 
+STR_CONFIG_SETTING_MORE_HEIGHTLEVELS                            :{LTBLUE}Разрешить более 16 уровней высоты: {ORANGE}{STRING}
+STR_CONFIG_SETTING_ERROR_NO_CHANGE_TO_OLD_POSSIBLE              :{WHITE}Вы пытаетесь запретить более 16 уровней высоты. К сожалению на карте существует гора выше 16 уровней. Запрет уровней высоты невозможен.
+
 STR_CONFIG_SETTING_QUERY_CAPTION                                :{WHITE}Изменить значение
 
 # Intro window
@@ -1584,6 +1671,7 @@
 STR_CHEATS_TOOLTIP                                              :{BLACK}Галочки показывают, использовали ли Вы этот чит раньше
 STR_CHEATS_WARNING                                              :{BLACK}Внимание, вы собираетесь предать своих соперников! Этого вам никогда не простят!
 STR_CHEAT_MONEY                                                 :{LTBLUE}Добавить {CURRENCY}
+STR_CHEAT_DAYLENGHT_INCOME                                      :{LTBLUE}Не делить прибыль транспорта на коэффициент длительности дня: {ORANGE}{STRING}
 STR_CHEAT_CHANGE_COMPANY                                        :{LTBLUE}Игра за компанию: {ORANGE}{COMMA}
 STR_CHEAT_EXTRA_DYNAMITE                                        :{LTBLUE}Волшебный динамит (снос ВСЕГО): {ORANGE}{STRING}
 STR_CHEAT_CROSSINGTUNNELS                                       :{LTBLUE}Туннели могут пересекаться: {ORANGE}{STRING}
@@ -2137,12 +2225,16 @@
 STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP                        :{BLACK}Входной семафор{}Открыт, если хотя бы один из выходных сигналов на следующей секции путей открыт. В остальных случаях закрыт.
 STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP                         :{BLACK}Выходной семафор{}Работает как обычный семафор, но его состояние учитывается при работе входящих и комбинированных сигналов.
 STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP                        :{BLACK}Комбинированный семафор{}Работает одновременно как входной и выходной семафор. Это позволяет построить большую разветвлённую сеть.
+STR_BUILD_SIGNAL_SEMAPHORE_PROG_TOOLTIP                         :{BLACK}Программируемый семафор{}Является комбинированным семафором, поведение которого может быть запрограммировано для сложных случаев.
+STR_BUILD_SIGNAL_SEMAPHORE_SPEED_TOOLTIP                        :{BLACK}Ограничивающий семафор{}Определяет максимальную скорость, с которой поезд может следовать до следующего ограничивающего семафора.
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP                          :{BLACK}Маршрутный семафор{}Позволяет нескольким поездам находиться в одном сигнальном блоке, если каждый из них может зарезервировать безопасный путь. Допускает следование поездов в обе стороны.
 STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP                     :{BLACK}Односторонний маршрутн. семафор{}Позволяет нескольким поездам находиться в одном сигнальном блоке, если каждый из них может зарезервировать безопасный путь. Не допускает следования поездов в обратную сторону.
 STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP                          :{BLACK}Стандартный светофор{}Не позволяет нескольким поездам одновременно находиться на одном блок-участке.
 STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP                         :{BLACK}Входной светофор{}Открыт, если хотя бы один из выходных сигналов на следующей секции путей открыт. В остальных случаях закрыт.
 STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP                          :{BLACK}Выходной светофор{}Работает как обычный светофор, но его состояние учитывается при работе входящих и комбинированных сигналов.
 STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP                         :{BLACK}Комбинированный светофор{}Работает одновременно как входной и выходной светофор. Это позволяет построить большую разветвлённую сеть.
+STR_BUILD_SIGNAL_ELECTRIC_PROG_TOOLTIP                          :{BLACK}Программируемый светофор{}Является комбинированным светофором, поведение которого может быть запрограммировано для сложных случаев.
+STR_BUILD_SIGNAL_ELECTRIC_SPEED_TOOLTIP                         :{BLACK}Ограничивающий светофор{}Определяет максимальную скорость, с которой поезд может следовать до следующего ограничивающего светофора.
 STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP                           :{BLACK}Маршрутный светофор{}Позволяет нескольким поездам находиться в одном сигнальном блоке, если каждый из них может зарезервировать безопасный путь. Допускает следование поездов в обе стороны.
 STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP                      :{BLACK}Односторонний маршрутн. светофор{}Позволяет нескольким поездам находиться в одном сигнальном блоке, если каждый из них может зарезервировать безопасный путь. Не допускает следования поездов в обратную сторону.
 STR_BUILD_SIGNAL_CONVERT_TOOLTIP                                :{BLACK}Изменение типа сигнала{}Когда кнопка нажата, щёлкните для преобразования существующего сигнала в сигнал выбранного типа и варианта, или щёлкните с нажатым Ctrl для перебора существующих вариантов. Shift+щелчок - оценка стоимости преобразования.
@@ -2150,6 +2242,73 @@
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP          :{BLACK}Уменьшить плотность сигналов при протягивании
 STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP          :{BLACK}Увеличить плотность сигналов при протягивании
 
+# Programmable Signals
+STR_PROGRAM_SIGNAL_TOOLTIP                                      :{BLACK}Программируемый сигнал
+
+STR_ERR_PROGSIG_INVALID_INSTRUCTION                             :{WHITE}Невозможно вставить инструкцию после инструкции с неправильным ID
+STR_ERR_PROGSIG_INVALID_OPCODE                                  :{WHITE}Невозможно вставить инструкцию с таким кодом операции
+STR_ERR_PROGSIG_NOT_THERE                                       :{WHITE}Здесь нет программируемого сигнала
+STR_ERR_PROGSIG_INVALID_SIGNAL_STATE                            :{WHITE}У этого сигнала неправильное состояние
+STR_ERR_PROGSIG_INVALID_CONDITION                               :{WHITE}Это неправильное условие
+STR_ERR_PROGSIG_INVALID_CONDITION_FIELD                         :{WHITE}Это неправильное поле для условия
+STR_ERR_PROGSIG_INVALID_COMPARATOR                              :{WHITE}Этот блок сравнения неправильный
+STR_ERR_PROGSIG_INVALID_SIGNAL                                  :{WHITE}Выбран неправильный сигнал
+
+STR_PROGSIG_CAPTION                                             :{WHITE}Программа сигнала
+STR_PROGSIG_COND_VARIABLE_TOOLTIP                               :{BLACK}Условие для сравнения
+STR_PROGSIG_COND_COMPARATOR_TOOLTIP                             :{BLACK}Оператор для сравнения переменных
+STR_PROGSIG_COND_VALUE_TOOLTIP                                  :{BLACK}Значение для сравнения с переменной
+STR_PROGSIG_SIGNAL_STATE_TOOLTIP                                :{BLACK}Установить сигнал в состояние
+STR_PROGSIG_COND_SET_SIGNAL                                     :{BLACK}Установить сигнал
+STR_PROGSIG_COND_SET_SIGNAL_TOOLTIP                             :{BLACK}Установить сигнал для слежения за
+STR_PROGSIG_GOTO_SIGNAL                                         :{BLACK}Перейти к сигналу
+STR_PROGSIG_GOTO_SIGNAL_TOOLTIP                                 :{BLACK}Перейти к этому сигналу
+STR_PROGSIG_INSERT_TOOLTIP                                      :{BLACK}Вставить инструкцию
+STR_PROGSIG_REMOVE_TOOLTIP                                      :{BLACK}Удалить выделенную инструкцию
+
+STR_PROGSIG_REMOVE                                              :{BLACK}Удалить
+STR_PROGSIG_INSERT                                              :Вставить
+STR_PROGSIG_INSERT_IF                                           :Условие
+STR_PROGSIG_INSERT_SET_SIGNAL                                   :Состояние сигнала
+
+STR_PROGSIG_FIRST                                               :Начало
+STR_PROGSIG_LAST                                                :Конец
+
+STR_PROGSIG_IF                                                  :Если {STRING} То
+STR_PROGSIG_ELSE                                                :Иначе
+STR_PROGSIG_ENDIF                                               :Конец Если
+
+STR_PROGSIG_SET_SIGNAL                                          :Сделать сигнал {STRING}
+
+STR_PROGSIG_COND_ALWAYS                                         :всегда
+STR_PROGSIG_COND_NEVER                                          :никогда
+STR_PROGSIG_COND_COMPARE                                        :{STRING} {STRING} {NUM}
+STR_PROGSIG_COND_SIGNAL_STATE                                   :состояние сигнала
+STR_PROGSIG_CONDVAR_SIGNAL_STATE                                :{STRING} зелёный
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_SPECIFIED                      :определенный сигнал
+STR_PROGSIG_CONDVAR_SIGNAL_STATE_UNSPECIFIED                    :{RED}неопределенный сигнал{STRING}
+STR_PROGSIG_CONDVAR_NUM_RED                                     :красные сигналы
+STR_PROGSIG_CONDVAR_NUM_GREEN                                   :зеленые сигналы
+
+STR_PROGSIG_CONDITION_VALUE_CAPT                                :{WHITE}Значение условия
+
+STR_ERROR_CAN_T_INSERT_INSTRUCTION                              :{WHITE}Невозможно вставить инструкцию
+STR_ERROR_CAN_T_MODIFY_INSTRUCTION                              :{WHITE}Невозможно изменить инструкцию
+STR_ERROR_CAN_T_REMOVE_INSTRUCTION                              :{WHITE}Невозможно удалить инструкцию
+STR_ERROR_CAN_T_GOTO_UNDEFINED_SIGNAL                           :{WHITE}Невозможно перейти к неопределенному сигналу
+STR_ERROR_NOT_AN_EXIT_SIGNAL                                    :{WHITE}Это не выходной сигнал
+STR_ERROR_CAN_T_DEPEND_UPON_BIDIRECTIONAL_SIGNALS               :{WHITE}Невозможно условно зависеть от двунаправленных сигналов
+STR_ERROR_INVALID_SIGNAL                                        :{WHITE}Неправильный сигнал
+
+STR_SPEEDSIG_CAPTION                                            :{WHITE}Ограничение скорости
+
+STR_SPEEDSIG_VALUE_NONE                                         :{WHITE}Нет ограничения скорости
+STR_SPEEDSIG_VALUE                                              :{WHITE}{VELOCITY}
+STR_SPEEDSIG_CLEAR                                              :{BLACK}Очистить
+STR_SPEEDSIG_CHANGE                                             :{BLACK}Изменить
+
+STR_ERROR_CAN_T_SET_SPEED                                       :{WHITE}Невозможно установить ограничение скорости
+
 # Bridge selection window
 STR_SELECT_RAIL_BRIDGE_CAPTION                                  :{WHITE}Выберите железнодорожный мост
 STR_SELECT_ROAD_BRIDGE_CAPTION                                  :{WHITE}Выберите тип моста
@@ -2180,6 +2339,7 @@
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY                :{BLACK}Строительство грузовых терминалов. Нажатие Ctrl позволяет объединять станции. При нажатом Shift - оценка стоимости строительства.
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION               :{BLACK}Строительство грузовых трамвайных станций. Нажатие Ctrl позволяет объединять станции. При нажатом Shift - оценка стоимости строительства.
 STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD                    :{BLACK}Включить/отключить односторонние дороги
+STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAFFIC_LIGHT                    :{BLACK}Строительство светофоров
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE                      :{BLACK}Строительство автомобильных мостов. При нажатом Shift - оценка стоимости строительства.
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE                   :{BLACK}Строительство трамвайных мостов. При нажатом Shift - оценка стоимости строительства.
 STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL                      :{BLACK}Строительство автомобильных туннелей. При нажатом Shift - оценка стоимости строительства.
@@ -2259,6 +2419,29 @@
 STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND                  :{BLACK}Поднять угол земли. Перетаскивание поднимает первый выбранный угол и выравнивает выбранную область до новой высоты угла. Ctrl выбирает область по диагонали. При нажатом Shift - оценка стоимости строительства.
 STR_LANDSCAPING_LEVEL_LAND_TOOLTIP                              :{BLACK}Выровнять землю до высоты первого выбранного угла. Ctrl выбирает область по диагонали. При нажатом Shift - оценка стоимости выравнивания.
 STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND                           :{BLACK}Покупка земли. При нажатом Shift - оценка стоимости покупки.
+STR_LANDSCAPING_TOOLTIP_RULER_TOOL                              :{BLACK}Использовать виртуальную линейку для измерения расстояния и высоты
+
+# copy paste
+STR_COPY_PASTE_TOOLBAR                                          :{WHITE}Копирование
+STR_COPY_PASTE_TOOLTIP                                          :{BLACK}Копирование и вставка
+STR_COPY_PASTE_COPY_TOOLTIP                                     :{BLACK}Копировать выбранную область
+STR_COPY_PASTE_PASTE_TOOLTIP                                    :{BLACK}Вставить скопированную область
+STR_COPY_PASTE_ROTATE_LEFT_TOOLTIP                              :{BLACK}Повернуть на 90 град. против часовой стрелки
+STR_COPY_PASTE_ROTATE_RIGHT_TOOLTIP                             :{BLACK}Повернуть на 90 град. по часовой стрелке
+STR_COPY_PASTE_VACANT_TERRAIN_TOOLTIP                           :{BLACK}Если свободно, должна быть вставлена поверхность
+STR_COPY_PASTE_LOAD_TOOLTIP                                     :{BLACK}Загрузить ранее сохраненный шаблон
+STR_COPY_PASTE_SAVE_TOOLTIP                                     :{BLACK}Сохранить текущее выделение в качестве шаблона
+STR_COPY_PASTE_MIRROR_HORIZONTAL_TOOLTIP                        :{BLACK}Отразить текущее выделение по горизонтали
+STR_COPY_PASTE_MIRROR_VERTICAL_TOOLTIP                          :{BLACK}Отразить текущее выделение по вертикали
+STR_COPY_PASTE_BULLDOZE_BEFORE_BUILD_TOOLTIP                    :{BLACK}Перед вставкой очистить занятую поверхность
+STR_COPY_PASTE_TOGGLE_SIGNAL_DIRECTION_TOOLTIP                  :{BLACK}При вставке переключить направление сигналов
+STR_COPY_PASTE_CONVERT_RAIL_TOOLTIP                             :{BLACK}При вставке преобразовать использованные ж/д пути к текущему типу
+STR_COPY_PASTE_WITHOUT_RAIL_TOOLTIP                             :{BLACK}Если включено, железные дороги будут скопированы
+STR_COPY_PASTE_WITHOUT_ROAD_TOOLTIP                             :{BLACK}Если включено, дороги будут скопированы
+STR_COPY_PASTE_ONLY_OWN_TOOLTIP                                 :{BLACK}Если выключено, будет скопирована только ваша собственность
+
+STR_COPY_PASTE_PASTE_DISABLED                                   :{WHITE}Вставка отключена...
+STR_CONFIG_PATCHES_CP_PASTE_SPEED                               :{LTBLUE}Скорость вставки в сетевой игре. (255 = выкл.): {ORANGE}{STRING}
 
 # Object construction window
 STR_OBJECT_BUILD_CAPTION                                        :{WHITE}Выбор объекта
@@ -2360,6 +2543,7 @@
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Администрация: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Нет
 STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Координаты: {LTBLUE}{NUM}x{NUM}x{NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_HEIGHT                       :{BLACK}Высота: {LTBLUE}{NUM}
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Построено: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Класс станции: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Тип станции: {LTBLUE}{STRING}
@@ -2409,6 +2593,7 @@
 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD                        :Дорога с озеленением
 STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT                     :Гараж
 STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING               :Железнодорожный переезд
+STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_TRAFFIC_LIGHTS               :Дорога со светофорами
 STR_LAI_ROAD_DESCRIPTION_TRAMWAY                                :Трамвайные пути
 
 # Houses come directly from their building names
@@ -2437,8 +2622,10 @@
 # Industries come directly from their industry names
 
 STR_LAI_TUNNEL_DESCRIPTION_RAILROAD                             :Железнодорожный туннель
+STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_SIGNAL                      :Железнодорожный туннель с имитацией сигналов
 STR_LAI_TUNNEL_DESCRIPTION_ROAD                                 :Автомобильный туннель
 
+STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL                      :Ж/д мост с имитацией сигналов
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_SUSPENSION_STEEL                :Стальной висячий ж/д мост
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_GIRDER_STEEL                    :Стальной балочный ж/д мост
 STR_LAI_BRIDGE_DESCRIPTION_RAIL_CANTILEVER_STEEL                :Стальной консольный ж/д мост
@@ -2468,6 +2655,9 @@
 STR_ABOUT_VERSION                                               :{BLACK}OpenTTD версия {REV}
 STR_ABOUT_COPYRIGHT_OPENTTD                                     :{BLACK}OpenTTD {COPYRIGHT} 2002-2011 Команда разработчиков OpenTTD
 
+# System time window
+STR_SYSTEM_TIME                                                 :{WHITE}Системное время
+
 # Save/load game/scenario
 STR_SAVELOAD_SAVE_CAPTION                                       :{WHITE}Сохранить игру
 STR_SAVELOAD_LOAD_CAPTION                                       :{WHITE}Загрузить игру
@@ -2475,6 +2665,8 @@
 STR_SAVELOAD_LOAD_SCENARIO                                      :{WHITE}Загрузить сценарий
 STR_SAVELOAD_LOAD_HEIGHTMAP                                     :{WHITE}Загрузить карту
 STR_SAVELOAD_SAVE_HEIGHTMAP                                     :{WHITE}Сохранить карту высот
+STR_SAVELOAD_SAVE_COPY_PASTE_TEMPLATE                           :{WHITE}Сохранить шаблон
+STR_SAVELOAD_LOAD_COPY_PASTE_TEMPLATE                           :{WHITE}Загрузить шаблон
 STR_SAVELOAD_HOME_BUTTON                                        :{BLACK}Кликните, чтобы перейти к текущей папке загрузки/сохранения по умолчанию
 STR_SAVELOAD_BYTES_FREE                                         :{BLACK}{BYTES} свободно
 STR_SAVELOAD_LIST_TOOLTIP                                       :{BLACK}Список дисков, папок и сохранённых игр
@@ -2491,6 +2683,10 @@
 STR_SAVELOAD_DETAIL_GRFSTATUS                                   :{SILVER}NewGRF: {WHITE}{STRING}
 
 STR_SAVELOAD_OSKTITLE                                           :{BLACK}Введите название сохраняемой игры
+STR_TEMPLATE_LOAD_FAILED                                        :{WHITE}Не удалось загрузить шаблон{}{STRING}
+STR_TEMPLATE_SAVE_FAILED                                        :{WHITE}Не удалось сохранить шаблон{}{STRING}
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW                        :Шаблон сделан в более новой версии
+STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN                         :Шаблон испорчен
 
 # World generation
 STR_MAPGEN_WORLD_GENERATION_CAPTION                             :{WHITE}Создание мира
@@ -2502,6 +2698,12 @@
 STR_MAPGEN_SNOW_LINE_HEIGHT                                     :{BLACK}Снеговая линия:
 STR_MAPGEN_SNOW_LINE_UP                                         :{BLACK}Поднять снеговую линию
 STR_MAPGEN_SNOW_LINE_DOWN                                       :{BLACK}Опустить снеговую линию
+STR_MAPGEN_DESERT_AMOUNT                                        :{BLACK}Количество пустынь:
+STR_MAPGEN_DESERT_AMOUNT_UP                                     :{BLACK}Увеличить количество пустынных клеток
+STR_MAPGEN_DESERT_AMOUNT_DOWN                                   :{BLACK}Уменьшить количество пустынных клеток
+STR_MAPGEN_TREE_LINE_HEIGHT                                     :{BLACK}Высота линии лесов:
+STR_MAPGEN_TREE_LINE_UP                                         :{BLACK}Поднять линию лесов на 1
+STR_MAPGEN_TREE_LINE_DOWN                                       :{BLACK}Опустить линию лесов на 1
 STR_MAPGEN_RANDOM_SEED                                          :{BLACK}Начальное число:
 STR_MAPGEN_RANDOM_SEED_HELP                                     :{BLACK}Ландшафт генерируется псевдослучайно, число - опорная точка в последовательности случайных чисел.
 STR_MAPGEN_RANDOM                                               :{BLACK}Случайное
@@ -2534,6 +2736,8 @@
 
 STR_MAPGEN_RANDOM_SEED_OSKTITLE                                 :{BLACK}Введите случайное число
 STR_MAPGEN_SNOW_LINE_QUERY_CAPT                                 :{WHITE}Изменить высоту снеговой линии
+STR_MAPGEN_DESERT_AMOUNT_QUERY_CAPT                             :{WHITE}Изменить количество пустынных клеток
+STR_MAPGEN_TREE_LINE_QUERY_CAPT                                 :{WHITE}Изменить высоту линии лесов
 STR_MAPGEN_START_DATE_QUERY_CAPT                                :{WHITE}Изменить год начала игры
 
 # SE Map generation
@@ -2743,12 +2947,35 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Мегаполис)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Население: {ORANGE}{COMMA}{BLACK}  Зданий: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Пассажиров за прошлый месяц: {ORANGE}{COMMA}{BLACK}  макс.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Почты за прошлый месяц: {ORANGE}{COMMA}{BLACK}  макс.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Груз, необходимый для роста города:
+STR_TOWN_VIEW_GENERATED_CARGO_LAST_MONTH                        :{BLACK}Произведено за прошедший месяц:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Пассажиров за прошлый месяц: {ORANGE}{COMMA}{BLACK}  макс.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Почты за прошлый месяц: {ORANGE}{COMMA}{BLACK}  макс.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Груз, доставленный / необходимый для роста города:
+STR_TOWN_VIEW_PASSENGERS_THIS_MONTH_MAX                         :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Необходимо для 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_MAIL_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Необходимо для 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_FOOD_THIS_MONTH_MAX                               :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Необходимо для 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_WATER_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Необходимо для 100%: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GOODS_THIS_MONTH_MAX                              :{BLACK}{STRING}: {ORANGE}{COMMA}{BLACK}.  Необходимо для 100%: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} требу{G 0 е е е ю}тся
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} требу{G 0 е е е ю}тся зимой
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} доставлено в прошлом месяце
+STR_TOWN_VIEW_GROWTH_RATE_LAST_MONTH                            :{BLACK}Темп роста за последний месяц: {ORANGE}{COMMA}{BLACK} %
+STR_TOWN_VIEW_GROWTH_SPEED_DISABLED                             :{RED}Скорость роста установлена в 0! Рост невозможен.
+STR_TOWN_VIEW_TRANSPORTED_RATE_LAST_MONTH                       :{BLACK}Требования роста города по прошлому месяцу: {ORANGE}{COMMA} %
+STR_TOWN_VIEW_CARGO_DEMAND_LAST_MONTH                           :{BLACK}Наиболее необходимо в прошлом месяце: {ORANGE}{STRING}
+STR_TOWN_VIEW_GROWTH_STANDARD                                   :Еще не рассчитано
+STR_TOWN_VIEW_GROWTH_NEED_STATION                               :Больше обслуживаемых станций
+STR_TOWN_VIEW_GROWTH_NEED_MORE_PASS                             :Больше {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_MAIL                             :Больше {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_FOOD                             :Больше {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_WATER                            :Больше {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MORE_GOODS                            :Больше {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_PASS                                  :Перевозка {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_MAIL                                  :Перевозка {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_FOOD                                  :Перевозка {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_WATER                                 :Перевозка {STRING}
+STR_TOWN_VIEW_GROWTH_NEED_GOODS                                 :Перевозка {STRING}
+STR_TOWN_VIEW_GROWTH_SATISFIED                                  :Не останавливайся!
 STR_TOWN_VIEW_NOISE_IN_TOWN                                     :{BLACK}Уровень шума в городе: {ORANGE}{COMMA}{BLACK}  макс: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CENTER_TOOLTIP                                    :{BLACK}Показать город в основном окне. Ctrl+клик - показать в дополнительном окне.
 STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON                            :{BLACK}Местные власти
@@ -2821,8 +3048,35 @@
 
 STR_STATION_VIEW_RATINGS_BUTTON                                 :{BLACK}Рейтинг
 STR_STATION_VIEW_RATINGS_TOOLTIP                                :{BLACK}Показать рейтинг станции
-STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Местный рейтинг транспортной компании:
+STR_STATION_VIEW_CARGO_RATINGS_TITLE                            :{BLACK}Снабжение за месяц и местный рейтинг:
 STR_STATION_VIEW_CARGO_RATING                                   :{WHITE}{STRING}: {YELLOW}{STRING} ({COMMA}%)
+STR_STATION_VIEW_CARGO_SUPPLY_RATING                            :{WHITE}{STRING}: {YELLOW}{COMMA} / {STRING} ({COMMA}%)
+ 
+STR_STATION_VIEW_DEPARTURES_BUTTON                              :{BLACK}Расписание
+STR_STATION_VIEW_DEPARTURES_TOOLTIP                             :{BLACK}Показать расписание станции
+ 
+STR_STATION_VIEW_GROUP                                          :{BLACK}Группировать по
+STR_STATION_VIEW_WAITING_STATION                                :Станция: Ожидает
+STR_STATION_VIEW_WAITING_AMOUNT                                 :Количество: Ожидает
+STR_STATION_VIEW_PLANNED_STATION                                :Станция: Планируется
+STR_STATION_VIEW_PLANNED_AMOUNT                                 :Количество: Планируется
+STR_STATION_VIEW_FROM                                           :{YELLOW}{SHORTCARGO} из {STATION}
+STR_STATION_VIEW_VIA                                            :{YELLOW}{SHORTCARGO} через {STATION}
+STR_STATION_VIEW_TO                                             :{YELLOW}{SHORTCARGO} на {STATION}
+STR_STATION_VIEW_FROM_ANY                                       :{RED}{SHORTCARGO} с неизвестной станции
+STR_STATION_VIEW_TO_ANY                                         :{RED}{SHORTCARGO} на любую станцию
+STR_STATION_VIEW_VIA_ANY                                        :{RED}{SHORTCARGO} через любую станцию
+STR_STATION_VIEW_FROM_HERE                                      :{GREEN}{SHORTCARGO} с этой станции
+STR_STATION_VIEW_VIA_HERE                                       :{GREEN}{SHORTCARGO}, останавливаясь на этой станции
+STR_STATION_VIEW_TO_HERE                                        :{GREEN}{SHORTCARGO} на эту станцию
+STR_STATION_VIEW_NONSTOP                                        :{YELLOW}{SHORTCARGO} без остановки
+
+STR_STATION_VIEW_GROUP_S_V_D                                    :откуда / через / куда
+STR_STATION_VIEW_GROUP_S_D_V                                    :откуда / куда / через
+STR_STATION_VIEW_GROUP_V_S_D                                    :через / откуда / куда
+STR_STATION_VIEW_GROUP_V_D_S                                    :через / куда / откуда
+STR_STATION_VIEW_GROUP_D_S_V                                    :куда / откуда / через
+STR_STATION_VIEW_GROUP_D_V_S                                    :куда / через / откуда
 
 ############ range for rating starts
 STR_CARGO_RATING_APPALLING                                      :Ужасный
@@ -2845,6 +3099,79 @@
 
 STR_STATION_VIEW_RENAME_STATION_CAPTION                         :Название станции
 
+# Departures window
+STR_DEPARTURES_CAPTION                                          :{WHITE}{STATION} Текущее расписание станции
+STR_DEPARTURES_CAPTION_WAYPOINT                                 :{WHITE}{WAYPOINT} Текущее расписание
+STR_DEPARTURES_DEPARTURES                                       :{BLACK}{TINYFONT}От
+STR_DEPARTURES_ARRIVALS                                         :{BLACK}{TINYFONT}Пр
+STR_DEPARTURES_VIA_BUTTON                                       :{BLACK}{TINYFONT}через
+STR_DEPARTURES_DEPARTURES_TOOLTIP                               :{BLACK}Показать отправления по расписанию
+STR_DEPARTURES_ARRIVALS_TOOLTIP                                 :{BLACK}Показать прибытия по расписанию
+STR_DEPARTURES_VIA_TOOLTIP                                      :{BLACK}Показать транспорт с расписанием, не останавливающийся здесь
+STR_DEPARTURES_NONE_SELECTED                                    :{ORANGE}Информация о расписании не была запрошена.
+STR_DEPARTURES_EMPTY                                            :{ORANGE}Нет транспорта с расписаниями с этой станцией.
+STR_DEPARTURES_TIME                                             :{ORANGE}{DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_TIME_DEP                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TIME_ARR                                         :{ORANGE}{DATE_WALLCLOCK_TINY} {RED}{DOWNARROW}
+STR_DEPARTURES_TIME_BOTH                                        :{ORANGE}{1:DATE_WALLCLOCK_TINY} {RED}{DOWNARROW} {ORANGE}{0:DATE_WALLCLOCK_TINY} {GREEN}{UPARROW}
+STR_DEPARTURES_TERMINUS                                         :{ORANGE}{STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA_STATION                             :{ORANGE}{STATION}{STRING} через {STATION}{STRING}
+STR_DEPARTURES_TERMINUS_VIA                                     :{ORANGE}{STATION}{STRING} через
+STR_DEPARTURES_VIA                                              :{ORANGE}через {STATION}{STRING}
+STR_DEPARTURES_TOC                                              :{ORANGE}{COMPANY}
+STR_DEPARTURES_GROUP                                            :{ORANGE}{GROUP}
+STR_DEPARTURES_VEH                                              :{ORANGE}{VEHICLE}
+STR_DEPARTURES_CALLING_AT                                       :{TINYFONT}{ORANGE}Следует к:
+STR_DEPARTURES_CALLING_AT_LARGE                                 :{ORANGE}Следует к:
+STR_DEPARTURES_CALLING_AT_FIRST_STATION                         :{STATION}
+STR_DEPARTURES_CALLING_AT_STATION                               :{STRING}, {STATION}
+STR_DEPARTURES_CALLING_AT_LAST_STATION                          :{STRING} и {STATION}
+STR_DEPARTURES_CALLING_AT_LIST                                  :{TINYFONT}{ORANGE}{STRING}.
+STR_DEPARTURES_CALLING_AT_LIST_LARGE                            :{ORANGE}{STRING}.
+
+STR_DEPARTURES_TYPE_TRAIN                                       :{ORANGE}{TRAIN}
+STR_DEPARTURES_TYPE_TRAIN_SILVER                                :{SILVER}{TRAIN}
+STR_DEPARTURES_TYPE_BUS                                         :{ORANGE}{BUS}
+STR_DEPARTURES_TYPE_BUS_SILVER                                  :{SILVER}{BUS}
+STR_DEPARTURES_TYPE_LORRY                                       :{ORANGE}{LORRY}
+STR_DEPARTURES_TYPE_LORRY_SILVER                                :{SILVER}{LORRY}
+STR_DEPARTURES_TYPE_PLANE                                       :{ORANGE}{PLANE}
+STR_DEPARTURES_TYPE_PLANE_SILVER                                :{SILVER}{PLANE}
+STR_DEPARTURES_TYPE_SHIP                                        :{ORANGE}{SHIP}
+STR_DEPARTURES_TYPE_SHIP_SILVER                                 :{SILVER}{SHIP}
+
+STR_DEPARTURES_STATION_NONE                                     :
+STR_DEPARTURES_STATION_PORT                                     :{ORANGE} {SHIP}
+STR_DEPARTURES_STATION_AIRPORT                                  :{ORANGE} {PLANE}
+STR_DEPARTURES_STATION_PORTAIRPORT                              :{ORANGE} {SHIP} {PLANE}
+
+############ possible statuses start
+STR_DEPARTURES_ON_TIME                                          :{GREEN}Без опоздания
+STR_DEPARTURES_ARRIVED                                          :{GREEN}Прибыл
+STR_DEPARTURES_DELAYED                                          :{YELLOW}Задерживается
+STR_DEPARTURES_EXPECTED                                         :{YELLOW}Ожид {DATE_WALLCLOCK_TINY}
+STR_DEPARTURES_CANCELLED                                        :{RED}Отменен
+
+############ config settings
+STR_CONFIG_SETTING_DEPARTUREBOARDS                              :{ORANGE}Табло расписаний
+STR_CONFIG_MAX_DEPARTURES                                       :{LTBLUE}Показывать максимум {ORANGE}{STRING}{LTBLUE} рейсов в расписании каждой станции
+STR_CONFIG_MAX_DEPARTURE_TIME                                   :{LTBLUE}Показывать рейсы за {ORANGE}{STRING}{LTBLUE} дней вперед
+STR_CONFIG_DEPARTURE_CALC_FREQUENCY                             :{LTBLUE}Расчитывать рейсы каждые {ORANGE}{STRING}{LTBLUE} «тик{P "" а ов}»
+STR_CONFIG_DEPARTURE_VEHICLE_NAME                               :{LTBLUE}Показывать имя траспорта на табло расписания: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_GROUP_NAME                                 :{LTBLUE}Показывать имя группы траспорта на табло расписания: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_COMPANY_NAME                               :{LTBLUE}Показывать имя компании на табло расписания: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_VEHICLE_TYPE                               :{LTBLUE}Показывать иконку вида траспорта на табло расписания: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_VEHICLE_COLOR                              :{LTBLUE}Показывать иконку вида траспорта серебром: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_LARGER_FONT                                :{LTBLUE}Использовать крупный шрифт для отображения пункта назначения на табло: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_DESTINATION_TYPE                           :{LTBLUE}Показывать иконки для пунктов назначения доков и аэропортов: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_SHOW_BOTH                                  :{LTBLUE}Показывать время прибытия и отправления на одной линии: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_ONLY_PASSENGERS                            :{LTBLUE}Показывать рейсы только для транспорта, который может перевозить пассажиров: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_CONDITIONALS                               :{LTBLUE}При обработке переходов в условиях: {ORANGE}{STRING}
+STR_CONFIG_DEPARTURE_CONDITIONALS_1                             :не обрабатывать
+STR_CONFIG_DEPARTURE_CONDITIONALS_2                             :предполагать, что переход будет
+STR_CONFIG_DEPARTURE_CONDITIONALS_3                             :предполагать, что перехода не будет
+STR_CONFIG_DEPARTURE_SHOW_ALL_STOPS                             :{LTBLUE}Показывать все станции вне завимости от погрузки/разгрузки: {ORANGE}{STRING}
+
 # Waypoint/buoy view window
 STR_WAYPOINT_VIEW_CAPTION                                       :{WHITE}{WAYPOINT}
 STR_WAYPOINT_VIEW_CENTER_TOOLTIP                                :{BLACK}Показать точку пути в основном окне. Ctrl+клик - показать в дополнительном окне.
@@ -2870,6 +3197,8 @@
 STR_FINANCES_SECTION_AIRCRAFT_INCOME                            :{GOLD}Доход от авиации
 STR_FINANCES_SECTION_SHIP_INCOME                                :{GOLD}Доход от кораблей
 STR_FINANCES_SECTION_LOAN_INTEREST                              :{GOLD}Проценты по займу
+STR_FINANCES_SECTION_INFRASTRUCTURE_COSTS                       :{GOLD}Плата за совм. инфрастр.
+STR_FINANCES_SECTION_INFRASTRUCTURE_INCOME                      :{GOLD}Доход от совм. инфрастр.
 STR_FINANCES_SECTION_OTHER                                      :{GOLD}Прочие расходы
 STR_FINANCES_NEGATIVE_INCOME                                    :{BLACK}-{CURRENCY}
 STR_FINANCES_POSITIVE_INCOME                                    :{BLACK}+{CURRENCY}
@@ -2905,6 +3234,11 @@
 STR_COMPANY_VIEW_RELOCATE_HQ                                    :{BLACK}Переместить
 STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS                  :{BLACK}Переместить штаб-квартиру компании в другое место за 1% оценочной стоимости капитала компании. Shift+щелчок - оценка стоимости переноса.
 
+STR_COMPANY_PROFILE_LOAD_BUTTON                                 :{BLACK}Загрузить профиль
+STR_COMPANY_PROFILE_LOAD_TOOLTIP                                :{BLACK}Загрузить профиль компании
+STR_COMPANY_PROFILE_SAVE_BUTTON                                 :{BLACK}Сохранить профиль
+STR_COMPANY_PROFILE_SAVE_TOOLTIP                                :{BLACK}Сохранить профиль текущей компании
+
 STR_COMPANY_VIEW_NEW_FACE_BUTTON                                :{BLACK}Внешность
 STR_COMPANY_VIEW_NEW_FACE_TOOLTIP                               :{BLACK}Изменить внешность директора
 STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON                           :{BLACK}Цвет
@@ -3011,6 +3345,9 @@
 
 STR_GROUP_RENAME_CAPTION                                        :{BLACK}Название группы
 
+STR_GROUP_PROFIT_THIS_YEAR                                      :{BLACK}Доход за этот год: {CURRENCY}
+STR_GROUP_PROFIT_LAST_YEAR                                      :{BLACK}Доход за прошлый год: {CURRENCY}
+
 # Build vehicle window
 STR_BUY_VEHICLE_TRAIN_RAIL_CAPTION                              :Новый поезд
 STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION                            :Новый электропоезд
@@ -3279,6 +3616,11 @@
 STR_VEHICLE_DETAILS_AIRCRAFT_RENAME                             :{BLACK}Переименовать воздушное судно
 
 STR_VEHICLE_INFO_AGE_RUNNING_COST_YR                            :{BLACK}Возраст: {LTBLUE}{STRING}{BLACK}   Стоимость обслуживания: {LTBLUE}{CURRENCY}/год
+
+STR_RUNNING	                                                    :{LTBLUE}Работает
+STR_NEED_REPAIR	                                                :{ORANGE}Нужен ремонт - максимальная скорость снижена до {VELOCITY}
+STR_CURRENT_STATUS                                              :{BLACK}Текущий статус: {STRING}
+
 # The next two need to stay in this order
 STR_VEHICLE_INFO_AGE                                            :{COMMA} {P год года лет} ({COMMA})
 STR_VEHICLE_INFO_AGE_RED                                        :{RED}{COMMA} {P год года лет} ({COMMA})
@@ -3310,7 +3652,9 @@
 
 # Extra buttons for train details windows
 STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE                :{LTBLUE}{ENGINE}{BLACK}  Построен в {LTBLUE}{NUM} г.{BLACK} Стоимость: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE_AND_SPEED      :{LTBLUE}{ENGINE}{BLACK}  Построен в {LTBLUE}{NUM} г.{BLACK} Стоимость: {LTBLUE}{CURRENCY} {BLACK}Макс. скорость: {LTBLUE}{VELOCITY}
 STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE                           :{LTBLUE}{ENGINE}{BLACK}   Стоимость: {LTBLUE}{CURRENCY}
+STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_AND_SPEED                 :{LTBLUE}{ENGINE}{BLACK}   Стоимость: {LTBLUE}{CURRENCY} {BLACK}Макс. скорость: {LTBLUE}{VELOCITY}
 
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT                   :{BLACK}Общая загруженность состава:
 STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY                        :{LTBLUE}- {CARGO} (Всего: {SHORTCARGO})
@@ -3333,6 +3677,9 @@
 
 # Vehicle refit
 STR_REFIT_CAPTION                                               :{WHITE}{VEHICLE} (Переоборудование)
+STR_REFIT_VEHICLE_SELECTION_TITLE                               :{GOLD}Выберите элементы состава для переоборудования:
+STR_REFIT_VEHICLE_SELECT_ALL                                    :{BLACK}{TINYFONT}ВСЕ
+STR_REFIT_VEHICLE_SELECT_ALL_TOOLTIP                            :{BLACK}Выбрать весь состав
 STR_REFIT_TITLE                                                 :{GOLD}Выберите тип груза для перевозки:
 STR_REFIT_NEW_CAPACITY_COST_OF_REFIT                            :{BLACK}Новая ёмкость: {GOLD}{CARGO}{}{BLACK}Стоимость переоборудования: {GOLD}{CURRENCY}
 STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT                   :{BLACK}Новая ёмкость: {GOLD}{CARGO}, {GOLD}{CARGO}{}{BLACK}Стоимость переоборудования: {GOLD}{CURRENCY}
@@ -3521,6 +3868,7 @@
 STR_TIMETABLE_AND_TRAVEL_FOR                                    :и идти до {STRING}
 STR_TIMETABLE_DAYS                                              :{COMMA} д{P ень ня ней}
 STR_TIMETABLE_TICKS                                             :{COMMA} тик{P "" а ов}
+STR_TIMETABLE_MINUTES                                           :{COMMA} минут{P а ы ""}
 
 STR_TIMETABLE_TOTAL_TIME                                        :{BLACK}Весь маршрут займёт {STRING}
 STR_TIMETABLE_TOTAL_TIME_INCOMPLETE                             :{BLACK}Движение по маршруту займёт {STRING} (не всё учтено)
@@ -3535,7 +3883,7 @@
 STR_TIMETABLE_STARTING_DATE_TOOLTIP                             :{BLACK}Изменить дату начала расчёта графика движения
 
 STR_TIMETABLE_CHANGE_TIME                                       :{BLACK}Изменить время
-STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Изменить время для выделенного задания
+STR_TIMETABLE_WAIT_TIME_TOOLTIP                                 :{BLACK}Изменить время для выделенного задания. Ctrl+щелчок позволяет изменить время ожидания для всех станций сразу.
 
 STR_TIMETABLE_CLEAR_TIME                                        :{BLACK}Сбросить время
 STR_TIMETABLE_CLEAR_TIME_TOOLTIP                                :{BLACK}Сбросить время в выделенном задании
@@ -3546,6 +3894,9 @@
 STR_TIMETABLE_AUTOFILL                                          :{BLACK}Авторасчёт
 STR_TIMETABLE_AUTOFILL_TOOLTIP                                  :{BLACK}Заполнить расписание автоматически временем, затраченным на движение в следующей поездке. Ctrl+клик, чтобы при этом не изменялось время ожидания.
 
+STR_TIMETABLE_AUTOMATE                                          :{BLACK}Автомат
+STR_TIMETABLE_AUTOMATE_TOOLTIP                                  :{BLACK}Заполнять график автоматически, обновляя каждый рейс. Отключите для остановки обновления и оставления текущего расписания. Ctrl+отключить очищает текущее расписание.
+
 STR_TIMETABLE_EXPECTED                                          :{BLACK}Ожидаемое время
 STR_TIMETABLE_SCHEDULED                                         :{BLACK}Расписание
 STR_TIMETABLE_EXPECTED_TOOLTIP                                  :{BLACK}Переключение между графиком движения и ожидаемым временем прибытия/отправления
@@ -3561,6 +3912,8 @@
 STR_DATE_DAY_TOOLTIP                                            :{BLACK}Выбор дня
 STR_DATE_MONTH_TOOLTIP                                          :{BLACK}Выбор месяца
 STR_DATE_YEAR_TOOLTIP                                           :{BLACK}Выбор года
+STR_DATE_MINUTES_DAY_TOOLTIP                                    :{BLACK}Выбор минуты
+STR_DATE_MINUTES_MONTH_TOOLTIP                                  :{BLACK}Выбор часа
 
 
 # AI debug window
@@ -3638,6 +3991,10 @@
 STR_INCOME_FLOAT_INCOME                                         :{GREEN}Доход: {CURRENCY}
 STR_FEEDER_TINY                                                 :{TINYFONT}{YELLOW}Трансфер: {CURRENCY}
 STR_FEEDER                                                      :{YELLOW}Трансфер: {CURRENCY}
+STR_FEEDER_INCOME_TINY                                          :{TINYFONT}{YELLOW}Трансфер: {CURRENCY}{WHITE} / {GREEN}Доход: {CURRENCY}
+STR_FEEDER_INCOME                                               :{YELLOW}Трансфер: {CURRENCY}{WHITE} / {GREEN}Доход: {CURRENCY}
+STR_FEEDER_COST_TINY                                            :{TINYFONT}{YELLOW}Трансфер: {CURRENCY}{WHITE} / {RED}Цена: {CURRENCY}
+STR_FEEDER_COST                                                 :{YELLOW}Трансфер: {CURRENCY}{WHITE} / {RED}Цена: {CURRENCY}
 STR_MESSAGE_ESTIMATED_COST                                      :{WHITE}Предполагаемая цена: {CURRENCY}
 STR_MESSAGE_ESTIMATED_INCOME                                    :{WHITE}Предполагаемый доход: {CURRENCY}
 
@@ -3657,6 +4014,11 @@
 STR_GAME_SAVELOAD_NOT_AVAILABLE                                 :<недоступно>
 STR_WARNING_LOADGAME_REMOVED_TRAMS                              :{WHITE}Игра была сохранена в версии без поддержки трамваев. Все трамваи удалены.
 
+STR_PROFILE_LOAD_ERROR                                          :{WHITE}Не удалось загрузить профиль
+STR_PROFILE_SAVE_ERROR                                          :{WHITE}Не удалось сохранить профиль
+STR_PROFILE_FACE_ERROR                                          :{WHITE}Неверное лицо компании
+STR_PROFILE_COLOUR_ERROR                                        :{WHITE}Неверный цвет компании
+
 # Map generation messages
 STR_ERROR_COULD_NOT_CREATE_TOWN                                 :{WHITE}Генерация карты остановлена...{}... нет доступных мест для размещения городов
 STR_ERROR_NO_TOWN_IN_SCENARIO                                   :{WHITE}... в этом сценарии нет городов
@@ -3673,6 +4035,7 @@
 
 STR_WARNING_HEIGHTMAP_SCALE_CAPTION                             :{WHITE}Выход за пределы доступных значений
 STR_WARNING_HEIGHTMAP_SCALE_MESSAGE                             :{YELLOW}Изменение размеров исходной карты до таких значений не рекомендуется. Продолжить?
+STR_MAPGEN_TOO_MANY_TILES_MESSAGE                               :{YELLOW}Слишком много клеток на карте. Максимальное количество клеток равно {NUM}, вы выбрали {NUM}
 
 # Soundset messages
 STR_WARNING_FALLBACK_SOUNDSET                                   :{WHITE}Текущая звуковая схема выбрана системой автоматически. Дополнительные наборы звуков можно загрузить через систему онлайн контента.
@@ -3856,6 +4219,7 @@
 # Rail construction errors
 STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION                          :{WHITE}Недопустимая комбинация путей
 STR_ERROR_MUST_REMOVE_SIGNALS_FIRST                             :{WHITE}Сначала удалите сигналы
+STR_ERROR_MUST_REMOVE_EXIT_SIGNALS_FIRST                        :{WHITE}Сначала удалите выходные сигналы
 STR_ERROR_NO_SUITABLE_RAILROAD_TRACK                            :{WHITE}Нет подходящих рельсов
 STR_ERROR_MUST_REMOVE_RAILROAD_TRACK                            :{WHITE}Сначала удалите рельсы
 STR_ERROR_CROSSING_ON_ONEWAY_ROAD                               :{WHITE}Дорога односторонняя или блокирована
@@ -3870,12 +4234,21 @@
 
 STR_ERROR_CAN_T_CONVERT_RAIL                                    :{WHITE}Здесь невозможно преобразовать тип рельса...
 
+STR_ERROR_SIGNAL_CHANGES                                        :{WHITE}Количество вычислений программируемых сигналов превысило лимит
+
 # Road construction errors
 STR_ERROR_MUST_REMOVE_ROAD_FIRST                                :{WHITE}Сначала удалите дорогу
 STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION                      :{WHITE}... односторонние дороги не могут иметь такое пересечение
 STR_ERROR_CAN_T_BUILD_ROAD_HERE                                 :{WHITE}Здесь невозможно построить дорогу...
 STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE                              :{WHITE}Здесь невозможно проложить трамвайные пути...
 STR_ERROR_CAN_T_REMOVE_ROAD_FROM                                :{WHITE}Не удалось удалить дорогу...
+STR_ERROR_CAN_T_REMOVE_TRAFFIC_LIGHTS_FROM                      :{WHITE}Не удалось удалить светофоры...
+STR_ERROR_MUST_REMOVE_TRAFFIC_LIGHTS_FIRST                      :{WHITE}... сначала удалите светофоры
+STR_ERROR_TRAFFIC_LIGHT_CONSIST_TOO_BIG                         :{WHITE}... состав светофоров слишком велик
+STR_ERROR_CAN_T_PLACE_TRAFFIC_LIGHTS                            :{WHITE}Невозможно поместить светофоры...
+STR_ERROR_CAN_ONLY_BE_PLACED_ON_ROAD_JUNCTIONS                  :{WHITE}... могут быть построены только на перекрестках
+STR_ERROR_BUILDING_TRAFFIC_LIGHTS_DISABLED                      :{WHITE}... выключена возможность постройки светофоров, включите ее в Расширенные настройки -> Строительство -> Светофоры
+STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS              :{WHITE}... выключена возможность постройки светофоров в городах, включите ее в Расширенные настройки -> Строительство -> Светофоры
 STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM                             :{WHITE}Не удалось удалить трамвайные пути...
 STR_ERROR_THERE_IS_NO_ROAD                                      :{WHITE}...здесь нет дороги
 STR_ERROR_THERE_IS_NO_TRAMWAY                                   :{WHITE}...здесь нет трамвайных путей
@@ -3896,6 +4269,7 @@
 STR_ERROR_TREE_ALREADY_HERE                                     :{WHITE}... уже есть дерево
 STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE                      :{WHITE}... эти деревья здесь не растут
 STR_ERROR_CAN_T_PLANT_TREE_HERE                                 :{WHITE}Невозможно высадить деревья...
+STR_ERROR_TREE_ABOVE_TREE_LINE                                  :{WHITE}... клетка находится выше линии лесов.
 
 # Bridge related errors
 STR_ERROR_CAN_T_BUILD_BRIDGE_HERE                               :{WHITE}Здесь невозможно построить мост...
@@ -3903,6 +4277,7 @@
 STR_ERROR_CAN_T_START_AND_END_ON                                :{WHITE}Не может начинаться и заканчиваться в той же точке
 STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT                           :{WHITE}Опоры моста должны быть на одном уровне
 STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN                            :{WHITE}Слишком низкий мост
+STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN                           :{WHITE}Слишком высокий мост
 STR_ERROR_START_AND_END_MUST_BE_IN                              :{WHITE}Начало и конец должны быть на одной линии
 STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH                              :{WHITE}... оба конца моста должны опираться на землю
 STR_ERROR_BRIDGE_TOO_LONG                                       :{WHITE}... мост слишком длинный
@@ -4508,7 +4883,6 @@
 STR_JUST_DATE_ISO                                               :{DATE_ISO}
 STR_JUST_STRING                                                 :{STRING}
 STR_JUST_STRING_SPACE_STRING                                    :{STRING} {STRING}
-STR_JUST_RAW_STRING                                             :{STRING}
 
 # Slightly 'raw' stringcodes with colour or size
 STR_BLACK_COMMA                                                 :{BLACK}{COMMA}
@@ -4554,3 +4928,7 @@
 STR_SHIP                                                        :{BLACK}{SHIP}
 
 STR_TOOLBAR_RAILTYPE_VELOCITY                                   :{STRING} ({VELOCITY})
+
+STR_WATCH_WINDOW_TITLE                                          :{WHITE}Слежение {STRING}.
+STR_WATCH_CLICK_TO_WATCH_COMPANY                                :{BLACK}Щелкните для слежения за офисом компании
+STR_WATCH_CLICK_NEW_WINDOW                                      :{BLACK}Щелкните для открытия нового окна слежения
diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt
--- a/src/lang/serbian.txt
+++ b/src/lang/serbian.txt
@@ -1290,18 +1290,6 @@
 STR_CONFIG_SETTING_ON                                           :Da
 STR_CONFIG_SETTING_DISABLED                                     :isključeno
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Ne
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Za svoje preduzeće
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Za sva preduzeća
-
-STR_CONFIG_SETTING_NONE                                         :Nema
-STR_CONFIG_SETTING_ORIGINAL                                     :Originalna
-STR_CONFIG_SETTING_REALISTIC                                    :Realistična
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Levo
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Sredina
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Desno
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Dozvoljena gradnja na kosinama i obalama: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Dozvoljena izmena nagiba ispod zgrada, koloseka, itd. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Realističnije veličine prihvatnih površina: {ORANGE}{STRING}
@@ -2721,9 +2709,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Grad)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Populacija: {ORANGE}{COMMA}{BLACK}  Zgrada: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Broj putnika tokom meseca: {ORANGE}{COMMA}{BLACK}  najviše: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Količina pošte tokom meseca: {ORANGE}{COMMA}{BLACK}  najviše: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Tovar potreban za razvoj naselja:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Broj putnika tokom meseca: {ORANGE}{COMMA}{BLACK}  najviše: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Količina pošte tokom meseca: {ORANGE}{COMMA}{BLACK}  najviše: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Tovar potreban za razvoj naselja:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} potrebno
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} potrebno zimi
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} dostavljeno prošlog meseca
diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt
--- a/src/lang/simplified_chinese.txt
+++ b/src/lang/simplified_chinese.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :打开
 STR_CONFIG_SETTING_DISABLED                                     :禁用
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :关闭
-STR_CONFIG_SETTING_COMPANIES_OWN                                :玩家公司
-STR_CONFIG_SETTING_COMPANIES_ALL                                :全部公司
-
-STR_CONFIG_SETTING_NONE                                         :无
-STR_CONFIG_SETTING_ORIGINAL                                     :原版
-STR_CONFIG_SETTING_REALISTIC                                    :真实
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :左侧
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :中央
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :右侧
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}允许在斜坡和河岸上建设：{ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}允许在建筑、轨道等下方改变地形（自动斜坡）： {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}允许更真实的客源范围：{ORANGE}{STRING}
@@ -2523,9 +2511,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (都市)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}人口：{ORANGE}{COMMA}{BLACK}  房屋：{ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}上月旅客数量：{ORANGE}{COMMA}{BLACK}  最大值：{ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}上月邮包数量：{ORANGE}{COMMA}{BLACK}  最大值：{ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}城镇发展所必需的货物：
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}上月旅客数量：{ORANGE}{COMMA}{BLACK}  最大值：{ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}上月邮包数量：{ORANGE}{COMMA}{BLACK}  最大值：{ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}城镇发展所必需的货物：
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{BLACK} 需要： {ORANGE}{STRING}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} 冬季的需求
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{BLACK} 上个月已运到： {ORANGE}{CARGO}
diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt
--- a/src/lang/slovak.txt
+++ b/src/lang/slovak.txt
@@ -1163,18 +1163,6 @@
 STR_CONFIG_SETTING_ON                                           :áno
 STR_CONFIG_SETTING_DISABLED                                     :zakázané
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Vypnutý
-STR_CONFIG_SETTING_COMPANIES_OWN                                :vlastná spoločnosť
-STR_CONFIG_SETTING_COMPANIES_ALL                                :všetky spoločnosti
-
-STR_CONFIG_SETTING_NONE                                         :Žiadne
-STR_CONFIG_SETTING_ORIGINAL                                     :Pôvodné
-STR_CONFIG_SETTING_REALISTIC                                    :Realistické
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :vlavo
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :v strede
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :vpravo
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Umožniť výstavbu na svahoch a na pobreží: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Povoliť úpravy terénu pod budovami, koľajami, a pod.: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Povoliť realistickejšiu veľkosť oblasti pokrytia: {ORANGE}{STRING}
diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt
--- a/src/lang/slovenian.txt
+++ b/src/lang/slovenian.txt
@@ -1248,18 +1248,6 @@
 STR_CONFIG_SETTING_ON                                           :Vklopi
 STR_CONFIG_SETTING_DISABLED                                     :onemogočeno
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Izklop
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Lastno podjetje
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Vsa podjetja
-
-STR_CONFIG_SETTING_NONE                                         :Brez
-STR_CONFIG_SETTING_ORIGINAL                                     :Originalno
-STR_CONFIG_SETTING_REALISTIC                                    :Realistično
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Levo
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Sredina
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Desno
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Dovoli gradnjo hiš na nagibih ali obali: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Dovoli oblikovanje terena pod objekti, tiri, ipd. (samonaklon): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Dovoli bolj resnični območni zajem postaj: {ORANGE}{STRING}
@@ -2679,9 +2667,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Mesto)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Prebivalstvo: {ORANGE}{COMMA}{BLACK}  Število stavb: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Potnikov prejšnji mesec: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Pošte prejšnji mesec: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Količina potrebnega tovora za rast mesta:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Potnikov prejšnji mesec: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Pošte prejšnji mesec: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Količina potrebnega tovora za rast mesta:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} potrebno
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} je potreben pozimi
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} podeljeno zadnji mesec
diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt
--- a/src/lang/spanish.txt
+++ b/src/lang/spanish.txt
@@ -1096,18 +1096,6 @@
 STR_CONFIG_SETTING_ON                                           :Sí
 STR_CONFIG_SETTING_DISABLED                                     :desactivado
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Apagado
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Propia empresa
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Todas las empresas
-
-STR_CONFIG_SETTING_NONE                                         :Ninguna
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realista
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Izquierda
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centro
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Derecha
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Permitir la construcción en cuestas y orillas: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Permitir modificar terreno bajo carreteras, raíles, etc.: {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Permitir tamaño del área de captación más realista: {ORANGE}{STRING}
@@ -2560,9 +2548,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Ciudad)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Habitantes: {ORANGE}{COMMA}{BLACK}  Casas: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Pasajeros último mes: {ORANGE}{COMMA}{BLACK}  Máx.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Correo último mes: {ORANGE}{COMMA}{BLACK}  Máx.: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Carga necesaria para crecimiento del pueblo:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Pasajeros último mes: {ORANGE}{COMMA}{BLACK}  Máx.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Correo último mes: {ORANGE}{COMMA}{BLACK}  Máx.: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Carga necesaria para crecimiento del pueblo:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} requeridos
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} requerido en invierno
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} entregados último mes
diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt
--- a/src/lang/swedish.txt
+++ b/src/lang/swedish.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :På
 STR_CONFIG_SETTING_DISABLED                                     :Avaktiverat
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Av
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eget företag
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alla företag
-
-STR_CONFIG_SETTING_NONE                                         :Ingen
-STR_CONFIG_SETTING_ORIGINAL                                     :Original
-STR_CONFIG_SETTING_REALISTIC                                    :Realistiskt
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Vänster
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Centrerad
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Höger
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Tillåt konstruktion på sluttningar och kuster: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Tillåt landskapsarkitektur under byggnader, spår, etc. (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Tillåt mer realistiska uppsamlingsområden för stationer: {ORANGE}{STRING}
@@ -1178,6 +1166,7 @@
 STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS                 :TerraGenesis
 STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Max avstånd ifrån kanten för oljeraffinaderier: {ORANGE}{STRING} rut{P 0:1 a or}
 STR_CONFIG_SETTING_SNOWLINE_HEIGHT                              :{LTBLUE}Snölinjeshöjd: {ORANGE}{STRING}
+STR_CONFIG_SETTING_TREELINE_HEIGHT                              :{LTBLUE}Höjd för trädgräns: {ORANGE}{STRING}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN                         :{LTBLUE}Terrängens svårhetsgrad (TerraGenesis endast) : {ORANGE}{STRING}
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH             :Väldigt lätt
 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH                  :Lätt
@@ -2559,9 +2548,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Stad)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Invånare: {ORANGE}{COMMA}{BLACK}  Hus: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Passagerare förra månaden: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Post förra månaden: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Fraktgods behövs för ortens tillväxt:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Passagerare förra månaden: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Post förra månaden: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Fraktgods behövs för ortens tillväxt:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} nödvändlig
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} krävs under vintern
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} levererat den senaste månaden
diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt
--- a/src/lang/traditional_chinese.txt
+++ b/src/lang/traditional_chinese.txt
@@ -1088,18 +1088,6 @@
 STR_CONFIG_SETTING_ON                                           :開
 STR_CONFIG_SETTING_DISABLED                                     :關閉
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :無
-STR_CONFIG_SETTING_COMPANIES_OWN                                :自家公司
-STR_CONFIG_SETTING_COMPANIES_ALL                                :所有公司
-
-STR_CONFIG_SETTING_NONE                                         :無
-STR_CONFIG_SETTING_ORIGINAL                                     :原版
-STR_CONFIG_SETTING_REALISTIC                                    :真實
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :靠左
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :置中
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :靠右
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}可在斜坡及岸邊興建：{ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}允許在建築物或軌道底下改變地形斜度 (autoslope)：{ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}依車站種類不同改變收集範圍：{ORANGE}{STRING}
@@ -1339,9 +1327,6 @@
 STR_CONFIG_SETTING_ECONOMY_TOWNS                                :{ORANGE}市鎮
 STR_CONFIG_SETTING_ECONOMY_INDUSTRIES                           :{ORANGE}工業
 
-STR_CONFIG_SETTING_PATHFINDER_NPF                               :NPF
-STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED                  :YAPF {BLUE}(建議)
-
 STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS                        :{LTBLUE}列車的路徑搜尋方式：{ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES                 :{LTBLUE}車輛的路徑搜尋方式：{ORANGE}{STRING}
 STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS                         :{LTBLUE}船隻的路徑搜尋方式：{ORANGE}{STRING}
@@ -2506,9 +2491,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (城市)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}人口：{ORANGE}{COMMA}{BLACK}  房屋：{ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}上月乘客：{ORANGE}{COMMA}{BLACK}  最多：{ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}上月郵件：{ORANGE}{COMMA}{BLACK}  最多：{ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}市鎮成長所需貨物：
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}上月乘客：{ORANGE}{COMMA}{BLACK}  最多：{ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}上月郵件：{ORANGE}{COMMA}{BLACK}  最多：{ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}市鎮成長所需貨物：
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{BLACK}還需要 {ORANGE}{STRING}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} 必須是冬天
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{BLACK}上個月已運送 {ORANGE}{CARGO}
diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt
--- a/src/lang/turkish.txt
+++ b/src/lang/turkish.txt
@@ -1096,18 +1096,6 @@
 STR_CONFIG_SETTING_ON                                           :Açık
 STR_CONFIG_SETTING_DISABLED                                     :kapalı
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Kapalı
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Kendi şirketim
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Tüm şirketler
-
-STR_CONFIG_SETTING_NONE                                         :Yok
-STR_CONFIG_SETTING_ORIGINAL                                     :Orijinal
-STR_CONFIG_SETTING_REALISTIC                                    :Gerçekçi
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Sol
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Orta
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Sağ
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Sahile ve eğimli araziye inşaat: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Binaların, yolların, rayların v.b. altındaki araziyi değiştirmeye izin ver (otomatik eğim): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}İstasyon kapsama alanlarının daha gerçeğe yakın ölçülerde olmasına izin ver: {ORANGE}{STRING}
@@ -2527,9 +2515,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Şehir)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Nüfus: {ORANGE}{COMMA}{BLACK}  Ev: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Geçen ayki yolcular: {ORANGE}{COMMA}{BLACK}  mak: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Geçen ayki posta: {ORANGE}{COMMA}{BLACK}  mak: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Kasaba büyümesi için gerekli kargo:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Geçen ayki yolcular: {ORANGE}{COMMA}{BLACK}  mak: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Geçen ayki posta: {ORANGE}{COMMA}{BLACK}  mak: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Kasaba büyümesi için gerekli kargo:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} gerekli
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} kışın gerekir
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :Geçen ay {ORANGE}{CARGO}{BLACK} taşındı
diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt
--- a/src/lang/ukrainian.txt
+++ b/src/lang/ukrainian.txt
@@ -1214,18 +1214,6 @@
 STR_CONFIG_SETTING_ON                                           :Так
 STR_CONFIG_SETTING_DISABLED                                     :вимкнено
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :відкл.
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Власна компанія
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Усі компанії
-
-STR_CONFIG_SETTING_NONE                                         :Немає
-STR_CONFIG_SETTING_ORIGINAL                                     :Стандартно
-STR_CONFIG_SETTING_REALISTIC                                    :Реалістично
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Ліворуч
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :По центру
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Праворуч
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Будувати на схилах та узбережжях: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Дозволити міняти схили під будівлями, дорогами тощо (автосхил): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Великий район обслуговування: {ORANGE}{STRING}
@@ -2635,9 +2623,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (місто)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Населення: {ORANGE}{COMMA}{BLACK}  Будинки: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Пасажирів за місяць: {ORANGE}{COMMA}{BLACK} найбільше: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Пошти за місяць: {ORANGE}{COMMA}{BLACK} найбільше: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Вантаж, потрібний для зростання міста:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Пасажирів за місяць: {ORANGE}{COMMA}{BLACK} найбільше: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Пошти за місяць: {ORANGE}{COMMA}{BLACK} найбільше: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Вантаж, потрібний для зростання міста:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} потрібно
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} потрібно взимку
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} перевезено за останній місяць
diff --git a/src/lang/unfinished/basque.txt b/src/lang/unfinished/basque.txt
--- a/src/lang/unfinished/basque.txt
+++ b/src/lang/unfinished/basque.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :Piztuta
 STR_CONFIG_SETTING_DISABLED                                     :desaktibatua
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Itzalita
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Enpresa propioa
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Enpresa guztiak
-
-STR_CONFIG_SETTING_NONE                                         :Bat ere ez
-STR_CONFIG_SETTING_ORIGINAL                                     :Originala
-STR_CONFIG_SETTING_REALISTIC                                    :Errealista
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Ezkerra
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Erdia
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Eskuina
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Aldapa eta kostan eraikitzea baimendu: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Eraikinen, trenbideen etabarren azpian paisaia aldatzea baimendu. (autoaldapak): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Bilketa guneen tamaina errealago egitea baimendu: {ORANGE}{STRING}
diff --git a/src/lang/unfinished/chuvash.txt b/src/lang/unfinished/chuvash.txt
--- a/src/lang/unfinished/chuvash.txt
+++ b/src/lang/unfinished/chuvash.txt
@@ -563,16 +563,6 @@
 STR_CONFIG_SETTING_ON                                           :Ҫут
 STR_CONFIG_SETTING_DISABLED                                     :хастар мар
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Сӳнтер
-
-STR_CONFIG_SETTING_NONE                                         :Ҫук
-STR_CONFIG_SETTING_ORIGINAL                                     :Чӑн
-STR_CONFIG_SETTING_REALISTIC                                    :Реалисмлӑ
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Сулахайра
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Варринче
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Сылтӑмра
-
 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE        :ҫук
 STR_CONFIG_SETTING_PLANE_CRASHES_NONE                           :ҫук
 
diff --git a/src/lang/unfinished/frisian.txt b/src/lang/unfinished/frisian.txt
--- a/src/lang/unfinished/frisian.txt
+++ b/src/lang/unfinished/frisian.txt
@@ -1088,18 +1088,6 @@
 STR_CONFIG_SETTING_ON                                           :oan
 STR_CONFIG_SETTING_DISABLED                                     :utskeakele
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Ût
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Eigen bedriuw
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Alle bedriuwen
-
-STR_CONFIG_SETTING_NONE                                         :Gjin
-STR_CONFIG_SETTING_ORIGINAL                                     :Orizjiniel
-STR_CONFIG_SETTING_REALISTIC                                    :Realistysk
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Lofts
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Midden
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Rjochts
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}It boue op in helling tastean: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Omkriten oanpasse under gebouen, spoaren, ensafuorthinne tastean (autoslope): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Gebrûk meer realistyske hannelsgebieten: {ORANGE}{STRING}
diff --git a/src/lang/unfinished/thai.txt b/src/lang/unfinished/thai.txt
--- a/src/lang/unfinished/thai.txt
+++ b/src/lang/unfinished/thai.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :เปิด
 STR_CONFIG_SETTING_DISABLED                                     :ไม่ให้เรียกใช้งาน
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :ปิด
-STR_CONFIG_SETTING_COMPANIES_OWN                                :บริษัทที่เป็นเจ้าของ
-STR_CONFIG_SETTING_COMPANIES_ALL                                :บริษัททั้งหมด
-
-STR_CONFIG_SETTING_NONE                                         :ไม่มี
-STR_CONFIG_SETTING_ORIGINAL                                     :ดั้งเดิม
-STR_CONFIG_SETTING_REALISTIC                                    :สมจริง
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :ซ้าย
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :กลาง
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :ขวา
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}อนุญาตให้สร้างบนที่ชันและริมตลิ่ง: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}อนุญาตให้เปลี่ยนสภาพพื้นผิวใต้สิ่งก่อสร้าง, ราง, ฯลฯ (ปรับความชันอัตโนมัติ): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}อนุญาตให้มีขนาดของพื้นที่เก็บน้ำที่สมเหตุสมผลมากขึ้น: {ORANGE}{STRING}
@@ -2316,8 +2304,8 @@
 STR_TOWN_DIRECTORY_NONE                                         :{ORANGE}- ไม่มี -
 
 # Town view window
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}ผู้โดยสารเมื่อเดือนที่แล้ว: {ORANGE}{COMMA}{BLACK}  จำนวนสูงสุด: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}จดหมายเมื่อเดือนที่แล้ว: {ORANGE}{COMMA}{BLACK}  จำนวนสูงสุด: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}ผู้โดยสารเมื่อเดือนที่แล้ว: {ORANGE}{COMMA}{BLACK}  จำนวนสูงสุด: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}จดหมายเมื่อเดือนที่แล้ว: {ORANGE}{COMMA}{BLACK}  จำนวนสูงสุด: {ORANGE}{COMMA}
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} ต้องการหิมะ
 STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON                            :{BLACK}เจ้าหน้าที่ท้องถิ่น
 STR_TOWN_VIEW_RENAME_TOOLTIP                                    :{BLACK}เปลี่ยนชื่อเมือง
diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt
--- a/src/lang/vietnamese.txt
+++ b/src/lang/vietnamese.txt
@@ -1095,18 +1095,6 @@
 STR_CONFIG_SETTING_ON                                           :Bật
 STR_CONFIG_SETTING_DISABLED                                     :tắt
 
-STR_CONFIG_SETTING_COMPANIES_OFF                                :Tắt
-STR_CONFIG_SETTING_COMPANIES_OWN                                :Công ty mình
-STR_CONFIG_SETTING_COMPANIES_ALL                                :Tất cả công ty
-
-STR_CONFIG_SETTING_NONE                                         :Không
-STR_CONFIG_SETTING_ORIGINAL                                     :Nguyên bản
-STR_CONFIG_SETTING_REALISTIC                                    :Giống Thực
-
-STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT                          :Trái
-STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER                        :Giữa
-STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT                         :Phải
-
 STR_CONFIG_SETTING_BUILDONSLOPES                                :{LTBLUE}Cho phép xây dựng trên dốc và bờ biển: {ORANGE}{STRING}
 STR_CONFIG_SETTING_AUTOSLOPE                                    :{LTBLUE}Cho phép thay đổi nền đất dưới công trình, đường.. (tự làm dốc): {ORANGE}{STRING}
 STR_CONFIG_SETTING_CATCHMENT                                    :{LTBLUE}Mô phỏng thực tế diện tích khu vực đón hàng: {ORANGE}{STRING}
@@ -2559,9 +2547,9 @@
 STR_TOWN_VIEW_TOWN_CAPTION                                      :{WHITE}{TOWN}
 STR_TOWN_VIEW_CITY_CAPTION                                      :{WHITE}{TOWN} (Thành Phố)
 STR_TOWN_VIEW_POPULATION_HOUSES                                 :{BLACK}Dân số: {ORANGE}{COMMA}{BLACK}  Toà nhà: {ORANGE}{COMMA}
-STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX                         :{BLACK}Du khách tháng trước: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX                               :{BLACK}Bưu kiện tháng trước: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
-STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH                              :{BLACK}Hàng hoá cần để đô thị tăng trưởng:
+STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX                     :{BLACK}Du khách tháng trước: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX                     :{BLACK}Bưu kiện tháng trước: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH                   :{BLACK}Hàng hoá cần để đô thị tăng trưởng:
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED                     :{ORANGE}{STRING}{BLACK} được yêu cầu
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER              :{ORANGE}{STRING}{BLACK} Yêu cầu trong mùa đông
 STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH                   :{ORANGE}{CARGO}{BLACK} đã cung cấp tháng trước
diff --git a/src/linkgraph/demands.cpp b/src/linkgraph/demands.cpp
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/demands.cpp
@@ -0,0 +1,192 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file demands.h Definition of demand calculating link graph handler. */
+
+#include "demands.h"
+#include "../station_base.h"
+#include "../settings_type.h"
+#include "../newgrf_cargo.h"
+#include "../cargotype.h"
+#include "../core/math_func.hpp"
+#include <list>
+
+typedef std::list<NodeID> NodeList;
+
+/**
+ * Set the demands between two nodes using the given base demand. In symmetric mode
+ * this sets demands in both directions.
+ * @param graph The link graph
+ * @param from_id The supplying node
+ * @þaram to_id The receiving node
+ * @param demand_forw Demand calculated for the "forward" direction
+ */
+void SymmetricScaler::SetDemands(LinkGraphComponent * graph, NodeID from_id, NodeID to_id, uint demand_forw)
+{
+	if (graph->GetNode(from_id).demand > 0) {
+		uint demand_back = demand_forw * this->mod_size / 100;
+		uint undelivered = graph->GetNode(to_id).undelivered_supply;
+		if (demand_back > undelivered) {
+			demand_back = undelivered;
+			demand_forw = max(1U, demand_back * 100 / this->mod_size);
+		}
+		this->Scaler::SetDemands(graph, to_id, from_id, demand_back);
+	}
+
+	this->Scaler::SetDemands(graph, from_id, to_id, demand_forw);
+}
+
+/**
+ * Set the demands between two nodes using the given base demand. In asymmetric mode
+ * this only sets demand in the "forward" direction.
+ * @param graph The link graph
+ * @param from_id The supplying node
+ * @þaram to_id The receiving node
+ * @param demand_forw Demand calculated for the "forward" direction
+ */
+FORCEINLINE void Scaler::SetDemands(LinkGraphComponent * graph, NodeID from_id, NodeID to_id, uint demand_forw)
+{
+	Edge &forward = graph->GetEdge(from_id, to_id);
+	forward.demand += demand_forw;
+	forward.unsatisfied_demand += demand_forw;
+	graph->GetNode(from_id).undelivered_supply -= demand_forw;
+}
+
+/**
+ * Do the actual demand calculation, called from constructor.
+ * @param graph the component to calculate the demands for
+ */
+template<class Tscaler>
+void DemandCalculator::CalcDemand(LinkGraphComponent *graph, Tscaler scaler)
+{
+	NodeList supplies;
+	NodeList demands;
+	uint num_supplies = 0;
+	uint num_demands = 0;
+
+	for(NodeID node = 0; node < graph->GetSize(); node++) {
+		Node &n = graph->GetNode(node);
+		scaler.AddNode(n);
+		if (n.supply > 0) {
+			supplies.push_back(node);
+			num_supplies++;
+		}
+		if (n.demand > 0) {
+			demands.push_back(node);
+			num_demands++;
+		}
+	}
+
+	if (num_supplies == 0 || num_demands == 0) return;
+
+	/* mean acceptance attributed to each node. If the distribution is
+	 * symmetric this is relative to remote supply, otherwise it is
+	 * relative to remote demand.
+	 */
+	scaler.SetDemandPerNode(num_demands);
+	uint chance = 0;
+
+	while(!supplies.empty() && !demands.empty()) {
+		NodeID node1 = supplies.front();
+		supplies.pop_front();
+
+		Node &from = graph->GetNode(node1);
+
+		for(uint i = 0; i < num_demands; ++i) {
+			assert(!demands.empty());
+			NodeID node2 = demands.front();
+			demands.pop_front();
+			if (node1 == node2) {
+				if (demands.empty() && supplies.empty()) {
+					/* only one node with supply and demand left */
+					return;
+				} else {
+					demands.push_back(node2);
+					continue;
+				}
+			}
+			Node &to = graph->GetNode(node2);
+
+			int32 supply = scaler.EffectiveSupply(from, to);
+			assert(supply > 0);
+
+			/* scale the distance by mod_dist around max_distance */
+			int32 distance = this->max_distance - (this->max_distance -
+					(int32)graph->GetEdge(node1, node2).distance) * this->mod_dist / 100;
+
+			/* scale the accuracy by distance around accuracy / 2 */
+			int32 divisor = this->accuracy * (this->mod_dist - 50) / 100 +
+					this->accuracy * distance / this->max_distance + 1;
+
+			assert(divisor > 0);
+
+			uint demand_forw = 0;
+			if (divisor <= supply) {
+				/* at first only distribute demand if
+				 * effective supply / accuracy divisor >= 1
+				 * Others are too small or too far away to be considered.
+				 */
+				demand_forw = supply / divisor;
+			} else if (++chance > this->accuracy * num_demands * num_supplies) {
+				/* After some trying, if there is still supply left, distribute
+				 * demand also to other nodes.
+				 */
+				demand_forw = 1;
+			}
+
+			demand_forw = min(demand_forw, from.undelivered_supply);
+
+			scaler.SetDemands(graph, node1, node2, demand_forw);
+
+			if (scaler.DemandLeft(to)) {
+				demands.push_back(node2);
+			} else {
+				num_demands--;
+			}
+
+			if (from.undelivered_supply == 0) break;
+
+		}
+		if (from.undelivered_supply != 0) {
+			supplies.push_back(node1);
+		} else {
+			num_supplies--;
+		}
+	}
+}
+
+/**
+ * Create the DemandCalculator and immediately do the calculation.
+ * @param graph the component to calculate the demands for
+ */
+DemandCalculator::DemandCalculator(LinkGraphComponent *graph) :
+	max_distance(MapSizeX() + MapSizeY() + 1)
+{
+	CargoID cargo = graph->GetCargo();
+	const LinkGraphSettings &settings = graph->GetSettings();
+
+	this->accuracy = settings.accuracy;
+	this->mod_dist = settings.demand_distance;
+	if (this->mod_dist > 100) {
+		/* increase effect of mod_dist > 100 */
+		int over100 = this->mod_dist - 100;
+		this->mod_dist = 100 + over100 * over100;
+	}
+
+	switch (settings.GetDistributionType(cargo)) {
+	case DT_SYMMETRIC:
+		this->CalcDemand<SymmetricScaler>(graph, SymmetricScaler(settings.demand_size));
+		break;
+	case DT_ASYMMETRIC:
+		this->CalcDemand<AsymmetricScaler>(graph, AsymmetricScaler());
+		break;
+	default:
+		NOT_REACHED();
+	}
+}
diff --git a/src/linkgraph/demands.h b/src/linkgraph/demands.h
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/demands.h
@@ -0,0 +1,155 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file demands.h Declaration of demand calculating link graph handler. */
+
+#ifndef DEMANDS_H_
+#define DEMANDS_H_
+
+#include "linkgraph.h"
+#include "../stdafx.h"
+#include "../cargo_type.h"
+#include "../map_func.h"
+
+/**
+ * scale various things according to symmetric/asymmetric distribution
+ */
+class Scaler {
+public:
+	Scaler() : demand_per_node(0) {}
+
+	void SetDemands(LinkGraphComponent * graph, NodeID from, NodeID to, uint demand_forw);
+protected:
+	uint demand_per_node; ///< mean demand associated with each node
+};
+
+/**
+ * Scaler for symmetric distribution
+ */
+class SymmetricScaler : public Scaler {
+public:
+	FORCEINLINE SymmetricScaler(uint mod_size) : mod_size(mod_size), supply_sum(0) {}
+
+	/**
+	 * count a node's supply into the sum of supplies
+	 * @param node the node
+	 */
+	FORCEINLINE void AddNode(const Node &node) {this->supply_sum += node.supply;}
+
+	/**
+	 * calculate the mean demand per node using the sum of supplies
+	 * @param num_demands the number of accepting nodes
+	 */
+	FORCEINLINE void SetDemandPerNode(uint num_demands)
+		{this->demand_per_node = max(this->supply_sum / num_demands, 1U);}
+
+	/**
+	 * get the effective supply of one node towards another one. In symmetric
+	 * distribution the supply of the other node is weighed in.
+	 * @param from The supplying node
+	 * @param to The receiving node
+	 * @return the effective supply
+	 */
+	FORCEINLINE uint EffectiveSupply(const Node &from, const Node &to)
+		{return max(from.supply * max(1U, to.supply) * this->mod_size / 100 / this->demand_per_node, 1U);}
+
+	/**
+	 * Check if there is any acceptance left for this node. In symmetric distribution
+	 * nodes only accept anything if they also supply something. So if
+	 * undelivered_supply == 0 at the node there isn't any demand left either
+	 * @param to The node to be checked
+	 */
+	FORCEINLINE bool DemandLeft(Node &to)
+		{return (to.supply == 0 || to.undelivered_supply > 0) && to.demand > 0;}
+
+	void SetDemands(LinkGraphComponent * graph, NodeID from, NodeID to, uint demand_forw);
+
+private:
+	uint mod_size;
+	uint supply_sum;
+};
+
+/**
+ * A scaler for asymmetric distribution.
+ */
+class AsymmetricScaler : public Scaler {
+public:
+	AsymmetricScaler() : demand_sum(0) {}
+
+	/**
+	 * count a node's demand into the sum of demands
+	 * @param node The node to be counted
+	 */
+	FORCEINLINE void AddNode(const Node &node) {this->demand_sum += node.demand;}
+
+	/**
+	 * calculate the mean demand per node using the sum of demands
+	 * @param num_demands the number of accepting nodes
+	 */
+	FORCEINLINE void SetDemandPerNode(uint num_demands)
+		{this->demand_per_node = max(this->demand_sum / num_demands, (uint)1);}
+
+	/**
+	 * get the effective supply of one node towards another one. In asymmetric
+	 * distribution the demand of the other node is weighed in.
+	 * @param from The supplying node
+	 * @param to The receiving node
+	 */
+	FORCEINLINE uint EffectiveSupply(const Node &from, const Node &to)
+		{return max(from.supply * to.demand / this->demand_per_node, (uint)1);}
+
+	/**
+	 * Check if there is any acceptance left for this node. In asymmetric distribution
+	 * nodes always accept as long as their demand > 0.
+	 * @param to The node to be checked
+	 */
+	FORCEINLINE bool DemandLeft(Node &to) {return to.demand > 0;}
+
+private:
+	uint demand_sum;
+
+};
+
+/**
+ * Calculate the demands. This class has a state, but is recreated for each
+ * call to of DemandHandler::Run.
+ */
+
+class DemandCalculator {
+public:
+	DemandCalculator(LinkGraphComponent *graph);
+
+private:
+	int32 max_distance; ///< maximum distance possible on the map
+	int32 mod_dist;     ///< distance modifier, determines how much demands decrease with distance
+	int32 accuracy;     ///< accuracy of the calculation
+
+	template<class Tscaler>
+	void CalcDemand(LinkGraphComponent *graph, Tscaler scaler);
+};
+
+/**
+ * Stateless, thread safe demand hander. Doesn't do anything but call DemandCalculator.
+ */
+class DemandHandler : public ComponentHandler {
+public:
+
+	/**
+	 * Call the demand calculator on the given component-
+	 * @param graph the component to calculate the demands for.
+	 */
+	virtual void Run(LinkGraphComponent *graph) {DemandCalculator c(graph);}
+
+	/**
+	 * Virtual destructor has to be defined because of virtual Run().
+	 */
+	virtual ~DemandHandler() {}
+};
+
+#endif /* DEMANDS_H_ */
diff --git a/src/linkgraph/flowmapper.cpp b/src/linkgraph/flowmapper.cpp
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/flowmapper.cpp
@@ -0,0 +1,50 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file flowmapper.cpp Definition of flowmapper */
+
+#include "flowmapper.h"
+
+/**
+ * Map the paths generated by the MCF solver into flows associated with nodes.
+ * @param component the link graph component to be used.
+ */
+void FlowMapper::Run(LinkGraphComponent *component) {
+	for (NodeID node_id = 0; node_id < component->GetSize(); ++node_id) {
+		Node &prev_node = component->GetNode(node_id);
+		StationID prev = prev_node.station;
+		PathSet& paths = prev_node.paths;
+		for(PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
+			Path *path = *i;
+			uint flow = path->GetFlow();
+			if (flow == 0) continue;
+			Node &node = component->GetNode(path->GetNode());
+			StationID via = node.station;
+			assert(prev != via);
+			StationID origin = component->GetNode(path->GetOrigin()).station;
+			assert(via != origin);
+			/* mark all of the flow for local consumation at "first" */
+			node.flows[origin][via] += flow;
+			/* pass some of the flow marked for local consumation at "prev" on to this node */
+			prev_node.flows[origin][via] += flow;
+			/* find simple circular flows ... */
+			assert(node.flows[origin][prev] == 0);
+			if (prev != origin) {
+				prev_node.flows[origin][prev] -= flow;
+			}
+		}
+	}
+	for (NodeID node_id = 0; node_id < component->GetSize(); ++node_id) {
+		PathSet &paths = component->GetNode(node_id).paths;
+		for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
+			delete (*i);
+		}
+		paths.clear();
+	}
+}
diff --git a/src/linkgraph/flowmapper.h b/src/linkgraph/flowmapper.h
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/flowmapper.h
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file flowmapper.h Declaration of flow mapper; merges paths into flows at nodes */
+
+#ifndef FLOWMAPPER_H_
+#define FLOWMAPPER_H_
+
+#include "linkgraph.h"
+
+/**
+ * Map the path trees generated by the MCF solver into flows. The path tree is
+ * useful to cache capacities and distances and allow quick disconnecting and
+ * reconnecting to other paths. The flows show how much cargo from which nodes
+ * is to be routed in which direction at a given node. This is what we need in
+ * the end.
+ */
+class FlowMapper : public ComponentHandler {
+public:
+	virtual ~FlowMapper() {}
+	virtual void Run(LinkGraphComponent *component);
+};
+
+#endif /* FLOWMAPPER_H_ */
diff --git a/src/linkgraph/linkgraph.cpp b/src/linkgraph/linkgraph.cpp
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/linkgraph.cpp
@@ -0,0 +1,558 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file linkgraph.cpp Definition of link graph classes used for cargo distribution. */
+
+#include "linkgraph.h"
+#include "demands.h"
+#include "mcf.h"
+#include "flowmapper.h"
+#include "../map_func.h"
+#include "../core/bitmath_func.hpp"
+#include "../debug.h"
+#include "../window_func.h"
+#include "../window_gui.h"
+#include "../moving_average.h"
+#include <queue>
+
+/**
+ * Global array of link graphs, one for each cargo.
+ */
+LinkGraph _link_graphs[NUM_CARGO];
+
+/**
+ * Handlers to be run for each job.
+ */
+LinkGraphJob::HandlerList LinkGraphJob::_handlers;
+
+/**
+ * Create a node or clear it.
+ * @param st ID of the associated station
+ * @param sup supply of cargo at the station last month
+ * @param dem acceptance for cargo at the station
+ */
+void Node::Init(StationID st, uint sup, uint dem)
+{
+	this->supply = sup;
+	this->undelivered_supply = sup;
+	this->demand = dem;
+	this->station = st;
+
+	for (PathSet::iterator i = this->paths.begin(); i != this->paths.end(); ++i) {
+		delete (*i);
+	}
+	this->paths.clear();
+	this->flows.clear();
+}
+
+/**
+ * Create an edge.
+ * @param distance length of the link as manhattan distance
+ * @param capacity capacity of the link
+ */
+FORCEINLINE void Edge::Init(uint distance, uint capacity)
+{
+	this->distance = distance;
+	this->capacity = capacity;
+	this->demand = 0;
+	this->unsatisfied_demand = 0;
+	this->flow = 0;
+	this->next_edge =INVALID_NODE;
+}
+
+/**
+ * 1. Build the link graph component containing the given station by using BFS on the link stats.
+ * 2. Set every included station's last_component to the new component's ID (this->current_component_id).
+ * 3. Start a link graph job with the new component.
+ * @param first Station to start the search at
+ */
+void LinkGraph::CreateComponent(Station *first)
+{
+	std::map<Station *, NodeID> index;
+	index[first] = this->AddNode(first);
+
+	std::queue<Station *> search_queue;
+	search_queue.push(first);
+
+	/* find all stations belonging to the current component */
+	while(!search_queue.empty()) {
+		Station *source = search_queue.front();
+		search_queue.pop();
+
+		const LinkStatMap &links = source->goods[this->cargo].link_stats;
+		for(LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
+			Station *target = Station::GetIfValid(i->first);
+			if (target == NULL) continue;
+
+			std::map<Station *, NodeID>::iterator index_it = index.find(target);
+			if (index_it == index.end()) {
+				search_queue.push(target);
+				NodeID node = this->AddNode(target);
+				index[target] = node;
+
+				this->AddEdge(index[source], node,	i->second.Capacity());
+			} else {
+				this->AddEdge(index[source], index_it->second,	i->second.Capacity());
+			}
+		}
+	}
+
+	/* here the list of nodes and edges for this component is complete. */
+	this->SpawnThread();
+}
+
+/**
+ * Looks for a suitable station to create the next link graph component from.
+ * Linearly searches all stations starting from current_station_id for one that
+ * hasn't been visited in this run over the link graph. The current run and the
+ * last run are differentiated by giving the components IDs divisible by 2
+ * every second run and ones not divisible by 2 on the other runs.
+ *
+ * If such a station is found current_station_id is set to that station's ID
+ * and CreateComponent is called with it.
+ *
+ * The search wraps around and changes current_component_id to 0 or 1
+ * accordingly. If the starting point is reached again it stops.
+ */
+void LinkGraph::NextComponent()
+{
+	/* Check for no stations to avoid problems with Station::GetPoolSize()
+	 * being 0 later and to avoid searching an empty pool.
+	 */
+	if (Station::GetNumItems() == 0) return;
+
+	/* Don't mess with running jobs (might happen when changing interval).*/
+	if (this->GetSize() > 0) return;
+
+	/* The station pool may shrink when saving and subsequently loading a game as
+	 * NULL entries at the end are cut off then. If the current station id points
+	 * to one of those NULL entries we have to clamp it here to avoid an infinite
+	 * loop later.
+	 */
+	StationID last_station_id = min(this->current_station_id, Station::GetPoolSize() - 1);
+	LinkGraphComponentID current_component_id = this->LinkGraphComponent::index;
+
+	do {
+		if (++this->current_station_id >= Station::GetPoolSize()) {
+			/* Wrap around and recycle the component IDs. Use different
+			 * divisibility by 2 than in the last run so that we can find out
+			 * which stations haven't been seen in this run.
+			 */
+			this->current_station_id = 0;
+			if (current_component_id % 2 == 0) {
+				current_component_id = 1;
+			} else {
+				current_component_id = 0;
+			}
+		}
+
+		/* find first station of next component */
+		Station *station = Station::GetIfValid(this->current_station_id);
+		if (station != NULL) {
+			GoodsEntry &ge = station->goods[this->cargo];
+			if (ge.last_component == INVALID_LINKGRAPH_COMPONENT ||
+					(ge.last_component + current_component_id) % 2 != 0) {
+				/* Different divisibility by 2: This station has not been seen
+				 * in the current run over the link graph.
+				 */
+
+				if (!ge.link_stats.empty()) {
+					this->LinkGraphComponent::Init(current_component_id + 2);
+					CreateComponent(station);
+					return;
+				}
+			}
+		}
+
+	} while (this->current_station_id != last_station_id);
+}
+
+/**
+ * Spawn or join a link graph component if any link graph is due to do so.
+ * Spawning is done on COMPONENTS_SPAWN_TICK every day, joining on
+ * COMPONENT_JOIN_TICK. Each link graph is due every recalc_interval days.
+ */
+void OnTick_LinkGraph()
+{
+	if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK ||
+			_date_fract == LinkGraph::COMPONENTS_JOIN_TICK) {
+
+		/* This creates a fair distribution of all link graphs' turns over
+		 * the available dates.
+		 */
+		for (uint cargo = _date % _settings_game.linkgraph.recalc_interval; cargo < NUM_CARGO;
+				cargo += _settings_game.linkgraph.recalc_interval) {
+
+			/* don't calculate a link graph if the distribution is manual */
+			if (_settings_game.linkgraph.GetDistributionType(cargo) == DT_MANUAL) continue;
+
+			if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK) {
+				_link_graphs[cargo].NextComponent();
+			} else /* LinkGraph::COMPONENTS_JOIN_TICK */ {
+				_link_graphs[cargo].Join();
+			}
+		}
+	}
+}
+
+/**
+ * Add a node to the component and create empty edges associated with it. Set
+ * the station's last_component to this component. Calculate the distances to all
+ * other nodes. The distances to _all_ nodes are important as the demand
+ * calculator relies on their availability.
+ * @param st the new node's station
+ * @return the new node's ID
+ */
+NodeID LinkGraphComponent::AddNode(Station *st)
+{
+	GoodsEntry &good = st->goods[this->cargo];
+	good.last_component = this->index;
+
+	bool do_resize = (this->nodes.size() == this->num_nodes);
+
+	if (do_resize) {
+		this->nodes.push_back(Node());
+		this->edges.push_back(std::vector<Edge>(this->num_nodes + 1));
+	}
+
+	this->nodes[this->num_nodes].Init(st->index, good.supply,
+			HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE));
+
+	std::vector<Edge> &new_edges = this->edges[this->num_nodes];
+
+	/* reset the first edge starting at the new node */
+	new_edges[this->num_nodes].next_edge = INVALID_NODE;
+
+	for(NodeID i = 0; i < this->num_nodes; ++i) {
+		uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
+		if (do_resize) this->edges[i].push_back(Edge());
+		new_edges[i].Init(distance);
+		this->edges[i][this->num_nodes].Init(distance);
+	}
+	return this->num_nodes++;
+}
+
+/**
+ * Fill an edge with values from a link.
+ * @param from source node of the link
+ * @param to destination node of the link
+ * @param capacity capacity of the link
+ */
+FORCEINLINE void LinkGraphComponent::AddEdge(NodeID from, NodeID to, uint capacity)
+{
+	assert(from != to);
+	Edge &edge = this->edges[from][to];
+	Edge &first = this->edges[from][from];
+	edge.capacity = capacity;
+	edge.next_edge = first.next_edge;
+	first.next_edge = to;
+}
+
+/**
+ * Resize the component and fill it with empty nodes and edges. Used when
+ * loading from save games.
+ *
+ * WARNING: The nodes and edges are expected to contain anything while
+ * num_nodes is expected to contain the desired size. Normally this is an
+ * invalid state, but just after loading the component's structure it is valid.
+ * This method should only be called from Load_LGRP.
+ */
+void LinkGraphComponent::SetSize()
+{
+	if (this->nodes.size() < this->num_nodes) {
+		for (EdgeMatrix::iterator i = this->edges.begin(); i != this->edges.end(); ++i) {
+			i->resize(this->num_nodes);
+		}
+		this->nodes.resize(this->num_nodes);
+		this->edges.resize(this->num_nodes, std::vector<Edge>(this->num_nodes));
+	}
+
+	for(uint i = 0; i < this->num_nodes; ++i) {
+		this->nodes[i].Init();
+		for (uint j = 0; j < this->num_nodes; ++j) {
+			this->edges[i][j].Init();
+		}
+	}
+}
+
+/**
+ * Create an empty component.
+ */
+LinkGraphComponent::LinkGraphComponent() :
+		settings(_settings_game.linkgraph),
+		cargo(INVALID_CARGO),
+		num_nodes(0),
+		index(INVALID_LINKGRAPH_COMPONENT)
+{}
+
+/**
+ * (re-)initialize this component with a new ID and a new copy of the settings.
+ */
+void LinkGraphComponent::Init(LinkGraphComponentID id)
+{
+	assert(this->num_nodes == 0);
+	this->index = id;
+	this->settings = _settings_game.linkgraph;
+}
+
+
+/**
+ * Exports all entries in the FlowViaMap pointed to by "source_flows_it", erases the source
+ * flows and increments the iterator afterwards.
+ * @param it iterator pointing to the flows to be exported into the main game state
+ * @param dest the flow stats to which the flows shall be exported
+ * @param cargo the cargo we're exporting flows for (used to check if the link stats for the new
+ *        flows still exist)
+ */
+void Node::ExportNewFlows(FlowMap::iterator &it, FlowStatSet &dest, CargoID cargo)
+{
+	StationID source = it->first;
+	FlowViaMap &source_flows = it->second;
+	if (!Station::IsValidID(source)) {
+		source_flows.clear();
+	} else {
+		Station *curr_station = Station::Get(this->station);
+		for (FlowViaMap::iterator update = source_flows.begin(); update != source_flows.end();) {
+			StationID next = update->first;
+			int planned = update->second;
+			assert(planned >= 0);
+
+			Station *via = Station::GetIfValid(next);
+			if (planned > 0 && via != NULL) {
+				uint distance = GetMovingAverageLength(curr_station, via);
+				if (next != this->station) {
+					const LinkStatMap &ls = curr_station->goods[cargo].link_stats;
+					if (ls.find(next) != ls.end()) {
+						dest.insert(FlowStat(distance, next, planned, 0));
+					}
+				} else {
+					dest.insert(FlowStat(distance, next, planned, 0));
+				}
+			}
+			source_flows.erase(update++);
+		}
+	}
+	assert(source_flows.empty());
+
+	this->flows.erase(it++);
+}
+
+/**
+ * Export all flows of this node to the main game state.
+ * @param cargo the cargo we're exporting flows for.
+ */
+void Node::ExportFlows(CargoID cargo) {
+	FlowStatMap &station_flows = Station::Get(this->station)->goods[cargo].flows;
+	FlowStatSet new_flows;
+	/* loop over all existing flows in the station and update them */
+	for(FlowStatMap::iterator station_outer_it(station_flows.begin()); station_outer_it != station_flows.end();) {
+		FlowMap::iterator node_outer_it(this->flows.find(station_outer_it->first));
+		if (node_outer_it == this->flows.end()) {
+			/* there are no flows for this source node anymore */
+			station_flows.erase(station_outer_it++);
+		} else {
+			FlowViaMap &source = node_outer_it->second;
+			FlowStatSet &dest = station_outer_it->second;
+			/* loop over the station's flow stats for this source node and update them */
+			for (FlowStatSet::iterator station_inner_it(dest.begin()); station_inner_it != dest.end();) {
+				FlowViaMap::iterator node_inner_it(source.find(station_inner_it->Via()));
+				if (node_inner_it != source.end()) {
+					assert(node_inner_it->second >= 0);
+					if (node_inner_it->second > 0) {
+						new_flows.insert(FlowStat(*station_inner_it, node_inner_it->second));
+					}
+					source.erase(node_inner_it);
+				}
+				dest.erase(station_inner_it++);
+			}
+			/* swap takes constant time, so we swap instead of adding all entries */
+			dest.swap(new_flows);
+			assert(new_flows.empty());
+			/* insert remaining flows for this source node */
+			ExportNewFlows(node_outer_it, dest, cargo);
+			/* careful: source_flows is dangling here */
+			++station_outer_it;
+		}
+	}
+	/* loop over remaining flows (for other sources) in the node's map and insert them into the station */
+	for (FlowMap::iterator it(this->flows.begin()); it != this->flows.end();) {
+		ExportNewFlows(it, station_flows[it->first], cargo);
+	}
+	assert(this->flows.empty());
+}
+
+/**
+ * Merge the current job's results into the main game state.
+ */
+void LinkGraph::Join()
+{
+	this->LinkGraphJob::Join();
+
+	for(NodeID node_id = 0; node_id < this->GetSize(); ++node_id) {
+		Node &node = this->GetNode(node_id);
+		if (Station::IsValidID(node.station)) {
+			node.ExportFlows(this->cargo);
+			Window *station_gui = FindWindowById(WC_STATION_VIEW, node.station);
+			if (station_gui != NULL) {
+				station_gui->OnInvalidateData(this->GetCargo());
+			}
+		}
+	}
+
+	this->LinkGraphComponent::Clear();
+}
+
+/**
+ * Run all handlers for the given Job.
+ * @param j a pointer to a link graph job
+ */
+/* static */ void LinkGraphJob::RunLinkGraphJob(void *j)
+{
+	LinkGraphJob *job = (LinkGraphJob *)j;
+	for (HandlerList::iterator i = _handlers.begin(); i != _handlers.end(); ++i) {
+		(*i)->Run(job);
+	}
+}
+
+/**
+ * Clear the handlers.
+ */
+/* static */ void LinkGraphJob::ClearHandlers()
+{
+	for(HandlerList::iterator i = _handlers.begin(); i != _handlers.end(); ++i) {
+		delete (*i);
+	}
+	_handlers.clear();
+}
+
+/**
+ * add this path as a new child to the given base path, thus making this path
+ * a "fork" of the base path.
+ * @param base the path to fork from
+ * @param cap maximum capacity of the new path
+ * @param dist distance of the new leg
+ */
+void Path::Fork(Path *base, uint cap, int free_cap, uint dist)
+{
+	this->capacity = min(base->capacity, cap);
+	this->free_capacity = min(base->free_capacity, free_cap);
+	this->distance = base->distance + dist;
+	assert(this->distance > 0);
+	if (this->parent != base) {
+		this->UnFork();
+		this->parent = base;
+		this->parent->num_children++;
+	}
+	this->origin = base->origin;
+}
+
+/**
+ * Push some flow along a path and register the path in the nodes it passes if
+ * successful.
+ * @param new_flow amount of flow to push
+ * @param graph the link graph component this node belongs to
+ * @param only_positive if true, don't push more flow than there is capacity
+ * @return the amount of flow actually pushed
+ */
+uint Path::AddFlow(uint new_flow, LinkGraphComponent *graph, bool only_positive)
+{
+	if (this->parent != NULL) {
+		Edge &edge = graph->GetEdge(this->parent->node, this->node);
+		if (only_positive) {
+			uint usable_cap = edge.capacity * graph->GetSettings().short_path_saturation / 100;
+			if(usable_cap > edge.flow) {
+				new_flow = min(new_flow, usable_cap - edge.flow);
+			} else {
+				return 0;
+			}
+		}
+		new_flow = this->parent->AddFlow(new_flow, graph, only_positive);
+		if (new_flow > 0) {
+			graph->GetNode(parent->node).paths.insert(this);
+		}
+		edge.flow += new_flow;
+	}
+	this->flow += new_flow;
+	return new_flow;
+}
+
+/**
+ * create a leg of a path in the link graph.
+ * @param n id of the link graph node this path passes
+ * @param source if true, this is the first leg of the path
+ */
+Path::Path(NodeID n, bool source)  :
+	distance(source ? 0 : UINT_MAX),
+	capacity(0),
+	free_capacity(source ? INT_MAX : INT_MIN),
+	flow(0), node(n), origin(source ? n : INVALID_NODE),
+	num_children(0), parent(NULL)
+{}
+
+/**
+ * Join the calling thread with this job's thread if threading is enabled.
+ */
+FORCEINLINE void LinkGraphJob::Join()
+{
+	if (this->thread != NULL) {
+		this->thread->Join();
+		delete this->thread;
+		this->thread = NULL;
+	}
+}
+
+/**
+ * Spawn a thread if possible and run the link graph job in the thread. If
+ * that's not possible run the job right now in the current thread.
+ */
+void LinkGraphJob::SpawnThread()
+{
+	assert(this->thread == NULL);
+	if (!ThreadObject::New(&(LinkGraphJob::RunLinkGraphJob), this, &(this->thread))) {
+		this->thread = NULL;
+		/* Of course this will hang a bit.
+		 * On the other hand, if you want to play games which make this hang noticably
+		 * on a platform without threads then you'll probably get other problems first.
+		 * OK:
+		 * If someone comes and tells me that this hangs for him/her, I'll implement a
+		 * smaller grained "Step" method for all handlers and add some more ticks where
+		 * "Step" is called. No problem in principle.
+		 */
+		LinkGraphJob::RunLinkGraphJob(this);
+	}
+}
+
+/**
+ * (Re-)Initialize the link graph: join all jobs and set current_station_id and
+ * cargo to their start values.
+ * @param cargo the new cargo ID for the link graph
+ */
+void LinkGraph::Init(CargoID cargo)
+{
+	this->LinkGraphJob::Join();
+	this->LinkGraphComponent::Clear();
+
+	this->current_station_id = 0;
+	this->LinkGraphComponent::cargo = cargo;
+}
+
+/**
+ * Initialize all link graphs. Used when loading a game.
+ */
+void InitializeLinkGraphs()
+{
+	for (CargoID c = 0; c < NUM_CARGO; ++c) _link_graphs[c].Init(c);
+
+	LinkGraphJob::ClearHandlers();
+	LinkGraphJob::AddHandler(new DemandHandler);
+	LinkGraphJob::AddHandler(new MCFHandler<MCF1stPass>);
+	LinkGraphJob::AddHandler(new FlowMapper);
+	LinkGraphJob::AddHandler(new MCFHandler<MCF2ndPass>);
+	LinkGraphJob::AddHandler(new FlowMapper);
+}
diff --git a/src/linkgraph/linkgraph.h b/src/linkgraph/linkgraph.h
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/linkgraph.h
@@ -0,0 +1,348 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file linkgraph.h Declaration of link graph classes used for cargo distribution. */
+
+#ifndef LINKGRAPH_H_
+#define LINKGRAPH_H_
+
+#include "../stdafx.h"
+#include "../station_base.h"
+#include "../cargo_type.h"
+#include "../thread/thread.h"
+#include "../settings_type.h"
+#include "../date_func.h"
+#include "linkgraph_type.h"
+#include <list>
+#include <vector>
+#include <set>
+
+struct SaveLoad;
+class Path;
+
+typedef std::set<Path *> PathSet;
+typedef std::map<NodeID, Path *> PathViaMap;
+typedef std::map<StationID, int> FlowViaMap;
+typedef std::map<StationID, FlowViaMap> FlowMap;
+
+/**
+ * Node of the link graph. contains all relevant information from the associated
+ * station. It's copied so that the link graph job can work on its own data set
+ * in a separate thread.
+ */
+class Node {
+public:
+	uint supply;             ///< supply at the station
+	uint undelivered_supply; ///< amount of supply that hasn't been distributed yet
+	uint demand;             ///< acceptance at the station
+	StationID station;       ///< the station's ID
+	PathSet paths;           ///< paths through this node
+	FlowMap flows;           ///< planned flows to other nodes
+
+	/**
+	 * Clear a node on destruction to delete paths that might remain.
+	 */
+	~Node() {this->Init();}
+
+	void Init(StationID st = INVALID_STATION, uint sup = 0, uint dem = 0);
+	void ExportFlows(CargoID cargo);
+
+private:
+	void ExportNewFlows(FlowMap::iterator &it, FlowStatSet &via_set, CargoID cargo);
+};
+
+/**
+ * An edge in the link graph. Corresponds to a link between two stations or at
+ * least the distance between them. Edges from one node to itself contain the
+ * ID of the opposite Node of the first active edge (i.e. not just distance) in
+ * the column as next_edge.
+ */
+class Edge {
+public:
+	uint distance;           ///< length of the link
+	uint capacity;           ///< capacity of the link
+	uint demand;             ///< transport demand between the nodes
+	uint unsatisfied_demand; ///< demand over this edge that hasn't been satisfied yet
+	uint flow;               ///< planned flow over this edge
+	NodeID next_edge;        ///< destination of next valid edge starting at the same source node
+
+	void Init(uint distance = 0, uint capacity = 0);
+};
+
+/**
+ * A connected component of a link graph. Contains a complete set of stations
+ * connected by links as nodes and edges. Each component also holds a copy of
+ * the link graph settings at the time of its creation. The global settings
+ * might change between the creation and join time so we can't rely on them.
+ */
+class LinkGraphComponent {
+private:
+	typedef std::vector<Node> NodeVector;
+	typedef std::vector<std::vector<Edge> > EdgeMatrix;
+
+public:
+	LinkGraphComponent();
+
+	void Init(LinkGraphComponentID id);
+
+	/**
+	 * Get a reference to an edge.
+	 * @param from the origin node
+	 * @param the destination node
+	 * @return the edge between from and to
+	 */
+	FORCEINLINE Edge &GetEdge(NodeID from, NodeID to)
+	{
+		return this->edges[from][to];
+	}
+
+	/**
+	 * Get a reference to a node with the specified id.
+	 * @param num ID of the node
+	 * @return the requested node
+	 */
+	FORCEINLINE Node &GetNode(NodeID num)
+	{
+		return this->nodes[num];
+	}
+
+	/**
+	 * Get the current size of the component.
+	 * @return the size
+	 */
+	FORCEINLINE uint GetSize() const
+	{
+		return this->num_nodes;
+	}
+
+	void SetSize();
+
+	NodeID AddNode(Station *st);
+
+	FORCEINLINE void AddEdge(NodeID from, NodeID to, uint capacity);
+
+	/**
+	 * Get the ID of this component.
+	 * @return the ID
+	 */
+	FORCEINLINE LinkGraphComponentID GetIndex() const
+	{
+		return this->index;
+	}
+
+	/**
+	 * Get the cargo ID this component's link graph refers to.
+	 * @return the cargo ID
+	 */
+	FORCEINLINE CargoID GetCargo() const
+	{
+		return this->cargo;
+	}
+
+	/**
+	 * Get the link graph settings for this component.
+	 * @return the settings
+	 */
+	FORCEINLINE const LinkGraphSettings &GetSettings() const
+	{
+		return this->settings;
+	}
+
+	/**
+	 * Get the first valid edge starting at the specified node.
+	 * @param from ID of the source node
+	 * @return ID of the destination node
+	 */
+	FORCEINLINE NodeID GetFirstEdge(NodeID from)
+	{
+		return edges[from][from].next_edge;
+	}
+
+	/**
+	 * Set the number of nodes to 0 to mark this component as done.
+	 */
+	FORCEINLINE void Clear()
+	{
+		this->num_nodes = 0;
+	}
+
+protected:
+	LinkGraphSettings settings; ///< Copy of _settings_game.linkgraph at creation time
+	CargoID cargo;              ///< Cargo of this component's link graph
+	uint num_nodes;             ///< Number of nodes in the component
+	LinkGraphComponentID index; ///< ID of the component
+	NodeVector nodes;           ///< Nodes in the component
+	EdgeMatrix edges;           ///< Edges in the component
+};
+
+/**
+ * A handler doing "something" on a link graph component. It must not keep any
+ * state as it is called concurrently from different threads.
+ */
+class ComponentHandler {
+public:
+	/**
+	 * Destroy the handler. Must be given due to virtual Run.
+	 */
+	virtual ~ComponentHandler() {}
+
+	/**
+	 * Run the handler. A link graph handler must not read or write any data
+	 * outside the given component as that would create a potential desync.
+	 */
+	virtual void Run(LinkGraphComponent *component) = 0;
+};
+
+/**
+ * A job to be executed on a link graph component. It inherits a component and
+ * keeps a static list of handlers to be run on it. It may or may not run in a
+ * thread and contains a thread object for this option.
+ */
+class LinkGraphJob : public LinkGraphComponent {
+private:
+	typedef std::list<ComponentHandler *> HandlerList;
+
+public:
+	LinkGraphJob() : thread(NULL) {}
+
+	/**
+	 * Destructor; Clean up the thread if it's there.
+	 */
+	~LinkGraphJob()
+	{
+		this->Join();
+	}
+
+	static void RunLinkGraphJob(void *j);
+
+	/**
+	 * Add a handler to the end of the list.
+	 * @param handler the handler to be added
+	 */
+	static void AddHandler(ComponentHandler *handler)
+	{
+		LinkGraphJob::_handlers.push_back(handler);
+	}
+
+	static void ClearHandlers();
+
+	void SpawnThread();
+
+	void Join();
+
+private:
+	static HandlerList _handlers;   ///< Handlers the job is executing
+	ThreadObject *thread;           ///< Thread the job is running in or NULL if it's running in the main thread
+
+	/**
+	 * Private Copy-Constructor: there cannot be two identical LinkGraphJobs.
+	 * @param other hypothetical other job to be copied.
+	 * @note It's necessary to explicitly initialize the link graph component in order to silence some compile warnings
+	 */
+	LinkGraphJob(const LinkGraphJob &other) : LinkGraphComponent(other) {NOT_REACHED();}
+};
+
+/**
+ * A link graph, inheriting one job.
+ */
+class LinkGraph : public LinkGraphJob {
+public:
+	static const uint COMPONENTS_JOIN_TICK  = 21; ///< tick when jobs are joined every day
+	static const uint COMPONENTS_SPAWN_TICK = 58; ///< tick when jobs are spawned every day
+
+	/**
+	 * Create a link graph.
+	 */
+	LinkGraph() : current_station_id(0) {}
+
+	void Init(CargoID cargo);
+
+	void NextComponent();
+
+	void Join();
+
+private:
+	StationID current_station_id; ///< ID of the last station examined while creating components
+
+	friend const SaveLoad *GetLinkGraphDesc();
+
+	void CreateComponent(Station *first);
+};
+
+/**
+ * A leg of a path in the link graph. Paths can form trees by being "forked".
+ */
+class Path {
+public:
+	Path(NodeID n, bool source = false);
+
+	/** get the node this leg passes. */
+	FORCEINLINE NodeID GetNode() const {return this->node;}
+
+	/** get the overall origin of the path. */
+	FORCEINLINE NodeID GetOrigin() const {return this->origin;}
+
+	/** get the parent leg of this one. */
+	FORCEINLINE Path *GetParent() {return this->parent;}
+
+	/** get the overall capacity of the path. */
+	FORCEINLINE uint GetCapacity() const {return this->capacity;}
+
+	/** get the free capacity of the path. */
+	FORCEINLINE int GetFreeCapacity() const {return this->free_capacity;}
+
+	/** get ratio of free * 16 (so that we get fewer 0) /
+	 * overall capacity + 1 (so that we don't divide by 0)
+	 */
+	FORCEINLINE int GetCapacityRatio() const {return (this->free_capacity << 4) / (this->capacity + 1);}
+
+	/** get the overall distance of the path. */
+	FORCEINLINE uint GetDistance() const {return this->distance;}
+
+	/** reduce the flow on this leg only by the specified amount. */
+	FORCEINLINE void ReduceFlow(uint f) {this->flow -= f;}
+
+	/** increase the flow on this leg only by the specified amount. */
+	FORCEINLINE void AddFlow(uint f) {this->flow += f;}
+
+	/** get the flow on this leg. */
+	FORCEINLINE uint GetFlow() const {return this->flow;}
+
+	/** get the number of "forked off" child legs of this one */
+	FORCEINLINE uint GetNumChildren() const {return this->num_children;}
+
+	/**
+	 * detach this path from its parent.
+	 */
+	FORCEINLINE void UnFork()
+	{
+		if (this->parent != NULL) {
+			this->parent->num_children--;
+			this->parent = NULL;
+		}
+	}
+	
+	uint AddFlow(uint f, LinkGraphComponent *graph, bool only_positive);
+	void Fork(Path *base, uint cap, int free_cap, uint dist);
+
+protected:
+	uint distance;     ///< sum(distance of all legs up to this one)
+	uint capacity;     ///< this capacity is min(capacity) fom all edges
+	int free_capacity; ///< this capacity is min(edge.capacity - edge.flow) for the current run of dijkstra
+	uint flow;         ///< this is the flow the current run of the mcf solver assigns
+	NodeID node;       ///< the link graph node this leg passes
+	NodeID origin;     ///< the link graph node this path originates from
+	uint num_children; ///< the number of child legs that have been forked from this path
+	Path *parent;      ///< the parent leg of this one
+};
+
+void InitializeLinkGraphs();
+extern LinkGraph _link_graphs[NUM_CARGO];
+
+#endif /* LINKGRAPH_H_ */
diff --git a/src/linkgraph/linkgraph_type.h b/src/linkgraph/linkgraph_type.h
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/linkgraph_type.h
@@ -0,0 +1,36 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file linkgraph_type.h Declaration of link graph types used for cargo distribution. */
+
+#ifndef LINKGRAPH_TYPE_H_
+#define LINKGRAPH_TYPE_H_
+
+typedef uint16 LinkGraphComponentID;
+static const LinkGraphComponentID INVALID_LINKGRAPH_COMPONENT = UINT16_MAX;
+
+typedef uint NodeID;
+static const NodeID INVALID_NODE = UINT_MAX;
+
+enum DistributionType {
+	DT_BEGIN = 0,
+	DT_SYMMETRIC = 0, ///< symmetric distribution. The same amount of cargo travels in each direction between each pair of nodes.
+	DT_ASYMMETRIC,    ///< asymmetric distribution. Usually cargo will only travel in one direction.
+	DT_MANUAL,        ///< manual distribution. No link graph calculations are run.
+	DT_NUM = 3,
+	DT_END = 3
+};
+
+/* It needs to be 8bits, because we save and load it as such
+ * Define basic enum properties
+ */
+template <> struct EnumPropsT<DistributionType> : MakeEnumPropsT<DistributionType, byte, DT_BEGIN, DT_END, DT_NUM> {};
+typedef TinyEnumT<DistributionType> DistributionTypeByte; // typedefing-enumification of DistributionType
+
+#endif /* LINKGRAPH_TYPE_H_ */
diff --git a/src/linkgraph/mcf.cpp b/src/linkgraph/mcf.cpp
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/mcf.cpp
@@ -0,0 +1,427 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file mcf.cpp Definition of Multi-Commodity-Flow solver */
+
+#include "mcf.h"
+#include "../core/math_func.hpp"
+
+/**
+ * Determines if an extension to the given Path with the given parameters is
+ * better than this path.
+ * @param base the other path
+ * @param cap the capacity of the new edge to be added to base
+ * @param dist the distance of the new edge
+ * @return true if base + the new edge would be better than the path associated
+ * with this annotation.
+ */
+bool DistanceAnnotation::IsBetter(const DistanceAnnotation *base, uint cap,
+		int free_cap, uint dist) const
+{
+	/* If any of the paths is disconnected, the other one is better. If both
+	 * are disconnected, this path is better.
+	 */
+	if (base->distance == UINT_MAX) {
+		return false;
+	} else if (this->distance == UINT_MAX) {
+		return true;
+	}
+
+	if (free_cap > 0 && base->free_capacity > 0) {
+		/* If both paths have capacity left, compare their distances.
+		 * If the other path has capacity left and this one hasn't, the
+		 * other one's better.
+		 */
+		return this->free_capacity > 0 ? (base->distance + dist < this->distance) : true;
+	} else {
+		/* If the other path doesn't have capacity left, but this one has,
+		 * this one is better.
+		 * If both paths are out of capacity, do the regular distance
+		 * comparison.
+		 */
+		return this->free_capacity > 0 ? false : (base->distance + dist < this->distance);
+	}
+}
+
+/**
+ * Determines if an extension to the given Path with the given parameters is
+ * better than this path.
+ * @param base the other path
+ * @param cap the capacity of the new edge to be added to base
+ * @param dist the distance of the new edge
+ * @return true if base + the new edge would be better than the path associated
+ * with this annotation.
+ */
+bool CapacityAnnotation::IsBetter(const CapacityAnnotation *base, uint cap,
+		int free_cap, uint dist) const
+{
+	int min_cap = (min(base->free_capacity, free_cap) << 4) / (min(base->capacity, cap) + 1);
+	int this_cap = this->GetCapacityRatio();
+	if (min_cap == this_cap) {
+		/* If the capacities are the same and the other path isn't disconnected
+		 * choose the shorter path.
+		 */
+		return base->distance == UINT_MAX ? false : (base->distance + dist < this->distance);
+	} else {
+		return min_cap > this_cap;
+	}
+}
+
+/**
+ * A slightly modified Dijkstra algorithm. Grades the paths not necessarily by
+ * distance, but by the value Tannotation computes. It can also be configured
+ * to only use paths already created before and not create new ones. If this is
+ * not done it uses the short_path_saturation setting to artificially decrease
+ * capacities. If a path has already been created is determined by checking the
+ * flows associated with its nodes.
+ * @tparam Tannotation the annotation to be used
+ * @param source_node the node where the algorithm starts.
+ * @param paths a container for the paths to be calculated
+ * @param create_new_paths if false, only use paths already seen before,
+ *                         otherwise artificially limit the capacity
+ */
+template<class Tannotation>
+void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths,
+		bool create_new_paths)
+{
+	typedef std::set<Tannotation *, typename Tannotation::comp> AnnoSet;
+	uint size = this->graph->GetSize();
+	StationID source_station = this->graph->GetNode(source_node).station;
+	AnnoSet annos;
+	paths.resize(size, NULL);
+	for (NodeID node = 0; node < size; ++node) {
+		Tannotation *anno = new Tannotation(node, node == source_node);
+		annos.insert(anno);
+		paths[node] = anno;
+	}
+	while(!annos.empty()) {
+		typename AnnoSet::iterator i = annos.begin();
+		Tannotation *source = *i;
+		annos.erase(i);
+		NodeID from = source->GetNode();
+		NodeID to = this->graph->GetFirstEdge(from);
+		while (to != INVALID_NODE) {
+			Edge &edge = this->graph->GetEdge(from, to);
+			assert(edge.distance < UINT_MAX);
+			if (create_new_paths ||
+					this->graph->GetNode(from).flows[source_station]
+					[this->graph->GetNode(to).station] > 0) {
+				uint capacity = edge.capacity;
+				if (create_new_paths) {
+					capacity *= this->graph->GetSettings().short_path_saturation;
+					capacity /= 100;
+					if (capacity == 0) capacity = 1;
+				}
+				/* punish in-between stops a little */
+				uint distance = edge.distance + 1;
+				Tannotation *dest = static_cast<Tannotation *>(paths[to]);
+				if (dest->IsBetter(source, capacity, capacity - edge.flow, distance)) {
+					annos.erase(dest);
+					dest->Fork(source, capacity, capacity - edge.flow, distance);
+					annos.insert(dest);
+				}
+			}
+			to = edge.next_edge;
+		}
+	}
+}
+
+/**
+ * Clean up paths that lead nowhere and the root path.
+ * @param source_id ID of the root node
+ * @param paths the paths to be cleaned up
+ */
+void MultiCommodityFlow::CleanupPaths(NodeID source_id, PathVector &paths) {
+	Path *source = paths[source_id];
+	paths[source_id] = NULL;
+	for(PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
+		Path *path = *i;
+		if (path != NULL) {
+			if (path->GetParent() == source) path->UnFork();
+			while (path != source && path != NULL && path->GetFlow() == 0) {
+				Path *parent = path->GetParent();
+				path->UnFork();
+				if (path->GetNumChildren() == 0) {
+					paths[path->GetNode()] = NULL;
+					delete path;
+				}
+				path = parent;
+			}
+		}
+	}
+	delete source;
+	paths.clear();
+}
+
+/**
+ * Push flow along a path and update the unsatisfied_demand of the associated
+ * edge.
+ * @param edge the edge whose ends the path connects
+ * @param path the end of the path the flow should be pushed on
+ * @param accuracy the accuracy of the calculation
+ * @param positive_cap if true only push flow up to the paths capacity,
+ *                     otherwise the path can be "overloaded".
+ */
+uint MultiCommodityFlow::PushFlow(Edge &edge, Path *path, uint accuracy,
+		bool positive_cap)
+{
+	assert(edge.unsatisfied_demand > 0);
+	uint flow = Clamp(edge.demand / accuracy, 1, edge.unsatisfied_demand);
+	flow = path->AddFlow(flow, this->graph, positive_cap);
+	edge.unsatisfied_demand -= flow;
+	return flow;
+}
+
+/**
+ * Find the flow along a cycle including cycle_begin in path.
+ * @param path the set of paths that form the cycle
+ * @param cycle_begin the path to start at
+ * @return the flow along the cycle
+ */
+uint MCF1stPass::FindCycleFlow(const PathVector &path, const Path *cycle_begin)
+{
+	uint flow = UINT_MAX;
+	const Path *cycle_end = cycle_begin;
+	do {
+		flow = min(flow, cycle_begin->GetFlow());
+		cycle_begin = path[cycle_begin->GetNode()];
+	} while(cycle_begin != cycle_end);
+	return flow;
+}
+
+/**
+ * Eliminate a cycle of the given flow in the given set of paths.
+ * @param path the set of paths containing the cycle
+ * @param cycle_begin a part the cycle to start at
+ * @param flow the flow along the cycle
+ */
+void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
+{
+	Path *cycle_end = cycle_begin;
+	do {
+		NodeID prev = cycle_begin->GetNode();
+		cycle_begin->ReduceFlow(flow);
+		cycle_begin = path[cycle_begin->GetNode()];
+		Edge &edge = this->graph->GetEdge(prev, cycle_begin->GetNode());
+		edge.flow -= flow;
+	} while(cycle_begin != cycle_end);
+}
+
+/**
+ * Eliminate cycles for origin_id in the graph. Start searching at next_id and
+ * work recursively. Also "summarize" paths: Add up the flows along parallel
+ * paths in one.
+ * @param path the paths checked in parent calls to this method
+ * @param origin_id the origin of the paths to be checked
+ * @param next_id the next node to be checked
+ * @return if any cycles have been found and eliminated
+ */
+bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id)
+{
+	static Path *invalid_path = new Path(INVALID_NODE, true);
+	Path *at_next_pos = path[next_id];
+	if (at_next_pos == invalid_path) {
+		/* this node has already been searched */
+		return false;
+	} else if (at_next_pos == NULL) {
+		/* summarize paths; add up the paths with the same source and next hop
+		 * in one path each
+		 */
+		PathSet &paths = this->graph->GetNode(next_id).paths;
+		PathViaMap next_hops;
+		for(PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
+			Path *new_child = *i;
+			if (new_child->GetOrigin() == origin_id) {
+				PathViaMap::iterator via_it = next_hops.find(new_child->GetNode());
+				if (via_it == next_hops.end()) {
+					next_hops[new_child->GetNode()] = new_child;
+				} else {
+					Path *child = via_it->second;
+					uint new_flow = new_child->GetFlow();
+					child->AddFlow(new_flow);
+					new_child->ReduceFlow(new_flow);
+				}
+			}
+		}
+		bool found = false;
+		/* search the next hops for nodes we have already visited */
+		for (PathViaMap::iterator via_it = next_hops.begin();
+				via_it != next_hops.end(); ++via_it)
+		{
+			Path *child = via_it->second;
+			if (child->GetFlow() > 0) {
+				/* push one child into the path vector and search this child's
+				 * children
+				 */
+				path[next_id] = child;
+				found = this->EliminateCycles(path, origin_id, child->GetNode()) || found;
+			}
+		}
+		/* All paths departing from this node have been searched. Mark as
+		 * resolved if no cycles found. If cycles were found further cycles
+		 * could be found in this branch, thus it has to be searched again next
+		 * time we spot it.
+		 */
+		path[next_id] = found ? NULL : invalid_path;
+		return found;
+	} else {
+		/* this node has already been visited => we have a cycle
+		 * backtrack to find the exact flow
+		 */
+		uint flow = this->FindCycleFlow(path, at_next_pos);
+		if (flow > 0) {
+			this->EliminateCycle(path, at_next_pos, flow);
+			return true;
+		} else {
+			return false;
+		}
+	}
+}
+
+/**
+ * Eliminate all cycles in the graph. Check paths starting at each node for
+ * potential cycles.
+ * @return if any cycles have been found and eliminated.
+ */
+bool MCF1stPass::EliminateCycles()
+{
+	bool cycles_found = false;
+	uint size = this->graph->GetSize();
+	PathVector path(size, NULL);
+	for (NodeID node = 0; node < size; ++node) {
+		/* starting at each node in the graph find all cycles involving this node */
+		std::fill(path.begin(), path.end(), (Path *)NULL);
+		cycles_found = this->EliminateCycles(path, node, node) || cycles_found;
+	}
+	return cycles_found;
+}
+
+/**
+ * Run the first pass of the MCF calculation.
+ * @param graph the component to calculate.
+ */
+MCF1stPass::MCF1stPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
+{
+	PathVector paths;
+	uint size = this->graph->GetSize();
+	uint accuracy = this->graph->GetSettings().accuracy;
+	bool no_overload = this->graph->GetSettings().no_overload_links;
+	bool more_loops = true;
+
+	while (more_loops) {
+		more_loops = false;
+
+		for (NodeID source = 0; source < size; ++source) {
+			/* first saturate the shortest paths */
+			this->Dijkstra<DistanceAnnotation>(source, paths, true);
+
+			for (NodeID dest = 0; dest < size; ++dest) {
+				Edge &edge = this->graph->GetEdge(source, dest);
+				if (edge.unsatisfied_demand > 0) {
+					Path *path = paths[dest];
+					assert(path != NULL);
+					/* Generally only allow paths that don't exceed the available capacity.
+					 * But if no demand has been assigned yet, make an exception and allow
+					 * any valid path *once*.
+					 */
+					if (path->GetFreeCapacity() > 0 && this->PushFlow(edge, path,
+							accuracy, no_overload) > 0) {
+						/* if a path has been found there is a chance we can
+						 * find more
+						 */
+						more_loops = (edge.unsatisfied_demand > 0);
+					} else if (edge.unsatisfied_demand == edge.demand && path->GetFreeCapacity() > INT_MIN) {
+						this->PushFlow(edge, path, accuracy, false);
+					}
+				}
+			}
+			CleanupPaths(source, paths);
+		}
+		if (!more_loops) more_loops = EliminateCycles();
+	}
+}
+
+/**
+ * Run the second pass of the MCF calculation.
+ * @param graph the component to calculate.
+ */
+MCF2ndPass::MCF2ndPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
+{
+	PathVector paths;
+	uint size = this->graph->GetSize();
+	uint accuracy = this->graph->GetSettings().accuracy;
+	bool no_overload = this->graph->GetSettings().no_overload_links;
+	bool demand_left = true;
+	uint flow_pushed = 1;
+	while (demand_left && flow_pushed > 0) {
+		flow_pushed = 0;
+		demand_left = false;
+		for (NodeID source = 0; source < size; ++source) {
+			/* Then assign all remaining demands */
+			this->Dijkstra<CapacityAnnotation>(source, paths, false);
+			for (NodeID dest = 0; dest < size; ++dest) {
+				Edge &edge = this->graph->GetEdge(source, dest);
+				Path *path = paths[dest];
+				if (edge.unsatisfied_demand > 0 && path->GetFreeCapacity() > INT_MIN) {
+ 					flow_pushed += this->PushFlow(edge, path, accuracy, no_overload);
+					if (edge.unsatisfied_demand > 0) demand_left = true;
+				}
+			}
+			CleanupPaths(source, paths);
+		}
+	}
+}
+
+/**
+ * Relation that creates a weak order without duplicates.
+ * Avoid accidentally deleting different paths of the same capacity/distance in
+ * a set. When the annotation is the same node IDs are compared, so there are
+ * no equal ranges.
+ * @tparam T the type to be compared on
+ * @param x_anno the first value
+ * @param y_anno the second value
+ * @param x the node id associated with the first value
+ * @param y the node id associated with the second value
+ */
+template <typename T>
+bool greater(T x_anno, T y_anno, NodeID x, NodeID y) {
+	if (x_anno > y_anno) {
+		return true;
+	} else if (x_anno < y_anno) {
+		return false;
+	} else {
+		return x > y;
+	}
+}
+
+/**
+ * Compare two capacity annotations.
+ * @param x the first capacity annotation
+ * @param y the second capacity annotation
+ * @return if x is better than y
+ */
+bool CapacityAnnotation::comp::operator()(const CapacityAnnotation *x,
+		const CapacityAnnotation *y) const
+{
+	return x != y && greater<int>(x->GetAnnotation(), y->GetAnnotation(),
+			x->GetNode(), y->GetNode());
+}
+
+/**
+ * Compare two distance annotations.
+ * @param x the first distance annotation
+ * @param y the second distance annotation
+ * @return if x is better than y
+ */
+bool DistanceAnnotation::comp::operator()(const DistanceAnnotation *x,
+		const DistanceAnnotation *y) const
+{
+	return x != y && !greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
+			x->GetNode(), y->GetNode());
+}
diff --git a/src/linkgraph/mcf.h b/src/linkgraph/mcf.h
new file mode 100644
--- /dev/null
+++ b/src/linkgraph/mcf.h
@@ -0,0 +1,135 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file mcf.h Declaration of Multi-Commodity-Flow solver */
+
+#ifndef MCF_H_
+#define MCF_H_
+
+#include "linkgraph.h"
+#include <vector>
+
+/**
+ * Distance-based annotation for use in the Dijkstra algorithm. This is close
+ * to the original meaning of "annotation" in this context. Paths are rated
+ * according to the sum of distances of their edges.
+ */
+class DistanceAnnotation : public Path {
+public:
+	DistanceAnnotation(NodeID n, bool source = false) : Path(n, source) {}
+
+	bool IsBetter(const DistanceAnnotation *base, uint cap, int free_cap, uint dist) const;
+
+	/**
+	 * return the actual value of the annotation, in this case the distance
+	 * @return the distance
+	 */
+	FORCEINLINE  uint GetAnnotation() const {return this->distance;}
+
+	struct comp {
+		bool operator()(const DistanceAnnotation *x, const DistanceAnnotation *y) const;
+	};
+};
+
+/**
+ * Capacity-based annotation for use in the Dijkstra algorithm. This annotation
+ * rates paths according to the maximum capacity of their edges. The Dijkstra
+ * algorithm still gives meaningful results like this as the capacity of a path
+ * can only decrease or stay the same if you add more edges.
+ */
+class CapacityAnnotation : public Path {
+public:
+	CapacityAnnotation(NodeID n, bool source = false) : Path(n, source) {}
+
+	bool IsBetter(const CapacityAnnotation *base, uint cap, int free_cap, uint dist) const;
+
+	/**
+	 * return the actual value of the annotation, in this case the capacity
+	 * @return the capacity
+	 */
+	FORCEINLINE int GetAnnotation() const {return this->GetCapacityRatio();}
+
+	struct comp {
+		bool operator()(const CapacityAnnotation *x, const CapacityAnnotation *y) const;
+	};
+};
+
+
+typedef std::vector<Path *> PathVector;
+
+/**
+ * Multi-commodity flow calculating base class.
+ */
+class MultiCommodityFlow {
+protected:
+	MultiCommodityFlow(LinkGraphComponent *graph) : graph(graph) {}
+
+	template<class ANNOTATION> void Dijkstra(NodeID from, PathVector &paths, bool create_new_paths);
+
+	uint PushFlow(Edge &edge, Path *path, uint accuracy, bool positive_cap);
+
+	void CleanupPaths(NodeID source, PathVector &paths);
+
+	LinkGraphComponent *graph; ///< the component we're working with
+};
+
+/**
+ * First pass of the MCF calculation. Saturates shortest paths first, creates
+ * new paths if needed, eliminates cycles. This calculation is of exponential
+ * complexity in the number of nodes but the constant factors are sufficiently
+ * small to make it usable for most real-life link graph components. You can
+ * deal with performance problems that might occur here in multiple ways:
+ * - The overall accuracy is used here to determine how much flow is assigned
+ *   in each loop. The lower the accuracy, the more flow is assigned, the less
+ *   loops it takes to assign all flow.
+ * - The short_path_saturation setting determines when this pass stops. The
+ *   lower you set it, the less flow will be assigned in this pass, the less
+ *   time it will take.
+ * - You can increase the recalculation interval to allow for longer running
+ *   times without creating lags.
+ */
+class MCF1stPass : public MultiCommodityFlow {
+private:
+	bool EliminateCycles();
+	bool EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id);
+	void EliminateCycle(PathVector &path, Path *cycle_begin, uint flow);
+	uint FindCycleFlow(const PathVector &path, const Path *cycle_begin);
+public:
+	MCF1stPass(LinkGraphComponent *graph);
+};
+
+/**
+ * Second pass of the MCF calculation. Saturates paths with most capacity left
+ * first and doesn't create any paths along edges that haven't been visited in
+ * the first pass. This is why it doesn't have to do any cycle detection and
+ * elimination. As cycle detection is the most intense problem in the first
+ * pass this pass is cheaper. The accuracy is used here, too.
+ */
+class MCF2ndPass : public MultiCommodityFlow {
+public:
+	MCF2ndPass(LinkGraphComponent *graph);
+};
+
+/**
+ * Link graph handler for MCF. Creates MultiCommodityFlow instance according to
+ * the template parameter.
+ */
+template<class Tpass>
+class MCFHandler : public ComponentHandler {
+public:
+	/**
+	 * run the calculation.
+	 * @param graph the component to be calculated.
+	 */
+	virtual void Run(LinkGraphComponent *graph) {Tpass pass(graph);}
+
+	virtual ~MCFHandler() {}
+};
+
+#endif /* MCF_H_ */
diff --git a/src/map.cpp b/src/map.cpp
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -12,6 +12,7 @@
 #include "stdafx.h"
 #include "debug.h"
 #include "core/alloc_func.hpp"
+#include "settings_type.h"
 #include "tile_map.h"
 #include "water_map.h"
 
@@ -29,26 +30,44 @@
 
 Tile *_m = NULL;          ///< Tiles of the map
 TileExtended *_me = NULL; ///< Extended Tiles of the map
+TileHeightData *_map_heightdata = NULL; ///< Heightlevel information
 
 
 /**
  * (Re)allocates a map with the given dimension
  * @param size_x the width of the map along the NE/SW edge
  * @param size_y the 'height' of the map along the SE/NW edge
+ *
+ * @note The _map_heightdata array is allocated if and only if
+ *       allocate_map_heightdata is true and AllowMoreHeightlevels() is true as well.
+ *
+ *       Reason for this additional parameter:
+ *       This procedure is called in different circumstances.
+ *       If we call it during the generation of a new map, everything is ok, we know
+ *       about the configuration setting regarding additional heightlevels.
+ *
+ *       If, however, we call it while loading a savegame, we call it before
+ *       we load the configuration.
+ *       So, in this case we call it at a point where we don't know yet wether we need
+ *       the _map_heightdata array or not.
+ *       So, in this case, we ignore it in this procedure and construct it in
+ *       LoadMAPH in misc.cpp if and only if we need it.
  */
-void AllocateMap(uint size_x, uint size_y)
+void AllocateMap(uint size_x, uint size_y, bool allocate_map_heightdata)
 {
+	DEBUG(map, 2, "Min/max map size %d/%d, max map tiles %d", MIN_MAP_SIZE, MAX_MAP_SIZE, MAX_MAP_TILES);
+	DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y);
+
 	/* Make sure that the map size is within the limits and that
 	 * size of both axes is a power of 2. */
-	if (!IsInsideMM(size_x, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) ||
-			!IsInsideMM(size_y, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) ||
+	if (size_x * size_y > MAX_MAP_TILES ||
+			size_x < MIN_MAP_SIZE ||
+			size_y < MIN_MAP_SIZE ||
 			(size_x & (size_x - 1)) != 0 ||
 			(size_y & (size_y - 1)) != 0) {
 		error("Invalid map size");
 	}
 
-	DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y);
-
 	_map_log_x = FindFirstBit(size_x);
 	_map_log_y = FindFirstBit(size_y);
 	_map_size_x = size_x;
@@ -61,8 +80,57 @@
 
 	_m = CallocT<Tile>(_map_size);
 	_me = CallocT<TileExtended>(_map_size);
+
+	if (allocate_map_heightdata && AllowMoreHeightlevels()) {
+		_map_heightdata = ReallocT<TileHeightData>(_map_heightdata, _map_size);
+	}
 }
 
+/**
+ * Copies the contents of the old heightlevel array (4 bits in Tile.type_height)
+ * into the new heightlevel array (_map_heightdata).
+ * Constructs _map_heightdata according to map size.
+ *
+ * Used when switching the allow_more_heightlevel setting.
+ */
+void CopyHeightlevelDataFromOldToExtended()
+{
+	_map_heightdata = ReallocT<TileHeightData>(_map_heightdata, MapSize());
+
+	for (TileIndex i = 0; i < MapSize(); i++) {
+		_map_heightdata[i].heightlevel = GB(_m[i].type_height, 0, 4);
+	}
+}
+
+/**
+ * Copies the contents of the _map_heightdata array into the old place of
+ * heightlevel information in Tile.type_height.
+ *
+ * But only, if all heightlevels can be encoded in 4 bit.
+ * If not, the procedure returns immediately, leaving
+ * some type_height values in their original state and some not.
+ * @return true if and only if all height levels where in the range 
+ *                0 <= height level <= 15.
+ */
+bool CopyHeightlevelDataFromExtendedToOld()
+{
+	for (TileIndex i = 0; i < MapSize(); i++) {
+		uint heightlevel = _map_heightdata[i].heightlevel;
+
+		if (heightlevel >= 16) {
+			/* We can't encode the heightlevel data from the extended array
+			 * in an array of 4 bit values. */
+			return false;
+		} else {
+			SB(_m[i].type_height, 0, 4, heightlevel);
+		}
+	}
+
+	free(_map_heightdata);
+	_map_heightdata = NULL;
+
+	return true;
+}
 
 #ifdef _DEBUG
 TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
diff --git a/src/map_func.h b/src/map_func.h
--- a/src/map_func.h
+++ b/src/map_func.h
@@ -43,7 +43,18 @@
  */
 extern TileExtended *_me;
 
-void AllocateMap(uint size_x, uint size_y);
+/**
+ * Pointer to the tile-array saving extended heightlevel data.
+ *
+ * @see map.cpp.
+ */
+extern TileHeightData *_map_heightdata;
+
+void AllocateMap(uint size_x, uint size_y, bool allocate_map_heightdata);
+
+void CopyHeightlevelDataFromOldToExtended();
+
+bool CopyHeightlevelDataFromExtendedToOld();
 
 /**
  * Logarithm of the map size along the X side.
@@ -426,4 +437,20 @@
 
 uint GetClosestWaterDistance(TileIndex tile, bool water);
 
+// TODO: convert copypaste to TILE_AREA_LOOP fix it and remove the function below.
+
+/**
+ * A loop which iterates to a square of tiles
+ *
+ * This macro starts 2 nested loops which iterates over a square of tiles.
+ *
+ * @param var The name of the variable which contains the current tile
+ * @param w The width (x-width) of the square
+ * @param h The heigth (y-width) of the square
+ * @param tile The start tile of the square
+ */
+#define TILE_LOOP(var, w, h, tile)                                                    \
+for (uint var = tile, cur_h = (h); cur_h > 0; --cur_h, var += TileDiffXY(0, 1) - (w)) \
+for (uint cur_w = (w); cur_w > 0; --cur_w, var++)
+
 #endif /* MAP_FUNC_H */
diff --git a/src/map_type.h b/src/map_type.h
--- a/src/map_type.h
+++ b/src/map_type.h
@@ -35,6 +35,17 @@
 };
 
 /**
+ * Heightlevel data.
+ * Placed in a separate data structure because this way we can
+ * avoid allocating memory for the corresponding array if the settings
+ * say that we don't allow additional heightlevels.
+ * (i.e. ConstructionSettings.allow_more_heightlevels is false.)
+ */
+struct TileHeightData {
+	byte heightlevel;
+};
+
+/**
  * An offset value between to tiles.
  *
  * This value is used fro the difference between
@@ -58,10 +69,12 @@
 };
 
 /** Minimal and maximal map width and height */
-static const uint MIN_MAP_SIZE_BITS = 6;                      ///< Minimal size of map is equal to 2 ^ MIN_MAP_SIZE_BITS
-static const uint MAX_MAP_SIZE_BITS = 11;                     ///< Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS
-static const uint MIN_MAP_SIZE      = 1 << MIN_MAP_SIZE_BITS; ///< Minimal map size = 64
-static const uint MAX_MAP_SIZE      = 1 << MAX_MAP_SIZE_BITS; ///< Maximal map size = 2048
+static const uint MIN_MAP_SIZE_BITS  = 6;                       ///< Minimal size of map is equal to 2 ^ MIN_MAP_SIZE_BITS
+static const uint MAX_MAP_SIZE_BITS  = 15;                      ///< Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS
+static const uint MAX_MAP_TILES_BITS = 26;                      ///< Maximal number of tiles in a map is equal to 2 ^ MAX_MAP_TILES_BITS.
+static const uint MIN_MAP_SIZE       = 1 << MIN_MAP_SIZE_BITS;  ///< Minimal map size = 64
+static const uint MAX_MAP_SIZE       = 1 << MAX_MAP_SIZE_BITS;  ///< Maximal map size = 32768 (only if other side is 2048 or smaller)
+static const uint MAX_MAP_TILES      = 1 << MAX_MAP_TILES_BITS; ///< Maximal number of tiles in a map = 8192 * 8192
 
 /**
  * Approximation of the length of a straight track, relative to a diagonal
diff --git a/src/misc.cpp b/src/misc.cpp
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -47,6 +47,7 @@
 void InitializeCheats();
 void InitializeNPF();
 void InitializeOldNames();
+void InitializeLinkGraphs();
 
 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings)
 {
@@ -54,14 +55,20 @@
 	 * related to the new game we're about to start/load. */
 	UnInitWindowSystem();
 
-	AllocateMap(size_x, size_y);
+	/* Has to be copied before AllocateMap because it's used there. */
+	if (reset_settings) {
+		MakeNewgameSettingsLive();
+	}
+
+	/* Also construct _map_heightdata here if needed, because we know 
+	 * wether we need it here. */
+	AllocateMap(size_x, size_y, true);
 
 	_pause_mode = PM_UNPAUSED;
 	_fast_forward = 0;
 	_tick_counter = 0;
 	_cur_tileloop_tile = 0;
 	_thd.redsq = INVALID_TILE;
-	if (reset_settings) MakeNewgameSettingsLive();
 
 	if (reset_date) {
 		SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0);
@@ -102,6 +109,7 @@
 #endif /* ENABLE_NETWORK */
 	InitializeAnimatedTiles();
 
+	InitializeLinkGraphs();
 	InitializeEconomy();
 
 	ResetObjectToPlace();
diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -33,6 +33,8 @@
 
 #include "table/strings.h"
 
+#include <time.h>
+
 /**
  * Try to retrive the current clipboard contents.
  *
@@ -183,6 +185,11 @@
 		GetString(this->landinfo_data[line_nr], td.str, lastof(this->landinfo_data[line_nr]));
 		line_nr++;
 
+		/* Height */
+		SetDParam(0, TileHeight(tile));
+		GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LANDINFO_HEIGHT, lastof(this->landinfo_data[line_nr]));
+		line_nr++;
+
 		/* Up to four owners */
 		for (uint i = 0; i < 4; i++) {
 			if (td.owner_type[i] == STR_NULL) continue;
@@ -814,17 +821,28 @@
 
 /**
  * Display animated feeder income.
- * @param x    World X position of the animation location.
- * @param y    World Y position of the animation location.
- * @param z    World Z position of the animation location.
- * @param cost Estimated feeder income.
+ * @param x        World X position of the animation location.
+ * @param y        World Y position of the animation location.
+ * @param z        World Z position of the animation location.
+ * @param transfer Estimated feeder income.
+ * @param income   Real income from goods being delivered to their final destination.
  */
-void ShowFeederIncomeAnimation(int x, int y, int z, Money cost)
+void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income)
 {
 	Point pt = RemapCoords(x, y, z);
 
-	SetDParam(0, cost);
-	AddTextEffect(STR_FEEDER, pt.x, pt.y, DAY_TICKS, TE_RISING);
+	SetDParam(0, transfer);
+	if (income == 0) {
+		AddTextEffect(STR_FEEDER, pt.x, pt.y, DAY_TICKS, TE_RISING);
+	} else {
+		StringID msg = STR_FEEDER_COST;
+		if (income < 0) {
+			income = -income;
+			msg = STR_FEEDER_INCOME;
+		}
+		SetDParam(1, income);
+		AddTextEffect(msg, pt.x, pt.y, DAY_TICKS, TE_RISING);
+	}
 }
 
 /**
@@ -1685,3 +1703,73 @@
 
 	new QueryWindow(&_query_desc, caption, message, parent, callback);
 }
+
+/** Widgets of the system time window. */
+enum SystemTimeWindowWidgets {
+	TW_TIME_TEXT,      ///< The time text (eg. 2009-12-31 14:55:55)
+};
+
+static const NWidgetPart _nested_time_widgets[] = {
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+		NWidget(WWT_CAPTION,  COLOUR_GREY),  SetDataTip(STR_SYSTEM_TIME, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_SHADEBOX, COLOUR_GREY),
+		NWidget(WWT_STICKYBOX, COLOUR_GREY),
+	EndContainer(),
+	NWidget(WWT_PANEL, COLOUR_CREAM),
+	NWidget(WWT_FRAME, COLOUR_CREAM), SetPadding(0, 5, 1, 5),
+			NWidget(WWT_EMPTY, INVALID_COLOUR, TW_TIME_TEXT),
+	EndContainer(),
+};
+
+static const WindowDesc _time_desc(
+	WDP_AUTO, 0, 0,
+	WC_SYSTEM_TIME, WC_NONE,
+	0,
+	_nested_time_widgets, lengthof(_nested_time_widgets)
+);
+
+struct TimeWindow : public Window {
+	time_t last_time;
+
+	TimeWindow() : Window(), last_time(0)
+	{
+		this->InitNested(&_time_desc);
+		this->flags4 |= WF_STICKY;
+	}
+
+	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
+	{
+		Dimension d = GetStringBoundingBox("2009-09-09 20:00:00");
+
+		*size = maxdim(*size, d);
+	}
+
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+	}
+
+	virtual void DrawWidget(const Rect &r, int widget) const
+	{
+		static char buf[1024];
+		time_t now = time(NULL);
+
+		strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&now));
+
+		DrawString(r.left + 2, r.right - 2, r.top + 4, buf, TC_WHITE, SA_LEFT | SA_FORCE);
+	}
+
+	virtual void OnTick()
+	{
+		time_t now = time(NULL);
+		if (now != this->last_time)
+			this->SetDirty();
+	}
+};
+
+void ShowSystemTimeWindow()
+{
+	DeleteWindowById(WC_SYSTEM_TIME, 0);
+	new TimeWindow();
+}
diff --git a/src/moving_average.cpp b/src/moving_average.cpp
new file mode 100644
--- /dev/null
+++ b/src/moving_average.cpp
@@ -0,0 +1,31 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file moving_average.cpp Implementation of moving average functions */
+
+#include "moving_average.h"
+#include "date_func.h"
+#include "station_base.h"
+
+/**
+ * Run moving average decrease function on all items from a pool which are due
+ * this tick. This function expects to be run every tick. It calls a method
+ * "RunAverages()" on all items for which id % ORIG_DAY_TICKS == _tick_counter % ORIG_DAY_TICKS.
+ * So each item is called once a day.
+ */
+template <class Titem> void RunAverages()
+{
+	for (uint id = _tick_counter % DAY_TICKS; id < Titem::GetPoolSize(); id += DAY_TICKS) {
+		Titem *item = Titem::GetIfValid(id);
+		if (item != NULL) item->RunAverages();
+	}
+}
+
+template class MovingAverage<uint>;
+template void RunAverages<Station>();
diff --git a/src/moving_average.h b/src/moving_average.h
new file mode 100644
--- /dev/null
+++ b/src/moving_average.h
@@ -0,0 +1,78 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file moving_average.h Utility class for moving averages. */
+
+#ifndef MOVING_AVERAGE_H_
+#define MOVING_AVERAGE_H_
+
+#include "stdafx.h"
+#include "settings_type.h"
+#include "core/math_func.hpp"
+
+/**
+ * Class implementing moving average functionality. An instance of this class
+ * can be used to get a meaningful (Monthly()) value from a moving average and
+ * it can be used to do the decrease operation.
+ * @tparam Tvalue Type supporting operator*(uint), operator/(uint),
+ * operator*=(uint) and operator/=(uint) with the usual semantics.
+ */
+template<class Tvalue>
+class MovingAverage {
+protected:
+	uint length;
+
+public:
+	/**
+	 * Create a moving average.
+	 * @param length Length to be used.
+	 */
+	FORCEINLINE MovingAverage(uint length) : length(length)
+		{
+			assert(this->length > 0);
+		}
+
+	/**
+	 * Get the length of this moving average.
+	 * @return Length
+	 */
+	FORCEINLINE uint Length() const
+		{
+			return this->length;
+		}
+
+	/**
+	 * Get the current average for 30 "length units" from the given value.
+	 * Mind that no one forces you to decrease the average daily. If you
+	 * don't this is not a real "monthly" value. In any case it's not really
+	 * "monthly" as we don't account for months with different numbers of
+	 * days than 30. It doesn't matter, though. The point is to get an
+	 * average over a defined past timeframe.
+	 * @param value Raw moving average.
+	 * @return 30 "length unit" average.
+	 */
+	FORCEINLINE Tvalue Monthly(const Tvalue &value) const
+	{
+		return (value * 30) / (this->length);
+	}
+
+	/**
+	 * Decrease the given value using this moving average.
+	 * @param value Moving average value to be decreased.
+	 * @return Decreased value.
+	 */
+	FORCEINLINE Tvalue &Decrease(Tvalue &value) const
+	{
+		return value = (value * this->length) / (this->length + 1);
+	}
+};
+
+template<class Titem> void RunAverages();
+
+#endif /* MOVING_AVERAGE_H_ */
diff --git a/src/music_gui.cpp b/src/music_gui.cpp
--- a/src/music_gui.cpp
+++ b/src/music_gui.cpp
@@ -22,7 +22,6 @@
 #include "gui.h"
 #include "core/geometry_func.hpp"
 #include "string_func.h"
-#include "settings_type.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -64,8 +63,8 @@
 /** Indices of all ezy street songs */
 static byte _playlist_ezy_street[NUM_SONGS_CLASS + 1];
 
-assert_compile(lengthof(_settings_client.music.custom_1) == NUM_SONGS_PLAYLIST + 1);
-assert_compile(lengthof(_settings_client.music.custom_2) == NUM_SONGS_PLAYLIST + 1);
+assert_compile(lengthof(_msf.custom_1) == NUM_SONGS_PLAYLIST + 1);
+assert_compile(lengthof(_msf.custom_2) == NUM_SONGS_PLAYLIST + 1);
 
 /** The different playlists that can be played. */
 static byte * const _playlists[] = {
@@ -73,8 +72,8 @@
 	_playlist_old_style,
 	_playlist_new_style,
 	_playlist_ezy_street,
-	_settings_client.music.custom_1,
-	_settings_client.music.custom_2,
+	_msf.custom_1,
+	_msf.custom_2,
 };
 
 /**
@@ -197,17 +196,17 @@
 
 	memset(_cur_playlist, 0, sizeof(_cur_playlist));
 	do {
-		const char *filename = BaseMusic::GetUsedSet()->files[_playlists[_settings_client.music.playlist][i] - 1].filename;
+		const char *filename = BaseMusic::GetUsedSet()->files[_playlists[_msf.playlist][i] - 1].filename;
 		/* We are now checking for the existence of that file prior
 		 * to add it to the list of available songs */
 		if (!StrEmpty(filename) && FioCheckFileExists(filename, GM_DIR)) {
-			_cur_playlist[j] = _playlists[_settings_client.music.playlist][i];
+			_cur_playlist[j] = _playlists[_msf.playlist][i];
 			j++;
 		}
-	} while (_playlists[_settings_client.music.playlist][++i] != 0 && j < lengthof(_cur_playlist) - 1);
+	} while (_playlists[_msf.playlist][++i] != 0 && j < lengthof(_cur_playlist) - 1);
 
 	/* Do not shuffle when on the intro-start window, as the song to play has to be the original TTD Theme*/
-	if (_settings_client.music.shuffle && _game_mode != GM_MENU) {
+	if (_msf.shuffle && _game_mode != GM_MENU) {
 		i = 500;
 		do {
 			uint32 r = InteractiveRandom();
@@ -241,7 +240,7 @@
 		if (_cur_playlist[0] == 0) {
 			_song_is_active = false;
 			_music_wnd_cursong = 0;
-			_settings_client.music.playing = false;
+			_msf.playing = false;
 			return;
 		}
 	}
@@ -260,9 +259,9 @@
 
 void MusicLoop()
 {
-	if (!_settings_client.music.playing && _song_is_active) {
+	if (!_msf.playing && _song_is_active) {
 		StopMusic();
-	} else if (_settings_client.music.playing && !_song_is_active) {
+	} else if (_msf.playing && !_song_is_active) {
 		PlayPlaylistSong();
 	}
 
@@ -281,7 +280,7 @@
 
 static void SelectPlaylist(byte list)
 {
-	_settings_client.music.playlist = list;
+	_msf.playlist = list;
 	InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
 	InvalidateWindowData(WC_MUSIC_WINDOW, 0);
 }
@@ -305,15 +304,15 @@
 		this->InitNested(desc, number);
 		this->LowerWidget(MTSW_LIST_LEFT);
 		this->LowerWidget(MTSW_LIST_RIGHT);
-		this->SetWidgetDisabledState(MTSW_CLEAR, _settings_client.music.playlist <= 3);
-		this->LowerWidget(MTSW_ALL + _settings_client.music.playlist);
+		this->SetWidgetDisabledState(MTSW_CLEAR, _msf.playlist <= 3);
+		this->LowerWidget(MTSW_ALL + _msf.playlist);
 	}
 
 	virtual void SetStringParameters(int widget) const
 	{
 		switch (widget) {
 			case MTSW_PLAYLIST:
-				SetDParam(0, STR_MUSIC_PLAYLIST_ALL + _settings_client.music.playlist);
+				SetDParam(0, STR_MUSIC_PLAYLIST_ALL + _msf.playlist);
 				break;
 		}
 	}
@@ -327,9 +326,9 @@
 	{
 		if (!gui_scope) return;
 		for (int i = 0; i < 6; i++) {
-			this->SetWidgetLoweredState(MTSW_ALL + i, i == _settings_client.music.playlist);
+			this->SetWidgetLoweredState(MTSW_ALL + i, i == _msf.playlist);
 		}
-		this->SetWidgetDisabledState(MTSW_CLEAR, _settings_client.music.playlist <= 3);
+		this->SetWidgetDisabledState(MTSW_CLEAR, _msf.playlist <= 3);
 		this->SetDirty();
 	}
 
@@ -395,7 +394,7 @@
 				GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK);
 
 				int y = r.top + WD_FRAMERECT_TOP;
-				for (const byte *p = _playlists[_settings_client.music.playlist]; *p != 0; p++) {
+				for (const byte *p = _playlists[_msf.playlist]; *p != 0; p++) {
 					uint i = *p - 1;
 					SetDParam(0, GetTrackNumber(i));
 					SetDParam(1, 2);
@@ -414,10 +413,10 @@
 			case MTSW_LIST_LEFT: { // add to playlist
 				int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
 
-				if (_settings_client.music.playlist < 4) return;
+				if (_msf.playlist < 4) return;
 				if (!IsInsideMM(y, 0, BaseMusic::GetUsedSet()->num_available)) return;
 
-				byte *p = _playlists[_settings_client.music.playlist];
+				byte *p = _playlists[_msf.playlist];
 				for (uint i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
 					if (p[i] == 0) {
 						/* Find the actual song number */
@@ -439,10 +438,10 @@
 			case MTSW_LIST_RIGHT: { // remove from playlist
 				int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
 
-				if (_settings_client.music.playlist < 4) return;
+				if (_msf.playlist < 4) return;
 				if (!IsInsideMM(y, 0, NUM_SONGS_PLAYLIST)) return;
 
-				byte *p = _playlists[_settings_client.music.playlist];
+				byte *p = _playlists[_msf.playlist];
 				for (uint i = y; i != NUM_SONGS_PLAYLIST - 1; i++) {
 					p[i] = p[i + 1];
 				}
@@ -453,7 +452,7 @@
 			}
 
 			case MTSW_CLEAR: // clear
-				for (uint i = 0; _playlists[_settings_client.music.playlist][i] != 0; i++) _playlists[_settings_client.music.playlist][i] = 0;
+				for (uint i = 0; _playlists[_msf.playlist][i] != 0; i++) _playlists[_msf.playlist][i] = 0;
 				this->SetDirty();
 				StopMusic();
 				SelectSongToPlay();
@@ -546,8 +545,8 @@
 	MusicWindow(const WindowDesc *desc, WindowNumber number) : Window()
 	{
 		this->InitNested(desc, number);
-		this->LowerWidget(_settings_client.music.playlist + MW_ALL);
-		this->SetWidgetLoweredState(MW_SHUFFLE, _settings_client.music.shuffle);
+		this->LowerWidget(_msf.playlist + MW_ALL);
+		this->SetWidgetLoweredState(MW_SHUFFLE, _msf.shuffle);
 	}
 
 	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
@@ -620,7 +619,7 @@
 
 			case MW_MUSIC_VOL: case MW_EFFECT_VOL: {
 				DrawFrameRect(r.left, r.top + 2, r.right, r.bottom - 2, COLOUR_GREY, FR_LOWERED);
-				byte volume = (widget == MW_MUSIC_VOL) ? _settings_client.music.music_vol : _settings_client.music.effect_vol;
+				byte volume = (widget == MW_MUSIC_VOL) ? _msf.music_vol : _msf.effect_vol;
 				int x = (volume * (r.right - r.left) / 127);
 				if (_current_text_dir == TD_RTL) {
 					x = r.right - x;
@@ -642,7 +641,7 @@
 	{
 		if (!gui_scope) return;
 		for (int i = 0; i < 6; i++) {
-			this->SetWidgetLoweredState(MW_ALL + i, i == _settings_client.music.playlist);
+			this->SetWidgetLoweredState(MW_ALL + i, i == _msf.playlist);
 		}
 		this->SetDirty();
 	}
@@ -663,17 +662,17 @@
 				break;
 
 			case MW_STOP: // stop playing
-				_settings_client.music.playing = false;
+				_msf.playing = false;
 				break;
 
 			case MW_PLAY: // start playing
-				_settings_client.music.playing = true;
+				_msf.playing = true;
 				break;
 
 			case MW_MUSIC_VOL: case MW_EFFECT_VOL: { // volume sliders
 				int x = pt.x - this->GetWidget<NWidgetBase>(widget)->pos_x;
 
-				byte *vol = (widget == MW_MUSIC_VOL) ? &_settings_client.music.music_vol : &_settings_client.music.effect_vol;
+				byte *vol = (widget == MW_MUSIC_VOL) ? &_msf.music_vol : &_msf.effect_vol;
 
 				byte new_vol = x * 127 / this->GetWidget<NWidgetBase>(widget)->current_x;
 				if (_current_text_dir == TD_RTL) new_vol = 127 - new_vol;
@@ -688,8 +687,8 @@
 			}
 
 			case MW_SHUFFLE: // toggle shuffle
-				_settings_client.music.shuffle ^= 1;
-				this->SetWidgetLoweredState(MW_SHUFFLE, _settings_client.music.shuffle);
+				_msf.shuffle ^= 1;
+				this->SetWidgetLoweredState(MW_SHUFFLE, _msf.shuffle);
 				this->SetWidgetDirty(MW_SHUFFLE);
 				StopMusic();
 				SelectSongToPlay();
diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -580,6 +580,8 @@
 		p->Recv_string(company_info->clients, sizeof(company_info->clients));
 
 		SetWindowDirty(WC_NETWORK_WINDOW, 0);
+		InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
+		SetWindowClassesDirty(WC_WATCH_COMPANY);
 
 		return NETWORK_RECV_STATUS_OKAY;
 	}
@@ -620,6 +622,8 @@
 		strecpy(ci->client_name, name, lastof(ci->client_name));
 
 		SetWindowDirty(WC_CLIENT_LIST, 0);
+		InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
+		SetWindowClassesDirty(WC_WATCH_COMPANY);
 
 		return NETWORK_RECV_STATUS_OKAY;
 	}
@@ -1026,6 +1030,8 @@
 	}
 
 	SetWindowDirty(WC_CLIENT_LIST, 0);
+	InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
+	SetWindowClassesDirty(WC_WATCH_COMPANY);
 
 	/* If we come here it means we could not locate the client.. strange :s */
 	return NETWORK_RECV_STATUS_OKAY;
@@ -1043,6 +1049,8 @@
 	}
 
 	SetWindowDirty(WC_CLIENT_LIST, 0);
+	InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
+	SetWindowClassesDirty(WC_WATCH_COMPANY);
 
 	return NETWORK_RECV_STATUS_OKAY;
 }
@@ -1112,6 +1120,8 @@
 	if (client_id == _network_own_client_id) {
 		SetLocalCompany(company_id);
 	}
+	InvalidateWindowClassesData(WC_WATCH_COMPANY, 0);
+	SetWindowClassesDirty(WC_WATCH_COMPANY);
 
 	return NETWORK_RECV_STATUS_OKAY;
 }
diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp
--- a/src/network/network_gui.cpp
+++ b/src/network/network_gui.cpp
@@ -30,6 +30,7 @@
 #include "../core/geometry_func.hpp"
 #include "../newgrf_text.h"
 #include "../genworld.h"
+#include "../newgrf.h"
 
 #include "table/strings.h"
 #include "../table/sprites.h"
@@ -1193,6 +1194,14 @@
 			}
 
 			case NSSW_GENERATE_GAME: // Start game
+				{
+					int numof_opened_grfs = CountSelectedGRFs (_grfconfig_newgame);
+					//DEBUG(grf, 0,  "numof_opened_grfs = %d", numof_opened_grfs);
+					if ( numof_opened_grfs >= MAX_FILE_SLOTS_IN_NETWORK ) {
+						ShowErrorMessage(STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED, INVALID_STRING_ID, WL_ERROR);
+						break; // break case NSSW_START
+					}
+				}
 				_is_network_server = true;
 				if (_ctrl_pressed) {
 					StartNewGameWithoutGUI(GENERATE_NEW_SEED);
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -1822,7 +1822,7 @@
 			} else {
 				cs->lag_test = 0;
 			}
-			if (cs->last_frame_server - cs->last_token_frame >= 5 * DAY_TICKS) {
+			if (cs->last_frame_server - cs->last_token_frame >= 5 * (uint)DAY_TICKS) {
 				/* This is a bad client! It didn't send the right token back. */
 				IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
 				cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
@@ -1837,7 +1837,7 @@
 			}
 		} else if (cs->status == NetworkClientSocket::STATUS_INACTIVE) {
 			uint lag = NetworkCalculateLag(cs);
-			if (lag > 4 * DAY_TICKS) {
+			if (lag > 4 * (uint)DAY_TICKS) {
 				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->client_id, 4 * DAY_TICKS);
 				cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
 				continue;
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2424,7 +2424,7 @@
 				} else if (buf->Remaining() < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
 					grfmsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table (" PRINTF_SIZE ")", buf->Remaining());
 				} else {
-					byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
+					uint16 table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
 
 					for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
 						for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
@@ -8832,6 +8832,9 @@
 	/* Create dynamic list of industry legends for smallmap_gui.cpp */
 	BuildIndustriesLegend();
 
+	/* build the routemap legend, based on the available cargos */
+	BuildLinkStatsLegend();
+
 	/* Add all new airports to the airports array. */
 	FinaliseAirportsArray();
 	BindAirportSpecs();
@@ -8981,3 +8984,16 @@
 {
 	return HasBit(_misc_grf_features, bit);
 }
+
+/**
+ * Returns amount of user selected NewGRFs files.
+ */
+int CountSelectedGRFs(GRFConfig *grfconf)
+{	
+	int i = 0;
+	
+	/* Find last entry in the list */
+	for (const GRFConfig *list = grfconf; list != NULL; list = list->next , i++) {
+	}
+	return i;
+}
diff --git a/src/newgrf.h b/src/newgrf.h
--- a/src/newgrf.h
+++ b/src/newgrf.h
@@ -178,5 +178,6 @@
 
 StringID MapGRFStringID(uint32 grfid, StringID str);
 void ShowNewGRFError();
+int  CountSelectedGRFs (GRFConfig *grfconf);
 
 #endif /* NEWGRF_H */
diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp
--- a/src/newgrf_debug_gui.cpp
+++ b/src/newgrf_debug_gui.cpp
@@ -45,7 +45,7 @@
  */
 static inline uint GetFeatureIndex(uint window_number)
 {
-	return GB(window_number, 0, 24);
+	return GB(window_number, 0, 27);
 }
 
 /**
@@ -57,8 +57,8 @@
  */
 static inline uint GetInspectWindowNumber(GrfSpecFeature feature, uint index)
 {
-	assert((index >> 24) == 0);
-	return (feature << 24) | index;
+	assert((index >> 27) == 0);
+	return (feature << 27) | index;
 }
 
 /**
@@ -249,7 +249,7 @@
  */
 static inline GrfSpecFeature GetFeatureNum(uint window_number)
 {
-	return (GrfSpecFeature)GB(window_number, 24, 8);
+	return (GrfSpecFeature)GB(window_number, 27, 8);
 }
 
 /**
diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp
--- a/src/newgrf_engine.cpp
+++ b/src/newgrf_engine.cpp
@@ -552,7 +552,7 @@
 
 			{
 				const Vehicle *w = v->Next();
-				uint16 altitude = v->z_pos - w->z_pos; // Aircraft height - shadow height
+				uint32 altitude = v->z_pos - w->z_pos; // Aircraft height - shadow height
 				byte airporttype = ATP_TTDP_LARGE;
 
 				const Station *st = GetTargetAirportIfValid(Aircraft::From(v));
diff --git a/src/newgrf_object.h b/src/newgrf_object.h
--- a/src/newgrf_object.h
+++ b/src/newgrf_object.h
@@ -66,7 +66,7 @@
 	ObjectFlags flags;            ///< Flags/settings related to the object.
 	AnimationInfo animation;      ///< Information about the animation.
 	uint16 callback_mask;         ///< Bitmask of requested/allowed callbacks.
-	uint8 height;                 ///< The height of this structure, in heightlevels; max MAX_TILE_HEIGHT.
+	uint8 height;                 ///< The height of this structure, in heightlevels; max MAX_TILE_HEIGHT_OLD. Note: Do not increase unless the pillar-glitches are fixed with high bridges.
 	uint8 views;                  ///< The number of views.
 	bool enabled;                 ///< Is this spec enabled?
 
diff --git a/src/newgrf_station.h b/src/newgrf_station.h
--- a/src/newgrf_station.h
+++ b/src/newgrf_station.h
@@ -25,7 +25,7 @@
 	STAT_CLASS_BEGIN = 0,    ///< the lowest valid value
 	STAT_CLASS_DFLT = 0,     ///< Default station class.
 	STAT_CLASS_WAYP,         ///< Waypoint class.
-	STAT_CLASS_MAX = 32,     ///< Maximum number of classes.
+	STAT_CLASS_MAX = 96,     ///< Maximum number of classes.
 };
 typedef SimpleTinyEnumT<StationClassID, byte> StationClassIDByte;
 template <> struct EnumPropsT<StationClassID> : MakeEnumPropsT<StationClassID, byte, STAT_CLASS_BEGIN, STAT_CLASS_MAX, STAT_CLASS_MAX, 8> {};
diff --git a/src/openttd.cpp b/src/openttd.cpp
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -25,6 +25,7 @@
 #include "saveload/saveload.h"
 #include "company_func.h"
 #include "command_func.h"
+#include "command_queue.h"
 #include "news_func.h"
 #include "fios.h"
 #include "aircraft.h"
@@ -49,6 +50,7 @@
 #include "animated_tile_func.h"
 #include "roadstop_base.h"
 #include "elrail_func.h"
+#include "copy_paste.h"
 #include "rev.h"
 #include "highscore.h"
 #include "thread/thread.h"
@@ -61,11 +63,15 @@
 #include "hotkeys.h"
 #include "newgrf.h"
 #include "misc/getoptdata.h"
+#include "programmable_signals.h"
 
+#include "newgrf.h"
 
 #include "town.h"
 #include "industry.h"
 
+#include "linkgraph/linkgraph.h"
+
 #include <stdarg.h>
 
 #include "table/strings.h"
@@ -292,6 +298,19 @@
 	/* Uninitialize variables that are allocated dynamically */
 	GamelogReset();
 
+// TODO: ¿ Move and clean like the other pools in r21113 ?
+
+	/* Reinitialize the link graphs to forcibly stop the threads.
+	 * If a link graph thread is running while the link graph handlers are
+	 * deleted we get a crash.
+	 */
+	InitializeLinkGraphs();
+
+	FreeSignalPrograms();
+	FreeSignalDependencies();
+ 	FreeSignalSpeeds();
+// END TODO
+
 #ifdef ENABLE_NETWORK
 	free(_config_file);
 #endif
@@ -760,7 +779,7 @@
 	_screen.zoom = ZOOM_LVL_NORMAL;
 
 	/* restore saved music volume */
-	_music_driver->SetVolume(_settings_client.music.music_vol);
+	_music_driver->SetVolume(_msf.music_vol);
 
 	NetworkStartUp(); // initialize network-core
 
@@ -865,6 +884,24 @@
 	MarkWholeScreenDirty();
 }
 
+/*
+ * Too large size may be stored in settings (especially if switching between between OpenTTD
+ * versions with different map size limits), we have to check if it is valid before generating world.
+ * Simple separate checking of X and Y map sizes is not enough, as their sum is what counts for the limit.
+ * Check the size and decrease the larger of the sizes till the size is in limit.
+ */
+static void FixConfigMapSize()
+{
+	while (_settings_game.game_creation.map_x + _settings_game.game_creation.map_y > MAX_MAP_TILES_BITS) {
+		/* Repeat reducing larger of X/Y dimensions until the map size is within allowable limits */
+		if (_settings_game.game_creation.map_x > _settings_game.game_creation.map_y) {
+			_settings_game.game_creation.map_x--;
+		} else {
+			_settings_game.game_creation.map_y--;
+		}
+	}
+}
+
 static void MakeNewGame(bool from_heightmap, bool reset_settings)
 {
 	_game_mode = GM_NORMAL;
@@ -872,6 +909,7 @@
 	ResetGRFConfig(true);
 
 	GenerateWorldSetCallback(&MakeNewGameDone);
+	FixConfigMapSize();
 	GenerateWorld(from_heightmap ? GWM_HEIGHTMAP : GWM_NEWGAME, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y, reset_settings);
 }
 
@@ -887,6 +925,7 @@
 	ResetGRFConfig(true);
 
 	GenerateWorldSetCallback(&MakeNewEditorWorldDone);
+	FixConfigMapSize();
 	GenerateWorld(GWM_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
 }
 
@@ -944,9 +983,13 @@
 
 void SwitchToMode(SwitchMode new_mode)
 {
+	//If we are not saving, the command_queue will be reset
+	if ((new_mode != SM_SAVE_GAME) && (new_mode != SM_SAVE_TEMPLATE) && (new_mode != SM_LOAD_TEMPLATE))
+		_copy_paste_command_queue.ClearCopyPasteCommandQueue();
+
 #ifdef ENABLE_NETWORK
 	/* If we are saving something, the network stays in his current state */
-	if (new_mode != SM_SAVE_GAME) {
+	if (new_mode != SM_SAVE_GAME && new_mode != SM_SAVE_TEMPLATE && new_mode != SM_LOAD_TEMPLATE) {
 		/* If the network is active, make it not-active */
 		if (_networking) {
 			if (_network_server && (new_mode == SM_LOAD_GAME || new_mode == SM_NEWGAME || new_mode == SM_RESTARTGAME)) {
@@ -1031,6 +1074,7 @@
 		case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor
 			SetLocalCompany(OWNER_NONE);
 
+			FixConfigMapSize();
 			GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
 			MarkWholeScreenDirty();
 			break;
@@ -1073,11 +1117,30 @@
 
 		case SM_GENRANDLAND: // Generate random land within scenario editor
 			SetLocalCompany(OWNER_NONE);
+			FixConfigMapSize();
 			GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
 			/* XXX: set date */
 			MarkWholeScreenDirty();
 			break;
 
+		case SM_SAVE_TEMPLATE: /* Save Template */
+			if (_copy_paste.SaveLoadTemplate(_file_to_saveload.name, SL_SAVE) != SL_OK) {
+				SetDParamStr(0, _copy_paste.GetErrorString());
+				ShowErrorMessage(INVALID_STRING_ID, STR_JUST_RAW_STRING, WL_ERROR);
+			} else {
+				DeleteWindowById(WC_SAVELOAD, 0);
+			}
+			break;
+
+		case SM_LOAD_TEMPLATE: /* Load Template */
+			if (_copy_paste.SaveLoadTemplate(_file_to_saveload.name, SL_LOAD) != SL_OK) {
+				SetDParamStr(0, _copy_paste.GetErrorString());
+				ShowErrorMessage(INVALID_STRING_ID, STR_JUST_RAW_STRING, WL_ERROR);
+			} else {
+				DeleteWindowById(WC_SAVELOAD, 0);
+			}
+			break;
+
 		default: NOT_REACHED();
 	}
 
@@ -1240,6 +1303,8 @@
 
 		CheckCaches();
 
+		CallCopyPasteCommandQueueTick();
+
 		/* All these actions has to be done from OWNER_NONE
 		 *  for multiplayer compatibility */
 		Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
@@ -1256,6 +1321,7 @@
 
 		CallWindowTickEvent();
 		NewsLoop();
+
 		cur_company.Restore();
 	}
 
diff --git a/src/openttd.h b/src/openttd.h
--- a/src/openttd.h
+++ b/src/openttd.h
@@ -35,6 +35,8 @@
 	SM_LOAD_SCENARIO,   ///< Load scenario from scenario editor.
 	SM_START_HEIGHTMAP, ///< Load a heightmap and start a new game from it.
 	SM_LOAD_HEIGHTMAP,  ///< Load heightmap from scenario editor.
+	SM_SAVE_TEMPLATE,
+	SM_LOAD_TEMPLATE,
 };
 
 /** Display Options */
diff --git a/src/order_base.h b/src/order_base.h
--- a/src/order_base.h
+++ b/src/order_base.h
@@ -195,6 +195,16 @@
 private:
 	friend void AfterLoadVehicles(bool part_of_load); ///< For instantiating the shared vehicle chain
 	friend const struct SaveLoad *GetOrderListDescription(); ///< Saving and loading of order lists.
+	
+	/**
+	 * Get the order after the given one or the first one, if the given one is the
+	 * last one.
+	 * @param curr Order to find the next one for.
+	 * @return Next order.
+	 */
+	inline const Order *GetNext(const Order *curr) const { return (curr->next == NULL) ? this->GetFirstOrder() : curr->next; }
+
+	StationID GetNextStoppingStation(const Order *next, StationID curr_station, uint hops) const;
 
 	Order *first;                     ///< First order of the order list.
 	VehicleOrderID num_orders;        ///< NOSAVE: How many orders there are in the list.
@@ -236,6 +246,8 @@
 	 */
 	inline Order *GetLastOrder() const { return this->GetOrderAt(this->num_orders - 1); }
 
+	StationID GetNextStoppingStation(VehicleOrderID curr_order, StationID curr_station) const;
+
 	/**
 	 * Get number of orders in the order list.
 	 * @return number of orders in the chain.
diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -27,6 +27,7 @@
 #include "station_base.h"
 #include "waypoint_base.h"
 #include "company_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -354,6 +355,63 @@
 }
 
 /**
+ * Recursively determine the next deterministic station to stop at.
+ * @param next First order to check.
+ * @param curr_station Station the vehicle is just visiting or INVALID_STATION.
+ * @param hops Number of orders we have already checked.
+ * @return Next stoppping station or INVALID_STATION.
+ */
+StationID OrderList::GetNextStoppingStation(const Order *next, StationID curr_station, uint hops) const
+{
+	if (next == NULL || hops > this->GetNumOrders()) {
+		return INVALID_STATION;
+	}
+
+	if (next->IsType(OT_CONDITIONAL)) {
+		StationID skip_to = this->GetNextStoppingStation(this->GetOrderAt(next->GetConditionSkipToOrder()), curr_station, hops + 1);
+		StationID advance = this->GetNextStoppingStation(this->GetNext(next), curr_station, hops + 1);
+		return (skip_to == advance) ? skip_to : INVALID_STATION;
+	}
+
+	if (!(next->IsType(OT_GOTO_STATION) || next->IsType(OT_IMPLICIT)) ||
+			(next->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0 ||
+			next->GetDestination() == curr_station) {
+		return GetNextStoppingStation(this->GetNext(next), curr_station, hops + 1);
+	}
+
+	return next->GetDestination();
+}
+
+/**
+ * Get the next station the vehicle will stop at, if that is deterministic.
+ * @param curr_order ID of the current order.
+ * @param curr_station Station the vehicle is just visiting or INVALID_STATION.
+ * @return ID of the next station the vehicle will stop at or INVALID_STATION.
+ */
+StationID OrderList::GetNextStoppingStation(VehicleOrderID curr_order, StationID curr_station) const
+{
+	const Order *curr = this->GetOrderAt(curr_order);
+	if (curr == NULL) {
+		curr = this->GetFirstOrder();
+		if (curr == NULL) {
+			return INVALID_STATION;
+		}
+	}
+
+	/* If we're not at a station or the current order doesn't yield the station
+	 * we're at, we have to check the current order; otherwise we have to check
+	 * the next one.
+	 */
+	if (curr_station == INVALID_STATION || 
+			!(curr->IsType(OT_GOTO_STATION) || curr->IsType(OT_IMPLICIT)) ||
+			curr_station != curr->GetDestination()) {
+		return this->GetNextStoppingStation(curr, curr_station, 0);
+	} else {
+		return this->GetNextStoppingStation(this->GetNext(curr), curr_station, 1);
+	}
+}
+
+/**
  * Insert a new order into the order chain.
  * @param new_order is the order to insert into the chain.
  * @param index is the position where the order is supposed to be inserted.
@@ -630,7 +688,7 @@
 			if (st == NULL) return CMD_ERROR;
 
 			if (st->owner != OWNER_NONE) {
-				CommandCost ret = CheckOwnership(st->owner);
+				CommandCost ret = CheckInfraUsageAllowed(v->type, st->owner);
 				if (ret.Failed()) return ret;
 			}
 
@@ -675,7 +733,7 @@
 
 					if (st == NULL) return CMD_ERROR;
 
-					CommandCost ret = CheckOwnership(st->owner);
+					CommandCost ret = CheckInfraUsageAllowed(v->type, st->owner);
 					if (ret.Failed()) return ret;
 
 					if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
@@ -686,7 +744,7 @@
 
 					if (dp == NULL) return CMD_ERROR;
 
-					CommandCost ret = CheckOwnership(GetTileOwner(dp->xy));
+					CommandCost ret = CheckInfraUsageAllowed(v->type, GetTileOwner(dp->xy), dp->xy);
 					if (ret.Failed()) return ret;
 
 					switch (v->type) {
@@ -724,7 +782,7 @@
 				case VEH_TRAIN: {
 					if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
 
-					CommandCost ret = CheckOwnership(wp->owner);
+					CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner);
 					if (ret.Failed()) return ret;
 					break;
 				}
@@ -732,7 +790,7 @@
 				case VEH_SHIP:
 					if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
 					if (wp->owner != OWNER_NONE) {
-						CommandCost ret = CheckOwnership(wp->owner);
+						CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner);
 						if (ret.Failed()) return ret;
 					}
 					break;
@@ -867,6 +925,8 @@
 		}
 		/* Update any possible open window of the vehicle */
 		InvalidateVehicleOrder(u, INVALID_VEH_ORDER_ID | (sel_ord << 8));
+
+		RecalcFrozenIfLoading(u);
 	}
 
 	/* As we insert an order, the order to skip to will be 'wrong'. */
@@ -899,6 +959,9 @@
 	if (flags & DC_EXEC) {
 		DeleteVehicleOrders(dst);
 		InvalidateVehicleOrder(dst, -1);
+
+		RecalcFrozenIfLoading(dst);
+
 		InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
 	}
 	return CommandCost();
@@ -988,6 +1051,8 @@
 
 		/* Update any possible open window of the vehicle */
 		InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
+
+		RecalcFrozenIfLoading(u);
 	}
 
 	/* As we delete an order, the order to skip to will be 'wrong'. */
@@ -1032,12 +1097,15 @@
 	if (ret.Failed()) return ret;
 
 	if (flags & DC_EXEC) {
+		if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
+
 		v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
 		v->UpdateRealOrderIndex();
 
-		if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
+		InvalidateVehicleOrder(v, -2);
 
-		InvalidateVehicleOrder(v, -2);
+		if (_settings_game.order.timetable_separation) v->ClearSeparation();
+		if (_settings_game.order.timetable_separation) ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
 	}
 
 	/* We have an aircraft/ship, they have a mini-schedule, so update them all */
@@ -1124,6 +1192,8 @@
 			assert(v->orders.list == u->orders.list);
 			/* Update any possible open window of the vehicle */
 			InvalidateVehicleOrder(u, moving_order | (target_order << 8));
+
+			RecalcFrozenIfLoading(u);
 		}
 
 		/* As we move an order, the order to skip to will be 'wrong'. */
@@ -1377,6 +1447,8 @@
 				u->current_order.SetLoadType(order->GetLoadType());
 			}
 			InvalidateVehicleOrder(u, -2);
+
+			RecalcFrozenIfLoading(u);
 		}
 	}
 
@@ -1447,6 +1519,13 @@
 				/* Link this vehicle in the shared-list */
 				dst->AddToShared(src);
 
+				/* Set automation bit if target has it */
+				if (HasBit(src->vehicle_flags, VF_AUTOMATE_TIMETABLE))
+					SetBit(dst->vehicle_flags, VF_AUTOMATE_TIMETABLE);
+
+				if (_settings_game.order.timetable_separation) dst->ClearSeparation();
+				if (_settings_game.order.timetable_separation) ClrBit(dst->vehicle_flags, VF_TIMETABLE_STARTED);
+
 				InvalidateVehicleOrder(dst, -1);
 				InvalidateVehicleOrder(src, -2);
 
@@ -1518,6 +1597,8 @@
 		default: return CMD_ERROR;
 	}
 
+	RecalcFrozenIfLoading(dst);
+
 	return CommandCost();
 }
 
@@ -1701,6 +1782,8 @@
 					/* In GUI, simulate by removing the order and adding it back */
 					InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8));
 					InvalidateVehicleOrder(w, (INVALID_VEH_ORDER_ID << 8) | id);
+
+					RecalcFrozenIfLoading(w);
 				}
 			}
 		}
@@ -1751,6 +1834,8 @@
 			CancelLoadingDueToDeletedOrder(v);
 		}
 	}
+
+	RecalcFrozenIfLoading(v);
 }
 
 /**
diff --git a/src/order_gui.cpp b/src/order_gui.cpp
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -29,6 +29,7 @@
 #include "waypoint_base.h"
 #include "core/geometry_func.hpp"
 #include "hotkeys.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -375,53 +376,55 @@
 	order.index = 0;
 
 	/* check depot first */
-	switch (GetTileType(tile)) {
-		case MP_RAILWAY:
-			if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_company)) {
-				if (IsRailDepot(tile)) {
+	if (_settings_game.order.gotodepot) {
+		switch (GetTileType(tile)) {
+			case MP_RAILWAY:
+				if (v->type == VEH_TRAIN && IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, tile)) {
+					if (IsRailDepot(tile)) {
+						order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
+								_settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
+						if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
+						return order;
+					}
+				}
+				break;
+
+			case MP_ROAD:
+				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsInfraTileUsageAllowed(VEH_ROAD, v->owner, tile)) {
 					order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
 							_settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
 					return order;
 				}
-			}
-			break;
+				break;
 
-		case MP_ROAD:
-			if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_company)) {
-				order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
-						_settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
-				if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
-				return order;
-			}
-			break;
+			case MP_STATION:
+				if (v->type != VEH_AIRCRAFT) break;
+				if (IsHangar(tile) && IsInfraTileUsageAllowed(VEH_AIRCRAFT, v->owner, tile)) {
+					order.MakeGoToDepot(GetStationIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
+					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
+					return order;
+				}
+				break;
 
-		case MP_STATION:
-			if (v->type != VEH_AIRCRAFT) break;
-			if (IsHangar(tile) && IsTileOwner(tile, _local_company)) {
-				order.MakeGoToDepot(GetStationIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
-				if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
-				return order;
-			}
-			break;
+			case MP_WATER:
+				if (v->type != VEH_SHIP) break;
+				if (IsShipDepot(tile) && IsInfraTileUsageAllowed(VEH_SHIP, v->owner, tile)) {
+					order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
+					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
+					return order;
+				}
+				break;
 
-		case MP_WATER:
-			if (v->type != VEH_SHIP) break;
-			if (IsShipDepot(tile) && IsTileOwner(tile, _local_company)) {
-				order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
-				if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
-				return order;
-			}
-			break;
-
-		default:
-			break;
+			default:
+				break;
+		}
 	}
 
 	/* check waypoint */
 	if (IsRailWaypointTile(tile) &&
 			v->type == VEH_TRAIN &&
-			IsTileOwner(tile, _local_company)) {
+			IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, tile)) {
 		order.MakeGoToWaypoint(Waypoint::GetByTile(tile)->index);
 		if (_settings_client.gui.new_nonstop != _ctrl_pressed) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
 		return order;
@@ -436,7 +439,7 @@
 		StationID st_index = GetStationIndex(tile);
 		const Station *st = Station::Get(st_index);
 
-		if (st->owner == _local_company || st->owner == OWNER_NONE) {
+		if (IsInfraUsageAllowed(v->type, v->owner, st->owner)) {
 			byte facil;
 			(facil = FACIL_DOCK, v->type == VEH_SHIP) ||
 			(facil = FACIL_TRAIN, v->type == VEH_TRAIN) ||
diff --git a/src/order_type.h b/src/order_type.h
--- a/src/order_type.h
+++ b/src/order_type.h
@@ -94,6 +94,7 @@
 	ODTF_MANUAL          = 0,      ///< Manually initiated order.
 	ODTFB_SERVICE        = 1 << 0, ///< This depot order is because of the servicing limit.
 	ODTFB_PART_OF_ORDERS = 1 << 1, ///< This depot order is because of a regular order.
+	ODTFB_BREAKDOWN      = 1 << 2, ///< This depot order is because of a breakdown.
 };
 
 /**
diff --git a/src/os/macosx/osx_stdafx.h b/src/os/macosx/osx_stdafx.h
--- a/src/os/macosx/osx_stdafx.h
+++ b/src/os/macosx/osx_stdafx.h
@@ -32,7 +32,7 @@
 #endif
 
 /* Check for mismatching 'architectures' */
-#if !defined(STRGEN) && !defined(SETTINGSGEN) && ((__LP64__ && !defined(_SQ64)) || (!__LP64__ && defined(_SQ64)))
+#if !defined(STRGEN) && ((__LP64__ && !defined(_SQ64)) || (!__LP64__ && defined(_SQ64)))
 #	error "Compiling 64 bits without _SQ64 set! (or vice versa)"
 #endif
 
diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp
--- a/src/pathfinder/follow_track.hpp
+++ b/src/pathfinder/follow_track.hpp
@@ -19,6 +19,7 @@
 #include "../tunnelbridge.h"
 #include "../tunnelbridge_map.h"
 #include "../depot_map.h"
+#include "../infrastructure_func.h"
 #include "pf_performance_timer.hpp"
 
 /**
@@ -298,6 +299,11 @@
 				m_err = EC_NO_WAY;
 				return false;
 			}
+			/* road stops shouldn't be entered unless allowed to */
+			if (!IsInfraTileUsageAllowed(VEH_ROAD, m_veh_owner, m_new_tile)) {
+				m_err = EC_OWNER;
+				return false;
+			}
 		}
 
 		/* single tram bits can only be entered from one direction */
@@ -316,8 +322,8 @@
 				m_err = EC_NO_WAY;
 				return false;
 			}
-			/* don't try to enter other company's depots */
-			if (GetTileOwner(m_new_tile) != m_veh_owner) {
+			/* don't try to enter other company's depots if not allowed */
+			if (!IsInfraTileUsageAllowed(VEH_ROAD, m_veh_owner, m_new_tile)) {
 				m_err = EC_OWNER;
 				return false;
 			}
@@ -330,8 +336,8 @@
 			}
 		}
 
-		/* rail transport is possible only on tiles with the same owner as vehicle */
-		if (IsRailTT() && GetTileOwner(m_new_tile) != m_veh_owner) {
+		/* rail transport is possible only on allowed tiles */
+		if (IsRailTT() && !IsInfraTileUsageAllowed(VEH_TRAIN, m_veh_owner, m_new_tile)) {
 			/* different owner */
 			m_err = EC_NO_WAY;
 			return false;
@@ -352,7 +358,7 @@
 			if (IsTunnel(m_new_tile)) {
 				if (!m_is_tunnel) {
 					DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(m_new_tile);
-					if (tunnel_enterdir != m_exitdir) {
+					if (tunnel_enterdir != m_exitdir || IsTunnelBridgeExit(m_new_tile)) {
 						m_err = EC_NO_WAY;
 						return false;
 					}
@@ -360,7 +366,7 @@
 			} else { // IsBridge(m_new_tile)
 				if (!m_is_bridge) {
 					DiagDirection ramp_enderdir = GetTunnelBridgeDirection(m_new_tile);
-					if (ramp_enderdir != m_exitdir) {
+					if (ramp_enderdir != m_exitdir || IsTunnelBridgeExit(m_new_tile)) {
 						m_err = EC_NO_WAY;
 						return false;
 					}
diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp
--- a/src/pathfinder/npf/npf.cpp
+++ b/src/pathfinder/npf/npf.cpp
@@ -15,6 +15,8 @@
 #include "../../viewport_func.h"
 #include "../../ship.h"
 #include "../../roadstop_base.h"
+#include "../../depot_map.h"
+#include "../../infrastructure_func.h"
 #include "../pathfinder_func.h"
 #include "../pathfinder_type.h"
 #include "../follow_track.hpp"
@@ -334,6 +336,8 @@
 			cost = NPF_TILE_LENGTH;
 			/* Increase the cost for level crossings */
 			if (IsLevelCrossing(tile)) cost += _settings_game.pf.npf.npf_crossing_penalty;
+			/* Increase cost for trafficlights. */
+			if (HasTrafficLights(tile)) cost += _settings_game.pf.npf.npf_road_trafficlight_penalty;
 			break;
 
 		case MP_STATION: {
@@ -663,25 +667,31 @@
  */
 static bool CanEnterTileOwnerCheck(Owner owner, TileIndex tile, DiagDirection enterdir)
 {
-	if (IsTileType(tile, MP_RAILWAY) || // Rail tile (also rail depot)
-			HasStationTileRail(tile) ||     // Rail station tile/waypoint
-			IsRoadDepotTile(tile) ||        // Road depot tile
-			IsStandardRoadStopTile(tile)) { // Road station tile (but not drive-through stops)
-		return IsTileOwner(tile, owner);  // You need to own these tiles entirely to use them
-	}
+	switch (GetTileType(tile)) {
+		case MP_RAILWAY:
+			return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile); // Rail tile (also rail depot)
 
-	switch (GetTileType(tile)) {
 		case MP_ROAD:
 			/* rail-road crossing : are we looking at the railway part? */
 			if (IsLevelCrossing(tile) &&
 					DiagDirToAxis(enterdir) != GetCrossingRoadAxis(tile)) {
-				return IsTileOwner(tile, owner); // Railway needs owner check, while the street is public
+				return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile); // Railway needs owner check, while the street is public
+			} else if (IsRoadDepot(tile)) { // Road depot tile
+				return IsInfraTileUsageAllowed(VEH_ROAD, owner, tile);
+			}
+			break;
+
+		case MP_STATION:
+			if (HasStationRail(tile)) { // Rail station tile/waypoint
+				return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile);
+			} else if (IsStandardRoadStopTile(tile)) { // Road station tile (but not drive-through stops)
+				return IsInfraTileUsageAllowed(VEH_ROAD, owner, tile);
 			}
 			break;
 
 		case MP_TUNNELBRIDGE:
 			if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
-				return IsTileOwner(tile, owner);
+				return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile);
 			}
 			break;
 
@@ -692,22 +702,6 @@
 	return true; // no need to check
 }
 
-
-/**
- * Returns the direction the exit of the depot on the given tile is facing.
- */
-static DiagDirection GetDepotDirection(TileIndex tile, TransportType type)
-{
-	assert(IsDepotTypeTile(tile, type));
-
-	switch (type) {
-		case TRANSPORT_RAIL:  return GetRailDepotDirection(tile);
-		case TRANSPORT_ROAD:  return GetRoadDepotDirection(tile);
-		case TRANSPORT_WATER: return GetShipDepotDirection(tile);
-		default: return INVALID_DIAGDIR; // Not reached
-	}
-}
-
 /** Tests if a tile is a road tile with a single tramtrack (tram can reverse) */
 static DiagDirection GetSingleTramBit(TileIndex tile)
 {
diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp
--- a/src/pathfinder/yapf/yapf_costrail.hpp
+++ b/src/pathfinder/yapf/yapf_costrail.hpp
@@ -229,6 +229,7 @@
 						/* special signal penalties */
 						if (n.m_num_signals_passed == 0) {
 							switch (sig_type) {
+								case SIGTYPE_PROG:
 								case SIGTYPE_COMBO:
 								case SIGTYPE_EXIT:   cost += Yapf().PfGetSettings().rail_firstred_exit_penalty; break; // first signal is red pre-signal-exit
 								case SIGTYPE_NORMAL:
@@ -513,14 +514,22 @@
 			/* Gather the next tile/trackdir/tile_type/rail_type. */
 			TILE next(tf_local.m_new_tile, (Trackdir)FindFirstBit2x64(tf_local.m_new_td_bits));
 
-			if (TrackFollower::DoTrackMasking() && IsTileType(next.tile, MP_RAILWAY)) {
-				if (HasSignalOnTrackdir(next.tile, next.td) && IsPbsSignal(GetSignalType(next.tile, TrackdirToTrack(next.td)))) {
-					/* Possible safe tile. */
-					end_segment_reason |= ESRB_SAFE_TILE;
-				} else if (HasSignalOnTrackdir(next.tile, ReverseTrackdir(next.td)) && GetSignalType(next.tile, TrackdirToTrack(next.td)) == SIGTYPE_PBS_ONEWAY) {
-					/* Possible safe tile, but not so good as it's the back of a signal... */
-					end_segment_reason |= ESRB_SAFE_TILE | ESRB_DEAD_END;
-					extra_cost += Yapf().PfGetSettings().rail_lastred_exit_penalty;
+			/* Get the setting if the back of a one way pbs signal is a safe waiting point and act accordingly. */
+			if (_settings_game.pf.back_of_one_way_pbs_waiting_point) {
+				if (TrackFollower::DoTrackMasking() && IsTileType(next.tile, MP_RAILWAY)) {
+					if (HasSignalOnTrackdir(next.tile, next.td) && IsPbsSignal(GetSignalType(next.tile, TrackdirToTrack(next.td)))) {
+						/* Possible safe tile. */
+						end_segment_reason |= ESRB_SAFE_TILE;
+					} else if (HasSignalOnTrackdir(next.tile, ReverseTrackdir(next.td)) && GetSignalType(next.tile, TrackdirToTrack(next.td)) == SIGTYPE_PBS_ONEWAY) {
+						/* Possible safe tile, but not so good as it's the back of a signal... */
+						end_segment_reason |= ESRB_SAFE_TILE | ESRB_DEAD_END;
+						extra_cost += Yapf().PfGetSettings().rail_lastred_exit_penalty;
+					}
+				}
+			} else {
+				if (TrackFollower::DoTrackMasking() && HasPbsSignalOnTrackdir(next.tile, next.td)) {
+				/* Possible safe tile. */
+				end_segment_reason |= ESRB_SAFE_TILE;
 				}
 			}
 
diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp
--- a/src/pathfinder/yapf/yapf_road.cpp
+++ b/src/pathfinder/yapf/yapf_road.cpp
@@ -90,6 +90,9 @@
 		} else {
 			/* non-diagonal trackdir */
 			cost = YAPF_TILE_CORNER_LENGTH + Yapf().PfGetSettings().road_curve_penalty;
+
+			/* Extra cost for traffic lights. */
+			if (HasTrafficLights(tile)) cost += Yapf().PfGetSettings().road_trafficlight_penalty;
 		}
 		return cost;
 	}
diff --git a/src/pbs.cpp b/src/pbs.cpp
--- a/src/pbs.cpp
+++ b/src/pbs.cpp
@@ -99,8 +99,7 @@
 		case MP_ROAD:
 			if (IsLevelCrossing(tile) && !HasCrossingReservation(tile)) {
 				SetCrossingReservation(tile, true);
-				BarCrossing(tile);
-				MarkTileDirtyByTile(tile); // crossing barred, make tile dirty
+				UpdateLevelCrossing(tile, false);
 				return true;
 			}
 			break;
@@ -218,7 +217,7 @@
 		/* Depot tile? Can't continue. */
 		if (IsRailDepotTile(tile)) break;
 		/* Non-pbs signal? Reservation can't continue. */
-		if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) break;
+		if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir))) && !IsSpeedSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) break;
 	}
 
 	return PBSTileInfo(tile, trackdir, false);
@@ -359,7 +358,10 @@
 
 	if (IsTileType(tile, MP_RAILWAY)) {
 		/* For non-pbs signals, stop on the signal tile. */
-		if (HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
+		if (HasSignalOnTrackdir(tile, trackdir) &&
+				!IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir))) &&
+				!IsSpeedSignal(GetSignalType(tile, TrackdirToTrack(trackdir))))
+			return true;
 	}
 
 	/* Check next tile. For perfomance reasons, we check for 90 degree turns ourself. */
diff --git a/src/programmable_signals.cpp b/src/programmable_signals.cpp
new file mode 100644
--- /dev/null
+++ b/src/programmable_signals.cpp
@@ -0,0 +1,773 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file programmable_signals.cpp Programmable Signals. */
+
+#include "stdafx.h"
+#include "programmable_signals.h"
+#include "debug.h"
+#include "command_func.h"
+#include "table/strings.h"
+#include "window_func.h"
+#include "company_func.h"
+#include "cmd_helper.h"
+#include <assert.h>
+
+ProgramList _signal_programs;
+SpeedLimits _speedlimits;
+
+SignalProgram::SignalProgram(TileIndex tile, Track track, bool raw)
+{
+	this->tile  = tile;
+	this->track = track;
+	if (!raw) {
+		this->first_instruction = new SignalSpecial(this, PSO_FIRST);
+		this->last_instruction  = new SignalSpecial(this, PSO_LAST);
+		SignalSpecial::link(this->first_instruction, this->last_instruction);
+	}
+}
+
+SignalProgram::~SignalProgram()
+{
+	this->DebugPrintProgram();
+	this->first_instruction->Remove();
+	delete this->first_instruction;
+	delete this->last_instruction;
+}
+
+struct SignalVM {
+	/* Initial information. */
+	uint num_exits;                 ///< Number of exits from block.
+	uint num_green;                 ///< Number of green exits from block.
+	SignalProgram *program;         ///< The program being run.
+
+	/* Current state. */
+	SignalInstruction *instruction; ///< Instruction to execute next.
+
+	/* Output state. */
+	SignalState state;
+
+	void Execute()
+	{
+		DEBUG(misc, 6, "Begining execution of programmable signal on tile %x, track %d", 
+					this->program->tile, this->program->track);
+		do {
+			DEBUG(misc, 10, "  Executing instruction %d, opcode %d", this->instruction->Id(), this->instruction->Opcode());
+			this->instruction->Evaluate(*this);
+		} while (this->instruction);
+		
+		DEBUG(misc, 6, "Completed");
+	}
+};
+
+/** Conditions. */
+
+SignalCondition::~SignalCondition()
+{}
+
+SignalSimpleCondition::SignalSimpleCondition(SignalConditionCode code)
+		: SignalCondition(code)
+{}
+
+/* virtual */ bool SignalSimpleCondition::Evaluate(SignalVM &vm)
+{
+	switch (this->cond_code) {
+		case PSC_ALWAYS:    return true;
+		case PSC_NEVER:     return false;
+		default: NOT_REACHED();
+	}
+}
+
+SignalVariableCondition::SignalVariableCondition(SignalConditionCode code)
+		: SignalCondition(code)
+{
+	switch (this->cond_code) {
+		case PSC_NUM_GREEN: comparator = SGC_NOT_EQUALS; break;
+		case PSC_NUM_RED:   comparator = SGC_EQUALS; break;
+		default: NOT_REACHED();
+	}
+	value = 0;
+}
+
+/*virtual*/ bool SignalVariableCondition::Evaluate(SignalVM &vm)
+{
+	uint32 var_val;
+	switch (this->cond_code) {
+		case PSC_NUM_GREEN:  var_val = vm.num_green; break;
+		case PSC_NUM_RED:    var_val = vm.num_exits - vm.num_green; break;
+		default: NOT_REACHED();
+	}
+
+	switch (this->comparator) {
+		case SGC_EQUALS:            return var_val == this->value;
+		case SGC_NOT_EQUALS:        return var_val != this->value;
+		case SGC_LESS_THAN:         return var_val <  this->value;
+		case SGC_LESS_THAN_EQUALS:  return var_val <= this->value;
+		case SGC_MORE_THAN:         return var_val >  this->value;
+		case SGC_MORE_THAN_EQUALS:  return var_val >= this->value;
+		case SGC_IS_TRUE:           return var_val != 0;
+		case SGC_IS_FALSE:          return !var_val;
+		default: NOT_REACHED();
+	}
+}
+
+SignalStateCondition::SignalStateCondition(SignalReference this_sig, TileIndex sig_tile, Trackdir sig_track)
+		: SignalCondition(PSC_SIGNAL_STATE), this_sig(this_sig), sig_tile(sig_tile)
+		, sig_track(sig_track)
+{
+	if (this->IsSignalValid()) {
+		AddSignalDependency(SignalReference(this->sig_tile, TrackdirToTrack(sig_track)), this->this_sig);
+	}
+}
+
+bool SignalStateCondition::IsSignalValid()
+{
+	if (IsValidTile(this->sig_tile)) {
+		if (HasSignalOnTrackdir(this->sig_tile, this->sig_track)) {
+			return true;
+		} else {
+			Invalidate();
+		}
+	}
+	return false;
+}
+
+void SignalStateCondition::Invalidate()
+{
+	this->sig_tile = INVALID_TILE;
+}
+
+
+void SignalStateCondition::SetSignal(TileIndex tile, Trackdir track)
+{
+	if (this->IsSignalValid()) {
+		RemoveSignalDependency(SignalReference(this->sig_tile, TrackdirToTrack(sig_track)), this->this_sig);
+	}
+	this->sig_tile = tile;
+	this->sig_track = track;
+	if (this->IsSignalValid()) {
+		AddSignalDependency(SignalReference(this->sig_tile, TrackdirToTrack(sig_track)), this->this_sig);
+	}
+}
+
+/*virtual*/ SignalStateCondition::~SignalStateCondition()
+{
+	if (this->IsSignalValid()) {
+		RemoveSignalDependency(SignalReference(this->sig_tile, TrackdirToTrack(sig_track)), this->this_sig);
+	}
+}
+
+/*virtual*/ bool SignalStateCondition::Evaluate(SignalVM& vm)
+{
+	if (!this->IsSignalValid()) {
+		DEBUG(misc, 1, "Signal (%x, %d) has an invalid condition", this->this_sig.tile, this->this_sig.track);
+		return false;
+	}
+
+	return GetSignalStateByTrackdir(this->sig_tile, this->sig_track) == SIGNAL_STATE_GREEN;
+}
+
+/** Instructions. */
+
+SignalInstruction::SignalInstruction(SignalProgram *prog, SignalOpcode op)
+		: opcode(op), previous(NULL), program(prog)
+{
+	*program->instructions.Append() = this;
+}
+
+SignalInstruction::~SignalInstruction()
+{
+	SignalInstruction** pthis = program->instructions.Find(this);
+	assert(pthis != program->instructions.End());
+	program->instructions.Erase(pthis);
+}
+
+void SignalInstruction::Insert(SignalInstruction *before_insn)
+{
+	this->previous = before_insn->Previous();
+	before_insn->Previous()->SetNext(this);
+	before_insn->SetPrevious(this);
+	this->SetNext(before_insn);
+}
+
+SignalSpecial::SignalSpecial(SignalProgram *prog, SignalOpcode op)
+		: SignalInstruction(prog, op)
+{
+	assert(op == PSO_FIRST || op == PSO_LAST);
+	this->next = NULL;
+}
+
+/*virtual*/ void SignalSpecial::Remove()
+{
+	if (opcode == PSO_FIRST) {
+		while (this->next->Opcode() != PSO_LAST) this->next->Remove();
+	} else if (opcode == PSO_LAST) {
+	} else NOT_REACHED();
+}
+
+/*static*/ void SignalSpecial::link(SignalSpecial *first, SignalSpecial *last)
+{
+	assert(first->opcode == PSO_FIRST && last->opcode == PSO_LAST);
+	first->next    = last;
+	last->previous = first;
+}
+
+void SignalSpecial::Evaluate(SignalVM &vm)
+{
+	if (this->opcode == PSO_FIRST) {
+		DEBUG(misc, 7, "  Executing First");
+		vm.instruction = this->next;
+	} else {
+		DEBUG(misc, 7, "  Executing Last");
+		vm.instruction = NULL;
+	}
+}
+
+/*virtual*/ void SignalSpecial::SetNext(SignalInstruction *next_insn)
+{
+	this->next = next_insn;
+}
+
+SignalIf::PseudoInstruction::PseudoInstruction(SignalProgram *prog, SignalOpcode op)
+		: SignalInstruction(prog, op)
+	{}
+
+SignalIf::PseudoInstruction::PseudoInstruction(SignalProgram *prog, SignalIf *block, SignalOpcode op)
+		: SignalInstruction(prog, op)
+{
+	this->block = block;
+	if (op == PSO_IF_ELSE) {
+		previous = block;
+	} else if (op == PSO_IF_ENDIF) {
+		previous = block->if_true;
+	} else NOT_REACHED();
+}
+
+/*virtual*/ void SignalIf::PseudoInstruction::Remove()
+{
+	if (opcode == PSO_IF_ELSE) {
+		this->block->if_true = NULL;
+		while(this->block->if_false) this->block->if_false->Remove();
+	} else if (opcode == PSO_IF_ENDIF) {
+		this->block->if_false = NULL;
+	} else NOT_REACHED();
+	delete this;
+}
+
+/*virtual*/ void SignalIf::PseudoInstruction::Evaluate(SignalVM &vm)
+{
+	DEBUG(misc, 7, "  Executing If Pseudo Instruction %s", opcode == PSO_IF_ELSE ? "Else" : "Endif");
+	vm.instruction = this->block->after;
+}
+
+/*virtual*/ void SignalIf::PseudoInstruction::SetNext(SignalInstruction *next_insn)
+{
+	if (this->opcode == PSO_IF_ELSE) {
+		this->block->if_false = next_insn;
+	} else if (this->opcode == PSO_IF_ENDIF) {
+		this->block->after = next_insn;
+	} else NOT_REACHED();
+}
+
+SignalIf::SignalIf(SignalProgram *prog, bool raw)
+		: SignalInstruction(prog, PSO_IF)
+{
+	if (!raw) {
+		this->condition = new SignalSimpleCondition(PSC_ALWAYS);
+		this->if_true   = new PseudoInstruction(prog, this, PSO_IF_ELSE);
+		this->if_false  = new PseudoInstruction(prog, this, PSO_IF_ENDIF);
+		this->after     = NULL;
+	}
+}
+
+/*virtual*/ void SignalIf::Remove()
+{
+	delete this->condition;
+	while (this->if_true)  this->if_true->Remove();
+
+	this->previous->SetNext(this->after);
+	this->after->SetPrevious(this->previous);
+	delete this;
+}
+
+/*virtual*/ void SignalIf::Insert(SignalInstruction *before_insn)
+{
+	this->previous = before_insn->Previous();
+	before_insn->Previous()->SetNext(this);
+	before_insn->SetPrevious(this->if_false);
+	this->after    = before_insn;
+}
+
+void SignalIf::SetCondition(SignalCondition *cond)
+{
+	assert(cond != this->condition);
+	delete this->condition;
+	this->condition = cond;
+}
+
+/*virtual*/ void SignalIf::Evaluate(SignalVM &vm)
+{
+	bool is_true = this->condition->Evaluate(vm);
+	DEBUG(misc, 7, "  Executing If, taking %s branch", is_true ? "then" : "else");
+	if (is_true) {
+		vm.instruction = this->if_true;
+	} else {
+		vm.instruction = this->if_false;
+	}
+}
+
+/*virtual*/ void SignalIf::SetNext(SignalInstruction *next_insn)
+{
+	this->if_true = next_insn;
+}
+
+
+
+SignalSet::SignalSet(SignalProgram *prog, SignalState state)
+		: SignalInstruction(prog, PSO_SET_SIGNAL)
+{
+	this->to_state = state;
+}
+
+/*virtual*/ void SignalSet::Remove()
+{
+	this->next->SetPrevious(this->previous);
+	this->previous->SetNext(this->next);
+	delete this;
+}
+
+/*virtual*/ void SignalSet::Evaluate(SignalVM &vm)
+{
+	DEBUG(misc, 7, "  Executing SetSignal, making %s", this->to_state? "green" : "red");
+	vm.state       = this->to_state;
+	vm.instruction = NULL;
+}
+
+
+/*virtual*/ void SignalSet::SetNext(SignalInstruction *next_insn)
+{
+	this->next = next_insn;
+}
+
+static SignalProgram *GetExistingSignalProgram(SignalReference ref)
+{
+	ProgramList::iterator i = _signal_programs.find(ref);
+	if (i != _signal_programs.end()) {
+		assert(i->first == ref);
+		return i->second;
+	} else {
+		return NULL;
+	}
+}
+
+
+SignalProgram *GetSignalProgram(SignalReference ref)
+{
+	SignalProgram *pr = GetExistingSignalProgram(ref);
+	if (!pr) {
+		pr = new SignalProgram(ref.tile, ref.track);
+		_signal_programs[ref] = pr;
+	} else {
+		assert(pr->tile == ref.tile && pr->track == ref.track);
+	}
+	return pr;
+}
+
+uint16 GetSignalSpeed(SignalReference ref)
+{
+	SpeedLimits::iterator i = _speedlimits.find(ref);
+	if (i != _speedlimits.end()) {
+		assert(i->first == ref);
+		return i->second;
+	} else {
+		return 0;
+	}
+}
+
+void FreeSignalProgram(SignalReference ref)
+{
+	DeleteWindowById(WC_SIGNAL_PROGRAM, (ref.tile << 3) | ref.track);
+	ProgramList::iterator i = _signal_programs.find(ref);
+	if (i != _signal_programs.end()) {
+		delete i->second;
+		_signal_programs.erase(i);
+	}
+}
+
+void FreeSignalSpeed(SignalReference ref)
+{
+	DeleteWindowById(WC_SIGNAL_PROGRAM, (ref.tile << 3) | ref.track);
+	SpeedLimits::iterator i = _speedlimits.find(ref);
+	if (i != _speedlimits.end()) {
+		_speedlimits.erase(i);
+	}
+}
+
+void FreeSignalSpeeds()
+{
+	_speedlimits.clear();
+}
+
+void FreeSignalPrograms()
+{
+	ProgramList::iterator i, e;
+	for (i = _signal_programs.begin(), e = _signal_programs.end(); i != e;) {
+		delete i->second;
+		_signal_programs.erase(i++); // Must postincrement here to avoid iterator invalidation.
+	}
+}
+
+SignalState RunSignalProgram(SignalReference ref, uint num_exits, uint num_green)
+{
+	SignalProgram *program = GetSignalProgram(ref);
+	SignalVM vm;
+	vm.program = program;
+	vm.num_exits = num_exits;
+	vm.num_green = num_green;
+
+	vm.instruction = program->first_instruction;
+	vm.state = SIGNAL_STATE_RED;
+
+	DEBUG(misc, 7, "%d exits, of which %d green", vm.num_exits, vm.num_green);
+	vm.Execute();
+	DEBUG(misc, 7, "Returning %s", vm.state == SIGNAL_STATE_GREEN ? "green" : "red");	
+	return vm.state;
+}
+
+void RemoveProgramDependencies(SignalReference by, SignalReference on)
+{
+	SignalProgram *prog = GetSignalProgram(by);
+	for (SignalInstruction **b = prog->instructions.Begin(), **i = b, **e = prog->instructions.End();
+			i != e; i++) {
+		SignalInstruction *insn = *i;
+		if (insn->Opcode() == PSO_IF) {
+			SignalIf* ifi = static_cast<SignalIf*>(insn);
+			if (ifi->condition->ConditionCode() == PSC_SIGNAL_STATE) {
+				SignalStateCondition* c = static_cast<SignalStateCondition*>(ifi->condition);
+				if(c->sig_tile == by.tile && TrackdirToTrack(c->sig_track) == by.track) {
+					c->Invalidate();
+				}
+			}
+		}
+	}
+
+	AddTrackToSignalBuffer(by.tile, by.track, GetTileOwner(by.tile));
+	UpdateSignalsInBuffer();
+}
+
+void SignalProgram::DebugPrintProgram()
+{
+	DEBUG(misc, 5, "Program %p listing", this);
+	for (SignalInstruction **b = this->instructions.Begin(), **i = b, **e = this->instructions.End();
+			i != e; i++) {
+		SignalInstruction *insn = *i;
+		DEBUG(misc, 5, " %ld: Opcode %d, prev %d", long(i - b), int(insn->Opcode()), 
+					int(insn->Previous() ? insn->Previous()->Id() : -1));
+	}
+}
+
+/**
+ * Insert a signal instruction into the signal program.
+ *
+ * @param tile The Tile on which to perform the operation.
+ * @param p1 Flags and information.
+ *   - Bits 0-2    Which track the signal sits on.
+ *   - Bits 3-18   ID of instruction to insert before.
+ *   - Bits 19-26  Which opcode to create.
+ *   - Bits 27-31  Reserved.
+ * @param p2 Depends upon instruction.
+ *   - PSO_SET_SIGNAL:
+ *       - Colour to set the signal to.
+ * @param text unused.
+ */
+CommandCost CmdInsertSignalInstruction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	Track track         = Extract<Track,        0,   3>(p1);
+	uint instruction_id = GB(p1, 3, 16);
+	SignalOpcode op     = Extract<SignalOpcode, 19,  8>(p1);
+
+	if (!IsValidTrack(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
+		return CMD_ERROR;
+	}
+
+	if (!IsTileOwner(tile, _current_company)) {
+		return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
+	}
+
+	SignalProgram *prog = GetExistingSignalProgram(SignalReference(tile, track));
+	if (!prog) {
+		return_cmd_error(STR_ERR_PROGSIG_NOT_THERE);
+	}
+
+	if (instruction_id > prog->instructions.Length()) {
+		return_cmd_error(STR_ERR_PROGSIG_INVALID_INSTRUCTION);
+	}
+
+	bool exec = (flags & DC_EXEC) != 0;
+
+	SignalInstruction *insert_before = prog->instructions[instruction_id];
+	switch (op) {
+		case PSO_IF: {
+			if (!exec) return CommandCost();
+			SignalIf *if_ins = new SignalIf(prog);
+			if_ins->Insert(insert_before);
+			break;
+		}
+
+		case PSO_SET_SIGNAL: {
+			SignalState ss = (SignalState) p2;
+			if (ss > SIGNAL_STATE_MAX) return_cmd_error(STR_ERR_PROGSIG_INVALID_OPCODE);
+			if (!exec) return CommandCost();
+
+			SignalSet *set = new SignalSet(prog, ss);
+			set->Insert(insert_before);
+			break;
+		}
+
+		case PSO_FIRST:
+		case PSO_LAST:
+		case PSO_IF_ELSE:
+		case PSO_IF_ENDIF:
+		default:
+			return_cmd_error(STR_ERR_PROGSIG_INVALID_OPCODE);
+	}
+
+	if (!exec) return CommandCost();
+	AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
+	UpdateSignalsInBuffer();
+	InvalidateWindowData(WC_SIGNAL_PROGRAM, (tile << 3) | track);
+	return CommandCost();
+}
+
+/**
+ * Modify a singal instruction.
+ *
+ * @param tile The Tile on which to perform the operation.
+ * @param p1 Flags and information.
+ *   - Bits 0-2    Which track the signal sits on.
+ *   - Bits 3-18   ID of instruction to insert before.
+ * @param p2 Depends upon instruction.
+ *   - PSO_SET_SIGNAL:
+ *       - Colour to set the signal to.
+ *   - PSO_IF:
+ *       - Bit 0 If 0, set the condidion code:
+ *         - Bit 1-8:  Conditon code to change to.
+ *       - Otherwise, if SignalVariableCondition:
+ *        - Bits 1-2:  Which field to change (ConditionField).
+ *        - Bits 3-31: Value to set field to.
+ *       - Otherwise, if SignalStateCondition:
+ *        - Bits 1-4:  Trackdir on which signal is located.
+ *        - Bits 5-31: Tile on which signal is located.
+ * @param text unused.
+ */
+CommandCost CmdModifySignalInstruction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	Track track         = Extract<Track, 0, 3 >(p1);
+	uint instruction_id = GB(p1, 3, 16);
+
+	if (!IsValidTrack(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
+		return CMD_ERROR;
+	}
+
+	if (!IsTileOwner(tile, _current_company)) {
+		return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
+	}
+
+	SignalProgram *prog = GetExistingSignalProgram(SignalReference(tile, track));
+	if (!prog) {
+		return_cmd_error(STR_ERR_PROGSIG_NOT_THERE);
+	}
+
+	if (instruction_id > prog->instructions.Length()) {
+		return_cmd_error(STR_ERR_PROGSIG_INVALID_INSTRUCTION);
+	}
+
+	bool exec = (flags & DC_EXEC) != 0;
+	
+	SignalInstruction *insn = prog->instructions[instruction_id];
+	switch (insn->Opcode()) {
+		case PSO_SET_SIGNAL: {
+			SignalState state = (SignalState) p2;
+			if (state > SIGNAL_STATE_MAX) {
+				return_cmd_error(STR_ERR_PROGSIG_INVALID_SIGNAL_STATE);
+			}
+			if (!exec) {
+				return CommandCost();
+			}
+			SignalSet *ss = static_cast<SignalSet*>(insn);
+			ss->to_state = state;
+		} break;
+
+		case PSO_IF: {
+			SignalIf *si = static_cast<SignalIf*>(insn);
+			byte act = GB(p2, 0, 1);
+			if (act == 0) { // Set code.
+				SignalConditionCode code = (SignalConditionCode) GB(p2, 1, 8);
+				if (code > PSC_MAX) {
+					return_cmd_error(STR_ERR_PROGSIG_INVALID_CONDITION);
+				}
+				if (!exec) return CommandCost();
+
+				SignalCondition *cond;
+				switch (code) {
+					case PSC_ALWAYS:
+					case PSC_NEVER:
+						cond = new SignalSimpleCondition(code);
+						break;
+
+					case PSC_NUM_GREEN:
+					case PSC_NUM_RED:
+						cond = new SignalVariableCondition(code);
+						break;
+
+					case PSC_SIGNAL_STATE:
+						cond = new SignalStateCondition(SignalReference(tile, track), INVALID_TILE, INVALID_TRACKDIR);
+						break;
+
+					default: NOT_REACHED();
+				}
+				si->SetCondition(cond);
+			} else { // Modify condition.
+				switch (si->condition->ConditionCode()) {
+					case PSC_ALWAYS:
+					case PSC_NEVER:
+						return CommandCost(STR_ERR_PROGSIG_INVALID_CONDITION_FIELD);
+
+					case PSC_NUM_GREEN:
+					case PSC_NUM_RED: {
+						SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(si->condition);
+						SignalConditionField f = (SignalConditionField) GB(p2, 1, 2);
+						uint32 val = GB(p2, 3, 27);
+						if (f == SCF_COMPARATOR) {
+							if (val > SGC_LAST) return_cmd_error(STR_ERR_PROGSIG_INVALID_COMPARATOR);
+							if (!exec) return CommandCost();						
+							vc->comparator = (SignalComparator) val;
+						} else if (f == SCF_VALUE) {
+							if (!exec) return CommandCost();
+							vc->value = val;
+						} else CommandCost(STR_ERR_PROGSIG_INVALID_CONDITION_FIELD);
+					} break;
+
+					case PSC_SIGNAL_STATE: {
+						SignalStateCondition *sc = static_cast<SignalStateCondition*>(si->condition);
+						Trackdir  td = (Trackdir)  GB(p2, 1, 4);
+						TileIndex ti = (TileIndex) GB(p2, 5, 27);
+
+						if (!IsValidTile(ti) || !IsValidTrackdir(td) || !HasSignalOnTrackdir(ti, td)
+								|| GetTileOwner(ti) != _current_company) {
+							return_cmd_error(STR_ERR_PROGSIG_INVALID_SIGNAL);
+						}
+						if (!exec) return CommandCost();
+						sc->SetSignal(ti, td);
+					} break;
+				}
+			}
+		} break;
+
+		case PSO_FIRST:
+		case PSO_LAST:
+		case PSO_IF_ELSE:
+		case PSO_IF_ENDIF:
+		default:
+			return CommandCost(STR_ERR_PROGSIG_INVALID_OPCODE);
+	}
+
+	if (!exec) return CommandCost();
+
+	AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
+	UpdateSignalsInBuffer();
+	InvalidateWindowData(WC_SIGNAL_PROGRAM, (tile << 3) | track);
+	return CommandCost();
+}
+
+/**
+ * Remove an instruction from a signal program.
+ *
+ * @param tile The Tile on which to perform the operation.
+ * @param p1 Flags and information.
+ *   - Bits 0-2    Which track the signal sits on.
+ *   - Bits 3-18   ID of instruction to insert before.
+ * @param p2 unused.
+ * @param text unused.
+ */
+CommandCost CmdRemoveSignalInstruction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	Track track         = Extract<Track, 0, 3 >(p1);
+	uint instruction_id = GB(p1, 3, 16);
+
+	if (!IsValidTrack(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
+		return CMD_ERROR;
+	}
+
+	if (!IsTileOwner(tile, _current_company)) {
+		return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
+	}
+
+	SignalProgram *prog = GetExistingSignalProgram(SignalReference(tile, track));
+	if (!prog) {
+		return_cmd_error(STR_ERR_PROGSIG_NOT_THERE);
+	}
+
+	if (instruction_id > prog->instructions.Length()) {
+		return_cmd_error(STR_ERR_PROGSIG_INVALID_INSTRUCTION);
+	}
+
+	bool exec = (flags & DC_EXEC) != 0;
+
+	SignalInstruction *insn = prog->instructions[instruction_id];
+	switch (insn->Opcode()) {
+		case PSO_SET_SIGNAL:
+		case PSO_IF:
+			if (!exec) return CommandCost();
+			insn->Remove();
+			break;
+
+		case PSO_FIRST:
+		case PSO_LAST:
+		case PSO_IF_ELSE:
+		case PSO_IF_ENDIF:
+		default:
+			return_cmd_error(STR_ERR_PROGSIG_INVALID_OPCODE);
+	}
+
+	if (!exec) return CommandCost();
+	AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
+	UpdateSignalsInBuffer();
+	InvalidateWindowData(WC_SIGNAL_PROGRAM, (tile << 3) | track);
+	return CommandCost();
+}
+
+/** Set a speed-signal's value
+ *
+ * @param tile The Tile on which to perform the operation
+ * @param p1 Flags and information
+ *   - Bits 0-2    Which track the signal sits on
+ *   - Bits 3-18   unused
+ * @param p2 the value to set
+ * @param text unused
+ */
+CommandCost CmdSetSignalSpeedLimit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	Track track         = Extract<Track, 0, 3 >(p1);
+
+	if (!IsValidTrack(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
+		return CMD_ERROR;
+	}
+
+	if (!IsTileOwner(tile, _current_company))
+		return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
+
+	SignalReference ref = SignalReference(tile, track);
+	_speedlimits[ref] = p2;
+
+	AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
+	UpdateSignalsInBuffer();
+	InvalidateWindowData(WC_SPEED_SIGNAL, (tile << 3) | track);
+	return CommandCost();
+}
diff --git a/src/programmable_signals.h b/src/programmable_signals.h
new file mode 100644
--- /dev/null
+++ b/src/programmable_signals.h
@@ -0,0 +1,441 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file programmable_signals.h Programmable Signals. */
+
+#ifndef PROGRAMMABLE_SIGNALS_H
+#define PROGRAMMABLE_SIGNALS_H
+#include "rail_map.h"
+#include "core/smallvec_type.hpp"
+#include <map>
+
+/** @defgroup progsigs Programmable Signals. */
+///@{
+
+/**
+ * The Programmable Signal virtual machine.
+ *
+ * This structure contains the state of the currently executing signal program.
+ */
+struct SignalVM;
+
+class SignalInstruction;
+class SignalSpecial;
+typedef SmallVector<SignalInstruction*, 4> InstructionList;
+
+/** The actual programmable signal information. */
+struct SignalProgram {
+	SignalProgram(TileIndex tile, Track track, bool raw = false);
+	~SignalProgram();
+	void DebugPrintProgram();
+	
+	TileIndex tile;
+	Track track;
+	
+	SignalSpecial *first_instruction;
+	SignalSpecial *last_instruction;
+	InstructionList instructions;
+};
+
+/**
+ * Programmable Signal opcode.
+ *
+ * Opcode types are discriminated by this enumeration. It is primarily used for
+ * code which must be able to inspect the type of a signal operation, rather than
+ * evaluate it (such as the programming GUI).
+ */
+enum SignalOpcode {
+	PSO_FIRST      = 0,   ///< Start pseudo instruction.
+	PSO_LAST       = 1,   ///< End pseudo instruction.
+	PSO_IF         = 2,   ///< If instruction.
+	PSO_IF_ELSE    = 3,   ///< If Else pseudo instruction.
+	PSO_IF_ENDIF   = 4,   ///< If Endif pseudo instruction.
+	PSO_SET_SIGNAL = 5,   ///< Set signal instruction.
+	
+	PSO_END,
+	PSO_INVALID   = 0xFF
+};
+template <> struct EnumPropsT<SignalOpcode> : MakeEnumPropsT<SignalOpcode, byte, PSO_FIRST, PSO_END, PSO_INVALID, 8> {};
+
+/** Signal instruction base class. All instructions must derive from this. */
+class SignalInstruction {
+public:
+	/* Get the instruction's opcode. */
+	inline SignalOpcode Opcode() const { return this->opcode; }
+	
+	/* Get the previous instruction. If this is NULL, then this is the first
+	 * instruction. */
+	inline SignalInstruction *Previous() const { return this->previous; }
+	
+	/* Get the Id of this instruction. */
+	inline int Id() const 
+	/* Const cast is safe (perculiarity of SmallVector). */
+	{ return program->instructions.FindIndex(const_cast<SignalInstruction*>(this)); }
+	
+	/* Insert this instruction, placing it before @p before_insn. */
+	virtual void Insert(SignalInstruction *before_insn);
+	
+	/* Evaluate the instruction. The instruction should update the VM state. */
+	virtual void Evaluate(SignalVM &vm) = 0;
+	
+	/* Remove the instruction. When removing itself, an instruction should
+	 * <ul>
+	 *   <li>Set next->previous to previous.
+	 *   <li>Set previous->next to next.
+	 *   <li>Destroy any other children.
+	 * </ul> */
+	virtual void Remove() = 0;
+	
+	/* Gets a reference to the previous member. This is only intended for use by
+	 * the saveload code. */
+	inline SignalInstruction *&GetPrevHandle()
+	{ return previous; }
+
+	/* Sets the previous instruction of this instruction. This is only intended 
+	 * to be used by instructions to update links during insertion and removal. */
+	inline void SetPrevious(SignalInstruction *prev)
+	{ previous = prev; }
+	/* Set the next instruction. This is only intended to be used by instructions
+	 * to update links during insertion and removal. */
+	virtual void SetNext(SignalInstruction *next_insn) = 0;
+	
+protected:
+	/* Constructs an instruction.
+	 * @param prog the program to add this instruction to
+	 * @param op the opcode of the instruction. */
+	SignalInstruction(SignalProgram *prog, SignalOpcode op) ;
+	~SignalInstruction();
+
+	const SignalOpcode opcode;
+	SignalInstruction *previous;
+	SignalProgram *program;
+};
+
+/**
+ * Programmable Signal condition code.
+ *
+ * These discriminate conditions in much the same way that SignalOpcode 
+ * discriminates instructions.
+ */
+enum SignalConditionCode {
+	PSC_ALWAYS = 0,       ///< Always true.
+	PSC_NEVER = 1,        ///< Always false.
+	PSC_NUM_GREEN = 2,    ///< Number of green signals behind this signal.
+	PSC_NUM_RED = 3,      ///< Number of red signals behind this signal.
+	PSC_SIGNAL_STATE = 4, ///< State of another signal.
+	
+	PSC_MAX = PSC_SIGNAL_STATE
+};
+
+class SignalCondition {
+public:
+	/* Get the condition's code. */
+	inline SignalConditionCode ConditionCode() const { return this->cond_code; }
+	
+	/* Evaluate the condition. */
+	virtual bool Evaluate(SignalVM& vm) = 0;
+	
+	/* Destroy the condition. Any children should also be destroyed. */
+	virtual ~SignalCondition();
+	
+protected:
+	SignalCondition(SignalConditionCode code) : cond_code(code) {}
+	
+	const SignalConditionCode cond_code;
+};
+
+
+/* -- Condition codes. -- */
+
+/**
+ * Simple condition code. These conditions have no complex inputs, and can be
+ * evaluated directly from VM state and their condition code.
+ */
+class SignalSimpleCondition: public SignalCondition {
+public:
+	SignalSimpleCondition(SignalConditionCode code);
+	virtual bool Evaluate(SignalVM& vm);
+};
+
+/** Comparator to use for variable conditions. */
+enum SignalComparator {
+	SGC_EQUALS = 0,           ///< the variable is equal to the specified value.
+	SGC_NOT_EQUALS = 1,       ///< the variable is not equal to the specified value.
+	SGC_LESS_THAN = 2,        ///< the variable is less than specified value.
+	SGC_LESS_THAN_EQUALS = 3, ///< the variable is less than or equal to the specified value.
+	SGC_MORE_THAN = 4,        ///< the variable is greater than the specified value.
+	SGC_MORE_THAN_EQUALS = 5, ///< the variable is grater than or equal to the specified value.
+	SGC_IS_TRUE = 6,          ///< the variable is true (non-zero).
+	SGC_IS_FALSE = 7,         ///< the variable is false (zero).
+	
+	SGC_LAST = SGC_IS_FALSE
+};
+
+/** Which field to modify in a condition. A parameter to CMD_MODIFY_SIGNAL_INSTRUCTION. */
+enum SignalConditionField {
+	SCF_COMPARATOR = 0, ///< the comparator (value from SignalComparator enum).
+	SCF_VALUE = 1,      ///< the value (integer value).
+};
+
+/**
+ * A conditon based upon comparing a variable and a value. This condition can be
+ * considered similar to the conditonal jumps in vehicle orders.
+ *
+ * The variable is specified by the conditon code, the comparison by @p comparator, and
+ * the value to compare against by @p value. The condition returns the result of that value.
+ */
+class SignalVariableCondition: public SignalCondition {
+public:
+	/* Constructs a condition refering to the value @p code refers to. Sets the
+	 * comparator and value to sane defaults. */
+	SignalVariableCondition(SignalConditionCode code);
+	
+	SignalComparator comparator;
+	uint32 value;
+	
+	/* Evaluates the condition. */
+	virtual bool Evaluate(SignalVM &vm);
+};
+
+/** A condition which is based upon the state of another signal. */
+class SignalStateCondition: public SignalCondition {
+	public:
+		SignalStateCondition(SignalReference this_sig, TileIndex sig_tile, 
+												 Trackdir sig_track);
+		
+		void SetSignal(TileIndex tile, Trackdir track);
+		bool IsSignalValid();
+        void Invalidate();
+		
+		virtual bool Evaluate(SignalVM& vm);
+		virtual ~SignalStateCondition();
+		
+		SignalReference this_sig;
+		TileIndex sig_tile;
+		Trackdir sig_track;
+		SignalState state;
+};
+
+
+/* -- Instructions. -- */
+
+/**
+ * The special start and end pseudo instructions.
+ *
+ * These instructions serve two purposes:
+ * <ol>
+ *   <li>They permit every other instruction to assume that there is another
+ *       following it. This makes the code much simpler (and by extension less
+ *       error prone).</li>
+ *   <li>Particularly in the case of the End instruction, they provide an 
+ *       instruction in the user interface that can be clicked on to add 
+ *       instructions at the end of a program.</li>
+ * </ol>
+ */
+class SignalSpecial: public SignalInstruction {
+public:
+	/**
+	 * Constructs a special signal of the opcode @p op in program @p prog.
+	 *
+	 * Generally you should not need to call this; it will be called by the 
+	 * program's constructor. An exception is in the saveload code, which needs
+	 * to construct raw objects to deserialize into.
+	 */
+	SignalSpecial(SignalProgram *prog, SignalOpcode op);
+	
+	/**
+	 * Evaluates the instruction. If this is an Start instruction, flow will be
+	 * vectored to the first instruction; if it is an End instruction, the program
+	 * will terminate and the signal will be left red.
+	 */
+	virtual void Evaluate(SignalVM &vm);
+	
+	/**
+	 * Links the first and last instructions in the program. Generally only to be
+	 * called from the SignalProgram constructor.
+	 */
+	static void link(SignalSpecial *first, SignalSpecial *last);
+	
+	/**
+	 * Removes this instruction. If this is the start instruction, then all of
+	 * the other instructions in the program will be successively removed,
+	 * (emptying it). If this is the End instruction, then it will do nothing.
+	 *
+	 * This operation, unlike when executed on most instructions, does not destroy
+	 * the instruction.
+	 */
+	virtual void Remove();
+	
+	/**
+	 * The next instruction after this one. On the End instruction, this should 
+	 * be NULL.
+	 */
+	SignalInstruction *next;
+	
+	virtual void SetNext(SignalInstruction *next_insn);
+};
+
+/**
+ * If signal instruction. This is perhaps the most important, as without it,
+ *  programmable signals are pretty useless.
+ *
+ * It's also the most complex!
+ */
+class SignalIf: public SignalInstruction {
+public:
+	/**
+	 * The If-Else and If-Endif pseudo instructions. The Else instruction 
+	 * follows the Then block, and the Endif instruction follows the Else block.
+	 *
+	 * These serve two purposes:
+	 * <ul>
+	 *  <li>They correctly vector the execution to after the if block 
+	 *      (if needed).
+	 *  <li>They provide an instruction for the GUI to insert other instructions
+	 *      before.
+	 * </ul>
+	 */
+	class PseudoInstruction: public SignalInstruction {
+	public:
+		/**
+		 * Normal constructor. The pseudo instruction will be constructed as 
+		 * belonging to @p block.
+		 */
+		PseudoInstruction(SignalProgram *prog, SignalIf *block, SignalOpcode op);
+		
+		/**
+		 * Constructs an empty instruction of type @p op. This should only be used
+		 * by the saveload code during deserialization. The instruction must have
+		 * its block field set correctly before the program is run.
+		 */
+		PseudoInstruction(SignalProgram *prog, SignalOpcode op);
+		
+		/**
+		 * Removes the pseudo instruction. Unless you are also removing the If it
+		 * belongs to, this is nonsense and dangerous.
+		 */
+		virtual void Remove();
+		
+		/**
+		 * Evaluate the pseudo instruction. This involves vectoring execution to
+		 * the instruction after the if.
+		 */
+		virtual void Evaluate(SignalVM &vm);
+		
+		/** The block to which this instruction belongs. */
+		SignalIf *block;
+		virtual void SetNext(SignalInstruction *next_insn);
+	};
+	
+public:
+	/**
+	 * Constructs an If instruction belonging to program @p prog. If @p raw is 
+	 * true, then the instruction is constructed raw (in order for the 
+	 * deserializer to be able to correctly deserialize the instruction).
+	 */
+	SignalIf(SignalProgram *prog, bool raw = false);
+	
+	/** Sets the instruction's condition, and releases the old condition. */
+	void SetCondition(SignalCondition *cond);
+	
+	/** Evaluates the If and takes the appropriate branch. */
+	virtual void Evaluate(SignalVM &vm);
+	
+	virtual void Insert(SignalInstruction *before_insn);
+	
+	/** Removes the If and all of its children. */
+	virtual void Remove();
+	
+	SignalCondition *condition;    ///< The if conditon.
+	SignalInstruction *if_true;    ///< The branch to take if true.
+	SignalInstruction *if_false;   ///< The branch to take if false.
+	SignalInstruction *after;      ///< The branch to take after the If.
+	
+	virtual void SetNext(SignalInstruction *next_insn);
+};
+
+/** Set signal instruction. This sets the state of the signal and terminates execution. */
+class SignalSet: public SignalInstruction {
+public:
+	/* Constructs the instruction and sets the state the signal is to be set to. */
+	SignalSet(SignalProgram *prog, SignalState = SIGNAL_STATE_RED);
+	
+	virtual void Evaluate(SignalVM &vm);
+	virtual void Remove();
+	
+	/* The state to set the signal to. */
+	SignalState to_state;
+	
+	/* The instruction following this one (for the editor). */
+	SignalInstruction *next;
+	
+	virtual void SetNext(SignalInstruction *next_insn);
+};
+
+/* The map type used for looking up signal programs. */
+typedef std::map<SignalReference, SignalProgram*> ProgramList;
+
+/* The global signal program list. */
+extern ProgramList _signal_programs;
+
+/* The map type used for looking up signal programs. */
+typedef std::map<SignalReference, uint16> SpeedLimits;
+
+/* The global signal program list */
+extern SpeedLimits _speedlimits;
+
+/* Verifies that a SignalReference refers to a signal which has a program. */
+static inline bool HasProgrammableSignals(SignalReference ref)
+{
+	return IsTileType(ref.tile, MP_RAILWAY) && GetRailTileType(ref.tile) == RAIL_TILE_SIGNALS
+	    && IsPresignalProgrammable(ref.tile, ref.track);
+}
+
+/* Verifies that a SignalReference refers to a speed-signal. */
+static inline bool HasSpeedSignals(SignalReference ref)
+{
+	return GetRailTileType(ref.tile) == RAIL_TILE_SIGNALS
+	    && IsSpeedSignal(ref.tile, ref.track);
+}
+
+/* Shows the programming window for the signal identified by @p tile and 
+ * @p track. */
+void ShowSignalProgramWindow(SignalReference ref);
+
+/* Shows the window to set the value of the speed-signal identified by @p
+ * tile and @p track. */
+void ShowSpeedSignalWindow(SignalReference ref);
+
+/* Gets the signal program for the tile identified by @p t and @p track.
+ * An empty program will be constructed if none is specified. */
+SignalProgram *GetSignalProgram(SignalReference ref);
+
+/* Gets the speed for the signal identified by @p t and @p track. */
+uint16 GetSignalSpeed(SignalReference ref);
+
+/* Frees a signal program by tile and track. */
+void FreeSignalProgram(SignalReference ref);
+
+/* Frees all signal programs (For use when creating a new game). */
+void FreeSignalPrograms();
+
+/* Frees a signal speed by tile and track. */
+void FreeSignalSpeed(SignalReference ref);
+
+/* Frees all signal speeds (For use when creating a new game). */
+void FreeSignalSpeeds();
+
+/* Runs the signal program, specifying the following parameters. */
+SignalState RunSignalProgram(SignalReference ref, uint num_exits, uint num_green);
+
+/* Remove dependencies on signal @p on from @p by. */
+void RemoveProgramDependencies(SignalReference by, SignalReference on);
+///@}
+
+#endif
diff --git a/src/programmable_signals_gui.cpp b/src/programmable_signals_gui.cpp
new file mode 100644
--- /dev/null
+++ b/src/programmable_signals_gui.cpp
@@ -0,0 +1,914 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file programmable_signals_gui.cpp GUI related to programming signals. */
+
+#include "stdafx.h"
+#include "programmable_signals.h"
+#include "command_func.h"
+#include "window_func.h"
+#include "strings_func.h"
+#include "string_func.h"
+#include "viewport_func.h"
+#include "textbuf_gui.h"
+#include "company_func.h"
+#include "widgets/dropdown_func.h"
+#include "gui.h"
+#include "gfx_func.h"
+#include "tilehighlight_func.h"
+#include "rail_map.h"
+#include "tile_cmd.h"
+
+#include "table/sprites.h"
+#include "table/strings.h"
+
+enum ProgramWindowWidgets {
+	PROGRAM_WIDGET_CAPTION,
+	PROGRAM_WIDGET_INSTRUCTION_LIST,
+	PROGRAM_WIDGET_SCROLLBAR,
+
+	PROGRAM_WIDGET_SEL_TOP_LEFT,
+	PROGRAM_WIDGET_SEL_TOP_MIDDLE,
+	PROGRAM_WIDGET_SEL_TOP_RIGHT,
+
+	PROGRAM_WIDGET_SET_STATE,
+	PROGRAM_WIDGET_COND_VARIABLE,
+	PROGRAM_WIDGET_COND_COMPARATOR,
+	PROGRAM_WIDGET_COND_VALUE,
+	PROGRAM_WIDGET_COND_GOTO_SIGNAL,
+	PROGRAM_WIDGET_COND_SET_SIGNAL,
+
+	PROGRAM_WIDGET_GOTO_SIGNAL,
+	PROGRAM_WIDGET_INSERT,
+	PROGRAM_WIDGET_REMOVE,
+};
+
+enum PanelWidgets {
+	/* Left. */
+	DPL_COND_VARIABLE = 0,
+	DPL_SET_STATE,
+
+	/* Middle. */
+	DPM_COND_COMPARATOR = 0,
+	DPM_COND_GOTO_SIGNAL,
+
+	/* Right. */
+	DPR_COND_VALUE = 0,
+	DPR_COND_SET_SIGNAL
+};
+
+static const StringID _program_insert[] = {
+	STR_PROGSIG_INSERT_IF,
+	STR_PROGSIG_INSERT_SET_SIGNAL,
+	INVALID_STRING_ID
+};
+
+static SignalOpcode OpcodeForIndex(int index)
+{
+	switch (index) {
+		case 0: return PSO_IF;
+		case 1: return PSO_SET_SIGNAL;
+		default: NOT_REACHED();
+	}
+}
+
+static bool IsConditionComparator(SignalCondition *cond)
+{
+	switch (cond->ConditionCode()) {
+		case PSC_NUM_GREEN:
+		case PSC_NUM_RED:
+			return true;
+
+		default:
+			return false;
+	}
+}
+
+static const StringID _program_condvar[] = {
+	STR_PROGSIG_COND_ALWAYS,       // PSC_ALWAYS
+	STR_PROGSIG_COND_NEVER,        // PSC_NEVER
+	STR_PROGSIG_CONDVAR_NUM_GREEN, // PSC_NUM_GREEN
+	STR_PROGSIG_CONDVAR_NUM_RED,   // PSC_NUM_RED
+	STR_PROGSIG_COND_SIGNAL_STATE, // PSC_SIGNAL_STATE
+	INVALID_STRING_ID
+};
+
+// TODO: These should probably lose the ORDER
+static const StringID _program_comparator[] = {
+	STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS,      // SGC_EQUALS
+	STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS,  // SGC_NOT_EQUALS
+	STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN,   // SGC_LESS_THAN
+	STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS, // SGC_LESS_THAN_EQUALS
+	STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN,   // SGC_MORE_THAN
+	STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS, // SGC_MORE_THAN_EQUALS
+	STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE,     // SGC_IS_TRUE
+	STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE,    // SGC_IS_FALSE
+	INVALID_STRING_ID
+};
+
+static const StringID _program_sigstate[] = {
+	STR_COLOUR_RED,
+	STR_COLOUR_GREEN,
+	INVALID_STRING_ID
+};
+
+/** Get the string for a condition. */
+static char *GetConditionString(SignalCondition *cond, char *buf, char *buflast, bool selected)
+{
+	StringID string = INVALID_STRING_ID;
+	bool comparator = IsConditionComparator(cond);
+
+	if (comparator) {
+		SignalVariableCondition *cv = static_cast<SignalVariableCondition*>(cond);
+		string = STR_PROGSIG_COND_COMPARE;
+		SetDParam(0, _program_condvar[cond->ConditionCode()]);
+		SetDParam(1, _program_comparator[cv->comparator]);
+		SetDParam(2, cv->value);
+	} else {
+		string = _program_condvar[cond->ConditionCode()];
+		if (cond->ConditionCode() == PSC_SIGNAL_STATE) {
+			string = STR_PROGSIG_CONDVAR_SIGNAL_STATE;
+			SetDParam(0, static_cast<SignalStateCondition*>(cond)->IsSignalValid()
+				? STR_PROGSIG_CONDVAR_SIGNAL_STATE_SPECIFIED : STR_PROGSIG_CONDVAR_SIGNAL_STATE_UNSPECIFIED);
+			SetDParam(1, selected ? STR_WHITE : STR_BLACK);
+		}
+	}
+	return GetString(buf, string, buflast);
+}
+
+/**
+ * Draws an instruction in the programming GUI.
+ * @param instruction The instruction to draw.
+ * @param y Y position for drawing.
+ * @param selected True, if the order is selected.
+ * @param indent How many levels the instruction is indented.
+ * @param left Left border for text drawing.
+ * @param right Right border for text drawing.
+ */
+static void DrawInstructionString(SignalInstruction *instruction, int y, bool selected, int indent, int left, int right)
+{
+	StringID instruction_string = INVALID_STRING_ID;
+
+	char condstr[512];
+
+	switch (instruction->Opcode()) {
+		case PSO_FIRST:
+			instruction_string = STR_PROGSIG_FIRST;
+			break;
+
+		case PSO_LAST:
+			instruction_string = STR_PROGSIG_LAST;
+			break;
+
+		case PSO_IF: {
+			SignalIf *if_ins = static_cast<SignalIf*>(instruction);
+			GetConditionString(if_ins->condition, condstr, lastof(condstr), selected);
+			SetDParamStr(0, condstr);
+			instruction_string = STR_PROGSIG_IF;
+			break;
+		}
+
+		case PSO_IF_ELSE:
+			instruction_string = STR_PROGSIG_ELSE;
+			break;
+
+		case PSO_IF_ENDIF:
+			instruction_string = STR_PROGSIG_ENDIF;
+			break;
+
+		case PSO_SET_SIGNAL: {
+			instruction_string = STR_PROGSIG_SET_SIGNAL;
+			SignalSet *set = static_cast<SignalSet*>(instruction);
+			SetDParam(0, _program_sigstate[set->to_state]);
+			break;
+		}
+
+		default: NOT_REACHED();
+	}
+
+	DrawString(left + indent * 16, right, y, instruction_string, selected ? TC_WHITE : TC_BLACK);
+}
+
+struct GuiInstruction {
+	SignalInstruction *insn;
+	uint indent;
+};
+
+typedef SmallVector<GuiInstruction, 4> GuiInstructionList;
+
+class ProgramWindow: public Window {
+public:
+	ProgramWindow(const WindowDesc *desc, SignalReference ref)
+	{
+		this->tile = ref.tile;
+		this->track = ref.track;
+		this->selected_instruction = -1;
+
+		this->CreateNestedTree(desc);
+		this->vscroll = this->GetScrollbar(PROGRAM_WIDGET_SCROLLBAR);
+		this->FinishInitNested(desc, (ref.tile << 3) | ref.track);
+
+		program = GetSignalProgram(ref);
+		RebuildInstructionList();
+	}
+
+	virtual void OnClick(Point pt, int widget, int click_count)
+	{
+		switch (widget) {
+			case PROGRAM_WIDGET_INSTRUCTION_LIST: {
+				int sel = this->GetInstructionFromPt(pt.y);
+
+				this->DeleteChildWindows();
+				HideDropDownMenu(this);
+
+				if (sel == -1 || this->GetOwner() != _local_company) {
+					/* Deselect. */
+					this->selected_instruction = -1;
+				} else {
+					this->selected_instruction = sel;
+				}
+
+				this->UpdateButtonState();
+			} break;
+
+			case PROGRAM_WIDGET_INSERT: {
+				DEBUG(misc, 5, "Selection is %d", this->selected_instruction);
+				if (this->GetOwner() != _local_company || this->selected_instruction < 1)
+					return;
+				ShowDropDownMenu(this, _program_insert, -1, PROGRAM_WIDGET_INSERT, 0, 0, 0);
+			} break;
+
+			case PROGRAM_WIDGET_REMOVE: {
+				SignalInstruction *ins = GetSelected();
+				if (this->GetOwner() != _local_company || !ins)
+					return;
+
+				uint32 p1 = 0;
+				SB(p1, 0, 3, this->track);
+				SB(p1, 3, 16, ins->Id());
+
+				DoCommandP(this->tile, p1, 0, CMD_REMOVE_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
+			} break;
+
+			case PROGRAM_WIDGET_SET_STATE: {
+				SignalInstruction *si = this->GetSelected();
+				if (!si || si->Opcode() != PSO_SET_SIGNAL) return;
+				SignalSet *ss = static_cast <SignalSet*>(si);
+
+				ShowDropDownMenu(this, _program_sigstate, ss->to_state, PROGRAM_WIDGET_SET_STATE, 0, 0, 0);
+			} break;
+
+			case PROGRAM_WIDGET_COND_VARIABLE: {
+				SignalInstruction *si = this->GetSelected();
+				if (!si || si->Opcode() != PSO_IF) return;
+				SignalIf *sif = static_cast <SignalIf*>(si);
+
+				ShowDropDownMenu(this, _program_condvar, sif->condition->ConditionCode(), PROGRAM_WIDGET_COND_VARIABLE, 0, 0, 0);
+			} break;
+
+			case PROGRAM_WIDGET_COND_COMPARATOR: {
+				SignalInstruction *si = this->GetSelected();
+				if (!si || si->Opcode() != PSO_IF) return;
+				SignalIf *sif = static_cast <SignalIf*>(si);
+				if (!IsConditionComparator(sif->condition)) return;
+				SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(sif->condition);
+
+				ShowDropDownMenu(this, _program_comparator, vc->comparator, PROGRAM_WIDGET_COND_COMPARATOR, 0, 0, 0);
+			} break;
+
+			case PROGRAM_WIDGET_COND_VALUE: {
+				SignalInstruction *si = this->GetSelected();
+				if (!si || si->Opcode() != PSO_IF) return;
+				SignalIf *sif = static_cast <SignalIf*>(si);
+				if (!IsConditionComparator(sif->condition)) return;
+				SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(sif->condition);
+
+				SetDParam(0, vc->value);
+				ShowQueryString(STR_JUST_INT, STR_PROGSIG_CONDITION_VALUE_CAPT, 5, this, CS_NUMERAL, QSF_NONE);
+			} break;
+
+			case PROGRAM_WIDGET_COND_GOTO_SIGNAL: {
+				SignalInstruction *si = this->GetSelected();
+				if (!si || si->Opcode() != PSO_IF) return;
+				SignalIf *sif = static_cast <SignalIf*>(si);
+				if (sif->condition->ConditionCode() != PSC_SIGNAL_STATE) return;
+				SignalStateCondition *sc = static_cast<SignalStateCondition*>(sif->condition);
+
+				if (sc->IsSignalValid()) {
+					ScrollMainWindowToTile(sc->sig_tile);
+				} else {
+					ShowErrorMessage(STR_ERROR_CAN_T_GOTO_UNDEFINED_SIGNAL, STR_EMPTY, WL_INFO);
+				}
+				this->RaiseWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
+			} break;
+
+			case PROGRAM_WIDGET_COND_SET_SIGNAL: {
+				this->SetWidgetDirty(PROGRAM_WIDGET_COND_SET_SIGNAL);
+				if (this->IsWidgetLowered(PROGRAM_WIDGET_COND_SET_SIGNAL)) {
+					SetObjectToPlaceWnd(ANIMCURSOR_BUILDSIGNALS, PAL_NONE, HT_RECT, this);
+				} else {
+					ResetObjectToPlace();
+				}
+			} break;
+
+			case PROGRAM_WIDGET_GOTO_SIGNAL: {
+				ScrollMainWindowToTile(this->tile);
+				this->RaiseWidget(PROGRAM_WIDGET_GOTO_SIGNAL);
+			} break;
+		}
+	}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		SignalInstruction *si = this->GetSelected();
+		if (!si || si->Opcode() != PSO_IF) return;
+		SignalIf *sif = static_cast <SignalIf*>(si);
+		if (sif->condition->ConditionCode() != PSC_SIGNAL_STATE) return;
+
+		if (!IsPlainRailTile(tile)) {
+			return;
+		}
+
+		TrackBits trackbits = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0));
+		if (trackbits & TRACK_BIT_VERT) { // N-S direction.
+			trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? TRACK_BIT_RIGHT : TRACK_BIT_LEFT;
+		}
+
+		if (trackbits & TRACK_BIT_HORZ) { // E-W direction.
+			trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? TRACK_BIT_UPPER : TRACK_BIT_LOWER;
+		}
+		Track track = FindFirstTrack(trackbits);
+
+		if (track == INVALID_TRACK) {
+			return;
+		}
+
+		Trackdir td = TrackToTrackdir(track);
+		Trackdir tdr = ReverseTrackdir(td);
+
+		if (HasSignalOnTrackdir(tile, td) && HasSignalOnTrackdir(tile, tdr)) {
+			ShowErrorMessage(STR_ERROR_INVALID_SIGNAL, STR_ERROR_CAN_T_DEPEND_UPON_BIDIRECTIONAL_SIGNALS, WL_INFO);
+			return;
+		} else if (HasSignalOnTrackdir(tile, tdr) && !HasSignalOnTrackdir(tile, td)) {
+			td = tdr;
+		}
+
+		if (!HasSignalOnTrackdir(tile, td)) {
+			return;
+		}
+
+		if (!IsPresignalExit(tile, track)) {
+			ShowErrorMessage(STR_ERROR_INVALID_SIGNAL, STR_ERROR_NOT_AN_EXIT_SIGNAL, WL_INFO);
+			return;
+		}
+
+		uint32 p1 = 0, p2 = 0;
+		SB(p1, 0, 3, this->track);
+		SB(p1, 3, 16, si->Id());
+
+		SB(p2, 0, 1, 1);
+		SB(p2, 1, 5,  td);
+		SB(p2, 5, 27, tile);
+
+		DoCommandP(this->tile, p1, p2, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
+		ResetObjectToPlace();
+		this->RaiseWidget(PROGRAM_WIDGET_COND_SET_SIGNAL);
+	}
+
+	virtual void OnQueryTextFinished(char *str)
+	{
+		if (!StrEmpty(str)) {
+			SignalInstruction *si = this->GetSelected();
+			if (!si || si->Opcode() != PSO_IF) return;
+			SignalIf *sif = static_cast <SignalIf*>(si);
+			if (!IsConditionComparator(sif->condition)) return;
+
+			uint value = atoi(str);
+
+			uint32 p1 = 0, p2 = 0;
+			SB(p1, 0, 3, this->track);
+			SB(p1, 3, 16, si->Id());
+
+			SB(p2, 0, 1, 1);
+			SB(p2, 1, 2, SCF_VALUE);
+			SB(p2, 3, 27, value);
+
+			DoCommandP(this->tile, p1, p2, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
+		}
+	}
+
+	virtual void OnDropdownSelect(int widget, int index)
+	{
+		SignalInstruction *ins = this->GetSelected();
+		if (!ins) return;
+
+		switch (widget) {
+			case PROGRAM_WIDGET_INSERT: {
+				uint32 p1 = 0;
+				SB(p1, 0, 3, this->track);
+				SB(p1, 3, 16, ins->Id());
+				SB(p1, 19, 8, OpcodeForIndex(index));
+
+				DoCommandP(this->tile, p1, 0, CMD_INSERT_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_INSERT_INSTRUCTION));
+				break;
+			}
+
+			case PROGRAM_WIDGET_SET_STATE: {
+				uint32 p1 = 0;
+				SB(p1, 0, 3, this->track);
+				SB(p1, 3, 16, ins->Id());
+
+				DoCommandP(this->tile, p1, index, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
+				break;
+			}
+
+			case PROGRAM_WIDGET_COND_VARIABLE: {
+				uint32 p1 = 0, p2 = 0;
+				SB(p1, 0, 3, this->track);
+				SB(p1, 3, 16, ins->Id());
+
+				SB(p2, 0, 1, 0);
+				SB(p2, 1, 8, index);
+
+				DoCommandP(this->tile, p1, p2, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
+				break;
+			}
+
+			case PROGRAM_WIDGET_COND_COMPARATOR: {
+				uint32 p1 = 0, p2 = 0;
+				SB(p1, 0, 3, this->track);
+				SB(p1, 3, 16, ins->Id());
+
+				SB(p2, 0, 1, 1);
+				SB(p2, 1, 2, SCF_COMPARATOR);
+				SB(p2, 3, 27, index);
+
+				DoCommandP(this->tile, p1, p2, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
+				break;
+			}
+		}
+	}
+
+	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
+	{
+		switch (widget) {
+			case PROGRAM_WIDGET_INSTRUCTION_LIST:
+				resize->height = FONT_HEIGHT_NORMAL;
+				size->height = 6 * resize->height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
+				break;
+		}
+	}
+
+	virtual void OnResize()
+	{
+		/* Update the scroll bar. */
+		this->vscroll->SetCapacityFromWidget(this, PROGRAM_WIDGET_INSTRUCTION_LIST);
+	}
+
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+	}
+
+	virtual void DrawWidget(const Rect &r, int widget) const
+	{
+		if (widget != PROGRAM_WIDGET_INSTRUCTION_LIST) return;
+
+		int y = r.top + WD_FRAMERECT_TOP;
+		int line_height = this->GetWidget<NWidgetBase>(PROGRAM_WIDGET_INSTRUCTION_LIST)->resize_y;
+
+		int no = this->vscroll->GetPosition();
+
+		for (const GuiInstruction *i = instructions.Begin() + no, *e = instructions.End();
+				i != e; ++i, no++) {
+			/* Don't draw anything if it extends past the end of the window. */
+			if (!this->vscroll->IsVisible(no)) break;
+
+			DrawInstructionString(i->insn, y, no == this->selected_instruction, i->indent, r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT);
+			y += line_height;
+		}
+	}
+
+	virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
+	{
+		if (!gui_scope) return;
+		RebuildInstructionList();
+	}
+
+	virtual void SetStringParameters(int widget) const
+	{
+		switch (widget) {
+			case PROGRAM_WIDGET_COND_VALUE: {
+				SetDParam(0, 0);
+				SignalInstruction *insn = this->GetSelected();
+				if (!insn || insn->Opcode() != PSO_IF) return;
+				SignalIf *si = static_cast<SignalIf*>(insn);
+				if (!IsConditionComparator(si->condition)) return;
+				SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(si->condition);
+				SetDParam(0, vc->value);
+			} break;
+		}
+	}
+
+private:
+	SignalInstruction *GetSelected() const
+	{
+		if (this->selected_instruction == -1
+				|| this->selected_instruction >= int(this->instructions.Length()))
+			return NULL;
+
+		return this->instructions[this->selected_instruction].insn;
+	}
+
+	Owner GetOwner()
+	{
+		return GetTileOwner(this->tile);
+	}
+
+	int GetInstructionFromPt(int y)
+	{
+		NWidgetBase *nwid = this->GetWidget<NWidgetBase>(PROGRAM_WIDGET_INSTRUCTION_LIST);
+		int sel = (y - nwid->pos_y - WD_FRAMERECT_TOP) / nwid->resize_y; // Selected line.
+
+		if ((uint)sel >= this->vscroll->GetCapacity()) return -1;
+
+		sel += this->vscroll->GetPosition();
+
+		return (sel <= int(this->instructions.Length()) && sel >= 0) ? sel : -1;
+	}
+
+	void RebuildInstructionList()
+	{
+		uint old_len = this->instructions.Length();
+		this->instructions.Clear();
+		SignalInstruction *insn = program->first_instruction;
+		uint indent = 0;
+
+		do {
+			DEBUG(misc, 5, "PSig Gui: Opcode %d", insn->Opcode());
+			switch (insn->Opcode()) {
+				case PSO_FIRST:
+				case PSO_LAST: {
+					SignalSpecial *s = static_cast<SignalSpecial*>(insn);
+					GuiInstruction *gi = this->instructions.Append();
+					gi->insn   = s;
+					gi->indent = indent;
+					insn = s->next;
+					break;
+				}
+
+				case PSO_IF: {
+					SignalIf *i = static_cast<SignalIf*>(insn);
+					GuiInstruction *gi = this->instructions.Append();
+					gi->insn   = i;
+					gi->indent = indent++;
+					insn = i->if_true;
+					break;
+				}
+
+				case PSO_IF_ELSE: {
+					SignalIf::PseudoInstruction *p = static_cast<SignalIf::PseudoInstruction*>(insn);
+					GuiInstruction *gi = this->instructions.Append();
+					gi->insn   = p;
+					gi->indent = indent - 1;
+					insn = p->block->if_false;
+					break;
+				}
+
+				case PSO_IF_ENDIF: {
+					SignalIf::PseudoInstruction *p = static_cast<SignalIf::PseudoInstruction*>(insn);
+					GuiInstruction *gi = this->instructions.Append();
+					gi->insn   = p;
+					gi->indent = --indent;
+					insn = p->block->after;
+					break;
+				}
+
+				case PSO_SET_SIGNAL: {
+					SignalSet *s = static_cast<SignalSet*>(insn);
+					GuiInstruction *gi = this->instructions.Append();
+					gi->insn   = s;
+					gi->indent = indent;
+					insn = s->next;
+					break;
+				}
+
+				default: NOT_REACHED();
+			}
+		} while (insn);
+
+		this->vscroll->SetCount(this->instructions.Length());
+		if (this->instructions.Length() != old_len)
+			selected_instruction = -1;
+		UpdateButtonState();
+	}
+
+	void UpdateButtonState()
+	{
+//		ResetObjectToPlace();
+		this->RaiseWidget(PROGRAM_WIDGET_INSERT);
+		this->RaiseWidget(PROGRAM_WIDGET_REMOVE);
+		this->RaiseWidget(PROGRAM_WIDGET_SET_STATE);
+		this->RaiseWidget(PROGRAM_WIDGET_COND_VARIABLE);
+		this->RaiseWidget(PROGRAM_WIDGET_COND_COMPARATOR);
+		this->RaiseWidget(PROGRAM_WIDGET_COND_VALUE);
+		this->RaiseWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
+
+		NWidgetStacked *left_sel   = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_LEFT);
+		NWidgetStacked *middle_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_MIDDLE);
+		NWidgetStacked *right_sel  = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_RIGHT);
+
+		/* Disable all the modifier buttons - we will re-enable them if applicable. */
+		this->DisableWidget(PROGRAM_WIDGET_SET_STATE);
+		this->DisableWidget(PROGRAM_WIDGET_COND_VARIABLE);
+		this->DisableWidget(PROGRAM_WIDGET_COND_COMPARATOR);
+		this->DisableWidget(PROGRAM_WIDGET_COND_VALUE);
+		this->DisableWidget(PROGRAM_WIDGET_COND_SET_SIGNAL);
+		this->DisableWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
+
+		/* Don't allow modifications if don't own, or have selected invalid instruction. */
+		if (this->GetOwner() != _local_company || this->selected_instruction < 1) {
+			this->DisableWidget(PROGRAM_WIDGET_INSERT);
+			this->DisableWidget(PROGRAM_WIDGET_REMOVE);
+			this->SetDirty();
+			return;
+		} else {
+			this->EnableWidget(PROGRAM_WIDGET_INSERT);
+			this->EnableWidget(PROGRAM_WIDGET_REMOVE);
+		}
+
+		SignalInstruction *insn = GetSelected();
+		if (!insn) return;
+
+		switch (insn->Opcode()) {
+			case PSO_IF: {
+				SignalIf *i = static_cast<SignalIf*>(insn);
+				left_sel->SetDisplayedPlane(DPL_COND_VARIABLE);
+				middle_sel->SetDisplayedPlane(DPM_COND_COMPARATOR);
+				right_sel->SetDisplayedPlane(DPR_COND_VALUE);
+
+				this->EnableWidget(PROGRAM_WIDGET_COND_VARIABLE);
+				this->GetWidget<NWidgetCore>(PROGRAM_WIDGET_COND_VARIABLE)->widget_data =
+						_program_condvar[i->condition->ConditionCode()];
+
+				if (IsConditionComparator(i->condition)) {
+					SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(i->condition);
+					this->EnableWidget(PROGRAM_WIDGET_COND_COMPARATOR);
+					this->EnableWidget(PROGRAM_WIDGET_COND_VALUE);
+
+					this->GetWidget<NWidgetCore>(PROGRAM_WIDGET_COND_COMPARATOR)->widget_data =
+						_program_comparator[vc->comparator];
+
+				} else if (i->condition->ConditionCode() == PSC_SIGNAL_STATE) {
+					this->EnableWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
+					this->EnableWidget(PROGRAM_WIDGET_COND_SET_SIGNAL);
+					middle_sel->SetDisplayedPlane(DPM_COND_GOTO_SIGNAL);
+					right_sel->SetDisplayedPlane(DPR_COND_SET_SIGNAL);
+				}
+			} break;
+
+			case PSO_SET_SIGNAL: {
+				SignalSet *s = static_cast<SignalSet*>(insn);
+				left_sel->SetDisplayedPlane(DPL_SET_STATE);
+				this->SetWidgetDisabledState(PROGRAM_WIDGET_SET_STATE, false);
+				this->GetWidget<NWidgetCore>(PROGRAM_WIDGET_SET_STATE)->widget_data =
+						_program_sigstate[s->to_state];
+			} break;
+
+			case PSO_FIRST:
+			case PSO_LAST:
+			case PSO_IF_ELSE:
+			case PSO_IF_ENDIF:
+				/* All cannot be modified. */
+				this->DisableWidget(PROGRAM_WIDGET_REMOVE);
+				break;
+
+			default:
+				NOT_REACHED();
+		}
+
+		this->SetDirty();
+	}
+
+	TileIndex tile;
+	Track track;
+	SignalProgram *program;
+	GuiInstructionList instructions;
+	int selected_instruction;
+	Scrollbar *vscroll;
+};
+
+static const NWidgetPart _nested_program_widgets[] = {
+	/* Title bar. */
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+		NWidget(WWT_CAPTION, COLOUR_GREY, PROGRAM_WIDGET_CAPTION), SetDataTip(STR_PROGSIG_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_SHADEBOX, COLOUR_GREY),
+		NWidget(WWT_STICKYBOX, COLOUR_GREY),
+	EndContainer(),
+
+	/* Program display. */
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_PANEL, COLOUR_GREY, PROGRAM_WIDGET_INSTRUCTION_LIST), SetMinimalSize(372, 62), SetDataTip(0x0, STR_PROGSIG_CAPTION), SetResize(1, 1), SetScrollbar(PROGRAM_WIDGET_SCROLLBAR), EndContainer(),
+		NWidget(NWID_VSCROLLBAR, COLOUR_GREY, PROGRAM_WIDGET_SCROLLBAR),
+	EndContainer(),
+
+	/* Button Bar. */
+	NWidget(NWID_HORIZONTAL),
+		NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+			NWidget(NWID_SELECTION, INVALID_COLOUR, PROGRAM_WIDGET_SEL_TOP_LEFT),
+				NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0),
+														SetDataTip(STR_NULL, STR_PROGSIG_COND_VARIABLE_TOOLTIP), SetResize(1, 0),
+				NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_SET_STATE), SetMinimalSize(124, 12), SetFill(1, 0),
+														SetDataTip(STR_NULL, STR_PROGSIG_SIGNAL_STATE_TOOLTIP), SetResize(1, 0),
+			EndContainer(),
+			NWidget(NWID_SELECTION, INVALID_COLOUR, PROGRAM_WIDGET_SEL_TOP_MIDDLE),
+				NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
+														SetDataTip(STR_NULL, STR_PROGSIG_COND_COMPARATOR_TOOLTIP), SetResize(1, 0),
+				NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, PROGRAM_WIDGET_COND_GOTO_SIGNAL), SetMinimalSize(124, 12), SetFill(1, 0),
+														SetDataTip(STR_PROGSIG_GOTO_SIGNAL, STR_PROGSIG_GOTO_SIGNAL_TOOLTIP), SetResize(1, 0),
+			EndContainer(),
+			NWidget(NWID_SELECTION, INVALID_COLOUR, PROGRAM_WIDGET_SEL_TOP_RIGHT),
+				NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, PROGRAM_WIDGET_COND_VALUE), SetMinimalSize(124, 12), SetFill(1, 0),
+														SetDataTip(STR_BLACK_COMMA, STR_PROGSIG_COND_VALUE_TOOLTIP), SetResize(1, 0),
+				NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, PROGRAM_WIDGET_COND_SET_SIGNAL), SetMinimalSize(124, 12), SetFill(1, 0),
+														SetDataTip(STR_PROGSIG_COND_SET_SIGNAL, STR_PROGSIG_COND_SET_SIGNAL_TOOLTIP), SetResize(1, 0),
+			EndContainer(),
+		EndContainer(),
+		NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, PROGRAM_WIDGET_GOTO_SIGNAL), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_RIGHT, STR_PROGSIG_GOTO_SIGNAL_TOOLTIP),
+	EndContainer(),
+
+	/* Second button row. */
+	NWidget(NWID_HORIZONTAL),
+		NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+				NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_INSERT), SetMinimalSize(124, 12), SetFill(1, 0),
+														SetDataTip(STR_PROGSIG_INSERT, STR_PROGSIG_INSERT_TOOLTIP), SetResize(1, 0),
+				NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, PROGRAM_WIDGET_REMOVE), SetMinimalSize(186, 12), SetFill(1, 0),
+														SetDataTip(STR_PROGSIG_REMOVE, STR_PROGSIG_REMOVE_TOOLTIP), SetResize(1, 0),
+		EndContainer(),
+		NWidget(WWT_RESIZEBOX, COLOUR_GREY),
+	EndContainer(),
+};
+
+static const WindowDesc _program_desc(
+	WDP_AUTO, 384, 100,
+	WC_SIGNAL_PROGRAM, WC_BUILD_SIGNAL,
+	WDF_CONSTRUCTION,
+	_nested_program_widgets, lengthof(_nested_program_widgets)
+);
+
+void ShowSignalProgramWindow(SignalReference ref)
+{
+	uint32 window_id = (ref.tile << 3) | ref.track;
+	if (BringWindowToFrontById(WC_SIGNAL_PROGRAM, window_id) != NULL) return;
+
+	new ProgramWindow(&_program_desc, ref);
+}
+
+extern uint ConvertSpeedToDisplaySpeed(uint speed);
+extern uint ConvertDisplaySpeedToSpeed(uint speed);
+
+enum SpeedWindowWidgets {
+	SPEED_WIDGET_CAPTION,
+	SPEED_WIDGET_VALUE,
+	SPEED_WIDGET_CLEAR,
+ 	SPEED_WIDGET_CHANGE,
+};
+
+class SpeedWindow: public Window {
+public:
+	SpeedWindow(const WindowDesc *desc, SignalReference ref)
+	{
+		this->InitNested(desc, (ref.tile << 3) | ref.track);
+		this->tile = ref.tile;
+		this->track = ref.track;
+
+		this->InvalidateData();
+		this->SetWidgetLoweredState(SPEED_WIDGET_CHANGE, true);
+		this->ShowChangeSpeedLimit();
+	}
+
+	void ShowChangeSpeedLimit()
+	{
+		uint16 speed = GetSignalSpeed(SignalReference(this->tile, this->track));
+		speed = ConvertSpeedToDisplaySpeed((speed * 10) / 16);
+
+		SetDParam(0, speed);
+		ShowQueryString(STR_JUST_INT, STR_SPEEDSIG_CAPTION, 31, this, CS_NUMERAL, QSF_NONE);
+	}
+
+	virtual void OnClick(Point pt, int widget, int click_count)
+	{
+		switch (widget) {
+			case SPEED_WIDGET_CLEAR: {
+				this->SetSpeedLimit(0);
+				break;
+			}
+			case SPEED_WIDGET_CHANGE: {
+				this->ShowChangeSpeedLimit();
+				break;
+			}
+		}
+	}
+
+	virtual void OnQueryTextFinished(char *str)
+	{
+		this->SetWidgetLoweredState(SPEED_WIDGET_CHANGE, false);
+		this->SetWidgetDirty(SPEED_WIDGET_CHANGE);
+
+		if (str == NULL) return;
+
+		uint16 speed = StrEmpty(str) ? 0 : strtoul(str, NULL, 10);
+		speed = ConvertDisplaySpeedToSpeed((speed * 16) / 10);
+
+		this->SetSpeedLimit(speed);
+	}
+
+	void SetSpeedLimit(uint16 speed)
+	{
+		uint32 p1 = 0;
+		SB(p1, 0, 3, this->track);
+
+		DoCommandP(this->tile, p1, (uint32)speed, CMD_SET_SIGNAL_SPEED_LIMIT | CMD_MSG(STR_ERROR_CAN_T_SET_SPEED));
+	}
+
+	virtual void OnPaint()
+	{
+		if (this->GetOwner() == _local_company) {
+			this->EnableWidget(SPEED_WIDGET_CLEAR);
+			this->EnableWidget(SPEED_WIDGET_CHANGE);
+		} else {
+			this->DisableWidget(SPEED_WIDGET_CLEAR);
+			this->DisableWidget(SPEED_WIDGET_CHANGE);
+		}
+		this->DrawWidgets();
+	}
+
+	virtual void OnInvalidateData(int data) {
+		uint16 speed = GetSignalSpeed(SignalReference(this->tile, this->track));
+
+		NWidgetCore *w = this->GetWidget<NWidgetCore>(SPEED_WIDGET_VALUE);
+
+		if (speed == 0) {
+			w->SetDataTip(STR_SPEEDSIG_VALUE_NONE, STR_NULL);
+		} else {
+			w->SetDataTip(STR_SPEEDSIG_VALUE, STR_NULL);
+		}
+	}
+
+	virtual void SetStringParameters(int widget) const
+	{
+		switch (widget) {
+			case SPEED_WIDGET_VALUE: {
+				 uint16 speed = GetSignalSpeed(SignalReference(this->tile, this->track));
+				 SetDParam(0, speed);
+				 break;
+			}
+		}
+	}
+
+private:
+	Owner GetOwner()
+	{
+		return GetTileOwner(this->tile);
+	}
+
+	TileIndex tile;
+	Track track;
+};
+
+static const NWidgetPart _nested_speed_widgets[] = {
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+		NWidget(WWT_CAPTION, COLOUR_GREY, SPEED_WIDGET_CAPTION), SetDataTip(STR_SPEEDSIG_CAPTION, STR_NULL),
+		NWidget(WWT_STICKYBOX, COLOUR_GREY),
+	EndContainer(),
+	NWidget(WWT_PANEL, COLOUR_GREY),
+		NWidget(WWT_LABEL, COLOUR_GREY, SPEED_WIDGET_VALUE), SetMinimalSize(128, 12), SetFill(1, 1), SetPadding(2, 2, 2, 2),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, SPEED_WIDGET_CLEAR), SetDataTip(STR_SPEEDSIG_CLEAR, STR_NULL), SetMinimalSize(87, 12), SetFill(1, 0),
+		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SPEED_WIDGET_CHANGE), SetDataTip(STR_SPEEDSIG_CHANGE, STR_NULL), SetMinimalSize(87, 12), SetFill(1, 0),
+	EndContainer(),
+};
+
+static const WindowDesc _speed_desc(
+	WDP_AUTO, 384, 100,
+	WC_SPEED_SIGNAL, WC_BUILD_SIGNAL,
+	WDF_CONSTRUCTION,
+	_nested_speed_widgets, lengthof(_nested_speed_widgets)
+);
+
+void ShowSpeedSignalWindow(SignalReference ref)
+{
+	uint32 window_id = (ref.tile << 3) | ref.track;
+	if (BringWindowToFrontById(WC_SPEED_SIGNAL, window_id) != NULL) return;
+
+	new SpeedWindow(&_speed_desc, ref);
+}
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -580,7 +580,15 @@
 
 			/* Charge extra to remove signals on the track, if they are there */
 			if (HasSignalOnTrack(tile, track)) {
-				cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS));
+				/* If track has an exit signal on it dissalow removal. */
+// Todo: Check if this exit signal has a dependancy or , if it is a progsig, depends on another exit signal. Allow removal if none of both is true.
+//       Removing the dependency or the being dependant upon flag would work equally well here ...
+				if (IsPresignalExit(tile, track)) {
+					return_cmd_error(STR_ERROR_MUST_REMOVE_EXIT_SIGNALS_FIRST);
+				} else {
+					CheckRemoveSignal(tile, track);
+					cost.AddCost(DoCommand(tile, track, 0, flags, CMD_REMOVE_SIGNALS));
+				}
 			}
 
 			if (flags & DC_EXEC) {
@@ -916,8 +924,7 @@
  * - p1 = (bit 4)   - 0 = signals, 1 = semaphores
  * - p1 = (bit 5-7) - type of the signal, for valid values see enum SignalType in rail_map.h
  * - p1 = (bit 8)   - convert the present signal type and variant
- * - p1 = (bit 9-11)- start cycle from this signal type
- * - p1 = (bit 12-14)-wrap around after this signal type
+ * - p1 = (bit 9-14)- cycle through which signal set?
  * - p1 = (bit 15-16)-cycle the signal direction this many times
  * - p1 = (bit 17)  - 1 = don't modify an existing signal but don't fail either, 0 = always set new signal type
  * @param p2 used for CmdBuildManySignals() to copy direction of first signal
@@ -932,17 +939,19 @@
 	SignalVariant sigvar = (ctrl_pressed ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC; // the signal variant of the new signal
 	SignalType sigtype = Extract<SignalType, 5, 3>(p1); // the signal type of the new signal
 	bool convert_signal = HasBit(p1, 8); // convert button pressed
-	SignalType cycle_start = Extract<SignalType, 9, 3>(p1);
-	SignalType cycle_stop = Extract<SignalType, 12, 3>(p1);
 	uint num_dir_cycle = GB(p1, 15, 2);
+	uint which_signals = GB(p1, 9, 6);
 
 	if (sigtype > SIGTYPE_LAST) return CMD_ERROR;
-	if (cycle_start > cycle_stop || cycle_stop > SIGTYPE_LAST) return CMD_ERROR;
-
-	/* You can only build signals on plain rail tiles, and the selected track must exist */
-	if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) ||
-			!HasTrack(tile, track)) {
-		return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
+
+	/* You can only build signals on plain rail tiles or tunnel/bridges, and the selected track must exist */
+	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+		if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return CMD_ERROR;
+		CommandCost ret = EnsureNoTrainOnTrack(GetOtherTunnelBridgeEnd(tile), track);
+		if (ret.Failed()) return ret;
+	} else if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) ||
+				!HasTrack(tile, track)) {
+			return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
 	}
 	CommandCost ret = EnsureNoTrainOnTrack(tile, track);
 	if (ret.Failed()) return ret;
@@ -951,8 +960,56 @@
 	if (p2 != 0 && (p2 & SignalOnTrack(track)) == 0) return CMD_ERROR;
 
 	ret = CheckTileOwnership(tile);
+
 	if (ret.Failed()) return ret;
 
+	CommandCost cost;
+	/* handle signals simulation on tunnel/bridgec */
+	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+		TileIndex tile_exit = GetOtherTunnelBridgeEnd(tile);
+		cost = CommandCost();
+		if (!HasWormholeSignals(tile)) { // toggle signal 0 costs
+			if (p2 != 12) cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS] * ((GetTunnelBridgeLength(tile, tile_exit) + 4) >> 2)); // minimal 1
+		}
+		if (flags & DC_EXEC) {
+			if (p2 == 0 && HasWormholeSignals(tile)){ // Toggle signal if allready signals present
+				if (IsTunnelBridgeEntrance (tile)) {
+					ClrBitTunnelBridgeSignal(tile);
+					ClrBitTunnelBridgeExit(tile_exit);
+					SetBitTunnelBridgeExit(tile);
+					SetBitTunnelBridgeSignal(tile_exit);
+				} else {
+					ClrBitTunnelBridgeSignal(tile_exit);
+					ClrBitTunnelBridgeExit(tile);
+					SetBitTunnelBridgeExit(tile_exit);
+					SetBitTunnelBridgeSignal(tile);
+				}			
+			} else{
+				/* Create  one direction tunnel/bridge if required*/
+				if (p2 == 0) {
+					SetBitTunnelBridgeSignal(tile);
+					SetBitTunnelBridgeExit(tile_exit);
+				} else if (p2 == 4 || p2 == 8) {
+					DiagDirection tbdir = GetTunnelBridgeDirection(tile);
+					/* If signal only on one side build accoringly one-way tunnel/bridge */
+					if ((p2 == 8 && (tbdir == DIAGDIR_NE || tbdir == DIAGDIR_SE)) ||
+						(p2 == 4 && (tbdir == DIAGDIR_SW || tbdir == DIAGDIR_NW))) {
+						SetBitTunnelBridgeSignal(tile);
+						SetBitTunnelBridgeExit(tile_exit);
+					} else {
+						SetBitTunnelBridgeSignal(tile_exit);
+						SetBitTunnelBridgeExit(tile);
+					}
+				}			
+			}
+			MarkTileDirtyByTile(tile);
+			MarkTileDirtyByTile(tile_exit);
+			AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_company);
+			YapfNotifyTrackLayoutChange(tile, track);
+		}
+		return cost;
+	}
+
 	{
 		/* See if this is a valid track combination for signals, (ie, no overlap) */
 		TrackBits trackbits = GetTrackBits(tile);
@@ -969,7 +1026,6 @@
 	/* you can not convert a signal if no signal is on track */
 	if (convert_signal && !HasSignalOnTrack(tile, track)) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
 
-	CommandCost cost;
 	if (!HasSignalOnTrack(tile, track)) {
 		/* build new signals */
 		cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS]);
@@ -1030,6 +1086,11 @@
 						sigtype = GetSignalType(tile, track);
 					} else {
 						/* convert the present signal to the chosen type and variant */
+						if (IsPresignalProgrammable(tile, track)) {
+							FreeSignalProgram(SignalReference(tile, track));
+						} else if(IsSpeedSignal(tile, track)) {
+							FreeSignalSpeed(SignalReference(tile, track));
+						}
 						SetSignalType(tile, track, sigtype);
 						SetSignalVariant(tile, track, sigvar);
 						if (IsPbsSignal(sigtype) && (GetPresentSignals(tile) & SignalOnTrack(track)) == SignalOnTrack(track)) {
@@ -1038,11 +1099,14 @@
 					}
 
 				} else if (ctrl_pressed) {
-					/* cycle between cycle_start and cycle_end */
-					sigtype = (SignalType)(GetSignalType(tile, track) + 1);
-
-					if (sigtype < cycle_start || sigtype > cycle_stop) sigtype = cycle_start;
-
+					/* cycle through signal types */
+					sigtype = (SignalType)(GetSignalType(tile, track));
+					if(IsProgrammableSignal(sigtype)) {
+						FreeSignalProgram(SignalReference(tile, track));
+					} else if(IsSpeedSignal(sigtype)) {
+						FreeSignalSpeed(SignalReference(tile, track));
+					}
+					sigtype = NextSignalType(sigtype, which_signals);
 					SetSignalType(tile, track, sigtype);
 					if (IsPbsSignal(sigtype) && (GetPresentSignals(tile) & SignalOnTrack(track)) == SignalOnTrack(track)) {
 						SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | KillFirstBit(SignalOnTrack(track)));
@@ -1059,6 +1123,11 @@
 			 * direction of the first signal given as parameter by CmdBuildManySignals */
 			SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | (p2 & SignalOnTrack(track)));
 			SetSignalVariant(tile, track, sigvar);
+			if(IsPresignalProgrammable(tile, track)) {
+				FreeSignalProgram(SignalReference(tile, track));
+			} else if(IsSpeedSignal(tile, track)) {
+				FreeSignalSpeed(SignalReference(tile, track));
+			}
 			SetSignalType(tile, track, sigtype);
 		}
 
@@ -1120,6 +1189,8 @@
 			return true;
 
 		case MP_TUNNELBRIDGE: {
+			if (!remove && HasWormholeSignals(tile)) return false;
+
 			TileIndex orig_tile = tile; // backup old value
 
 			if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return false;
@@ -1221,7 +1292,7 @@
 	bool had_success = false;
 	for (;;) {
 		/* only build/remove signals with the specified density */
-		if ((remove && autofill) || signal_ctr % signal_density == 0) {
+		if ((remove && autofill) || signal_ctr % signal_density == 0 || IsTileType(tile, MP_TUNNELBRIDGE)) {
 			uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3);
 			SB(p1, 3, 1, mode);
 			SB(p1, 4, 1, semaphores);
@@ -1238,7 +1309,15 @@
 			/* Be user-friendly and try placing signals as much as possible */
 			if (ret.Succeeded()) {
 				had_success = true;
-				total_cost.AddCost(ret);
+
+				if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+					if ((!autofill && GetTunnelBridgeDirection(tile) == TrackdirToExitdir(trackdir)) ||
+							(autofill && GetTunnelBridgeDirection(tile) != TrackdirToExitdir(trackdir))) {
+						total_cost.AddCost(ret);
+					}
+				} else {
+					total_cost.AddCost(ret);
+				}
 			} else {
 				/* The "No railway" error is the least important one. */
 				if (ret.GetErrorMessage() != STR_ERROR_THERE_IS_NO_RAILROAD_TRACK ||
@@ -1309,15 +1388,27 @@
 CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
 	Track track = Extract<Track, 0, 3>(p1);
-
-	if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
-		return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
+	Money cost = _price[PR_CLEAR_SIGNALS];
+
+	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+		TileIndex end = GetOtherTunnelBridgeEnd(tile);
+		if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
+		if (!HasWormholeSignals(tile)) return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
+
+		cost *= ((GetTunnelBridgeLength(tile, end) + 4) >> 2);
+
+		CommandCost ret = EnsureNoTrainOnTrack(GetOtherTunnelBridgeEnd(tile), track);
+		if (ret.Failed()) return ret;
+	} else {
+		if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
+			return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
+		}
+		if (!HasSignalOnTrack(tile, track)) {
+			return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
+		}
+		CommandCost ret = EnsureNoTrainOnTrack(tile, track);
+		if (ret.Failed()) return ret;
 	}
-	if (!HasSignalOnTrack(tile, track)) {
-		return_cmd_error(STR_ERROR_THERE_ARE_NO_SIGNALS);
-	}
-	CommandCost ret = EnsureNoTrainOnTrack(tile, track);
-	if (ret.Failed()) return ret;
 
 	/* Only water can remove signals from anyone */
 	if (_current_company != OWNER_WATER) {
@@ -1327,6 +1418,20 @@
 
 	/* Do it? */
 	if (flags & DC_EXEC) {
+
+		if (HasWormholeSignals(tile)) { // handle tunnel/bridge signals
+			TileIndex end = GetOtherTunnelBridgeEnd(tile);
+			ClrBitTunnelBridgeExit(tile);
+			ClrBitTunnelBridgeExit(end);
+			ClrBitTunnelBridgeSignal(tile);
+			ClrBitTunnelBridgeSignal(end);
+			_m[tile].m2 = 0;
+			_m[end].m2 = 0;
+			MarkTileDirtyByTile(tile);
+			MarkTileDirtyByTile(end);
+			return CommandCost(EXPENSES_CONSTRUCTION, cost);
+		}
+
 		Train *v = NULL;
 		if (HasReservedTracks(tile, TrackToTrackBits(track))) {
 			v = GetTrainForReservation(tile, track);
@@ -1343,6 +1448,8 @@
 				}
 			}
 		}
+		
+		CheckRemoveSignal(tile, track);
 		SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track));
 
 		/* removed last signal from tile? */
@@ -1359,7 +1466,7 @@
 		MarkTileDirtyByTile(tile);
 	}
 
-	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_SIGNALS]);
+	return CommandCost(EXPENSES_CONSTRUCTION, cost);
 }
 
 /**
@@ -1637,6 +1744,8 @@
 
 	switch (GetRailTileType(tile)) {
 		case RAIL_TILE_SIGNALS:
+			if (flags & DC_EXEC) CheckRemoveSignalsFromTile(tile);
+
 		case RAIL_TILE_NORMAL: {
 			Slope tileh = GetTileSlope(tile);
 			/* Is there flat water on the lower halftile that gets cleared expensively? */
@@ -1715,9 +1824,22 @@
 	if (type == SIGTYPE_NORMAL && variant == SIG_ELECTRIC) {
 		/* Normal electric signals are picked from original sprites. */
 		sprite = SPR_ORIGINAL_SIGNALS_BASE + image + condition;
+// TODO: change drawing of speed and progsigs to the "other signals" method when the sprites are added to openttd.grf.
+	} else if (type == SIGTYPE_PROG && variant == SIG_ELECTRIC) {
+		/* Speed electric signals are picked from speedsignals.gf sprites. */
+		sprite = (SPR_PROGSIGNAL_BASE + 16) + image + condition;
+	} else if (type == SIGTYPE_PROG && variant == SIG_SEMAPHORE) {
+		/* Speed semaphore signals are picked from speedsignals.gf sprites. */
+		sprite = SPR_PROGSIGNAL_BASE + image + condition;
+	} else if (type == SIGTYPE_SPEED && variant == SIG_ELECTRIC) {
+		/* Speed electric signals are picked from speedsignals.gf sprites. */
+		sprite = (SPR_SPEEDSIGNAL_BASE + 16) + image + condition;
+	} else if (type == SIGTYPE_SPEED && variant == SIG_SEMAPHORE) {
+		/* Speed semaphore signals are picked from speedsignals.gf sprites. */
+		sprite = SPR_SPEEDSIGNAL_BASE + image + condition;
 	} else {
 		/* All other signals are picked from add on sprites. */
-		sprite = SPR_SIGNALS_BASE + (type - 1) * 16 + variant * 64 + image + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0);
+		sprite = SPR_SIGNALS_BASE + (type - 1) * 16 + variant * 64 + image + condition + (IsSignalSpritePBS(type) ? 64 : 0);
 	}
 
 	AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track));
@@ -2360,6 +2482,8 @@
 	RailGroundType old_ground = GetRailGroundType(tile);
 	RailGroundType new_ground;
 
+	ReduceStuckCounter(tile);
+
 	if (old_ground == RAIL_GROUND_WATER) {
 		TileLoop_Water(tile);
 		return;
@@ -2602,14 +2726,16 @@
 			break;
 
 		case RAIL_TILE_SIGNALS: {
-			static const StringID signal_type[6][6] = {
+			static const StringID signal_type[8][8] = {
 				{
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS,
-					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SPEEDSIGNALS
 				},
 				{
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PRESIGNALS,
@@ -2617,7 +2743,9 @@
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_EXITSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_COMBOSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PBSSIGNALS,
-					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_NOENTRYSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_SPEEDSIGNALS
 				},
 				{
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_EXITSIGNALS,
@@ -2625,7 +2753,9 @@
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXITSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS,
-					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_SPEEDSIGNALS
 				},
 				{
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_COMBOSIGNALS,
@@ -2633,7 +2763,9 @@
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_COMBOSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBOSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS,
-					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_SPEEDSIGNALS
 				},
 				{
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PBSSIGNALS,
@@ -2641,7 +2773,9 @@
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PBSSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PBSSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBSSIGNALS,
-					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_SPEEDSIGNALS
 				},
 				{
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_NOENTRYSIGNALS,
@@ -2649,7 +2783,29 @@
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_NOENTRYSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_NOENTRYSIGNALS,
 					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_NOENTRYSIGNALS,
-					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRYSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRY_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRY_SPEEDSIGNALS
+				},
+				{
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRY_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PROGSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PROG_SPEEDSIGNALS
+				},
+				{
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SPEEDSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PRE_SPEEDSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_EXIT_SPEEDSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_COMBO_SPEEDSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PBS_SPEEDSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NOENTRY_SPEEDSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_PROG_SPEEDSIGNALS,
+					STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_SPEEDSIGNALS
 				}
 			};
 
diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp
--- a/src/rail_gui.cpp
+++ b/src/rail_gui.cpp
@@ -218,13 +218,27 @@
 	Track track = FindFirstTrack(trackbits);
 
 	if (_remove_button_clicked) {
+		// TODO: also check if a programmable signal is dependant on this signal ...
 		DoCommandP(tile, track, 0, CMD_REMOVE_SIGNALS | CMD_MSG(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM), CcPlaySound1E);
-	} else {
+		return;
+	}
+
+	if (_program_signal_button) {
+		if (IsPlainRailTile(tile) && HasTrack(tile, track) && HasSignalOnTrack(tile,track) && IsPresignalProgrammable(tile, track)) {
+			/* Show program gui if there is a programmable signal */
+			ShowSignalProgramWindow(SignalReference(tile, track));
+			return;
+		} else if(IsPlainRailTile(tile) && HasTrack(tile, track) && HasSignalOnTrack(tile,track) && IsSpeedSignal(tile, track)) {
+			ShowSpeedSignalWindow(SignalReference(tile, track));
+			return;
+		}
+		/* Don't display error here even though program-button is pressed and there is no programmable signal,
+		 * instead just handle it normally. That way player can keep the program-button pressed all the time
+		 * to build slightly faster. */
+	}
+
 		const Window *w = FindWindowById(WC_BUILD_SIGNAL, 0);
 
-		/* Map the setting cycle_signal_types to the lower and upper allowed signal type. */
-		static const uint cycle_bounds[] = {SIGTYPE_NORMAL | (SIGTYPE_LAST_NOPBS << 3), SIGTYPE_PBS | (SIGTYPE_LAST << 3), SIGTYPE_NORMAL | (SIGTYPE_LAST << 3)};
-
 		/* various bitstuffed elements for CmdBuildSingleSignal() */
 		uint32 p1 = track;
 
@@ -234,19 +248,18 @@
 			SB(p1, 4, 1, _cur_signal_variant);
 			SB(p1, 5, 3, _cur_signal_type);
 			SB(p1, 8, 1, _convert_signal_button);
-			SB(p1, 9, 6, cycle_bounds[_settings_client.gui.cycle_signal_types]);
+			SB(p1, 9, 7, _settings_client.gui.cycle_signal_types);
 		} else {
 			SB(p1, 3, 1, _ctrl_pressed);
 			SB(p1, 4, 1, (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
 			SB(p1, 5, 3, _default_signal_type[_settings_client.gui.default_signal_type]);
 			SB(p1, 8, 1, 0);
-			SB(p1, 9, 6, cycle_bounds[_settings_client.gui.cycle_signal_types]);
+			SB(p1, 9, 7, _settings_client.gui.cycle_signal_types);
 		}
 
 		DoCommandP(tile, p1, 0, CMD_BUILD_SIGNALS |
 				CMD_MSG((w != NULL && _convert_signal_button) ? STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE : STR_ERROR_CAN_T_BUILD_SIGNALS_HERE),
 				CcPlaySound1E);
-	}
 }
 
 /**
@@ -1113,6 +1126,7 @@
 					}
 				}
 				size->width = max(size->width, d.width + padding.width);
+
 				break;
 			}
 
@@ -1503,15 +1517,20 @@
 	BSW_SEMAPHORE_ENTRY,
 	BSW_SEMAPHORE_EXIT,
 	BSW_SEMAPHORE_COMBO,
+	BSW_SEMAPHORE_PROG,
+	BSW_SEMAPHORE_SPEED,
 	BSW_SEMAPHORE_PBS,
 	BSW_SEMAPHORE_PBS_OWAY,
 	BSW_ELECTRIC_NORM,
 	BSW_ELECTRIC_ENTRY,
 	BSW_ELECTRIC_EXIT,
 	BSW_ELECTRIC_COMBO,
+	BSW_ELECTRIC_PROG,
+	BSW_ELECTRIC_SPEED,
 	BSW_ELECTRIC_PBS,
 	BSW_ELECTRIC_PBS_OWAY,
 	BSW_CONVERT,
+	BSW_PROGRAM,
 	BSW_DRAG_SIGNALS_DENSITY,
 	BSW_DRAG_SIGNALS_DENSITY_LABEL,
 	BSW_DRAG_SIGNALS_DENSITY_DECREASE,
@@ -1576,16 +1595,35 @@
 			/* We need to do some custom sprite widget drawing for the signals. */
 			const SpriteID _signal_lookup[] = {
 				SPR_IMG_SIGNAL_SEMAPHORE_NORM,  SPR_IMG_SIGNAL_SEMAPHORE_ENTRY, SPR_IMG_SIGNAL_SEMAPHORE_EXIT,
-				SPR_IMG_SIGNAL_SEMAPHORE_COMBO, SPR_IMG_SIGNAL_SEMAPHORE_PBS,   SPR_IMG_SIGNAL_SEMAPHORE_PBS_OWAY,
+				SPR_IMG_SIGNAL_SEMAPHORE_COMBO, SPR_IMG_SIGNAL_SEMAPHORE_PROG, SPR_IMG_SIGNAL_SEMAPHORE_SPEED,
+				SPR_IMG_SIGNAL_SEMAPHORE_PBS,   SPR_IMG_SIGNAL_SEMAPHORE_PBS_OWAY,
 
 				SPR_IMG_SIGNAL_ELECTRIC_NORM,  SPR_IMG_SIGNAL_ELECTRIC_ENTRY, SPR_IMG_SIGNAL_ELECTRIC_EXIT,
-				SPR_IMG_SIGNAL_ELECTRIC_COMBO, SPR_IMG_SIGNAL_ELECTRIC_PBS,   SPR_IMG_SIGNAL_ELECTRIC_PBS_OWAY
+				SPR_IMG_SIGNAL_ELECTRIC_COMBO, SPR_IMG_SIGNAL_ELECTRIC_PROG, SPR_IMG_SIGNAL_ELECTRIC_SPEED,
+				SPR_IMG_SIGNAL_ELECTRIC_PBS,   SPR_IMG_SIGNAL_ELECTRIC_PBS_OWAY
 			};
 
 			this->DrawSignalSprite(widget, _signal_lookup[widget - BSW_SEMAPHORE_NORM]);
 		}
 	}
 
+	inline SignalType TypeForClick(uint id)
+	{
+		switch(id) {
+			case 0: return SIGTYPE_NORMAL;
+			case 1: return SIGTYPE_ENTRY;
+			case 2: return SIGTYPE_EXIT;
+			case 3: return SIGTYPE_COMBO;
+			case 4: return SIGTYPE_PROG;
+			case 5: return SIGTYPE_SPEED;
+			case 6: return SIGTYPE_PBS;
+			case 7: return SIGTYPE_PBS_ONEWAY;
+			default:
+				assert(!"Bad signal type button ID");
+				return SIGTYPE_NORMAL;
+		}
+	}
+
 	virtual void OnClick(Point pt, int widget, int click_count)
 	{
 		switch (widget) {
@@ -1593,22 +1631,33 @@
 			case BSW_SEMAPHORE_ENTRY:
 			case BSW_SEMAPHORE_EXIT:
 			case BSW_SEMAPHORE_COMBO:
+			case BSW_SEMAPHORE_PROG:
+			case BSW_SEMAPHORE_SPEED:
 			case BSW_SEMAPHORE_PBS:
 			case BSW_SEMAPHORE_PBS_OWAY:
 			case BSW_ELECTRIC_NORM:
 			case BSW_ELECTRIC_ENTRY:
 			case BSW_ELECTRIC_EXIT:
 			case BSW_ELECTRIC_COMBO:
+			case BSW_ELECTRIC_PROG:
+			case BSW_ELECTRIC_SPEED:
 			case BSW_ELECTRIC_PBS:
 			case BSW_ELECTRIC_PBS_OWAY:
-				this->RaiseWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_type);
+				this->RaiseWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_button);
 
-				_cur_signal_type = (SignalType)((uint)((widget - BSW_SEMAPHORE_NORM) % (SIGTYPE_LAST + 1)));
+				_cur_signal_button = (uint)((widget - BSW_SEMAPHORE_NORM) % (SIGTYPE_END));
+				_cur_signal_type = TypeForClick(_cur_signal_button);
 				_cur_signal_variant = widget >= BSW_ELECTRIC_NORM ? SIG_ELECTRIC : SIG_SEMAPHORE;
 				break;
 
 			case BSW_CONVERT:
 				_convert_signal_button = !_convert_signal_button;
+				if(_convert_signal_button) _program_signal_button = false;
+				break;
+
+			case BSW_PROGRAM:
+				_program_signal_button = !_program_signal_button;
+				if(_program_signal_button) _convert_signal_button = false;
 				break;
 
 			case BSW_DRAG_SIGNALS_DENSITY_DECREASE:
@@ -1639,9 +1688,10 @@
 	virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
 	{
 		if (!gui_scope) return;
-		this->LowerWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_type);
+		this->LowerWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_button);
 
 		this->SetWidgetLoweredState(BSW_CONVERT, _convert_signal_button);
+		this->SetWidgetLoweredState(BSW_PROGRAM, _program_signal_button);
 
 		this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_DECREASE, _settings_client.gui.drag_signals_density == 1);
 		this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_INCREASE, _settings_client.gui.drag_signals_density == 20);
@@ -1654,33 +1704,40 @@
 		NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
 		NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_BUILD_SIGNAL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 	EndContainer(),
-	NWidget(NWID_VERTICAL, NC_EQUALSIZE),
-		NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_NORM), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_NORM_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_ENTRY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_EXIT), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_COMBO), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_PBS), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, BSW_CONVERT), SetDataTip(SPR_IMG_SIGNAL_CONVERT, STR_BUILD_SIGNAL_CONVERT_TOOLTIP), SetFill(1, 1),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(NWID_VERTICAL, NC_EQUALSIZE),
+			NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_NORM),     SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_NORM_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_ENTRY),    SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_EXIT),     SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_COMBO),    SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_PROG),     SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PROG_TOOLTIP), EndContainer(), SetFill(1, 1),
+ 				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_SPEED),    SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_SPEED_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_PBS),      SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, BSW_CONVERT), SetDataTip(SPR_IMG_SIGNAL_CONVERT, STR_BUILD_SIGNAL_CONVERT_TOOLTIP), SetFill(1, 1),
+			EndContainer(),
+			NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_NORM),     SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_ENTRY),    SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_EXIT),     SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_COMBO),    SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_PROG),     SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PROG_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_SPEED),    SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_SPEED_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_PBS),      SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP), EndContainer(), SetFill(1, 1),
+				NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, BSW_PROGRAM), SetDataTip(SPR_IMG_SETTINGS, STR_PROGRAM_SIGNAL_TOOLTIP), SetFill(1, 1),
+			EndContainer(),
 		EndContainer(),
-		NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_NORM), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_ENTRY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_EXIT), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_COMBO), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_PBS), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_ELECTRIC_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP), EndContainer(), SetFill(1, 1),
-			NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_DRAG_SIGNALS_DENSITY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
-				NWidget(WWT_LABEL, COLOUR_DARK_GREEN, BSW_DRAG_SIGNALS_DENSITY_LABEL), SetDataTip(STR_ORANGE_INT, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
-				NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
-					NWidget(NWID_SPACER), SetFill(1, 0),
-					NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, BSW_DRAG_SIGNALS_DENSITY_DECREASE), SetMinimalSize(9, 12), SetDataTip(AWV_DECREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP),
-					NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, BSW_DRAG_SIGNALS_DENSITY_INCREASE), SetMinimalSize(9, 12), SetDataTip(AWV_INCREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP),
-					NWidget(NWID_SPACER), SetFill(1, 0),
-				EndContainer(),
-				NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
+		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_DRAG_SIGNALS_DENSITY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
+			NWidget(WWT_LABEL, COLOUR_DARK_GREEN, BSW_DRAG_SIGNALS_DENSITY_LABEL), SetDataTip(STR_ORANGE_INT, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(1, 1),
+			NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
+				NWidget(NWID_SPACER), SetFill(1, 0),
+				NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, BSW_DRAG_SIGNALS_DENSITY_DECREASE), SetMinimalSize(9, 12), SetDataTip(AWV_DECREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP),
+				NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, BSW_DRAG_SIGNALS_DENSITY_INCREASE), SetMinimalSize(9, 12), SetDataTip(AWV_INCREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP),
+				NWidget(NWID_SPACER), SetFill(1, 0),
 			EndContainer(),
+			NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
 		EndContainer(),
 	EndContainer(),
 };
@@ -1965,7 +2022,7 @@
 		Window *w = FindWindowById(WC_BUILD_SIGNAL, 0);
 		if (w != NULL) {
 			w->SetDirty();
-			w->RaiseWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_type);
+			w->RaiseWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_button);
 		}
 		_cur_signal_variant = new_variant;
 	}
@@ -1982,7 +2039,13 @@
 	SetDefaultRailGui();
 
 	_convert_signal_button = false;
-	_cur_signal_type = _default_signal_type[_settings_client.gui.default_signal_type];
+	_program_signal_button = false;
+	_cur_signal_type   = _default_signal_type[_settings_client.gui.default_signal_type];
+	_cur_signal_button =
+		_cur_signal_type == SIGTYPE_PROG ? 4 :
+		_cur_signal_type == SIGTYPE_SPEED ? 5 :
+		_cur_signal_type == SIGTYPE_PBS ? 6 :
+		_cur_signal_type == SIGTYPE_PBS_ONEWAY ? 7 : _cur_signal_type;
 	ResetSignalVariant();
 }
 
diff --git a/src/rail_gui.h b/src/rail_gui.h
--- a/src/rail_gui.h
+++ b/src/rail_gui.h
@@ -15,6 +15,8 @@
 #include "rail_type.h"
 #include "widgets/dropdown_type.h"
 
+extern RailType _cur_railtype;
+
 struct Window *ShowBuildRailToolbar(RailType railtype);
 void ReinitGuiAfterToggleElrail(bool disable);
 bool ResetSignalVariant(int32 = 0);
diff --git a/src/rail_map.h b/src/rail_map.h
--- a/src/rail_map.h
+++ b/src/rail_map.h
@@ -128,7 +128,6 @@
 	SB(_m[t].m3, 0, 4, r);
 }
 
-
 /**
  * Gets the track bits of the given tile
  * @param tile the tile to get the track bits from
@@ -185,7 +184,6 @@
 	return DiagDirToDiagTrack(GetRailDepotDirection(t));
 }
 
-
 /**
  * Returns the reserved track bits of the tile
  * @pre IsPlainRailTile(t)
@@ -285,12 +283,6 @@
 	return HasDepotReservation(t) ? TrackToTrackBits(GetRailDepotTrack(t)) : TRACK_BIT_NONE;
 }
 
-
-static inline bool IsPbsSignal(SignalType s)
-{
-	return s == SIGTYPE_PBS || s == SIGTYPE_PBS_ONEWAY;
-}
-
 static inline SignalType GetSignalType(TileIndex t, Track track)
 {
 	assert(GetRailTileType(t) == RAIL_TILE_SIGNALS);
@@ -308,18 +300,34 @@
 
 static inline bool IsPresignalEntry(TileIndex t, Track track)
 {
-	return GetSignalType(t, track) == SIGTYPE_ENTRY || GetSignalType(t, track) == SIGTYPE_COMBO;
+	return IsEntrySignal(GetSignalType(t, track));
 }
 
 static inline bool IsPresignalExit(TileIndex t, Track track)
 {
-	return GetSignalType(t, track) == SIGTYPE_EXIT || GetSignalType(t, track) == SIGTYPE_COMBO;
+	return IsExitSignal(GetSignalType(t, track));
+}
+
+static inline bool IsPresignalCombo(TileIndex t, Track track)
+{
+	return IsComboSignal(GetSignalType(t, track));
+}
+
+static inline bool IsPresignalProgrammable(TileIndex t, Track track)
+{
+	return IsProgrammableSignal(GetSignalType(t, track));
+}
+
+static inline bool IsSpeedSignal(TileIndex t, Track track)
+{
+	return IsSpeedSignal(GetSignalType(t, track));
 }
 
 /** One-way signals can't be passed the 'wrong' way. */
 static inline bool IsOnewaySignal(TileIndex t, Track track)
 {
-	return GetSignalType(t, track) != SIGTYPE_PBS;
+	return GetSignalType(t, track) != SIGTYPE_PBS &&
+		GetSignalType(t, track) != SIGTYPE_SPEED;
 }
 
 static inline void CycleSignalSide(TileIndex t, Track track)
@@ -353,6 +361,8 @@
 enum SignalState {
 	SIGNAL_STATE_RED   = 0, ///< The signal is red
 	SIGNAL_STATE_GREEN = 1, ///< The signal is green
+
+	SIGNAL_STATE_MAX = SIGNAL_STATE_GREEN
 };
 
 /**
@@ -486,10 +496,9 @@
 static inline bool HasOnewaySignalBlockingTrackdir(TileIndex tile, Trackdir td)
 {
 	return IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)) &&
-			!HasSignalOnTrackdir(tile, td) && IsOnewaySignal(tile, TrackdirToTrack(td));
+			!HasSignalOnTrackdir(tile, td) && IsOnewaySignal(tile, TrackdirToTrack(td)) && !IsSpeedSignal(tile, TrackdirToTrack(td));
 }
 
-
 RailType GetTileRailType(TileIndex tile);
 
 /** The ground 'under' the rail */
@@ -526,7 +535,6 @@
 	return GetRailGroundType(t) == RAIL_GROUND_ICE_DESERT;
 }
 
-
 static inline void MakeRailNormal(TileIndex t, Owner o, TrackBits b, RailType r)
 {
 	SetTileType(t, MP_RAILWAY);
@@ -539,7 +547,6 @@
 	_me[t].m7 = 0;
 }
 
-
 static inline void MakeRailDepot(TileIndex t, Owner o, DepotID did, DiagDirection d, RailType r)
 {
 	SetTileType(t, MP_RAILWAY);
@@ -552,4 +559,24 @@
 	_me[t].m7 = 0;
 }
 
+static inline void IncreaseStuckCounter(TileIndex t)
+{
+	if (!IsTileType(t, MP_RAILWAY)) return;
+	if (_me[t].m7 == 255) return;
+	_me[t].m7++;
+}
+
+static inline void ReduceStuckCounter(TileIndex t)
+{
+	if (!IsTileType(t, MP_RAILWAY)) return;
+	_me[t].m7 -= _me[t].m7/4;
+}
+
+static inline byte GetStuckCounter(TileIndex t)
+{
+	if (!IsTileType(t, MP_RAILWAY)) return 0;
+	return _me[t].m7;
+
+}
+
 #endif /* RAIL_MAP_H */
diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -35,6 +35,7 @@
 #include "newgrf_railtype.h"
 #include "date_func.h"
 #include "genworld.h"
+#include "trafficlight_func.h"
 
 #include "table/strings.h"
 
@@ -173,9 +174,10 @@
  * @param pieces roadbits to remove
  * @param rt roadtype to remove
  * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
+ * @param trafficlights_check Should we check if there is a traffic light before removing road bits?
  * @param town_check should we check if the town allows removal?
  */
-static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check = true)
+static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool crossing_check, bool trafficlights_check, bool town_check = true)
 {
 	RoadTypes rts = GetRoadTypes(tile);
 	/* The tile doesn't have the given road type */
@@ -282,6 +284,11 @@
 			/* Now set present what it will be after the remove */
 			present ^= pieces;
 
+			/* Check if traffic lights are present and if removing them would cause the tile to have less than three roadbits (of any kind!). */
+			if (trafficlights_check && HasTrafficLights(tile) && (CountBits(present | GetOtherRoadBits(tile, rt)) < 3)) {
+				return_cmd_error(STR_ERROR_MUST_REMOVE_TRAFFIC_LIGHTS_FIRST);
+			}
+
 			/* Check for invalid RoadBit combinations on slopes */
 			if (tileh != SLOPE_FLAT && present != ROAD_NONE &&
 					(present & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) == present) {
@@ -863,7 +870,7 @@
 
 		/* try to remove the halves. */
 		if (bits != 0) {
-			CommandCost ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true);
+			CommandCost ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true, true);
 			if (ret.Succeeded()) {
 				if (flags & DC_EXEC) {
 					money -= ret.GetCost();
@@ -871,7 +878,7 @@
 						_additional_cash_required = DoCommand(start_tile, end_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
 						return cost;
 					}
-					RemoveRoad(tile, flags, bits, rt, true, false);
+					RemoveRoad(tile, flags, bits, rt, true, true, false);
 				}
 				cost.AddCost(ret);
 				had_success = true;
@@ -963,9 +970,18 @@
 			/* Clear the road if only one piece is on the tile OR we are not using the DC_AUTO flag */
 			if ((HasExactlyOneBit(b) && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || !(flags & DC_AUTO)) {
 				CommandCost ret(EXPENSES_CONSTRUCTION);
+
+				/* Remove traffic light if necessary. */
+				if (HasTrafficLights(tile)) {
+					CommandCost tl_ret = CmdRemoveTrafficLights(tile, flags, 0, 0, 0);
+					if (tl_ret.Failed()) return tl_ret;
+					ret.AddCost(tl_ret);
+				}
+
+				/* Remove road bits. */
 				RoadType rt;
 				FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
-					CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true);
+					CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true, false);
 					if (tmp_ret.Failed()) return tmp_ret;
 					ret.AddCost(tmp_ret);
 				}
@@ -985,7 +1001,7 @@
 			RoadType rt = ROADTYPE_TRAM;
 			do {
 				if (HasBit(rts, rt)) {
-					CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false);
+					CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false, false);
 					if (tmp_ret.Failed()) return tmp_ret;
 					ret.AddCost(tmp_ret);
 				}
@@ -1174,6 +1190,8 @@
 		}
 	}
 
+	if (_settings_game.construction.traffic_lights && HasTrafficLights(ti->tile) && _cur_dpi->zoom <= ZOOM_LVL_DETAIL) DrawTrafficLights(ti);
+
 	if (HasRoadWorks(ti->tile)) {
 		/* Road works */
 		DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
@@ -1362,6 +1380,19 @@
 	}
 }
 
+/**
+ * Animates the traffic lights on a tile.
+ * @param tile This tile.
+ * @pre The setting must be anabled.
+ * @pre The tile must have trafficlights.
+ */
+static void AnimateTile_Road(TileIndex tile)
+{
+	if (_settings_game.construction.traffic_lights && HasTrafficLights(tile)) {
+		if (_tick_counter % 16 == 0) MarkTileDirtyByTile(tile);
+	}
+}
+
 static const Roadside _town_road_types[][2] = {
 	{ ROADSIDE_GRASS,         ROADSIDE_GRASS },
 	{ ROADSIDE_PAVED,         ROADSIDE_PAVED },
@@ -1446,20 +1477,29 @@
 			SetRoadside(tile, cur_rs);
 			MarkTileDirtyByTile(tile);
 		}
-	} else if (IncreaseRoadWorksCounter(tile)) {
-		TerminateRoadWorks(tile);
+	} else {
+		/* In the first half of roadworks, generate traffic lights with a certain chance. */
+		if (_settings_game.construction.traffic_lights && _settings_game.construction.towns_build_traffic_lights &&
+				(GetRoadWorksCounter(tile) < 8) && (CountBits(GetRoadBits(tile, ROADTYPE_ROAD)) >= 3) &&
+				!HasTrafficLights(tile) && Chance16(1, 20)) {
+			CmdBuildTrafficLights(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, 0, 0, 0);
+			MarkTileDirtyByTile(tile);
+		}
+		if (IncreaseRoadWorksCounter(tile)) {
+			TerminateRoadWorks(tile);
 
-		if (_settings_game.economy.mod_road_rebuild) {
-			/* Generate a nicer town surface */
-			const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
-			const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
+			if (_settings_game.economy.mod_road_rebuild) {
+				/* Generate a nicer town surface. */
+				const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
+				const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
 
-			if (old_rb != new_rb) {
-				RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), ROADTYPE_ROAD, true);
+				if (old_rb != new_rb) {
+					RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), ROADTYPE_ROAD, true, true);
+				}
 			}
+
+			MarkTileDirtyByTile(tile);
 		}
-
-		MarkTileDirtyByTile(tile);
 	}
 }
 
@@ -1494,7 +1534,7 @@
 static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
 {
 	TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
-	TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
+	TrackdirBits red_signals = TRACKDIR_BIT_NONE; // Crossing barred or red traffic light.
 	switch (mode) {
 		case TRANSPORT_RAIL:
 			if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile));
@@ -1513,6 +1553,8 @@
 
 					uint multiplier = drd_to_multiplier[rt == ROADTYPE_TRAM ? DRD_NONE : GetDisallowedRoadDirections(tile)];
 					if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits] * multiplier);
+					if (_settings_game.construction.traffic_lights && HasTrafficLights(tile))
+							red_signals = trackdirbits & GetTrafficLightDisallowedDirections(tile);
 					break;
 				}
 
@@ -1582,7 +1624,11 @@
 
 		default: {
 			RoadTypes rts = GetRoadTypes(tile);
-			td->str = (HasBit(rts, ROADTYPE_ROAD) ? _road_tile_strings[GetRoadside(tile)] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
+			if (HasTrafficLights(tile)) {
+				td->str = STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_TRAFFIC_LIGHTS;
+			} else {
+				td->str = (HasBit(rts, ROADTYPE_ROAD) ? _road_tile_strings[GetRoadside(tile)] : STR_LAI_ROAD_DESCRIPTION_TRAMWAY);
+			}
 			if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
 			if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
 			break;
diff --git a/src/road_cmd.h b/src/road_cmd.h
--- a/src/road_cmd.h
+++ b/src/road_cmd.h
@@ -14,8 +14,11 @@
 
 #include "direction_type.h"
 #include "road_type.h"
+#include "tile_cmd.h"
+#include "gfx_type.h"
 
 void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt);
 void UpdateNearestTownForRoadTiles(bool invalidate);
+void DrawRoadDetail(SpriteID img, TileInfo *ti, int dx, int dy, int h);
 
 #endif /* ROAD_CMD_H */
diff --git a/src/road_gui.cpp b/src/road_gui.cpp
--- a/src/road_gui.cpp
+++ b/src/road_gui.cpp
@@ -65,6 +65,23 @@
 }
 
 /**
+ * Place trafficlights on a tile or returns an error.
+ * @param tile This tile.
+ */
+static void PlaceRoad_TrafficLights(TileIndex tile, Window *w)
+{
+	if (_remove_button_clicked) {
+		DoCommandP(tile, 0, 0, CMD_REMOVE_TRAFFICLIGHTS | CMD_MSG(STR_ERROR_CAN_T_REMOVE_TRAFFIC_LIGHTS_FROM), CcPlaySound1D);
+	} else {
+		if (!_settings_game.construction.traffic_lights) {
+			DoCommandP(tile, 0, 0, CMD_BUILD_TRAFFICLIGHTS | CMD_MSG(STR_ERROR_BUILDING_TRAFFIC_LIGHTS_DISABLED), CcPlaySound1D);
+		} else{
+			DoCommandP(tile, 0, 0, CMD_BUILD_TRAFFICLIGHTS | CMD_MSG(STR_ERROR_CAN_T_PLACE_TRAFFIC_LIGHTS), CcPlaySound1D);
+		}
+	}
+}
+
+/**
  * Callback to start placing a bridge.
  * @param tile Start tile of the bridge.
  */
@@ -278,6 +295,7 @@
 	RTW_BUS_STATION,
 	RTW_TRUCK_STATION,
 	RTW_ONE_WAY,
+	RTW_TRAFFIC_LIGHT,
 	RTW_BUILD_BRIDGE,
 	RTW_BUILD_TUNNEL,
 	RTW_REMOVE,
@@ -315,6 +333,12 @@
 		}
 	}
 
+	/* Allow ctrl also for traffic lights. */
+	if (w->IsWidgetLowered(RTW_TRAFFIC_LIGHT)) {
+		ToggleRoadButton_Remove(w);
+		return true;
+	}
+
 	return false;
 }
 
@@ -330,6 +354,11 @@
 				RTW_ONE_WAY,
 				WIDGET_LIST_END);
 
+		this->SetWidgetsDisabledState(!_settings_game.construction.traffic_lights,
+				RTW_TRAFFIC_LIGHT,
+				WIDGET_LIST_END);
+		if (!_settings_game.construction.traffic_lights && this->IsWidgetLowered(RTW_TRAFFIC_LIGHT)) ResetObjectToPlace();
+
 		this->OnInvalidateData();
 		this->last_started_action = WIDGET_LIST_END;
 
@@ -379,6 +408,7 @@
 
 			case RTW_BUS_STATION:
 			case RTW_TRUCK_STATION:
+			case RTW_TRAFFIC_LIGHT:
 				this->DisableWidget(RTW_ONE_WAY);
 				this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget));
 				break;
@@ -463,6 +493,11 @@
 				SetSelectionRed(false);
 				break;
 
+			case RTW_TRAFFIC_LIGHT:
+				HandlePlacePushButton(this, RTW_TRAFFIC_LIGHT, SPR_CURSOR_TRAFFIC_LIGHT, HT_RECT);
+				this->last_started_action = widget;
+				break;
+
 			case RTW_BUILD_BRIDGE:
 				HandlePlacePushButton(this, RTW_BUILD_BRIDGE, SPR_CURSOR_BRIDGE, HT_RECT);
 				this->last_started_action = widget;
@@ -537,6 +572,10 @@
 				PlaceRoad_TruckStation(tile);
 				break;
 
+			case RTW_TRAFFIC_LIGHT:
+				PlaceRoad_TrafficLights(tile, this);
+				break;
+
 			case RTW_BUILD_BRIDGE:
 				PlaceRoad_Bridge(tile, this);
 				break;
@@ -718,6 +757,8 @@
 		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ONE_WAY),
 						SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_ONE_WAY, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_TRAFFIC_LIGHT),
+						SetFill(false, true), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAFFIC_LIGHT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAFFIC_LIGHT),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_BRIDGE),
 						SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_TUNNEL),
@@ -757,6 +798,8 @@
 						SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRUCK_BAY, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION),
 		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
 		NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, RTW_ONE_WAY), SetMinimalSize(0, 0),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_TRAFFIC_LIGHT),
+						SetFill(false, true), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAFFIC_LIGHT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAFFIC_LIGHT),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_BRIDGE),
 						SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_TUNNEL),
@@ -817,6 +860,8 @@
 		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ONE_WAY),
 						SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_ONE_WAY, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_TRAFFIC_LIGHT),
+						SetFill(false, true), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAFFIC_LIGHT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAFFIC_LIGHT),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_BRIDGE),
 						SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_TUNNEL),
diff --git a/src/road_map.h b/src/road_map.h
--- a/src/road_map.h
+++ b/src/road_map.h
@@ -251,6 +251,29 @@
 	return HasTileRoadType(t, ROADTYPE_ROAD) && IsRoadOwner(t, ROADTYPE_ROAD, OWNER_TOWN);
 }
 
+static inline void MakeTrafficLights(TileIndex t)
+{
+	assert(IsTileType(t, MP_ROAD));
+	assert(GetRoadTileType(t) == ROAD_TILE_NORMAL);
+	SetBit(_me[t].m7, 4);
+}
+
+static inline void ClearTrafficLights(TileIndex t)
+{
+	assert(IsTileType(t, MP_ROAD));
+	assert(GetRoadTileType(t) == ROAD_TILE_NORMAL);
+	ClrBit(_me[t].m7, 4);
+}
+
+/**
+ * Check if a tile has traffic lights returns true if tile has traffic lights.
+ * @param t The tile to check.
+ */
+static inline bool HasTrafficLights(TileIndex t)
+{
+	return (IsTileType(t, MP_ROAD) && (GetRoadTileType(t) == ROAD_TILE_NORMAL) && HasBit(_me[t].m7, 4));
+}
+
 /** Which directions are disallowed ? */
 enum DisallowedRoadDirections {
 	DRD_NONE,       ///< None of the directions are disallowed
@@ -496,6 +519,11 @@
 	return GB(_me[t].m7, 0, 4) == 15;
 }
 
+static inline byte GetRoadWorksCounter(TileIndex t)
+{
+	return GB(_m[t].m3, 0, 4);
+}
+
 /**
  * Start road works on a tile.
  * @param t The tile to start the work on.
diff --git a/src/roadveh.h b/src/roadveh.h
--- a/src/roadveh.h
+++ b/src/roadveh.h
@@ -163,6 +163,8 @@
 		if (!this->IsArticulatedPart()) {
 			/* Road vehicle weight is in units of 1/4 t. */
 			weight += GetVehicleProperty(this, PROP_ROADVEH_WEIGHT, RoadVehInfo(this->engine_type)->weight) / 4;
+			// DIRTY HACK
+			if (!weight) weight = 1; // At least 1 for realistic accelerate.
 		}
 
 		return weight;
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -237,6 +237,19 @@
  */
 CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
 {
+	if (!IsEngineBuildable(e->index, VEH_ROAD, _current_company)) return_cmd_error(STR_ERROR_ROAD_VEHICLE_NOT_AVAILABLE);
+
+	/* Engines without valid cargo should not be available */
+	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
+
+	CommandCost cost(EXPENSES_NEW_VEHICLES, e->GetCost());
+	if (flags & DC_QUERY_COST) return cost;
+
+	/* The ai_new queries the vehicle cost before building the route,
+	 * so we must check against cheaters no sooner than now. --pasky */
+	if (!IsRoadDepotTile(tile)) return CMD_ERROR;
+	if (!IsInfraUsageAllowed(VEH_ROAD, _current_company, GetTileOwner(tile))) return CMD_ERROR;
+
 	if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
 
 	if (flags & DC_EXEC) {
@@ -262,11 +275,14 @@
 		v->cargo_cap = rvi->capacity;
 
 		v->last_station_visited = INVALID_STATION;
+		v->last_loading_station = INVALID_STATION;
+
 		v->engine_type = e->index;
 		v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
 
 		v->reliability = e->reliability;
 		v->reliability_spd_dec = e->reliability_spd_dec;
+		v->breakdown_chance = 128;
 		v->max_age = e->GetLifeLengthInDays();
 		_new_vehicle_id = v->index;
 
@@ -356,12 +372,11 @@
 	RoadVehicle *v = RoadVehicle::GetIfValid(p1);
 	if (v == NULL) return CMD_ERROR;
 
-	CommandCost ret = CheckOwnership(v->owner);
+	CommandCost ret = CheckVehicleControlAllowed(v);
 	if (ret.Failed()) return ret;
 
 	if ((v->vehstatus & VS_STOPPED) ||
 			(v->vehstatus & VS_CRASHED) ||
-			v->breakdown_ctr != 0 ||
 			v->overtaking != 0 ||
 			v->state == RVSB_WORMHOLE ||
 			v->IsInDepot() ||
@@ -786,6 +801,9 @@
 	/* For now, articulated road vehicles can't overtake anything. */
 	if (v->HasArticulatedPart()) return;
 
+	/* Don't overtake if the vehicle is broken or about to break down. */
+	if (v->breakdown_ctr != 0) return;
+
 	/* Vehicles are not driving in same direction || direction is not a diagonal direction */
 	if (v->direction != u->direction || !(v->direction & 1)) return;
 
@@ -812,7 +830,7 @@
 	v->overtaking = RVSB_DRIVE_SIDE;
 }
 
-static void RoadZPosAffectSpeed(RoadVehicle *v, byte old_z)
+static void RoadZPosAffectSpeed(RoadVehicle *v, int32 old_z)
 {
 	if (old_z == v->z_pos || _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) return;
 
@@ -854,14 +872,14 @@
 	TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
 
 	if (IsTileType(tile, MP_ROAD)) {
-		if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
+		if (IsRoadDepot(tile) && (!IsInfraTileUsageAllowed(VEH_ROAD, v->owner, tile) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
 			/* Road depot owned by another company or with the wrong orientation */
 			trackdirs = TRACKDIR_BIT_NONE;
 		}
 	} else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
 		/* Standard road stop (drive-through stops are treated as normal road) */
 
-		if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
+		if (!IsInfraTileUsageAllowed(VEH_ROAD, v->owner, tile) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
 			/* different station owner or wrong orientation or the vehicle has articulated parts */
 			trackdirs = TRACKDIR_BIT_NONE;
 		} else {
@@ -1122,7 +1140,7 @@
 
 		v->x_pos = gp.x;
 		v->y_pos = gp.y;
-		VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
+		VehicleMove(v, v->IsDrawn());
 		return true;
 	}
 
@@ -1369,7 +1387,7 @@
 			/* In case an RV is stopped in a road stop, why not try to load? */
 			if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
 					v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
-					v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
+					IsInfraTileUsageAllowed(VEH_ROAD, v->owner, v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
 					GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
 				Station *st = Station::GetByTile(v->tile);
 				v->last_station_visited = st->index;
@@ -1403,7 +1421,7 @@
 			_road_stop_stop_frame[v->state - RVSB_IN_ROAD_STOP + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)] == v->frame) ||
 			(IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
 			v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
-			v->owner == GetTileOwner(v->tile) &&
+			IsInfraTileUsageAllowed(VEH_ROAD, v->owner, v->tile) &&
 			GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
 			v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
 
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -482,6 +482,30 @@
  */
 bool AfterLoadGame()
 {
+	/* Put this at the very beginning, since the subsequent code in
+	 * AfterLoadGame sometimes uses heightlevel information.
+	 * So that code might fail if we load a savegame without extended
+	 * heightlevel data, but allow_more_heightlevels is still true
+	 * because it was not yet overwritten since the previous game.
+	 *
+	 * This especially applies when exiting a game and switching
+	 * to the intro game. */
+	if (IsSavegameVersionBefore(MORE_HEIGHTLEVEL_SAVEGAME_VERSION)) {
+		/* Maybe it is still filled from the previous game. If the currently loaded
+		 * game was saved with an OpenTTD version where the allow more heightlevels
+		 * patch was not yet introduced, we know for sure that it was NOT filled
+		 * during SlLoadChunks (because no MAPH chunk can exist in such a savegame). */
+		free(_map_heightdata);
+		_map_heightdata = NULL;
+
+		/* Also, the default for such a game is that this patch is turned off.
+		 * However, the player may turn it on using the menu afterwards. */
+		_settings_game.construction.allow_more_heightlevels = false;
+	}
+
+	/* Assure that configuration setting is consistent to the data. */
+	assert(AllowMoreHeightlevels() == (_map_heightdata != NULL));
+
 	SetSignalHandlers();
 
 	TileIndex map_size = MapSize();
@@ -628,7 +652,7 @@
 	}
 
 	/* The value of _date_fract got divided, so make sure that old games are converted correctly. */
-	if (IsSavegameVersionBefore(11, 1) || (IsSavegameVersionBefore(147) && _date_fract > DAY_TICKS)) _date_fract /= 885;
+	if (IsSavegameVersionBefore(11, 1) || (IsSavegameVersionBefore(KEEP_COMPATIBLE_1_SV) && _date_fract > DAY_TICKS)) _date_fract /= 885;
 
 	/* Update current year
 	 * must be done before loading sprites as some newgrfs check it */
@@ -868,7 +892,17 @@
 	 *  before that. */
 	if (IsSavegameVersionBefore(9)) {
 		Town *t;
-		FOR_ALL_TOWNS(t) UpdateTownMaxPass(t);
+		FOR_ALL_TOWNS(t) {
+			UpdateTownGenCargo(t);
+		}
+	}
+
+	/* From now on we have a demand for goods from towns. */
+	if (IsSavegameVersionBefore(TOWN_GROWTH_SV)) {
+		Town *t;
+		FOR_ALL_TOWNS(t) {
+			UpdateTownDemands(t);
+		}
 	}
 
 	/* From version 16.0, we included autorenew on engines, which are now saved, but
@@ -1084,6 +1118,7 @@
 		}
 
 		FOR_ALL_VEHICLES(v) {
+			int z = GetSlopeZ(v->x_pos, v->y_pos);
 			if (!v->IsGroundVehicle()) continue;
 			if (IsBridgeTile(v->tile)) {
 				DiagDirection dir = GetTunnelBridgeDirection(v->tile);
@@ -1912,7 +1947,7 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(147) && Object::GetNumItems() == 0) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_1_SV) && Object::GetNumItems() == 0) {
 		/* Make real objects for object tiles. */
 		for (TileIndex t = 0; t < map_size; t++) {
 			if (!IsTileType(t, MP_OBJECT)) continue;
@@ -2302,13 +2337,13 @@
 				UpdateAircraftCache(v);
 				AircraftNextAirportPos_and_Order(v);
 				/* get aircraft back on running altitude */
-				if ((v->vehstatus & VS_CRASHED) == 0) SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlyingAltitude(v));
+				if ((v->vehstatus & VS_CRASHED) == 0) SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftMaxAltitude(v->x_pos, v->y_pos, 0));
 			}
 		}
 	}
 
 	/* Move the animation frame to the same location (m7) for all objects. */
-	if (IsSavegameVersionBefore(147)) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_1_SV)) {
 		for (TileIndex t = 0; t < map_size; t++) {
 			switch (GetTileType(t)) {
 				case MP_HOUSE:
@@ -2340,7 +2375,7 @@
 	}
 
 	/* Add (random) colour to all objects. */
-	if (IsSavegameVersionBefore(148)) {
+	if (IsSavegameVersionBefore(148) && (!IsSavegameVersionBefore(MORE_HEIGHTLEVEL_SAVEGAME_VERSION))) {
 		Object *o;
 		FOR_ALL_OBJECTS(o) {
 			Owner owner = GetTileOwner(o->location.tile);
@@ -2348,7 +2383,7 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(149)) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_3_SV)) {
 		for (TileIndex t = 0; t < map_size; t++) {
 			if (!IsTileType(t, MP_STATION)) continue;
 			if (!IsBuoy(t) && !IsOilRig(t) && !(IsDock(t) && GetTileSlope(t) == SLOPE_FLAT)) {
@@ -2370,7 +2405,7 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(152)) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_10_SV)) {
 		_industry_builder.Reset(); // Initialize industry build data.
 
 		/* The moment vehicles go from hidden to visible changed. This means
@@ -2439,7 +2474,7 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(153)) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_11_SV)) {
 		RoadVehicle *rv;
 		FOR_ALL_ROADVEHICLES(rv) {
 			if (rv->state == RVSB_IN_DEPOT || rv->state == RVSB_WORMHOLE) continue;
@@ -2454,7 +2489,27 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(156)) {
+	if (IsSavegameVersionBefore(DAYLENGHT_SL)) {
+		/* Make sure the cheat to not devide income by daylengh factor is off.
+		 * When cheats were used in an older savegame the code may get confused and enable it.*/
+		_cheats.daylength_income.value = false;
+	}
+
+	if (IsSavegameVersionBefore(IS_SL)) {
+		Company *c;
+		FOR_ALL_COMPANIES(c) {
+			/* yearly_expenses has 3*15 entries now, saveload code gave us 3*13.
+			 * Move the old data to the right place in the new array and clear the new data.
+			 * The move has to be done in reverse order (first 2, then 1). */
+			MemMoveT(&c->yearly_expenses[2][0], &c->yearly_expenses[1][11], 13);
+			MemMoveT(&c->yearly_expenses[1][0], &c->yearly_expenses[0][13], 13);
+			/* Clear the old location of just-moved data, so sharing income/expenses is set to 0 */
+			MemSetT(&c->yearly_expenses[0][13], 0, 2);
+			MemSetT(&c->yearly_expenses[1][13], 0, 2);
+		}
+	}
+
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_17_SV)) {
 		/* The train's pathfinder lost flag got moved. */
 		Train *t;
 		FOR_ALL_TRAINS(t) {
@@ -2472,7 +2527,7 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(158)) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_16_SV)) {
 		Vehicle *v;
 		FOR_ALL_VEHICLES(v) {
 			switch (v->type) {
@@ -2569,7 +2624,7 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(159)) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_17_SV)) {
 		/* If the savegame is old (before version 100), then the value of 255
 		 * for these settings did not mean "disabled". As such everything
 		 * before then did reverse.
@@ -2584,7 +2639,7 @@
 		}
 	}
 
-	if (IsSavegameVersionBefore(160)) {
+	if (IsSavegameVersionBefore(KEEP_COMPATIBLE_18_SV)) {
 		/* Setting difficulty industry_density other than zero get bumped to +1
 		 * since a new option (minimal at position 1) has been added */
 		if (_settings_game.difficulty.industry_density > 0) {
@@ -2672,6 +2727,48 @@
 	 * which is done by StartupEngines(). */
 	if (gcf_res != GLC_ALL_GOOD) StartupEngines();
 
+	/* Set some breakdown-related variables to the correct values. */
+	if (IsSavegameVersionBefore(SL_IB)) {
+		Vehicle *v;
+		FOR_ALL_VEHICLES(v) {
+			switch(v->type) {
+				case VEH_TRAIN: {
+					if (Train::From(v)->IsFrontEngine()) {
+						if (v->breakdown_ctr == 1) SetBit(Train::From(v)->flags, VRF_BREAKDOWN_STOPPED);
+					} else if (Train::From(v)->IsEngine() || Train::From(v)->IsMultiheaded()) {
+						/* Non-front engines could have a reliability of 0.
+						 * Set it to the reliability of the front engine or the maximum, whichever is lower. */
+						const Engine *e = Engine::Get(v->engine_type);
+						v->reliability_spd_dec = e->reliability_spd_dec;
+						v->reliability = min(v->First()->reliability, e->reliability);
+					}
+				}
+				case VEH_ROAD:
+					v->breakdown_chance = 128;
+					break;
+				case VEH_SHIP:
+					v->breakdown_chance = 64;
+					break;
+				case VEH_AIRCRAFT:
+					v->breakdown_chance = Clamp(64 + (AircraftVehInfo(v->engine_type)->max_speed >> 3), 0, 255);
+					v->breakdown_severity = 40;
+					break;
+				default: break;
+			}
+		}
+	}
+
+	if (IsSavegameVersionBefore(TL_SV)) {
+		/* Savegames before this version can not have trafficlights already.
+		 * Sometimes they are added randomly when loading old savegames.
+		 * Unfortunately also in the wrong places -> not on crossings.
+		 *
+		 * Iterate over the whole map and remove any trafficlights found. */
+		for (TileIndex tile = 0; tile < MapSize(); tile++) {
+			if (HasTrafficLights(tile)) ClearTrafficLights(tile);
+		}
+	}
+
 	/* Road stops is 'only' updating some caches */
 	AfterLoadRoadStops();
 	AfterLoadLabelMaps();
@@ -2681,6 +2778,8 @@
 	InitializeWindowsAndCaches();
 	/* Restore the signals */
 	ResetSignalHandlers();
+
+	AfterLoadLinkGraphs();
 	return true;
 }
 
diff --git a/src/saveload/cargopacket_sl.cpp b/src/saveload/cargopacket_sl.cpp
--- a/src/saveload/cargopacket_sl.cpp
+++ b/src/saveload/cargopacket_sl.cpp
@@ -29,7 +29,7 @@
 		 * to the current tile of the vehicle to prevent excessive profits
 		 */
 		FOR_ALL_VEHICLES(v) {
-			const VehicleCargoList::List *packets = v->cargo.Packets();
+			const CargoPacketList *packets = v->cargo.Packets();
 			for (VehicleCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
 				CargoPacket *cp = *it;
 				cp->source_xy = Station::IsValidID(cp->source) ? Station::Get(cp->source)->xy : v->tile;
@@ -47,7 +47,7 @@
 			for (CargoID c = 0; c < NUM_CARGO; c++) {
 				GoodsEntry *ge = &st->goods[c];
 
-				const StationCargoList::List *packets = ge->cargo.Packets();
+				const StationCargoPacketMap *packets = ge->cargo.Packets();
 				for (StationCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
 					CargoPacket *cp = *it;
 					cp->source_xy = Station::IsValidID(cp->source) ? Station::Get(cp->source)->xy : st->xy;
diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp
--- a/src/saveload/company_sl.cpp
+++ b/src/saveload/company_sl.cpp
@@ -134,14 +134,17 @@
 
 	/* yearly expenses was changed to 64-bit in savegame version 2. */
 	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_FILE_I32 | SLE_VAR_I64, 3 * 13, 0, 1),
-	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_INT64, 3 * 13,                  2, SL_MAX_VERSION),
+	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_INT64, 3 * 13,                  2, IS_SL - 1),
+	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_INT64, 3 * 15,              IS_SL, SL_MAX_VERSION),
 
 	SLE_CONDVAR(CompanyProperties, is_ai,                 SLE_BOOL,                    2, SL_MAX_VERSION),
 	SLE_CONDNULL(1, 107, 111), ///< is_noai
 	SLE_CONDNULL(1, 4, 99),
 
-	SLE_CONDVAR(CompanyProperties, terraform_limit,       SLE_UINT32,                156, SL_MAX_VERSION),
-	SLE_CONDVAR(CompanyProperties, clear_limit,           SLE_UINT32,                156, SL_MAX_VERSION),
+	SLE_CONDVAR(CompanyProperties, terraform_limit,       SLE_UINT32,                156, BEFORE_ADDING_PATCHES_SL),
+	SLE_CONDVAR(CompanyProperties, terraform_limit,       SLE_UINT32,                KEEP_COMPATIBLE_14_SV, SL_MAX_VERSION),
+	SLE_CONDVAR(CompanyProperties, clear_limit,           SLE_UINT32,                156, BEFORE_ADDING_PATCHES_SL),
+	SLE_CONDVAR(CompanyProperties, clear_limit,           SLE_UINT32,                KEEP_COMPATIBLE_14_SV, SL_MAX_VERSION),
 
 	SLE_END()
 };
diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp
--- a/src/saveload/economy_sl.cpp
+++ b/src/saveload/economy_sl.cpp
@@ -63,11 +63,11 @@
 }
 
 static const SaveLoad _cargopayment_desc[] = {
-	SLE_REF(CargoPayment, front,         REF_VEHICLE),
-	SLE_VAR(CargoPayment, route_profit,  SLE_INT64),
-	SLE_VAR(CargoPayment, visual_profit, SLE_INT64),
-
-	SLE_END()
+	    SLE_REF(CargoPayment, front,           REF_VEHICLE),
+	    SLE_VAR(CargoPayment, route_profit,    SLE_INT64),
+	    SLE_VAR(CargoPayment, visual_profit,   SLE_INT64),
+	SLE_CONDVAR(CargoPayment, visual_transfer, SLE_INT64, SL_CARGOMAP, SL_MAX_VERSION),
+	    SLE_END()
 };
 
 static void Save_CAPY()
diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp
new file mode 100644
--- /dev/null
+++ b/src/saveload/linkgraph_sl.cpp
@@ -0,0 +1,157 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file linkgraph_sl.cpp Code handling saving and loading of link graphs */
+
+#include "../linkgraph/linkgraph.h"
+#include "../linkgraph/demands.h"
+#include "../settings_internal.h"
+#include "saveload.h"
+#include <vector>
+
+const SettingDesc *GetSettingDescription(uint index);
+
+/**
+ * Get a SaveLoad array for a link graph. The settings struct is derived from
+ * the global settings saveload array. The exact entries are calculated when the function
+ * is called the first time.
+ * It's necessary to keep a copy of the settings for each link graph so that you can
+ * change the settings while in-game and still not mess with current link graph runs.
+ * Of course the settings have to be saved and loaded, too, to avoid desyncs.
+ * @return Array of SaveLoad structs.
+ */
+const SaveLoad *GetLinkGraphDesc()
+{
+	static std::vector<SaveLoad> saveloads;
+	static const char *prefix = "linkgraph.";
+
+	/* Build the SaveLoad array on first call and don't touch it later on */
+	if (saveloads.empty()) {
+		size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
+		size_t offset_component = cpp_offsetof(LinkGraph, settings);
+
+		size_t prefixlen = strlen(prefix);
+
+		int setting = 0;
+		const SettingDesc *desc = GetSettingDescription(setting);
+		while (desc->save.cmd != SL_END) {
+			if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) {
+				SaveLoad sl = desc->save;
+				char *&address = reinterpret_cast<char *&>(sl.address);
+				address -= offset_gamesettings;
+				address += offset_component;
+				saveloads.push_back(sl);
+			}
+			desc = GetSettingDescription(++setting);
+		}
+
+		const SaveLoad component_desc[] = {
+			SLE_CONDVAR(LinkGraph, num_nodes,          SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
+			SLE_CONDVAR(LinkGraph, index,              SLE_UINT16, SL_COMPONENTS, SL_MAX_VERSION),
+			SLE_CONDVAR(LinkGraph, current_station_id, SLE_UINT16, SL_COMPONENTS, SL_MAX_VERSION),
+			SLE_CONDVAR(LinkGraph, cargo,              SLE_UINT8,  SL_COMPONENTS, SL_MAX_VERSION),
+			SLE_END()
+		};
+
+		int i = 0;
+		do {
+			saveloads.push_back(component_desc[i++]);
+		} while (saveloads.back().cmd != SL_END);
+	}
+
+	return &saveloads[0];
+}
+
+/* Edges and nodes are saved in the correct order, so we don't need to save their ids. */
+
+/**
+ * SaveLoad desc for a link graph node.
+ */
+static const SaveLoad _node_desc[] = {
+	 SLE_CONDVAR(Node, supply,    SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
+	 SLE_CONDVAR(Node, demand,    SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
+	 SLE_CONDVAR(Node, station,   SLE_UINT16, SL_COMPONENTS, SL_MAX_VERSION),
+	 SLE_END()
+};
+
+/**
+ * SaveLoad desc for a link graph edge.
+ */
+static const SaveLoad _edge_desc[] = {
+	 SLE_CONDVAR(Edge, distance,  SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
+	 SLE_CONDVAR(Edge, capacity,  SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
+	 SLE_CONDVAR(Edge, next_edge, SLE_UINT32,        SL_MCF, SL_MAX_VERSION),
+	 SLE_END()
+};
+
+/**
+ * Save/load a component of a link graph
+ * @param comp the component to be saved or loaded
+ */
+static void SaveLoad_LinkGraphComponent(LinkGraphComponent &comp)
+{
+	uint size = comp.GetSize();
+	for (NodeID from = 0; from < size; ++from) {
+		Node *node = &comp.GetNode(from);
+		SlObject(node, _node_desc);
+		for (NodeID to = 0; to < size; ++to) {
+			SlObject(&comp.GetEdge(from, to), _edge_desc);
+		}
+	}
+}
+
+/**
+ * Save all link graphs.
+ */
+static void DoSave_LGRP(void *)
+{
+	for (CargoID cargo = 0; cargo < NUM_CARGO; ++cargo) {
+		LinkGraph &graph = _link_graphs[cargo];
+		SlObject(&graph, GetLinkGraphDesc());
+		SaveLoad_LinkGraphComponent(graph);
+	}
+}
+
+/**
+ * Load all link graphs.
+ */
+static void Load_LGRP()
+{
+	for (CargoID cargo = 0; cargo < NUM_CARGO; ++cargo) {
+		LinkGraph &graph = _link_graphs[cargo];
+		assert(graph.GetSize() == 0);
+		SlObject(&graph, GetLinkGraphDesc());
+		graph.SetSize();
+		SaveLoad_LinkGraphComponent(graph);
+		for (uint i = 0; i < graph.GetSize(); ++i) {
+			Node &node = graph.GetNode(i);
+			node.undelivered_supply = node.supply;
+		}
+	}
+}
+
+/**
+ * Spawn the threads for running link graph calculations.
+ * Has to be done after loading as the cargo classes might have changed.
+ */
+void AfterLoadLinkGraphs()
+{
+	for (CargoID cargo = 0; cargo < NUM_CARGO; ++cargo) {
+		LinkGraph &graph = _link_graphs[cargo];
+		if (graph.GetSize() > 0) graph.SpawnThread();
+	}
+}
+
+static void Save_LGRP() {
+	SlAutolength((AutolengthProc*)DoSave_LGRP, NULL);
+}
+
+extern const ChunkHandler _linkgraph_chunk_handlers[] = {
+	{ 'LGRP', Save_LGRP, Load_LGRP, NULL, NULL, CH_LAST},
+};
diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp
--- a/src/saveload/map_sl.cpp
+++ b/src/saveload/map_sl.cpp
@@ -13,6 +13,7 @@
 #include "../map_func.h"
 #include "../core/bitmath_func.hpp"
 #include "../fios.h"
+#include "../tile_map.h"
 
 #include "saveload.h"
 
@@ -35,7 +36,9 @@
 static void Load_MAPS()
 {
 	SlGlobList(_map_dimensions);
-	AllocateMap(_map_dim_x, _map_dim_y);
+	/* Don't construct _map_heightdata here, because we don't know wether
+	 * we need it before Load_MAPH. */
+	AllocateMap(_map_dim_x, _map_dim_y, false);
 }
 
 static void Check_MAPS()
@@ -246,6 +249,76 @@
 		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }
+/**
+ * The general idea behind loading and saving MAPH:
+ * ===============================================
+ * The _map_heightdata array is not NULL if and only if AllowMoreHeightlevels(),
+ * defined in tile_map.h is true.
+ *
+ * Saving:
+ * ======
+ * So if AllowMoreHeightlevels is true, we have to save it and do so.
+ * However, if AllowMoreHeightlevels is false, we just save a junk named MAPH
+ * with length 0.
+ *
+ * Loading:
+ * =======
+ * If we load an old savegame without MAPH, then Load_MAPH is not even called.
+ * So, in AfterLoadGame, we set _map_heightdata to NULL and
+ * allow_more_heightlevels to false. (The player may turn on this setting
+ * afterwards in game.)
+ *
+ * If, however, we load a new savegame (where MAPH was already introduced),
+ * SlGetFieldLength() was already set to the length of the chunk by LoadChunk.
+ * So, if AllowMoreHeightLevels is false, we get SlGetFieldLength() == 0 here
+ * and set _map_heightdata to NULL accordingly.
+ * Otherwise, we just load _map_heightdata from the chunk..
+ *
+ * For background information about how and where _map_heightdata is
+ * constructed and freed see comment of AllocateMap() in map_func.h.
+ * @see AllocateMap() in map_func.h.
+ */
+static void Load_MAPH()
+{
+	/* Maybe it was still filled from the previous game. */
+	free(_map_heightdata);
+	/* Does free set it to NULL?  I don't know, so I better do it explicitely. */
+	_map_heightdata = NULL;
+	if (SlGetFieldLength() != 0) {
+		/* We didn't construct it before because we didn't know wether we need it
+		 * before - see comment of AllocateMap for a detailed explanation. */
+		_map_heightdata = CallocT<TileHeightData>(MapSize());
+
+		SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
+		TileIndex size = MapSize();
+
+		for (TileIndex i = 0; i != size;) {
+			SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
+			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) {
+			_map_heightdata[i++].heightlevel = buf[j];
+			}
+		}
+	}
+}
+
+static void Save_MAPH()
+{
+	/* Assure that configuration setting is consistent to the data. */
+	assert(AllowMoreHeightlevels() == (_map_heightdata != NULL));
+
+	if (!AllowMoreHeightlevels()) {
+		SlSetLength(0);
+	} else {
+		SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
+		TileIndex size = MapSize();
+
+		SlSetLength(size * sizeof(uint16));
+		for (TileIndex i = 0; i != size;) {
+			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _map_heightdata[i++].heightlevel;
+			SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
+		}
+	}
+}
 
 extern const ChunkHandler _map_chunk_handlers[] = {
 	{ 'MAPS', Save_MAPS, Load_MAPS, NULL, Check_MAPS, CH_RIFF },
@@ -256,5 +329,6 @@
 	{ 'M3HI', Save_MAP4, Load_MAP4, NULL, NULL,       CH_RIFF },
 	{ 'MAP5', Save_MAP5, Load_MAP5, NULL, NULL,       CH_RIFF },
 	{ 'MAPE', Save_MAP6, Load_MAP6, NULL, NULL,       CH_RIFF },
-	{ 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL,       CH_RIFF | CH_LAST },
+	{ 'MAP7', Save_MAP7, Load_MAP7, NULL, NULL,       CH_RIFF },
+	{ 'MAPH', Save_MAPH, Load_MAPH, NULL, NULL,       CH_RIFF | CH_LAST },
 };
diff --git a/src/saveload/newgrf_sl.cpp b/src/saveload/newgrf_sl.cpp
--- a/src/saveload/newgrf_sl.cpp
+++ b/src/saveload/newgrf_sl.cpp
@@ -60,7 +60,8 @@
 	    SLE_STR(GRFConfig, filename,         SLE_STR,    0x40),
 	    SLE_VAR(GRFConfig, ident.grfid,      SLE_UINT32),
 	    SLE_ARR(GRFConfig, ident.md5sum,     SLE_UINT8,  16),
-	SLE_CONDVAR(GRFConfig, version,          SLE_UINT32, 151, SL_MAX_VERSION),
+	SLE_CONDVAR(GRFConfig, version,          SLE_UINT32, 151, BEFORE_ADDING_PATCHES_SL),
+	SLE_CONDVAR(GRFConfig, version,          SLE_UINT32, KEEP_COMPATIBLE_7_SV, SL_MAX_VERSION),
 	    SLE_ARR(GRFConfig, param,            SLE_UINT32, 0x80),
 	    SLE_VAR(GRFConfig, num_params,       SLE_UINT8),
 	SLE_CONDVAR(GRFConfig, palette,          SLE_UINT8,  101, SL_MAX_VERSION),
diff --git a/src/saveload/object_sl.cpp b/src/saveload/object_sl.cpp
--- a/src/saveload/object_sl.cpp
+++ b/src/saveload/object_sl.cpp
@@ -22,8 +22,10 @@
 	    SLE_VAR(Object, location.h,                 SLE_FILE_U8 | SLE_VAR_U16),
 	    SLE_REF(Object, town,                       REF_TOWN),
 	    SLE_VAR(Object, build_date,                 SLE_UINT32),
-	SLE_CONDVAR(Object, colour,                     SLE_UINT8,                  148, SL_MAX_VERSION),
-	SLE_CONDVAR(Object, view,                       SLE_UINT8,                  155, SL_MAX_VERSION),
+	SLE_CONDVAR(Object, colour,                     SLE_UINT8,                  148, BEFORE_ADDING_PATCHES_SL),
+	SLE_CONDVAR(Object, colour,                     SLE_UINT8,                  KEEP_COMPATIBLE_2_SV, SL_MAX_VERSION),
+	SLE_CONDVAR(Object, view,                       SLE_UINT8,                  155, BEFORE_ADDING_PATCHES_SL),
+	SLE_CONDVAR(Object, view,                       SLE_UINT8,                  KEEP_COMPATIBLE_13_SV, SL_MAX_VERSION),
 
 	SLE_END()
 };
@@ -53,7 +55,7 @@
 	Object *o;
 	FOR_ALL_OBJECTS(o) {
 		SlObject(o, _object_desc);
-		if (IsSavegameVersionBefore(148) && !IsTileType(o->location.tile, MP_OBJECT)) {
+		if (IsSavegameVersionBefore(KEEP_COMPATIBLE_2_SV) && !IsTileType(o->location.tile, MP_OBJECT)) {
 			/* Due to a small bug stale objects could remain. */
 			delete o;
 		} else {
diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp
--- a/src/saveload/oldloader_sl.cpp
+++ b/src/saveload/oldloader_sl.cpp
@@ -710,7 +710,7 @@
 	SB(ge->acceptance_pickup, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
 	SB(ge->acceptance_pickup, GoodsEntry::GES_PICKUP, 1, _cargo_source != 0xFF);
 	if (GB(_waiting_acceptance, 0, 12) != 0 && CargoPacket::CanAllocateItem()) {
-		ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, 0, 0));
+		ge->cargo.Append(INVALID_STATION, new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, (_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, 0, 0));
 	}
 
 	return true;
diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h
--- a/src/saveload/saveload.h
+++ b/src/saveload/saveload.h
@@ -85,8 +85,63 @@
 	REF_STORAGE       = 9, ///< Load/save a reference to a persistent storage.
 };
 
-/** Highest possible savegame version. */
-#define SL_MAX_VERSION 255
+/**
+ * save/load versions used for the various branches / patches
+ */
+enum SaveLoadVersions {
+	BEFORE_ADDING_PATCHES_SL            = 185,
+	BACK_ONE_WAY_SIGNAL_SAFE_WAITING_SL = 186, // Back of one way signals is evil-deadlock.
+	TREE_GROWTH_RATE_SL                 = 188, // 
+	PROG_SIGS_SL                        = 189, // If Then Else signals ...
+	DAYLENGHT_SL                        = 190, // Daylenght
+	TOWN_CARGO_FACTOR_SL                = 191, // Generated town cargo amount
+	SL_RESERVATION                      = 192, // C
+	SL_CAPACITIES                       = 193, // A
+	SL_COMPONENTS                       = 194, // R
+	SL_DEMANDS                          = 195, // G
+	SL_MCF                              = 196, // O
+	SL_FLOWMAP                          = 197, // D
+	SL_CARGOMAP                         = 198, // I
+	SL_EXT_RATING                       = 199, // S (for T @see Keep compatible 8 :P )
+	TIMESEP_SV                          = 200, // Vehicles seperation
+	MORE_HEIGHTLEVEL_SAVEGAME_VERSION   = 201, // High high higher ...
+	KEEP_COMPATIBLE_1_SV                = 202, // 147 (with 147 no new chunks are introduced so no need to do the redeclaration trick)
+	KEEP_COMPATIBLE_2_SV                = 203, // 148
+	KEEP_COMPATIBLE_3_SV                = 204, // 148
+	KEEP_COMPATIBLE_4_SV                = 205, // 149
+	KEEP_COMPATIBLE_5_SV                = 206, // 150
+	KEEP_COMPATIBLE_6_SV                = 206, // MORE_HEIGHTLEVEL_SAVEGAME_VERSION(disaster-vehicle_sl)
+	KEEP_COMPATIBLE_7_SV                = 206, // 151
+	KEEP_COMPATIBLE_8_SV                = 207, // CargoDist SL_CAPACITIES(last_loading_station)
+	INGAME_TREELINE_SV                  = 208, // Fix treeline for old games (and have it configurable ingame at the same time ;) )
+	KEEP_COMPATIBLE_9_SV                = 209, // 151 (vehicle_sl-> CONDNULL)
+	KEEP_COMPATIBLE_10_SV               = 210, // 152
+	KEEP_COMPATIBLE_11_SV               = 210, // 153
+	IS_SL                               = 211, // Infrastructure sharing
+	EXCLUSIVE_DL_SL                     = 212, // Adjust exclusive counter to daylenght in town_sl.cpp
+	KEEP_COMPATIBLE_12_SV               = 213, // 154
+	KEEP_COMPATIBLE_13_SV               = 214, // 155
+	KEEP_COMPATIBLE_14_SV               = 215, // 156
+	KEEP_COMPATIBLE_15_SV               = 216, // 157
+	KEEP_COMPATIBLE_16_SV               = 217, // 158
+	KEEP_COMPATIBLE_17_SV               = 218, // 159
+	KEEP_COMPATIBLE_18_SV               = 219, // 160
+	KEEP_COMPATIBLE_19_SV               = 220, // 160
+	KEEP_COMPATIBLE_20_SV               = 221, // Save ticks per minute (departure boards)
+	SL_IB                               = 222, // Improved breakdowns
+	TL_SV                               = 223, // Trafficlights
+	TOWN_GROWTH_SV                      = 224, // Town growth needs goods
+	DESERT_SV                           = 225, // Amount of desert selectable (not sure if this needs to be saved but it does not hurt ...)
+	KEEP_COMPATIBLE_21_SV               = 226, // TOWN_GROWTH_SV -> saving larger towns values
+	SPEED_SIGNALS_SV                    = 227, // Speed signals (based on progsigs patch)
+	KEEP_COMPATIBLE_22_SV               = 228, // No linkgraph overloading (extension to CargoDist).
+	KEEP_COMPATIBLE_23_SV               = 229, // Advanced setting for industrie placement (More Height Levels)
+	KEEP_COMPATIBLE_24_SV               = 230, // TL_SV -> Advanced setting for selecting distance between trafficlights in a syncronised consist.
+	TREEDRAG_SV                         = 231, // Configurable drag limit for trees.
+
+	/** Highest possible savegame version. */
+	SL_MAX_VERSION                      = 255
+};
 
 /** Flags of a chunk. */
 enum ChunkType {
diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h
--- a/src/saveload/saveload_internal.h
+++ b/src/saveload/saveload_internal.h
@@ -30,6 +30,7 @@
 void AfterLoadStations();
 void AfterLoadRoadStops();
 void AfterLoadLabelMaps();
+void AfterLoadLinkGraphs();
 void UpdateHousesAndTowns();
 
 void UpdateOldAircraft();
diff --git a/src/saveload/signal_sl.cpp b/src/saveload/signal_sl.cpp
new file mode 100644
--- /dev/null
+++ b/src/saveload/signal_sl.cpp
@@ -0,0 +1,341 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file signal_sl.cpp Code handling saving and loading of signals */
+
+#include "../stdafx.h"
+#include "../programmable_signals.h"
+#include "../core/alloc_type.hpp"
+#include "../core/bitmath_func.hpp"
+#include <vector>
+#include "saveload.h"
+
+typedef std::vector<byte> Buffer;
+
+/* Variable length integers are stored in Variable Length Quantity
+ * format (http://en.wikipedia.org/wiki/Variable-length_quantity). */
+
+static void WriteVLI(Buffer &b, uint i)
+{
+    uint lsmask =  0x7F;
+    uint msmask = ~0x7F;
+    while(i & msmask) {
+        byte part = (i & lsmask) | 0x80;
+        b.push_back(part);
+        i >>= 7;
+    }
+    b.push_back((byte) i);
+}
+
+static uint ReadVLI()
+{
+    uint shift = 0;
+		uint val = 0;
+    byte b;
+
+    b = SlReadByte();
+    while(b & 0x80) {
+        val |= uint(b & 0x7F) << shift;
+        shift += 7;
+        b = SlReadByte();
+    }
+    val |= uint(b) << shift;
+    return val;
+}
+
+static void WriteCondition(Buffer &b, SignalCondition *c)
+{
+	WriteVLI(b, c->ConditionCode());
+	switch(c->ConditionCode()) {
+		case PSC_NUM_GREEN:
+		case PSC_NUM_RED: {
+			SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(c);
+			WriteVLI(b, vc->comparator);
+			WriteVLI(b, vc->value);
+		} break;
+		
+		case PSC_SIGNAL_STATE: {
+			SignalStateCondition *sc = static_cast<SignalStateCondition*>(c);
+			WriteVLI(b, sc->sig_tile);
+			WriteVLI(b, sc->sig_track);
+		} break;
+		
+		default:
+			break;
+	}
+}
+
+static SignalCondition *ReadCondition(SignalReference this_sig)
+{
+	SignalConditionCode code = (SignalConditionCode) ReadVLI();
+	switch(code) {
+		case PSC_NUM_GREEN:
+		case PSC_NUM_RED: {
+			SignalVariableCondition *c = new SignalVariableCondition(code);
+			c->comparator = (SignalComparator) ReadVLI();
+			if(c->comparator > SGC_LAST) NOT_REACHED();
+			c->value = ReadVLI();
+			return c;
+		}
+		
+		case PSC_SIGNAL_STATE: {
+			TileIndex ti = (TileIndex) ReadVLI();
+			Trackdir  td = (Trackdir) ReadVLI();
+			return new SignalStateCondition(this_sig, ti, td);
+		}
+		
+		default:
+			return new SignalSimpleCondition(code);
+	}
+}
+
+static void Save_SPRG()
+{
+	/* Check for, and dispose of, any signal information on a tile which doesn't have signals.
+	 * This indicates that someone removed the signals from the tile but didn't clean them up.
+	 * (This code is to detect bugs and limit their consquences, not to cover them up!) */
+	for(ProgramList::iterator i = _signal_programs.begin(), e = _signal_programs.end();
+			i != e; ++i) {
+		SignalReference ref = i->first;
+		if(!HasProgrammableSignals(ref)) {
+			DEBUG(sl, 0, "Programmable signal information for (%x, %d) has been leaked!",
+						ref.tile, ref.track);
+			++i;
+			FreeSignalProgram(ref);
+			if(i == e) break;
+		}
+	}
+	
+	/* OK, we can now write out our programs. */
+	Buffer b;
+	WriteVLI(b, _signal_programs.size());
+	for(ProgramList::iterator i = _signal_programs.begin(), e = _signal_programs.end();
+			i != e; ++i) {
+		SignalReference ref = i->first;
+		SignalProgram *prog = i->second;
+	
+		prog->DebugPrintProgram();
+	
+		WriteVLI(b, prog->tile);
+		WriteVLI(b, prog->track);
+		WriteVLI(b, prog->instructions.Length());
+		for(SignalInstruction **j = prog->instructions.Begin(), **je = prog->instructions.End();
+				j != je; ++j) {
+			SignalInstruction *insn = *j;
+			WriteVLI(b, insn->Opcode());
+			if(insn->Opcode() != PSO_FIRST)
+				WriteVLI(b, insn->Previous()->Id());
+			switch(insn->Opcode()) {
+				case PSO_FIRST: {
+					SignalSpecial *s = static_cast<SignalSpecial*>(insn);
+					WriteVLI(b, s->next->Id());
+					break;
+				}
+				
+				case PSO_LAST: break;
+				
+				case PSO_IF: {
+					SignalIf *i = static_cast<SignalIf*>(insn);
+					WriteCondition(b, i->condition);
+					WriteVLI(b, i->if_true->Id()); 
+					WriteVLI(b, i->if_false->Id());
+					WriteVLI(b, i->after->Id());
+					break;
+				}
+				
+				case PSO_IF_ELSE:
+				case PSO_IF_ENDIF: {
+					SignalIf::PseudoInstruction *p = static_cast<SignalIf::PseudoInstruction*>(insn);
+					WriteVLI(b, p->block->Id());
+					break;
+				}
+				
+				case PSO_SET_SIGNAL: {
+					SignalSet *s = static_cast<SignalSet*>(insn);
+					WriteVLI(b, s->next->Id());
+					WriteVLI(b, s->to_state ? 1 : 0);
+					break;
+				}
+				
+				default: NOT_REACHED();
+			}
+		}
+	}
+	
+	uint size = b.size();
+	SlSetLength(size);
+	for(uint i = 0; i < size; i++)
+		SlWriteByte(b[i]); // TODO Gotta be a better way
+}
+
+static void Load_SSIG()
+{
+	_speedlimits.clear();
+
+	uint count = ReadVLI();
+	for(uint i = 0; i < count; i++) {
+		TileIndex tile    = ReadVLI();
+		Track     track   = (Track) ReadVLI();
+		uint16 speed = ReadVLI();
+		SignalReference ref(tile, track);
+
+		_speedlimits[ref] = speed;
+	}
+}
+
+static void Save_SSIG()
+{
+	/* Check for, and dispose of, any signal information on a tile which doesn't have signals.
+	 * This indicates that someone removed the signals from the tile but didn't clean them up.
+	 * (This code is to detect bugs and limit their consquences, not to cover them up!) */
+	for(SpeedLimits::iterator i = _speedlimits.begin(), e = _speedlimits.end();
+			i != e; ++i) {
+		SignalReference ref = i->first;
+		if(!HasSpeedSignals(ref)) {
+			DEBUG(sl, 0, "Speed signal information for (%x, %d) has been leaked!",
+						ref.tile, ref.track);
+			++i;
+			FreeSignalSpeed(ref);
+			if(i == e) break;
+		}
+	}
+
+	/* OK, we can now write out our speed limits. */
+	Buffer b;
+	WriteVLI(b, _speedlimits.size());
+	for(SpeedLimits::iterator i = _speedlimits.begin(), e = _speedlimits.end();
+			i != e; ++i) {
+		SignalReference ref = i->first;
+		uint16 speed = i->second;
+
+		WriteVLI(b, ref.tile);
+		WriteVLI(b, ref.track);
+		WriteVLI(b, speed);
+	}
+
+	uint size = b.size();
+	SlSetLength(size);
+	for(uint i = 0; i < size; i++)
+		SlWriteByte(b[i]); // TODO Gotta be a better way.
+}
+
+/* We don't know the pointer values that need to be stored in various 
+ * instruction fields at load time, so we need to instead store the IDs and
+ * then fix them up once all of the instructions have been loaded.
+ *
+ * Additionally, we store the opcode type we expect (if we expect a specific one)
+ * to check for consistency (For example, an If Pseudo Instruction's block should
+ * point at an If!) */
+struct Fixup {
+	Fixup(SignalInstruction **p, SignalOpcode type)
+		: type(type), ptr(p)
+	{}
+	
+	SignalOpcode type;
+	SignalInstruction **ptr;
+};
+
+typedef SmallVector<Fixup, 4> FixupList;
+
+template<typename T>
+static void MakeFixup(FixupList &l, T *&ir, uint id, SignalOpcode op = PSO_INVALID)
+{
+	ir = reinterpret_cast<T*>(id);
+	new(l.Append()) Fixup(reinterpret_cast<SignalInstruction**>(&ir), op);
+}
+
+static void DoFixups(FixupList &l, InstructionList &il)
+{
+	for(Fixup *i = l.Begin(), *e = l.End(); i != e; ++i) {
+		uint id = reinterpret_cast<size_t>(*i->ptr);
+		if(id >= il.Length())
+			NOT_REACHED();
+			
+		*i->ptr = il[id];
+		
+		if(i->type != PSO_INVALID && (*i->ptr)->Opcode() != i->type) {
+			DEBUG(sl, 0, "Expected Id %d to be %d, but was in fact %d", id, i->type, (*i->ptr)->Opcode());
+			NOT_REACHED();
+		}
+	}
+}
+
+static void Load_SPRG()
+{
+	uint count = ReadVLI();
+	for(uint i = 0; i < count; i++) {
+		FixupList l;
+		TileIndex tile    = ReadVLI();
+		Track     track   = (Track) ReadVLI();
+		uint instructions = ReadVLI();
+		SignalReference ref(tile, track);
+		
+		SignalProgram *sp = new SignalProgram(tile, track, true);
+		_signal_programs[ref] = sp;
+		
+		for(uint j = 0; j < instructions; j++) {
+			SignalOpcode op = (SignalOpcode) ReadVLI();
+			switch(op) {
+				case PSO_FIRST: {
+					sp->first_instruction = new SignalSpecial(sp, PSO_FIRST);
+					sp->first_instruction->GetPrevHandle() = NULL;
+					MakeFixup(l, sp->first_instruction->next, ReadVLI());
+					break;
+				}
+				
+				case PSO_LAST: {
+					sp->last_instruction = new SignalSpecial(sp, PSO_LAST);
+					sp->last_instruction->next = NULL;
+					MakeFixup(l, sp->last_instruction->GetPrevHandle(), ReadVLI());
+					break;
+				}
+				
+				case PSO_IF: {
+					SignalIf *i = new SignalIf(sp, true);
+					MakeFixup(l, i->GetPrevHandle(), ReadVLI());
+					i->condition = ReadCondition(ref);
+					MakeFixup(l, i->if_true,  ReadVLI()); 
+					MakeFixup(l, i->if_false, ReadVLI()); 
+					MakeFixup(l, i->after, ReadVLI()); 
+					break;
+				}
+				
+				case PSO_IF_ELSE:
+				case PSO_IF_ENDIF: {
+					SignalIf::PseudoInstruction *p = new SignalIf::PseudoInstruction(sp, op);
+					MakeFixup(l, p->GetPrevHandle(), ReadVLI());
+					MakeFixup(l, p->block, ReadVLI(), PSO_IF);
+					break;
+				}
+				
+				case PSO_SET_SIGNAL: {
+					SignalSet *s = new SignalSet(sp);
+					MakeFixup(l, s->GetPrevHandle(), ReadVLI());
+					MakeFixup(l, s->next, ReadVLI());
+					s->to_state = (SignalState) ReadVLI();
+					if(s->to_state > SIGNAL_STATE_MAX) NOT_REACHED();
+					break;
+				}
+				
+				default: NOT_REACHED();
+			}
+		}
+		
+		DoFixups(l, sp->instructions);
+		sp->DebugPrintProgram();
+	}
+}
+
+extern const ChunkHandler _signal_chunk_handlers[] = {
+	{ 'SPRG', Save_SPRG, Load_SPRG, NULL, NULL, CH_RIFF | CH_LAST},
+};
+
+extern const ChunkHandler _speed_signal_chunk_handlers[] = {
+	{ 'SSIG', Save_SSIG, Load_SSIG, NULL, NULL, CH_RIFF | CH_LAST},
+};
diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp
--- a/src/saveload/station_sl.cpp
+++ b/src/saveload/station_sl.cpp
@@ -225,9 +225,11 @@
 };
 
 static uint16 _waiting_acceptance;
+static uint16 _num_links;
+static uint32 _num_flows;
 static uint16 _cargo_source;
 static uint32 _cargo_source_xy;
-static uint16 _cargo_days;
+static uint8  _cargo_days;
 static Money  _cargo_feeder_share;
 
 static const SaveLoad _station_speclist_desc[] = {
@@ -237,6 +239,49 @@
 	SLE_END()
 };
 
+static StationID _station_id;
+
+/**
+ * Wrapper function to get the LinkStat's internal structure while
+ * some of the variables are private.
+ * @return Saveload description for LinkStat.
+ */
+const SaveLoad *GetLinkStatDesc()
+{
+	static const SaveLoad linkstat_desc[] = {
+		SLEG_CONDVAR(             _station_id,         SLE_UINT16,      SL_CAPACITIES, SL_MAX_VERSION),
+		 SLE_CONDVAR(LinkStat,    length,              SLE_UINT32,      SL_CAPACITIES, SL_MAX_VERSION),
+		 SLE_CONDVAR(LinkStat,    capacity,            SLE_UINT32,      SL_CAPACITIES, SL_MAX_VERSION),
+		 SLE_CONDVAR(LinkStat,    frozen,              SLE_UINT32,      SL_CAPACITIES, SL_MAX_VERSION),
+		 SLE_CONDVAR(LinkStat,    usage,               SLE_UINT32,      SL_CAPACITIES, SL_MAX_VERSION),
+		 SLE_END()
+	};
+	
+	return linkstat_desc;
+}
+
+/**
+ * Wrapper function to get the FlowStats's internal structure while
+ * some of the variables are private.
+ * @return Saveload description for FlowStat.
+ */
+const SaveLoad *GetFlowStatDesc()
+{
+	static const SaveLoad _flowstat_desc[] = {
+		SLEG_CONDVAR(             _station_id,         SLE_UINT16,         SL_FLOWMAP, SL_MAX_VERSION),
+		 SLE_CONDVAR(FlowStat,    via,                 SLE_UINT16,         SL_FLOWMAP, SL_MAX_VERSION),
+		 SLE_CONDVAR(FlowStat,    length,              SLE_UINT32,         SL_FLOWMAP, SL_MAX_VERSION),
+		 SLE_CONDVAR(FlowStat,    planned,             SLE_UINT32,         SL_FLOWMAP, SL_MAX_VERSION),
+		 SLE_CONDVAR(FlowStat,    sent,                SLE_UINT32,         SL_FLOWMAP, SL_MAX_VERSION),
+		 SLE_END()
+	};
+
+	return _flowstat_desc;
+}
+
+std::list<CargoPacket *> _packets;
+uint32 _num_dests;
+
 /**
  * Wrapper function to get the GoodsEntry's internal structure while
  * some of the variables itself are private.
@@ -258,15 +303,51 @@
 		     SLE_VAR(GoodsEntry, last_age,            SLE_UINT8),
 		SLEG_CONDVAR(            _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
 		SLEG_CONDVAR(            _cargo_feeder_share, SLE_INT64,                  65, 67),
-		 SLE_CONDVAR(GoodsEntry, amount_fract,        SLE_UINT8,                 150, SL_MAX_VERSION),
-		 SLE_CONDLST(GoodsEntry, cargo.packets,       REF_CARGO_PACKET,           68, SL_MAX_VERSION),
-
+		 SLE_CONDVAR(GoodsEntry, amount_fract,        SLE_UINT8,                 150, BEFORE_ADDING_PATCHES_SL),
+		 SLE_CONDVAR(GoodsEntry, amount_fract,        SLE_UINT8,                 KEEP_COMPATIBLE_5_SV, SL_MAX_VERSION),
+		SLEG_CONDLST(            _packets,            REF_CARGO_PACKET,           68, SL_CARGOMAP - 1),
+		SLEG_CONDVAR(            _num_dests,          SLE_UINT32,        SL_CARGOMAP, SL_MAX_VERSION),
+		 SLE_CONDVAR(GoodsEntry, supply,              SLE_UINT32,      SL_CAPACITIES, SL_MAX_VERSION),
+		 SLE_CONDVAR(GoodsEntry, supply_new,          SLE_UINT32,      SL_CAPACITIES, SL_MAX_VERSION),
+		SLEG_CONDVAR(            _num_links,          SLE_UINT16,      SL_CAPACITIES, SL_MAX_VERSION),
+		SLEG_CONDVAR(            _num_flows,          SLE_UINT32,         SL_FLOWMAP, SL_MAX_VERSION),
+		 SLE_CONDVAR(GoodsEntry, last_component,      SLE_UINT16,      SL_COMPONENTS, SL_MAX_VERSION),
+		 SLE_CONDVAR(GoodsEntry, max_waiting_cargo,   SLE_UINT32,      SL_EXT_RATING, SL_MAX_VERSION),
 		SLE_END()
 	};
 
 	return goods_desc;
 }
 
+typedef std::pair<const StationID, std::list<CargoPacket *> > StationCargoPair;
+
+static const SaveLoad _cargo_list_desc[] = {
+	SLE_VAR(StationCargoPair, first,  SLE_UINT16),
+	SLE_LST(StationCargoPair, second, REF_CARGO_PACKET),
+	SLE_END()
+};
+
+/**
+ * swap the temporary packets with the packets without specific destination in
+ * the given goods entry. Assert that at least one of those is empty.
+ * @param ge the goods entry to swap with
+ */
+static void SwapPackets(GoodsEntry *ge)
+{
+	StationCargoPacketMap &ge_packets = const_cast<StationCargoPacketMap &>(*ge->cargo.Packets());
+
+	if (_packets.empty()) {
+		std::map<StationID, std::list<CargoPacket *> >::iterator it(ge_packets.find(INVALID_STATION));
+		if (it == ge_packets.end()) {
+			return;
+		} else {
+			it->second.swap(_packets);
+		}
+	} else {
+		assert(ge_packets[INVALID_STATION].empty());
+		ge_packets[INVALID_STATION].swap(_packets);
+	}
+}
 
 static void Load_STNS()
 {
@@ -282,6 +363,7 @@
 		for (CargoID i = 0; i < num_cargo; i++) {
 			GoodsEntry *ge = &st->goods[i];
 			SlObject(ge, GetGoodsDesc());
+			SwapPackets(ge);
 			if (IsSavegameVersionBefore(68)) {
 				SB(ge->acceptance_pickup, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
 				if (GB(_waiting_acceptance, 0, 12) != 0) {
@@ -293,8 +375,11 @@
 					 * savegame versions. As the CargoPacketPool has more than
 					 * 16 million entries; it fits by an order of magnitude. */
 					assert(CargoPacket::CanAllocateItem());
-					ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, source, _cargo_source_xy, _cargo_source_xy, _cargo_feeder_share));
-					SB(ge->acceptance_pickup, GoodsEntry::GES_PICKUP, 1, 1);
+
+					/* Don't construct the packet with station here, because that'll fail with old savegames */
+					CargoPacket *cp = new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, source, _cargo_source_xy, _cargo_source_xy, _cargo_feeder_share);
+					ge->cargo.Append(INVALID_STATION, cp);
+ 					SB(ge->acceptance_pickup, GoodsEntry::GES_PICKUP, 1, 1);
 				}
 			}
 		}
@@ -319,7 +404,9 @@
 		if (!IsSavegameVersionBefore(68)) {
 			for (CargoID i = 0; i < NUM_CARGO; i++) {
 				GoodsEntry *ge = &st->goods[i];
+				SwapPackets(ge);
 				SlObject(ge, GetGoodsDesc());
+				SwapPackets(ge);
 			}
 		}
 		SlObject(st, _old_station_desc);
@@ -409,8 +496,29 @@
 
 	if (!waypoint) {
 		Station *st = Station::From(bst);
-		for (CargoID i = 0; i < NUM_CARGO; i++) {
-			SlObject(&st->goods[i], GetGoodsDesc());
+		for (CargoID c = 0; c < NUM_CARGO; c++) {
+			_num_dests = (uint32)st->goods[c].cargo.Packets()->MapSize();
+			_num_links = (uint16)st->goods[c].link_stats.size();
+			_num_flows = 0;
+			for (FlowStatMap::const_iterator it(st->goods[c].flows.begin()); it != st->goods[c].flows.end(); ++it) {
+				_num_flows += (uint32)it->second.size();
+			}
+			SlObject(&st->goods[c], GetGoodsDesc());
+			for (LinkStatMap::const_iterator it(st->goods[c].link_stats.begin()); it != st->goods[c].link_stats.end(); ++it) {
+				_station_id = it->first;
+				LinkStat ls(it->second); // make a copy to avoid constness problems
+				SlObject(&ls, GetLinkStatDesc());
+			}
+			for (FlowStatMap::const_iterator outer_it(st->goods[c].flows.begin()); outer_it != st->goods[c].flows.end(); ++outer_it) {
+				_station_id = outer_it->first;
+				for (FlowStatSet::const_iterator inner_it(outer_it->second.begin()); inner_it != outer_it->second.end(); ++inner_it) {
+					FlowStat fs(*inner_it); // make a copy to avoid constness problems
+					SlObject(&fs, GetFlowStatDesc());
+				}
+			}
+			for (StationCargoPacketMap::ConstMapIterator it(st->goods[c].cargo.Packets()->begin()); it != st->goods[c].cargo.Packets()->end(); ++it) {
+				SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), _cargo_list_desc);
+			}
 		}
 	}
 
@@ -474,7 +582,16 @@
 	FOR_ALL_STATIONS(st) {
 		for (CargoID i = 0; i < NUM_CARGO; i++) {
 			GoodsEntry *ge = &st->goods[i];
-			SlObject(ge, GetGoodsDesc());
+			if (IsSavegameVersionBefore(SL_CARGOMAP)) {
+				SwapPackets(ge);
+				SlObject(ge, GetGoodsDesc());
+				SwapPackets(ge);
+			} else {
+				SlObject(ge, GetGoodsDesc());
+				for (StationCargoPacketMap::ConstMapIterator it = ge->cargo.Packets()->begin(); it != ge->cargo.Packets()->end(); ++it) {
+					SlObject(const_cast<StationCargoPair *>(&(*it)), _cargo_list_desc);
+				}
+			}
 		}
 		SlObject(st, _station_desc);
 	}
diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp
--- a/src/saveload/town_sl.cpp
+++ b/src/saveload/town_sl.cpp
@@ -165,7 +165,8 @@
 	    SLE_VAR(Town, road_build_months,     SLE_UINT8),
 
 	SLE_CONDVAR(Town, exclusivity,           SLE_UINT8,                  2, SL_MAX_VERSION),
-	SLE_CONDVAR(Town, exclusive_counter,     SLE_UINT8,                  2, SL_MAX_VERSION),
+	SLE_CONDVAR(Town, exclusive_counter,     SLE_UINT8,                  2, EXCLUSIVE_DL_SL - 1),
+	SLE_CONDVAR(Town, exclusive_counter,     SLE_UINT16,   EXCLUSIVE_DL_SL, SL_MAX_VERSION),
 
 	SLE_CONDVAR(Town, larger_town,           SLE_BOOL,                  56, SL_MAX_VERSION),
 	SLE_CONDVAR(Town, layout,                SLE_UINT8,                113, SL_MAX_VERSION),
diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp
--- a/src/saveload/vehicle_sl.cpp
+++ b/src/saveload/vehicle_sl.cpp
@@ -195,7 +195,7 @@
 			if (a->subtype == AIR_HELICOPTER) a->Next()->Next()->cur_speed = 32;
 
 			/* set new position x,y,z */
-			SetAircraftPosition(a, gp.x, gp.y, GetAircraftFlyingAltitude(a));
+			SetAircraftPosition(a, gp.x, gp.y, GetAircraftMaxAltitude(a->x_pos, a->y_pos, 0));
 		}
 	}
 }
@@ -318,7 +318,7 @@
 			}
 		}
 
-		if (IsSavegameVersionBefore(157)) {
+		if (IsSavegameVersionBefore(KEEP_COMPATIBLE_15_SV)) {
 			/* The road vehicle subtype was converted to a flag. */
 			RoadVehicle *rv;
 			FOR_ALL_ROADVEHICLES(rv) {
@@ -335,7 +335,7 @@
 			}
 		}
 
-		if (IsSavegameVersionBefore(160)) {
+		if (IsSavegameVersionBefore(KEEP_COMPATIBLE_19_SV)) {
 			/* In some old savegames there might be some "crap" stored. */
 			FOR_ALL_VEHICLES(v) {
 				if (!v->IsPrimaryVehicle() && v->type != VEH_DISASTER) {
@@ -491,6 +491,7 @@
 		     SLE_VAR(Vehicle, engine_type,           SLE_UINT16),
 
 		SLE_CONDNULL(2,                                                            0,  151),
+		SLE_CONDNULL(2,                                                            BEFORE_ADDING_PATCHES_SL,  KEEP_COMPATIBLE_9_SV),
 		     SLE_VAR(Vehicle, cur_speed,             SLE_UINT16),
 		     SLE_VAR(Vehicle, subspeed,              SLE_UINT8),
 		     SLE_VAR(Vehicle, acceleration,          SLE_UINT8),
@@ -499,6 +500,7 @@
 		     SLE_VAR(Vehicle, vehstatus,             SLE_UINT8),
 		 SLE_CONDVAR(Vehicle, last_station_visited,  SLE_FILE_U8  | SLE_VAR_U16,   0,   4),
 		 SLE_CONDVAR(Vehicle, last_station_visited,  SLE_UINT16,                   5, SL_MAX_VERSION),
+		 SLE_CONDVAR(Vehicle, last_loading_station,  SLE_UINT16, KEEP_COMPATIBLE_8_SV, SL_MAX_VERSION),
 
 		     SLE_VAR(Vehicle, cargo_type,            SLE_UINT8),
 		 SLE_CONDVAR(Vehicle, cargo_subtype,         SLE_UINT8,                   35, SL_MAX_VERSION),
@@ -557,6 +559,8 @@
 		     SLE_VAR(Vehicle, breakdown_delay,       SLE_UINT8),
 		     SLE_VAR(Vehicle, breakdowns_since_last_service, SLE_UINT8),
 		     SLE_VAR(Vehicle, breakdown_chance,      SLE_UINT8),
+		 SLE_CONDVAR(Vehicle, breakdown_type,        SLE_UINT8,                SL_IB, SL_MAX_VERSION),
+		 SLE_CONDVAR(Vehicle, breakdown_severity,    SLE_UINT8,	               SL_IB, SL_MAX_VERSION),
 		 SLE_CONDVAR(Vehicle, build_year,            SLE_FILE_U8 | SLE_VAR_I32,    0,  30),
 		 SLE_CONDVAR(Vehicle, build_year,            SLE_INT32,                   31, SL_MAX_VERSION),
 
@@ -577,6 +581,9 @@
 		 SLE_CONDVAR(Vehicle, random_bits,           SLE_UINT8,                    2, SL_MAX_VERSION),
 		 SLE_CONDVAR(Vehicle, waiting_triggers,      SLE_UINT8,                    2, SL_MAX_VERSION),
 
+		 SLE_CONDREF(Vehicle, ahead_separation,      REF_VEHICLE,         TIMESEP_SV, SL_MAX_VERSION),
+		 SLE_CONDREF(Vehicle, behind_separation,     REF_VEHICLE,         TIMESEP_SV, SL_MAX_VERSION),
+
 		 SLE_CONDREF(Vehicle, next_shared,           REF_VEHICLE,                  2, SL_MAX_VERSION),
 		SLE_CONDNULL(2,                                                            2,  68),
 		SLE_CONDNULL(4,                                                           69, 100),
@@ -584,6 +591,7 @@
 		 SLE_CONDVAR(Vehicle, group_id,              SLE_UINT16,                  60, SL_MAX_VERSION),
 
 		 SLE_CONDVAR(Vehicle, current_order_time,    SLE_UINT32,                  67, SL_MAX_VERSION),
+		 SLE_CONDVAR(Vehicle, current_loading_time,  SLE_UINT32,          TIMESEP_SV, SL_MAX_VERSION),
 		 SLE_CONDVAR(Vehicle, lateness_counter,      SLE_INT32,                   67, SL_MAX_VERSION),
 
 		SLE_CONDNULL(10,                                                           2, 143), // old reserved space
@@ -608,6 +616,7 @@
 
 		SLE_CONDNULL(2, 2, 19),
 		 SLE_CONDVAR(Train, gv_flags,            SLE_UINT16,                 139, SL_MAX_VERSION),
+ 		 SLE_CONDVAR(Train, signal_speedlimit,   SLE_UINT16,                 SPEED_SIGNALS_SV, SL_MAX_VERSION),
 		SLE_CONDNULL(11, 2, 143), // old reserved space
 
 		     SLE_END()
@@ -658,10 +667,11 @@
 		 SLE_CONDVAR(Aircraft, last_direction,        SLE_UINT8,                    2, SL_MAX_VERSION),
 		 SLE_CONDVAR(Aircraft, number_consecutive_turns, SLE_UINT8,                 2, SL_MAX_VERSION),
 
+		 SLE_CONDVAR(Aircraft, in_max_height_correction, SLE_UINT8,               MORE_HEIGHTLEVEL_SAVEGAME_VERSION, SL_MAX_VERSION),
+		 SLE_CONDVAR(Aircraft, in_min_height_correction, SLE_UINT8,               MORE_HEIGHTLEVEL_SAVEGAME_VERSION, SL_MAX_VERSION),
+
 		 SLE_CONDVAR(Aircraft, turn_counter,          SLE_UINT8,                  136, SL_MAX_VERSION),
-
 		SLE_CONDNULL(13,                                                           2, 143), // old reserved space
-
 		     SLE_END()
 	};
 
@@ -727,6 +737,8 @@
 
 		     SLE_VAR(DisasterVehicle, image_override,            SLE_UINT16),
 		     SLE_VAR(DisasterVehicle, big_ufo_destroyer_target,  SLE_UINT16),
+		 SLE_CONDVAR(DisasterVehicle, in_max_height_correction, SLE_UINT8,       MORE_HEIGHTLEVEL_SAVEGAME_VERSION, SL_MAX_VERSION),
+		 SLE_CONDVAR(DisasterVehicle, in_min_height_correction, SLE_UINT8,       MORE_HEIGHTLEVEL_SAVEGAME_VERSION, SL_MAX_VERSION),
 
 		SLE_CONDNULL(16,                                                           2, 143), // old reserved space
 
@@ -793,6 +805,10 @@
 			v->last_station_visited = INVALID_STATION;
 		}
 
+		if (IsSavegameVersionBefore(KEEP_COMPATIBLE_8_SV)) {
+			v->last_loading_station = INVALID_STATION;
+		}
+
 		if (IsSavegameVersionBefore(5)) {
 			/* Convert the current_order.type (which is a mix of type and flags, because
 			 *  in those versions, they both were 4 bits big) to type and flags */
diff --git a/src/screenshot.cpp b/src/screenshot.cpp
--- a/src/screenshot.cpp
+++ b/src/screenshot.cpp
@@ -792,7 +792,7 @@
 	while (n > 0) {
 		TileIndex ti = TileXY(MapMaxX(), y);
 		for (uint x = MapMaxX(); true; x--) {
-			*buf = 16 * TileHeight(ti);
+			*buf = 1 * TileHeight(ti); // Todo: adjust to allow choosing generated height; 16 is trunk
 			buf++;
 			if (x == 0) break;
 			ti = TILE_ADDXY(ti, -1, 0);
diff --git a/src/settings.cpp b/src/settings.cpp
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -61,6 +61,10 @@
 #include "smallmap_gui.h"
 #include "roadveh.h"
 #include "fios.h"
+#include "company_manager_face.h"
+#include "infrastructure_func.h"
+#include "strings_func.h"
+#include "trafficlight_func.h"
 
 #include "void_map.h"
 #include "station_base.h"
@@ -950,7 +954,7 @@
  * J: breakdowns (0 = off, 2 = normal)
  * K: subsidy multiplier (0 = 1.5, 3 = 4.0)
  * L: construction cost (0-2)
- * M: terrain type (0 = very flat, 3 = mountainous)
+ * M: terrain type (0 = very flat, 6 = alpinist)
  * N: amount of water (0 = very low, 3 = high)
  * O: economy (0 = steady, 1 = fluctuating)
  * P: Train reversing (0 = end of line + stations, 1 = end of line)
@@ -959,10 +963,10 @@
  * S: the difficulty level
  */
 static const DifficultySettings _default_game_diff[3] = { /*
-	 A, C, D,      E, F, G, H, J, K, L, M, N, O, P, Q, R, S*/
-	{2, 2, 4, 300000, 2, 0, 2, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0}, ///< easy
-	{4, 2, 3, 150000, 3, 1, 3, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1}, ///< medium
-	{7, 3, 3, 100000, 4, 1, 3, 2, 0, 2, 3, 2, 1, 1, 1, 2, 2}, ///< hard
+	 A, C, D,         E, F, G, H, J, K, L, M, N, O, P, Q, R, S*/
+	{0, 2, 1, 999950000, 0, 0, 0, 0, 3, 0, 1, 1, 0, 0, 0, 0, 0}, ///< kidscorner
+	{4, 2, 3,    150000, 3, 1, 3, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1}, ///< medium
+	{7, 3, 3,    100000, 4, 1, 3, 2, 0, 2, 3, 2, 1, 1, 1, 2, 2}, ///< hard
 };
 
 void SetDifficultyLevel(int mode, DifficultySettings *gm_opt)
@@ -1069,6 +1073,21 @@
 	return LookupOneOfMany("normal|hilly|desert|candy", value);
 }
 
+/**
+ * What to do when traffic light Setting was changed.
+ * @param p1 unused
+ * @return always 0
+ */
+static bool TLSettingChanged(int32 p1)
+{
+	/* Road building gui changed. */
+	MarkWholeScreenDirty();
+
+	/* If traffic lights got disabled, clear them all. */
+	if (!_settings_game.construction.traffic_lights) ClearAllTrafficLights();
+	return true;
+}
+
 static bool CheckFreeformEdges(int32 p1)
 {
 	if (_game_mode == GM_MENU) return true;
@@ -1186,6 +1205,28 @@
 	return true;
 }
 
+static bool CheckSharingRail(int32 p1)
+{
+	if (!CheckSharingChangePossible(VEH_TRAIN)) return false;
+	UpdateAllBlockSignals();
+	return true;
+}
+
+static bool CheckSharingRoad(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_ROAD);
+}
+
+static bool CheckSharingWater(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_SHIP);
+}
+
+static bool CheckSharingAir(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_AIRCRAFT);
+}
+
 #endif /* ENABLE_NETWORK */
 
 
@@ -1491,6 +1532,7 @@
 static void HandleSettingDescs(IniFile *ini, SettingDescProc *proc, SettingDescProcList *proc_list)
 {
 	proc(ini, (const SettingDesc*)_misc_settings,    "misc",  NULL);
+	proc(ini, (const SettingDesc*)_music_settings,   "music", &_msf);
 #if defined(WIN32) && !defined(DEDICATED)
 	proc(ini, (const SettingDesc*)_win32_settings,   "win32", NULL);
 #endif /* WIN32 */
@@ -1622,7 +1664,7 @@
 	delete ini;
 }
 
-static const SettingDesc *GetSettingDescription(uint index)
+const SettingDesc *GetSettingDescription(uint index)
 {
 	if (index >= lengthof(_settings)) return NULL;
 	return &_settings[index];
@@ -1822,6 +1864,157 @@
 }
 
 /**
+ * Build the CompanyProfile information from a given company
+ * @param company The company to build from
+ * @return A filled CompanyProfile
+ */
+CompanyProfile GetCompanyProfile(const Company &company)
+{
+	CompanyProfile company_profile;
+
+	SetDParam(0, company.index);
+	GetString(company_profile.president_name, STR_PRESIDENT_NAME, lastof(company_profile.president_name));
+
+	SetDParam(0, company.index);
+	GetString(company_profile.company_name, STR_COMPANY_NAME, lastof(company_profile.company_name));
+
+	company_profile.face = company.face;
+
+	for (int i = 0; i < LS_END; i++) {
+		company_profile.livery[i] = company.livery[i];
+	}
+
+	return company_profile;
+
+}
+
+/**
+ * Set a companies information from a CompanyProfile
+ * @param company_profile The CompanyProfile to use
+ * @return STR_NULL on success STR_* on fail
+ */
+StringID SetCompanyProfile(const CompanyProfile &company_profile) 
+{
+	char buf[MAX_LENGTH_PRESIDENT_NAME_CHARS > MAX_LENGTH_COMPANY_NAME_CHARS ? MAX_LENGTH_PRESIDENT_NAME_CHARS : MAX_LENGTH_COMPANY_NAME_CHARS];
+
+	sprintf(buf, "company_profile");
+
+	/* Set president name */
+	SetDParam(0, _company_pool.Get(_local_company)->index);  // Get local name
+	GetString(buf, STR_PRESIDENT_NAME, lastof(buf));         // ^Continued
+	if (strcmp(buf, company_profile.president_name) != 0) {  // Compare local and loaded
+		if (!DoCommandP(0, 0, 0, CMD_RENAME_PRESIDENT, NULL, company_profile.president_name)) return STR_ERROR_CAN_T_CHANGE_PRESIDENT;
+	}
+	
+	/* Set company name */
+	SetDParam(0, _company_pool.Get(_local_company)->index);// Get local name
+	GetString(buf, STR_COMPANY_NAME, lastof(buf));         // ^Continued
+	if (strcmp(buf, company_profile.company_name) != 0) {  // Compare local and loaded
+		if (!DoCommandP(0, 0, 0, CMD_RENAME_COMPANY, NULL, company_profile.company_name)) return STR_ERROR_CAN_T_CHANGE_COMPANY_NAME;
+	}
+
+	/* Set president face */
+	if (!IsValidCompanyManagerFace(company_profile.face) || !DoCommandP(0, 0, company_profile.face, CMD_SET_COMPANY_MANAGER_FACE)) return STR_PROFILE_FACE_ERROR;
+
+	/* Set livery */
+	for (int i = 0; i < LS_END; i++) {
+		if (!DoCommandP(0, i,            company_profile.livery[i].colour1, CMD_SET_COMPANY_COLOUR)) return STR_PROFILE_COLOUR_ERROR;
+		if (!DoCommandP(0, i | (1 << 8), company_profile.livery[i].colour2, CMD_SET_COMPANY_COLOUR)) return STR_PROFILE_COLOUR_ERROR;
+		if (!DoCommandP(0, i | (2 << 8), company_profile.livery[i].in_use,  CMD_SET_COMPANY_COLOUR)) return STR_PROFILE_COLOUR_ERROR;
+	}
+
+	return STR_NULL;
+
+}
+
+/**
+ * Load the company profile from the config
+ * @param company_profile CompanyProfile pointer to load into
+ * @return STR_NULL on success. STR_* on fail
+ */
+StringID CompanyLoadProfile(CompanyProfile &company_profile)
+{
+	IniFile  *ini;
+	IniGroup *group;
+	IniItem  *item;
+	char     buf[MAX_LENGTH_PRESIDENT_NAME_CHARS > MAX_LENGTH_COMPANY_NAME_CHARS ? MAX_LENGTH_PRESIDENT_NAME_CHARS : MAX_LENGTH_COMPANY_NAME_CHARS];
+	char     buf_ptr[16];
+	uint	 colour1,colour2;
+
+	sprintf(buf, "company_profile");
+
+	//CompanyProfile cp;
+	ini = IniLoadConfig();
+	group = ini->GetGroup(buf);
+	
+	/* Load president name */
+	item = group->GetItem("president_name", true);
+	if (item->value == NULL || strlen(item->value) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) return STR_PROFILE_LOAD_ERROR;
+	strcpy(company_profile.president_name, item->value);
+
+	/* Load company name */
+	item = group->GetItem("company_name", true);
+	if (item->value == NULL || strlen(item->value) >= MAX_LENGTH_COMPANY_NAME_CHARS) return STR_PROFILE_LOAD_ERROR;
+	strcpy(company_profile.company_name, item->value);
+
+	/* Load president face */
+	item = group->GetItem("face", true);
+	if (item->value == NULL || sscanf(item->value, "%u", &(company_profile.face)) != 1) return STR_PROFILE_LOAD_ERROR;
+	
+	/* Load livery */
+	for (int i = 0; i < LS_END; i++) {
+		sprintf(buf_ptr, "livery_%i", i);
+		item = group->GetItem(buf_ptr, true);
+		if (item->value == NULL) return STR_PROFILE_LOAD_ERROR;
+		sscanf(strtok(item->value, ","), "%u", &colour1);
+		sscanf(strtok(NULL,        ","), "%u", &colour2);
+		company_profile.livery[i].colour1 = (byte) colour1;
+		company_profile.livery[i].colour2 = (byte) colour2;
+		company_profile.livery[i].in_use  = strcmp(strtok(NULL, ","),"1") == 0 ? true : false;
+	}
+
+	return STR_NULL;
+}
+
+/**
+ * Save the company profile information to the config
+ * @param company_profile CompanyProfile to save
+ * @return STR_NULL on success. STR_PROFILE_SAVE_ERROR on fail
+ */
+StringID CompanySaveProfile(const CompanyProfile &company_profile)
+{
+	IniFile  *ini;
+	IniGroup *group;
+	char     buf[32];
+	char     buf_item[16];
+	char     buf_ptr[16];
+	
+	sprintf(buf, "company_profile");
+
+	ini = IniLoadConfig();	
+	ini->RemoveGroup(buf);
+	group = ini->GetGroup(buf);
+
+	group->GetItem("president_name", true)->SetValue(company_profile.president_name);
+	group->GetItem("company_name",   true)->SetValue(company_profile.company_name);
+
+	sprintf(buf, "%u", company_profile.face);
+	group->GetItem("face",           true)->SetValue(buf);
+
+	/* Save Livery */
+	for (int i = 0; i < LS_END; i++) {
+		sprintf(buf_item, "livery_%i", i);
+		sprintf(buf_ptr, "%u,%u,%u", uint(company_profile.livery[i].colour1), uint(company_profile.livery[i].colour2), uint(company_profile.livery[i].in_use));
+		group->GetItem(buf_item, true)->SetValue(buf_ptr);
+	}
+
+	StringID result = ini->SaveToDisk(_config_file) ? STR_NULL : STR_PROFILE_SAVE_ERROR;
+	delete ini;
+
+	return result;
+}
+
+/**
  * Set a setting value with a string.
  * @param index the settings index.
  * @param value the value to write
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -52,6 +52,8 @@
 
 static const StringID _autosave_dropdown[] = {
 	STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
+	STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_DAY,
+	STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_WEEK,
 	STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH,
 	STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS,
 	STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS,
@@ -684,7 +686,7 @@
 		uint i;
 		const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + widget;
 		int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
-		SetDParam(0, sd->desc.val_str + value);
+		SetDParam(0, sd->desc.str + value);
 	}
 
 	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
@@ -702,7 +704,7 @@
 		/* Get the string and try all strings from the smallest to the highest value */
 		StringID str = this->GetWidget<NWidgetCore>(widget)->widget_data;
 		for (int32 value = sdb->min; (uint32)value <= sdb->max; value += sdb->interval) {
-			SetDParam(0, sdb->val_str + value);
+			SetDParam(0, sdb->str + value);
 			*size = maxdim(*size, GetStringBoundingBox(str));
 		}
 	}
@@ -1257,7 +1259,7 @@
 			if (sdb->flags & SGF_CURRENCY) {
 				SetDParam(0, STR_JUST_CURRENCY);
 			} else if (sdb->flags & SGF_MULTISTRING) {
-				SetDParam(0, sdb->val_str - sdb->min + value);
+				SetDParam(0, sdb->str - sdb->min + value + 1);
 			} else {
 				SetDParam(0, (sdb->flags & SGF_NOCOMMA) ? STR_JUST_INT : STR_JUST_COMMA);
 			}
@@ -1350,14 +1352,17 @@
 
 
 static SettingEntry _settings_ui_display[] = {
+	SettingEntry("gui.vehicle_speed"),
 	SettingEntry("gui.date_format_in_default_names"),
 	SettingEntry("gui.population_in_label"),
+	SettingEntry("gui.population_in_label_coloured"),
 	SettingEntry("gui.measure_tooltip"),
 	SettingEntry("gui.loading_indicators"),
 	SettingEntry("gui.liveries"),
 	SettingEntry("gui.show_track_reservation"),
 	SettingEntry("gui.expenses_layout"),
 	SettingEntry("gui.smallmap_land_colour"),
+	SettingEntry("gui.smallmap_flood_warning"),
 };
 /** Display options sub-page */
 static SettingsPage _settings_ui_display_page = {_settings_ui_display, lengthof(_settings_ui_display)};
@@ -1384,9 +1389,29 @@
 /** Interaction sub-page */
 static SettingsPage _settings_ui_interaction_page = {_settings_ui_interaction, lengthof(_settings_ui_interaction)};
 
+static SettingEntry _settings_ui_departureboards[] = {
+	SettingEntry("gui.max_departures"),
+	SettingEntry("gui.max_departure_time"),
+	SettingEntry("gui.departure_calc_frequency"),
+	SettingEntry("gui.departure_show_vehicle"),
+	SettingEntry("gui.departure_show_group"),
+	SettingEntry("gui.departure_show_company"),
+	SettingEntry("gui.departure_show_vehicle_type"),
+	SettingEntry("gui.departure_show_vehicle_color"),
+	SettingEntry("gui.departure_larger_font"),
+	SettingEntry("gui.departure_destination_type"),
+	SettingEntry("gui.departure_show_both"),
+	SettingEntry("gui.departure_only_passengers"),
+	SettingEntry("gui.departure_conditionals"),
+	SettingEntry("gui.departure_show_all_stops"),
+};
+/** Departureboards sub-page */
+static SettingsPage _settings_ui_departureboards_page = {_settings_ui_departureboards, lengthof(_settings_ui_departureboards)};
+
 static SettingEntry _settings_ui[] = {
 	SettingEntry(&_settings_ui_display_page, STR_CONFIG_SETTING_DISPLAY_OPTIONS),
 	SettingEntry(&_settings_ui_interaction_page, STR_CONFIG_SETTING_INTERACTION),
+	SettingEntry(&_settings_ui_departureboards_page, STR_CONFIG_SETTING_DEPARTUREBOARDS),
 	SettingEntry("gui.show_finances"),
 	SettingEntry("gui.errmsg_duration"),
 	SettingEntry("gui.hover_delay"),
@@ -1396,6 +1421,9 @@
 	SettingEntry("gui.pause_on_newgame"),
 	SettingEntry("gui.advanced_vehicle_list"),
 	SettingEntry("gui.timetable_in_ticks"),
+	SettingEntry("gui.time_in_minutes"),
+	SettingEntry("gui.ticks_per_minute"),
+	SettingEntry("gui.date_with_time"),
 	SettingEntry("gui.timetable_arrival_departure"),
 	SettingEntry("gui.quick_goto"),
 	SettingEntry("gui.default_rail_type"),
@@ -1413,12 +1441,26 @@
 	SettingEntry("gui.semaphore_build_before"),
 	SettingEntry("gui.default_signal_type"),
 	SettingEntry("gui.cycle_signal_types"),
+	SettingEntry("construction.maximum_signal_evaluations"),
 };
 /** Signals subpage */
 static SettingsPage _settings_construction_signals_page = {_settings_construction_signals, lengthof(_settings_construction_signals)};
 
+static SettingEntry _settings_construction_trafficlights[] = {
+	SettingEntry("construction.traffic_lights"),
+	SettingEntry("construction.towns_build_traffic_lights"),
+	SettingEntry("construction.allow_building_tls_in_towns"),
+	SettingEntry("construction.traffic_lights_green_phase"),
+	SettingEntry("construction.max_tlc_size"),
+	SettingEntry("construction.max_tlc_distance"),
+};
+/** Traffic lights subpage */
+static SettingsPage _settings_construction_trafficlights_page = {_settings_construction_trafficlights, lengthof(_settings_construction_trafficlights)};
+
 static SettingEntry _settings_construction[] = {
 	SettingEntry(&_settings_construction_signals_page, STR_CONFIG_SETTING_CONSTRUCTION_SIGNALS),
+	SettingEntry(&_settings_construction_trafficlights_page, STR_CONFIG_SETTING_CONSTRUCTION_TRAFFIC_LIGHTS),
+	SettingEntry("construction.allow_more_heightlevels"),
 	SettingEntry("construction.build_on_slopes"),
 	SettingEntry("construction.autoslope"),
 	SettingEntry("construction.extra_dynamite"),
@@ -1427,7 +1469,11 @@
 	SettingEntry("station.never_expire_airports"),
 	SettingEntry("construction.freeform_edges"),
 	SettingEntry("construction.extra_tree_placement"),
+	SettingEntry("construction.tree_placement_drag_limit"),
 	SettingEntry("construction.command_pause_level"),
+	SettingEntry("construction.ingame_tree_line_height"),
+	SettingEntry("construction.tree_growth_rate"),
+	SettingEntry("gui.cp_paste_speed"),
 };
 /** Construction sub-page */
 static SettingsPage _settings_construction_page = {_settings_construction, lengthof(_settings_construction)};
@@ -1463,8 +1509,13 @@
 	SettingEntry("economy.found_town"),
 	SettingEntry("economy.mod_road_rebuild"),
 	SettingEntry("economy.town_growth_rate"),
+	SettingEntry("economy.town_growth_cargo"),
+	SettingEntry("economy.town_pop_need_goods"),
+	SettingEntry("economy.larger_town_growth_cargo"),
+	SettingEntry("economy.larger_town_pop_need_goods"),
 	SettingEntry("economy.larger_towns"),
 	SettingEntry("economy.initial_city_size"),
+	SettingEntry("economy.town_cargo_factor"),
 };
 /** Towns sub-page */
 static SettingsPage _settings_economy_towns_page = {_settings_economy_towns, lengthof(_settings_economy_towns)};
@@ -1472,6 +1523,7 @@
 static SettingEntry _settings_economy_industries[] = {
 	SettingEntry("construction.raw_industry_construction"),
 	SettingEntry("construction.industry_platform"),
+	SettingEntry("construction.extra_industry_placement_logic"),
 	SettingEntry("economy.multiple_industry_per_town"),
 	SettingEntry("game_creation.oil_refinery_limit"),
 };
@@ -1484,10 +1536,28 @@
 	SettingEntry("economy.inflation"),
 	SettingEntry("economy.smooth_economy"),
 	SettingEntry("economy.feeder_payment_share"),
+	SettingEntry("daylength_factor"),
 };
 /** Economy sub-page */
 static SettingsPage _settings_economy_page = {_settings_economy, lengthof(_settings_economy)};
 
+static SettingEntry _settings_linkgraph[] = {
+	SettingEntry("linkgraph.recalc_interval"),
+	SettingEntry("linkgraph.distribution_pax"),
+	SettingEntry("linkgraph.distribution_mail"),
+	SettingEntry("linkgraph.distribution_express"),
+	SettingEntry("linkgraph.distribution_armoured"),
+	SettingEntry("linkgraph.distribution_default"),
+	SettingEntry("linkgraph.accuracy"),
+	SettingEntry("linkgraph.demand_distance"),
+	SettingEntry("linkgraph.demand_size"),
+	SettingEntry("linkgraph.short_path_saturation"),
+	SettingEntry("linkgraph.no_overload_links"),
+	SettingEntry("gui.linkgraph_companies"),
+};
+/** Linkgraph sub-page */
+static SettingsPage _settings_linkgraph_page = {_settings_linkgraph, lengthof(_settings_linkgraph)};
+
 static SettingEntry _settings_ai_npc[] = {
 	SettingEntry("ai.ai_in_multiplayer"),
 	SettingEntry("ai.ai_disable_veh_train"),
@@ -1499,8 +1569,23 @@
 /** Computer players sub-page */
 static SettingsPage _settings_ai_npc_page = {_settings_ai_npc, lengthof(_settings_ai_npc)};
 
+static SettingEntry _settings_sharing[] = {
+	SettingEntry("economy.infrastructure_sharing[0]"),
+	SettingEntry("economy.infrastructure_sharing[1]"),
+	SettingEntry("economy.infrastructure_sharing[2]"),
+	SettingEntry("economy.infrastructure_sharing[3]"),
+	SettingEntry("economy.sharing_fee[0]"),
+	SettingEntry("economy.sharing_fee[1]"),
+	SettingEntry("economy.sharing_fee[2]"),
+	SettingEntry("economy.sharing_fee[3]"),
+	SettingEntry("economy.sharing_payment_in_debt"),
+};
+/** Infrastructure sharing sub-page */
+static SettingsPage _settings_sharing_page = {_settings_sharing, lengthof(_settings_sharing)};
+
 static SettingEntry _settings_ai[] = {
 	SettingEntry(&_settings_ai_npc_page, STR_CONFIG_SETTING_AI_NPC),
+	SettingEntry(&_settings_sharing_page, STR_CONFIG_SETTING_SHARING),
 	SettingEntry("economy.give_money"),
 	SettingEntry("economy.allow_shares"),
 };
@@ -1510,6 +1595,7 @@
 static SettingEntry _settings_vehicles_routing[] = {
 	SettingEntry("pf.pathfinder_for_trains"),
 	SettingEntry("pf.forbid_90_deg"),
+	SettingEntry("pf.back_of_one_way_pbs_waiting_point"),
 	SettingEntry("pf.pathfinder_for_roadvehs"),
 	SettingEntry("pf.roadveh_queue"),
 	SettingEntry("pf.pathfinder_for_ships"),
@@ -1533,6 +1619,7 @@
 	SettingEntry("vehicle.servint_aircraft"),
 	SettingEntry("order.no_servicing_if_no_breakdowns"),
 	SettingEntry("order.serviceathelipad"),
+	SettingEntry("vehicle.improved_breakdowns"),
 };
 /** Servicing sub-page */
 static SettingsPage _settings_vehicles_servicing_page = {_settings_vehicles_servicing, lengthof(_settings_vehicles_servicing)};
@@ -1555,6 +1642,7 @@
 	SettingEntry(&_settings_vehicles_autorenew_page, STR_CONFIG_SETTING_VEHICLES_AUTORENEW),
 	SettingEntry(&_settings_vehicles_servicing_page, STR_CONFIG_SETTING_VEHICLES_SERVICING),
 	SettingEntry(&_settings_vehicles_trains_page, STR_CONFIG_SETTING_VEHICLES_TRAINS),
+	SettingEntry("order.gotodepot"),
 	SettingEntry("gui.new_nonstop"),
 	SettingEntry("gui.order_review_system"),
 	SettingEntry("gui.vehicle_income_warn"),
@@ -1566,6 +1654,8 @@
 	SettingEntry("vehicle.max_ships"),
 	SettingEntry("vehicle.plane_speed"),
 	SettingEntry("vehicle.plane_crashes"),
+	SettingEntry("order.timetable_separation"),
+	SettingEntry("order.timetabling"),
 	SettingEntry("vehicle.dynamic_engines"),
 	SettingEntry("vehicle.roadveh_acceleration_model"),
 	SettingEntry("vehicle.roadveh_slope_steepness"),
@@ -1580,6 +1670,7 @@
 	SettingEntry(&_settings_vehicles_page,     STR_CONFIG_SETTING_VEHICLES),
 	SettingEntry(&_settings_stations_page,     STR_CONFIG_SETTING_STATIONS),
 	SettingEntry(&_settings_economy_page,      STR_CONFIG_SETTING_ECONOMY),
+	SettingEntry(&_settings_linkgraph_page,    STR_CONFIG_SETTING_LINKGRAPH),
 	SettingEntry(&_settings_ai_page,           STR_CONFIG_SETTING_AI),
 };
 
diff --git a/src/settings_internal.h b/src/settings_internal.h
--- a/src/settings_internal.h
+++ b/src/settings_internal.h
@@ -69,7 +69,6 @@
 	int32 interval;         ///< the interval to use between settings in the 'settings' window. If interval is '0' the interval is dynamically determined
 	const char *many;       ///< ONE/MANY_OF_MANY: string of possible values for this type
 	StringID str;           ///< (translated) string with descriptive text; gui and console
-	StringID val_str;       ///< (translated) first string describing the value.
 	OnChange *proc;         ///< callback procedure for when the value is changed
 	OnConvert *proc_cnvt;   ///< callback procedure when loading value mechanism fails
 };
diff --git a/src/settings_type.h b/src/settings_type.h
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -18,6 +18,8 @@
 #include "network/core/config.h"
 #include "company_type.h"
 #include "openttd.h"
+#include "cargotype.h"
+#include "linkgraph/linkgraph_type.h"
 
 /** Available industry map generation densities. */
 enum IndustryDensity {
@@ -54,6 +56,7 @@
 
 /** Settings related to the GUI and other stuff that is not saved in the savegame. */
 struct GUISettings {
+	bool   vehicle_speed;                    ///< show vehicle speed
 	bool   sg_full_load_any;                 ///< new full load calculation, any cargo must be full read from pre v93 savegames
 	bool   lost_vehicle_warn;                ///< if a vehicle can't find its destination, show a warning
 	uint8  order_review_system;              ///< perform order reviews on vehicles
@@ -67,6 +70,8 @@
 	byte   hover_delay;                      ///< time required to activate a hover event, in seconds
 	bool   link_terraform_toolbar;           ///< display terraform toolbar when displaying rail, road, water and airport toolbars
 	uint8  smallmap_land_colour;             ///< colour used for land and heightmap at the smallmap
+	bool   smallmap_flood_warning;           ///< wether to show the flood warning colour or not
+	uint8  linkgraph_companies;              ///< Wether to show the linkgraps for all companies or not in the smallmap.
 	bool   reverse_scroll;                   ///< right-Click-Scrolling scrolls in the opposite direction
 	bool   smooth_scroll;                    ///< smooth scroll viewports
 	bool   measure_tooltip;                  ///< show a permanent tooltip when dragging tools
@@ -87,16 +92,35 @@
 	uint8  date_format_in_default_names;     ///< should the default savegame/screenshot name use long dates (31th Dec 2008), short dates (31-12-2008) or ISO dates (2008-12-31)
 	byte   max_num_autosaves;                ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1)
 	bool   population_in_label;              ///< show the population of a town in his label?
+	bool   population_in_label_coloured;     ///< show the population of a town in his label?
 	uint8  right_mouse_btn_emulation;        ///< should we emulate right mouse clicking?
 	uint8  scrollwheel_scrolling;            ///< scrolling using the scroll wheel?
 	uint8  scrollwheel_multiplier;           ///< how much 'wheel' per incoming event from the OS?
 	bool   timetable_arrival_departure;      ///< show arrivals and departures in vehicle timetables
+	uint8  max_departures;                   ///< maximum number of departures to show per station
+	uint16 max_departure_time;               ///< maximum time in advance to show departures
+	uint16 departure_calc_frequency;         ///< how often to calculate departures (in ticks)
+	bool   departure_show_vehicle;           ///< whether to show vehicle names with departures
+	bool   departure_show_group;             ///< whether to show group names with departures
+	bool   departure_show_company;           ///< whether to show company names with departures
+	bool   departure_show_vehicle_type;      ///< whether to show vehicle type icons with departures
+	bool   departure_show_vehicle_color;     ///< whether to show vehicle type icons in silver instead of orange
+	bool   departure_larger_font;            ///< whether to show the calling at list in a larger font
+	bool   departure_destination_type;       ///< whether to show destination types for ports and airports
+	bool   departure_show_both;              ///< whether to show departure and arrival times on the same line
+	bool   departure_only_passengers;        ///< whether to only show passenger services
+	uint8  departure_conditionals;           ///< how to handle conditional orders
+	bool   departure_show_all_stops;         ///< whether to show stops regardless of loading/unloading done at them
 	bool   left_mouse_btn_scrolling;         ///< left mouse button scroll
 	bool   pause_on_newgame;                 ///< whether to start new games paused or not
 	bool   enable_signal_gui;                ///< show the signal GUI when the signal button is pressed
 	Year   coloured_news_year;               ///< when does newspaper become coloured?
 	bool   timetable_in_ticks;               ///< whether to show the timetable in ticks rather than days
+	bool   time_in_minutes;                  ///< whether to use the hh:mm conversion when printing dates
+	uint8  ticks_per_minute;                 ///< how many ticks per minute
+	uint8  date_with_time;                   ///< whether to show the month and year with the time
 	bool   quick_goto;                       ///< Allow quick access to 'goto button' in vehicle orders window
+	bool   bridge_pillars;                   ///< show bridge pillars for high bridges
 	bool   auto_euro;                        ///< automatically switch to euro in 2002
 	byte   drag_signals_density;             ///< many signals density
 	Year   semaphore_build_before;           ///< build semaphore signals automatically before this year
@@ -115,6 +139,10 @@
 
 	uint16 console_backlog_timeout;          ///< the minimum amount of time items should be in the console backlog before they will be removed in ~3 seconds granularity.
 	uint16 console_backlog_length;           ///< the minimum amount of items in the console backlog before items will be removed.
+
+	uint8  station_gui_group_order;          ///< the order of grouping cargo entries in the station gui
+	uint8  station_gui_sort_by;              ///< sort cargo entries in the station gui by station name or amount
+	uint8  station_gui_sort_order;           ///< the sort order of entries in the station gui - ascending or descending
 #ifdef ENABLE_NETWORK
 	uint16 network_chat_box_width;           ///< width of the chat box in pixels
 	uint8  network_chat_box_height;          ///< height of the chat box in lines
@@ -128,6 +156,7 @@
 	bool   scenario_developer;               ///< activate scenario developer: allow modifying NewGRFs in an existing game
 	bool   newgrf_show_old_versions;         ///< whether to show old versions in the NewGRF list
 	uint8  newgrf_default_palette;           ///< default palette to use for NewGRFs without action 14 palette information
+	uint8  cp_paste_speed;                   ///< paste speed in multiplayer games (ticks between pastes)
 
 	/**
 	 * Returns true when the user has sufficient privileges to edit newgrfs on a running game
@@ -139,17 +168,6 @@
 	}
 };
 
-/** Settings related to music. */
-struct MusicSettings {
-	byte playlist;     ///< The playlist (number) to play
-	byte music_vol;    ///< The requested music volume
-	byte effect_vol;   ///< The requested effects volume
-	byte custom_1[33]; ///< The order of the first custom playlist
-	byte custom_2[33]; ///< The order of the second custom playlist
-	bool playing;      ///< Whether music is playing
-	bool shuffle;      ///< Whether to shuffle the music
-};
-
 /** Settings related to currency/unit systems. */
 struct LocaleSettings {
 	byte   currency;                         ///< currency we currently use
@@ -227,6 +245,7 @@
 
 /** Settings related to construction in-game */
 struct ConstructionSettings {
+	bool   allow_more_heightlevels;          ///< allow more than just 16 heightlevels
 	bool   build_on_slopes;                  ///< allow building on slopes
 	bool   autoslope;                        ///< allow terraforming under things
 	uint16 max_bridge_length;                ///< maximum length of bridges
@@ -239,12 +258,22 @@
 	uint8  industry_platform;                ///< the amount of flat land around an industry
 	bool   freeform_edges;                   ///< allow terraforming the tiles at the map edges
 	uint8  extra_tree_placement;             ///< (dis)allow building extra trees in-game
+	uint8  tree_placement_drag_limit;        ///< how many tiles can be filled by trees at once by player?
 	uint8  command_pause_level;              ///< level/amount of commands that can't be executed while paused
-
 	uint32 terraform_per_64k_frames;         ///< how many tile heights may, over a long period, be terraformed per 65536 frames?
 	uint16 terraform_frame_burst;            ///< how many tile heights may, over a short period, be terraformed?
 	uint32 clear_per_64k_frames;             ///< how many tiles may, over a long period, be cleared per 65536 frames?
 	uint16 clear_frame_burst;                ///< how many tiles may, over a short period, be cleared?
+	byte   ingame_tree_line_height;          ///< Allow building trees below this height ingame (Unrelated to the treeline when generation a map)
+	uint8  tree_growth_rate;                 ///< tree growth rate
+	uint16 maximum_signal_evaluations;       ///< maximum number of programmable signals which may be evaluated in one pass
+	bool traffic_lights;                     ///< Whether traffic lights are enabled.
+	bool towns_build_traffic_lights;         ///< Whether towns build traffic lights during road construction.
+	bool allow_building_tls_in_towns;        ///< Whether the players are allowed to build traffic lights on town owned roads.
+	uint8 traffic_lights_green_phase;        ///< How long traffic lights' green phase lasts.
+	uint8 max_tlc_size;                      ///< Maximum size for traffic light consists.
+	uint8 max_tlc_distance;                  ///< Maximum distance between traffic lights for synchronising them.
+	uint8 extra_industry_placement_logic;    ///< Maximum height below which we allow more then one heightlevel to be terraformed. (Needed for better industry placement with moreheightlevels enabled.)
 };
 
 /** Settings related to the AI. */
@@ -287,6 +316,7 @@
 	uint32 npf_road_curve_penalty;           ///< the penalty for curves
 	uint32 npf_crossing_penalty;             ///< the penalty for level crossings
 	uint32 npf_road_drive_through_penalty;   ///< the penalty for going through a drive-through road stop
+	uint32 npf_road_trafficlight_penalty;    ///< Penalty for junctions with traffic lights.
 	uint32 npf_road_dt_occupied_penalty;     ///< the penalty multiplied by the fill percentage of a drive-through road stop
 	uint32 npf_road_bay_occupied_penalty;    ///< the penalty multiplied by the fill percentage of a road bay
 };
@@ -303,6 +333,7 @@
 	uint32 road_curve_penalty;               ///< penalty for curves
 	uint32 road_crossing_penalty;            ///< penalty for level crossing
 	uint32 road_stop_penalty;                ///< penalty for going through a drive-through road stop
+	uint32 road_trafficlight_penalty;        ///< Penalty for junctions with traffic lights.	
 	uint32 road_stop_occupied_penalty;       ///< penalty multiplied by the fill percentage of a drive-through road stop
 	uint32 road_stop_bay_occupied_penalty;   ///< penalty multiplied by the fill percentage of a road bay
 	bool   rail_firstred_twoway_eol;         ///< treat first red two-way signal as dead end
@@ -352,6 +383,8 @@
 	OPFSettings  opf;                        ///< pathfinder settings for the old pathfinder
 	NPFSettings  npf;                        ///< pathfinder settings for the new pathfinder
 	YAPFSettings yapf;                       ///< pathfinder settings for the yet another pathfinder
+
+	bool back_of_one_way_pbs_waiting_point;  ///< whether the back of a one way signal a safe waiting point
 };
 
 /** Settings related to orders. */
@@ -359,7 +392,11 @@
 	bool   improved_load;                    ///< improved loading algorithm
 	bool   gradual_loading;                  ///< load vehicles gradually
 	bool   selectgoods;                      ///< only send the goods to station if a train has been there
+	bool   gotodepot;                        ///< allow goto depot in orders
 	bool   no_servicing_if_no_breakdowns;    ///< dont send vehicles to depot when breakdowns are disabled
+	bool   timetabling;                      ///< whether to allow timetabling
+	bool   timetable_automated;              ///< whether to automatically manage timetables
+	bool   timetable_separation;             ///< whether to perform automatic separation based on timetable.
 	bool   serviceathelipad;                 ///< service helicopters at helipads automatically (no need to send to depot)
 };
 
@@ -384,6 +421,7 @@
 	byte   extend_vehicle_life;              ///< extend vehicle life by this many years
 	byte   road_side;                        ///< the side of the road vehicles drive on
 	uint8  plane_crashes;                    ///< number of plane crashes, 0 = none, 1 = reduced, 2 = normal
+	bool   improved_breakdowns;	             ///< Different types, chances and serverities of breakdowns.
 };
 
 /** Settings related to the economy. */
@@ -402,12 +440,48 @@
 	uint8  town_growth_rate;                 ///< town growth rate
 	uint8  larger_towns;                     ///< the number of cities to build. These start off larger and grow twice as fast
 	uint8  initial_city_size;                ///< multiplier for the initial size of the cities compared to towns
+	uint8  town_growth_cargo;                ///< Whether to base town growth on transported passenger/mail/goods or not.
+	uint32 town_pop_need_goods;              ///< The town population limit before needing goods for growth
+	uint8  larger_town_growth_cargo;         ///< Whether to base city growth on transported passenger/mail/goods or not.
+	uint32 larger_town_pop_need_goods;       ///< The city population limit before needing goods for growth
 	TownLayoutByte town_layout;              ///< select town layout, @see TownLayout
 	bool   allow_town_roads;                 ///< towns are allowed to build roads (always allowed when generating world / in SE)
 	TownFoundingByte found_town;             ///< town founding, @see TownFounding
 	bool   station_noise_level;              ///< build new airports when the town noise level is still within accepted limits
 	uint16 town_noise_population[3];         ///< population to base decision on noise evaluation (@see town_council_tolerance)
 	bool   allow_town_level_crossings;       ///< towns are allowed to build level crossings
+	int8   town_cargo_factor;                ///< power-of-two multiplier for town (passenger, mail) generation. May be negative.
+	bool   infrastructure_sharing[4];        ///< enable infrastructure sharing for rail/road/water/air
+	uint   sharing_fee[4];                   ///< fees for infrastructure sharing for rail/road/water/air
+	bool   sharing_payment_in_debt;          ///< allow fee payment for companies with more loan than money (switch off to prevent MP exploits)
+};
+
+struct LinkGraphSettings {
+	uint16 recalc_interval;                     ///< minimum interval (in days) between subsequent calculations of components in the same link graph
+	DistributionTypeByte distribution_pax;      ///< distribution type for passengers
+	DistributionTypeByte distribution_mail;     ///< distribution type for mail
+	DistributionTypeByte distribution_express;  ///< distribution type for express cargo class
+	DistributionTypeByte distribution_armoured; ///< distribution type for armoured cargo class
+	DistributionTypeByte distribution_default;  ///< distribution type for all other goods
+	uint8 accuracy;                             ///< accuracy when calculating things on the link graph. low accuracy => low running time
+	uint8 demand_size;                          ///< influence of supply ("station size") on the demand function
+	uint8 demand_distance;                      ///< influence of distance between stations on the demand function
+	uint8 short_path_saturation;                ///< percentage up to which short paths are saturated before saturating most capacious paths
+	bool no_overload_links;                     ///< if true, try to stop planned flows exceeding links' capacities
+
+	FORCEINLINE DistributionType GetDistributionType(CargoID cargo) const {
+		if (IsCargoInClass(cargo, CC_PASSENGERS)) {
+			return this->distribution_pax;
+		} else if (IsCargoInClass(cargo, CC_MAIL)) {
+			return this->distribution_mail;
+		} else if (IsCargoInClass(cargo, CC_EXPRESS)) {
+			return this->distribution_express;
+		} else if (IsCargoInClass(cargo, CC_ARMOURED)) {
+			return this->distribution_armoured;
+		} else {
+			return this->distribution_default;
+		}
+	}
 };
 
 /** Settings related to stations. */
@@ -448,6 +522,7 @@
 	OrderSettings        order;              ///< settings related to orders
 	VehicleSettings      vehicle;            ///< options for vehicles
 	EconomySettings      economy;            ///< settings to change the economy
+	LinkGraphSettings    linkgraph;          ///< settings for link graph calculations
 	StationSettings      station;            ///< settings related to station management
 	LocaleSettings       locale;             ///< settings related to used currency/unit system in the current game
 };
@@ -457,7 +532,6 @@
 	GUISettings          gui;                ///< settings related to the GUI
 	NetworkSettings      network;            ///< settings related to the network
 	CompanySettings      company;            ///< default values for per-company settings
-	MusicSettings        music;              ///< settings related to music/sound
 };
 
 /** The current settings for this game. */
diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -127,7 +127,7 @@
 
 	FOR_ALL_DEPOTS(depot) {
 		TileIndex tile = depot->xy;
-		if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
+		if (IsShipDepotTile(tile) && IsInfraTileUsageAllowed(VEH_SHIP, v->owner, tile)) {
 			uint dist = DistanceManhattan(tile, v->tile);
 			if (dist < best_dist) {
 				best_dist = dist;
@@ -343,10 +343,24 @@
 
 	spd = min(v->cur_speed + 1, v->vcache.cached_max_speed);
 
+	if(v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_POWER && v->cur_speed > (v->breakdown_severity * ShipVehInfo(v->engine_type)->max_speed) >> 8) {
+		if((v->tick_counter & 0x7) == 0 && v->cur_speed > 0) {
+			spd = v->cur_speed - 1;
+		} else {
+			spd = v->cur_speed;
+		}
+	}
+
+	if(v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_SPEED) {
+		spd = min(spd, v->breakdown_severity);
+	}
+
 	/* updates statusbar only if speed have changed to save CPU time */
 	if (spd != v->cur_speed) {
 		v->cur_speed = spd;
-		SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
+		if (_settings_client.gui.vehicle_speed) {
+			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
+		}
 	}
 
 	/* Convert direction-indepenent speed into direction-dependent speed. (old movement method) */
@@ -629,6 +643,27 @@
 CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
 {
 	tile = GetShipDepotNorthTile(tile);
+	UnitID unit_num;
+
+	if (!IsEngineBuildable(e->index, VEH_SHIP, _current_company)) return_cmd_error(STR_ERROR_SHIP_NOT_AVAILABLE);
+
+	CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost());
+
+	/* Engines without valid cargo should not be available */
+	if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR;
+
+	if (flags & DC_QUERY_COST) return value;
+
+	/* The ai_new queries the vehicle cost before building the route,
+	 * so we must check against cheaters no sooner than now. --pasky */
+	if (!IsShipDepotTile(tile)) return CMD_ERROR;
+	if (!IsInfraUsageAllowed(VEH_SHIP, _current_company, GetTileOwner(tile))) return CMD_ERROR;
+
+	unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_SHIP);
+
+	if (!Vehicle::CanAllocateItem() || unit_num > _settings_game.vehicle.max_ships)
+		return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
+
 	if (flags & DC_EXEC) {
 		int x;
 		int y;
@@ -654,10 +689,13 @@
 		v->cargo_cap = svi->capacity;
 
 		v->last_station_visited = INVALID_STATION;
+		v->last_loading_station = INVALID_STATION;
+
 		v->engine_type = e->index;
 
 		v->reliability = e->reliability;
 		v->reliability_spd_dec = e->reliability_spd_dec;
+		v->breakdown_chance = 64; // Ships have a 50% lower breakdown chance than normal.
 		v->max_age = e->GetLifeLengthInDays();
 		_new_vehicle_id = v->index;
 
diff --git a/src/signal.cpp b/src/signal.cpp
--- a/src/signal.cpp
+++ b/src/signal.cpp
@@ -17,7 +17,22 @@
 #include "viewport_func.h"
 #include "train.h"
 #include "company_base.h"
+#include "gui.h"
+#include "table/strings.h"
+#include "programmable_signals.h"
+#include "infrastructure_func.h"
 
+/** List of signals dependent upon this one */
+typedef SmallVector<SignalReference, 4>     SignalDependencyList;
+
+/**
+ * Map of dependencies. The key identifies the signal,
+ * the value is a list of all of the signals which depend upon that signal.
+ */
+typedef std::map<SignalReference, SignalDependencyList> SignalDependencyMap;
+
+static SignalDependencyMap _signal_dependencies;
+static void MarkDependencidesForUpdate(SignalReference sig);
 
 /** these are the maximums used for updating signal blocks */
 static const uint SIG_TBU_SIZE    =  64; ///< number of signals entering to block
@@ -185,7 +200,7 @@
 static SmallSet<Trackdir, SIG_TBU_SIZE> _tbuset("_tbuset");         ///< set of signals that will be updated
 static SmallSet<DiagDirection, SIG_TBD_SIZE> _tbdset("_tbdset");    ///< set of open nodes in current signal block
 static SmallSet<DiagDirection, SIG_GLOB_SIZE> _globset("_globset"); ///< set of places to be updated in following runs
-
+static uint _num_signals_evaluated;                                 ///< Number of programmable signals evaluated
 
 /** Check whether there is a train on rail, not in a depot */
 static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
@@ -195,7 +210,6 @@
 	return v;
 }
 
-
 /**
  * Perform some operations before adding data into Todo set
  * The new and reverse direction is removed from _globset, because we are sure
@@ -221,6 +235,14 @@
 	return true;
 }
 
+/** Check whether there is a train only on ramp */
+static Vehicle *TrainInWormholeTileEnum(Vehicle *v, void *data)
+{
+	/* Only look for front engine or last wagon */
+	if (v->type != VEH_TRAIN || (v->Previous() != NULL && v->Next() != NULL)) return NULL;
+	if (*(TileIndex *)data != TileVirtXY(v->x_pos, v->y_pos)) return NULL;
+	return v;
+}
 
 /**
  * Perform some operations before adding data into Todo set
@@ -245,18 +267,25 @@
 
 /** Current signal block state flags */
 enum SigFlags {
-	SF_NONE   = 0,
-	SF_TRAIN  = 1 << 0, ///< train found in segment
-	SF_EXIT   = 1 << 1, ///< exitsignal found
-	SF_EXIT2  = 1 << 2, ///< two or more exits found
-	SF_GREEN  = 1 << 3, ///< green exitsignal found
-	SF_GREEN2 = 1 << 4, ///< two or more green exits found
-	SF_FULL   = 1 << 5, ///< some of buffers was full, do not continue
-	SF_PBS    = 1 << 6, ///< pbs signal found
+	SF_NONE  = 0,
+	SF_TRAIN = 1 << 0, ///< train found in segment
+	SF_FULL  = 1 << 1, ///< some of buffers was full, do not continue
+	SF_PBS   = 1 << 2, ///< pbs signal found
 };
 
 DECLARE_ENUM_AS_BIT_SET(SigFlags)
 
+struct SigInfo {
+	inline SigInfo()
+	{
+		flags = SF_NONE;
+		num_exits = 0;
+		num_green = 0;
+	}
+	SigFlags flags;
+	uint num_exits;
+	uint num_green;
+};
 
 /**
  * Search signal block
@@ -264,10 +293,9 @@
  * @param owner owner whose signals we are updating
  * @return SigFlags
  */
-static SigFlags ExploreSegment(Owner owner)
+static SigInfo ExploreSegment(Owner owner)
 {
-	SigFlags flags = SF_NONE;
-
+	SigInfo info;
 	TileIndex tile;
 	DiagDirection enterdir;
 
@@ -277,17 +305,17 @@
 
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY: {
-				if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing)
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 
 				if (IsRailDepot(tile)) {
 					if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
-						if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
+						if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
 						exitdir = GetRailDepotDirection(tile);
 						tile += TileOffsByDiagDir(exitdir);
 						enterdir = ReverseDiagDir(exitdir);
 						break;
 					} else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot
-						if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
+						if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
 						continue;
 					} else {
 						continue;
@@ -300,15 +328,15 @@
 				if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one incidating track, no need to check
 					tracks = tracks_masked;
 					/* If no train detected yet, and there is not no train -> there is a train -> set the flag */
-					if (!(flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags |= SF_TRAIN;
+					if (!(info.flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) info.flags |= SF_TRAIN;
 				} else {
 					if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
-					if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
+					if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
 				}
 
 				if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
 					Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
-					if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir
+					if (HasSignalOnTrack(tile, track) && !IsSpeedSignal(GetSignalType(tile, track))) { // now check whole track, not trackdir
 						SignalType sig = GetSignalType(tile, track);
 						Trackdir trackdir = (Trackdir)FindFirstBit((tracks * 0x101) & _enterdir_to_trackdirbits[enterdir]);
 						Trackdir reversedir = ReverseTrackdir(trackdir);
@@ -317,20 +345,19 @@
 						 * (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */
 						if (HasSignalOnTrackdir(tile, reversedir)) {
 							if (IsPbsSignal(sig)) {
-								flags |= SF_PBS;
+								info.flags |= SF_PBS;
 							} else if (!_tbuset.Add(tile, reversedir)) {
-								return flags | SF_FULL;
+								info.flags |= SF_FULL;
+								return info;
 							}
 						}
-						if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags |= SF_PBS;
+						if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) info.flags |= SF_PBS;
 
-						/* if it is a presignal EXIT in OUR direction and we haven't found 2 green exits yes, do special check */
-						if (!(flags & SF_GREEN2) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit
-							if (flags & SF_EXIT) flags |= SF_EXIT2; // found two (or more) exits
-							flags |= SF_EXIT; // found at least one exit - allow for compiler optimizations
+						/* if it is a presignal EXIT in OUR direction, count it */
+						if (IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit
+							info.num_exits++;
 							if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { // found green presignal exit
-								if (flags & SF_GREEN) flags |= SF_GREEN2;
-								flags |= SF_GREEN;
+								info.num_green++;
 							}
 						}
 
@@ -342,7 +369,10 @@
 					if (dir != enterdir && (tracks & _enterdir_to_trackbits[dir])) { // any track incidating?
 						TileIndex newtile = tile + TileOffsByDiagDir(dir);  // new tile to check
 						DiagDirection newdir = ReverseDiagDir(dir); // direction we are entering from
-						if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SF_FULL;
+						if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) {
+							info.flags |= SF_FULL;
+							return info;
+						}
 					}
 				}
 
@@ -351,51 +381,76 @@
 
 			case MP_STATION:
 				if (!HasStationRail(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
 				if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
 
-				if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
+				if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
 				tile += TileOffsByDiagDir(exitdir);
 				break;
 
 			case MP_ROAD:
 				if (!IsLevelCrossing(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
 
-				if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
+				if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
 				tile += TileOffsByDiagDir(exitdir);
 				break;
 
-			case MP_TUNNELBRIDGE: {
-				if (GetTileOwner(tile) != owner) continue;
-				if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
-				DiagDirection dir = GetTunnelBridgeDirection(tile);
+			case MP_TUNNELBRIDGE:
+				{
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
+					if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
+					DiagDirection dir;
+					dir = GetTunnelBridgeDirection(tile);
 
-				if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole
-					if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
-					enterdir = dir;
-					exitdir = ReverseDiagDir(dir);
-					tile += TileOffsByDiagDir(exitdir); // just skip to next tile
-				} else { // NOT incoming from the wormhole!
-					if (ReverseDiagDir(enterdir) != dir) continue;
-					if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
-					tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile
-					enterdir = INVALID_DIAGDIR;
-					exitdir = INVALID_DIAGDIR;
-				}
-				}
+					if (HasWormholeSignals(tile)) {
+						if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole
+							if (!(info.flags & SF_TRAIN) && IsTunnelBridgeExit(tile)) { // tunnel entrence is ignored
+								if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
+								if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
+							}
+							enterdir = dir;
+							exitdir = ReverseDiagDir(dir);
+							tile += TileOffsByDiagDir(exitdir); // just skip to next tile
+						} else { // NOT incoming from the wormhole!
+							if (ReverseDiagDir(enterdir) != dir) continue;
+							if (!(info.flags & SF_TRAIN)) {
+								if (HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
+								if (!(info.flags & SF_TRAIN) && IsTunnelBridgeExit(tile)) {
+									if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
+								} 
+							}
+							continue;
+						}
+					} else {
+						if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole
+							if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
+							enterdir = dir;
+							exitdir = ReverseDiagDir(dir);
+							tile += TileOffsByDiagDir(exitdir); // just skip to next tile
+						} else { // NOT incoming from the wormhole!
+							if (ReverseDiagDir(enterdir) != dir) continue;
+							if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
+							tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile
+							enterdir = INVALID_DIAGDIR;
+							exitdir = INVALID_DIAGDIR;
+						}
+					}
+ 				}
 				break;
 
 			default:
 				continue; // continue the while() loop
 		}
 
-		if (!MaybeAddToTodoSet(tile, enterdir, oldtile, exitdir)) return flags | SF_FULL;
+		if (!MaybeAddToTodoSet(tile, enterdir, oldtile, exitdir)) {
+			info.flags |= SF_FULL;
+		}
 	}
 
-	return flags;
+	return info;
 }
 
 
@@ -404,49 +459,74 @@
  *
  * @param flags info about segment
  */
-static void UpdateSignalsAroundSegment(SigFlags flags)
+static void UpdateSignalsAroundSegment(SigInfo info)
 {
 	TileIndex tile;
 	Trackdir trackdir;
+	Track track;
 
 	while (_tbuset.Get(&tile, &trackdir)) {
 		assert(HasSignalOnTrackdir(tile, trackdir));
 
-		SignalType sig = GetSignalType(tile, TrackdirToTrack(trackdir));
+		track = TrackdirToTrack(trackdir);
+		SignalType sig = GetSignalType(tile, track);
 		SignalState newstate = SIGNAL_STATE_GREEN;
 
 		/* determine whether the new state is red */
-		if (flags & SF_TRAIN) {
+		if (sig == SIGTYPE_SPEED) {
+			newstate = SIGNAL_STATE_GREEN;
+		} else if (info.flags & SF_TRAIN) {
 			/* train in the segment */
 			newstate = SIGNAL_STATE_RED;
+		} else if (sig == SIGTYPE_PROG && 
+				_num_signals_evaluated > _settings_game.construction.maximum_signal_evaluations) {
+			/* too many cascades */
+			newstate = SIGNAL_STATE_RED;
 		} else {
 			/* is it a bidir combo? - then do not count its other signal direction as exit */
-			if (sig == SIGTYPE_COMBO && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
-				/* at least one more exit */
-				if ((flags & SF_EXIT2) &&
-						/* no green exit */
-						(!(flags & SF_GREEN) ||
-						/* only one green exit, and it is this one - so all other exits are red */
-						(!(flags & SF_GREEN2) && GetSignalStateByTrackdir(tile, ReverseTrackdir(trackdir)) == SIGNAL_STATE_GREEN))) {
-					newstate = SIGNAL_STATE_RED;
+			if (IsComboSignal(sig) && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
+				// Don't count ourselves
+				uint exits = info.num_exits - 1;
+				uint green = info.num_green;
+				if (GetSignalStateByTrackdir(tile, ReverseTrackdir(trackdir)) == SIGNAL_STATE_GREEN)
+					green--;
+				
+				if (sig == SIGTYPE_PROG) { /* Programmable */
+					_num_signals_evaluated++;
+					
+					if (!RunSignalProgram(SignalReference(tile, track), exits, green))
+						newstate = SIGNAL_STATE_RED;
+				} else { /* traditional combo */
+					if (!green && exits)
+						newstate = SIGNAL_STATE_RED;
 				}
 			} else { // entry, at least one exit, no green exit
-				if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && (flags & SF_EXIT) && !(flags & SF_GREEN)) newstate = SIGNAL_STATE_RED;
+				if (IsEntrySignal(sig)) {
+					if (sig == SIGTYPE_PROG) {
+						_num_signals_evaluated++;
+						if (!RunSignalProgram(SignalReference(tile, track), info.num_exits, info.num_green))
+							newstate = SIGNAL_STATE_RED;
+					} else { /* traditional combo */
+						if (!info.num_green && info.num_exits) newstate = SIGNAL_STATE_RED;
+					}
+				}
 			}
 		}
 
 		/* only when the state changes */
 		if (newstate != GetSignalStateByTrackdir(tile, trackdir)) {
-			if (IsPresignalExit(tile, TrackdirToTrack(trackdir))) {
+			if (IsExitSignal(sig)) {
 				/* for pre-signal exits, add block to the global set */
 				DiagDirection exitdir = TrackdirToExitdir(ReverseTrackdir(trackdir));
 				_globset.Add(tile, exitdir); // do not check for full global set, first update all signals
+
+				/* Progsig dependencies */
+				MarkDependencidesForUpdate(SignalReference(tile, track));
 			}
 			SetSignalStateByTrackdir(tile, trackdir, newstate);
 			MarkTileDirtyByTile(tile);
 		}
 	}
-
 }
 
 
@@ -472,6 +552,7 @@
 
 	bool first = true;  // first block?
 	SigSegState state = SIGSEG_FREE; // value to return
+	_num_signals_evaluated = 0;
 
 	TileIndex tile;
 	DiagDirection dir;
@@ -491,7 +572,9 @@
 				assert(GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL);
 				assert(dir == INVALID_DIAGDIR || dir == ReverseDiagDir(GetTunnelBridgeDirection(tile)));
 				_tbdset.Add(tile, INVALID_DIAGDIR);  // we can safely start from wormhole centre
-				_tbdset.Add(GetOtherTunnelBridgeEnd(tile), INVALID_DIAGDIR);
+				if (!HasWormholeSignals(tile)) {  // don't worry with other side of tunnel.
+					_tbdset.Add(GetOtherTunnelBridgeEnd(tile), INVALID_DIAGDIR);
+				}
 				break;
 
 			case MP_RAILWAY:
@@ -526,25 +609,29 @@
 		assert(!_tbdset.Overflowed()); // it really shouldn't overflow by these one or two items
 		assert(!_tbdset.IsEmpty()); // it wouldn't hurt anyone, but shouldn't happen too
 
-		SigFlags flags = ExploreSegment(owner);
+		SigInfo info = ExploreSegment(owner);
 
 		if (first) {
 			first = false;
 			/* SIGSEG_FREE is set by default */
-			if (flags & SF_PBS) {
+			if (info.flags & SF_PBS) {
 				state = SIGSEG_PBS;
-			} else if ((flags & SF_TRAIN) || ((flags & SF_EXIT) && !(flags & SF_GREEN)) || (flags & SF_FULL)) {
+			} else if ((info.flags & SF_TRAIN) || ((info.num_exits) && !(info.num_green)) || (info.flags & SF_FULL)) {
 				state = SIGSEG_FULL;
 			}
 		}
 
 		/* do not do anything when some buffer was full */
-		if (flags & SF_FULL) {
+		if (info.flags & SF_FULL) {
 			ResetSets(); // free all sets
 			break;
 		}
 
-		UpdateSignalsAroundSegment(flags);
+		if (_num_signals_evaluated > _settings_game.construction.maximum_signal_evaluations) {
+			ShowErrorMessage(STR_ERROR_SIGNAL_CHANGES, STR_EMPTY, WL_INFO);
+		}
+
+		UpdateSignalsAroundSegment(info);
 	}
 
 	return state;
@@ -583,8 +670,9 @@
 		DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE
 	};
 
-	/* do not allow signal updates for two companies in one run */
-	assert(_globset.IsEmpty() || owner == _last_owner);
+	/* do not allow signal updates for two companies in one run,
+	 * if these companies are not part of the same signal block */
+	assert(_globset.IsEmpty() || IsOneSignalBlock(owner, _last_owner));
 
 	_last_owner = owner;
 
@@ -608,8 +696,9 @@
  */
 void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner)
 {
-	/* do not allow signal updates for two companies in one run */
-	assert(_globset.IsEmpty() || owner == _last_owner);
+	/* do not allow signal updates for two companies in one run,
+	 * if these companies are not part of the same signal block */
+	assert(_globset.IsEmpty() || IsOneSignalBlock(owner, _last_owner));
 
 	_last_owner = owner;
 
@@ -657,3 +746,90 @@
 	AddTrackToSignalBuffer(tile, track, owner);
 	UpdateSignalsInBuffer(owner);
 }
+
+void AddSignalDependency(SignalReference on, SignalReference dep)
+{	
+	assert(GetTileOwner(on.tile) == GetTileOwner(dep.tile));
+	SignalDependencyList &dependencies = _signal_dependencies[on];
+	(*dependencies.Append()) = dep;
+}
+
+void RemoveSignalDependency(SignalReference on, SignalReference dep)
+{
+	SignalDependencyList &dependencies = _signal_dependencies[on];
+	SignalReference *ob = dependencies.Find(dep);
+
+	// Destroying both signals in same command
+	if(ob == dependencies.End())
+		return;
+
+	dependencies.Erase(ob);
+	if (dependencies.Length() == 0)
+		_signal_dependencies.erase(on);
+}
+
+void FreeSignalDependencies()
+{
+	_signal_dependencies.clear();
+}
+
+static void MarkDependencidesForUpdate(SignalReference on)
+{
+	SignalDependencyMap::iterator f = _signal_dependencies.find(on);
+	if (f == _signal_dependencies.end()) return;
+	
+	SignalDependencyList &dependencies = f->second;
+	for (SignalReference *i = dependencies.Begin(), *e = dependencies.End();
+			i != e; ++i) {
+		assert(GetTileOwner(i->tile) == GetTileOwner(on.tile));
+	
+		Trackdir td = TrackToTrackdir(i->track);
+		_globset.Add(i->tile, TrackdirToExitdir(td));
+		_globset.Add(i->tile, TrackdirToExitdir(ReverseTrackdir(td)));
+	}
+}
+
+void CheckRemoveSignalsFromTile(TileIndex tile)
+{
+	if (!HasSignals(tile)) return;
+	
+	TrackBits tb = GetTrackBits(tile);
+	Track tr;
+	while ((tr = RemoveFirstTrack(&tb)) != INVALID_TRACK) {
+		if (HasSignalOnTrack(tile, tr)) CheckRemoveSignal(tile, tr);
+	}
+}
+
+static void NotifyRemovingDependentSignal(SignalReference on, SignalReference by)
+{
+    SignalType t = GetSignalType(by.tile, by.track);
+    if (IsProgrammableSignal(t)) {
+        RemoveProgramDependencies(by, on);
+    } else DEBUG(misc, 0, "Removing dependency held by non-programmable signal (Unexpected)");
+}
+
+void CheckRemoveSignal(TileIndex tile, Track track)
+{
+	if (!HasSignalOnTrack(tile, track)) return;
+	SignalReference thisRef(tile, track);
+	
+	SignalType t = GetSignalType(tile, track);
+	if (IsProgrammableSignal(t)) {
+		FreeSignalProgram(thisRef);
+	} else if (IsSpeedSignal(t)) {
+		FreeSignalSpeed(thisRef);
+	}
+	
+	SignalDependencyMap::iterator i = _signal_dependencies.find(SignalReference(tile, track)), e = _signal_dependencies.end();
+
+	if (i != e) {
+		SignalDependencyList &dependencies = i->second;
+
+		for (SignalReference *ir = dependencies.Begin(), *er = dependencies.End(); ir != er; ++ir) {
+			assert(GetTileOwner(ir->tile) == GetTileOwner(tile));
+			NotifyRemovingDependentSignal(thisRef, *ir);
+		}
+
+		_signal_dependencies.erase(i);
+	}
+}
diff --git a/src/signal_func.h b/src/signal_func.h
--- a/src/signal_func.h
+++ b/src/signal_func.h
@@ -12,10 +12,12 @@
 #ifndef SIGNAL_FUNC_H
 #define SIGNAL_FUNC_H
 
+#include "signal_type.h"
 #include "track_type.h"
 #include "tile_type.h"
 #include "direction_type.h"
 #include "company_type.h"
+#include "debug.h"
 
 /**
  * Maps a trackdir to the bit that stores its status in the map arrays, in the
@@ -47,6 +49,68 @@
 	return _signal_on_track[track];
 }
 
+/** Is a given signal type a presignal entry signal? */
+static inline bool IsEntrySignal(SignalType type)
+{
+	return type == SIGTYPE_ENTRY || type == SIGTYPE_COMBO || type == SIGTYPE_PROG;
+}
+
+/** Is a given signal type a presignal exit signal? */
+static inline bool IsExitSignal(SignalType type)
+{
+	return type == SIGTYPE_EXIT || type == SIGTYPE_COMBO || type == SIGTYPE_PROG;
+}
+
+/** Is a given signal type a presignal combo signal? */
+static inline bool IsComboSignal(SignalType type)
+{
+	return type == SIGTYPE_COMBO || type == SIGTYPE_PROG;
+}
+
+/** Is a given signal type a PBS signal? */
+static inline bool IsPbsSignal(SignalType type)
+{
+	return type == SIGTYPE_PBS || type == SIGTYPE_PBS_ONEWAY;
+}
+
+/** Is this a programmable signal? */
+static inline bool IsProgrammableSignal(SignalType type)
+{
+	return type == SIGTYPE_PROG;
+}
+
+/** Is this a speed signal? */
+static inline bool IsSpeedSignal(SignalType type)
+{
+	return type == SIGTYPE_SPEED;
+}
+
+/** Does a given signal have a PBS sprite? */
+static inline bool IsSignalSpritePBS(SignalType type)
+{
+	return type >= SIGTYPE_FIRST_PBS_SPRITE;
+}
+
+static inline SignalType NextSignalType(SignalType cur, uint which_signals)
+{
+	bool pbs   = (which_signals != 0);
+	bool block = (which_signals != 1);
+	
+	switch(cur) {
+		case SIGTYPE_NORMAL:     return block ? SIGTYPE_ENTRY      : SIGTYPE_PBS;
+		case SIGTYPE_ENTRY:      return block ? SIGTYPE_EXIT       : SIGTYPE_PBS;
+		case SIGTYPE_EXIT:       return block ? SIGTYPE_COMBO      : SIGTYPE_PBS;
+		case SIGTYPE_COMBO:      return block ? SIGTYPE_PROG       : SIGTYPE_PBS;
+		case SIGTYPE_PROG:       return pbs   ? SIGTYPE_PBS        : SIGTYPE_NORMAL;
+		case SIGTYPE_SPEED:      return SIGTYPE_SPEED;
+		case SIGTYPE_PBS:        return pbs   ? SIGTYPE_PBS_ONEWAY : SIGTYPE_NORMAL;
+		case SIGTYPE_PBS_ONEWAY: return block ? SIGTYPE_NORMAL     : SIGTYPE_PBS;
+		default: 
+			DEBUG(map, 0, "Attempt to cycle from signal type %d", cur);
+			return SIGTYPE_NORMAL; // Fortunately mostly harmless
+	}
+}
+
 /** State of the signal segment */
 enum SigSegState {
 	SIGSEG_FREE,    ///< Free and has no pre-signal exits or at least one green exit
@@ -54,6 +118,33 @@
 	SIGSEG_PBS,     ///< Segment is a PBS segment
 };
 
+/**
+ * Checks for any data attached to any signals, and removes it. Call when performing
+ * an action which may potentially remove signals from a tile, in order to avoid leaking
+ * data.
+ */
+void CheckRemoveSignalsFromTile(TileIndex tile);
+
+/**
+ * Checks for, and removes, any extra signal data. Call when removing a piece of track
+ * which is potentially signalled, in order to free any extra data that may be associated
+ * with said track.
+ */
+void CheckRemoveSignal(TileIndex tile, Track track);
+
+/**
+ * Adds a signal dependency
+ *  The signal identified by @p dep will be marked as dependend upon
+ *  the signal identified by @p on
+ */
+void AddSignalDependency(SignalReference on, SignalReference dep);
+
+/** Removes a signal dependency. Arguments same as AddSignalDependency */
+void RemoveSignalDependency(SignalReference on, SignalReference dep);
+
+/** Frees signal dependencies (for newgame/load) */
+void FreeSignalDependencies();
+
 SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner);
 void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner);
 void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner);
diff --git a/src/signal_type.h b/src/signal_type.h
--- a/src/signal_type.h
+++ b/src/signal_type.h
@@ -13,6 +13,8 @@
 #define SIGNAL_TYPE_H
 
 #include "core/enum_type.hpp"
+#include "track_type.h"
+#include "tile_type.h"
 
 /** Variant of the signal, i.e. how does the signal look? */
 enum SignalVariant {
@@ -20,22 +22,37 @@
 	SIG_SEMAPHORE = 1  ///< Old-fashioned semaphore signal
 };
 
-
 /** Type of signal, i.e. how does the signal behave? */
 enum SignalType {
 	SIGTYPE_NORMAL     = 0, ///< normal signal
 	SIGTYPE_ENTRY      = 1, ///< presignal block entry
 	SIGTYPE_EXIT       = 2, ///< presignal block exit
-	SIGTYPE_COMBO      = 3, ///< presignal inter-block
+	SIGTYPE_COMBO      = 3, ///< presignal combo inter-block
 	SIGTYPE_PBS        = 4, ///< normal pbs signal
 	SIGTYPE_PBS_ONEWAY = 5, ///< no-entry signal
+	SIGTYPE_PROG       = 6, ///< programmable presignal
+ 	SIGTYPE_SPEED      = 7, ///< speed limit signal
 
 	SIGTYPE_END,
-	SIGTYPE_LAST       = SIGTYPE_PBS_ONEWAY,
-	SIGTYPE_LAST_NOPBS = SIGTYPE_COMBO
+	SIGTYPE_LAST             = SIGTYPE_SPEED,
+	SIGTYPE_FIRST_PBS_SPRITE = SIGTYPE_PBS
 };
 /** Helper information for extract tool. */
 template <> struct EnumPropsT<SignalType> : MakeEnumPropsT<SignalType, byte, SIGTYPE_NORMAL, SIGTYPE_END, SIGTYPE_END, 3> {};
 
+/**
+ * Reference to a signal
+ *
+ * A reference to a signal by its tile and track
+ */
+struct SignalReference {
+	inline SignalReference(TileIndex t, Track tr) : tile(t), track(tr) {}
+	inline bool operator<(const SignalReference& o) const { return tile < o.tile || (tile == o.tile && track < o.track); }
+	inline bool operator==(const SignalReference& o) const { return tile == o.tile && track == o.track; }
+	inline bool operator!=(const SignalReference& o) const { return tile != o.tile || track != o.track; }
+	
+	TileIndex tile; 
+	Track track;
+};
 
 #endif /* SIGNAL_TYPE_H */
diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp
--- a/src/smallmap_gui.cpp
+++ b/src/smallmap_gui.cpp
@@ -26,35 +26,44 @@
 #include "sound_func.h"
 #include "window_func.h"
 #include "company_base.h"
+//#include "cargotype.h"
+//#include "openttd.h"
+#include "company_func.h"
+#include "station_base.h"
 
 #include "table/strings.h"
 
+//#include <cmath>
+#include <vector>
+
 /** Widget numbers of the small map window. */
 enum SmallMapWindowWidgets {
 	SM_WIDGET_CAPTION,           ///< Caption widget.
 	SM_WIDGET_MAP_BORDER,        ///< Border around the smallmap.
 	SM_WIDGET_MAP,               ///< Panel containing the smallmap.
 	SM_WIDGET_LEGEND,            ///< Bottom panel to display smallmap legends.
+	SM_WIDGET_BLANK,             ///< Empty button as placeholder.
 	SM_WIDGET_ZOOM_IN,           ///< Button to zoom in one step.
 	SM_WIDGET_ZOOM_OUT,          ///< Button to zoom out one step.
 	SM_WIDGET_CONTOUR,           ///< Button to select the contour view (height map).
 	SM_WIDGET_VEHICLES,          ///< Button to select the vehicles view.
 	SM_WIDGET_INDUSTRIES,        ///< Button to select the industries view.
+	SM_WIDGET_LINKSTATS,         ///< Button to select the link stats view.
 	SM_WIDGET_ROUTES,            ///< Button to select the routes view.
 	SM_WIDGET_VEGETATION,        ///< Button to select the vegetation view.
 	SM_WIDGET_OWNERS,            ///< Button to select the owners view.
 	SM_WIDGET_CENTERMAP,         ///< Button to move smallmap center to main window center.
 	SM_WIDGET_TOGGLETOWNNAME,    ///< Toggle button to display town names.
 	SM_WIDGET_SELECT_BUTTONS,    ///< Selection widget for the buttons present in some smallmap modes.
-	SM_WIDGET_ENABLE_ALL,        ///< Button to enable display of all legend entries.
-	SM_WIDGET_DISABLE_ALL,       ///< Button to disable display of all legend entries.
+	SM_WIDGET_ENABLE_ALL,        ///< Button to enable display of all toggable legend entries.
+	SM_WIDGET_DISABLE_ALL,       ///< Button to disable display of all toggable legend entries.
 	SM_WIDGET_SHOW_HEIGHT,       ///< Show heightmap toggle button.
 };
 
-static int _smallmap_industry_count; ///< Number of used industries
-static int _smallmap_company_count;  ///< Number of entries in the owner legend.
-
+static int _smallmap_industry_count;         ///< Number of used industries
+static int _smallmap_company_count;          ///< Number of entries in the owner legend.
 static const int NUM_NO_COMPANY_ENTRIES = 4; ///< Number of entries in the owner legend that are not companies.
+static int _smallmap_cargo_count;            ///< number of cargos in the link stats legend
 
 static const uint8 PC_ROUGH_LAND      = 0x52; ///< Dark green palette colour for rough land.
 static const uint8 PC_GRASS_LAND      = 0x54; ///< Dark green palette colour for grass land.
@@ -63,27 +72,42 @@
 static const uint8 PC_TREES           = 0x57; ///< Green palette colour for trees.
 static const uint8 PC_WATER           = 0xCA; ///< Dark blue palette colour for water.
 
+enum SmallMapStats {
+	STAT_CAPACITY,
+	STAT_BEGIN = STAT_CAPACITY,
+	STAT_USAGE,
+	STAT_PLANNED,
+	STAT_SENT,
+	STAT_TEXT,
+	STAT_GRAPH,
+	STAT_END,
+	NUM_STATS = STAT_END,
+};
+
 /** Macro for ordinary entry of LegendAndColour */
 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
 
 /** Macro for a height legend entry with configurable colour. */
 #define MC(height)  {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, true, false, false}
 
-/** Macro for non-company owned property entry of LegendAndColour */
-#define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
-
-/** Macro used for forcing a rebuild of the owner legend the first time it is used. */
-#define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
-
-/** Macro for end of list marker in arrays of LegendAndColour */
-#define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
-
 /**
  * Macro for break marker in arrays of LegendAndColour.
  * It will have valid data, though
  */
 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true}
 
+/** Macro for a height legend break marker entry with configurable colour. */
+#define MCS(height)  {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, true, false, true}
+
+/** Macro for non-company owned property entry of LegendAndColour */
+#define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
+
+/** Macro used for forcing a rebuild of the owner legend the first time it is used. */
+#define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
+
+/** Macro for end of list marker in arrays of LegendAndColour */
+#define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
+
 /** Structure for holding relevant data for legends in small map */
 struct LegendAndColour {
 	uint8 colour;              ///< Colour of the item on the map.
@@ -96,14 +120,14 @@
 	bool col_break;            ///< Perform a column break and go further at the next column.
 };
 
-/** Legend text giving the colours to look for on the minimap */
-static LegendAndColour _legend_land_contours[] = {
-	/* The colours for the following values are set at BuildLandLegend() based on each colour scheme. */
-	MC(0),
-	MC(4),
-	MC(8),
-	MC(12),
-	MC(14),
+/** Legend text giving the colours to look for on the minimap (original) */
+static LegendAndColour _legend_land_contours_old[] = {
+	/* The colours for the following values are set at BuildLandLegend() based on each colour scheme when the more height levels patch is off. */
+	MC(1),
+	MC(5),
+	MC(9),
+	MC(13),
+	MC(15),
 
 	MS(PC_BLACK,           STR_SMALLMAP_LEGENDA_ROADS),
 	MK(PC_GREY,            STR_SMALLMAP_LEGENDA_RAILROADS),
@@ -113,6 +137,37 @@
 	MKEND()
 };
 
+/** Legend text giving the colours to look for on the minimap (in case of AllowMoreHeightlevels()) */
+static LegendAndColour _legend_land_contours_extended[] = {
+	/* The colours for the following values are set at BuildLandLegend() based on each colour scheme when the more height levels patch is on. */
+	MC(1),
+	MC(16),
+	MC(32),
+	MC(48),
+	MC(64),
+	MC(80),
+
+	MCS(96),
+	MC(112),
+	MC(128),
+	MC(144),
+	MC(160),
+	MC(176),
+
+	MCS(192),
+	MC(208),
+	MC(224),
+	MC(240),
+	MC(255),
+
+	MS(PC_BLACK,      STR_SMALLMAP_LEGENDA_ROADS),
+	MK(PC_GREY,       STR_SMALLMAP_LEGENDA_RAILROADS),
+	MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
+	MK(PC_DARK_RED,   STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
+	MK(PC_WHITE,      STR_SMALLMAP_LEGENDA_VEHICLES),
+	MKEND()
+};
+
 static const LegendAndColour _legend_vehicles[] = {
 	MK(PC_RED,             STR_SMALLMAP_LEGENDA_TRAINS),
 	MK(PC_YELLOW,          STR_SMALLMAP_LEGENDA_ROAD_VEHICLES),
@@ -165,6 +220,7 @@
 #undef MK
 #undef MC
 #undef MS
+#undef MCS
 #undef MO
 #undef MOEND
 #undef MKEND
@@ -212,10 +268,87 @@
 	_smallmap_industry_count = j;
 }
 
-static const LegendAndColour * const _legend_table[] = {
-	_legend_land_contours,
+static LegendAndColour _legend_linkstats[NUM_CARGO + NUM_STATS + 1];
+
+/**
+ * Populate legend table for the link stat view.
+ */
+void BuildLinkStatsLegend()
+{
+	/* Clear the legend */
+	memset(_legend_linkstats, 0, sizeof(_legend_linkstats));
+
+	uint i = 0;
+	for (; i < _sorted_cargo_specs_size; ++i) {
+		const CargoSpec *cs = _sorted_cargo_specs[i];
+
+		_legend_linkstats[i].legend = cs->name;
+		_legend_linkstats[i].colour = cs->legend_colour;
+		_legend_linkstats[i].type = cs->Index();
+		_legend_linkstats[i].show_on_map = true;
+	}
+
+	_legend_linkstats[i].col_break = true;
+
+	_smallmap_cargo_count = i;
+
+	/* the colours cannot be resolved before the gfx system is initialized.
+	 * So we have to build the legend when creating the window.
+	 */
+	for (uint st = 0; st < NUM_STATS; ++st) {
+		LegendAndColour & legend_entry = _legend_linkstats[i + st];
+		switch(st) {
+		case STAT_CAPACITY:
+			legend_entry.colour = _colour_gradient[COLOUR_WHITE][7];
+			legend_entry.legend = STR_SMALLMAP_LEGENDA_CAPACITY;
+			legend_entry.show_on_map = true;
+			break;
+		case STAT_USAGE:
+			legend_entry.colour = _colour_gradient[COLOUR_GREY][1];
+			legend_entry.legend = STR_SMALLMAP_LEGENDA_USAGE;
+			legend_entry.show_on_map = false;
+			break;
+		case STAT_PLANNED:
+			legend_entry.colour = _colour_gradient[COLOUR_RED][5];
+			legend_entry.legend = STR_SMALLMAP_LEGENDA_PLANNED;
+			legend_entry.show_on_map = true;
+			break;
+		case STAT_SENT:
+			legend_entry.colour = _colour_gradient[COLOUR_YELLOW][5];
+			legend_entry.legend = STR_SMALLMAP_LEGENDA_SENT;
+			legend_entry.show_on_map = false;
+			break;
+		case STAT_TEXT:
+			legend_entry.colour = _colour_gradient[COLOUR_GREY][7];
+			legend_entry.legend = STR_SMALLMAP_LEGENDA_SHOW_TEXT;
+			legend_entry.show_on_map = false;
+			break;
+		case STAT_GRAPH:
+			legend_entry.colour = _colour_gradient[COLOUR_GREY][7];
+			legend_entry.legend = STR_SMALLMAP_LEGENDA_SHOW_GRAPH;
+			legend_entry.show_on_map = true;
+			break;
+		}
+	}
+
+	_legend_linkstats[i + NUM_STATS].end = true;
+}
+
+static const LegendAndColour * const _legend_table_old[] = {
+	_legend_land_contours_old,
 	_legend_vehicles,
 	_legend_from_industries,
+	_legend_linkstats,
+	_legend_routes,
+	_legend_vegetation,
+	_legend_land_owners,
+};
+
+static const LegendAndColour * const _legend_table_extended[] = {
+	_legend_land_contours_extended,
+	_legend_vehicles,
+	_legend_from_industries,
+	_legend_linkstats,
 	_legend_routes,
 	_legend_vegetation,
 	_legend_land_owners,
@@ -237,8 +370,12 @@
 #define MKCOLOUR_F00F       MKCOLOUR_X00X(0xFF)
 #define MKCOLOUR_FFFF       MKCOLOUR_XXXX(0xFF)
 
-/** Height map colours for the green colour scheme, ordered by height. */
-static const uint32 _green_map_heights[] = {
+/**
+ * Colour array for displaying elevation in the smallmap, ordered by height.
+ * This is the original array for use when AllowMoreHeightlevels() is false.
+ */
+static const uint32 _green_map_heights_old[] = {
+	MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
 	MKCOLOUR_XXXX(0x5A),
 	MKCOLOUR_XYXY(0x5A, 0x5B),
 	MKCOLOUR_XXXX(0x5B),
@@ -256,10 +393,288 @@
 	MKCOLOUR_XXXX(0x27),
 	MKCOLOUR_XXXX(0x27),
 };
-assert_compile(lengthof(_green_map_heights) == MAX_TILE_HEIGHT + 1);
-
-/** Height map colours for the dark green colour scheme, ordered by height. */
-static const uint32 _dark_green_map_heights[] = {
+assert_compile(lengthof(_green_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
+
+/**
+ * Height map colours for the green colour scheme, ordered by height.
+ * Used when AllowMoreHeightlevels() is true.
+ * For the moment the aray is extended to 256 levels.
+ */
+static const uint32 _green_map_heights_extended[] = {
+	/* First two colours are action colours.(First commented out, first we need level -1 (and underwater tunnels)) */
+	//MKCOLOUR(0xdcdcdcdc), // Nice flashy colour, darkblue. (Do not use above level 1. (second colour)) (I keep it here to become level -1 ground tile (not flooded) (For now: To see its full effect, use this as second color.Then imagine at level -1.))
+	MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
+	MKCOLOUR(0x59595958), // height 1
+	MKCOLOUR(0x59595958), // height 2
+	MKCOLOUR(0X59595959), // height 3
+	MKCOLOUR(0X59595959), // height 4
+	MKCOLOUR(0X5959595A), // height 5
+	MKCOLOUR(0X5959595A), // height 6
+	MKCOLOUR(0X59595A59), // height 7
+	MKCOLOUR(0X59595A59), // height 8
+	MKCOLOUR(0X59595A5A), // height 9
+	MKCOLOUR(0X59595A5A), // height 10
+	MKCOLOUR(0X595A5959), // height 11
+	MKCOLOUR(0X595A5959), // height 12
+	MKCOLOUR(0X595A595A), // height 13
+	MKCOLOUR(0X595A595A), // height 14
+	MKCOLOUR(0X595A5A59), // height 15
+	MKCOLOUR(0X595A5A59), // height 16
+	MKCOLOUR(0X595A5A5A), // height 17
+	MKCOLOUR(0X595A5A5A), // height 18
+	MKCOLOUR(0X5A595959), // height 19
+	MKCOLOUR(0X5A595959), // height 20
+	MKCOLOUR(0X5A59595A), // height 21
+	MKCOLOUR(0X5A59595A), // height 22
+	MKCOLOUR(0X5A595A59), // height 23
+	MKCOLOUR(0X5A595A59), // height 24
+	MKCOLOUR(0X5A595A5A), // height 25
+	MKCOLOUR(0X5A595A5A), // height 26
+	MKCOLOUR(0X5A5A5959), // height 27
+	MKCOLOUR(0X5A5A5959), // height 28
+	MKCOLOUR(0X5A5A595A), // height 29
+	MKCOLOUR(0X5A5A595A), // height 30
+	MKCOLOUR(0X5A5A5A59), // height 31
+	MKCOLOUR(0X5A5A5A59), // height 32
+	MKCOLOUR(0x5A5A5A5A), // height 33 // original smallmap color do not modify
+	MKCOLOUR(0x5A5A5A5A), // height 34 // original smallmap color do not modify
+	MKCOLOUR(0x5A5A5A5B), // height 35
+	MKCOLOUR(0x5A5A5A5B), // height 36
+	MKCOLOUR(0x5A5A5B5A), // height 37
+	MKCOLOUR(0x5A5A5B5A), // height 38
+	MKCOLOUR(0x5A5A5B5B), // height 39
+	MKCOLOUR(0x5A5A5B5B), // height 40
+	MKCOLOUR(0x5A5B5A5A), // height 41
+	MKCOLOUR(0x5A5B5A5A), // height 42
+	MKCOLOUR(0x5A5B5A5B), // height 43 // original smallmap color do not modify
+	MKCOLOUR(0x5A5B5A5B), // height 44 // original smallmap color do not modify
+	MKCOLOUR(0x5A5B5B5A), // height 45
+	MKCOLOUR(0x5A5B5B5A), // height 46
+	MKCOLOUR(0x5A5B5B5B), // height 47
+	MKCOLOUR(0x5A5B5B5B), // height 48
+	MKCOLOUR(0x5B5A5A5A), // height 49
+	MKCOLOUR(0x5B5A5A5A), // height 50
+	MKCOLOUR(0x5B5A5A5B), // height 51
+	MKCOLOUR(0x5B5A5A5B), // height 52
+	MKCOLOUR(0x5B5A5B5A), // height 53
+	MKCOLOUR(0x5B5A5B5A), // height 54
+	MKCOLOUR(0x5B5A5B5B), // height 55
+	MKCOLOUR(0x5B5A5B5B), // height 56
+	MKCOLOUR(0x5B5B5A5A), // height 57
+	MKCOLOUR(0x5B5B5A5A), // height 58
+	MKCOLOUR(0x5B5B5A5B), // height 59
+	MKCOLOUR(0x5B5B5A5B), // height 60
+	MKCOLOUR(0x5B5B5B5B), // height 61 // original smallmap color do not modify
+	MKCOLOUR(0x5B5B5B5B), // height 62 // original smallmap color do not modify
+	MKCOLOUR(0x5B5B5B5C), // height 63
+	MKCOLOUR(0x5B5B5B5C), // height 64
+	MKCOLOUR(0x5B5B5C5B), // height 65
+	MKCOLOUR(0x5B5B5C5B), // height 66
+	MKCOLOUR(0x5B5B5C5C), // height 67
+	MKCOLOUR(0x5B5B5C5C), // height 68
+	MKCOLOUR(0x5B5C5B5B), // height 69
+	MKCOLOUR(0x5B5C5B5B), // height 70
+	MKCOLOUR(0x5B5C5B5C), // height 71 // original smallmap color do not modify
+	MKCOLOUR(0x5B5C5B5C), // height 72 // original smallmap color do not modify
+	MKCOLOUR(0x5B5C5C5B), // height 73
+	MKCOLOUR(0x5B5C5C5B), // height 74
+	MKCOLOUR(0x5B5C5C5C), // height 75
+	MKCOLOUR(0x5B5C5C5C), // height 76
+	MKCOLOUR(0x5C5B5B5B), // height 77
+	MKCOLOUR(0x5C5B5B5B), // height 78
+	MKCOLOUR(0x5C5B5B5C), // height 79
+	MKCOLOUR(0x5C5B5B5C), // height 80
+	MKCOLOUR(0x5C5B5C5B), // height 81
+	MKCOLOUR(0x5C5B5C5B), // height 82
+	MKCOLOUR(0x5C5B5C5C), // height 83
+	MKCOLOUR(0x5C5B5C5C), // height 84
+	MKCOLOUR(0x5C5C5B5B), // height 85
+	MKCOLOUR(0x5C5C5B5B), // height 86
+	MKCOLOUR(0x5C5C5B5C), // height 87
+	MKCOLOUR(0x5C5C5B5C), // height 88
+	MKCOLOUR(0x5C5C5C5C), // height 89 // original smallmap color do not modify
+	MKCOLOUR(0x5C5C5C5C), // height 90 // original smallmap color do not modify
+	MKCOLOUR(0x5C5C5C5D), // height 91
+	MKCOLOUR(0x5C5C5C5D), // height 92
+	MKCOLOUR(0x5C5C5D5C), // height 93
+	MKCOLOUR(0x5C5C5D5C), // height 94
+	MKCOLOUR(0x5C5C5D5D), // height 95
+	MKCOLOUR(0x5C5C5D5D), // height 96
+	MKCOLOUR(0x5C5D5C5C), // height 97
+	MKCOLOUR(0x5C5D5C5C), // height 98
+	MKCOLOUR(0x5C5D5C5D), // height 99 // original smallmap color do not modify
+	MKCOLOUR(0x5C5D5C5D), // height 100 // original smallmap color do not modify
+	MKCOLOUR(0x5C5D5D5C), // height 101
+	MKCOLOUR(0x5C5D5D5C), // height 102
+	MKCOLOUR(0x5C5D5D5D), // height 103
+	MKCOLOUR(0x5C5D5D5D), // height 104
+	MKCOLOUR(0x5D5C5C5C), // height 105
+	MKCOLOUR(0x5D5C5C5C), // height 106
+	MKCOLOUR(0x5D5C5C5D), // height 107
+	MKCOLOUR(0x5D5C5C5D), // height 108
+	MKCOLOUR(0x5D5C5D5C), // height 109
+	MKCOLOUR(0x5D5C5D5C), // height 110
+	MKCOLOUR(0x5D5C5D5D), // height 111
+	MKCOLOUR(0x5D5C5D5D), // height 112
+	MKCOLOUR(0x5D5D5C5C), // height 113
+	MKCOLOUR(0x5D5D5C5C), // height 114
+	MKCOLOUR(0x5D5D5C5D), // height 115
+	MKCOLOUR(0x5D5D5C5D), // height 116
+	MKCOLOUR(0x5D5D5D5D), // height 117 // original smallmap color do not modify
+	MKCOLOUR(0x5D5D5D5D), // height 118 // original smallmap color do not modify
+	MKCOLOUR(0x5D5D5D5E), // height 119
+	MKCOLOUR(0x5D5D5D5E), // height 120
+	MKCOLOUR(0x5D5D5E5D), // height 121
+	MKCOLOUR(0x5D5D5E5D), // height 122
+	MKCOLOUR(0x5D5D5E5E), // height 123
+	MKCOLOUR(0x5D5D5E5E), // height 124
+	MKCOLOUR(0x5D5E5D5D), // height 125
+	MKCOLOUR(0x5D5E5D5D), // height 126
+	MKCOLOUR(0x5D5E5D5E), // height 127 // original smallmap color do not modify
+	MKCOLOUR(0x5D5E5D5E), // height 128 // original smallmap color do not modify
+	MKCOLOUR(0x5D5E5E5D), // height 129
+	MKCOLOUR(0x5D5E5E5D), // height 130
+	MKCOLOUR(0x5D5E5E5E), // height 131
+	MKCOLOUR(0x5D5E5E5E), // height 132
+	MKCOLOUR(0x5E5D5D5D), // height 133
+	MKCOLOUR(0x5E5D5D5D), // height 134
+	MKCOLOUR(0x5E5D5D5E), // height 135
+	MKCOLOUR(0x5E5D5D5E), // height 136
+	MKCOLOUR(0x5E5D5E5D), // height 137
+	MKCOLOUR(0x5E5D5E5D), // height 138
+	MKCOLOUR(0x5E5D5E5E), // height 139
+	MKCOLOUR(0x5E5D5E5E), // height 140
+	MKCOLOUR(0x5E5D5D5D), // height 141
+	MKCOLOUR(0x5E5D5D5D), // height 142
+	MKCOLOUR(0x5E5D5D5E), // height 143
+	MKCOLOUR(0x5E5D5D5E), // height 144
+	MKCOLOUR(0x5E5E5E5E), // height 145 // original smallmap color do not modify
+	MKCOLOUR(0x5E5E5E5E), // height 146 // original smallmap color do not modify
+	MKCOLOUR(0x5E5E5E5F), // height 147
+	MKCOLOUR(0x5E5E5E5F), // height 148
+	MKCOLOUR(0x5E5E5F5E), // height 149
+	MKCOLOUR(0x5E5E5F5E), // height 150
+	MKCOLOUR(0x5E5E5F5F), // height 151
+	MKCOLOUR(0x5E5E5F5F), // height 152
+	MKCOLOUR(0x5E5F5E5E), // height 153
+	MKCOLOUR(0x5E5F5E5E), // height 154
+	MKCOLOUR(0x5E5F5E5F), // height 155 // original smallmap color do not modify
+	MKCOLOUR(0x5E5F5E5F), // height 156 // original smallmap color do not modify
+	MKCOLOUR(0x5E5F5F5E), // height 157
+	MKCOLOUR(0x5E5F5F5E), // height 158
+	MKCOLOUR(0x5E5F5F5F), // height 159
+	MKCOLOUR(0x5E5F5F5F), // height 160
+	MKCOLOUR(0x5F5E5E5E), // height 161
+	MKCOLOUR(0x5F5E5E5E), // height 162
+	MKCOLOUR(0x5F5E5E5F), // height 163
+	MKCOLOUR(0x5F5E5E5F), // height 164
+	MKCOLOUR(0x5F5E5F5E), // height 165
+	MKCOLOUR(0x5F5E5F5E), // height 166
+	MKCOLOUR(0x5F5E5F5F), // height 167
+	MKCOLOUR(0x5F5E5F5F), // height 168
+	MKCOLOUR(0x5F5F5E5E), // height 169
+	MKCOLOUR(0x5F5F5E5E), // height 170
+	MKCOLOUR(0x5F5F5E5F), // height 171
+	MKCOLOUR(0x5F5F5E5F), // height 172
+	MKCOLOUR(0x5F5F5F5F), // height 173 // original smallmap color do not modify
+	MKCOLOUR(0x5F5F5F5F), // height 174 // original smallmap color do not modify
+	MKCOLOUR(0x5F5F5F1F), // height 175
+	MKCOLOUR(0x5F5F5F1F), // height 176
+	MKCOLOUR(0x5F5F1F5F), // height 177
+	MKCOLOUR(0x5F5F1F5F), // height 178
+	MKCOLOUR(0x5F5F1F1F), // height 179
+	MKCOLOUR(0x5F5F1F1F), // height 180
+	MKCOLOUR(0x5F1F5F1F), // height 181 // original smallmap color do not modify
+	MKCOLOUR(0x5F1F5F1F), // height 182 // original smallmap color do not modify
+// pale greens need finetuning ?
+	MKCOLOUR(0x5F1F1F1F), // height 183
+	MKCOLOUR(0x5F1F1F1F), // height 184
+	MKCOLOUR(0x1F5F5F5F), // height 185
+	MKCOLOUR(0x1F5F5F5F), // height 186
+	MKCOLOUR(0x1F5F5F1F), // height 187
+	MKCOLOUR(0x1F5F5F1F), // height 188
+	MKCOLOUR(0x1F5F1F5F), // height 189
+	MKCOLOUR(0x1F5F1F5F), // height 190
+	MKCOLOUR(0x1F5F1F1F), // height 191
+	MKCOLOUR(0x1F5F1F1F), // height 192
+	MKCOLOUR(0x1F1F5F5F), // height 193
+	MKCOLOUR(0x1F1F5F5F), // height 194
+	MKCOLOUR(0x1F1F5F1F), // height 195
+	MKCOLOUR(0x1F1F5F1F), // height 196
+	MKCOLOUR(0x1F1F1F5F), // height 197
+	MKCOLOUR(0x1F1F1F5F), // height 198
+//fine tune pale greens untill here ?
+	MKCOLOUR(0x1F1F1F1F), // height 199 // original smallmap color do not modify
+	MKCOLOUR(0x1F1F1F1F), // height 200 // original smallmap color do not modify
+	MKCOLOUR(0x1F1F1F27), // height 201
+	MKCOLOUR(0x1F1F1F27), // height 202
+	MKCOLOUR(0x1F1F271F), // height 203
+	MKCOLOUR(0x1F1F271F), // height 204
+	MKCOLOUR(0x1F1F2727), // height 205
+	MKCOLOUR(0x1F1F2727), // height 206
+	MKCOLOUR(0x1F271F1F), // height 207
+	MKCOLOUR(0x1F271F1F), // height 208
+	MKCOLOUR(0x1F271F27), // height 209 // original smallmap color do not modify
+	MKCOLOUR(0x1F271F27), // height 210 // original smallmap color do not modify
+	MKCOLOUR(0x1F272727), // height 211
+	MKCOLOUR(0x1F272727), // height 212
+	MKCOLOUR(0x271F1F1F), // height 213
+	MKCOLOUR(0x271F1F1F), // height 214
+	MKCOLOUR(0x271F1F27), // height 215
+	MKCOLOUR(0x271F1F27), // height 216
+	MKCOLOUR(0x271F271F), // height 217
+	MKCOLOUR(0x271F271F), // height 218
+	MKCOLOUR(0x271F2727), // height 219
+	MKCOLOUR(0x271F2727), // height 220
+	MKCOLOUR(0x27271F1F), // height 221
+	MKCOLOUR(0x27271F1F), // height 222
+	MKCOLOUR(0x27271F27), // height 223
+	MKCOLOUR(0x27271F27), // height 224
+	MKCOLOUR(0x2727271F), // height 225
+	MKCOLOUR(0x2727271F), // height 226
+	MKCOLOUR(0x27272727), // height 227 // original smallmap color do not modify
+	MKCOLOUR(0x27272727), // height 228 // original smallmap color do not modify
+    /* Above and below the same color. I know. It was like that before I arrived. I prefer extending over modifying, it stays. */
+	MKCOLOUR(0x27272727), // height 229 // original smallmap color do not modify
+	MKCOLOUR(0x27272727), // height 230 // original smallmap color do not modify
+	/* Purple top */
+	MKCOLOUR(0x1F27AF27), // height 231
+	MKCOLOUR(0x1F27AF27), // height 232
+	MKCOLOUR(0x1F274FAF), // height 233
+	MKCOLOUR(0x1F274FAF), // height 234
+	MKCOLOUR(0x4F274FAF), // height 235
+	MKCOLOUR(0x4F274FAF), // height 236
+	MKCOLOUR(0x4FAF1FAF), // height 237
+	MKCOLOUR(0x4FAF1FAF), // height 238
+	MKCOLOUR(0x4F2727AF), // height 239
+	MKCOLOUR(0x4F2727AF), // height 240
+	MKCOLOUR(0x4F27AF27), // height 241
+	MKCOLOUR(0x4F27AF27), // height 242
+	MKCOLOUR(0x4F27AFAF), // height 243
+	MKCOLOUR(0x4F27AFAF), // height 244
+	MKCOLOUR(0x4FAF2727), // height 245
+	MKCOLOUR(0x4FAF2727), // height 246
+	MKCOLOUR(0x4FAF27AF), // height 247
+	MKCOLOUR(0x4FAF27AF), // height 248
+	MKCOLOUR(0x4FAFAF27), // height 249
+	MKCOLOUR(0x4FAFAF27), // height 250
+	MKCOLOUR(0x4FAFAFAF), // height 251
+	MKCOLOUR(0x4FAFAFAF), // height 252
+	MKCOLOUR(0x4FAFAFCF), // height 253
+	MKCOLOUR(0x4FAFAFCF), // height 254
+	MKCOLOUR(0x4FAFCFAF), // height 255
+	MKCOLOUR(0x4FCFAFAF), /* 1 extra color for people not liking the flood_warning feature. */
+	/* Flashing test with current parameters no longer needed. */
+	//MKCOLOUR(0x04dcdcdc), /* FLASHING TEST (You can use this when going for 512 colours.) */
+};
+assert_compile(lengthof(_green_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
+
+/**
+ * Height map colours for the dark green colour scheme, ordered by height.
+ * This is the original array for use when AllowMoreHeightlevels() is false.
+ */
+static const uint32 _dark_green_map_heights_old[] = {
+	MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
 	MKCOLOUR_XXXX(0x60),
 	MKCOLOUR_XYXY(0x60, 0x61),
 	MKCOLOUR_XXXX(0x61),
@@ -277,10 +692,308 @@
 	MKCOLOUR_XXXX(0x67),
 	MKCOLOUR_XXXX(0x67),
 };
-assert_compile(lengthof(_dark_green_map_heights) == MAX_TILE_HEIGHT + 1);
-
-/** Height map colours for the violet colour scheme, ordered by height. */
-static const uint32 _violet_map_heights[] = {
+assert_compile(lengthof(_dark_green_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
+
+/**
+ * Height map colours for the dark green colour scheme, ordered by height.
+ * Used when AllowMoreHeightlevels() is true.
+ * For the moment the aray is extended to 256 levels.
+ */
+static const uint32 _dark_green_map_heights_extended[] = {
+	/* First two colours are action colours.(First commented out, first we need level -1 (and underwater tunnels)) */
+	//MKCOLOUR(0xdcdcdcdc), // Nice flashy colour, darkblue. (Do not use above level 1. (second colour)) (I keep it here to become level -1 ground tile (not flooded) (For now: To see its full effect, use this as second color.Then imagine at level -1.))
+	MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
+	MKCOLOUR(0x60606060), // height 1 // original smallmap color do not modify
+	MKCOLOUR(0x60606060),
+	MKCOLOUR(0x60606061), // height 3
+	MKCOLOUR(0x60606061),
+	MKCOLOUR(0x60606160), // height 5
+	MKCOLOUR(0x60606160),
+	MKCOLOUR(0x60606161), // height 7
+	MKCOLOUR(0x60606161),
+	MKCOLOUR(0x60616060), // height 9
+	MKCOLOUR(0x60616060),
+	MKCOLOUR(0x60616061), // height 11 // original smallmap color do not modify
+	MKCOLOUR(0x60616061),
+	MKCOLOUR(0x60616160), // height 13
+	MKCOLOUR(0x60616160),
+	MKCOLOUR(0x60616161), // height 15
+	MKCOLOUR(0x60616161),
+	MKCOLOUR(0x61606060), // height 17
+	MKCOLOUR(0x61606060),
+	MKCOLOUR(0x61606061), // height 19
+	MKCOLOUR(0x61606061),
+	MKCOLOUR(0x61606160), // height 21
+	MKCOLOUR(0x61606160),
+	MKCOLOUR(0x61606161), // height 23
+	MKCOLOUR(0x61606161),
+	MKCOLOUR(0x61616060), // height 25
+	MKCOLOUR(0x61616060),
+	MKCOLOUR(0x61616061), // height 27
+	MKCOLOUR(0x61616061),
+	MKCOLOUR(0x61616160), // height 29
+	MKCOLOUR(0x61616160),
+	MKCOLOUR(0x61616161), // height 31 // original smallmap color do not modify
+	MKCOLOUR(0x61616161),
+	MKCOLOUR(0x61616162), // height 33
+	MKCOLOUR(0x61616162),
+	MKCOLOUR(0x61616261), // height 35
+	MKCOLOUR(0x61616261),
+	MKCOLOUR(0x61616262), // height 37
+	MKCOLOUR(0x61616262),
+	MKCOLOUR(0x61626161), // height 39
+	MKCOLOUR(0x61626161),
+	MKCOLOUR(0x61626162), // height 41 // original smallmap color do not modify
+	MKCOLOUR(0x61626162),
+	MKCOLOUR(0x61626261), // height 43
+	MKCOLOUR(0x61626261),
+	MKCOLOUR(0x61626262), // height 45
+	MKCOLOUR(0x61626262),
+	MKCOLOUR(0x62616161), // height 47
+	MKCOLOUR(0x62616161),
+	MKCOLOUR(0x62616162), // height 49
+	MKCOLOUR(0x62616162),
+	MKCOLOUR(0x62616261), // height 51
+	MKCOLOUR(0x62616261),
+	MKCOLOUR(0x62616262), // height 53
+	MKCOLOUR(0x62616262),
+	MKCOLOUR(0x62626161), // height 55
+	MKCOLOUR(0x62626161),
+	MKCOLOUR(0x62626162), // height 57
+	MKCOLOUR(0x62626162),
+	MKCOLOUR(0x62626261), // height 59
+	MKCOLOUR(0x62626261),
+	MKCOLOUR(0x62626262), // height 61 // original smallmap color do not modify
+	MKCOLOUR(0x62626262),
+	MKCOLOUR(0x62626263), // height 63
+	MKCOLOUR(0x62626263),
+	MKCOLOUR(0x62626362), // height 65
+	MKCOLOUR(0x62626362),
+	MKCOLOUR(0x62626363), // height 67
+	MKCOLOUR(0x62626363),
+	MKCOLOUR(0x62636262), // height 69
+	MKCOLOUR(0x62636262),
+	MKCOLOUR(0x62636263), // height 71 // original smallmap color do not modify
+	MKCOLOUR(0x62636263),
+	MKCOLOUR(0x62636362), // height 73
+	MKCOLOUR(0x62636362),
+	MKCOLOUR(0x62636363), // height 75
+	MKCOLOUR(0x62636363),
+	MKCOLOUR(0x63626262), // height 77
+	MKCOLOUR(0x63626262),
+	MKCOLOUR(0x63626263), // height 79
+	MKCOLOUR(0x63626263),
+	MKCOLOUR(0x63626362), // height 81
+	MKCOLOUR(0x63626362),
+	MKCOLOUR(0x63626363), // height 83
+	MKCOLOUR(0x63626363),
+	MKCOLOUR(0x63636262), // height 85
+	MKCOLOUR(0x63636262),
+	MKCOLOUR(0x63636263), // height 87
+	MKCOLOUR(0x63636263),
+	MKCOLOUR(0x63636362), // height 89
+	MKCOLOUR(0x63636362),
+	MKCOLOUR(0x63636363), // height 91 // original smallmap color do not modify
+	MKCOLOUR(0x63636363),
+	MKCOLOUR(0x63636364), // height 93
+	MKCOLOUR(0x63636364),
+	MKCOLOUR(0x63636463), // height 95
+	MKCOLOUR(0x63636463),
+	MKCOLOUR(0x63636464), // height 97
+	MKCOLOUR(0x63636464),
+	MKCOLOUR(0x63646363), // height 99
+	MKCOLOUR(0x63646363),
+	MKCOLOUR(0x63646364), // height 101 // original smallmap color do not modify
+	MKCOLOUR(0x63646364),
+	MKCOLOUR(0x63646463), // height 103
+	MKCOLOUR(0x63646463),
+	MKCOLOUR(0x63646464), // height 105
+	MKCOLOUR(0x63646464),
+	MKCOLOUR(0x64636363), // height 107
+	MKCOLOUR(0x64636363),
+	MKCOLOUR(0x64636364), // height 109
+	MKCOLOUR(0x64636364),
+	MKCOLOUR(0x64636463), // height 111
+	MKCOLOUR(0x64636463),
+	MKCOLOUR(0x64636464), // height 113
+	MKCOLOUR(0x64636464),
+	MKCOLOUR(0x64646363), // height 115
+	MKCOLOUR(0x64646363),
+	MKCOLOUR(0x64646364), // height 117
+	MKCOLOUR(0x64646364),
+	MKCOLOUR(0x64646463), // height 119
+	MKCOLOUR(0x64646463),
+	MKCOLOUR(0x64646464), // height 121 // original smallmap color do not modify
+	MKCOLOUR(0x64646464),
+	MKCOLOUR(0x64646465), // height 123
+	MKCOLOUR(0x64646465),
+	MKCOLOUR(0x64646564), // height 125
+	MKCOLOUR(0x64646564),
+	MKCOLOUR(0x64646565), // height 127
+	MKCOLOUR(0x64646565),
+	MKCOLOUR(0x64656464), // height 129
+	MKCOLOUR(0x64656464),
+	MKCOLOUR(0x64656465), // height 131 // original smallmap color do not modify
+	MKCOLOUR(0x64656465),
+	MKCOLOUR(0x64656564), // height 133
+	MKCOLOUR(0x64656564),
+	MKCOLOUR(0x64656565), // height 135
+	MKCOLOUR(0x64656565),
+	MKCOLOUR(0x65646464), // height 137
+	MKCOLOUR(0x65646464),
+	MKCOLOUR(0x65646465), // height 139
+	MKCOLOUR(0x65646465),
+	MKCOLOUR(0x65646564), // height 141
+	MKCOLOUR(0x65646564),
+	MKCOLOUR(0x65646565), // height 143
+	MKCOLOUR(0x65646565),
+	MKCOLOUR(0x65656464), // height 145
+	MKCOLOUR(0x65656464),
+	MKCOLOUR(0x65656465), // height 147
+	MKCOLOUR(0x65656465),
+	MKCOLOUR(0x65656564), // height 149
+	MKCOLOUR(0x65656564),
+	MKCOLOUR(0x65656565), // height 151 // original smallmap color do not modify
+	MKCOLOUR(0x65656565),
+	MKCOLOUR(0x65656566), // height 153
+	MKCOLOUR(0x65656566),
+	MKCOLOUR(0x65656665), // height 155
+	MKCOLOUR(0x65656665),
+	MKCOLOUR(0x65656666), // height 157
+	MKCOLOUR(0x65656666),
+	MKCOLOUR(0x65666565), // height 159
+	MKCOLOUR(0x65666565),
+	MKCOLOUR(0x65666566), // height 161 // original smallmap color do not modify
+	MKCOLOUR(0x65666566),
+	MKCOLOUR(0x65666665), // height 163
+	MKCOLOUR(0x65666665),
+	MKCOLOUR(0x65666666), // height 165
+	MKCOLOUR(0x65666666),
+	MKCOLOUR(0x66656565), // height 167
+	MKCOLOUR(0x66656565),
+	MKCOLOUR(0x66656566), // height 169
+	MKCOLOUR(0x66656566),
+	MKCOLOUR(0x66656665), // height 171
+	MKCOLOUR(0x66656665),
+	MKCOLOUR(0x66656666), // height 173
+	MKCOLOUR(0x66656666),
+	MKCOLOUR(0x66666565), // height 175
+	MKCOLOUR(0x66666565),
+	MKCOLOUR(0x66666566), // height 177
+	MKCOLOUR(0x66666566),
+	MKCOLOUR(0x66666665), // height 179
+	MKCOLOUR(0x66666665),
+	MKCOLOUR(0x66666666), // height 181 // original smallmap color do not modify
+	MKCOLOUR(0x66666666),
+	MKCOLOUR(0x66666667), // height 183
+	MKCOLOUR(0x66666667),
+	MKCOLOUR(0x66666766), // height 185
+	MKCOLOUR(0x66666766),
+	MKCOLOUR(0x66666767), // height 187
+	MKCOLOUR(0x66666767),
+	MKCOLOUR(0x66676666), // height 189
+	MKCOLOUR(0x66676666),
+	MKCOLOUR(0x66676667), // height 191 // original smallmap color do not modify
+	MKCOLOUR(0x66676667),
+	MKCOLOUR(0x66676766), // height 193
+	MKCOLOUR(0x66676766),
+	MKCOLOUR(0x66676767), // height 195
+	MKCOLOUR(0x66676767),
+	MKCOLOUR(0x67676767), // height 197 // original smallmap color do not modify
+	MKCOLOUR(0x67676767),
+
+// TODO: Extend. read: replace dummy (copied) colurs below
+
+//	MKCOLOUR(0x67676768), // browns or something do not use untill ...
+//	MKCOLOUR(0x67676868),
+//	MKCOLOUR(0x67686868),
+//	MKCOLOUR(0x68686868),
+//	MKCOLOUR(0x68686869),
+//	MKCOLOUR(0x69686869),
+//	MKCOLOUR(0x68686969),
+//	MKCOLOUR(0x68696969),
+//	MKCOLOUR(0x69696969),
+//	MKCOLOUR(0x6969696A),
+//	MKCOLOUR(0x69A96A6A),
+//	MKCOLOUR(0x6A6A6A6A),
+//	MKCOLOUR(0x6A6A6A6B),
+//	MKCOLOUR(0x6A6A6B6B),
+//	MKCOLOUR(0x6A6B6B6B),
+//	MKCOLOUR(0x6B6B6B6B), // ... here and probably a little further.
+
+	MKCOLOUR(0x67676767), // height 199
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 201
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 203
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 205
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 207
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 209
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 211
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 213
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 215
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 217
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 219
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 221
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 223
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 225
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 227
+	MKCOLOUR(0x67676767),
+	MKCOLOUR(0x67676767), // height 229
+	MKCOLOUR(0x67676767),
+
+// TODO: extend untill here
+
+	/* purple top */
+	MKCOLOUR(0x1F27AF27), // height 231
+	MKCOLOUR(0x1F27AF27), // height 232
+	MKCOLOUR(0x1F274FAF), // height 233
+	MKCOLOUR(0x1F274FAF), // height 234
+	MKCOLOUR(0x4F274FAF), // height 235
+	MKCOLOUR(0x4F274FAF), // height 236
+	MKCOLOUR(0x4FAF1FAF), // height 237
+	MKCOLOUR(0x4FAF1FAF), // height 238
+	MKCOLOUR(0x4F2727AF), // height 239
+	MKCOLOUR(0x4F2727AF), // height 240
+	MKCOLOUR(0x4F27AF27), // height 241
+	MKCOLOUR(0x4F27AF27), // height 242
+	MKCOLOUR(0x4F27AFAF), // height 243
+	MKCOLOUR(0x4F27AFAF), // height 244
+	MKCOLOUR(0x4FAF2727), // height 245
+	MKCOLOUR(0x4FAF2727), // height 246
+	MKCOLOUR(0x4FAF27AF), // height 247
+	MKCOLOUR(0x4FAF27AF), // height 248
+	MKCOLOUR(0x4FAFAF27), // height 249
+	MKCOLOUR(0x4FAFAF27), // height 250
+	MKCOLOUR(0x4FAFAFAF), // height 251
+	MKCOLOUR(0x4FAFAFAF), // height 252
+	MKCOLOUR(0x4FAFAFCF), // height 253
+	MKCOLOUR(0x4FAFAFCF), // height 254
+	MKCOLOUR(0x4FAFCFAF), // height 255
+	MKCOLOUR(0x4FCFAFAF), /* 1 extra color for people not liking the flood_warning feature. */
+	/* Flashing test with current parameters no longer needed. */
+	//MKCOLOUR(0x04dcdcdc), /* FLASHING TEST (You can use this when going for 512 colours.) */
+};
+assert_compile(lengthof(_dark_green_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
+
+/**
+ * Height map colours for the violet colour scheme, ordered by height.
+ * This is the original array for use when AllowMoreHeightlevels() is false.
+ */
+static const uint32 _violet_map_heights_old[] = {
+	MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
 	MKCOLOUR_XXXX(0x80),
 	MKCOLOUR_XYXY(0x80, 0x81),
 	MKCOLOUR_XXXX(0x81),
@@ -298,19 +1011,341 @@
 	MKCOLOUR_XXXX(0x87),
 	MKCOLOUR_XXXX(0x87),
 };
-assert_compile(lengthof(_violet_map_heights) == MAX_TILE_HEIGHT + 1);
+assert_compile(lengthof(_violet_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
+
+/**
+ * Height map colours for the violet colour scheme, ordered by height.
+ * Used when AllowMoreHeightlevels() is true.
+ * For the moment the aray is extended to 256 levels.
+ */
+static const uint32 _violet_map_heights_extended[] = {
+	/* First two colours are action colours.(First commented out, first we need level -1 (and underwater tunnels)) */
+	//MKCOLOUR(0xdcdcdcdc), // Nice flashy colour, darkblue. (Do not use above level 1. (second colour)) (I keep it here to become level -1 ground tile (not flooded) (For now: To see its full effect, use this as second color.Then imagine at level -1.))
+	MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
+	MKCOLOUR(0x80808080), // height 1 // original smallmap color do not modify
+	MKCOLOUR(0x80808080),
+	MKCOLOUR(0x80808081), // height 3
+	MKCOLOUR(0x80808081),
+	MKCOLOUR(0x80808180), // height 5
+	MKCOLOUR(0x80808180),
+	MKCOLOUR(0x80808181), // height 7
+	MKCOLOUR(0x80808181),
+	MKCOLOUR(0x80818080), // height 9
+	MKCOLOUR(0x80818080),
+	MKCOLOUR(0x80818081), // height 11 // original smallmap color do not modify
+	MKCOLOUR(0x80818081),
+	MKCOLOUR(0x80818180), // height 13
+	MKCOLOUR(0x80818180),
+	MKCOLOUR(0x80818181), // height 15
+	MKCOLOUR(0x80818181),
+	MKCOLOUR(0x81808080), // height 17
+	MKCOLOUR(0x81808080),
+	MKCOLOUR(0x81808081), // height 19
+	MKCOLOUR(0x81808081),
+	MKCOLOUR(0x81808180), // height 21
+	MKCOLOUR(0x81808180),
+	MKCOLOUR(0x81808181), // height 23
+	MKCOLOUR(0x81808181),
+	MKCOLOUR(0x81818080), // height 25
+	MKCOLOUR(0x81818080),
+	MKCOLOUR(0x81818081), // height 27
+	MKCOLOUR(0x81818081),
+	MKCOLOUR(0x81818180), // height 29
+	MKCOLOUR(0x81818180),
+	MKCOLOUR(0x81818181), // height 31 // original smallmap color do not modify
+	MKCOLOUR(0x81818181),
+	MKCOLOUR(0x81818182), // height 33
+	MKCOLOUR(0x81818182),
+	MKCOLOUR(0x81818281), // height 35
+	MKCOLOUR(0x81818281),
+	MKCOLOUR(0x81818282), // height 37
+	MKCOLOUR(0x81818282),
+	MKCOLOUR(0x81828181), // height 39
+	MKCOLOUR(0x81828181),
+	MKCOLOUR(0x81828182), // height 41 // original smallmap color do not modify
+	MKCOLOUR(0x81828182),
+	MKCOLOUR(0x81828281), // height 43
+	MKCOLOUR(0x81828281),
+	MKCOLOUR(0x81828282), // height 45
+	MKCOLOUR(0x81828282),
+	MKCOLOUR(0x82818181), // height 47
+	MKCOLOUR(0x82818181),
+	MKCOLOUR(0x82818182), // height 49
+	MKCOLOUR(0x82818182),
+	MKCOLOUR(0x82818281), // height 51
+	MKCOLOUR(0x82818281),
+	MKCOLOUR(0x82818282), // height 53
+	MKCOLOUR(0x82818282),
+	MKCOLOUR(0x82828181), // height 55
+	MKCOLOUR(0x82828181),
+	MKCOLOUR(0x82828182), // height 57
+	MKCOLOUR(0x82828182),
+	MKCOLOUR(0x82828281), // height 59
+	MKCOLOUR(0x82828281),
+	MKCOLOUR(0x82828282), // height 61 // original smallmap color do not modify
+	MKCOLOUR(0x82828282),
+	MKCOLOUR(0x82828283), // height 63
+	MKCOLOUR(0x82828283),
+	MKCOLOUR(0x82828382), // height 65
+	MKCOLOUR(0x82828382),
+	MKCOLOUR(0x82828383), // height 67
+	MKCOLOUR(0x82828383),
+	MKCOLOUR(0x82838282), // height 69
+	MKCOLOUR(0x82838282),
+	MKCOLOUR(0x82838283), // height 71 // original smallmap color do not modify
+	MKCOLOUR(0x82838283),
+	MKCOLOUR(0x82838382), // height 73
+	MKCOLOUR(0x82838382),
+	MKCOLOUR(0x82838383), // height 75
+	MKCOLOUR(0x82838383),
+	MKCOLOUR(0x83828282), // height 77
+	MKCOLOUR(0x83828282),
+	MKCOLOUR(0x83828283), // height 79
+	MKCOLOUR(0x83828283),
+	MKCOLOUR(0x83828382), // height 81
+	MKCOLOUR(0x83828382),
+	MKCOLOUR(0x83828383), // height 83
+	MKCOLOUR(0x83828383),
+	MKCOLOUR(0x83838282), // height 85
+	MKCOLOUR(0x83838282),
+	MKCOLOUR(0x83838283), // height 87
+	MKCOLOUR(0x83838283),
+	MKCOLOUR(0x83838382), // height 89
+	MKCOLOUR(0x83838382),
+	MKCOLOUR(0x83838383), // height 91 // original smallmap color do not modify
+	MKCOLOUR(0x83838383),
+	MKCOLOUR(0x83838384), // height 93
+	MKCOLOUR(0x83838384),
+	MKCOLOUR(0x83838483), // height 95
+	MKCOLOUR(0x83838483),
+	MKCOLOUR(0x83838484), // height 97
+	MKCOLOUR(0x83838484),
+	MKCOLOUR(0x83848383), // height 99
+	MKCOLOUR(0x83848383),
+	MKCOLOUR(0x83848384), // height 101 // original smallmap color do not modify
+	MKCOLOUR(0x83848384),
+	MKCOLOUR(0x83848483), // height 103
+	MKCOLOUR(0x83848483),
+	MKCOLOUR(0x83848484), // height 105
+	MKCOLOUR(0x83848484),
+	MKCOLOUR(0x84838383), // height 107
+	MKCOLOUR(0x84838383),
+	MKCOLOUR(0x84838384), // height 109
+	MKCOLOUR(0x84838384),
+	MKCOLOUR(0x84838483), // height 111
+	MKCOLOUR(0x84838483),
+	MKCOLOUR(0x84838484), // height 113
+	MKCOLOUR(0x84838484),
+	MKCOLOUR(0x84848383), // height 115
+	MKCOLOUR(0x84848383),
+	MKCOLOUR(0x84848384), // height 117
+	MKCOLOUR(0x84848384),
+	MKCOLOUR(0x84848483), // height 119
+	MKCOLOUR(0x84848483),
+	MKCOLOUR(0x84848484), // height 121 // original smallmap color do not modify
+	MKCOLOUR(0x84848484),
+	MKCOLOUR(0x84848485), // height 123
+	MKCOLOUR(0x84848485),
+	MKCOLOUR(0x84848584), // height 125
+	MKCOLOUR(0x84848584),
+	MKCOLOUR(0x84848585), // height 127
+	MKCOLOUR(0x84848585),
+	MKCOLOUR(0x84858484), // height 129
+	MKCOLOUR(0x84858484),
+	MKCOLOUR(0x84858485), // height 131 // original smallmap color do not modify
+	MKCOLOUR(0x84858485),
+	MKCOLOUR(0x84858584), // height 133
+	MKCOLOUR(0x84858584),
+	MKCOLOUR(0x84858585), // height 135
+	MKCOLOUR(0x84858585),
+	MKCOLOUR(0x85848484), // height 137
+	MKCOLOUR(0x85848484),
+	MKCOLOUR(0x85848485), // height 139
+	MKCOLOUR(0x85848485),
+	MKCOLOUR(0x85848584), // height 141
+	MKCOLOUR(0x85848584),
+	MKCOLOUR(0x85848585), // height 143
+	MKCOLOUR(0x85848585),
+	MKCOLOUR(0x85858484), // height 145
+	MKCOLOUR(0x85858484),
+	MKCOLOUR(0x85858485), // height 147
+	MKCOLOUR(0x85858485),
+	MKCOLOUR(0x85858584), // height 149
+	MKCOLOUR(0x85858584),
+	MKCOLOUR(0x85858585), // height 151 // original smallmap color do not modify
+	MKCOLOUR(0x85858585),
+	MKCOLOUR(0x85858586), // height 153
+	MKCOLOUR(0x85858586),
+	MKCOLOUR(0x85858685), // height 155
+	MKCOLOUR(0x85858685),
+	MKCOLOUR(0x85858686), // height 157
+	MKCOLOUR(0x85858686),
+	MKCOLOUR(0x85868585), // height 159
+	MKCOLOUR(0x85868585),
+	MKCOLOUR(0x85868586), // height 161 // original smallmap color do not modify
+	MKCOLOUR(0x85868586),
+	MKCOLOUR(0x85868685), // height 163
+	MKCOLOUR(0x85868685),
+	MKCOLOUR(0x85868686), // height 165
+	MKCOLOUR(0x85868686),
+	MKCOLOUR(0x85868585), // height 167
+	MKCOLOUR(0x85868585),
+	MKCOLOUR(0x85868586), // height 169
+	MKCOLOUR(0x85868586),
+	MKCOLOUR(0x85868685), // height 171
+	MKCOLOUR(0x85868685),
+	MKCOLOUR(0x85868686), // height 173
+	MKCOLOUR(0x85868686),
+	MKCOLOUR(0x86868585), // height 175
+	MKCOLOUR(0x86868585),
+	MKCOLOUR(0x86868586), // height 177
+	MKCOLOUR(0x86868586),
+	MKCOLOUR(0x86868685), // height 179
+	MKCOLOUR(0x86868685),
+	MKCOLOUR(0x86868686), // height 181 // original smallmap color do not modify
+	MKCOLOUR(0x86868686),
+	MKCOLOUR(0x86868687), // height 183
+	MKCOLOUR(0x86868687),
+	MKCOLOUR(0x86868786), // height 185
+	MKCOLOUR(0x86868786),
+	MKCOLOUR(0x86868787), // height 187
+	MKCOLOUR(0x86868787),
+	MKCOLOUR(0x86878686), // height 189
+	MKCOLOUR(0x86878686),
+	MKCOLOUR(0x86878687), // height 191 // original smallmap color do not modify
+	MKCOLOUR(0x86878687),
+	MKCOLOUR(0x86878786), // height 193
+	MKCOLOUR(0x86878786),
+	MKCOLOUR(0x86878787), // height 195
+	MKCOLOUR(0x86878787),
+	MKCOLOUR(0x87868686), // height 197
+	MKCOLOUR(0x87868686),
+	MKCOLOUR(0x87868687), // height 199
+	MKCOLOUR(0x87868687),
+	MKCOLOUR(0x87868786), // height 201
+	MKCOLOUR(0x87868786),
+	MKCOLOUR(0x87868787), // height 203
+	MKCOLOUR(0x87868787),
+	MKCOLOUR(0x87878686), // height 205
+	MKCOLOUR(0x87878686),
+	MKCOLOUR(0x87878687), // height 207
+	MKCOLOUR(0x87878687),
+	MKCOLOUR(0x87878786), // height 209
+	MKCOLOUR(0x87878786),
+	MKCOLOUR(0x87878787), // height 211 // original smallmap color do not modify
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 213 // original smallmap color do not modify
+	MKCOLOUR(0x87878787),
+
+// TODO: Extend. read: replace dummy (copied) colurs below
+
+//	MKCOLOUR(0x87878788), // don't use greys/blacks
+//	MKCOLOUR(0x87878788),
+//	MKCOLOUR(0x87878887),
+//	MKCOLOUR(0x87878887),
+//	MKCOLOUR(0x87878888),
+//	MKCOLOUR(0x87878888),
+//	MKCOLOUR(0x87888787),
+//	MKCOLOUR(0x87888787),
+//	MKCOLOUR(0x87888788),
+//	MKCOLOUR(0x87888788),
+//	MKCOLOUR(0x87888887),
+//	MKCOLOUR(0x87888887),
+//	MKCOLOUR(0x87888888),
+//	MKCOLOUR(0x87888888),
+//	MKCOLOUR(0x88878787),
+//	MKCOLOUR(0x88878788),
+//	MKCOLOUR(0x88878887),
+//	MKCOLOUR(0x88878888),
+//	MKCOLOUR(0x88888787),
+//	MKCOLOUR(0x88888788),
+//	MKCOLOUR(0x88888887),
+//	MKCOLOUR(0x88888888), // dont't use untill here probaby a little further too
+
+	MKCOLOUR(0x87878787), // height 215
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 217
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 219
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 221
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 223
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 225
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 227
+	MKCOLOUR(0x87878787),
+	MKCOLOUR(0x87878787), // height 229
+	MKCOLOUR(0x87878787),
+
+// TODO: extend untill here
+
+	/* purple top */
+	MKCOLOUR(0x1F27AF27), // height 231
+	MKCOLOUR(0x1F27AF27), // height 232
+	MKCOLOUR(0x1F274FAF), // height 233
+	MKCOLOUR(0x1F274FAF), // height 234
+	MKCOLOUR(0x4F274FAF), // height 235
+	MKCOLOUR(0x4F274FAF), // height 236
+	MKCOLOUR(0x4FAF1FAF), // height 237
+	MKCOLOUR(0x4FAF1FAF), // height 238
+	MKCOLOUR(0x4F2727AF), // height 239
+	MKCOLOUR(0x4F2727AF), // height 240
+	MKCOLOUR(0x4F27AF27), // height 241
+	MKCOLOUR(0x4F27AF27), // height 242
+	MKCOLOUR(0x4F27AFAF), // height 243
+	MKCOLOUR(0x4F27AFAF), // height 244
+	MKCOLOUR(0x4FAF2727), // height 245
+	MKCOLOUR(0x4FAF2727), // height 246
+	MKCOLOUR(0x4FAF27AF), // height 247
+	MKCOLOUR(0x4FAF27AF), // height 248
+	MKCOLOUR(0x4FAFAF27), // height 249
+	MKCOLOUR(0x4FAFAF27), // height 250
+	MKCOLOUR(0x4FAFAFAF), // height 251
+	MKCOLOUR(0x4FAFAFAF), // height 252
+	MKCOLOUR(0x4FAFAFCF), // height 253
+	MKCOLOUR(0x4FAFAFCF), // height 254
+	MKCOLOUR(0x4FAFCFAF), // height 255
+	MKCOLOUR(0x4FCFAFAF), /* 1 extra color for people not liking the flood_warning feature. */
+	/* Flashing test with current parameters no longer needed. */
+	//MKCOLOUR(0x04dcdcdc), /* FLASHING TEST (You can use this when going for 512 colours.) */
+};
+assert_compile(lengthof(_violet_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
+
+/**
+ * Colour Coding for Stuck Counter
+ */
+static const uint32 _stuck_counter_colours[] = {
+	MKCOLOUR(0xD0D0D0D0),
+	MKCOLOUR(0xCECECECE),
+	MKCOLOUR(0xBFBFBFBF),
+	MKCOLOUR(0xBDBDBDBD),
+	MKCOLOUR(0xBABABABA),
+	MKCOLOUR(0xB8B8B8B8),
+	MKCOLOUR(0xB6B6B6B6),
+	MKCOLOUR(0xB4B4B4B4),
+};
+assert_compile(lengthof(_stuck_counter_colours) == 8);
 
 /** Colour scheme of the smallmap. */
 struct SmallMapColourScheme {
 	const uint32 *height_colours; ///< Colour of each level in a heightmap.
-	uint32 default_colour;   ///< Default colour of the land.
+	uint32 default_colour;        ///< Default colour of the land.
 };
 
-/** Available colour schemes for height maps. */
-static const SmallMapColourScheme _heightmap_schemes[] = {
-	{_green_map_heights,      MKCOLOUR_XXXX(0x54)}, ///< Green colour scheme.
-	{_dark_green_map_heights, MKCOLOUR_XXXX(0x62)}, ///< Dark green colour scheme.
-	{_violet_map_heights,     MKCOLOUR_XXXX(0x82)}, ///< Violet colour scheme.
+/** Available colour schemes for height maps. (original) */
+static const SmallMapColourScheme _heightmap_schemes_old[] = {
+	{_green_map_heights_old,      MKCOLOUR_XXXX(0x54)}, ///< Green colour scheme.
+	{_dark_green_map_heights_old, MKCOLOUR_XXXX(0x62)}, ///< Dark green colour scheme.
+	{_violet_map_heights_old,     MKCOLOUR_XXXX(0x82)}, ///< Violet colour scheme.
+};
+
+/** Available colour schemes for height maps. (in case of AllowMoreHeightlevels() ) */
+static const SmallMapColourScheme _heightmap_schemes_extended[] = {
+	{_green_map_heights_extended,      MKCOLOUR(0x54545454)}, ///< Green colour scheme.
+	{_dark_green_map_heights_extended, MKCOLOUR(0x62626262)}, ///< Dark green colour scheme.
+	{_violet_map_heights_extended,     MKCOLOUR(0x82828282)}, ///< Violet colour scheme.
 };
 
 /**
@@ -318,8 +1353,14 @@
  */
 void BuildLandLegend()
 {
-	for (LegendAndColour *lc = _legend_land_contours; lc->legend == STR_TINY_BLACK_HEIGHT; lc++) {
-		lc->colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].height_colours[lc->height];
+	if (AllowMoreHeightlevels()) {
+		for (LegendAndColour *lc = _legend_land_contours_extended; lc->legend == STR_TINY_BLACK_HEIGHT; lc++) {
+			lc->colour = _heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour].height_colours[lc->height];
+		}
+	} else {
+		for (LegendAndColour *lc = _legend_land_contours_old; lc->legend == STR_TINY_BLACK_HEIGHT; lc++) {
+			lc->colour = _heightmap_schemes_old[_settings_client.gui.smallmap_land_colour].height_colours[lc->height];
+		}
 	}
 }
 
@@ -328,7 +1369,11 @@
  */
 void BuildOwnerLegend()
 {
-	_legend_land_owners[1].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].default_colour;
+	if (AllowMoreHeightlevels()) {
+		_legend_land_owners[1].colour = _heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour].default_colour;
+	} else {
+		_legend_land_owners[1].colour = _heightmap_schemes_old[_settings_client.gui.smallmap_land_colour].default_colour;
+	}
 
 	int i = NUM_NO_COMPANY_ENTRIES;
 	const Company *c;
@@ -359,7 +1404,6 @@
 	return (colour & mask->mand) | mask->mor;
 }
 
-
 /** Colour masks for "Contour" and "Routes" modes. */
 static const AndOr _smallmap_contours_andor[] = {
 	{MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_CLEAR
@@ -433,8 +1477,51 @@
  */
 static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
 {
-	const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
-	return ApplyMask(cs->height_colours[TileHeight(tile)], &_smallmap_contours_andor[t]);
+	uint tile_height = TileHeight(tile);
+
+	if (_settings_client.gui.smallmap_land_colour == 0) {
+		if (AllowMoreHeightlevels()) {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_green_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
+			} else {
+				return ApplyMask(_green_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
+			}
+		} else {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_green_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
+			} else {
+				return ApplyMask(_green_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
+			}
+		}
+	} else if (_settings_client.gui.smallmap_land_colour == 1) {
+		if (AllowMoreHeightlevels()) {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_dark_green_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
+			} else {
+				return ApplyMask(_dark_green_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
+			}
+		} else {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_dark_green_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
+			} else {
+				return ApplyMask(_dark_green_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
+			}
+		}
+	} else {
+		if (AllowMoreHeightlevels()) {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_violet_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
+			} else {
+				return ApplyMask(_violet_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
+			}
+		} else {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_violet_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
+			} else {
+				return ApplyMask(_violet_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
+			}
+		}
+	}
 }
 
 /**
@@ -446,8 +1533,13 @@
  */
 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
 {
-	const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
-	return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
+	if (AllowMoreHeightlevels()) {
+		const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
+		return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
+	} else {
+		const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
+		return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
+	}
 }
 
 /**
@@ -469,8 +1561,49 @@
 		}
 	}
 
-	const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
-	return ApplyMask(_smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour, &_smallmap_vehicles_andor[t]);
+	if (_settings_client.gui.smallmap_land_colour == 0) {
+		if (AllowMoreHeightlevels()) {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
+			} else {
+				return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
+			}
+		} else {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
+			} else {
+				return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
+			}
+		}
+	} else if (_settings_client.gui.smallmap_land_colour == 1) {
+		if (AllowMoreHeightlevels()) {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
+			} else {
+				return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
+			}
+		} else {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
+			} else {
+				return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
+			}
+		}
+	} else {
+		if (AllowMoreHeightlevels()) {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
+			} else {
+				return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
+			}
+		} else {
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
+			} else {
+				return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
+			}
+		}
+	}
 }
 
 /**
@@ -480,6 +1613,40 @@
  * @param t    Effective tile type of the tile (see #GetEffectiveTileType).
  * @return The colour of tile  in the small map in mode "Routes"
  */
+static inline uint32 GetSmallMapStuckRoutesPixels(TileIndex tile, TileType t)
+{
+	if (t == MP_STATION) {
+		switch (GetStationType(tile)) {
+			case STATION_RAIL:    return MKCOLOUR(0x56565656);
+			case STATION_AIRPORT: return MKCOLOUR(0xB8B8B8B8);
+			case STATION_TRUCK:   return MKCOLOUR(0xC2C2C2C2);
+			case STATION_BUS:     return MKCOLOUR(0xBFBFBFBF);
+			case STATION_DOCK:    return MKCOLOUR(0x98989898);
+			default:              return MKCOLOUR(0xFFFFFFFF);
+		}
+	} else if (t == MP_RAILWAY) {
+		byte c = GetStuckCounter(tile);
+		if (c==0) return 0;
+		return _stuck_counter_colours[c/32];
+	}
+
+	/* Ground colour */
+	if (AllowMoreHeightlevels()) {
+		const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
+		return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
+	} else {
+		const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
+		return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
+	}
+}
+
+/**
+ * Return the colour a tile would be displayed with in the small map in mode "link stats" while showing height is disabled.
+ *
+ * @param tile The tile of which we would like to get the colour.
+ * @param t    Effective tile type of the tile (see #GetEffectiveTileType).
+ * @return The colour of tile  in the small map in mode "Routes"
+ */
 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
 {
 	if (t == MP_STATION) {
@@ -497,15 +1664,36 @@
 			_smallmap_contours_andor[t].mand
 		};
 
-		const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
-		return ApplyMask(cs->default_colour, &andor);
+		if (AllowMoreHeightlevels()) {
+			const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
+			return ApplyMask(cs->default_colour, &andor);
+		} else {
+			const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
+			return ApplyMask(cs->default_colour, &andor);
+		}
 	}
 
 	/* Ground colour */
-	const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
-	return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
+	if (AllowMoreHeightlevels()) {
+		const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
+		return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
+	} else {
+		const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
+		return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
+	}
 }
 
+/**
+ * Return the colour a tile would be displayed with in the small map in mode "link stats".
+ *
+ * @param tile The tile of which we would like to get the colour.
+ * @param t    Effective tile type of the tile (see #GetEffectiveTileType).
+ * @return The colour of tile in the small map in mode "link stats"
+ */
+static inline uint32 GetSmallMapLinkStatsPixels(TileIndex tile, TileType t)
+{
+	return _smallmap_show_heightmap ? GetSmallMapContoursPixels(tile, t) : GetSmallMapRoutesPixels(tile, t);
+}
 
 static const uint32 _vegetation_clear_bits[] = {
 	MKCOLOUR_XXXX(PC_GRASS_LAND), ///< full grass
@@ -568,8 +1756,22 @@
 
 	if ((o < MAX_COMPANIES && !_legend_land_owners[_company_to_list_pos[o]].show_on_map) || o == OWNER_NONE || o == OWNER_WATER) {
 		if (t == MP_WATER) return MKCOLOUR_XXXX(PC_WATER);
-		const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
-		return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour;
+		if (AllowMoreHeightlevels()) {
+			const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour;
+			} else {
+				return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile) + 1] : cs->default_colour;
+
+			}
+		} else {
+			const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
+			if(_settings_client.gui.smallmap_flood_warning) {
+				return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour;
+			} else {
+				return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile) + 1] : cs->default_colour;
+			}
+		}
 	} else if (o == OWNER_TOWN) {
 		return MKCOLOUR_XXXX(PC_DARK_RED);
 	}
@@ -577,11 +1779,45 @@
 	return MKCOLOUR_XXXX(_legend_land_owners[_company_to_list_pos[o]].colour);
 }
 
+static Point TileCoordFromScreenCoord(int x, int y)
+{
+	/*  What we calculate here is the inverse function of RemapCoords,
+	 *  assuming z = 0 in RemapCoords.
+	 */
+	Point pt;
+	pt.x = (2 * y - x) / 4;
+	pt.y = (x + 2 * y) / 4;
+	return pt;
+}
+
 /** Vehicle colours in #SMT_VEHICLES mode. Indexed by #VehicleTypeByte. */
 static const byte _vehicle_type_colours[6] = {
 	PC_RED, PC_YELLOW, PC_LIGHT_BLUE, PC_WHITE, PC_BLACK, PC_RED
 };
 
+/**
+ * Draw a square symbolizing a producer of cargo in the link stats view.
+ * @param x the x coordinate of the middle of the vertex
+ * @param y the y coordinate of the middle of the vertex
+ * @param size the x and y extend of the vertex
+ * @param colour the colour with which the vertex will be filled
+ * @param border_colour the colour for the border of the vertex
+ */
+void DrawVertex(int x, int y, int size, int colour, int border_colour)
+{
+	size--;
+	int w1 = size / 2;
+	int w2 = size / 2 + size % 2;
+
+	GfxFillRect(x - w1, y - w1, x + w2, y + w2, colour);
+
+	w1++;
+	w2++;
+	GfxDrawLine(x - w1, y - w1, x + w2, y - w1, border_colour);
+	GfxDrawLine(x - w1, y + w2, x + w2, y + w2, border_colour);
+	GfxDrawLine(x - w1, y - w1, x - w1, y + w2, border_colour);
+	GfxDrawLine(x + w2, y - w1, x + w2, y + w2, border_colour);
+}
 
 /** Class managing the smallmap window. */
 class SmallMapWindow : public Window {
@@ -590,11 +1826,33 @@
 		SMT_CONTOUR,
 		SMT_VEHICLES,
 		SMT_INDUSTRY,
+		SMT_LINKSTATS,
 		SMT_ROUTES,
 		SMT_VEGETATION,
 		SMT_OWNER,
 	};
 
+	/**
+	 * Save the Vehicle's old position here, so that we don't get glitches when
+	 * redrawing.
+	 * The glitches happen when a vehicle occupies a larger area (zoom-in) and
+	 * a partial redraw happens which only covers part of the vehicle. If the
+	 * vehicle has moved in the meantime, it looks ugly afterwards.
+	 */
+	struct VehicleAndPosition {
+		VehicleAndPosition(const Vehicle *v) : vehicle(v->index)
+		{
+			this->position.x = v->x_pos;
+			this->position.y = v->y_pos;
+		}
+
+		Point position;
+		VehicleID vehicle;
+	};
+
+	typedef std::list<VehicleAndPosition> VehicleList;
+	VehicleList vehicles_on_map; ///< cached vehicle positions to avoid glitches
+	
 	/** Available kinds of zoomlevel changes. */
 	enum ZoomLevelChange {
 		ZLC_INITIALIZE, ///< Initialize zoom level.
@@ -610,12 +1868,85 @@
 	uint min_number_of_fixed_rows; ///< Minimal number of rows in the legends for the fixed layouts only (all except #SMT_INDUSTRY).
 	uint column_width;             ///< Width of a column in the #SM_WIDGET_LEGEND widget.
 
+	bool HasButtons()
+	{
+		return this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER;
+	}
+
+	Point cursor;
+
+	struct BaseCargoDetail {
+		BaseCargoDetail()
+		{
+			this->Clear();
+		}
+
+		void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow)
+		{
+			this->capacity += orig_link.Capacity();
+			this->usage += orig_link.Usage();
+			this->planned += orig_flow.Planned();
+			this->sent += orig_flow.Sent();
+		}
+
+		void Clear()
+		{
+			this->capacity = this->usage = this->planned = this->sent = 0;
+		}
+
+		uint capacity;
+		uint usage;
+		uint planned;
+		uint sent;
+	};
+
+	struct CargoDetail : public BaseCargoDetail {
+		CargoDetail(const LegendAndColour * c, const LinkStat &ls, const FlowStat &fs) : legend(c)
+		{
+			this->AddLink(ls, fs);
+		}
+
+		const LegendAndColour *legend;
+	};
+
+	typedef std::vector<CargoDetail> StatVector;
+
+	struct LinkDetails {
+		LinkDetails() {this->Clear();}
+
+		StationID sta;
+		StationID stb;
+		StatVector a_to_b;
+		StatVector b_to_a;
+
+		void Clear()
+		{
+			this->sta = INVALID_STATION;
+			this->stb = INVALID_STATION;
+			this->a_to_b.clear();
+			this->b_to_a.clear();
+		}
+
+		bool Empty() const
+		{
+			return this->sta == INVALID_STATION;
+		}
+	};
+
+	/**
+	 * those are detected while drawing the links and used when drawing
+	 * the legend. They don't represent game state.
+	 */
+	mutable LinkDetails link_details;
+	mutable StationID supply_details;
+
 	int32 scroll_x;  ///< Horizontal world coordinate of the base tile left of the top-left corner of the smallmap display.
 	int32 scroll_y;  ///< Vertical world coordinate of the base tile left of the top-left corner of the smallmap display.
 	int32 subscroll; ///< Number of pixels (0..3) between the right end of the base tile and the pixel at the top-left corner of the smallmap display.
 	int zoom;        ///< Zoom level. Bigger number means more zoom-out (further away).
 
 	static const uint8 FORCE_REFRESH_PERIOD = 0x1F; ///< map is redrawn after that many ticks
+	static const uint8 REFRESH_NEXT_TICK = 1;       ///< if refreh has this value the map is redrawn in the next tick
 	uint8 refresh; ///< refresh counter, zeroed every FORCE_REFRESH_PERIOD ticks
 
 	/**
@@ -626,43 +1957,61 @@
 	 */
 	FORCEINLINE Point RemapTile(int tile_x, int tile_y) const
 	{
-		int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
-		int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
-
-		if (this->zoom == 1) return RemapCoords(x_offset, y_offset, 0);
-
-		/* For negative offsets, round towards -inf. */
-		if (x_offset < 0) x_offset -= this->zoom - 1;
-		if (y_offset < 0) y_offset -= this->zoom - 1;
-
-		return RemapCoords(x_offset / this->zoom, y_offset / this->zoom, 0);
+		if (this->zoom > 0) {
+			int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
+			int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
+
+			/* For negative offsets, round towards -inf. */
+			if (x_offset < 0) x_offset -= this->zoom - 1;
+			if (y_offset < 0) y_offset -= this->zoom - 1;
+
+			return RemapCoords(x_offset / this->zoom, y_offset / this->zoom, 0);
+		} else {
+			int x_offset = tile_x * (-this->zoom) - this->scroll_x * (-this->zoom) / (int)TILE_SIZE;
+			int y_offset = tile_y * (-this->zoom) - this->scroll_y * (-this->zoom) / (int)TILE_SIZE;
+
+			return RemapCoords(x_offset, y_offset, 0);
+		}
 	}
 
 	/**
-	 * Determine the tile relative to the base tile of the smallmap, and the pixel position at
-	 * that tile for a point in the smallmap.
+	 * Determine the world coordinates relative to the base tile of the smallmap, and the pixel position at
+	 * that location for a point in the smallmap.
 	 * @param px       Horizontal coordinate of the pixel.
 	 * @param py       Vertical coordinate of the pixel.
 	 * @param sub[out] Pixel position at the tile (0..3).
 	 * @param add_sub  Add current #subscroll to the position.
-	 * @return Tile being displayed at the given position relative to #scroll_x and #scroll_y.
+	 * @return world coordinates being displayed at the given position relative to #scroll_x and #scroll_y.
 	 * @note The #subscroll offset is already accounted for.
 	 */
-	FORCEINLINE Point PixelToTile(int px, int py, int *sub, bool add_sub = true) const
+	FORCEINLINE Point PixelToWorld(int px, int py, int *sub, bool add_sub = true) const
 	{
 		if (add_sub) px += this->subscroll;  // Total horizontal offset.
 
 		/* For each two rows down, add a x and a y tile, and
 		 * For each four pixels to the right, move a tile to the right. */
-		Point pt = {((py >> 1) - (px >> 2)) * this->zoom, ((py >> 1) + (px >> 2)) * this->zoom};
+		Point pt = {
+			((py >> 1) - (px >> 2)) * TILE_SIZE,
+			((py >> 1) + (px >> 2)) * TILE_SIZE
+		};
+
+		if (this->zoom > 0) {
+			pt.x *= this->zoom;
+			pt.y *= this->zoom;
+		} else {
+			pt.x /= (-this->zoom);
+			pt.y /= (-this->zoom);
+		}
+
 		px &= 3;
 
 		if (py & 1) { // Odd number of rows, handle the 2 pixel shift.
+			int offset = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
 			if (px < 2) {
-				pt.x += this->zoom;
+				pt.x += offset;
 				px += 2;
 			} else {
-				pt.y += this->zoom;
+				pt.y += offset;
 				px -= 2;
 			}
 		}
@@ -685,19 +2034,21 @@
 		assert(x >= 0 && y >= 0);
 
 		int new_sub;
-		Point tile_xy = PixelToTile(x, y, &new_sub, false);
+		Point tile_xy = PixelToWorld(x, y, &new_sub, false);
 		tx -= tile_xy.x;
 		ty -= tile_xy.y;
 
+		int offset = this->zoom < 0 ? TILE_SIZE / (-this->zoom) : this->zoom * TILE_SIZE;
+
 		Point scroll;
 		if (new_sub == 0) {
 			*sub = 0;
-			scroll.x = (tx + this->zoom) * TILE_SIZE;
-			scroll.y = (ty - this->zoom) * TILE_SIZE;
+			scroll.x = tx + offset;
+			scroll.y = ty - offset;
 		} else {
 			*sub = 4 - new_sub;
-			scroll.x = (tx + 2 * this->zoom) * TILE_SIZE;
-			scroll.y = (ty - 2 * this->zoom) * TILE_SIZE;
+			scroll.x = tx + 2 * offset;
+			scroll.y = ty - 2 * offset;
 		}
 		return scroll;
 	}
@@ -710,16 +2061,17 @@
 	 */
 	void SetZoomLevel(ZoomLevelChange change, const Point *zoom_pt)
 	{
-		static const int zoomlevels[] = {1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
+		static const int zoomlevels[] = {-4, -2, 1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
 		static const int MIN_ZOOM_INDEX = 0;
+		static const int DEFAULT_ZOOM_INDEX = 2;
 		static const int MAX_ZOOM_INDEX = lengthof(zoomlevels) - 1;
 
 		int new_index, cur_index, sub;
-		Point tile;
+		Point position;
 		switch (change) {
 			case ZLC_INITIALIZE:
 				cur_index = - 1; // Definitely different from new_index.
-				new_index = MIN_ZOOM_INDEX;
+				new_index = DEFAULT_ZOOM_INDEX;
 				break;
 
 			case ZLC_ZOOM_IN:
@@ -729,7 +2081,7 @@
 				}
 				assert(cur_index <= MAX_ZOOM_INDEX);
 
-				tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
+				position = this->PixelToWorld(zoom_pt->x, zoom_pt->y, &sub);
 				new_index = Clamp(cur_index + ((change == ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
 				break;
 
@@ -739,9 +2091,9 @@
 		if (new_index != cur_index) {
 			this->zoom = zoomlevels[new_index];
 			if (cur_index >= 0) {
-				Point new_tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
-				this->SetNewScroll(this->scroll_x + (tile.x - new_tile.x) * TILE_SIZE,
-						this->scroll_y + (tile.y - new_tile.y) * TILE_SIZE, sub);
+				Point new_pos = this->PixelToWorld(zoom_pt->x, zoom_pt->y, &sub);
+				this->SetNewScroll(this->scroll_x + position.x - new_pos.x,
+						this->scroll_y + position.y - new_pos.y, sub);
 			}
 			this->SetWidgetDisabledState(SM_WIDGET_ZOOM_IN,  this->zoom == zoomlevels[MIN_ZOOM_INDEX]);
 			this->SetWidgetDisabledState(SM_WIDGET_ZOOM_OUT, this->zoom == zoomlevels[MAX_ZOOM_INDEX]);
@@ -780,7 +2132,7 @@
 				return GetSmallMapIndustriesPixels(tile, et);
 
 			case SMT_ROUTES:
-				return GetSmallMapRoutesPixels(tile, et);
+				return GetSmallMapStuckRoutesPixels(tile, et);
 
 			case SMT_VEGETATION:
 				return GetSmallMapVegetationPixels(tile, et);
@@ -788,6 +2140,9 @@
 			case SMT_OWNER:
 				return GetSmallMapOwnerPixels(tile, et);
 
+			case SMT_LINKSTATS:
+				return GetSmallMapLinkStatsPixels(tile, et);
+
 			default: NOT_REACHED();
 		}
 	}
@@ -796,8 +2151,8 @@
 	 * Draws one column of tiles of the small map in a certain mode onto the screen buffer, skipping the shifted rows in between.
 	 *
 	 * @param dst Pointer to a part of the screen buffer to write to.
-	 * @param xc The X coordinate of the first tile in the column.
-	 * @param yc The Y coordinate of the first tile in the column
+	 * @param xc The world X coordinate of the rightmost place in the column.
+	 * @param yc The world Y coordinate of the topmost place in the column.
 	 * @param pitch Number of pixels to advance in the screen buffer each time a pixel is written.
 	 * @param reps Number of lines to draw
 	 * @param start_pos Position of first pixel to draw.
@@ -811,9 +2166,12 @@
 		void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
 		uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
 
+		int increment = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
+		int extent = this->zoom > 0 ? this->zoom : 1;
+
 		do {
 			/* Check if the tile (xc,yc) is within the map range */
-			if (xc >= MapMaxX() || yc >= MapMaxY()) continue;
+			if (xc / TILE_SIZE >= MapMaxX() || yc / TILE_SIZE >= MapMaxY()) continue;
 
 			/* Check if the dst pointer points to a pixel inside the screen buffer */
 			if (dst < _screen.dst_ptr) continue;
@@ -821,12 +2179,12 @@
 
 			/* Construct tilearea covered by (xc, yc, xc + this->zoom, yc + this->zoom) such that it is within min_xy limits. */
 			TileArea ta;
-			if (min_xy == 1 && (xc == 0 || yc == 0)) {
-				if (this->zoom == 1) continue; // The tile area is empty, don't draw anything.
-
-				ta = TileArea(TileXY(max(min_xy, xc), max(min_xy, yc)), this->zoom - (xc == 0), this->zoom - (yc == 0));
+			if (min_xy == 1 && (xc < TILE_SIZE || yc < TILE_SIZE)) {
+				if (this->zoom <= 1) continue; // The tile area is empty, don't draw anything.
+
+				ta = TileArea(TileXY(max(min_xy, xc / TILE_SIZE), max(min_xy, yc / TILE_SIZE)), this->zoom - (xc < TILE_SIZE), this->zoom - (yc < TILE_SIZE));
 			} else {
-				ta = TileArea(TileXY(xc, yc), this->zoom, this->zoom);
+				ta = TileArea(TileXY(xc / TILE_SIZE, yc / TILE_SIZE), extent, extent);
 			}
 			ta.ClampToMap(); // Clamp to map boundaries (may contain MP_VOID tiles!).
 
@@ -838,7 +2196,7 @@
 				idx++;
 			}
 		/* Switch to next tile in the column */
-		} while (xc += this->zoom, yc += this->zoom, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
+		} while (xc += increment, yc += increment, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
 	}
 
 	/**
@@ -848,36 +2206,585 @@
 	 */
 	void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
 	{
-		const Vehicle *v;
-		FOR_ALL_VEHICLES(v) {
-			if (v->type == VEH_EFFECT) continue;
-			if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
+		for(VehicleList::const_iterator i = this->vehicles_on_map.begin(); i != this->vehicles_on_map.end(); ++i) {
+			const Vehicle *v = Vehicle::GetIfValid(i->vehicle);
+			if (v == NULL) continue;
 
 			/* Remap into flat coordinates. */
-			Point pt = this->RemapTile(v->x_pos / TILE_SIZE, v->y_pos / TILE_SIZE);
+			Point pt = RemapTile(i->position.x / (int)TILE_SIZE, i->position.y / (int)TILE_SIZE);
 
 			int y = pt.y - dpi->top;
-			if (!IsInsideMM(y, 0, dpi->height)) continue; // y is out of bounds.
-
-			bool skip = false; // Default is to draw both pixels.
 			int x = pt.x - this->subscroll - 3 - dpi->left; // Offset X coordinate.
-			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;
-			}
+
+			int scale = this->zoom < 0 ? -this->zoom : 1;
 
 			/* Calculate pointer to pixel and the colour */
 			byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
 
-			/* And draw either one or two pixels depending on clipping */
-			blitter->SetPixel(dpi->dst_ptr, x, y, colour);
-			if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
+			/* Draw rhombus */
+			for (int dy = 0; dy < scale; dy++) {
+				for (int dx = 0; dx < scale; dx++) {
+					Point pt = RemapCoords(dx, dy, 0);
+					if (IsInsideMM(y + pt.y, 0, dpi->height)) {
+						if (IsInsideMM(x + pt.x, 0, dpi->width)) {
+							blitter->SetPixel(dpi->dst_ptr, x + pt.x, y + pt.y, colour);
+						}
+						if (IsInsideMM(x + pt.x + 1, 0, dpi->width)) {
+							blitter->SetPixel(dpi->dst_ptr, x + pt.x + 1, y + pt.y, colour);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	FORCEINLINE Point GetStationMiddle(const Station *st) const
+	{
+		int x = (st->rect.right + st->rect.left + 1) / 2;
+		int y = (st->rect.bottom + st->rect.top + 1) / 2;
+		Point ret = this->RemapTile(x, y);
+		ret.x -= 3 + this->subscroll;
+		if (this->zoom < 0) {
+			/* add half a tile if width or height is odd */
+			if (((st->rect.bottom - st->rect.top) & 1) == 0) {
+				Point offset = RemapCoords(0, -this->zoom / 2, 0);
+				ret.x += offset.x;
+				ret.y += offset.y;
+			}
+			if (((st->rect.right - st->rect.left) & 1) == 0) {
+				Point offset = RemapCoords(-this->zoom / 2, 0, 0);
+				ret.x += offset.x;
+				ret.y += offset.y;
+			}
+		}
+		return ret;
+	}
+
+	StationID DrawStationDots() const
+	{
+		const Station *supply_details = NULL;
+
+		const Station *st;
+		FOR_ALL_STATIONS(st) {
+			if (((st->owner != _local_company && Company::IsValidID(st->owner)) ||
+					st->rect.IsEmpty()) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
+
+			Point pt = GetStationMiddle(st);
+
+			if (supply_details == NULL && CheckStationSelected(&pt)) {
+				supply_details = st;
+			}
+
+			/* Add up cargo supplied for each selected cargo type */
+			uint q = 0;
+			int colour = 0;
+			int numCargos = 0;
+
+			if (AllowMoreHeightlevels()) {
+				for (int i = 0; i < _smallmap_cargo_count; ++i) {
+					const LegendAndColour &tbl = _legend_table_extended[this->map_type][i];
+					if (!tbl.show_on_map && supply_details != st) continue;
+					uint supply = st->goods[tbl.type].supply;
+					if (supply > 0) {
+						q += supply;
+						colour += tbl.colour;
+						numCargos++;
+					}
+				}
+
+			} else {
+				for (int i = 0; i < _smallmap_cargo_count; ++i) {
+					const LegendAndColour &tbl = _legend_table_old[this->map_type][i];
+					if (!tbl.show_on_map && supply_details != st) continue;
+					uint supply = st->goods[tbl.type].supply;
+					if (supply > 0) {
+						q += supply;
+						colour += tbl.colour;
+						numCargos++;
+					}
+				}
+			}
+
+			if (numCargos > 1) colour /= numCargos;
+
+			uint r = 2;
+			if (q >= 10) r++;
+			if (q >= 20) r++;
+			if (q >= 40) r++;
+			if (q >= 80) r++;
+			if (q >= 160) r++;
+
+			DrawVertex(pt.x, pt.y, r, colour, _colour_gradient[COLOUR_GREY][supply_details == st ? 3 : 1]);
+		}
+		return (supply_details == NULL) ? INVALID_STATION : supply_details->index;
+	}
+
+	class LinkDrawer {
+
+	protected:
+		virtual void DrawContent() = 0;
+		virtual void Highlight() {}
+		virtual void AddLink(const LinkStat &orig_link, const FlowStat &orig_flow, const LegendAndColour &cargo_entry) = 0;
+
+		FORCEINLINE bool IsLinkVisible()
+		{
+			const NWidgetBase *wi = this->window->GetWidget<NWidgetCore>(SM_WIDGET_MAP);
+			return !((this->pta.x < 0 && this->ptb.x < 0) ||
+					(this->pta.y < 0 && this->ptb.y < 0) ||
+					(this->pta.x > (int)wi->current_x && this->ptb.x > (int)wi->current_x) ||
+					(this->pta.y > (int)wi->current_y && this->ptb.y > (int)wi->current_y));
+		}
+
+		Point pta, ptb;
+		bool search_link_details;
+		LinkDetails link_details;
+		const SmallMapWindow *window;
+
+		void DrawLink(StationID sta, StationID stb)
+		{
+			bool highlight_empty = this->search_link_details && this->link_details.Empty();
+			bool highlight =
+					(sta == this->link_details.sta && stb == this->link_details.stb) ||
+					(highlight_empty && window->CheckLinkSelected(&this->pta, &this->ptb));
+			bool reverse_empty = this->link_details.b_to_a.empty();
+			bool reverse_highlight = (sta == this->link_details.stb && stb == this->link_details.sta);
+			if (highlight_empty && highlight) {
+				this->link_details.sta = sta;
+				this->link_details.stb = stb;
+			}
+
+			if (highlight || reverse_highlight) {
+				this->Highlight();
+			}
+
+			if (AllowMoreHeightlevels()) {
+				for (int i = 0; i < _smallmap_cargo_count; ++i) {
+					const LegendAndColour &cargo_entry = _legend_table_extended[window->map_type][i];
+					CargoID cargo = cargo_entry.type;
+					if (cargo_entry.show_on_map || highlight || reverse_highlight) {
+						GoodsEntry &ge = Station::Get(sta)->goods[cargo];
+						FlowStat sum_flows = ge.GetSumFlowVia(stb);
+						const LinkStatMap &ls_map = ge.link_stats;
+						LinkStatMap::const_iterator i = ls_map.find(stb);
+						if (i != ls_map.end()) {
+							const LinkStat &link_stat = i->second;
+							this->AddLink(link_stat, sum_flows, cargo_entry);
+							if (highlight_empty && highlight) {
+								this->link_details.a_to_b.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
+							} else if (reverse_empty && reverse_highlight) {
+								this->link_details.b_to_a.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
+							}
+						}
+					}
+				}
+
+			} else {
+				for (int i = 0; i < _smallmap_cargo_count; ++i) {
+					const LegendAndColour &cargo_entry = _legend_table_old[window->map_type][i];
+					CargoID cargo = cargo_entry.type;
+					if (cargo_entry.show_on_map || highlight || reverse_highlight) {
+						GoodsEntry &ge = Station::Get(sta)->goods[cargo];
+						FlowStat sum_flows = ge.GetSumFlowVia(stb);
+						const LinkStatMap &ls_map = ge.link_stats;
+						LinkStatMap::const_iterator i = ls_map.find(stb);
+						if (i != ls_map.end()) {
+							const LinkStat &link_stat = i->second;
+							this->AddLink(link_stat, sum_flows, cargo_entry);
+							if (highlight_empty && highlight) {
+								this->link_details.a_to_b.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
+							} else if (reverse_empty && reverse_highlight) {
+								this->link_details.b_to_a.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
+							}
+						}
+					}
+				}
+			}
+		}
+
+		virtual void DrawForwBackLinks(StationID sta, StationID stb)
+		{
+			this->DrawLink(sta, stb);
+			this->DrawContent();
+			Swap(this->pta, this->ptb);
+			this->DrawLink(stb, sta);
+			this->DrawContent();
+		}
+
+	public:
+		virtual ~LinkDrawer() {}
+
+		LinkDetails DrawLinks(const SmallMapWindow * w, bool search)
+		{
+			this->link_details.Clear();
+			this->window = w;
+			this->search_link_details = search;
+			std::set<StationID> seen_stations;
+			std::set<std::pair<StationID, StationID> > seen_links;
+
+			const Station *sta;
+			if (AllowMoreHeightlevels()) {
+				FOR_ALL_STATIONS(sta) {
+					if (sta->owner != _local_company && Company::IsValidID(sta->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
+
+					for (int i = 0; i < _smallmap_cargo_count; ++i) {
+						const LegendAndColour &tbl = _legend_table_extended[window->map_type][i];
+						if (!tbl.show_on_map) continue;
+
+						CargoID c = tbl.type;
+						const LinkStatMap &links = sta->goods[c].link_stats;
+						for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
+							StationID from = sta->index;
+							StationID to = i->first;
+							if (Station::IsValidID(to) && seen_stations.find(to) == seen_stations.end()) {
+								const Station *stb = Station::Get(to);
+
+								if (stb->owner != _local_company && Company::IsValidID(stb->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
+								if (sta->rect.IsEmpty() || stb->rect.IsEmpty()) continue;
+								if (seen_links.find(std::make_pair(to, from)) != seen_links.end()) continue;
+
+								this->pta = this->window->GetStationMiddle(sta);
+								this->ptb = this->window->GetStationMiddle(stb);
+								if (!this->IsLinkVisible()) continue;
+
+								this->DrawForwBackLinks(sta->index, stb->index);
+								seen_stations.insert(to);
+							}
+							seen_links.insert(std::make_pair(from, to));
+						}
+					}
+					seen_stations.clear();
+				}
+
+			} else {
+				FOR_ALL_STATIONS(sta) {
+					if (sta->owner != _local_company && Company::IsValidID(sta->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
+
+					for (int i = 0; i < _smallmap_cargo_count; ++i) {
+						const LegendAndColour &tbl = _legend_table_old[window->map_type][i];
+						if (!tbl.show_on_map) continue;
+
+						CargoID c = tbl.type;
+						const LinkStatMap &links = sta->goods[c].link_stats;
+						for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
+							StationID from = sta->index;
+							StationID to = i->first;
+							if (Station::IsValidID(to) && seen_stations.find(to) == seen_stations.end()) {
+								const Station *stb = Station::Get(to);
+
+								if (stb->owner != _local_company && Company::IsValidID(stb->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
+								if (sta->rect.IsEmpty() || stb->rect.IsEmpty()) continue;
+								if (seen_links.find(std::make_pair(to, from)) != seen_links.end()) continue;
+
+								this->pta = this->window->GetStationMiddle(sta);
+								this->ptb = this->window->GetStationMiddle(stb);
+								if (!this->IsLinkVisible()) continue;
+
+								this->DrawForwBackLinks(sta->index, stb->index);
+								seen_stations.insert(to);
+							}
+							seen_links.insert(std::make_pair(from, to));
+						}
+					}
+				
+					seen_stations.clear();
+				}
+			}
+			return this->link_details;
+		}
+
+	};
+
+	class LinkLineDrawer : public LinkDrawer {
+	public:
+		LinkLineDrawer() : highlight(false) {}
+
+	protected:
+		typedef std::set<uint16> ColourSet;
+		ColourSet colours;
+		bool highlight;
+
+		virtual void DrawForwBackLinks(StationID sta, StationID stb)
+		{
+			this->DrawLink(sta, stb);
+			this->DrawLink(stb, sta);
+			this->DrawContent();
+		}
+
+		virtual void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow, const LegendAndColour &cargo_entry)
+		{
+			this->colours.insert(cargo_entry.colour);
+		}
+
+		virtual void Highlight()
+		{
+			this->highlight = true;
+		}
+
+		virtual void DrawContent()
+		{
+			uint colour = 0;
+			uint num_colours = 0;
+			for (ColourSet::iterator i = colours.begin(); i != colours.end(); ++i) {
+				colour += *i;
+				num_colours++;
+			}
+			colour /= num_colours;
+			byte border_colour = _colour_gradient[COLOUR_GREY][highlight ? 3 : 1];
+			GfxDrawLine(this->pta.x - 1, this->pta.y, this->ptb.x - 1, this->ptb.y, border_colour);
+			GfxDrawLine(this->pta.x + 1, this->pta.y, this->ptb.x + 1, this->ptb.y, border_colour);
+			GfxDrawLine(this->pta.x, this->pta.y - 1, this->ptb.x, this->ptb.y - 1, border_colour);
+			GfxDrawLine(this->pta.x, this->pta.y + 1, this->ptb.x, this->ptb.y + 1, border_colour);
+			GfxDrawLine(this->pta.x, this->pta.y, this->ptb.x, this->ptb.y, colour);
+			this->colours.clear();
+			this->highlight = false;
+		}
+	};
+
+	class LinkValueDrawer : public LinkDrawer, public BaseCargoDetail {
+	protected:
+
+		virtual void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow, const LegendAndColour &cargo_entry)
+		{
+			this->BaseCargoDetail::AddLink(orig_link, orig_flow);
+		}
+	};
+
+	class LinkTextDrawer : public LinkValueDrawer {
+	protected:
+		virtual void DrawContent()
+		{
+			Point ptm;
+			ptm.x = (this->pta.x + 2*this->ptb.x) / 3;
+			ptm.y = (this->pta.y + 2*this->ptb.y) / 3;
+			int nums = 0;
+			if (_legend_linkstats[_smallmap_cargo_count + STAT_CAPACITY].show_on_map) {
+				SetDParam(nums++, this->capacity);
+			}
+			if (_legend_linkstats[_smallmap_cargo_count + STAT_USAGE].show_on_map) {
+				SetDParam(nums++, this->usage);
+			}
+			if (_legend_linkstats[_smallmap_cargo_count + STAT_PLANNED].show_on_map) {
+				SetDParam(nums++, this->planned);
+			}
+			if (_legend_linkstats[_smallmap_cargo_count + STAT_SENT].show_on_map) {
+				SetDParam(nums++, this->sent);
+			}
+			StringID str;
+			switch (nums) {
+			case 0:
+				str = STR_EMPTY; break;
+			case 1:
+				str = STR_NUM; break;
+			case 2:
+				str = STR_NUM_RELATION_2; break;
+			case 3:
+				str = STR_NUM_RELATION_3; break;
+			case 4:
+				str = STR_NUM_RELATION_4; break;
+			default:
+				NOT_REACHED();
+			}
+			DrawString(ptm.x, ptm.x + this->window->ColumnWidth(), ptm.y, str, TC_WHITE);
+			this->Clear();
+		}
+	};
+
+	class LinkGraphDrawer : public LinkValueDrawer {
+		typedef std::multimap<uint, byte, std::greater<uint> > SizeMap;
+	protected:
+		virtual void DrawContent()
+		{
+			Point ptm;
+			SizeMap sizes;
+			/* these floats only serve to calculate the size of the coloured boxes for capacity, usage, planned, sent
+			 * they are not reused anywhere, so it's network safe.
+			 */
+			const LegendAndColour *legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_USAGE;
+			if (legend_entry->show_on_map && this->usage > 0) {
+				sizes.insert(std::make_pair((uint)sqrt((float)this->usage), legend_entry->colour));
+			}
+			legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_CAPACITY;
+			if (legend_entry->show_on_map && this->capacity > 0) {
+				sizes.insert(std::make_pair((uint)sqrt((float)this->capacity), legend_entry->colour));
+			}
+			legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_PLANNED;
+			if (legend_entry->show_on_map && this->planned > 0) {
+				sizes.insert(std::make_pair((uint)sqrt((float)this->planned),  legend_entry->colour));
+			}
+			legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_SENT;
+			if (legend_entry->show_on_map && this->sent > 0) {
+				sizes.insert(std::make_pair((uint)sqrt((float)this->sent), legend_entry->colour));
+			}
+
+			ptm.x = (this->pta.x + this->ptb.x) / 2;
+			ptm.y = (this->pta.y + this->ptb.y) / 2;
+
+			for (SizeMap::iterator i = sizes.begin(); i != sizes.end(); ++i) {
+				if (this->pta.x > this->ptb.x) {
+					ptm.x -= 1;
+					GfxFillRect(ptm.x - i->first / 2, ptm.y - i->first * 2, ptm.x, ptm.y, i->second);
+				} else {
+					ptm.x += 1;
+					GfxFillRect(ptm.x, ptm.y - i->first * 2, ptm.x + i->first / 2, ptm.y, i->second);
+				}
+			}
+			this->Clear();
+		}
+	};
+
+	static const uint MORE_SPACE_NEEDED = 0x1000;
+
+	uint DrawLinkDetails(StatVector &details, uint x, uint y, uint right, uint bottom) const
+	{
+		uint x_orig = x;
+		SetDParam(0, 9999);
+		static uint entry_width = LEGEND_BLOB_WIDTH +
+				GetStringBoundingBox(STR_ABBREV_PASSENGERS).width +
+				GetStringBoundingBox(STR_SMALLMAP_LINK_CAPACITY).width +
+				GetStringBoundingBox(STR_SMALLMAP_LINK_USAGE).width +
+				GetStringBoundingBox(STR_SMALLMAP_LINK_PLANNED).width +
+				GetStringBoundingBox(STR_SMALLMAP_LINK_SENT).width;
+		uint entries_per_row = (right - x_orig) / entry_width;
+		if (details.empty()) {
+			DrawString(x, x + entry_width, y, STR_TINY_NOTHING, TC_BLACK);
+			return y + FONT_HEIGHT_SMALL;
+		}
+		for (uint i = 0; i < details.size(); ++i) {
+			CargoDetail &detail = details[i];
+			if (x + entry_width >= right) {
+				x = x_orig;
+				y += FONT_HEIGHT_SMALL;
+				if (y + 2 * FONT_HEIGHT_SMALL > bottom && details.size() - i > entries_per_row) {
+					return y | MORE_SPACE_NEEDED;
+				}
+			}
+			uint x_next = x + entry_width;
+			if (detail.legend->show_on_map) {
+				GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK); // outer border of the legend colour
+			}
+			GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, detail.legend->colour); // legend colour
+			x += LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
+			TextColour textcol[4];
+			for (int stat = STAT_CAPACITY; stat <= STAT_SENT; ++stat) {
+				textcol[stat] = (detail.legend->show_on_map && _legend_linkstats[_smallmap_cargo_count + stat].show_on_map) ?
+						TC_BLACK : TC_GREY;
+			}
+
+			SetDParam(0, CargoSpec::Get(detail.legend->type)->abbrev);
+			x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK, detail.legend->show_on_map ? TC_BLACK : TC_GREY);
+			SetDParam(0, detail.capacity);
+			x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_CAPACITY, textcol[STAT_CAPACITY]);
+			SetDParam(0, detail.usage);
+			x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_USAGE, textcol[STAT_USAGE]);
+			SetDParam(0, detail.planned);
+			x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_PLANNED, textcol[STAT_PLANNED]);
+			SetDParam(0, detail.sent);
+			x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_SENT, textcol[STAT_SENT]);
+			x = x_next;
+		}
+		return y + FONT_HEIGHT_SMALL;
+	}
+
+	uint DrawLinkDetailCaption(uint x, uint y, uint right, StationID sta, StationID stb) const
+	{
+		SetDParam(0, sta);
+		SetDParam(1, stb);
+		static uint height = GetStringBoundingBox(STR_SMALLMAP_LINK_CAPTION).height;
+		DrawString(x, right - 1, y, STR_SMALLMAP_LINK_CAPTION, TC_BLACK);
+		y += height;
+		return y;
+	}
+
+	void DrawLinkDetails(uint x, uint y, uint right, uint bottom) const
+	{
+		y = DrawLinkDetailCaption(x, y, right, this->link_details.sta, this->link_details.stb);
+		if (y + 2 * FONT_HEIGHT_SMALL > bottom) {
+			DrawString(x, right, y, "...", TC_BLACK);
+			return;
+		}
+		y = DrawLinkDetails(this->link_details.a_to_b, x, y, right, bottom);
+		if (y + 3 * FONT_HEIGHT_SMALL > bottom) {
+			/* caption takes more space -> 3 * row height */
+			DrawString(x, right, y, "...", TC_BLACK);
+			return;
+		}
+		y = DrawLinkDetailCaption(x, y + 2, right, this->link_details.stb, this->link_details.sta);
+		if (y + 2 * FONT_HEIGHT_SMALL > bottom) {
+			DrawString(x, right, y, "...", TC_BLACK);
+			return;
+		}
+		y = DrawLinkDetails(this->link_details.b_to_a, x, y, right, bottom);
+		if (y & MORE_SPACE_NEEDED) {
+			/* only draw "..." if more entries would have been drawn */
+			DrawString(x, right, y ^ MORE_SPACE_NEEDED, "...", TC_BLACK);
+			return;
+		}
+	}
+
+	void DrawSupplyDetails(uint x, uint y_org, uint bottom) const
+	{
+		const Station *st = Station::GetIfValid(this->supply_details);
+		if (st == NULL) return;
+		SetDParam(0, this->supply_details);
+		static uint height = GetStringBoundingBox(STR_SMALLMAP_SUPPLY_CAPTION).height;
+		DrawString(x, x + 2 * this->column_width - 1, y_org, STR_SMALLMAP_SUPPLY_CAPTION, TC_BLACK);
+		y_org += height;
+		uint y = y_org;
+		if (AllowMoreHeightlevels()) {
+			for (int i = 0; i < _smallmap_cargo_count; ++i) {
+				if (y + FONT_HEIGHT_SMALL - 1 >= bottom) {
+					/* Column break needed, continue at top, SD_LEGEND_COLUMN_WIDTH pixels
+					 * (one "row") to the right. */
+					x += this->column_width;
+					y = y_org;
+				}
+
+				const LegendAndColour &tbl = _legend_table_extended[this->map_type][i];
+
+				CargoID c = tbl.type;
+				uint supply = st->goods[c].supply;
+				if (supply > 0) {
+					TextColour textcol = TC_BLACK;
+					if (tbl.show_on_map) {
+						GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK); // outer border of the legend colour
+					} else {
+						textcol = TC_GREY;
+					}
+					SetDParam(0, c);
+					SetDParam(1, supply);
+					DrawString(x + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT, x + this->column_width - 1, y, STR_SMALLMAP_SUPPLY, textcol);
+					GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, tbl.colour); // legend colour
+					y += FONT_HEIGHT_SMALL;
+				}
+			}
+
+		} else {
+			for (int i = 0; i < _smallmap_cargo_count; ++i) {
+				if (y + FONT_HEIGHT_SMALL - 1 >= bottom) {
+					/* Column break needed, continue at top, SD_LEGEND_COLUMN_WIDTH pixels
+					 * (one "row") to the right. */
+					x += this->column_width;
+					y = y_org;
+				}
+
+				const LegendAndColour &tbl = _legend_table_old[this->map_type][i];
+
+				CargoID c = tbl.type;
+				uint supply = st->goods[c].supply;
+				if (supply > 0) {
+					TextColour textcol = TC_BLACK;
+					if (tbl.show_on_map) {
+						GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK); // outer border of the legend colour
+					} else {
+						textcol = TC_GREY;
+					}
+					SetDParam(0, c);
+					SetDParam(1, supply);
+					DrawString(x + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT, x + this->column_width - 1, y, STR_SMALLMAP_SUPPLY, textcol);
+					GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, tbl.colour); // legend colour
+					y += FONT_HEIGHT_SMALL;
+				}
+			}
 		}
 	}
 
@@ -977,13 +2884,14 @@
 
 		/* Which tile is displayed at (dpi->left, dpi->top)? */
 		int dx;
-		Point tile = this->PixelToTile(dpi->left, dpi->top, &dx);
-		int tile_x = this->scroll_x / (int)TILE_SIZE + tile.x;
-		int tile_y = this->scroll_y / (int)TILE_SIZE + tile.y;
+		Point position = this->PixelToWorld(dpi->left, dpi->top, &dx);
+		int pos_x = this->scroll_x + position.x;
+		int pos_y = this->scroll_y + position.y;
 
 		void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
 		int x = - dx - 4;
 		int y = 0;
+		int increment = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom); 
 
 		for (;;) {
 			/* Distance from left edge */
@@ -993,16 +2901,16 @@
 				int end_pos = min(dpi->width, x + 4);
 				int reps = (dpi->height - y + 1) / 2; // Number of lines.
 				if (reps > 0) {
-					this->DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter);
+					this->DrawSmallMapColumn(ptr, pos_x, pos_y, dpi->pitch * 2, reps, x, end_pos, blitter);
 				}
 			}
 
 			if (y == 0) {
-				tile_y += this->zoom;
+				pos_y += increment;
 				y++;
 				ptr = blitter->MoveTo(ptr, 0, 1);
 			} else {
-				tile_x -= this->zoom;
+				pos_x -= increment;
 				y--;
 				ptr = blitter->MoveTo(ptr, 0, -1);
 			}
@@ -1013,6 +2921,23 @@
 		/* Draw vehicles */
 		if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
 
+		/* Draw the cargo linkgraphs */
+		if (this->map_type == SMT_LINKSTATS && _game_mode == GM_NORMAL) {
+			LinkLineDrawer lines;
+			this->link_details = lines.DrawLinks(this, true);
+
+			this->supply_details = DrawStationDots();
+
+			if (_legend_linkstats[_smallmap_cargo_count + STAT_TEXT].show_on_map) {
+				LinkTextDrawer text;
+				text.DrawLinks(this, false);
+			}
+			if (_legend_linkstats[_smallmap_cargo_count + STAT_GRAPH].show_on_map) {
+				LinkGraphDrawer graph;
+				graph.DrawLinks(this, false);
+			}
+		}
+
 		/* Draw town names */
 		if (this->show_towns) this->DrawTowns(dpi);
 
@@ -1022,6 +2947,63 @@
 		_cur_dpi = old_dpi;
 	}
 
+	bool CheckStationSelected(Point *pt) const
+	{
+		return abs(this->cursor.x - pt->x) < 7 && abs(this->cursor.y - pt->y) < 7;
+	}
+
+	bool CheckLinkSelected(Point *pta, Point *ptb) const
+	{
+		if (this->cursor.x == -1 && this->cursor.y == -1) return false;
+		if (CheckStationSelected(pta) || CheckStationSelected(ptb)) return false;
+		if (pta->x > ptb->x) Swap(pta, ptb);
+		int minx = min(pta->x, ptb->x);
+		int maxx = max(pta->x, ptb->x);
+		int miny = min(pta->y, ptb->y);
+		int maxy = max(pta->y, ptb->y);
+		if (!IsInsideMM(cursor.x, minx - 3, maxx + 3) || !IsInsideMM(cursor.y, miny - 3, maxy + 3)) {
+			return false;
+		}
+
+		if (pta->x == ptb->x || ptb->y == pta->y) {
+			return true;
+		} else {
+			int incliney = (ptb->y - pta->y);
+			int inclinex = (ptb->x - pta->x);
+			int diff = (cursor.x - minx) * incliney / inclinex - (cursor.y - miny);
+			if (incliney < 0) {
+				diff += maxy - miny;
+			}
+			return abs(diff) < 4;
+		}
+	}
+
+	/**
+	 * recalculate which vehicles are visible and their positions.
+	 */
+	void RecalcVehiclePositions()
+	{
+		this->vehicles_on_map.clear();
+		const Vehicle *v;
+		const NWidgetCore *wi = this->GetWidget<NWidgetCore>(SM_WIDGET_MAP);
+		int scale = this->zoom < 0 ? -this->zoom : 1;
+
+		FOR_ALL_VEHICLES(v) {
+			if (v->type == VEH_EFFECT) continue;
+			if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
+
+			/* Remap into flat coordinates. We have to do that again in DrawVehicles to account for scrolling. */
+			Point pos = RemapTile(v->x_pos / (int)TILE_SIZE, v->y_pos / (int)TILE_SIZE);
+
+			/* Check if rhombus is inside bounds */
+			if (IsInsideMM(pos.x, -2 * scale, wi->current_x + 2 * scale) &&
+				IsInsideMM(pos.y, -2 * scale, wi->current_y + 2 * scale)) {
+
+				this->vehicles_on_map.push_back(VehicleAndPosition(v));
+			}
+		}
+	}
+
 	/**
 	 * Function to set up widgets depending on the information being shown on the smallmap.
 	 */
@@ -1039,6 +3021,13 @@
 				plane = 0;
 				break;
 
+			case SMT_LINKSTATS:
+				legend_tooltip = STR_SMALLMAP_TOOLTIP_LINK_STATS_SELECTION;
+				enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_LINK_STATS;
+				disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_LINK_STATS;
+				plane = 0;
+				break;
+
 			case SMT_OWNER:
 				legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
 				enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
@@ -1063,9 +3052,16 @@
 public:
 	uint min_number_of_columns;    ///< Minimal number of columns in legends.
 
-	SmallMapWindow(const WindowDesc *desc, int window_number) : Window(), refresh(FORCE_REFRESH_PERIOD)
+	SmallMapWindow(const WindowDesc *desc, int window_number) : Window(), supply_details(INVALID_STATION), refresh(FORCE_REFRESH_PERIOD)
 	{
+		this->cursor.x = -1;
+		this->cursor.y = -1;
 		this->InitNested(desc, window_number);
+		if (_smallmap_cargo_count == 0) {
+			this->DisableWidget(SM_WIDGET_LINKSTATS);
+			if (this->map_type == SMT_LINKSTATS) this->map_type = SMT_CONTOUR;
+		}
+
 		this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
 
 		BuildLandLegend();
@@ -1079,6 +3075,15 @@
 		this->SmallMapCenterOnCurrentPos();
 	}
 
+//	/**
+//	 * Compute maximal required height of the legends. // TODO: remove and fix
+//	 * @return Maximally needed height for displaying the smallmap legends in pixels.
+//	 */
+//	inline uint GetMaxLegendHeight() const
+//	{
+//		return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + this->GetMaxNumberRowsLegend(this->min_number_of_columns) * FONT_HEIGHT_SMALL;
+//	}
+
 	/**
 	 * Compute minimal required width of the legends.
 	 * @return Minimally needed width for displaying the smallmap legends in pixels.
@@ -1098,14 +3103,18 @@
 	}
 
 	/**
-	 * Compute height given a number of columns.
+//	 * Compute height given a number of columns.
+	 * Compute height given a width.
 	 * @param Number of columns.
 	 * @return Needed height for displaying the smallmap legends in pixels.
 	 */
 	uint GetLegendHeight(uint num_columns) const
+//	uint GetLegendHeight(uint width) const
 	{
-		uint num_rows = max(this->min_number_of_fixed_rows, CeilDiv(max(_smallmap_company_count, _smallmap_industry_count), num_columns));
-		return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
+//		uint num_rows = max(this->min_number_of_fixed_rows, CeilDiv(max(_smallmap_company_count, _smallmap_industry_count), num_columns));
+//		return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
+// 		uint num_columns = this->GetNumberColumnsLegend(width);
+		return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + this->GetNumberRowsLegend(num_columns) * FONT_HEIGHT_SMALL;
 	}
 
 	virtual void SetStringParameters(int widget) const
@@ -1121,43 +3130,91 @@
 	{
 		uint min_width = 0;
 		this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
-		this->min_number_of_fixed_rows = 0;
-		for (uint i = 0; i < lengthof(_legend_table); i++) {
-			uint height = 0;
-			uint num_columns = 1;
-			for (const LegendAndColour *tbl = _legend_table[i]; !tbl->end; ++tbl) {
-				StringID str;
-				if (i == SMT_INDUSTRY) {
-					SetDParam(0, tbl->legend);
-					SetDParam(1, IndustryPool::MAX_SIZE);
-					str = STR_SMALLMAP_INDUSTRY;
-				} else if (i == SMT_OWNER) {
-					if (tbl->company != INVALID_COMPANY) {
-						if (!Company::IsValidID(tbl->company)) {
-							/* Rebuild the owner legend. */
-							BuildOwnerLegend();
-							this->OnInit();
-							return;
+//		this->min_number_of_fixed_rows = 0;
+		this->min_number_of_fixed_rows = lengthof(_legend_linkstats) / 2 + 1;
+		if (AllowMoreHeightlevels()) {
+			for (uint i = 0; i < lengthof(_legend_table_extended); i++) {
+				uint height = 0;
+				uint num_columns = 1;
+				for (const LegendAndColour *tbl = _legend_table_extended[i]; !tbl->end; ++tbl) {
+					StringID str;
+					if (i == SMT_INDUSTRY) {
+						SetDParam(0, tbl->legend);
+						SetDParam(1, IndustryPool::MAX_SIZE);
+						str = STR_SMALLMAP_INDUSTRY;
+					} else if (i == SMT_LINKSTATS) {
+						SetDParam(0, tbl->legend);
+						str = STR_SMALLMAP_LINKSTATS;
+					} else if (i == SMT_OWNER) {
+						if (tbl->company != INVALID_COMPANY) {
+							if (!Company::IsValidID(tbl->company)) {
+								/* Rebuild the owner legend. */
+								BuildOwnerLegend();
+								this->OnInit();
+								return;
+							}
+							/* Non-fixed legend entries for the owner view. */
+							SetDParam(0, tbl->company);
+							str = STR_SMALLMAP_COMPANY;
+						} else {
+							str = tbl->legend;
+	 					}
+					} else {
+						if (tbl->col_break) {
+							this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
+							height = 0;
+							num_columns++;
 						}
-						/* Non-fixed legend entries for the owner view. */
-						SetDParam(0, tbl->company);
-						str = STR_SMALLMAP_COMPANY;
-					} else {
+						height++;
 						str = tbl->legend;
 					}
-				} else {
-					if (tbl->col_break) {
-						this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
-						height = 0;
-						num_columns++;
+					min_width = max(GetStringBoundingBox(str).width, min_width);
+				}
+				this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
+				this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
+			}
+
+		} else {
+			for (uint i = 0; i < lengthof(_legend_table_old); i++) {
+				uint height = 0;
+				uint num_columns = 1;
+				for (const LegendAndColour *tbl = _legend_table_old[i]; !tbl->end; ++tbl) {
+					StringID str;
+					if (i == SMT_INDUSTRY) {
+						SetDParam(0, tbl->legend);
+						SetDParam(1, IndustryPool::MAX_SIZE);
+						str = STR_SMALLMAP_INDUSTRY;
+					} else if (i == SMT_LINKSTATS) {
+						SetDParam(0, tbl->legend);
+						str = STR_SMALLMAP_LINKSTATS;
+					} else if (i == SMT_OWNER) {
+						if (tbl->company != INVALID_COMPANY) {
+							if (!Company::IsValidID(tbl->company)) {
+								/* Rebuild the owner legend. */
+								BuildOwnerLegend();
+								this->OnInit();
+								return;
+							}
+							/* Non-fixed legend entries for the owner view. */
+							SetDParam(0, tbl->company);
+							str = STR_SMALLMAP_COMPANY;
+						} else {
+							str = tbl->legend;
+	 					}
+					} else {
+						if (tbl->col_break) {
+							this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
+							height = 0;
+							num_columns++;
+						}
+						height++;
+						str = tbl->legend;
 					}
-					height++;
-					str = tbl->legend;
+					min_width = max(GetStringBoundingBox(str).width, min_width);
 				}
-				min_width = max(GetStringBoundingBox(str).width, min_width);
+				this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
+				this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
 			}
-			this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
-			this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
 		}
 
 		/* The width of a column is the minimum width of all texts + the size of the blob + some spacing */
@@ -1167,12 +3224,23 @@
 	virtual void OnPaint()
 	{
 		if (this->map_type == SMT_OWNER) {
-			for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
-				if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
-					/* Rebuild the owner legend. */
-					BuildOwnerLegend();
-					this->InvalidateData(1);
-					break;
+			if (AllowMoreHeightlevels()) {
+				for (const LegendAndColour *tbl = _legend_table_extended[this->map_type]; !tbl->end; ++tbl) {
+					if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
+						/* Rebuild the owner legend. */
+						BuildOwnerLegend();
+						this->InvalidateData(1);
+						break;
+					}
+				}
+			} else {
+				for (const LegendAndColour *tbl = _legend_table_old[this->map_type]; !tbl->end; ++tbl) {
+					if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
+						/* Rebuild the owner legend. */
+						BuildOwnerLegend();
+						this->InvalidateData(1);
+						break;
+					}
 				}
 			}
 		}
@@ -1191,64 +3259,180 @@
 			}
 
 			case SM_WIDGET_LEGEND: {
-				uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
-				uint number_of_rows = max((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER) ? CeilDiv(max(_smallmap_company_count, _smallmap_industry_count), columns) : 0, this->min_number_of_fixed_rows);
-				bool rtl = _current_text_dir == TD_RTL;
 				uint y_org = r.top + WD_FRAMERECT_TOP;
-				uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
-				uint y = y_org;
-				uint i = 0; // Row counter for industry legend.
-				uint row_height = FONT_HEIGHT_SMALL;
-
-				uint text_left  = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
-				uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
-				uint blob_left  = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
-				uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
-
-				for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
-					if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) {
-						/* Column break needed, continue at top, COLUMN_WIDTH pixels
-						 * (one "row") to the right. */
-						x += rtl ? -(int)this->column_width : this->column_width;
-						y = y_org;
-						i = 1;
+				uint x = r.left + WD_FRAMERECT_LEFT;
+				if (this->supply_details != INVALID_STATION) {
+					this->DrawSupplyDetails(x, y_org, r.bottom - WD_FRAMERECT_BOTTOM);
+				} else if (!this->link_details.Empty()) {
+					this->DrawLinkDetails(x, y_org, r.right - WD_FRAMERECT_RIGHT, r.bottom - WD_FRAMERECT_BOTTOM);
+				} else {
+					uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
+					uint number_of_rows = this->GetNumberRowsLegend(columns);
+					bool rtl = _current_text_dir == TD_RTL;
+					uint y_org = r.top + WD_FRAMERECT_TOP;
+					uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
+					uint y = y_org;
+					uint i = 0; // Row counter for industry legend.
+					uint row_height = FONT_HEIGHT_SMALL;
+
+					uint text_left  = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
+					uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
+					uint blob_left  = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
+					uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
+
+					StringID string = STR_NULL;
+					switch (this->map_type) {
+						case SMT_INDUSTRY:
+							string = STR_SMALLMAP_INDUSTRY;
+							break;
+						case SMT_LINKSTATS:
+							string = STR_SMALLMAP_LINKSTATS;
+							break;
+						case SMT_OWNER:
+							string = STR_SMALLMAP_COMPANY;
+							break;
+						default:
+							break;
 					}
 
-					if (this->map_type == SMT_INDUSTRY) {
-						/* Industry name must be formatted, since it's not in tiny font in the specs.
-						 * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font */
-						SetDParam(0, tbl->legend);
-						SetDParam(1, Industry::GetIndustryTypeCount(tbl->type));
-						if (!tbl->show_on_map) {
-							/* Simply draw the string, not the black border of the legend colour.
-							 * This will enforce the idea of the disabled item */
-							DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
-						} else {
-							DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
-							GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
-						}
-					} else if (this->map_type == SMT_OWNER && tbl->company != INVALID_COMPANY) {
-						SetDParam(0, tbl->company);
-						if (!tbl->show_on_map) {
-							/* Simply draw the string, not the black border of the legend colour.
-							 * This will enforce the idea of the disabled item */
-							DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_COMPANY, TC_GREY);
-						} else {
-							DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_COMPANY, TC_BLACK);
-							GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
+					if (AllowMoreHeightlevels()) {
+						for (const LegendAndColour *tbl = _legend_table_extended[this->map_type]; !tbl->end; ++tbl) {
+							if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) {
+								/* Column break needed, continue at top, COLUMN_WIDTH pixels
+								 * (one "row") to the right. */
+								x += rtl ? -(int)this->column_width : this->column_width;
+								y = y_org;
+								i = 1;
+							}
+
+							switch(this->map_type) {
+								case SMT_INDUSTRY:
+									/* Industry name must be formatted, since it's not in tiny font in the specs.
+									 * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font. */
+									SetDParam(1, Industry::GetIndustryTypeCount(tbl->type));
+								case SMT_LINKSTATS:
+									SetDParam(0, tbl->legend);
+								case SMT_OWNER:
+									if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
+										if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
+										if (!tbl->show_on_map) {
+											/* Simply draw the string, not the black border of the legend colour.
+											* This will enforce the idea of the disabled item */
+											DrawString(x + text_left, x + text_right, y, string, TC_GREY);
+										} else {
+											DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
+											GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
+										}
+									break;
+									} // else fall through
+								default:
+									if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
+
+									/* Anything that is not an industry or a company is using normal process */
+									GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
+									DrawString(x + text_left, x + text_right, y, tbl->legend);
+									break;
+							}
+							GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour); // Legend colour.
+
+							y += row_height;
 						}
 					} else {
-						if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
-
-						/* Anything that is not an industry or a company is using normal process */
-						GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
-						DrawString(x + text_left, x + text_right, y, tbl->legend);
+						for (const LegendAndColour *tbl = _legend_table_old[this->map_type]; !tbl->end; ++tbl) {
+							if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) {
+								/* Column break needed, continue at top, COLUMN_WIDTH pixels
+								 * (one "row") to the right. */
+								x += rtl ? -(int)this->column_width : this->column_width;
+								y = y_org;
+								i = 1;
+							}
+
+							switch(this->map_type) {
+								case SMT_INDUSTRY:
+									/* Industry name must be formatted, since it's not in tiny font in the specs.
+									 * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font. */
+									SetDParam(1, Industry::GetIndustryTypeCount(tbl->type));
+								case SMT_LINKSTATS:
+									SetDParam(0, tbl->legend);
+								case SMT_OWNER:
+									if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
+										if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
+										if (!tbl->show_on_map) {
+											/* Simply draw the string, not the black border of the legend colour.
+											* This will enforce the idea of the disabled item */
+											DrawString(x + text_left, x + text_right, y, string, TC_GREY);
+										} else {
+											DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
+											GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
+										}
+									break;
+									} // else fall through
+								default:
+									if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
+
+									/* Anything that is not an industry or a company is using normal process */
+									GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
+									DrawString(x + text_left, x + text_right, y, tbl->legend);
+									break;
+							}
+							GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour); // Legend colour
+
+							y += row_height;
+						}
 					}
-					GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour); // Legend colour
-
-					y += row_height;
+				}
+			} break;
+		}
+	}
+
+	/**
+	 * Get the number of rows in the legend from the number of columns. Those
+	 * are at least min_number_of_fixed_rows and possibly more if there are so
+	 * many cargoes, industry types or companies that they won't fit in the
+	 * available space.
+	 * @param columns Number of columns in the legend.
+	 * @return Number of rows needed for everything to fit in.
+	 */
+	uint GetNumberRowsLegend(uint columns) const
+	{
+		/* reserve one column for link colours */
+		uint num_rows_linkstats = CeilDiv(_smallmap_cargo_count, columns - 1);
+
+		uint num_rows_others = CeilDiv(max(_smallmap_industry_count,_smallmap_company_count), columns);
+		return max(this->min_number_of_fixed_rows, max(num_rows_linkstats, num_rows_others));
+	}
+
+	/**
+	 * Select and toggle a legend item. When CTRL is pressed, disable all other
+	 * items in the group defined by begin_legend_item and end_legend_item and
+	 * keep the clicked one enabled even if it was already enabled before. If
+	 * the other items in the group are all disabled already and CTRL is pressed
+	 * enable them instead.
+	 * @param click_pos the index of the item being selected
+	 * @param legend the legend from which we select
+	 * @param end_legend_item index one past the last item in the group to be inverted
+	 * @param begin_legend_item index of the first item in the group to be inverted
+	 */
+	void SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item = 0)
+	{
+		if (_ctrl_pressed) {
+			/* Disable all, except the clicked one */
+			bool changes = false;
+			for (int i = begin_legend_item; i != end_legend_item; i++) {
+				bool new_state = (i == click_pos);
+				if (legend[i].show_on_map != new_state) {
+					changes = true;
+					legend[i].show_on_map = new_state;
 				}
 			}
+			if (!changes) {
+				/* Nothing changed? Then show all (again). */
+				for (int i = begin_legend_item; i != end_legend_item; i++) {
+					legend[i].show_on_map = true;
+				}
+			}
+		} else {
+			legend[click_pos].show_on_map = !legend[click_pos].show_on_map;
 		}
 	}
 
@@ -1285,15 +3469,40 @@
 				_left_button_clicked = false;
 
 				const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
+
+				/* We need to take the height at the clicked position into account
+				 * (i.e. move the map northwards).
+				 * Basically, we compute the inverse of function RemapX/Y here.
+				 * Note that we have to subtract 2 from x and 16 from y here because
+				 * _cursor_pos.x/y - this->left/top includes the edge of the small map. */
+				int offset_inside_sm_x = _cursor.pos.x - this->left + wid->pos_x;
+				int offset_inside_sm_y = _cursor.pos.y - this->top - wid->pos_y;
+				int clicked_screen_x = offset_inside_sm_x * TILE_SIZE + pt.x;
+				int clicked_screen_y = offset_inside_sm_y * TILE_SIZE + pt.y;
+				Point clicked_tile = TileCoordFromScreenCoord(clicked_screen_x, clicked_screen_y);
+				clicked_tile.x /= TILE_SIZE;
+				clicked_tile.y /= TILE_SIZE;
+				int clicked_tile_height = TileHeightOutsideMap(clicked_tile.x, clicked_tile.y);
+
+				DEBUG(map, 9, "clicked: offset_inside_sm (%i,%i), clicked_tile (%i,%i), clicked_screen (%i,%i), clicked_tile_height %i",
+						offset_inside_sm_x, offset_inside_sm_y, clicked_tile.x, clicked_tile.y, clicked_screen_x, clicked_screen_y, clicked_tile_height);
+
 				Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
 				int sub;
-				pt = this->PixelToTile(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
-				pt = RemapCoords(this->scroll_x + pt.x * TILE_SIZE + this->zoom * (TILE_SIZE - sub * TILE_SIZE / 4),
-						this->scroll_y + pt.y * TILE_SIZE + sub * this->zoom * TILE_SIZE / 4, 0);
+				pt = this->PixelToWorld(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
+				int offset = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
+				pt = RemapCoords(this->scroll_x + pt.x + offset - offset * sub / 4,
+						this->scroll_y + pt.y + sub * offset / 4, 0);
 
 				w->viewport->follow_vehicle = INVALID_VEHICLE;
 				w->viewport->dest_scrollpos_x = pt.x - (w->viewport->virtual_width  >> 1);
-				w->viewport->dest_scrollpos_y = pt.y - (w->viewport->virtual_height >> 1);
+				w->viewport->dest_scrollpos_y = pt.y - ((clicked_tile_height * TILE_HEIGHT) + (w->viewport->virtual_height >> 1)); // TODO: add moreheightlevels_v29 and merge with cargodist (when clicking the smallmap main vieport positioning is slighlty off)
+
+				DEBUG(map, 9, "OnClick: scroll_x, scroll_y = (%i,%i), pt = (%i,%i), dest_scrollpos = (%i,%i), cursor = (%i,%i), left/top = (%i, %i), virtual = (%i,%i)",
+						this->scroll_x, this->scroll_y, pt.x, pt.y,
+						w->viewport->dest_scrollpos_x, w->viewport->dest_scrollpos_y,
+						_cursor.pos.x, _cursor.pos.y, this->left, this->top,
+						w->viewport->virtual_width, w->viewport->virtual_height);
 
 				this->SetDirty();
 				break;
@@ -1311,6 +3520,7 @@
 			case SM_WIDGET_CONTOUR:    // Show land contours
 			case SM_WIDGET_VEHICLES:   // Show vehicles
 			case SM_WIDGET_INDUSTRIES: // Show industries
+			case SM_WIDGET_LINKSTATS:  // Show route map
 			case SM_WIDGET_ROUTES:     // Show transport routes
 			case SM_WIDGET_VEGETATION: // Show vegetation
 			case SM_WIDGET_OWNERS:     // Show land owners
@@ -1333,98 +3543,68 @@
 				break;
 
 			case SM_WIDGET_LEGEND: // Legend
-				if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER) {
+				/* If industry type small map*/
+				if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) {
+					/* If click on industries label, find right industry type and enable/disable it */
 					const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_LEGEND); // Label panel
 					uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
 					uint columns = this->GetNumberColumnsLegend(wi->current_x);
-					uint number_of_rows = max(CeilDiv(max(_smallmap_company_count, _smallmap_industry_count), columns), this->min_number_of_fixed_rows);
+					uint number_of_rows = this->GetNumberRowsLegend(columns);
 					if (line >= number_of_rows) break;
 
 					bool rtl = _current_text_dir == TD_RTL;
 					int x = pt.x - wi->pos_x;
 					if (rtl) x = wi->current_x - x;
 					uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
-
-					/* If industry type small map*/
+					int click_pos = (column * number_of_rows) + line;
+
+					/* Check if click is on industry label*/
 					if (this->map_type == SMT_INDUSTRY) {
-						/* If click on industries label, find right industry type and enable/disable it. */
-						int industry_pos = (column * number_of_rows) + line;
-						if (industry_pos < _smallmap_industry_count) {
-							if (_ctrl_pressed) {
-								/* Disable all, except the clicked one. */
-								bool changes = false;
-								for (int i = 0; i != _smallmap_industry_count; i++) {
-									bool new_state = i == industry_pos;
-									if (_legend_from_industries[i].show_on_map != new_state) {
-										changes = true;
-										_legend_from_industries[i].show_on_map = new_state;
-									}
-								}
-								if (!changes) {
-									/* Nothing changed? Then show all (again). */
-									for (int i = 0; i != _smallmap_industry_count; i++) {
-										_legend_from_industries[i].show_on_map = true;
-									}
-								}
-							} else {
-								_legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
+						if (click_pos < _smallmap_industry_count) {
+							this->SelectLegendItem(click_pos, _legend_from_industries, _smallmap_industry_count);
+						}
+					/* Check if click was on linkstats label*/
+					} else if (this->map_type == SMT_LINKSTATS) {
+						if (click_pos < _smallmap_cargo_count) {
+							this->SelectLegendItem(click_pos, _legend_linkstats, _smallmap_cargo_count);
+						} else {
+							uint stats_column = CeilDiv(_smallmap_cargo_count, number_of_rows);
+							if (column == stats_column && line < NUM_STATS) {
+								this->SelectLegendItem(_smallmap_cargo_count + line, _legend_linkstats,
+										_smallmap_cargo_count + NUM_STATS, _smallmap_cargo_count);
 							}
 						}
+					/* Check if click is on company label. */
 					} else if (this->map_type == SMT_OWNER) {
-						/* If click on companies label, find right company and enable/disable it. */
-						int company_pos = (column * number_of_rows) + line;
-						if (company_pos < NUM_NO_COMPANY_ENTRIES) break;
-						if (company_pos < _smallmap_company_count) {
-							if (_ctrl_pressed) {
-								/* Disable all, except the clicked one */
-								bool changes = false;
-								for (int i = NUM_NO_COMPANY_ENTRIES; i != _smallmap_company_count; i++) {
-									bool new_state = i == company_pos;
-									if (_legend_land_owners[i].show_on_map != new_state) {
-										changes = true;
-										_legend_land_owners[i].show_on_map = new_state;
-									}
-								}
-								if (!changes) {
-									/* Nothing changed? Then show all (again). */
-									for (int i = NUM_NO_COMPANY_ENTRIES; i != _smallmap_company_count; i++) {
-										_legend_land_owners[i].show_on_map = true;
-									}
-								}
-							} else {
-								_legend_land_owners[company_pos].show_on_map = !_legend_land_owners[company_pos].show_on_map;
-							}
+						if (click_pos < _smallmap_company_count) {
+						this->SelectLegendItem(click_pos, _legend_land_owners, _smallmap_company_count, NUM_NO_COMPANY_ENTRIES);
 						}
 					}
 					this->SetDirty();
 				}
 				break;
 
-			case SM_WIDGET_ENABLE_ALL:
-				if (this->map_type == SMT_INDUSTRY) {
-					for (int i = 0; i != _smallmap_industry_count; i++) {
-						_legend_from_industries[i].show_on_map = true;
+			case SM_WIDGET_ENABLE_ALL: // enable/diable all items
+			case SM_WIDGET_DISABLE_ALL: {
+				LegendAndColour *tbl = NULL;
+					switch (this->map_type) {
+						case SMT_INDUSTRY:
+							tbl = _legend_from_industries;
+							break;
+						case SMT_OWNER:
+							tbl = &(_legend_land_owners[NUM_NO_COMPANY_ENTRIES]);
+							break;
+						case SMT_LINKSTATS:
+							tbl = _legend_linkstats;
+							break;
+						default:
+							NOT_REACHED();
 					}
-				} else if (this->map_type == SMT_OWNER) {
-					for (int i = NUM_NO_COMPANY_ENTRIES; i != _smallmap_company_count; i++) {
-						_legend_land_owners[i].show_on_map = true;
-					}
-				}
+
+				for (;!tbl->end; ++tbl) tbl->show_on_map = (widget == SM_WIDGET_ENABLE_ALL);
 				this->SetDirty();
 				break;
-
-			case SM_WIDGET_DISABLE_ALL:
-				if (this->map_type == SMT_INDUSTRY) {
-					for (int i = 0; i != _smallmap_industry_count; i++) {
-						_legend_from_industries[i].show_on_map = false;
-					}
-				} else {
-					for (int i = NUM_NO_COMPANY_ENTRIES; i != _smallmap_company_count; i++) {
-						_legend_land_owners[i].show_on_map = false;
-					}
-				}
-				this->SetDirty();
-				break;
+			}
 
 			case SM_WIDGET_SHOW_HEIGHT: // Enable/disable showing of heightmap.
 				_smallmap_show_heightmap = !_smallmap_show_heightmap;
@@ -1434,6 +3614,22 @@
 		}
 	}
 
+	virtual void OnMouseOver(Point pt, int widget)
+	{
+		static Point invalid = {-1, -1};
+		if (widget == SM_WIDGET_MAP) {
+			const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
+			pt.x -= wid->pos_x;
+			pt.y -= wid->pos_y;
+			if (pt.x != cursor.x || pt.y != cursor.y) {
+				this->refresh = 1;
+				cursor = pt;
+			}
+		} else {
+			cursor = invalid;
+		}
+	}
+
 	/**
 	 * Some data on this window has become invalid.
 	 * @param data Information about the changed data.
@@ -1491,6 +3687,8 @@
 		/* Update the window every now and then */
 		if (--this->refresh != 0) return;
 
+		this->RecalcVehiclePositions();
+
 		this->refresh = FORCE_REFRESH_PERIOD;
 		this->SetDirty();
 	}
@@ -1506,8 +3704,13 @@
 	{
 		const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
 		Point hv = InverseRemapCoords(wi->current_x * TILE_SIZE / 2, wi->current_y * TILE_SIZE / 2);
-		hv.x *= this->zoom;
-		hv.y *= this->zoom;
+		if (this->zoom > 0) {
+			hv.x *= this->zoom;
+			hv.y *= this->zoom;
+		} else {
+			hv.x /= (-this->zoom);
+			hv.y /= (-this->zoom);
+		}
 
 		if (sx < -hv.x) {
 			sx = -hv.x;
@@ -1537,8 +3740,8 @@
 
 		/* While tile is at (delta.x, delta.y)? */
 		int sub;
-		Point pt = this->PixelToTile(delta.x, delta.y, &sub);
-		this->SetNewScroll(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, sub);
+		Point pt = this->PixelToWorld(delta.x, delta.y, &sub);
+		this->SetNewScroll(this->scroll_x + pt.x, this->scroll_y + pt.y, sub);
 
 		this->SetDirty();
 	}
@@ -1550,10 +3753,12 @@
 
 		int sub;
 		const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
-		Point sxy = this->ComputeScroll(pt.x / TILE_SIZE, pt.y / TILE_SIZE, max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
+		Point sxy = this->ComputeScroll(pt.x, pt.y, max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
 		this->SetNewScroll(sxy.x, sxy.y, sub);
 		this->SetDirty();
 	}
+
+	uint ColumnWidth() const {return column_width;}
 };
 
 SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR;
@@ -1586,6 +3791,7 @@
 		this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
 		this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
 		this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight(smallmap_window->min_number_of_columns));
+//		this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight());
 		this->fill_x = max(display->fill_x, bar->fill_x);
 		this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
 		this->resize_x = max(display->resize_x, bar->resize_x);
@@ -1610,7 +3816,8 @@
 			bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
 		}
 
-		uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->smallest_x)));
+//		uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->smallest_x)));
+		uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(given_width - bar->smallest_x));
 		uint display_height = given_height - bar_height;
 		display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
 		bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
@@ -1651,6 +3858,8 @@
 							SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
 					NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP),
 							SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
+					NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_BLANK), SetMinimalSize(22, 22),
+							SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR),
 							SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
 					NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES),
@@ -1664,6 +3873,8 @@
 							SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
 					NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME),
 							SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
+					NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_LINKSTATS),
+							SetDataTip(SPR_IMG_GRAPHS, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP), SetFill(1, 1),
 					NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES),
 							SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), SetFill(1, 1),
 					NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION),
@@ -1715,7 +3926,7 @@
 };
 
 static const WindowDesc _smallmap_desc(
-	WDP_AUTO, 446, 314,
+	WDP_AUTO, 484, 314,
 	WC_SMALLMAP, WC_NONE,
 	WDF_UNCLICK_BUTTONS,
 	_nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h
--- a/src/smallmap_gui.h
+++ b/src/smallmap_gui.h
@@ -12,6 +12,9 @@
 #ifndef SMALLMAP_GUI_H
 #define SMALLMAP_GUI_H
 
+/* set up the cargos to be displayed in the smallmap's route legend */
+void BuildLinkStatsLegend();
+
 void BuildIndustriesLegend();
 void ShowSmallMap();
 void BuildLandLegend();
diff --git a/src/sound.cpp b/src/sound.cpp
--- a/src/sound.cpp
+++ b/src/sound.cpp
@@ -22,6 +22,7 @@
 #include "base_media_func.h"
 
 static SoundEntry _original_sounds[ORIGINAL_SAMPLE_COUNT];
+MusicFileSettings _msf;
 
 static void OpenBankFile(const char *filename)
 {
@@ -227,7 +228,7 @@
  */
 static void SndPlayScreenCoordFx(SoundID sound, int left, int right, int top, int bottom)
 {
-	if (_settings_client.music.effect_vol == 0) return;
+	if (_msf.effect_vol == 0) return;
 
 	const Window *w;
 	FOR_ALL_WINDOWS_FROM_BACK(w) {
@@ -243,7 +244,7 @@
 			StartSound(
 				sound,
 				panning,
-				(_settings_client.music.effect_vol * _vol_factor_by_zoom[vp->zoom - ZOOM_LVL_BEGIN]) / 256
+				(_msf.effect_vol * _vol_factor_by_zoom[vp->zoom - ZOOM_LVL_BEGIN]) / 256
 			);
 			return;
 		}
@@ -272,7 +273,7 @@
 
 void SndPlayFx(SoundID sound)
 {
-	StartSound(sound, 0.5, _settings_client.music.effect_vol);
+	StartSound(sound, 0.5, _msf.effect_vol);
 }
 
 INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia<SoundsSet>, SoundsSet)
diff --git a/src/sound_func.h b/src/sound_func.h
--- a/src/sound_func.h
+++ b/src/sound_func.h
@@ -16,6 +16,8 @@
 #include "vehicle_type.h"
 #include "tile_type.h"
 
+extern MusicFileSettings _msf;
+
 void SndPlayTileFx(SoundID sound, TileIndex tile);
 void SndPlayVehicleFx(SoundID sound, const Vehicle *v);
 void SndPlayFx(SoundID sound);
diff --git a/src/sound_type.h b/src/sound_type.h
--- a/src/sound_type.h
+++ b/src/sound_type.h
@@ -12,6 +12,16 @@
 #ifndef SOUND_TYPE_H
 #define SOUND_TYPE_H
 
+struct MusicFileSettings {
+	byte playlist;
+	byte music_vol;
+	byte effect_vol;
+	byte custom_1[33];
+	byte custom_2[33];
+	bool playing;
+	bool shuffle;
+};
+
 struct SoundEntry {
 	uint8 file_slot;
 	size_t file_offset;
diff --git a/src/station.cpp b/src/station.cpp
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -61,10 +61,16 @@
 	last_vehicle_type(VEH_INVALID)
 {
 	/* this->random_bits is set in Station::AddFacility() */
+
+	/* has to be done like this as we can't give arguments when constructing an array */
+	for (CargoID i = 0; i < NUM_CARGO; ++i) {
+		this->goods[i].cargo.AssignTo(this, i);
+	}
 }
 
 /**
- * Clean up a station by clearing vehicle orders and invalidating windows.
+ * Clean up a station by clearing vehicle orders, invalidating windows and
+ * removing link stats.
  * Aircraft-Hangar orders need special treatment here, as the hangars are
  * actually part of a station (tiletype is STATION), but the order type
  * is OT_GOTO_DEPOT.
@@ -88,12 +94,26 @@
 		if (a->targetairport == this->index) a->targetairport = INVALID_STATION;
 	}
 
+	Station *st;
+	FOR_ALL_STATIONS(st) {
+		for (CargoID c = 0; c < NUM_CARGO; ++c) {
+			GoodsEntry &ge = st->goods[c];
+			ge.link_stats.erase(this->index);
+			DeleteStaleFlows(st->index, c, this->index);
+			ge.cargo.RerouteStalePackets(this->index);
+		}
+	}
+
 	Vehicle *v;
 	FOR_ALL_VEHICLES(v) {
 		/* Forget about this station if this station is removed */
 		if (v->last_station_visited == this->index) {
 			v->last_station_visited = INVALID_STATION;
 		}
+
+		if (v->last_loading_station == this->index) {
+			v->last_loading_station = INVALID_STATION;
+		}
 	}
 
 	/* Clear the persistent storage. */
diff --git a/src/station_base.h b/src/station_base.h
--- a/src/station_base.h
+++ b/src/station_base.h
@@ -17,6 +17,10 @@
 #include "cargopacket.h"
 #include "industry_type.h"
 #include "newgrf_storage.h"
+#include "linkgraph/linkgraph_type.h"
+#include "moving_average.h"
+#include <map>
+#include <set>
 
 typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
 extern StationPool _station_pool;
@@ -24,6 +28,276 @@
 static const byte INITIAL_STATION_RATING = 175;
 
 /**
+ * Link statistics. They include figures for capacity and usage of a link. Both
+ * are moving averages which are increased for every vehicle arriving at the
+ * destination station and decreased in regular intervals. Additionally while a
+ * vehicle is loading at the source station part of the capacity is frozen and
+ * prevented from being decreased. This is done so that the link won't break
+ * down all the time when the typical "full load" order is used.
+ */
+class LinkStat : private MovingAverage<uint> {
+private:
+	/**
+	 * Capacity of the link.
+	 * This is a moving average. Use MovingAverage::Monthly() to get a meaningful value.
+	 */
+	uint capacity;
+	
+	/**
+	 * Capacity of currently loading vehicles
+	 */
+	uint frozen;
+	
+	/**
+	 * Usage of the link.
+	 * This is a moving average. Use MovingAverage::Monthly() to get a meaningful value.
+	 */
+	uint usage;
+
+public:
+	/**
+	 * Minimum length of moving averages for capacity and usage.
+	 */
+	static const uint MIN_AVERAGE_LENGTH = 96;
+
+	friend const SaveLoad *GetLinkStatDesc();
+
+	FORCEINLINE LinkStat(uint distance = 1, uint capacity = 0, uint frozen = 0, uint usage = 0) :
+		MovingAverage<uint>(distance), capacity(capacity), frozen(frozen), usage(usage) {}
+
+	/**
+	 * Reset everything to 0.
+	 */
+	FORCEINLINE void Clear()
+	{
+		this->capacity = 0;
+		this->usage = 0;
+		this->frozen = 0;
+	}
+
+	/**
+	 * Apply the moving averages to usage and capacity.
+	 */
+	FORCEINLINE void Decrease()
+	{
+		this->MovingAverage<uint>::Decrease(this->usage);
+		this->capacity = max(this->MovingAverage<uint>::Decrease(this->capacity), this->frozen);
+	}
+
+	/**
+	 * Get an estimate of the current capacity by calculating the moving average.
+	 * @return Capacity.
+	 */
+	FORCEINLINE uint Capacity() const
+	{
+		return this->MovingAverage<uint>::Monthly(this->capacity);
+	}
+
+	/**
+	 * Get an estimate of the current usage by calculating the moving average.
+	 * @rerturn Usage.
+	 */
+	FORCEINLINE uint Usage() const
+	{
+		return this->MovingAverage<uint>::Monthly(this->usage);
+	}
+
+	/**
+	 * Get the amount of frozen capacity.
+	 * @return Frozen capacity.
+	 */
+	FORCEINLINE uint Frozen() const
+	{
+		return this->frozen;
+	}
+
+	/**
+	 * Add some capacity and usage.
+	 * @param capacity Additional capacity.
+	 * @param usage Additional usage.
+	 */
+	FORCEINLINE void Increase(uint capacity, uint usage)
+	{
+		this->capacity += capacity;
+		this->usage += usage;
+	}
+
+	/**
+	 * Freeze some of the capacity and prevent it from being decreased by the
+	 * moving average.
+	 * @param capacity Amount of capacity to be frozen.
+	 */
+	FORCEINLINE void Freeze(uint capacity)
+	{
+		this->frozen += capacity;
+		this->capacity = max(this->frozen, this->capacity);
+	}
+
+	/**
+	 * Thaw some of the frozen capacity and make it available for Decrease().
+	 * @param capacity Capacity to be thawed.
+	 */
+	FORCEINLINE void Unfreeze(uint capacity)
+	{
+		this->frozen -= capacity;
+	}
+
+	/**
+	 * Thaw all frozen capacity.
+	 */
+	FORCEINLINE void Unfreeze()
+	{
+		this->frozen = 0;
+	}
+
+	/**
+	 * Check if the capacity is 0. This is necessary as Capacity() might return
+	 * 0 even if there is a miniscule amount of capacity left.
+	 * @return If capacity is 0.
+	 */
+	FORCEINLINE bool IsNull() const
+	{
+		return this->capacity == 0;
+	}
+};
+
+/**
+ * Flow statistics telling how much flow should be and was sent along a link.
+ */
+class FlowStat : private MovingAverage<uint> {
+private:
+	uint planned;  ///< Cargo planned to be sent along a link each "month" (30 units of time, determined by moving average).
+	uint sent;     ///< Moving average of cargo being sent.
+	StationID via; ///< Other end of the link. Can be this station, then it means "deliver here".
+
+public:
+	friend const SaveLoad *GetFlowStatDesc();
+
+	/**
+	 * Create a flow stat.
+	 * @param distance Distance to be used as length of moving average.
+	 * @param st Remote station.
+	 * @param planned Cargo planned to be sent along this link.
+	 * @param sent Cargo already sent along this link.
+	 */
+	FORCEINLINE FlowStat(uint distance = 1, StationID st = INVALID_STATION, uint planned = 0, uint sent = 0) :
+		MovingAverage<uint>(distance), planned(planned), sent(sent), via(st) {}
+
+	/**
+	 * Clone an existing flow stat, changing the plan.
+	 * @param prev Flow stat to be cloned.
+	 * @param new_plan New value for planned.
+	 */
+	FORCEINLINE FlowStat(const FlowStat &prev, uint new_plan) :
+		MovingAverage<uint>(prev.length), planned(new_plan), sent(prev.sent), via(prev.via) {}
+
+	/**
+	 * Prevents one copy operation when moving a flowstat from one set to another and decreasing it at the same time.
+	 */
+	FORCEINLINE FlowStat GetDecreasedCopy() const
+	{
+		FlowStat ret(this->length, this->via, this->planned, this->sent);
+		this->MovingAverage<uint>::Decrease(ret.sent);
+		return ret;
+	}
+
+	/**
+	 * Increase the sent value.
+	 * @param sent Amount to be added to sent.
+	 */
+	FORCEINLINE void Increase(uint sent)
+	{
+		this->sent += sent;
+	}
+
+	/**
+	 * Get an estimate of cargo sent along this link during the last 30 time units.
+	 * @return Cargo sent along this link.
+	 */
+	FORCEINLINE uint Sent() const
+	{
+		return this->MovingAverage<uint>::Monthly(sent);
+	}
+
+	/**
+	 * Get the amount of cargo planned to be sent along this link in 30 time units.
+	 * @return Cargo planned to be sent.
+	 */
+	FORCEINLINE uint Planned() const
+	{
+		return this->planned;
+	}
+
+	/**
+	 * Get the station this link is connected to.
+	 * @return Remote station.
+	 */
+	FORCEINLINE StationID Via() const
+	{
+		return this->via;
+	}
+
+	/**
+	 * Comparator for two flow stats for ordering them in a way that makes
+	 * the next flow stat to sent cargo for show up as first element.
+	 */
+	struct Comparator {
+		/**
+		 * Comparator function. Decides by planned - sent or via, if those
+		 * are equal.
+		 * @param x First flow stat.
+		 * @param y Second flow stat.
+		 * @return True if x.planned - x.sent is greater than y.planned - y.sent.
+		 */
+		bool operator()(const FlowStat &x, const FlowStat &y) const {
+			int diff_x = (int)x.Planned() - (int)x.Sent();
+			int diff_y = (int)y.Planned() - (int)y.Sent();
+			if (diff_x != diff_y) {
+				return diff_x > diff_y;
+			} else {
+				return x.Via() > y.Via();
+			}
+		}
+	};
+
+	/**
+	 * Add up two flow stats' planned and sent figures and assign via from the other one to this one.
+	 * @param other Flow stat to add to this one.
+	 * @return This flow stat.
+	 */
+	FORCEINLINE FlowStat &operator+=(const FlowStat &other)
+	{
+		assert(this->via == INVALID_STATION || other.via == INVALID_STATION || this->via == other.via);
+		if (other.via != INVALID_STATION) this->via = other.via;
+		this->planned += other.planned;
+		uint sent = this->sent + other.sent;
+		if (sent > 0) {
+			this->length = (this->length * this->sent + other.length * other.sent) / sent;
+			assert(this->length > 0);
+		}
+		this->sent = sent;
+		return *this;
+	}
+
+	/**
+	 * Clear this flow stat.
+	 */
+	FORCEINLINE void Clear()
+	{
+		this->planned = 0;
+		this->sent = 0;
+		this->via = INVALID_STATION;
+	}
+};
+
+typedef std::set<FlowStat, FlowStat::Comparator> FlowStatSet; ///< Percentage of flow to be sent via specified station (or consumed locally).
+
+typedef std::map<StationID, LinkStat> LinkStatMap;
+typedef std::map<StationID, FlowStatSet> FlowStatMap; ///< Flow descriptions by origin stations.
+
+uint GetMovingAverageLength(const Station *from, const Station *to);
+
+/**
  * Stores station stats for a single cargo.
  */
 struct GoodsEntry {
@@ -42,7 +316,11 @@
 		days_since_pickup(255),
 		rating(INITIAL_STATION_RATING),
 		last_speed(0),
-		last_age(255)
+		last_age(255),
+		supply(0),
+		supply_new(0),
+		last_component(INVALID_LINKGRAPH_COMPONENT),
+		max_waiting_cargo(0)
 	{}
 
 	byte acceptance_pickup; ///< Status of this cargo, see #GoodsEntryStatus.
@@ -50,8 +328,22 @@
 	byte rating;            ///< Station rating for this cargo.
 	byte last_speed;        ///< Maximum speed of the last vehicle that picked up this cargo (up to 255).
 	byte last_age;          ///< Age in years of the last vehicle that picked up this cargo.
-	byte amount_fract;      ///< Fractional part of the amount in the cargo list
-	StationCargoList cargo; ///< The cargo packets of cargo waiting in this station
+	byte amount_fract;                   ///< Fractional part of the amount in the cargo list.
+	StationCargoList cargo;              ///< The cargo packets of cargo waiting in this station.
+	uint supply;                         ///< Cargo supplied last month.
+	uint supply_new;                     ///< Cargo supplied so far this month.
+	FlowStatMap flows;                   ///< Planned flows through this station.
+	LinkStatMap link_stats;              ///< Capacities and usage statistics for outgoing links.
+	LinkGraphComponentID last_component; ///< Component this station was last part of in this cargo's link graph.
+	uint max_waiting_cargo;              ///< Max cargo from this station waiting at any station.
+	
+	FlowStat GetSumFlowVia(StationID via) const;
+
+	void UpdateFlowStats(StationID source, uint count, StationID next);
+	void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
+	void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
+
+	StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
 };
 
 /** All airport-related information. Only valid if tile != INVALID_TILE. */
@@ -257,6 +549,8 @@
 	/* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
 
 	/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
+
+	void RunAverages();
 };
 
 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -46,6 +46,7 @@
 #include "debug.h"
 #include "core/random_func.hpp"
 #include "company_base.h"
+#include "moving_average.h"
 #include "table/airporttile_ids.h"
 #include "newgrf_airporttiles.h"
 #include "order_backup.h"
@@ -3077,6 +3078,19 @@
 			int rating = 0;
 			uint waiting = ge->cargo.Count();
 
+			/* num_dests is at least 1 if there is any cargo as
+			 * INVALID_STATION is also a destination.
+			 */
+			uint num_dests = (uint)ge->cargo.Packets()->MapSize();
+
+			/* Average amount of cargo per next hop, but prefer solitary stations
+			 * with only one or two next hops. They are allowed to have more
+			 * cargo waiting per next hop.
+			 * With manual cargo distribution waiting_avg = waiting / 2 as then
+			 * INVALID_STATION is the only destination.
+			 */
+			uint waiting_avg = waiting / (num_dests + 1);
+
 			if (HasBit(cs->callback_mask, CBM_CARGO_STATION_RATING_CALC)) {
 				/* Perform custom station rating. If it succeeds the speed, days in transit and
 				 * waiting cargo ratings must not be executed. */
@@ -3085,7 +3099,7 @@
 				uint last_speed = ge->last_speed;
 				if (last_speed == 0) last_speed = 0xFF;
 
-				uint32 var18 = min(ge->days_since_pickup, 0xFF) | (min(waiting, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
+				uint32 var18 = min(ge->days_since_pickup, 0xFF) | (min(ge->max_waiting_cargo, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
 				/* Convert to the 'old' vehicle types */
 				uint32 var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
 				uint16 callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
@@ -3110,11 +3124,11 @@
 				(rating += 45, days > 3) ||
 				(rating += 35, true);
 
-				(rating -= 90, waiting > 1500) ||
-				(rating += 55, waiting > 1000) ||
-				(rating += 35, waiting > 600) ||
-				(rating += 10, waiting > 300) ||
-				(rating += 20, waiting > 100) ||
+				(rating -= 90, ge->max_waiting_cargo > 1500) ||
+				(rating += 55, ge->max_waiting_cargo > 1000) ||
+				(rating += 35, ge->max_waiting_cargo > 600) ||
+				(rating += 10, ge->max_waiting_cargo > 300) ||
+				(rating += 20, ge->max_waiting_cargo > 100) ||
 				(rating += 10, true);
 			}
 
@@ -3132,12 +3146,12 @@
 				/* 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,
+				/* if rating is <= 64 and more than 100 items waiting on average per destination,
 				 * remove some random amount of goods from the station */
-				if (rating <= 64 && waiting >= 200) {
+				if (rating <= 64 && waiting_avg >= 100) {
 					int dec = Random() & 0x1F;
-					if (waiting < 400) dec &= 7;
-					waiting -= dec + 1;
+					if (waiting_avg < 200) dec &= 7;
+					waiting -= (dec + 1) * num_dests;
 					waiting_changed = true;
 				}
 
@@ -3146,7 +3160,7 @@
 					uint32 r = Random();
 					if (rating <= (int)GB(r, 0, 7)) {
 						/* Need to have int, otherwise it will just overflow etc. */
-						waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0);
+						waiting = max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0);
 						waiting_changed = true;
 					}
 				}
@@ -3166,7 +3180,28 @@
 					waiting_changed = true;
 				}
 
-				if (waiting_changed) ge->cargo.Truncate(waiting);
+				if (waiting_changed) {
+					/* feed back the exact own waiting cargo at this station for the
+					 * next rating calculation.
+					 */
+					ge->max_waiting_cargo = 0;
+
+					/* If truncating also punish the source stations' ratings to
+					 * decrease the flow of incoming cargo. */
+
+					StationCargoAmountMap waiting_per_source;
+					ge->cargo.CountAndTruncate(waiting, waiting_per_source);
+					for (StationCargoAmountMap::iterator i(waiting_per_source.begin()); i != waiting_per_source.end(); ++i) {
+						Station *source_station = Station::GetIfValid(i->first);
+						if (source_station == NULL) continue;
+
+						GoodsEntry &source_ge = source_station->goods[cs->Index()];
+						source_ge.max_waiting_cargo = max(source_ge.max_waiting_cargo, i->second);
+					}
+				} else {
+					/* if the average number per next hop is low, be more forgiving. */
+					ge->max_waiting_cargo = waiting_avg;
+				}
 			}
 		}
 	}
@@ -3179,7 +3214,202 @@
 	}
 }
 
-/* called for every station each tick */
+/**
+ * Delete all flows at a station for specific cargo and destination.
+ * @param at Station to delete flows from.
+ * @param c_id Cargo for which flows shall be deleted.
+ * @param to Remote station of flows to be deleted.
+ */
+void DeleteStaleFlows(StationID at, CargoID c_id, StationID to)
+{
+	FlowStatMap &flows = Station::Get(at)->goods[c_id].flows;
+	for (FlowStatMap::iterator f_it = flows.begin(); f_it != flows.end();) {
+		FlowStatSet &s_flows = f_it->second;
+		for (FlowStatSet::iterator s_it = s_flows.begin(); s_it != s_flows.end();) {
+			if (s_it->Via() == to) {
+				s_flows.erase(s_it++);
+				break; // There can only be one flow stat for this remote station in each set.
+			} else {
+				++s_it;
+			}
+		}
+		if (s_flows.empty()) {
+			flows.erase(f_it++);
+		} else {
+			++f_it;
+		}
+	}
+}
+
+/**
+ * Get the length of a moving average for a link between two stations.
+ * @param from Source station.
+ * @param to Destination station.
+ * @return Moving average length.
+ */
+uint GetMovingAverageLength(const Station *from, const Station *to)
+{
+	return LinkStat::MIN_AVERAGE_LENGTH + (DistanceManhattan(from->xy, to->xy) >> 2);
+}
+
+/**
+ * Run the moving average decrease function for all link stats.
+ */
+void Station::RunAverages()
+{
+	FlowStatSet new_flows;
+	for (int goods_index = 0; goods_index < NUM_CARGO; ++goods_index) {
+		LinkStatMap &links = this->goods[goods_index].link_stats;
+		for (LinkStatMap::iterator i = links.begin(); i != links.end();) {
+			StationID id = i->first;
+			Station *other = Station::GetIfValid(id);
+			if (other == NULL) {
+				this->goods[goods_index].cargo.RerouteStalePackets(id);
+				links.erase(i++);
+			} else {
+				LinkStat &ls = i->second;
+				ls.Decrease();
+				if (ls.IsNull()) {
+					DeleteStaleFlows(this->index, goods_index, id);
+					this->goods[goods_index].cargo.RerouteStalePackets(id);
+					links.erase(i++);
+				} else {
+					++i;
+				}
+			}
+		}
+
+		if (_settings_game.linkgraph.GetDistributionType(goods_index) == DT_MANUAL) {
+			this->goods[goods_index].flows.clear();
+			continue;
+		}
+
+		FlowStatMap &flows = this->goods[goods_index].flows;
+		for (FlowStatMap::iterator i = flows.begin(); i != flows.end();) {
+			if (!Station::IsValidID(i->first)) {
+				flows.erase(i++);
+			} else {
+				FlowStatSet &flow_set = i->second;
+				for (FlowStatSet::iterator j = flow_set.begin(); j != flow_set.end(); ++j) {
+					if (Station::IsValidID(j->Via())) {
+						new_flows.insert(j->GetDecreasedCopy());
+					}
+				}
+				flow_set.swap(new_flows);
+				new_flows.clear();
+				++i;
+			}
+		}
+	}
+}
+
+/**
+ * Recalculate the frozen value of the station the given vehicle is loading at
+ * if the vehicle is loading.
+ * @param v Vehicle to be examined.
+ */
+void RecalcFrozenIfLoading(const Vehicle *v)
+{
+	if (v->current_order.IsType(OT_LOADING)) {
+		RecalcFrozen(Station::Get(v->last_station_visited));
+	}
+}
+
+/**
+ * Recalculate all frozen values for all link stats of a station. This is done
+ * by adding up the capacities of all loading vehicles.
+ * @param st Station.
+ */
+void RecalcFrozen(Station *st)
+{
+	for (CargoID cargo = 0; cargo < NUM_CARGO; ++cargo) {
+		LinkStatMap &links = st->goods[cargo].link_stats;
+		for (LinkStatMap::iterator i = links.begin(); i != links.end(); ++i) {
+			i->second.Unfreeze();
+		}
+	}
+
+	std::list<Vehicle *>::iterator v_it = st->loading_vehicles.begin();
+	while (v_it != st->loading_vehicles.end()) {
+		const Vehicle *front = *v_it;
+		OrderList *orders = front->orders.list;
+		if (orders != NULL) {
+			StationID next_station_id = orders->GetNextStoppingStation(front->cur_implicit_order_index, st->index);
+			if (next_station_id != INVALID_STATION && next_station_id != st->index) {
+				IncreaseStats(st, front, next_station_id, true);
+			}
+		}
+		++v_it;
+	}
+}
+
+/**
+ * Decrease the frozen values of all link stats associated with vehicles in the
+ * given consist (ie the consist is leaving the station).
+ * @param st Station to decrease the frozen values on.
+ * @param front First vehicle in the consist.
+ * @param next_station_id Station the vehicle is leaving for.
+ */
+void DecreaseFrozen(Station *st, const Vehicle *front, StationID next_station_id) {
+	assert(st->index != next_station_id);
+	assert(next_station_id != INVALID_STATION);
+	for (const Vehicle *v = front; v != NULL; v = v->Next()) {
+		if (v->cargo_cap <= 0) continue;
+
+		LinkStatMap &link_stats = st->goods[v->cargo_type].link_stats;
+		LinkStatMap::iterator lstat_it = link_stats.find(next_station_id);
+		if (lstat_it == link_stats.end()) {
+			DEBUG(misc, 1, "frozen not in linkstat list.");
+			RecalcFrozen(st);
+			return;
+		}
+
+		LinkStat &link_stat = lstat_it->second;
+		if (link_stat.Frozen() < v->cargo_cap) {
+			DEBUG(misc, 1, "frozen is smaller than cargo cap.");
+			RecalcFrozen(st);
+			return;
+		}
+		link_stat.Unfreeze(v->cargo_cap);
+		assert(!link_stat.IsNull());
+	}
+}
+
+/**
+ * Either freeze or increase capacity for all link stats associated with vehicles
+ * in the given consist.
+ * @param st Station to get the link stats from.
+ * @param front First vehicle in the consist.
+ * @param next_station_id Station the consist will be travelling to next.
+ * @param freeze If true, freeze capacity, otherwise increase capacity.
+ */
+void IncreaseStats(Station *st, const Vehicle *front, StationID next_station_id, bool freeze)
+{
+	Station *next = Station::GetIfValid(next_station_id);
+	assert(st->index != next_station_id && next != NULL);
+	uint average_length = GetMovingAverageLength(st, next);
+
+	for (const Vehicle *v = front; v != NULL; v = v->Next()) {
+		if (v->cargo_cap > 0) {
+			LinkStatMap &stats = st->goods[v->cargo_type].link_stats;
+			LinkStatMap::iterator i = stats.find(next_station_id);
+			if (i == stats.end()) {
+				stats.insert(std::make_pair(next_station_id, LinkStat(average_length,
+						v->cargo_cap, freeze ? v->cargo_cap : 0, freeze ? 0 : v->cargo.Count())));
+			} else {
+				LinkStat &link_stat = i->second;
+				if (freeze) {
+					link_stat.Freeze(v->cargo_cap);
+				} else {
+					link_stat.Increase(v->cargo_cap, v->cargo.Count());
+				}
+				assert(!link_stat.IsNull());
+			}
+		}
+	}
+}
+
+/* Called for every station each tick. */
 static void StationHandleSmallTick(BaseStation *st)
 {
 	if ((st->facilities & FACIL_WAYPOINT) != 0 || !st->IsInUse()) return;
@@ -3195,6 +3425,8 @@
 {
 	if (_game_mode == GM_EDITOR) return;
 
+	RunAverages<Station>();
+
 	BaseStation *st;
 	FOR_ALL_BASE_STATIONS(st) {
 		StationHandleSmallTick(st);
@@ -3217,6 +3449,13 @@
 	Station *st;
 
 	FOR_ALL_STATIONS(st) {
+		for(int goods_index = 0; goods_index < NUM_CARGO; ++goods_index) {
+			st->goods[goods_index].supply = st->goods[goods_index].supply_new;
+			st->goods[goods_index].supply_new = 0;
+		}
+	}
+
+	FOR_ALL_STATIONS(st) {
 		for (CargoID i = 0; i < NUM_CARGO; i++) {
 			GoodsEntry *ge = &st->goods[i];
 			SB(ge->acceptance_pickup, GoodsEntry::GES_LAST_MONTH, 1, GB(ge->acceptance_pickup, GoodsEntry::GES_CURRENT_MONTH, 1));
@@ -3258,7 +3497,42 @@
 	/* No new "real" cargo item yet. */
 	if (amount == 0) return 0;
 
-	ge.cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id));
+	StationID id = st->index;
+	StationID next = INVALID_STATION;
+	FlowStatSet &flow_stats = ge.flows[id];
+	FlowStatSet::iterator i = flow_stats.begin();
+	if (i != flow_stats.end()) {
+		next = i->Via();
+		const FlowStat &f = *i;
+
+		if (_settings_game.linkgraph.no_overload_links &&
+				_settings_game.linkgraph.GetDistributionType(type) == DT_SYMMETRIC) {
+			int limit = f.Planned() - f.Sent();
+
+			LinkStatMap::const_iterator it = ge.link_stats.find(next);
+			const LinkStat &ls = (it->second);
+
+			/* Don't send more than was planned or if the link's usage is higher than permitted. */
+			limit = min(limit, (ls.Capacity() * _settings_game.linkgraph.short_path_saturation) / 100 - ls.Usage());
+
+			if (limit < 0) {
+				limit = 0;
+			}
+
+			if (amount > (uint)limit) {
+				amount = (uint)limit;
+			}
+		}
+
+ 		ge.UpdateFlowStats(flow_stats, i, amount);
+
+		if (amount == 0) {
+			return amount;
+		}
+	}
+
+	ge.cargo.Append(next, new CargoPacket(st->index, st->xy, amount, source_type, source_id));
+	ge.supply_new += amount;
 
 	if (!HasBit(ge.acceptance_pickup, GoodsEntry::GES_PICKUP)) {
 		InvalidateWindowData(WC_STATION_LIST, st->index);
@@ -3632,6 +3906,95 @@
 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 }
 
+/**
+ * Update the flow stats for a specific entry.
+ * @param flow_stats Flow stats to update.
+ * @param flow_it Iterator pointing to an entry in flow_stats.
+ * @param count Amount by which the flow should be increased.
+ */
+void GoodsEntry::UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count)
+{
+	FlowStat fs = *flow_it;
+	fs.Increase(count);
+	flow_stats.erase(flow_it);
+	flow_stats.insert(fs);
+}
+
+/**
+ * Update the flow stats for a specific next station.
+ * @param flow_stats Flow stats to update.
+ * @param count Amount by which the flow should be increased.
+ * @param next Next hop for which the flow stats should be updated.
+ */
+void GoodsEntry::UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next)
+{
+	FlowStatSet::iterator flow_it = flow_stats.begin();
+	while (flow_it != flow_stats.end()) {
+		StationID via = flow_it->Via();
+		if (via == next) { //usually the first one is the correct one
+			this->UpdateFlowStats(flow_stats, flow_it, count);
+			return;
+		} else {
+			++flow_it;
+		}
+	}
+}
+
+/**
+ * Update the flow stats for "count" cargo from "source" sent to "next".
+ * @param source ID of station the cargo is from.
+ * @param count Amount of cargo.
+ * @param next ID of the station the cargo is travelling to.
+ */
+void GoodsEntry::UpdateFlowStats(StationID source, uint count, StationID next)
+{
+	if (source == INVALID_STATION || next == INVALID_STATION || this->flows.empty()) return;
+	FlowStatSet &flow_stats = this->flows[source];
+	this->UpdateFlowStats(flow_stats, count, next);
+}
+
+/**
+ * Update the flow stats for "count" cargo that cannot be delivered here.
+ * @param source ID of station where the cargo is from.
+ * @param count Amount of cargo.
+ * @param curr ID of station where it is stored for now.
+ * @return ID of the station where the cargo is sent next.
+ */
+StationID GoodsEntry::UpdateFlowStatsTransfer(StationID source, uint count, StationID curr)
+{
+	if (source == INVALID_STATION || this->flows.empty()) return INVALID_STATION;
+	FlowStatSet &flow_stats = this->flows[source];
+	FlowStatSet::iterator flow_it = flow_stats.begin();
+	while (flow_it != flow_stats.end()) {
+		StationID via = flow_it->Via();
+		if (via != curr) {
+			this->UpdateFlowStats(flow_stats, flow_it, count);
+			return via;
+		} else {
+			++flow_it;
+		}
+	}
+	return INVALID_STATION;
+}
+
+/**
+ * Get the sum of flows via a specific station from this GoodsEntry.
+ * @param via Remote station to look for.
+ * @return a FlowStat with all flows for 'via' added up.
+ */
+FlowStat GoodsEntry::GetSumFlowVia(StationID via) const {
+	FlowStat ret(1, via);
+	for (FlowStatMap::const_iterator i = this->flows.begin(); i != this->flows.end(); ++i) {
+		const FlowStatSet &flow_set = i->second;
+		for (FlowStatSet::const_iterator j = flow_set.begin(); j != flow_set.end(); ++j) {
+			const FlowStat &flow = *j;
+			if (flow.Via() == via) {
+				ret += flow;
+			}
+		}
+	}
+	return ret;
+}
 
 extern const TileTypeProcs _tile_type_station_procs = {
 	DrawTile_Station,           // draw_tile_proc
diff --git a/src/station_func.h b/src/station_func.h
--- a/src/station_func.h
+++ b/src/station_func.h
@@ -18,6 +18,7 @@
 #include "road_type.h"
 #include "cargo_type.h"
 #include "company_type.h"
+#include "vehicle_type.h"
 
 void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
 
@@ -46,4 +47,14 @@
 
 void UpdateAirportsNoise();
 
+void DecreaseFrozen(Station *st, const Vehicle *v, StationID next_station_id);
+
+void RecalcFrozen(Station *st);
+
+void RecalcFrozenIfLoading(const Vehicle *v);
+
+void IncreaseStats(Station *st, const Vehicle *v, StationID next_station_id, bool freeze);
+
+void DeleteStaleFlows(StationID at, CargoID c_id, StationID to);
+
 #endif /* STATION_FUNC_H */
diff --git a/src/station_gui.cpp b/src/station_gui.cpp
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -19,6 +19,7 @@
 #include "cargotype.h"
 #include "station_gui.h"
 #include "strings_func.h"
+#include "string_func.h"
 #include "window_func.h"
 #include "viewport_func.h"
 #include "widgets/dropdown_func.h"
@@ -29,9 +30,12 @@
 #include "sortlist_type.h"
 #include "core/geometry_func.hpp"
 #include "vehiclelist.h"
+#include "departures_gui.h"
 
 #include "table/strings.h"
 
+#include <vector>
+
 /**
  * Draw a (multi)line of cargos seperated by commas, and prefixed with a string.
  * @param cargo_mask Mask of cargos to include in the list.
@@ -273,7 +277,7 @@
 			GetString(buf_cache, STR_STATION_NAME, lastof(buf_cache));
 		}
 
-		return strcmp(buf, buf_cache);
+		return strnatcmp(buf, buf_cache); // sort by name using natural sorting
 	}
 
 	/** Sort stations by their type */
@@ -818,10 +822,18 @@
 		NWidget(WWT_STICKYBOX, COLOUR_GREY),
 	EndContainer(),
 	NWidget(NWID_HORIZONTAL),
-		NWidget(WWT_PANEL, COLOUR_GREY, SVW_WAITING), SetMinimalSize(237, 52), SetResize(1, 10), SetScrollbar(SVW_SCROLLBAR), EndContainer(),
+		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SVW_SORT_ORDER), SetMinimalSize(81, 12), SetFill(1, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
+		NWidget(WWT_DROPDOWN, COLOUR_GREY, SVW_SORT_BY), SetMinimalSize(168, 12), SetResize(1, 0), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, SVW_GROUP), SetMinimalSize(81, 12), SetFill(1, 1), SetDataTip(STR_STATION_VIEW_GROUP, 0x0),
+		NWidget(WWT_DROPDOWN, COLOUR_GREY, SVW_GROUP_BY), SetMinimalSize(168, 12), SetResize(1, 0), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_PANEL, COLOUR_GREY, SVW_WAITING), SetMinimalSize(237, 44), SetResize(1, 10), SetScrollbar(SVW_SCROLLBAR), EndContainer(),
 		NWidget(NWID_VSCROLLBAR, COLOUR_GREY, SVW_SCROLLBAR),
 	EndContainer(),
-	NWidget(WWT_PANEL, COLOUR_GREY, SVW_ACCEPTLIST), SetMinimalSize(249, 32), SetResize(1, 0), EndContainer(),
+	NWidget(WWT_PANEL, COLOUR_GREY, SVW_ACCEPTLIST), SetMinimalSize(249, 23), SetResize(1, 0), EndContainer(),
 	NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SVW_LOCATION), SetMinimalSize(60, 12), SetResize(1, 0), SetFill(1, 1),
 				SetDataTip(STR_BUTTON_LOCATION, STR_STATION_VIEW_CENTER_TOOLTIP),
@@ -829,6 +841,8 @@
 				SetDataTip(STR_STATION_VIEW_RATINGS_BUTTON, STR_STATION_VIEW_RATINGS_TOOLTIP),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SVW_RENAME), SetMinimalSize(60, 12), SetResize(1, 0), SetFill(1, 1),
 				SetDataTip(STR_BUTTON_RENAME, STR_STATION_VIEW_RENAME_TOOLTIP),
+		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SVW_DEPARTURES), SetMinimalSize(80, 12), SetResize(1, 0), SetFill(1, 1),
+				SetDataTip(STR_STATION_VIEW_DEPARTURES_BUTTON, STR_STATION_VIEW_DEPARTURES_TOOLTIP),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SVW_TRAINS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_TRAIN, STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SVW_ROADVEHS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_LORRY, STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SVW_SHIPS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_SHIP, STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP),
@@ -854,33 +868,247 @@
 
 	SpriteID sprite = CargoSpec::Get(i)->GetCargoIcon();
 
-	int x = _current_text_dir == TD_RTL ? right - num * 10 : left;
+	int x = _current_text_dir == TD_RTL ? left : right - num * 10;
 	do {
 		DrawSprite(sprite, PAL_NONE, x, y);
 		x += 10;
 	} while (--num);
 }
 
-struct CargoData {
-	CargoID cargo;
-	StationID source;
-	uint count;
+CargoDataEntry::CargoDataEntry() :
+	parent(NULL),
+	station(INVALID_STATION),
+	num_children(0),
+	count(0),
+	children(new CargoDataSet(CargoSorter(ST_CARGO_ID)))
+{}
 
-	CargoData(CargoID cargo, StationID source, uint count) :
-		cargo(cargo),
-		source(source),
-		count(count)
-	{ }
-};
+CargoDataEntry::CargoDataEntry(CargoID cargo, uint count, CargoDataEntry *parent) :
+	parent(parent),
+	cargo(cargo),
+	num_children(0),
+	count(count),
+	children(new CargoDataSet)
+{}
 
-typedef std::list<CargoData> CargoDataList;
+CargoDataEntry::CargoDataEntry(StationID station, uint count, CargoDataEntry *parent) :
+	parent(parent),
+	station(station),
+	num_children(0),
+	count(count),
+	children(new CargoDataSet)
+{}
+
+CargoDataEntry::CargoDataEntry(StationID station) :
+	parent(NULL),
+	station(station),
+	num_children(0),
+	count(0),
+	children(NULL)
+{}
+
+CargoDataEntry::CargoDataEntry(CargoID cargo) :
+	parent(NULL),
+	cargo(cargo),
+	num_children(0),
+	count(0),
+	children(NULL)
+{}
+
+CargoDataEntry::~CargoDataEntry()
+{
+	this->Clear();
+	delete this->children;
+}
+
+/**
+ * Delete all subentries, reset count and num_children and adapt parent's count.
+ */
+void CargoDataEntry::Clear()
+{
+	if (this->children != NULL) {
+		for (CargoDataSet::iterator i = this->children->begin(); i != this->children->end(); ++i) {
+			assert(*i != this);
+			delete *i;
+		}
+		this->children->clear();
+	}
+	if (this->parent != NULL) this->parent->count -= this->count;
+	this->count = 0;
+	this->num_children = 0;
+}
+
+/**
+ * Remove a subentry from this one and delete it.
+ * @param child the entry to be removed. This may also be a synthetic entry
+ * which only contains the ID of the entry to be removed. In this case child is
+ * not deleted.
+ */
+void CargoDataEntry::Remove(CargoDataEntry *child)
+{
+	CargoDataSet::iterator i = this->children->find(child);
+	if (i != this->children->end()) {
+		delete(*i);
+		this->children->erase(i);
+	}
+}
+
+/**
+ * Retrieve a subentry or insert it if it doesn't exist, yet.
+ * @tparam ID type of ID: either StationID or CargoID
+ * @param child_id ID of the child to be inserted or retrieved.
+ * @return the new or retrieved subentry
+ */
+template<class ID>
+CargoDataEntry *CargoDataEntry::InsertOrRetrieve(ID child_id)
+{
+	CargoDataEntry tmp(child_id);
+	CargoDataSet::iterator i = this->children->find(&tmp);
+	if (i == this->children->end()) {
+		IncrementSize();
+		return *(this->children->insert(new CargoDataEntry(child_id, 0, this)).first);
+	} else {
+		CargoDataEntry *ret = *i;
+		assert(this->children->value_comp().GetSortType() != ST_COUNT);
+		return ret;
+	}
+}
+
+/**
+ * Update the count for this entry and propagate the change to the parent entry
+ * if there is one.
+ * @param count the amount to be added to this entry
+ */
+void CargoDataEntry::Update(uint count)
+{
+	this->count += count;
+	if (this->parent != NULL) this->parent->Update(count);
+}
+
+/**
+ * Increment
+ */
+void CargoDataEntry::IncrementSize()
+{
+	 ++this->num_children;
+	 if (this->parent != NULL) this->parent->IncrementSize();
+}
+
+void CargoDataEntry::Resort(CargoSortType type, SortOrder order)
+{
+	CargoDataSet *new_subs = new CargoDataSet(this->children->begin(), this->children->end(), CargoSorter(type, order));
+	delete this->children;
+	this->children = new_subs;
+}
+
+CargoDataEntry *CargoDataEntry::Retrieve(CargoDataSet::iterator i) const
+{
+	if (i == this->children->end()) {
+		return NULL;
+	} else {
+		assert(this->children->value_comp().GetSortType() != ST_COUNT);
+		return *i;
+	}
+}
+
+bool CargoSorter::operator()(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const
+{
+	switch (this->type) {
+	case ST_STATION_ID:
+		return this->SortId<StationID>(cd1->GetStation(), cd2->GetStation());
+		break;
+	case ST_CARGO_ID:
+		return this->SortId<CargoID>(cd1->GetCargo(), cd2->GetCargo());
+		break;
+	case ST_COUNT:
+		return this->SortCount(cd1, cd2);
+		break;
+	case ST_STATION_STRING:
+		return this->SortStation(cd1->GetStation(), cd2->GetStation());
+		break;
+	default:
+		NOT_REACHED();
+	}
+}
+
+template<class ID>
+bool CargoSorter::SortId(ID st1, ID st2) const
+{
+	return (this->order == SO_ASCENDING) ? st1 < st2 : st2 < st1;
+}
+
+bool CargoSorter::SortCount(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const
+{
+	uint c1 = cd1->GetCount();
+	uint c2 = cd2->GetCount();
+	if (c1 == c2) {
+		return this->SortStation(cd1->GetStation(), cd2->GetStation());
+	} else if (this->order == SO_ASCENDING) {
+		return c1 < c2;
+	} else {
+		return c2 < c1;
+	}
+}
+
+bool CargoSorter::SortStation(StationID st1, StationID st2) const
+{
+	static char buf1[64];
+	static char buf2[64];
+
+	if (!Station::IsValidID(st1)) {
+		return Station::IsValidID(st2) ? this->order == SO_ASCENDING : this->SortId(st1, st2);
+	} else if (!Station::IsValidID(st2)) {
+		return order == SO_DESCENDING;
+	}
+
+	SetDParam(0, st1);
+	GetString(buf1, STR_STATION_NAME, lastof(buf1));
+	SetDParam(0, st2);
+	GetString(buf2, STR_STATION_NAME, lastof(buf2));
+
+	int res = strcmp(buf1, buf2);
+	if (res == 0) {
+		return this->SortId(st1, st2);
+	} else {
+		return (this->order == SO_ASCENDING) ? res < 0 : res > 0;
+	}
+}
 
 /**
  * The StationView window
  */
 struct StationViewWindow : public Window {
-	uint32 cargo;                 ///< Bitmask of cargo types to expand
-	uint16 cargo_rows[NUM_CARGO]; ///< Header row for each cargo type
+	struct RowDisplay {
+		RowDisplay(CargoDataEntry *f, StationID n) : filter(f), next_station(n) {}
+		RowDisplay(CargoDataEntry *f, CargoID n) : filter(f), next_cargo(n) {}
+		CargoDataEntry *filter;
+		union {
+			StationID next_station;
+			CargoID next_cargo;
+		};
+	};
+
+	typedef std::vector<RowDisplay> CargoDataVector;
+
+	static const int NUM_COLUMNS = 4;
+
+	enum Invalidation {
+		INV_FLOWS = 0x100,
+		INV_CARGO = 0x200
+	};
+
+	enum Grouping {
+		GR_SOURCE,
+		GR_NEXT,
+		GR_DESTINATION,
+		GR_CARGO,
+	};
+
+	enum Mode {
+		MODE_WAITING,
+		MODE_PLANNED
+	};
+	
 	uint expand_shrink_width;     ///< The width allocated to the expand/shrink 'button'
 	int rating_lines;             ///< Number of lines in the cargo ratings view.
 	int accepts_lines;            ///< Number of lines in the accepted cargo view.
@@ -892,7 +1120,23 @@
 		ALH_ACCEPTS = 3,  ///< Height of the accepted cargo view.
 	};
 
-	StationViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
+	static const StringID _sort_names[];
+	static const StringID _group_names[];
+
+	CargoSortType sortings[NUM_COLUMNS];
+	SortOrder sort_orders[NUM_COLUMNS];
+
+	int scroll_to_row;
+	int grouping_index;
+	Mode current_mode;
+	Grouping groupings[NUM_COLUMNS];
+
+	CargoDataEntry expanded_rows;
+	CargoDataEntry cached_destinations;
+	CargoDataVector displayed_rows;
+
+	StationViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(),
+		scroll_to_row(INT_MAX), grouping_index(0)
 	{
 		this->rating_lines  = ALH_RATING;
 		this->accepts_lines = ALH_ACCEPTS;
@@ -902,6 +1146,12 @@
 		/* Nested widget tree creation is done in two steps to ensure that this->GetWidget<NWidgetCore>(SVW_ACCEPTS) exists in UpdateWidgetSize(). */
 		this->FinishInitNested(desc, window_number);
 
+		this->groupings[0] = GR_CARGO;
+		this->sortings[0] = ST_AS_GROUPING;
+		this->SelectGroupBy(_settings_client.gui.station_gui_group_order);
+		this->SelectSortBy(_settings_client.gui.station_gui_sort_by);
+		this->sort_orders[0] = SO_ASCENDING;
+		this->SelectSortOrder((SortOrder)_settings_client.gui.station_gui_sort_order);
 		Owner owner = Station::Get(window_number)->owner;
 		if (owner != OWNER_NONE) this->owner = owner;
 	}
@@ -917,12 +1167,40 @@
 		DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, owner, this->window_number).Pack(), false);
 	}
 
+	void ShowCargo(CargoDataEntry *data, CargoID cargo, StationID source, StationID next, StationID dest, uint count)
+	{
+		if (count == 0) return;
+		const CargoDataEntry *expand = &this->expanded_rows;
+		for (int i = 0; i < NUM_COLUMNS && expand != NULL; ++i) {
+			switch (groupings[i]) {
+			case GR_CARGO:
+				assert(i == 0);
+				data = data->InsertOrRetrieve(cargo);
+				expand = expand->Retrieve(cargo);
+				break;
+			case GR_SOURCE:
+				data = data->InsertOrRetrieve(source);
+				expand = expand->Retrieve(source);
+				break;
+			case GR_NEXT:
+				data = data->InsertOrRetrieve(next);
+				expand = expand->Retrieve(next);
+				break;
+			case GR_DESTINATION:
+				data = data->InsertOrRetrieve(dest);
+				expand = expand->Retrieve(dest);
+				break;
+			}
+		}
+		data->Update(count);
+	}
+
 	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
 	{
 		switch (widget) {
 			case SVW_WAITING:
 				resize->height = FONT_HEIGHT_NORMAL;
-				size->height = WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM;
+				size->height = WD_FRAMERECT_TOP + 4 * resize->height + WD_FRAMERECT_BOTTOM;
 				this->expand_shrink_width = max(GetStringBoundingBox("-").width, GetStringBoundingBox("+").width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
 				break;
 
@@ -934,20 +1212,21 @@
 
 	virtual void OnPaint()
 	{
-		CargoDataList cargolist;
-		uint32 transfers = 0;
-		this->OrderWaitingCargo(&cargolist, &transfers);
+		const Station *st = Station::Get(this->window_number);
+		CargoDataEntry cargo;
+		BuildCargoList(&cargo, st);
 
-		this->vscroll->SetCount((int)cargolist.size() + 1); // update scrollbar
+		this->vscroll->SetCount(cargo.GetNumChildren()); // update scrollbar
 
 		/* disable some buttons */
-		const Station *st = Station::Get(this->window_number);
 		this->SetWidgetDisabledState(SVW_RENAME,   st->owner != _local_company);
 		this->SetWidgetDisabledState(SVW_TRAINS,   !(st->facilities & FACIL_TRAIN));
 		this->SetWidgetDisabledState(SVW_ROADVEHS, !(st->facilities & FACIL_TRUCK_STOP) && !(st->facilities & FACIL_BUS_STOP));
 		this->SetWidgetDisabledState(SVW_SHIPS,    !(st->facilities & FACIL_DOCK));
 		this->SetWidgetDisabledState(SVW_PLANES,   !(st->facilities & FACIL_AIRPORT));
 
+		SetDParam(0, st->index);
+		SetDParam(1, st->facilities);
 		this->DrawWidgets();
 
 		if (!this->IsShaded()) {
@@ -970,10 +1249,20 @@
 				}
 			}
 
+			/* draw arrow pointing up/down for ascending/descending sorting */
+			this->DrawSortButtonState(SVW_SORT_ORDER, sort_orders[1] == SO_ASCENDING ? SBS_UP : SBS_DOWN);
+
+			int pos = this->vscroll->GetPosition();
+
+			int maxrows = this->vscroll->GetCapacity();
+
+			displayed_rows.clear();
+
 			/* Draw waiting cargo. */
 			NWidgetBase *nwi = this->GetWidget<NWidgetBase>(SVW_WAITING);
 			Rect waiting_rect = {nwi->pos_x, nwi->pos_y, nwi->pos_x + nwi->current_x - 1, nwi->pos_y + nwi->current_y - 1};
-			this->DrawWaitingCargo(waiting_rect, cargolist, transfers);
+			this->DrawEntries(&cargo, waiting_rect, pos, maxrows, 0);
+			scroll_to_row = INT_MAX;
 		}
 	}
 
@@ -986,117 +1275,271 @@
 		}
 	}
 
-	/**
-	 * Order waiting cargo by type and destination.
-	 * @param cargolist [out] Ordered cargo.
-	 * @param transfers [out] Bitmask for cargoes being transfered.
-	 * @pre \c *cargolist must be empty.
-	 */
-	void OrderWaitingCargo(CargoDataList *cargolist, uint32 *transfers)
-	{
-		assert(cargolist->size() == 0);
-		*transfers = 0;
+	void RecalcDestinations(CargoID i)
+ 	{
+		const Station *st = Station::Get(this->window_number);
+		CargoDataEntry *cargo_entry = cached_destinations.InsertOrRetrieve(i);
+		cargo_entry->Clear();
 
-		StationID station_id = this->window_number;
-		const Station *st = Station::Get(station_id);
-
-		/* count types of cargos waiting in station */
-		for (CargoID i = 0; i < NUM_CARGO; i++) {
-			if (st->goods[i].cargo.Empty()) {
-				this->cargo_rows[i] = 0;
-			} else {
-				/* Add an entry for total amount of cargo of this type waiting. */
-				cargolist->push_back(CargoData(i, INVALID_STATION, st->goods[i].cargo.Count()));
-
-				/* Set the row for this cargo entry for the expand/hide button */
-				this->cargo_rows[i] = (uint16)cargolist->size();
-
-				/* Add an entry for each distinct cargo source. */
-				const StationCargoList::List *packets = st->goods[i].cargo.Packets();
-				for (StationCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
-					const CargoPacket *cp = *it;
-					if (cp->SourceStation() != station_id) {
-						bool added = false;
-
-						/* Enable the expand/hide button for this cargo type */
-						SetBit(*transfers, i);
-
-						/* Don't add cargo lines if not expanded */
-						if (!HasBit(this->cargo, i)) break;
-
-						/* Check if we already have this source in the list */
-						for (CargoDataList::iterator jt(cargolist->begin()); jt != cargolist->end(); jt++) {
-							CargoData *cd = &(*jt);
-							if (cd->cargo == i && cd->source == cp->SourceStation()) {
-								cd->count += cp->Count();
-								added = true;
-								break;
-							}
-						}
-
-						if (!added) cargolist->push_back(CargoData(i, cp->SourceStation(), cp->Count()));
-					}
+		const FlowStatMap &flows = st->goods[i].flows;
+		for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) {
+			StationID from = it->first;
+			CargoDataEntry *source_entry = cargo_entry->InsertOrRetrieve(from);
+			const FlowStatSet &flow_set = it->second;
+			for (FlowStatSet::const_iterator flow_it = flow_set.begin(); flow_it != flow_set.end(); ++flow_it) {
+				const FlowStat &stat = *flow_it;
+				StationID via = stat.Via();
+				CargoDataEntry *via_entry = source_entry->InsertOrRetrieve(via);
+				if (via == this->window_number) {
+					via_entry->InsertOrRetrieve(via)->Update(stat.Planned());
+				} else {
+					EstimateDestinations(i, from, via, stat.Planned(), via_entry);
 				}
 			}
 		}
 	}
 
-	/**
-	 * Draw waiting cargo.
-	 * @param r Rectangle of the widget.
-	 * @param cargolist Cargo, ordered by type and destination.
-	 * @param transfers Bitmask for cargoes that are transfered.
-	 */
-	void DrawWaitingCargo(const Rect &r, const CargoDataList &cargolist, uint32 transfers) const
+	void EstimateDestinations(CargoID cargo, StationID source, StationID next, uint count, CargoDataEntry *dest)
 	{
-		int y = r.top + WD_FRAMERECT_TOP;
-		int pos = this->vscroll->GetPosition();
+		if (Station::IsValidID(next) && Station::IsValidID(source)) {
+			CargoDataEntry tmp;
+			const FlowStatMap &flowmap = Station::Get(next)->goods[cargo].flows;
+			FlowStatMap::const_iterator map_it = flowmap.find(source);
+			if (map_it != flowmap.end()) {
+				const FlowStatSet &flows = map_it->second;
+				for (FlowStatSet::const_iterator i = flows.begin(); i != flows.end(); ++i) {
+					tmp.InsertOrRetrieve(i->Via())->Update(i->Planned());
+				}
+			}
 
-		const Station *st = Station::Get(this->window_number);
-		if (--pos < 0) {
-			StringID str = STR_JUST_NOTHING;
-			for (CargoID i = 0; i < NUM_CARGO; i++) {
-				if (!st->goods[i].cargo.Empty()) str = STR_EMPTY;
+			if (tmp.GetCount() == 0) {
+				dest->InsertOrRetrieve(INVALID_STATION)->Update(count);
+			} else {
+				uint sum_estimated = 0;
+				while(sum_estimated < count) {
+					for(CargoDataSet::iterator i = tmp.Begin(); i != tmp.End() && sum_estimated < count; ++i) {
+						CargoDataEntry *child = *i;
+						uint estimate = DivideApprox(child->GetCount() * count, tmp.GetCount());
+						if (estimate == 0) estimate = 1;
+
+						sum_estimated += estimate;
+						if (sum_estimated > count) {
+							estimate -= sum_estimated - count;
+							sum_estimated = count;
+						}
+
+						if (estimate > 0) {
+							if (child->GetStation() == next) {
+								dest->InsertOrRetrieve(next)->Update(estimate);
+							} else {
+								EstimateDestinations(cargo, source, child->GetStation(), estimate, dest);
+							}
+						}
+					}
+				}
 			}
-			SetDParam(0, str);
-			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_STATION_VIEW_WAITING_TITLE);
-			y += FONT_HEIGHT_NORMAL;
+		} else {
+			dest->InsertOrRetrieve(INVALID_STATION)->Update(count);
+		}
+	}
+
+	void BuildFlowList(CargoID i, const FlowStatMap &flows, CargoDataEntry *cargo)
+ 	{
+		const CargoDataEntry *source_dest = this->cached_destinations.Retrieve(i);
+		for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) {
+			StationID from = it->first;
+			const CargoDataEntry *source_entry = source_dest->Retrieve(from);
+			const FlowStatSet &flow_set = it->second;
+			for (FlowStatSet::const_iterator flow_it = flow_set.begin(); flow_it != flow_set.end(); ++flow_it) {
+				const FlowStat &stat = *flow_it;
+				const CargoDataEntry *via_entry = source_entry->Retrieve(stat.Via());
+				for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End(); ++dest_it) {
+					CargoDataEntry *dest_entry = *dest_it;
+					ShowCargo(cargo, i, from, stat.Via(), dest_entry->GetStation(), dest_entry->GetCount());
+				}
+			}
+		}
+	}
+
+	void BuildCargoList(CargoID i, const StationCargoList &packets, CargoDataEntry *cargo)
+	{
+		const CargoDataEntry *source_dest = this->cached_destinations.Retrieve(i);
+		for (StationCargoList::ConstIterator it = packets.Packets()->begin(); it != packets.Packets()->end(); it++) {
+			const CargoPacket *cp = *it;
+			StationID next = it.GetKey();
+
+			const CargoDataEntry *source_entry = source_dest->Retrieve(cp->SourceStation());
+			if (source_entry == NULL) {
+				ShowCargo(cargo, i, cp->SourceStation(), next, INVALID_STATION, cp->Count());
+				continue;
+			}
+
+			const CargoDataEntry *via_entry = source_entry->Retrieve(next);
+			if (via_entry == NULL) {
+				ShowCargo(cargo, i, cp->SourceStation(), next, INVALID_STATION, cp->Count());
+				continue;
+			}
+
+			for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End(); ++dest_it) {
+				CargoDataEntry *dest_entry = *dest_it;
+				uint val = DivideApprox(cp->Count() * dest_entry->GetCount(), via_entry->GetCount());
+				ShowCargo(cargo, i, cp->SourceStation(), next, dest_entry->GetStation(), val);
+			}
+		}
+	}
+
+	void BuildCargoList(CargoDataEntry *cargo, const Station *st)
+	{
+		for (CargoID i = 0; i < NUM_CARGO; i++) {
+			if (this->cached_destinations.Retrieve(i) == NULL) {
+				this->RecalcDestinations(i);
+			}
+
+			if (this->current_mode == MODE_WAITING) {
+				BuildCargoList(i, st->goods[i].cargo, cargo);
+			} else {
+				BuildFlowList(i, st->goods[i].flows, cargo);
+			}
+		}
+	}
+
+	void SetDisplayedRow(const CargoDataEntry *data)
+	{
+		std::list<StationID> stations;
+		const CargoDataEntry *parent = data->GetParent();
+		if (parent->GetParent() == NULL) {
+			this->displayed_rows.push_back(RowDisplay(&this->expanded_rows, data->GetCargo()));
+			return;
 		}
 
-		bool rtl = _current_text_dir == TD_RTL;
-		int text_left    = rtl ? r.left + this->expand_shrink_width : r.left + WD_FRAMERECT_LEFT;
-		int text_right   = rtl ? r.right - WD_FRAMERECT_LEFT : r.right - this->expand_shrink_width;
-		int shrink_left  = rtl ? r.left + WD_FRAMERECT_LEFT : r.right - this->expand_shrink_width + WD_FRAMERECT_LEFT;
-		int shrink_right = rtl ? r.left + this->expand_shrink_width - WD_FRAMERECT_RIGHT : r.right - WD_FRAMERECT_RIGHT;
+		StationID next = data->GetStation();
+		while(parent->GetParent()->GetParent() != NULL) {
+			stations.push_back(parent->GetStation());
+			parent = parent->GetParent();
+		}
 
+		CargoID cargo = parent->GetCargo();
+		CargoDataEntry *filter = this->expanded_rows.Retrieve(cargo);
+		while(!stations.empty()) {
+			filter = filter->Retrieve(stations.back());
+			stations.pop_back();
+		}
 
-		int maxrows = this->vscroll->GetCapacity();
-		for (CargoDataList::const_iterator it = cargolist.begin(); it != cargolist.end() && pos > -maxrows; ++it) {
-			if (--pos < 0) {
-				const CargoData *cd = &(*it);
-				if (cd->source == INVALID_STATION) {
-					/* Heading */
-					DrawCargoIcons(cd->cargo, cd->count, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y);
-					SetDParam(0, cd->cargo);
-					SetDParam(1, cd->count);
-					if (HasBit(transfers, cd->cargo)) {
-						/* This cargo has transfers waiting so show the expand or shrink 'button' */
-						const char *sym = HasBit(this->cargo, cd->cargo) ? "-" : "+";
-						DrawString(text_left, text_right, y, STR_STATION_VIEW_WAITING_CARGO, TC_FROMSTRING, SA_RIGHT);
-						DrawString(shrink_left, shrink_right, y, sym, TC_YELLOW, SA_RIGHT);
-					} else {
-						DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_STATION_VIEW_WAITING_CARGO, TC_FROMSTRING, SA_RIGHT);
-					}
+		this->displayed_rows.push_back(RowDisplay(filter, next));
+	}
+
+	StringID GetEntryString(StationID station, StringID here, StringID other_station, StringID any)
+	{
+		if (station == this->window_number) {
+			return here;
+		} else if (station != INVALID_STATION) {
+			SetDParam(2, station);
+			return other_station;
+		} else {
+			return any;
+		}
+	}
+
+	StringID SearchNonStop(CargoDataEntry *cd, StationID station, int column)
+	{
+		CargoDataEntry *parent = cd->GetParent();
+		for (int i = column - 1; i > 0; --i) {
+			if (this->groupings[i] == GR_DESTINATION) {
+				if (parent->GetStation() == station) {
+					return STR_STATION_VIEW_NONSTOP;
 				} else {
-					SetDParam(0, cd->cargo);
-					SetDParam(1, cd->count);
-					SetDParam(2, cd->source);
-					DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_STATION_VIEW_EN_ROUTE_FROM, TC_FROMSTRING, SA_RIGHT);
+					return STR_STATION_VIEW_VIA;
 				}
+			}
+			parent = parent->GetParent();
+		}
 
-				y += FONT_HEIGHT_NORMAL;
+		if (this->groupings[column + 1] == GR_DESTINATION) {
+			CargoDataSet::iterator begin = cd->Begin();
+			CargoDataSet::iterator end = cd->End();
+			if (begin != end && ++(cd->Begin()) == end && (*(begin))->GetStation() == station) {
+				return STR_STATION_VIEW_NONSTOP;
+			} else {
+				return STR_STATION_VIEW_VIA;
 			}
 		}
+
+		return STR_STATION_VIEW_VIA;
+	}
+
+	int DrawEntries(CargoDataEntry *entry, Rect &r, int pos, int maxrows, int column, CargoID cargo = CT_INVALID)
+	{
+		if (this->sortings[column] == ST_AS_GROUPING) {
+			if (this->groupings[column] != GR_CARGO) {
+				entry->Resort(ST_STATION_STRING, this->sort_orders[column]);
+			}
+		} else {
+			entry->Resort(ST_COUNT, this->sort_orders[column]);
+		}
+		for (CargoDataSet::iterator i = entry->Begin(); i != entry->End(); ++i) {
+			CargoDataEntry *cd = *i;
+
+			if (this->groupings[column] == GR_CARGO) cargo = cd->GetCargo();
+
+			if (pos > -maxrows && pos <= 0) {
+				StringID str = STR_EMPTY;
+				int y = r.top + WD_FRAMERECT_TOP - pos * FONT_HEIGHT_NORMAL;
+				SetDParam(0, cargo);
+				SetDParam(1, cd->GetCount());
+
+				if (this->groupings[column] == GR_CARGO) {
+					str = STR_STATION_VIEW_WAITING_CARGO;
+					DrawCargoIcons(cd->GetCargo(), cd->GetCount(), r.left + WD_FRAMERECT_LEFT + this->expand_shrink_width, r.right - WD_FRAMERECT_RIGHT - this->expand_shrink_width, y);
+				} else {
+					StationID station = cd->GetStation();
+
+					switch(this->groupings[column]) {
+					case GR_SOURCE:
+						str = this->GetEntryString(station, STR_STATION_VIEW_FROM_HERE, STR_STATION_VIEW_FROM, STR_STATION_VIEW_FROM_ANY);
+						break;
+					case GR_NEXT:
+						str = this->GetEntryString(station, STR_STATION_VIEW_VIA_HERE, STR_STATION_VIEW_VIA, STR_STATION_VIEW_VIA_ANY);
+						if (str == STR_STATION_VIEW_VIA) str = SearchNonStop(cd, station, column);
+						break;
+					case GR_DESTINATION:
+						str = this->GetEntryString(station, STR_STATION_VIEW_TO_HERE, STR_STATION_VIEW_TO, STR_STATION_VIEW_TO_ANY);
+						break;
+					default:
+						NOT_REACHED();
+					}
+					if (pos == -this->scroll_to_row && Station::IsValidID(station)) {
+						ScrollMainWindowToTile(Station::Get(station)->xy);
+					}
+				}
+				
+				bool rtl = _current_text_dir == TD_RTL;
+				int text_left    = rtl ? r.left + this->expand_shrink_width : r.left + WD_FRAMERECT_LEFT + column * this->expand_shrink_width;
+				int text_right   = rtl ? r.right - WD_FRAMERECT_LEFT - column * this->expand_shrink_width : r.right - this->expand_shrink_width;
+				int shrink_left  = rtl ? r.left + WD_FRAMERECT_LEFT : r.right - this->expand_shrink_width + WD_FRAMERECT_LEFT;
+				int shrink_right = rtl ? r.left + this->expand_shrink_width - WD_FRAMERECT_RIGHT : r.right - WD_FRAMERECT_RIGHT;
+
+				DrawString(text_left, text_right, y, str);
+
+				if (column < NUM_COLUMNS - 1) {
+					const char *sym = cd->GetNumChildren() > 0 ? "-" : "+";
+					DrawString(shrink_left, shrink_right, y, sym, TC_YELLOW);
+				}
+				SetDisplayedRow(cd);
+			}
+			pos = DrawEntries(cd, r, --pos, maxrows, column + 1, cargo);
+		}
+		return pos;
+	}
+
+ 	/**
+ 	 * Invalidate the cache for the given cargo.
+ 	 * @param cargo ID of the cargo.
+	 * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
+ 	 */
+	virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
+	{
+		if (!gui_scope) return;
+		this->cached_destinations.Remove((CargoID)data);
 	}
 
 	/**
@@ -1136,32 +1579,46 @@
 			if (!HasBit(ge->acceptance_pickup, GoodsEntry::GES_PICKUP)) continue;
 
 			SetDParam(0, cs->name);
-			SetDParam(2, ToPercent8(ge->rating));
-			SetDParam(1, STR_CARGO_RATING_APPALLING + (ge->rating >> 5));
-			DrawString(r.left + WD_FRAMERECT_LEFT + 6, r.right - WD_FRAMERECT_RIGHT - 6, y, STR_STATION_VIEW_CARGO_RATING);
+			SetDParam(1, ge->supply);
+			SetDParam(3, ToPercent8(ge->rating));
+			SetDParam(2, STR_CARGO_RATING_APPALLING + (ge->rating >> 5));
+			DrawString(r.left + WD_FRAMERECT_LEFT + 6, r.right - WD_FRAMERECT_RIGHT - 6, y, STR_STATION_VIEW_CARGO_SUPPLY_RATING);
 			y += FONT_HEIGHT_NORMAL;
 		}
 		return CeilDiv(y - r.top - WD_FRAMERECT_TOP, FONT_HEIGHT_NORMAL);
 	}
 
+	template<class ID>
+	void HandleCargoWaitingClick(CargoDataEntry *filter, ID next)
+ 	{
+		if (filter->Retrieve(next) != NULL) {
+			filter->Remove(next);
+		} else {
+			filter->InsertOrRetrieve(next);
+		}
+	}
+
 	void HandleCargoWaitingClick(int row)
 	{
-		if (row == 0) return;
-
-		for (CargoID c = 0; c < NUM_CARGO; c++) {
-			if (this->cargo_rows[c] == row) {
-				ToggleBit(this->cargo, c);
-				this->SetWidgetDirty(SVW_WAITING);
-				break;
+		if (row < 0 || (uint)row >= this->displayed_rows.size()) return;
+		if (_ctrl_pressed) {
+			this->scroll_to_row = row;
+		} else {
+			RowDisplay &display = this->displayed_rows[row];
+			if (display.filter == &this->expanded_rows) {
+				HandleCargoWaitingClick<CargoID>(display.filter, display.next_cargo);
+			} else {
+				HandleCargoWaitingClick<StationID>(display.filter, display.next_station);
 			}
 		}
+		this->SetWidgetDirty(SVW_WAITING);
 	}
 
 	virtual void OnClick(Point pt, int widget, int click_count)
 	{
 		switch (widget) {
 			case SVW_WAITING:
-				this->HandleCargoWaitingClick(this->vscroll->GetScrolledRowFromWidget(pt.y, this, SVW_WAITING, WD_FRAMERECT_TOP, FONT_HEIGHT_NORMAL));
+				this->HandleCargoWaitingClick(this->vscroll->GetScrolledRowFromWidget(pt.y, this, SVW_WAITING, WD_FRAMERECT_TOP, FONT_HEIGHT_NORMAL) - this->vscroll->GetPosition());
 				break;
 
 			case SVW_LOCATION:
@@ -1199,6 +1656,111 @@
 			case SVW_PLANES:   // Show list of scheduled aircraft to this station
 				ShowVehicleListWindow(this->owner, (VehicleType)(widget - SVW_TRAINS), (StationID)this->window_number);
 				break;
+
+			case SVW_DEPARTURES:
+				ShowStationDepartures((StationID)this->window_number);
+				break;
+
+			case SVW_SORT_BY: {
+				ShowDropDownMenu(this, _sort_names, this->current_mode, SVW_SORT_BY, 0, 0);
+				break;
+			}
+
+			case SVW_GROUP_BY: {
+				ShowDropDownMenu(this, _group_names, this->grouping_index, SVW_GROUP_BY, 0, 0);
+				break;
+			}
+
+			case SVW_SORT_ORDER: { // flip sorting method asc/desc
+				this->SelectSortOrder(this->sort_orders[1] == SO_ASCENDING ? SO_DESCENDING : SO_ASCENDING);
+				this->flags4 |= WF_TIMEOUT_BEGIN;
+				this->LowerWidget(SVW_SORT_ORDER);
+				break;
+			}
+		}
+	}
+
+	void SelectSortOrder(SortOrder order)
+	{
+		this->sort_orders[1] = this->sort_orders[2] = this->sort_orders[3] = order;
+		_settings_client.gui.station_gui_sort_order = this->sort_orders[1];
+		this->SetDirty();
+	}
+
+	void SelectSortBy(int index)
+	{
+		_settings_client.gui.station_gui_sort_by = index;
+		switch(_sort_names[index]) {
+		case STR_STATION_VIEW_WAITING_STATION:
+			this->current_mode = MODE_WAITING;
+			this->sortings[1] = this->sortings[2] = this->sortings[3] = ST_AS_GROUPING;
+			break;
+		case STR_STATION_VIEW_WAITING_AMOUNT:
+			this->current_mode = MODE_WAITING;
+			this->sortings[1] = this->sortings[2] = this->sortings[3] = ST_COUNT;
+			break;
+		case STR_STATION_VIEW_PLANNED_STATION:
+			this->current_mode = MODE_PLANNED;
+			this->sortings[1] = this->sortings[2] = this->sortings[3] = ST_AS_GROUPING;
+			break;
+		case STR_STATION_VIEW_PLANNED_AMOUNT:
+			this->current_mode = MODE_PLANNED;
+			this->sortings[1] = this->sortings[2] = this->sortings[3] = ST_COUNT;
+			break;
+		default:
+			NOT_REACHED();
+		}
+		/* Display the current sort variant */
+		this->GetWidget<NWidgetCore>(SVW_SORT_BY)->widget_data = _sort_names[index];
+		this->SetDirty();
+	}
+
+	void SelectGroupBy(int index)
+	{
+		this->grouping_index = index;
+		_settings_client.gui.station_gui_group_order = index;
+		this->GetWidget<NWidgetCore>(SVW_GROUP_BY)->widget_data = _group_names[index];
+		switch(_group_names[index]) {
+		case STR_STATION_VIEW_GROUP_S_V_D:
+			this->groupings[1] = GR_SOURCE;
+			this->groupings[2] = GR_NEXT;
+			this->groupings[3] = GR_DESTINATION;
+			break;
+		case STR_STATION_VIEW_GROUP_S_D_V:
+			this->groupings[1] = GR_SOURCE;
+			this->groupings[2] = GR_DESTINATION;
+			this->groupings[3] = GR_NEXT;
+			break;
+		case STR_STATION_VIEW_GROUP_V_S_D:
+			this->groupings[1] = GR_NEXT;
+			this->groupings[2] = GR_SOURCE;
+			this->groupings[3] = GR_DESTINATION;
+			break;
+		case STR_STATION_VIEW_GROUP_V_D_S:
+			this->groupings[1] = GR_NEXT;
+			this->groupings[2] = GR_DESTINATION;
+			this->groupings[3] = GR_SOURCE;
+			break;
+		case STR_STATION_VIEW_GROUP_D_S_V:
+			this->groupings[1] = GR_DESTINATION;
+			this->groupings[2] = GR_SOURCE;
+			this->groupings[3] = GR_NEXT;
+			break;
+		case STR_STATION_VIEW_GROUP_D_V_S:
+			this->groupings[1] = GR_DESTINATION;
+			this->groupings[2] = GR_NEXT;
+			this->groupings[3] = GR_SOURCE;
+			break;
+		}
+		this->SetDirty();
+	}
+
+	virtual void OnDropdownSelect(int widget, int index)
+	{
+		if (widget == SVW_SORT_BY) {
+			this->SelectSortBy(index);
+		} else {
+			this->SelectGroupBy(index);
 		}
 	}
 
@@ -1215,9 +1777,26 @@
 	}
 };
 
+const StringID StationViewWindow::_sort_names[] = {
+	STR_STATION_VIEW_WAITING_STATION,
+	STR_STATION_VIEW_WAITING_AMOUNT,
+	STR_STATION_VIEW_PLANNED_STATION,
+	STR_STATION_VIEW_PLANNED_AMOUNT,
+	INVALID_STRING_ID
+};
+
+const StringID StationViewWindow::_group_names[] = {
+	STR_STATION_VIEW_GROUP_S_V_D,
+	STR_STATION_VIEW_GROUP_S_D_V,
+	STR_STATION_VIEW_GROUP_V_S_D,
+	STR_STATION_VIEW_GROUP_V_D_S,
+	STR_STATION_VIEW_GROUP_D_S_V,
+	STR_STATION_VIEW_GROUP_D_V_S,
+	INVALID_STRING_ID
+};
 
 static const WindowDesc _station_view_desc(
-	WDP_AUTO, 249, 110,
+	WDP_AUTO, 249, 117,
 	WC_STATION_VIEW, WC_NONE,
 	WDF_UNCLICK_BUTTONS,
 	_nested_station_view_widgets, lengthof(_nested_station_view_widgets)
diff --git a/src/station_gui.h b/src/station_gui.h
--- a/src/station_gui.h
+++ b/src/station_gui.h
@@ -13,24 +13,32 @@
 #define STATION_GUI_H
 
 #include "command_type.h"
+#include "station_type.h"
 #include "tilearea_type.h"
 #include "window_type.h"
+#include "cargo_type.h"
+#include <set>
 
 /** Enum for StationView, referring to _station_view_widgets and _station_view_expanded_widgets */
 enum StationViewWidgets {
 	SVW_CAPTION    =  0, ///< Caption of the window
-	SVW_WAITING    =  1, ///< List of waiting cargo
-	SVW_SCROLLBAR  =  2, ///< Scrollbar
-	SVW_ACCEPTLIST =  3, ///< List of accepted cargos
-	SVW_RATINGLIST =  3, ///< Ratings of cargos
-	SVW_LOCATION   =  4, ///< 'Location' button
-	SVW_RATINGS    =  5, ///< 'Ratings' button
-	SVW_ACCEPTS    =  5, ///< 'Accepts' button
-	SVW_RENAME     =  6, ///< 'Rename' button
-	SVW_TRAINS     =  7, ///< List of scheduled trains button
+	SVW_SORT_ORDER =  1, ///< 'Sort order' button
+	SVW_SORT_BY    =  2, ///< 'Sort by' button
+	SVW_GROUP      =  3, ///< label for "group by"
+	SVW_GROUP_BY   =  4, ///< 'Group by' button
+	SVW_WAITING    =  5, ///< List of waiting cargo
+	SVW_SCROLLBAR  =  6, ///< Scrollbar
+	SVW_ACCEPTLIST =  7, ///< List of accepted cargos
+	SVW_RATINGLIST =  7, ///< Ratings of cargos
+	SVW_LOCATION   =  8, ///< 'Location' button
+	SVW_RATINGS    =  9, ///< 'Ratings' button
+	SVW_ACCEPTS    =  9, ///< 'Accepts' button
+	SVW_RENAME     = 10, ///< 'Rename' button
+	SVW_TRAINS     = 11, ///< List of scheduled trains button
 	SVW_ROADVEHS,        ///< List of scheduled road vehs button
 	SVW_SHIPS,           ///< List of scheduled ships button
 	SVW_PLANES,          ///< List of scheduled planes button
+	SVW_DEPARTURES,      ///< 'Departures' button
 };
 
 /** Types of cargo to display for station coverage. */
@@ -46,4 +54,152 @@
 void ShowSelectStationIfNeeded(CommandContainer cmd, TileArea ta);
 void ShowSelectWaypointIfNeeded(CommandContainer cmd, TileArea ta);
 
+enum SortOrder {
+	SO_DESCENDING,
+	SO_ASCENDING
+};
+
+class CargoDataEntry;
+
+enum CargoSortType {
+	ST_AS_GROUPING,    ///< by the same principle the entries are being grouped
+	ST_COUNT,          ///< by amount of cargo
+	ST_STATION_STRING, ///< by station name
+	ST_STATION_ID,     ///< by station id
+	ST_CARGO_ID,       ///< by cargo id
+};
+
+class CargoSorter {
+public:
+	CargoSorter(CargoSortType t = ST_STATION_ID, SortOrder o = SO_ASCENDING) : type(t), order(o) {}
+	CargoSortType GetSortType() {return this->type;}
+	bool operator()(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const;
+
+private:
+	CargoSortType type;
+	SortOrder order;
+
+	template<class ID>
+	bool SortId(ID st1, ID st2) const;
+	bool SortCount(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const;
+	bool SortStation (StationID st1, StationID st2) const;
+};
+
+typedef std::set<CargoDataEntry *, CargoSorter> CargoDataSet;
+
+/**
+ * A cargo data entry representing one possible row in the station view window's
+ * top part. Cargo data entries form a tree where each entry can have several
+ * children. Parents keep track of the sums of their childrens' cargo counts.
+ */
+class CargoDataEntry {
+public:
+	CargoDataEntry();
+	~CargoDataEntry();
+
+	/**
+	 * Insert a new child or retrieve an existing child using a station ID as ID.
+	 * @param station ID of the station for which an entry shall be created or retrieved
+	 * @return a child entry associated with the given station.
+	 */
+	CargoDataEntry *InsertOrRetrieve(StationID station) {return this->InsertOrRetrieve<StationID>(station);}
+
+	/**
+	 * Insert a new child or retrieve an existing child using a cargo ID as ID.
+	 * @param cargo ID of the cargo for which an entry shall be created or retrieved
+	 * @return a child entry associated with the given cargo.
+	 */
+	CargoDataEntry *InsertOrRetrieve(CargoID cargo) {return this->InsertOrRetrieve<CargoID>(cargo);}
+
+	void Update(uint count);
+
+	/**
+	 * Remove a child associated with the given station.
+	 * @param station ID of the station for which the child should be removed.
+	 */
+	void Remove(StationID station) {CargoDataEntry t(station); this->Remove(&t);}
+
+	/**
+	 * Remove a child associated with the given cargo.
+	 * @param cargo ID of the cargo for which the child should be removed.
+	 */
+	void Remove(CargoID cargo) {CargoDataEntry t(cargo); this->Remove(&t);}
+
+	/**
+	 * Retrieve a child for the given station. Return NULL if it doesn't exist.
+	 * @param station ID of the station the child we're looking for is associated with.
+	 * @return a child entry for the given station or NULL.
+	 */
+	CargoDataEntry *Retrieve(StationID station) const {CargoDataEntry t(station); return this->Retrieve(this->children->find(&t));}
+
+	/**
+	 * Retrieve a child for the given cargo. Return NULL if it doesn't exist.
+	 * @param cargo ID of the cargo the child we're looking for is associated with.
+	 * @return a child entry for the given cargo or NULL.
+	 */
+	CargoDataEntry *Retrieve(CargoID cargo) const {CargoDataEntry t(cargo);return this->Retrieve(this->children->find(&t));}
+
+	void Resort(CargoSortType type, SortOrder order);
+
+	/**
+	 * Get the station ID for this entry.
+	 */
+	StationID GetStation() const {return this->station;}
+
+	/**
+	 * Get the cargo ID for this entry.
+	 */
+	CargoID GetCargo() const {return this->cargo;}
+
+	/**
+	 * Get the cargo count for this entry.
+	 */
+	uint GetCount() const {return this->count;}
+
+	/**
+	 * Get the parent entry for this entry.
+	 */
+	CargoDataEntry *GetParent() const {return this->parent;}
+
+	/**
+	 * Get the number of children for this entry.
+	 */
+	uint GetNumChildren() const {return this->num_children;}
+
+	/**
+	 * Get an iterator pointing to the begin of the set of children.
+	 */
+	CargoDataSet::iterator Begin() const {return this->children->begin();}
+
+	/**
+	 * Get an iterator pointing to the end of the set of children.
+	 */
+	CargoDataSet::iterator End() const {return this->children->end();}
+
+	void Clear();
+private:
+
+	CargoDataEntry(StationID st, uint c, CargoDataEntry *p);
+	CargoDataEntry(CargoID car, uint c, CargoDataEntry *p);
+	CargoDataEntry(StationID st);
+	CargoDataEntry(CargoID car);
+
+	CargoDataEntry *Retrieve(CargoDataSet::iterator i) const;
+
+	template<class ID>
+	CargoDataEntry *InsertOrRetrieve(ID s);
+
+	void Remove(CargoDataEntry *comp);
+	void IncrementSize();
+
+	CargoDataEntry *parent;   ///< the parent of this entry
+	const union {
+		StationID station;    ///< ID of the station this entry is associated with
+		CargoID cargo;        ///< ID of the cargo this entry is associated with
+	};
+	uint num_children;        ///< the number of subentries belonging to this entry
+	uint count;               ///< sum of counts of all children or amount of cargo for this entry
+	CargoDataSet *children;   ///< the children of this entry
+};
+
 #endif /* STATION_GUI_H */
diff --git a/src/station_type.h b/src/station_type.h
--- a/src/station_type.h
+++ b/src/station_type.h
@@ -15,6 +15,8 @@
 #include "core/smallvec_type.hpp"
 #include "tilearea_type.h"
 
+#include <list>
+
 typedef uint16 StationID;
 typedef uint16 RoadStopID;
 
@@ -87,6 +89,9 @@
 
 static const uint MAX_LENGTH_STATION_NAME_CHARS = 32; ///< The maximum length of a station name in characters including '\0'
 
+/** List of station IDs */
+typedef std::list<StationID> StationIDList;
+
 /** List of stations */
 typedef SmallVector<Station *, 2> StationList;
 
diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp
--- a/src/statusbar_gui.cpp
+++ b/src/statusbar_gui.cpp
@@ -134,9 +134,9 @@
 	{
 		switch (widget) {
 			case SBW_LEFT:
-				/* Draw the date */
-				SetDParam(0, _date);
-				DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
+				/* Draw the date */ //TODO: prevent overflowing the displayed date with high daylength factors.
+				SetDParam(0, ((DateTicks)_date * DAY_TICKS) + _date_fract);
+				DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_WHITE_DATE_WALLCLOCK_LONG, TC_FROMSTRING, SA_HOR_CENTER);
 				break;
 
 			case SBW_RIGHT: {
@@ -217,6 +217,10 @@
 	{
 		if (_pause_mode != PM_UNPAUSED) return;
 
+		if (_settings_client.gui.time_in_minutes) {
+			this->SetWidgetDirty(SBW_LEFT);
+		}
+
 		if (this->ticker_scroll < TICKER_STOP) { // Scrolling text
 			this->ticker_scroll += COUNTER_STEP;
 			this->SetWidgetDirty(SBW_MIDDLE);
@@ -233,7 +237,7 @@
 
 static const NWidgetPart _nested_main_status_widgets[] = {
 	NWidget(NWID_HORIZONTAL),
-		NWidget(WWT_PANEL, COLOUR_GREY, SBW_LEFT), SetMinimalSize(140, 12), EndContainer(),
+		NWidget(WWT_PANEL, COLOUR_GREY, SBW_LEFT), SetMinimalSize(160, 12), EndContainer(),
 		NWidget(WWT_PUSHBTN, COLOUR_GREY, SBW_MIDDLE), SetMinimalSize(40, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
 		NWidget(WWT_PUSHBTN, COLOUR_GREY, SBW_RIGHT), SetMinimalSize(140, 12),
 	EndContainer(),
diff --git a/src/stdafx.h b/src/stdafx.h
--- a/src/stdafx.h
+++ b/src/stdafx.h
@@ -244,7 +244,7 @@
 
 /* NOTE: the string returned by these functions is only valid until the next
  * call to the same function and is not thread- or reentrancy-safe */
-#if !defined(STRGEN) && !defined(SETTINGSGEN)
+#if !defined(STRGEN)
 	#if defined(WIN32) || defined(WIN64)
 		char *getcwd(char *buf, size_t size);
 		#include <tchar.h>
@@ -268,7 +268,7 @@
 		#define SQ2OTTD(name) (name)
 		#define OTTD2SQ(name) (name)
 	#endif /* WIN32 */
-#endif /* STRGEN || SETTINGSGEN */
+#endif /* STRGEN */
 
 #if defined(WIN32) || defined(WIN64) || defined(__OS2__) && !defined(__INNOTEK_LIBC__)
 	#define PATHSEP "\\"
diff --git a/src/string.cpp b/src/string.cpp
--- a/src/string.cpp
+++ b/src/string.cpp
@@ -151,11 +151,11 @@
 	*dst = '\0';
 
 	if (dst == last && *src != '\0') {
-#if defined(STRGEN) || defined(SETTINGSGEN)
+#if defined(STRGEN)
 		error("String too long for destination buffer");
-#else /* STRGEN || SETTINGSGEN */
+#else /* STRGEN */
 		DEBUG(misc, 0, "String too long for destination buffer");
-#endif /* STRGEN || SETTINGSGEN */
+#endif /* STRGEN */
 	}
 	return dst;
 }
diff --git a/src/strings.cpp b/src/strings.cpp
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -912,11 +912,27 @@
 				break;
 			}
 
+			case SCC_DATE_WALLCLOCK_TINY: // {DATE_WALLCLOCK_TINY}
+				if (_settings_client.gui.time_in_minutes) {
+					buff = FormatWallClockString(buff, args->GetInt64(SCC_DATE_WALLCLOCK_TINY), last, false);
+				} else {
+					buff = FormatTinyOrISODate(buff, args->GetInt64(SCC_DATE_WALLCLOCK_TINY) / DAY_TICKS, STR_FORMAT_DATE_TINY, last);
+				}
+				break;
+
 			case SCC_DATE_TINY: { // {DATE_TINY}
 				buff = FormatTinyOrISODate(buff, args->GetInt32(SCC_DATE_TINY), STR_FORMAT_DATE_TINY, last);
 				break;
 			}
 
+			case SCC_DATE_WALLCLOCK_ISO: // {DATE_WALLCLOCK_ISO}
+				if (_settings_client.gui.time_in_minutes) {
+					buff = FormatWallClockString(buff, args->GetInt64(SCC_DATE_WALLCLOCK_ISO), last, false);
+				} else {
+					buff = FormatTinyOrISODate(buff, args->GetInt64(SCC_DATE_WALLCLOCK_ISO) / DAY_TICKS, STR_FORMAT_DATE_ISO, last);
+				}
+				break;
+
 			case SCC_DATE_ISO: { // {DATE_ISO}
 				buff = FormatTinyOrISODate(buff, args->GetInt32(), STR_FORMAT_DATE_ISO, last);
 				break;
diff --git a/src/strings_func.h b/src/strings_func.h
--- a/src/strings_func.h
+++ b/src/strings_func.h
@@ -78,7 +78,7 @@
 	 */
 	int64 GetInt64(WChar type = 0)
 	{
-		assert(this->offset < this->num_param);
+		assert(this->offset < this->num_param); // TODO: outcommenting or fix Improved Breakdowns in info tab.
 		if (this->type != NULL) {
 			assert(this->type[this->offset] == 0 || this->type[this->offset] == type);
 			this->type[this->offset] = type;
diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini
--- a/src/table/company_settings.ini
+++ b/src/table/company_settings.ini
@@ -6,113 +6,4 @@
 ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 ;
 
-[pre-amble]
-static bool CheckInterval(int32 p1);
-static bool InvalidateDetailsWindow(int32 p1);
-
-static const SettingDesc _company_settings[] = {
-[post-amble]
-};
-[templates]
-SDT_BOOL = SDT_BOOL($base, $var,        $flags, $guiflags, $def,                        $str, $strval, $proc, $from, $to),
-SDT_VAR  =  SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strval, $proc, $from, $to),
-SDT_END  = SDT_END()
-
-[defaults]
-flags    = 0
-guiflags = SGF_PER_COMPANY
-interval = 0
-str      = STR_NULL
-strval   = STR_NULL
-proc     = NULL
-load     = NULL
-from     = 0
-to       = SL_MAX_VERSION
-
-
-
-[SDT_BOOL]
-base     = CompanySettings
-var      = engine_renew
-def      = false
-str      = STR_CONFIG_SETTING_AUTORENEW_VEHICLE
-
-[SDT_VAR]
-base     = CompanySettings
-var      = engine_renew_months
-type     = SLE_INT16
-def      = 6
-min      = -12
-max      = 12
-str      = STR_CONFIG_SETTING_AUTORENEW_MONTHS
-
-[SDT_VAR]
-base     = CompanySettings
-var      = engine_renew_money
-type     = SLE_UINT
-guiflags = SGF_PER_COMPANY | SGF_CURRENCY
-def      = 100000
-min      = 0
-max      = 2000000
-str      = STR_CONFIG_SETTING_AUTORENEW_MONEY
-
-[SDT_BOOL]
-base     = CompanySettings
-var      = renew_keep_length
-def      = false
-
-[SDT_BOOL]
-base     = CompanySettings
-var      = vehicle.servint_ispercent
-def      = false
-str      = STR_CONFIG_SETTING_SERVINT_ISPERCENT
-proc     = CheckInterval
-
-[SDT_VAR]
-base     = CompanySettings
-var      = vehicle.servint_trains
-type     = SLE_UINT16
-guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
-def      = 150
-min      = 5
-max      = 800
-str      = STR_CONFIG_SETTING_SERVINT_TRAINS
-proc     = InvalidateDetailsWindow
-
-[SDT_VAR]
-base     = CompanySettings
-var      = vehicle.servint_roadveh
-type     = SLE_UINT16
-guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
-def      = 150
-min      = 5
-max      = 800
-str      = STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES
-proc     = InvalidateDetailsWindow
-
-[SDT_VAR]
-base     = CompanySettings
-var      = vehicle.servint_ships
-type     = SLE_UINT16
-guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
-def      = 360
-min      = 5
-max      = 800
-str      = STR_CONFIG_SETTING_SERVINT_SHIPS
-proc     = InvalidateDetailsWindow
-
-[SDT_VAR]
-base     = CompanySettings
-var      = vehicle.servint_aircraft
-type     = SLE_UINT16
-guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
-def      = 100
-min      = 5
-max      = 800
-str      = STR_CONFIG_SETTING_SERVINT_AIRCRAFT
-proc     = InvalidateDetailsWindow
-
-[SDT_END]
-
-
-};
+; thanks but no thanks for now.
diff --git a/src/table/control_codes.h b/src/table/control_codes.h
--- a/src/table/control_codes.h
+++ b/src/table/control_codes.h
@@ -63,6 +63,10 @@
 	SCC_DATE_SHORT,
 	SCC_DATE_LONG,
 	SCC_DATE_ISO,
+	SCC_DATE_WALLCLOCK_TINY,
+	SCC_DATE_WALLCLOCK_SHORT,
+	SCC_DATE_WALLCLOCK_LONG,
+	SCC_DATE_WALLCLOCK_ISO,
 
 	SCC_STRING1,
 	SCC_STRING2,
diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini
--- a/src/table/currency_settings.ini
+++ b/src/table/currency_settings.ini
@@ -6,61 +6,4 @@
 ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 ;
 
-[pre-amble]
-static const SettingDesc _currency_settings[] = {
-[post-amble]
-};
-[templates]
-SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strval, $proc, $from, $to),
-SDT_CHR = SDT_CHR($base, $var,        $flags, $guiflags, $def,                        $str, $strval, $proc, $from, $to),
-SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def,                        $str, $strval, $proc, $from, $to),
-SDT_END = SDT_END()
-
-[defaults]
-flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
-guiflags = 0
-interval = 0
-str      = STR_NULL
-strval   = STR_NULL
-proc     = NULL
-load     = NULL
-from     = 0
-to       = SL_MAX_VERSION
-
-
-
-[SDT_VAR]
-base     = CurrencySpec
-var      = rate
-type     = SLE_UINT16
-def      = 1
-min      = 0
-max      = UINT16_MAX
-
-[SDT_CHR]
-base     = CurrencySpec
-var      = separator
-def      = "".""
-
-[SDT_VAR]
-base     = CurrencySpec
-var      = to_euro
-type     = SLE_INT32
-def      = 0
-min      = MIN_YEAR
-max      = MAX_YEAR
-
-[SDT_STR]
-base     = CurrencySpec
-var      = prefix
-type     = SLE_STRBQ
-def      = NULL
-
-[SDT_STR]
-base     = CurrencySpec
-var      = suffix
-type     = SLE_STRBQ
-def      = "" credits""
-
-[SDT_END]
-
+; thanks but no thanks for now.
diff --git a/src/table/settings.h b/src/table/settings.h
new file mode 100644
--- /dev/null
+++ b/src/table/settings.h
@@ -0,0 +1,872 @@
+/* $Id: settings.h 22074 2011-02-13 20:52:33Z yexo $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file table/settings.h Settings to save in the savegame and config file. */
+
+/* Begin - Callback Functions for the various settings */
+static bool v_PositionMainToolbar(int32 p1);
+static bool v_PositionStatusbar(int32 p1);
+static bool PopulationInLabelActive(int32 p1);
+static bool RedrawScreen(int32 p1);
+static bool RedrawSmallmap(int32 p1);
+static bool InvalidateDetailsWindow(int32 p1);
+static bool InvalidateStationBuildWindow(int32 p1);
+static bool InvalidateBuildIndustryWindow(int32 p1);
+static bool CloseSignalGUI(int32 p1);
+static bool InvalidateTownViewWindow(int32 p1);
+static bool DeleteSelectStationWindow(int32 p1);
+static bool UpdateConsists(int32 p1);
+static bool CheckInterval(int32 p1);
+static bool TrainAccelerationModelChanged(int32 p1);
+static bool RoadVehAccelerationModelChanged(int32 p1);
+static bool TrainSlopeSteepnessChanged(int32 p1);
+static bool RoadVehSlopeSteepnessChanged(int32 p1);
+static bool DragSignalsDensityChanged(int32);
+static bool TownFoundingChanged(int32 p1);
+static bool DifficultyReset(int32 level);
+static bool DifficultyChange(int32);
+static bool DifficultyNoiseChange(int32 i);
+static bool MaxNoAIsChange(int32 i);
+static bool CheckRoadSide(int p1);
+static size_t ConvertLandscape(const char *value);
+static bool TLSettingChanged(int32 p1);
+static bool CheckFreeformEdges(int32 p1);
+static bool ChangeDynamicEngines(int32 p1);
+static bool StationCatchmentChanged(int32 p1);
+static bool InvalidateVehTimetableWindow(int32 p1);
+static bool InvalidateCompanyLiveryWindow(int32 p1);
+static bool InvalidateNewGRFChangeWindows(int32 p1);
+static bool InvalidateIndustryViewWindow(int32 p1);
+static bool RedrawTownAuthority(int32 p1);
+extern bool UpdateNewGRFConfigPalette(int32 p1);
+static bool CheckSharingRail(int32 p1); // TODO: re-introduce IS individual company settings?
+static bool CheckSharingRoad(int32 p1);
+static bool CheckSharingWater(int32 p1);
+static bool CheckSharingAir(int32 p1);
+
+#ifdef ENABLE_NETWORK
+static bool UpdateClientName(int32 p1);
+static bool UpdateServerPassword(int32 p1);
+static bool UpdateRconPassword(int32 p1);
+static bool UpdateClientConfigValues(int32 p1);
+#endif /* ENABLE_NETWORK */
+/* End - Callback Functions for the various settings */
+
+
+/****************************
+ * OTTD specific INI stuff
+ ****************************/
+
+/**
+ * Settings-macro usage:
+ * The list might look daunting at first, but is in general easy to understand.
+ * We have two types of list:
+ * 1. SDTG_something
+ * 2. SDT_something
+ * The 'G' stands for global, so this is the one you will use for a
+ * SettingDescGlobVarList section meaning global variables. The other uses a
+ * Base/Offset and runtime variable selection mechanism, known from the saveload
+ * convention (it also has global so it should not be hard).
+ * Of each type there are again two versions, the normal one and one prefixed
+ * with 'COND'.
+ * COND means that the setting is only valid in certain savegame versions
+ * (since settings are saved to the savegame, this bookkeeping is necessary.
+ * Now there are a lot of types. Easy ones are:
+ * - VAR:  any number type, 'type' field specifies what number. eg int8 or uint32
+ * - BOOL: a boolean number type
+ * - STR:  a string or character. 'type' field specifies what string. Normal, string, or quoted
+ * A bit more difficult to use are MMANY (meaning ManyOfMany) and OMANY (OneOfMany)
+ * These are actually normal numbers, only bitmasked. In MMANY several bits can
+ * be set, in the other only one.
+ * The most complex type is INTLIST. This is basically an array of numbers. If
+ * the intlist is only valid in certain savegame versions because for example
+ * it has grown in size its length cannot be automatically be calculated so
+ * use SDT(G)_CONDLISTO() meaning Old.
+ * If nothing fits you, you can use the GENERAL macros, but it exposes the
+ * internal structure somewhat so it needs a little looking. There are _NULL()
+ * macros as well, these fill up space so you can add more settings there (in
+ * place) and you DON'T have to increase the savegame version.
+ *
+ * While reading values from openttd.cfg, some values may not be converted
+ * properly, for any kind of reasons.  In order to allow a process of self-cleaning
+ * mechanism, a callback procedure is made available.  You will have to supply the function, which
+ * will work on a string, one function per setting. And of course, enable the callback param
+ * on the appropriate macro.
+ */
+
+#define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, proc, load)\
+	{name, (const void*)(size_t)(def), {(byte)cmd}, {(uint16)guiflags}, min, max, interval, many, str, proc, load}
+
+/* Macros for various objects to go in the configuration file.
+ * This section is for global variables */
+#define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, proc, from, to)\
+	{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, proc, NULL), SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to)}
+
+#define SDTG_CONDVAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc, from, to)\
+	SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, NULL, str, proc, from, to)
+#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc)\
+	SDTG_CONDVAR(name, type, flags, guiflags, var, def, min, max, interval, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTG_CONDBOOL(name, flags, guiflags, var, def, str, proc, from, to)\
+	SDTG_GENERAL(name, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, var, 0, def, 0, 1, 0, NULL, str, proc, from, to)
+#define SDTG_BOOL(name, flags, guiflags, var, def, str, proc)\
+	SDTG_CONDBOOL(name, flags, guiflags, var, def, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTG_CONDLIST(name, type, length, flags, guiflags, var, def, str, proc, from, to)\
+	SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, NULL, str, proc, from, to)
+#define SDTG_LIST(name, type, flags, guiflags, var, def, str, proc)\
+	SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, lengthof(var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTG_CONDSTR(name, type, length, flags, guiflags, var, def, str, proc, from, to)\
+	SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, length, def, 0, 0, 0, NULL, str, proc, from, to)
+#define SDTG_STR(name, type, flags, guiflags, var, def, str, proc)\
+	SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, lengthof(var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTG_CONDOMANY(name, type, flags, guiflags, var, def, max, full, str, proc, from, to)\
+	SDTG_GENERAL(name, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, max, 0, full, str, proc, from, to)
+#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, proc)\
+	SDTG_CONDOMANY(name, type, flags, guiflags, var, def, max, full, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTG_CONDMMANY(name, type, flags, guiflags, var, def, full, str, proc, from, to)\
+	SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, proc, from, to)
+#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, proc)\
+	SDTG_CONDMMANY(name, type, flags, guiflags, var, def, full, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTG_CONDNULL(length, from, to)\
+	{{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL, NULL}, SLEG_CONDNULL(length, from, to)}
+
+#define SDTG_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL, NULL}, SLEG_END()}
+
+/* Macros for various objects to go in the configuration file.
+ * This section is for structures where their various members are saved */
+#define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, proc, load, from, to)\
+	{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, proc, load), SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to)}
+
+#define SDT_CONDVAR(base, var, type, from, to, flags, guiflags, def, min, max, interval, str, proc)\
+	SDT_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, NULL, str, proc, NULL, from, to)
+#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, proc)\
+	SDT_CONDVAR(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, min, max, interval, str, proc)
+
+#define SDT_CONDBOOL(base, var, from, to, flags, guiflags, def, str, proc)\
+	SDT_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, base, var, 1, def, 0, 1, 0, NULL, str, proc, NULL, from, to)
+#define SDT_BOOL(base, var, flags, guiflags, def, str, proc)\
+	SDT_CONDBOOL(base, var, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
+
+#define SDT_CONDLIST(base, var, type, from, to, flags, guiflags, def, str, proc)\
+	SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to)
+#define SDT_LIST(base, var, type, flags, guiflags, def, str, proc)\
+	SDT_CONDLIST(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
+
+#define SDT_CONDSTR(base, var, type, from, to, flags, guiflags, def, str, proc)\
+	SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to)
+#define SDT_STR(base, var, type, flags, guiflags, def, str, proc)\
+	SDT_CONDSTR(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
+#define SDT_CONDSTRO(base, var, length, type, from, to, flags, def, str, proc)\
+	SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, 0, base, var, length, def, 0, 0, NULL, str, proc, from, to)
+
+#define SDT_CONDCHR(base, var, from, to, flags, guiflags, def, str, proc)\
+	SDT_GENERAL(#var, SDT_STRING, SL_VAR, SLE_CHAR, flags, guiflags, base, var, 1, def, 0, 0, 0, NULL, str, proc, NULL, from, to)
+#define SDT_CHR(base, var, flags, guiflags, def, str, proc)\
+	SDT_CONDCHR(base, var, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
+
+#define SDT_CONDOMANY(base, var, type, from, to, flags, guiflags, def, max, full, str, proc, load)\
+	SDT_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, max, 0, full, str, proc, load, from, to)
+#define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, proc, load)\
+	SDT_CONDOMANY(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, max, full, str, proc, load)
+
+#define SDT_CONDMMANY(base, var, type, from, to, flags, guiflags, def, full, str, proc)\
+	SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, proc, NULL, from, to)
+#define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc)\
+	SDT_CONDMMANY(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, full, str, proc)
+
+#define SDT_CONDNULL(length, from, to)\
+	{{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL, NULL}, SLE_CONDNULL(length, from, to)}
+
+
+#define SDTC_CONDVAR(var, type, from, to, flags, guiflags, def, min, max, interval, str, proc)\
+	SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, NULL, str, proc, from, to)
+#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, proc)\
+	SDTC_CONDVAR(var, type, 0, SL_MAX_VERSION, flags, guiflags, def, min, max, interval, str, proc)
+
+#define SDTC_CONDBOOL(var, from, to, flags, guiflags, def, str, proc)\
+	SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, NULL, str, proc, from, to)
+#define SDTC_BOOL(var, flags, guiflags, def, str, proc)\
+	SDTC_CONDBOOL(var, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
+
+#define SDTC_CONDLIST(var, type, length, flags, guiflags, def, str, proc, from, to)\
+	SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, length, def, 0, 0, 0, NULL, str, proc, from, to)
+#define SDTC_LIST(var, type, flags, guiflags, def, str, proc)\
+	SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTC_CONDSTR(var, type, length, flags, guiflags, def, str, proc, from, to)\
+	SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, length, def, 0, 0, 0, NULL, str, proc, from, to)
+#define SDTC_STR(var, type, flags, guiflags, def, str, proc)\
+	SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+
+#define SDTC_CONDOMANY(var, type, from, to, flags, guiflags, def, max, full, str, proc)\
+	SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, proc, from, to)
+#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, proc)\
+	SDTC_CONDOMANY(var, type, 0, SL_MAX_VERSION, flags, guiflags, def, max, full, str, proc)
+
+#define SDT_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, NULL, NULL}, SLE_END()}
+
+/* Shortcuts for macros below. Logically if we don't save the value
+ * we also don't sync it in a network game */
+#define S SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+#define C SLF_NOT_IN_CONFIG
+#define N SLF_NO_NETWORK_SYNC
+
+#define D0 SGF_0ISDISABLED
+#define NC SGF_NOCOMMA
+#define MS SGF_MULTISTRING
+#define NO SGF_NETWORK_ONLY
+#define CR SGF_CURRENCY
+#define NN SGF_NO_NETWORK
+#define NG SGF_NEWGAME_ONLY
+#define NS SGF_NEWGAME_ONLY | SGF_SCENEDIT_TOO
+#define PC SGF_PER_COMPANY
+
+#include "../map_func.h"
+
+static bool AfterChangeOfAllowMoreHeightlevels(int32 p1)
+{
+	/* It's a boolean setting, so anything else would be really strange... */
+	assert(p1 == 0 || p1 == 1);
+
+	/* Allow_more_heightlevels was turned off before, now we turn it on. */
+	if (p1 == 1) {
+		/* If we are in game or in the editor, we have to copy
+		 * the heightlevel information to its new place. */
+		if (_game_mode != GM_MENU) {
+			CopyHeightlevelDataFromOldToExtended();
+		}
+		return true;
+	} else {
+		if (_game_mode != GM_MENU) {
+			/* Considering the assertion above, p1 == 0 is true here. */
+			bool success = CopyHeightlevelDataFromExtendedToOld();
+			if (!success) {
+				_settings_game.construction.allow_more_heightlevels = true;
+				ShowErrorMessage(STR_CONFIG_SETTING_ERROR_NO_CHANGE_TO_OLD_POSSIBLE, INVALID_STRING_ID, WL_WARNING);
+				return false;
+				}
+			}
+		/* Other settings are reduced to old heightlevels. */
+		_settings_newgame.game_creation.snow_line_height     = Clamp(_settings_newgame.game_creation.snow_line_height, MIN_SNOWLINE_HEIGHT, MAX_SNOWLINE_HEIGHT_OLD);
+		_settings_newgame.game_creation.se_flat_world_height = Clamp(_settings_newgame.game_creation.se_flat_world_height, 0, MAX_TILE_HEIGHT_OLD);
+		_settings_newgame.game_creation.tree_line_height     = Clamp(_settings_newgame.game_creation.tree_line_height, MIN_TREELINE_HEIGHT, MAX_TREELINE_HEIGHT_OLD);
+		return true;
+	}
+}
+
+static const SettingDesc _music_settings[] = {
+	 SDT_VAR(MusicFileSettings, playlist,   SLE_UINT8, S, 0, 0,     0,   5, 1, STR_NULL, NULL),
+	 SDT_VAR(MusicFileSettings, music_vol,  SLE_UINT8, S, 0, 127,   0, 127, 1, STR_NULL, NULL),
+	 SDT_VAR(MusicFileSettings, effect_vol, SLE_UINT8, S, 0, 127,   0, 127, 1, STR_NULL, NULL),
+	SDT_LIST(MusicFileSettings, custom_1,   SLE_UINT8, S, 0, NULL,             STR_NULL, NULL),
+	SDT_LIST(MusicFileSettings, custom_2,   SLE_UINT8, S, 0, NULL,             STR_NULL, NULL),
+	SDT_BOOL(MusicFileSettings, playing,               S, 0, true,             STR_NULL, NULL),
+	SDT_BOOL(MusicFileSettings, shuffle,               S, 0, false,            STR_NULL, NULL),
+	 SDT_END()
+};
+
+/* win32_v.cpp only settings */
+#if defined(WIN32) && !defined(DEDICATED)
+extern bool _force_full_redraw, _window_maximize;
+extern uint _display_hz, _fullscreen_bpp;
+
+static const SettingDescGlobVarList _win32_settings[] = {
+	 SDTG_VAR("display_hz",              SLE_UINT,    S, 0, _display_hz,             0,     0, 120,        0, STR_NULL, NULL),
+	SDTG_BOOL("force_full_redraw",                    S, 0, _force_full_redraw,      false,                   STR_NULL, NULL),
+	 SDTG_VAR("fullscreen_bpp",          SLE_UINT,    S, 0, _fullscreen_bpp,         8,     8, 32,         0, STR_NULL, NULL),
+	SDTG_BOOL("window_maximize",                      S, 0, _window_maximize,        false,                   STR_NULL, NULL),
+	 SDTG_END()
+};
+#endif /* WIN32 */
+
+extern char _config_language_file[MAX_PATH];
+
+static const SettingDescGlobVarList _misc_settings[] = {
+	SDTG_MMANY("display_opt",           SLE_UINT8,    S, 0, _display_opt, (1 << DO_SHOW_TOWN_NAMES | 1 << DO_SHOW_STATION_NAMES | 1 << DO_SHOW_SIGNS | 1 << DO_FULL_ANIMATION | 1 << DO_FULL_DETAIL | 1 << DO_SHOW_WAYPOINT_NAMES), "SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION||FULL_DETAIL|WAYPOINTS", STR_NULL, NULL),
+	 SDTG_BOOL("news_ticker_sound",                   S, 0, _news_ticker_sound,      true,                    STR_NULL, NULL),
+	 SDTG_BOOL("fullscreen",                          S, 0, _fullscreen,             false,                   STR_NULL, NULL),
+	  SDTG_STR("graphicsset",            SLE_STRQ,    S, 0, BaseGraphics::ini_set,   NULL,                    STR_NULL, NULL),
+	  SDTG_STR("soundsset",              SLE_STRQ,    S, 0, BaseSounds::ini_set,     NULL,                    STR_NULL, NULL),
+	  SDTG_STR("musicset",               SLE_STRQ,    S, 0, BaseMusic::ini_set,      NULL,                    STR_NULL, NULL),
+	  SDTG_STR("videodriver",            SLE_STRQ,    S, 0, _ini_videodriver,        NULL,                    STR_NULL, NULL),
+	  SDTG_STR("musicdriver",            SLE_STRQ,    S, 0, _ini_musicdriver,        NULL,                    STR_NULL, NULL),
+	  SDTG_STR("sounddriver",            SLE_STRQ,    S, 0, _ini_sounddriver,        NULL,                    STR_NULL, NULL),
+	  SDTG_STR("blitter",                SLE_STRQ,    S, 0, _ini_blitter,            NULL,                    STR_NULL, NULL),
+	  SDTG_STR("language",               SLE_STRB,    S, 0, _config_language_file,   NULL,                    STR_NULL, NULL),
+	SDTG_CONDLIST("resolution",           SLE_INT, 2, S, 0, _cur_resolution,         "640,480",               STR_NULL, NULL, 0, SL_MAX_VERSION), // workaround for implicit lengthof() in SDTG_LIST
+	  SDTG_STR("screenshot_format",      SLE_STRB,    S, 0, _screenshot_format_name, NULL,                    STR_NULL, NULL),
+	  SDTG_STR("savegame_format",        SLE_STRB,    S, 0, _savegame_format,        NULL,                    STR_NULL, NULL),
+	 SDTG_BOOL("rightclick_emulate",                  S, 0, _rightclick_emulate,     false,                   STR_NULL, NULL),
+#ifdef WITH_FREETYPE
+	  SDTG_STR("small_font",             SLE_STRB,    S, 0, _freetype.small_font,    NULL,                    STR_NULL, NULL),
+	  SDTG_STR("medium_font",            SLE_STRB,    S, 0, _freetype.medium_font,   NULL,                    STR_NULL, NULL),
+	  SDTG_STR("large_font",             SLE_STRB,    S, 0, _freetype.large_font,    NULL,                    STR_NULL, NULL),
+	  SDTG_VAR("small_size",             SLE_UINT,    S, 0, _freetype.small_size,    8,     0, 72,         0, STR_NULL, NULL),
+	  SDTG_VAR("medium_size",            SLE_UINT,    S, 0, _freetype.medium_size,   10,    0, 72,         0, STR_NULL, NULL),
+	  SDTG_VAR("large_size",             SLE_UINT,    S, 0, _freetype.large_size,    16,    0, 72,         0, STR_NULL, NULL),
+	 SDTG_BOOL("small_aa",                            S, 0, _freetype.small_aa,      false,                   STR_NULL, NULL),
+	 SDTG_BOOL("medium_aa",                           S, 0, _freetype.medium_aa,     false,                   STR_NULL, NULL),
+	 SDTG_BOOL("large_aa",                            S, 0, _freetype.large_aa,      false,                   STR_NULL, NULL),
+#endif
+	  SDTG_VAR("sprite_cache_size",      SLE_UINT,    S, 0, _sprite_cache_size,       4,    1, 64,         0, STR_NULL, NULL),
+	  SDTG_VAR("player_face",          SLE_UINT32,    S, 0, _company_manager_face,    0,    0, 0xFFFFFFFF, 0, STR_NULL, NULL),
+	  SDTG_VAR("transparency_options",   SLE_UINT,    S, 0, _transparency_opt,        0,    0, 0x3FF,      0, STR_NULL, NULL),
+	  SDTG_VAR("transparency_locks",     SLE_UINT,    S, 0, _transparency_lock,       0,    0, 0x3FF,      0, STR_NULL, NULL),
+	  SDTG_VAR("invisibility_options",   SLE_UINT,    S, 0, _invisibility_opt,        0,    0, 0xFF,       0, STR_NULL, NULL),
+	  SDTG_STR("keyboard",               SLE_STRB,    S, 0, _keyboard_opt[0],         NULL,                   STR_NULL, NULL),
+	  SDTG_STR("keyboard_caps",          SLE_STRB,    S, 0, _keyboard_opt[1],         NULL,                   STR_NULL, NULL),
+	  SDTG_END()
+};
+
+static const uint GAME_DIFFICULTY_NUM = 18;
+static uint16 _old_diff_custom[GAME_DIFFICULTY_NUM];
+
+/* Most of these strings are used both for gameopt-backward compatability
+ * and the settings tables. The rest is here for consistency. */
+static const char *_locale_currencies = "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|RON|RUR|SIT|SEK|YTL|SKK|BRL|EEK|custom";
+static const char *_locale_units      = "imperial|metric|si";
+static const char *_town_names        = "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovak|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan";
+static const char *_climates          = "temperate|arctic|tropic|toyland";
+static const char *_autosave_interval = "off|daily|weekly|monthly|quarterly|half year|yearly";
+static const char *_roadsides         = "left|right";
+static const char *_savegame_date     = "long|short|iso";
+#ifdef ENABLE_NETWORK
+static const char *_server_langs      = "ANY|ENGLISH|GERMAN|FRENCH|BRAZILIAN|BULGARIAN|CHINESE|CZECH|DANISH|DUTCH|ESPERANTO|FINNISH|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|LITHUANIAN|NORWEGIAN|POLISH|PORTUGUESE|ROMANIAN|RUSSIAN|SLOVAK|SLOVENIAN|SPANISH|SWEDISH|TURKISH|UKRAINIAN|AFRIKAANS|CROATIAN|CATALAN|ESTONIAN|GALICIAN|GREEK|LATVIAN";
+#endif /* ENABLE_NETWORK */
+
+static const SettingDesc _gameopt_settings[] = {
+	/* In version 4 a new difficulty setting has been added to the difficulty settings,
+	 * town attitude towards demolishing. Needs special handling because some dimwit thought
+	 * it funny to have the GameDifficulty struct be an array while it is a struct of
+	 * same-sized members
+	 * XXX - To save file-space and since values are never bigger than about 10? only
+	 * save the first 16 bits in the savegame. Question is why the values are still int32
+	 * and why not byte for example?
+	 * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlArray() hack
+	 * for savegames version 0 - though it is an array, it has to go through the byteswap process */
+	 SDTG_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_FILE_I16 | SLE_VAR_U16,       C, 0, _old_diff_custom, 17, 0, 0, 0, 0, NULL, STR_NULL, NULL, 0, 3),
+	 SDTG_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_UINT16,                       C, 0, _old_diff_custom, 18, 0, 0, 0, 0, NULL, STR_NULL, NULL, 4, SL_MAX_VERSION),
+
+	      SDT_VAR(GameSettings, difficulty.diff_level,       SLE_UINT8,                 0, 0, 3, 0, 3, 0,                                STR_NULL, NULL),
+	    SDT_OMANY(GameSettings, locale.currency,             SLE_UINT8,                 N, 0, 0, CUSTOM_CURRENCY_ID, _locale_currencies, STR_NULL, NULL, NULL),
+	    SDT_OMANY(GameSettings, locale.units,                SLE_UINT8,                 N, 0, 1, 2,                  _locale_units,      STR_NULL, NULL, NULL),
+	/* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */
+	    SDT_OMANY(GameSettings, game_creation.town_name,     SLE_UINT8,                 0, 0, 0, 255, _town_names, STR_NULL, NULL, NULL),
+	    SDT_OMANY(GameSettings, game_creation.landscape,     SLE_UINT8,                 0, 0, 0, 3,     _climates, STR_NULL, NULL, ConvertLandscape),
+	  SDT_CONDVAR(GameSettings, game_creation.snow_line,     SLE_FILE_U8 | SLE_VAR_U16, 0,          MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, 0, DEF_SNOWLINE_HEIGHT_OLD * TILE_HEIGHT,      MIN_SNOWLINE_HEIGHT * TILE_HEIGHT, MAX_SNOWLINE_HEIGHT_OLD * TILE_HEIGHT,      0, STR_NULL, NULL),
+	  SDT_CONDVAR(GameSettings, game_creation.snow_line,     SLE_UINT16,                MORE_HEIGHTLEVEL_SAVEGAME_VERSION, SL_MAX_VERSION, 0, 0, DEF_SNOWLINE_HEIGHT_EXTENDED * TILE_HEIGHT, MIN_SNOWLINE_HEIGHT * TILE_HEIGHT, MAX_SNOWLINE_HEIGHT_EXTENDED * TILE_HEIGHT, 0, STR_NULL, NULL),
+	  SDT_CONDVAR(GameSettings, game_creation.desert_amount, SLE_UINT8,                 DESERT_SV, SL_MAX_VERSION, 0, 0, DEF_DESERT_AMOUNT, MIN_DESERT_AMOUNT, MAX_DESERT_AMOUNT, 1, STR_NULL, NULL),
+	  SDT_CONDVAR(GameSettings, game_creation.tree_line,     SLE_FILE_U8 | SLE_VAR_U16, MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 2, MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, 0, DEF_TREELINE_HEIGHT_OLD * TILE_HEIGHT,      MIN_TREELINE_HEIGHT * TILE_HEIGHT, MAX_TREELINE_HEIGHT_OLD * TILE_HEIGHT,      0, STR_NULL, NULL),
+	  SDT_CONDVAR(GameSettings, game_creation.tree_line,     SLE_UINT16,                MORE_HEIGHTLEVEL_SAVEGAME_VERSION,                            SL_MAX_VERSION, 0, 0, DEF_TREELINE_HEIGHT_EXTENDED * TILE_HEIGHT, MIN_TREELINE_HEIGHT * TILE_HEIGHT, MAX_TREELINE_HEIGHT_EXTENDED * TILE_HEIGHT, 0, STR_NULL, NULL),
+	 SDT_CONDNULL(1,  0, 22),
+   SDTC_CONDOMANY(              gui.autosave,                SLE_UINT8,                 23, SL_MAX_VERSION, S, 0, 3, 6, _autosave_interval, STR_NULL, NULL),
+	    SDT_OMANY(GameSettings, vehicle.road_side,           SLE_UINT8,                 0, 0, 1, 1, _roadsides, STR_NULL, NULL, NULL),
+	    SDT_END()
+};
+
+/* Some settings do not need to be synchronised when playing in multiplayer.
+ * These include for example the GUI settings and will not be saved with the
+ * savegame.
+ * It is also a bit tricky since you would think that service_interval
+ * for example doesn't need to be synched. Every client assigns the
+ * service_interval value to the v->service_interval, meaning that every client
+ * assigns his value. If the setting was company-based, that would mean that
+ * vehicles could decide on different moments that they are heading back to a
+ * service depot, causing desyncs on a massive scale. */
+const SettingDesc _settings[] = {
+	/***************************************************************************/
+	/* Saved settings variables. */
+	/* Do not ADD or REMOVE something in this "difficulty.XXX" table or before it. It breaks savegame compatability. */
+	 SDT_CONDVAR(GameSettings, difficulty.max_no_competitors,                  SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    0,                              0,                  MAX_COMPANIES-1,              1,     STR_NULL,                                               MaxNoAIsChange),
+	SDT_CONDNULL(1, 97, 109),
+	 SDT_CONDVAR(GameSettings, difficulty.number_towns,                        SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NG,    2,                              0,                  4,                            1,     STR_NUM_VERY_LOW,                                       DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.industry_density,                    SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NG,    ID_END-1,                       0,                  ID_END-1,                     1,     STR_FUNDING_ONLY,                                       DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.max_loan,                            SLE_UINT32,                97,                                    SL_MAX_VERSION,                        0, NS|CR, 300000,                         100000,             500000,                       50000, STR_NULL,                                               DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.initial_interest,                    SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NS,    2,                              2,                  4,                            1,     STR_NULL,                                               DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.vehicle_costs,                       SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NS,    0,                              0,                  2,                            1,     STR_SEA_LEVEL_LOW,                                      DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.competitor_speed,                    SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    2,                              0,                  4,                            1,     STR_AI_SPEED_VERY_SLOW,                                 DifficultyChange),
+	SDT_CONDNULL(1, 97, 109),
+	 SDT_CONDVAR(GameSettings, difficulty.vehicle_breakdowns,                  SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    1,                              0,                  2,                            1,     STR_DISASTER_NONE,                                      DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.subsidy_multiplier,                  SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    2,                              0,                  3,                            1,     STR_SUBSIDY_X1_5,                                       DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.construction_cost,                   SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NS,    0,                              0,                  2,                            1,     STR_SEA_LEVEL_LOW,                                      DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.terrain_type,                        SLE_FILE_U8 | SLE_VAR_U8,  97,                                    MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, NG,    1,                              0,                  3,                            1,     STR_TERRAIN_TYPE_VERY_FLAT,                             DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.terrain_type,                        SLE_UINT8,                 MORE_HEIGHTLEVEL_SAVEGAME_VERSION,     SL_MAX_VERSION,                        0, NG,    1,                              0,                  6,                            1,     STR_TERRAIN_TYPE_FALLEN,                                DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.quantity_sea_lakes,                  SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NG,    0,                              0,                  4,                            1,     STR_SEA_LEVEL_VERY_LOW,                                 DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.economy,                             SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    0,                              0,                  1,                            1,     STR_ECONOMY_STEADY,                                     DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.line_reverse_mode,                   SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    0,                              0,                  1,                            1,     STR_REVERSE_AT_END_OF_LINE_AND_AT_STATIONS,             DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.disasters,                           SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    0,                              0,                  1,                            1,     STR_DISASTERS_OFF,                                      DifficultyChange),
+	 SDT_CONDVAR(GameSettings, difficulty.town_council_tolerance,              SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    0,                              0,                  2,                            1,     STR_CITY_APPROVAL_PERMISSIVE,                           DifficultyNoiseChange),
+	 SDT_CONDVAR(GameSettings, difficulty.diff_level,                          SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0,  0,    3,                              0,                  3,                            0,     STR_NULL,                                               DifficultyReset),
+
+	/* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */
+   SDT_CONDOMANY(GameSettings, game_creation.town_name,                        SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NN,    0,                              255,              _town_names,                          STR_NULL,                                                NULL, NULL),
+   SDT_CONDOMANY(GameSettings, game_creation.landscape,                        SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NN,    0,                              3,                _climates,                            STR_NULL,                                                NULL, ConvertLandscape),
+     SDT_CONDVAR(GameSettings, game_creation.snow_line,                        SLE_FILE_U8 | SLE_VAR_U16, 97,                                    MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, NN,    DEF_SNOWLINE_HEIGHT_OLD * TILE_HEIGHT,      MIN_SNOWLINE_HEIGHT * TILE_HEIGHT, MAX_SNOWLINE_HEIGHT_OLD * TILE_HEIGHT,      0, STR_NULL,          NULL),
+     SDT_CONDVAR(GameSettings, game_creation.snow_line,                        SLE_UINT16,                MORE_HEIGHTLEVEL_SAVEGAME_VERSION,     SL_MAX_VERSION,                        0, NN,    DEF_SNOWLINE_HEIGHT_EXTENDED * TILE_HEIGHT, MIN_SNOWLINE_HEIGHT * TILE_HEIGHT, MAX_SNOWLINE_HEIGHT_EXTENDED * TILE_HEIGHT, 0, STR_NULL,          NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.desert_amount,                    SLE_UINT8,                 DESERT_SV,                             SL_MAX_VERSION,                        0, NN,    DEF_DESERT_AMOUNT,                          MIN_DESERT_AMOUNT,                 MAX_DESERT_AMOUNT,                          0, STR_NULL,          NULL),
+     SDT_CONDVAR(GameSettings, game_creation.tree_line,                        SLE_FILE_U8 | SLE_VAR_U16, MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 2, MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, NN,    DEF_TREELINE_HEIGHT_OLD * TILE_HEIGHT,      MIN_TREELINE_HEIGHT * TILE_HEIGHT, MAX_TREELINE_HEIGHT_OLD * TILE_HEIGHT,      0, STR_NULL,          NULL),
+     SDT_CONDVAR(GameSettings, game_creation.tree_line,                        SLE_UINT16,                MORE_HEIGHTLEVEL_SAVEGAME_VERSION,     SL_MAX_VERSION,                        0, NN,    DEF_TREELINE_HEIGHT_EXTENDED * TILE_HEIGHT, MIN_TREELINE_HEIGHT * TILE_HEIGHT, MAX_TREELINE_HEIGHT_EXTENDED * TILE_HEIGHT, 0, STR_NULL,          NULL),
+   SDT_CONDOMANY(GameSettings, vehicle.road_side,                              SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        0, NN,    1,                             1,                  _roadsides,                          STR_NULL,                                                CheckRoadSide, NULL),
+
+// TODO: savegameversion + 1 and no network.
+	SDT_CONDBOOL(GameSettings, construction.allow_more_heightlevels,                                      MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_MORE_HEIGHTLEVELS,                   AfterChangeOfAllowMoreHeightlevels),
+	    SDT_BOOL(GameSettings, construction.build_on_slopes,                                                                                                                            0, NN,    true,                                                                                    STR_CONFIG_SETTING_BUILDONSLOPES,                       NULL),
+	 SDT_CONDVAR(GameSettings, construction.command_pause_level,               SLE_UINT8,                 154,                                   BEFORE_ADDING_PATCHES_SL,              0, MS|NN, 1,                             0,                  3,                             1,     STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL,                 NULL),
+	 SDT_CONDVAR(GameSettings, construction.command_pause_level,               SLE_UINT8,                 KEEP_COMPATIBLE_12_SV,                 SL_MAX_VERSION,                        0, MS|NN, 1,                             0,                  3,                             1,     STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL,                 NULL),
+	 SDT_CONDVAR(GameSettings, construction.terraform_per_64k_frames,          SLE_UINT32,                156,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     64 << 16,                      0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.terraform_per_64k_frames,          SLE_UINT32,                KEEP_COMPATIBLE_14_SV,                 SL_MAX_VERSION,                        0, 0,     64 << 16,                      0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.terraform_frame_burst,             SLE_UINT16,                156,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     4096,                          0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.terraform_frame_burst,             SLE_UINT16,                KEEP_COMPATIBLE_14_SV,                 SL_MAX_VERSION,                        0, 0,     4096,                          0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.clear_per_64k_frames,              SLE_UINT32,                156,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     64 << 16,                      0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.clear_per_64k_frames,              SLE_UINT32,                KEEP_COMPATIBLE_14_SV,                 SL_MAX_VERSION,                        0, 0,     64 << 16,                      0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.clear_frame_burst,                 SLE_UINT16,                156,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     4096,                          0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.clear_frame_burst,                 SLE_UINT16,                KEEP_COMPATIBLE_14_SV,                 SL_MAX_VERSION,                        0, 0,     4096,                          0,                  1 << 30,                       1,     STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, construction.autoslope,                                                    75,                                    SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_AUTOSLOPE,                           NULL),
+	    SDT_BOOL(GameSettings, construction.extra_dynamite,                                                                                                                             0, 0,     true,                                                                                    STR_CONFIG_SETTING_EXTRADYNAMITE,                       NULL),
+	 SDT_CONDVAR(GameSettings, construction.max_bridge_length,                 SLE_UINT16,                159,                                   BEFORE_ADDING_PATCHES_SL,              0, NN,    64,                            1,                  2048,                          1,     STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH,                   NULL),
+	 SDT_CONDVAR(GameSettings, construction.max_bridge_length,                 SLE_UINT16,                KEEP_COMPATIBLE_17_SV,                 SL_MAX_VERSION,                        0, NN,    64,                            1,                  2048,                          1,     STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH,                   NULL),
+	 SDT_CONDVAR(GameSettings, construction.max_tunnel_length,                 SLE_UINT16,                159,                                   BEFORE_ADDING_PATCHES_SL,              0, NN,    64,                            1,                  2048,                          1,     STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH,                   NULL),
+	 SDT_CONDVAR(GameSettings, construction.max_tunnel_length,                 SLE_UINT16,                KEEP_COMPATIBLE_17_SV,                 SL_MAX_VERSION,                        0, NN,    64,                            1,                  2048,                          1,     STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH,                   NULL),
+	SDT_CONDNULL(1, 0, 158), // construction.longbridges
+	SDT_CONDNULL(1, BEFORE_ADDING_PATCHES_SL, KEEP_COMPATIBLE_16_SV), // construction.longbridges
+	    SDT_BOOL(GameSettings, construction.signal_side,                                                                                                                                N, NN,    true,                                                                                    STR_CONFIG_SETTING_SIGNALSIDE,                          RedrawScreen),
+	    SDT_BOOL(GameSettings, station.never_expire_airports,                                                                                                                           0, NN,    false,                                                                                   STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS,               NULL),
+	 SDT_CONDVAR(GameSettings, economy.town_layout,                            SLE_UINT8,                 59,                                    SL_MAX_VERSION,                        0, MS,    TL_ORIGINAL,                   TL_BEGIN,           NUM_TLS - 1,                   1,     STR_CONFIG_SETTING_TOWN_LAYOUT,                         TownFoundingChanged),
+	SDT_CONDBOOL(GameSettings, economy.allow_town_roads,                                                  113,                                   SL_MAX_VERSION,                        0, NN,    true,                                                                                    STR_CONFIG_SETTING_ALLOW_TOWN_ROADS,                    NULL),
+	SDTG_CONDVAR("daylength_factor", SLE_UINT8, 0, 0, _date_daylength_factor, 1, 1, 255, 1, STR_CONFIG_SETTING_DAYLENGTH_FACTOR, NULL, DAYLENGHT_SL, SL_MAX_VERSION),
+	 SDT_CONDVAR(GameSettings, economy.found_town,                             SLE_UINT8,                 128,                                   SL_MAX_VERSION,                        0, MS,    TF_FORBIDDEN,                  TF_BEGIN,           TF_END - 1,                    1,     STR_CONFIG_SETTING_TOWN_FOUNDING,                       TownFoundingChanged),
+	SDT_CONDBOOL(GameSettings, economy.allow_town_level_crossings,                                        143,                                   SL_MAX_VERSION,                        0, NN,    true,                                                                                    STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS,          NULL),
+	 SDT_CONDVAR(GameSettings, economy.town_cargo_factor,                      SLE_INT8,                  TOWN_CARGO_FACTOR_SL,                  SL_MAX_VERSION,                        0, 0,     0,                             -16,                8,                             1,     STR_CONFIG_SETTING_TOWN_CARGO_FACTOR,                   NULL),
+
+	     SDT_VAR(GameSettings, vehicle.train_acceleration_model,               SLE_UINT8,                                                                                               0, MS,    0,                             0,                  1,                             1,     STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL,            TrainAccelerationModelChanged),
+	 SDT_CONDVAR(GameSettings, vehicle.roadveh_acceleration_model,             SLE_UINT8,                 139,                                   SL_MAX_VERSION,                        0, MS,    0,                             0,                  1,                             1,     STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL,     RoadVehAccelerationModelChanged),
+	 SDT_CONDVAR(GameSettings, vehicle.train_slope_steepness,                  SLE_UINT8,                 133,                                   SL_MAX_VERSION,                        0, 0,     3,                             0,                  10,                            1,     STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS,               TrainSlopeSteepnessChanged),
+	 SDT_CONDVAR(GameSettings, vehicle.roadveh_slope_steepness,                SLE_UINT8,                 139,                                   SL_MAX_VERSION,                        0, 0,     7,                             0,                  10,                            1,     STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS,        RoadVehSlopeSteepnessChanged),
+	    SDT_BOOL(GameSettings, pf.forbid_90_deg,                                                                                                                                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_FORBID_90_DEG,                       NULL),
+	SDT_CONDBOOL(GameSettings, pf.back_of_one_way_pbs_waiting_point,                                      BACK_ONE_WAY_SIGNAL_SAFE_WAITING_SL,   SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_BACK_ONE_WAY_PBS_SAFE_WAITING,       NULL),
+	 SDT_CONDVAR(GameSettings, vehicle.max_train_length,                       SLE_UINT8,                 159,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     7,                             1,                  64,                            1,     STR_CONFIG_SETTING_TRAIN_LENGTH,                        NULL),
+	 SDT_CONDVAR(GameSettings, vehicle.max_train_length,                       SLE_UINT8,                 KEEP_COMPATIBLE_17_SV,                 SL_MAX_VERSION,                        0, 0,     7,                             1,                  64,                            1,     STR_CONFIG_SETTING_TRAIN_LENGTH,                        NULL),
+	SDT_CONDNULL(1, 0, 158), // vehicle.mammoth_trains
+	SDT_CONDNULL(1, BEFORE_ADDING_PATCHES_SL, KEEP_COMPATIBLE_16_SV), // vehicle.mammoth_trains
+	 SDT_CONDVAR(GameSettings, vehicle.smoke_amount,                           SLE_UINT8,                 145,                                   SL_MAX_VERSION,                        0, MS,    1,                             0,                  2,                             0,     STR_CONFIG_SETTING_SMOKE_AMOUNT,                        NULL),
+	    SDT_BOOL(GameSettings, order.gotodepot,                                                                                                                                         0, 0,     true,                                                                                    STR_CONFIG_SETTING_GOTODEPOT,                           NULL),
+	    SDT_BOOL(GameSettings, pf.roadveh_queue,                                                                                                                                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_ROAD_VEHICLE_QUEUEING,               NULL),
+	SDT_CONDBOOL(GameSettings, pf.new_pathfinding_all,                                                     0,                                    86,                                    0, 0,     false,                                                                                   STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, pf.yapf.ship_use_yapf,                                                     28,                                    86,                                    0, 0,     false,                                                                                   STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, pf.yapf.road_use_yapf,                                                     28,                                    86,                                    0, 0,     true,                                                                                    STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, pf.yapf.rail_use_yapf,                                                     28,                                    86,                                    0, 0,     true,                                                                                    STR_NULL,                                               NULL),
+
+	 SDT_CONDVAR(GameSettings, pf.pathfinder_for_trains,                       SLE_UINT8,                 87,                                    SL_MAX_VERSION,                        0, MS,    2,                             1,                  2,                             1,     STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS,               NULL),
+	 SDT_CONDVAR(GameSettings, pf.pathfinder_for_roadvehs,                     SLE_UINT8,                 87,                                    SL_MAX_VERSION,                        0, MS,    2,                             1,                  2,                             1,     STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES,        NULL),
+	 SDT_CONDVAR(GameSettings, pf.pathfinder_for_ships,                        SLE_UINT8,                 87,                                    SL_MAX_VERSION,                        0, MS,    2,                             0,                  2,                             1,     STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS,                NULL),
+
+	    SDT_BOOL(GameSettings, vehicle.never_expire_vehicles,                                                                                                                           0, NN,    false,                                                                                   STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES,               NULL),
+	     SDT_VAR(GameSettings, vehicle.max_trains,                             SLE_UINT16,                                                                                              0, 0,     500,                           0,                  5000,                          0,     STR_CONFIG_SETTING_MAX_TRAINS,                          RedrawScreen),
+	     SDT_VAR(GameSettings, vehicle.max_roadveh,                            SLE_UINT16,                                                                                              0, 0,     500,                           0,                  5000,                          0,     STR_CONFIG_SETTING_MAX_ROAD_VEHICLES,                   RedrawScreen),
+	     SDT_VAR(GameSettings, vehicle.max_aircraft,                           SLE_UINT16,                                                                                              0, 0,     200,                           0,                  5000,                          0,     STR_CONFIG_SETTING_MAX_AIRCRAFT,                        RedrawScreen),
+	     SDT_VAR(GameSettings, vehicle.max_ships,                              SLE_UINT16,                                                                                              0, 0,     300,                           0,                  5000,                          0,     STR_CONFIG_SETTING_MAX_SHIPS,                           RedrawScreen),
+   SDTG_CONDBOOL(NULL, 0, NN, _old_vds.servint_ispercent, false, STR_NULL, NULL, 0, 119),
+	SDTG_CONDVAR(NULL, SLE_UINT16, 0, D0, _old_vds.servint_trains, 150, 5, 800, 0, STR_NULL, NULL, 0, 119),
+	SDTG_CONDVAR(NULL, SLE_UINT16, 0, D0, _old_vds.servint_roadveh, 150, 5, 800, 0, STR_NULL, NULL, 0, 119),
+	SDTG_CONDVAR(NULL, SLE_UINT16, 0, D0, _old_vds.servint_ships, 360, 5, 800, 0, STR_NULL, NULL, 0, 119),
+	SDTG_CONDVAR(NULL, SLE_UINT16, 0, D0, _old_vds.servint_aircraft, 150, 5, 800, 0, STR_NULL, NULL, 0, 119),
+	    SDT_BOOL(GameSettings, order.no_servicing_if_no_breakdowns,                                                                                                                     0, 0,     true,                                                                                    STR_CONFIG_SETTING_NOSERVICE,                           NULL),
+	    SDT_BOOL(GameSettings, vehicle.wagon_speed_limits,                                                                                                                              0, NN,    true,                                                                                    STR_CONFIG_SETTING_WAGONSPEEDLIMITS,                    UpdateConsists),
+	SDT_CONDBOOL(GameSettings, vehicle.disable_elrails,                                                   38,                                    SL_MAX_VERSION,                        0, NN,    false,                                                                                   STR_CONFIG_SETTING_DISABLE_ELRAILS,                     SettingsDisableElrail),
+	 SDT_CONDVAR(GameSettings, vehicle.freight_trains,                         SLE_UINT8,                 39,                                    SL_MAX_VERSION,                        0, NN,    1,                             1,                  255,                           1,     STR_CONFIG_SETTING_FREIGHT_TRAINS,                      UpdateConsists),
+	 SDT_CONDVAR(GUISettings,  ticks_per_minute,                               SLE_UINT8,                 KEEP_COMPATIBLE_20_SV,                 SL_MAX_VERSION,                        0, 0,     74,                            1,                  255,                           1,     STR_CONFIG_SETTING_TICKS_PER_MINUTE,                    InvalidateVehTimetableWindow),
+	SDT_CONDBOOL(GameSettings, order.timetabling,                                                         67,                                    SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_TIMETABLE_ALLOW,                     NULL),
+	SDT_CONDBOOL(GameSettings, order.timetable_automated,                                                 TIMESEP_SV,                            SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_TIMETABLE_AUTOMATED,                 NULL),
+	SDT_CONDBOOL(GameSettings, order.timetable_separation,                                                TIMESEP_SV,                            SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_TIMETABLE_SEPARATION,                NULL),
+	 SDT_CONDVAR(GameSettings, vehicle.plane_speed,                            SLE_UINT8,                 90,                                    SL_MAX_VERSION,                        0, NN,    4,                             1,                  4,                             0,     STR_CONFIG_SETTING_PLANE_SPEED,                         NULL),
+	SDT_CONDBOOL(GameSettings, vehicle.dynamic_engines,                                                   95,                                    SL_MAX_VERSION,                        0, NN,    true,                                                                                    STR_CONFIG_SETTING_DYNAMIC_ENGINES,                     ChangeDynamicEngines),
+	 SDT_CONDVAR(GameSettings, vehicle.plane_crashes,                          SLE_UINT8,                 138,                                   SL_MAX_VERSION,                        0, MS,    2,                             0,                  2,                             1,     STR_CONFIG_SETTING_PLANE_CRASHES,                       NULL),
+    SDT_CONDBOOL(GameSettings, vehicle.improved_breakdowns,		                                          SL_IB,                                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_IMPROVED_BREAKDOWNS,                 NULL),
+
+	SDT_CONDNULL(1, 0, 158), // station.join_stations
+	SDT_CONDNULL(1, BEFORE_ADDING_PATCHES_SL, KEEP_COMPATIBLE_16_SV), // station.join_stations
+   SDTC_CONDBOOL(              gui.sg_full_load_any,                                                      22,                                    92,                                    0, 0,     true,                                                                                    STR_NULL,                                               NULL),
+	    SDT_BOOL(GameSettings, order.improved_load,                                                                                                                                     0, NN,    true,                                                                                    STR_CONFIG_SETTING_IMPROVEDLOAD,                        NULL),
+	    SDT_BOOL(GameSettings, order.selectgoods,                                                                                                                                       0, 0,     true,                                                                                    STR_CONFIG_SETTING_SELECTGOODS,                         NULL),
+   SDTC_CONDBOOL(              gui.sg_new_nonstop,                                                        22,                                    92,                                    0, 0,     false,                                                                                   STR_NULL,                                               NULL),
+	SDT_CONDNULL(1, 0, 158), // station.nonuniform_stations
+	SDT_CONDNULL(1, BEFORE_ADDING_PATCHES_SL, KEEP_COMPATIBLE_16_SV), // station.nonuniform_stations
+	     SDT_VAR(GameSettings, station.station_spread,                         SLE_UINT8,                                                                                               0, 0,     12,                            4,                  64,                            0,     STR_CONFIG_SETTING_STATION_SPREAD,                      InvalidateStationBuildWindow),
+	    SDT_BOOL(GameSettings, order.serviceathelipad,                                                                                                                                  0, 0,     true,                                                                                    STR_CONFIG_SETTING_SERVICEATHELIPAD,                    NULL),
+	    SDT_BOOL(GameSettings, station.modified_catchment,                                                                                                                              0, 0,     true,                                                                                    STR_CONFIG_SETTING_CATCHMENT,                           StationCatchmentChanged),
+	SDT_CONDBOOL(GameSettings, order.gradual_loading,                                                     40,                                    SL_MAX_VERSION,                        0, NN,    true,                                                                                    STR_CONFIG_SETTING_GRADUAL_LOADING,                     NULL),
+	SDT_CONDBOOL(GameSettings, construction.road_stop_on_town_road,                                       47,                                    SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD,                   NULL),
+	SDT_CONDBOOL(GameSettings, construction.road_stop_on_competitor_road,                                 114,                                   SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD,             NULL),
+	SDT_CONDBOOL(GameSettings, station.adjacent_stations,                                                 62,                                    SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_ADJACENT_STATIONS,                   NULL),
+	SDT_CONDBOOL(GameSettings, economy.station_noise_level,                                               96,                                    SL_MAX_VERSION,                        0, NN,    false,                                                                                   STR_CONFIG_SETTING_NOISE_LEVEL,                         InvalidateTownViewWindow),
+	SDT_CONDBOOL(GameSettings, station.distant_join_stations,                                             106,                                   SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS,               DeleteSelectStationWindow),
+
+	    SDT_BOOL(GameSettings, economy.inflation,                                                                                                                                       0, 0,     true,                                                                                    STR_CONFIG_SETTING_INFLATION,                           NULL),
+	     SDT_VAR(GameSettings, construction.raw_industry_construction,         SLE_UINT8,                                                                                               0, MS,    0,                            0,                   2,                             0,     STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD,    InvalidateBuildIndustryWindow),
+	 SDT_CONDVAR(GameSettings, construction.industry_platform,                 SLE_UINT8,                 148,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     1,                            0,                   4,                             0,     STR_CONFIG_SETTING_INDUSTRY_PLATFORM,                   NULL),
+	 SDT_CONDVAR(GameSettings, construction.industry_platform,                 SLE_UINT8,                 KEEP_COMPATIBLE_2_SV,                  SL_MAX_VERSION,                        0, 0,     1,                            0,                   4,                             0,     STR_CONFIG_SETTING_INDUSTRY_PLATFORM,                   NULL),
+	    SDT_BOOL(GameSettings, economy.multiple_industry_per_town,                                                                                                                      0, 0,     false,                                                                                   STR_CONFIG_SETTING_MULTIPINDTOWN,                       NULL),
+	 SDT_CONDVAR(GameSettings, construction.extra_industry_placement_logic,    SLE_UINT8,                 KEEP_COMPATIBLE_23_SV,                 SL_MAX_VERSION,                        0, NN,    60,                           1,                   255,                           1,     STR_CONFIG_SETTING_EXTRA_INDUSTRY_PLACEMENT_LOGIC,      NULL),
+	SDT_CONDNULL(1, 0, 140),
+	    SDT_BOOL(GameSettings, economy.bribe,                                                                                                                                           0, 0,     true,                                                                                    STR_CONFIG_SETTING_BRIBE,                               RedrawTownAuthority),
+	SDT_CONDBOOL(GameSettings, economy.exclusive_rights,                                                  79,                                    SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_ALLOW_EXCLUSIVE,                     RedrawTownAuthority),
+	SDT_CONDBOOL(GameSettings, economy.fund_roads,                                                        160,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     true,                                                                                    STR_CONFIG_SETTING_ALLOW_FUND_ROAD,                     RedrawTownAuthority),
+	SDT_CONDBOOL(GameSettings, economy.fund_roads,                                                        KEEP_COMPATIBLE_18_SV,                 SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_ALLOW_FUND_ROAD,                     RedrawTownAuthority),
+	SDT_CONDBOOL(GameSettings, economy.give_money,                                                        79,                                    SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_ALLOW_GIVE_MONEY,                    NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.snow_line_height,                 SLE_FILE_U8 | SLE_VAR_U16, 0,                                     MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, 0,     DEF_SNOWLINE_HEIGHT_OLD,      MIN_SNOWLINE_HEIGHT, MAX_SNOWLINE_HEIGHT_OLD,       0,     STR_CONFIG_SETTING_SNOWLINE_HEIGHT,                     NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.snow_line_height,                 SLE_UINT16,                MORE_HEIGHTLEVEL_SAVEGAME_VERSION,     SL_MAX_VERSION,                        0, 0,     DEF_SNOWLINE_HEIGHT_EXTENDED, MIN_SNOWLINE_HEIGHT, MAX_SNOWLINE_HEIGHT_EXTENDED,  0,     STR_CONFIG_SETTING_SNOWLINE_HEIGHT,                     NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.desert_amount,                    SLE_UINT8,                 DESERT_SV,                             SL_MAX_VERSION,                        0, NN,    DEF_DESERT_AMOUNT,            MIN_DESERT_AMOUNT,   MAX_DESERT_AMOUNT,             0,     STR_CONFIG_SETTING_DESERT_AMOUNT,                       NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.tree_line_height,                 SLE_FILE_U8 | SLE_VAR_U16, MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 2, MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, 0,     DEF_TREELINE_HEIGHT_OLD,      MIN_TREELINE_HEIGHT, MAX_TREELINE_HEIGHT_OLD,       0,     STR_CONFIG_SETTING_TREELINE_HEIGHT,                     NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.tree_line_height,                 SLE_UINT16,                MORE_HEIGHTLEVEL_SAVEGAME_VERSION,     SL_MAX_VERSION,                        0, 0,     DEF_TREELINE_HEIGHT_EXTENDED, MIN_TREELINE_HEIGHT, MAX_TREELINE_HEIGHT_EXTENDED,  0,     STR_CONFIG_SETTING_TREELINE_HEIGHT,                     NULL),
+	SDT_CONDNULL(4, 0, 143),
+	     SDT_VAR(GameSettings, game_creation.starting_year,                    SLE_INT32,                                                                                               0, NC,    DEF_START_YEAR,               MIN_YEAR,            MAX_YEAR,                      1,     STR_CONFIG_SETTING_STARTING_YEAR,                       NULL),
+	SDT_CONDNULL(4, 0, 104),
+	    SDT_BOOL(GameSettings, economy.smooth_economy,                                                                                                                                  0, 0,     true,                                                                                    STR_CONFIG_SETTING_SMOOTH_ECONOMY,                      InvalidateIndustryViewWindow),
+	    SDT_BOOL(GameSettings, economy.allow_shares,                                                                                                                                    0, 0,     false,                                                                                   STR_CONFIG_SETTING_ALLOW_SHARES,                        NULL),
+	 SDT_CONDVAR(GameSettings, economy.feeder_payment_share,                   SLE_UINT8,                 134,                                   SL_MAX_VERSION,                        0, 0,     75,                           0,                    100,                          0,     STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE,                NULL),
+	 SDT_CONDVAR(GameSettings, economy.town_growth_rate,                       SLE_UINT8,                 54,                                    SL_MAX_VERSION,                        0, MS,    2,                            0,                    4,                            0,     STR_CONFIG_SETTING_TOWN_GROWTH,                         NULL),
+	 SDT_CONDVAR(GameSettings, economy.larger_towns,                           SLE_UINT8,                 54,                                    SL_MAX_VERSION,                        0, D0,    4,                            0,                    255,                          1,     STR_CONFIG_SETTING_LARGER_TOWNS,                        NULL),
+	 SDT_CONDVAR(GameSettings, economy.initial_city_size,                      SLE_UINT8,                 56,                                    SL_MAX_VERSION,                        0, 0,     2,                            1,                    10,                           1,     STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER,                NULL),
+	 SDT_CONDVAR(GameSettings, economy.town_growth_cargo,                      SLE_UINT8,                 TOWN_GROWTH_SV,                        SL_MAX_VERSION,                        0, MS,    0,                            0,                    6,                            1,     STR_CONFIG_SETTING_TOWN_GROWTH_CARGO,                   InvalidateTownViewWindow),
+	 SDT_CONDVAR(GameSettings, economy.town_pop_need_goods,                    SLE_UINT32,                TOWN_GROWTH_SV,                        SL_MAX_VERSION,                        0, 0,     4500,                         500,                  20000,                        500,   STR_CONFIG_SETTING_TOWN_GROWTH_MAX_POP_WO_GOODS,        InvalidateTownViewWindow),
+	 SDT_CONDVAR(GameSettings, economy.larger_town_growth_cargo,               SLE_UINT8,                 KEEP_COMPATIBLE_21_SV,                 SL_MAX_VERSION,                        0, MS,    0,                            0,                    6,                            1,     STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_CARGO,            InvalidateTownViewWindow),
+	 SDT_CONDVAR(GameSettings, economy.larger_town_pop_need_goods,             SLE_UINT32,                KEEP_COMPATIBLE_21_SV,                 SL_MAX_VERSION,                        0, 0,     9000,                         500,                  20000,                        500,   STR_CONFIG_SETTING_LARGER_TOWN_GROWTH_MAX_POP_WO_GOODS, InvalidateTownViewWindow),
+	SDT_CONDBOOL(GameSettings, economy.mod_road_rebuild,                                                  77,                                    SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_MODIFIED_ROAD_REBUILD,               NULL),
+	 SDT_CONDVAR(GameSettings, construction.maximum_signal_evaluations,        SLE_UINT16,                PROG_SIGS_SL,                          SL_MAX_VERSION,                        0, 0,     256,                          64,                   4096,                         1,     STR_CONFIG_SETTING_MAX_SIGNAL_EVALUATIONS,              NULL),
+
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[0],                                         IS_SL,                                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_SHARING_RAIL,                        CheckSharingRail),
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[1],                                         IS_SL,                                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_SHARING_ROAD,                        CheckSharingRoad),
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[2],                                         IS_SL,                                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_SHARING_WATER,                       CheckSharingWater),
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[3],                                         IS_SL,                                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_SHARING_AIR,                         CheckSharingAir),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[0],                         SLE_UINT,                  IS_SL,                                 SL_MAX_VERSION,                        0, CR,    100,                          0,                    1000000,                      10,    STR_CONFIG_SETTING_SHARING_FEE_RAIL,                    NULL),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[1],                         SLE_UINT,                  IS_SL,                                 SL_MAX_VERSION,                        0, CR,    100,                          0,                    1000000,                      10,    STR_CONFIG_SETTING_SHARING_FEE_ROAD,                    NULL),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[2],                         SLE_UINT,                  IS_SL,                                 SL_MAX_VERSION,                        0, CR,    100,                          0,                    1000000,                      10,    STR_CONFIG_SETTING_SHARING_FEE_WATER,                   NULL),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[3],                         SLE_UINT,                  IS_SL,                                 SL_MAX_VERSION,                        0, CR,    100,                          0,                    1000000,                      10,    STR_CONFIG_SETTING_SHARING_FEE_AIR,                     NULL),
+	SDT_CONDBOOL(GameSettings, economy.sharing_payment_in_debt,                                           IS_SL,                                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT,             NULL),
+
+	SDT_CONDNULL(1, 0, 106), // previously ai-new setting.
+	    SDT_BOOL(GameSettings, ai.ai_in_multiplayer,                                                                                                                                    0, 0,     true,                                                                                    STR_CONFIG_SETTING_AI_IN_MULTIPLAYER,                   NULL),
+	    SDT_BOOL(GameSettings, ai.ai_disable_veh_train,                                                                                                                                 0, 0,     false,                                                                                   STR_CONFIG_SETTING_AI_BUILDS_TRAINS,                    NULL),
+	    SDT_BOOL(GameSettings, ai.ai_disable_veh_roadveh,                                                                                                                               0, 0,     false,                                                                                   STR_CONFIG_SETTING_AI_BUILDS_ROAD_VEHICLES,             NULL),
+	    SDT_BOOL(GameSettings, ai.ai_disable_veh_aircraft,                                                                                                                              0, 0,     false,                                                                                   STR_CONFIG_SETTING_AI_BUILDS_AIRCRAFT,                  NULL),
+	    SDT_BOOL(GameSettings, ai.ai_disable_veh_ship,                                                                                                                                  0, 0,     false,                                                                                   STR_CONFIG_SETTING_AI_BUILDS_SHIPS,                     NULL),
+	 SDT_CONDVAR(GameSettings, ai.ai_max_opcode_till_suspend,                  SLE_UINT32,                107,                                   SL_MAX_VERSION,                        0, NG,    10000,                       5000,                  250000,                       2500,  STR_CONFIG_SETTING_AI_MAX_OPCODES,                      NULL),
+
+	     SDT_VAR(GameSettings, vehicle.extend_vehicle_life,                    SLE_UINT8,                                                                                               0, 0,     0,                           0,                     100,                          0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, economy.dist_local_authority,                   SLE_UINT8,                                                                                               0, 0,     20,                          5,                     60,                           0,     STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, pf.reverse_at_signals,                                                     159,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     false,                                                                                   STR_CONFIG_SETTING_REVERSE_AT_SIGNALS,                  NULL),
+	SDT_CONDBOOL(GameSettings, pf.reverse_at_signals,                                                     KEEP_COMPATIBLE_17_SV,                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_REVERSE_AT_SIGNALS,                  NULL),
+	     SDT_VAR(GameSettings, pf.wait_oneway_signal,                          SLE_UINT8,                                                                                               0, 0,     15,                          2,                     255,                          0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.wait_twoway_signal,                          SLE_UINT8,                                                                                               0, 0,     41,                          2,                     255,                          0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, economy.town_noise_population[0],               SLE_UINT16,                96,                                    SL_MAX_VERSION,                        0, 0,     800,                         200,                   65535,                        0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, economy.town_noise_population[1],               SLE_UINT16,                96,                                    SL_MAX_VERSION,                        0, 0,     2000,                        400,                   65535,                        0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, economy.town_noise_population[2],               SLE_UINT16,                96,                                    SL_MAX_VERSION,                        0, 0,     4000,                        800,                   65535,                        0,     STR_NULL,                                               NULL),
+
+	SDT_CONDBOOL(GameSettings, construction.traffic_lights,                                               TL_SV,                                 SL_MAX_VERSION,                        0, NN,     true,                                                                                   STR_CONFIG_SETTING_TRAFFIC_LIGHTS,                      TLSettingChanged),
+	SDT_CONDBOOL(GameSettings, construction.towns_build_traffic_lights,                                   TL_SV,                                 SL_MAX_VERSION,                        0, NN,     true,                                                                                   STR_CONFIG_SETTING_TOWNS_BUILD_TRAFFIC_LIGHTS,          NULL),
+	SDT_CONDBOOL(GameSettings, construction.allow_building_tls_in_towns,                                  TL_SV,                                 SL_MAX_VERSION,                        0, NN,     false,                                                                                  STR_CONFIG_SETTING_ALLOW_BUILDING_TLS_ON_TOWN_ROADS,    NULL),
+	 SDT_CONDVAR(GameSettings, construction.traffic_lights_green_phase,        SLE_UINT8,                 TL_SV,                                 SL_MAX_VERSION,                        0, NN,     2,                           1,                     16,                          1,     STR_CONFIG_SETTING_TRAFFIC_LIGHTS_GREEN_PHASE,          NULL),
+	 SDT_CONDVAR(GameSettings, construction.max_tlc_size,                      SLE_UINT8,                 TL_SV,                                 SL_MAX_VERSION,                        0, NN,     4,                           1,                     32,                          0,     STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_SIZE,      NULL),
+	 SDT_CONDVAR(GameSettings, construction.max_tlc_distance,                  SLE_UINT8,                 KEEP_COMPATIBLE_24_SV,                 SL_MAX_VERSION,                        0, NN,     1,                           0,                     4,                           0,     STR_CONFIG_SETTING_MAX_TRAFFIC_LIGHT_CONSIST_DISTANCE,  NULL),
+
+	 SDT_CONDVAR(GameSettings, linkgraph.recalc_interval,                      SLE_UINT16,                SL_COMPONENTS,                         SL_MAX_VERSION,                        0, 0,     16,                          1,                     4096,                         1,     STR_CONFIG_SETTING_LINKGRAPH_INTERVAL,                  NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.distribution_pax,                     SLE_UINT8,                 SL_COMPONENTS,                         SL_MAX_VERSION,                        0, MS,    DT_SYMMETRIC,                DT_BEGIN,              DT_NUM - 1,                   1,     STR_CONFIG_SETTING_DISTRIBUTION_PAX,                    NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.distribution_mail,                    SLE_UINT8,                 SL_COMPONENTS,                         SL_MAX_VERSION,                        0, MS,    DT_SYMMETRIC,                DT_BEGIN,              DT_NUM - 1,                   1,     STR_CONFIG_SETTING_DISTRIBUTION_MAIL,                   NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.distribution_express,                 SLE_UINT8,                 SL_COMPONENTS,                         SL_MAX_VERSION,                        0, MS,    DT_ASYMMETRIC,               DT_BEGIN,              DT_NUM - 1,                   1,     STR_CONFIG_SETTING_DISTRIBUTION_EXPRESS,                NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.distribution_armoured,                SLE_UINT8,                 SL_COMPONENTS,                         SL_MAX_VERSION,                        0, MS,    DT_ASYMMETRIC,               DT_BEGIN,              DT_NUM - 1,                   1,     STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED,               NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.distribution_default,                 SLE_UINT8,                 SL_COMPONENTS,                         SL_MAX_VERSION,                        0, MS,    DT_ASYMMETRIC,               DT_BEGIN,              DT_NUM - 1,                   1,     STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT,                NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.accuracy,                             SLE_UINT8,                 SL_DEMANDS,                            SL_MAX_VERSION,                        0, 0,     16,                          2,                     64,                           1,     STR_CONFIG_SETTING_LINKGRAPH_ACCURACY,                  NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.demand_distance,                      SLE_UINT8,                 SL_DEMANDS,                            SL_MAX_VERSION,                        0, 0,     90,                          0,                     255,                          5,     STR_CONFIG_SETTING_DEMAND_DISTANCE,                     NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.demand_size,                          SLE_UINT8,                 SL_DEMANDS,                            SL_MAX_VERSION,                        0, 0,     90,                          0,                     100,                          5,     STR_CONFIG_SETTING_DEMAND_SIZE,                         NULL),
+	 SDT_CONDVAR(GameSettings, linkgraph.short_path_saturation,                SLE_UINT8,                 SL_MCF,                                SL_MAX_VERSION,                        0, 0,     80,                          0,                     250,                          5,     STR_CONFIG_SETTING_SHORT_PATH_SATURATION,               NULL),
+ 	SDT_CONDBOOL(GameSettings, linkgraph.no_overload_links,                                               KEEP_COMPATIBLE_22_SV,                 SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_CONFIG_SETTING_NO_OVERLOAD_LINKS,                   NULL),
+
+	 SDT_CONDVAR(GameSettings, pf.wait_for_pbs_path,                           SLE_UINT8,                 100,                                   SL_MAX_VERSION,                        0, 0,     30,                          2,                     255,                          0,     STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, pf.reserve_paths,                                                          100,                                   SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.path_backoff_interval,                       SLE_UINT8,                 100,                                   SL_MAX_VERSION,                        0, 0,     20,                          1,                     255,                          0,     STR_NULL,                                               NULL),
+
+	     SDT_VAR(GameSettings, pf.opf.pf_maxlength,                            SLE_UINT16,                                                                                              0, 0,     4096,                        64,                    65535,                        0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.opf.pf_maxdepth,                             SLE_UINT8,                                                                                               0, 0,     48,                          4,                     255,                          0,     STR_NULL,                                               NULL),
+
+	     SDT_VAR(GameSettings, pf.npf.npf_max_search_nodes,                    SLE_UINT,                                                                                                0, 0,     10000,                       500,                   100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_rail_firstred_penalty,               SLE_UINT,                                                                                                0, 0,     10 * NPF_TILE_LENGTH,        0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_rail_firstred_exit_penalty,          SLE_UINT,                                                                                                0, 0,     100 * NPF_TILE_LENGTH,       0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_rail_lastred_penalty,                SLE_UINT,                                                                                                0, 0,     10 * NPF_TILE_LENGTH,        0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_rail_station_penalty,                SLE_UINT,                                                                                                0, 0,     1 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_rail_slope_penalty,                  SLE_UINT,                                                                                                0, 0,     1 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_rail_curve_penalty,                  SLE_UINT,                                                                                                0, 0,     1 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_rail_depot_reverse_penalty,          SLE_UINT,                                                                                                0, 0,     50 * NPF_TILE_LENGTH,        0,                     100000,                       0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.npf.npf_rail_pbs_cross_penalty,              SLE_UINT,                  100,                                   SL_MAX_VERSION,                        0, 0,     3 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.npf.npf_rail_pbs_signal_back_penalty,        SLE_UINT,                  100,                                   SL_MAX_VERSION,                        0, 0,     15 * NPF_TILE_LENGTH,        0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_buoy_penalty,                        SLE_UINT,                                                                                                0, 0,     2 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_water_curve_penalty,                 SLE_UINT,                                                                                                0, 0,     1 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_road_curve_penalty,                  SLE_UINT,                                                                                                0, 0,     1 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, pf.npf.npf_crossing_penalty,                    SLE_UINT,                                                                                                0, 0,     3 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.npf.npf_road_drive_through_penalty,          SLE_UINT,                  47,                                    SL_MAX_VERSION,                        0, 0,     8 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.npf.npf_road_trafficlight_penalty,           SLE_UINT,                  TL_SV,                                 SL_MAX_VERSION,                        0, 0,     2 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.npf.npf_road_dt_occupied_penalty,            SLE_UINT,                  130,                                   SL_MAX_VERSION,                        0, 0,     8 * NPF_TILE_LENGTH,         0,                     100000,                       0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.npf.npf_road_bay_occupied_penalty,           SLE_UINT,                  130,                                   SL_MAX_VERSION,                        0, 0,     15 * NPF_TILE_LENGTH,        0,                     100000,                       0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.npf.maximum_go_to_depot_penalty,             SLE_UINT,                  131,                                   SL_MAX_VERSION,                        0, 0,     20 * NPF_TILE_LENGTH,        0,                     1000000,                      0,     STR_NULL,                                               NULL),
+
+	SDT_CONDBOOL(GameSettings, pf.yapf.disable_node_optimization,                                         28,                                    SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.max_search_nodes,                       SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     10000,                       500,                   1000000,                      0,     STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, pf.yapf.rail_firstred_twoway_eol,                                          28,                                    SL_MAX_VERSION,                        0, 0,     false,                                                                                   STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_firstred_penalty,                  SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     10 * YAPF_TILE_LENGTH,        0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_firstred_exit_penalty,             SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     100 * YAPF_TILE_LENGTH,       0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_lastred_penalty,                   SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     10 * YAPF_TILE_LENGTH,        0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_lastred_exit_penalty,              SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     100 * YAPF_TILE_LENGTH,       0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_station_penalty,                   SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     10 * YAPF_TILE_LENGTH,        0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_slope_penalty,                     SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     2 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_curve45_penalty,                   SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     1 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_curve90_penalty,                   SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     6 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_depot_reverse_penalty,             SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     50 * YAPF_TILE_LENGTH,        0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_crossing_penalty,                  SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     3 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_look_ahead_max_signals,            SLE_UINT,                  28,                                    SL_MAX_VERSION,                        0, 0,     10,                           1,                    100,                          0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_look_ahead_signal_p0,              SLE_INT,                   28,                                    SL_MAX_VERSION,                        0, 0,     500,                          -1000000,             1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_look_ahead_signal_p1,              SLE_INT,                   28,                                    SL_MAX_VERSION,                        0, 0,     -100,                         -1000000,             1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_look_ahead_signal_p2,              SLE_INT,                   28,                                    SL_MAX_VERSION,                        0, 0,     5,                            -1000000,             1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_pbs_cross_penalty,                 SLE_UINT,                  100,                                   SL_MAX_VERSION,                        0, 0,     3 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_pbs_station_penalty,               SLE_UINT,                  100,                                   SL_MAX_VERSION,                        0, 0,     8 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_pbs_signal_back_penalty,           SLE_UINT,                  100,                                   SL_MAX_VERSION,                        0, 0,     15 * YAPF_TILE_LENGTH,        0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_doubleslip_penalty,                SLE_UINT,                  100,                                   SL_MAX_VERSION,                        0, 0,     1 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_longer_platform_penalty,           SLE_UINT,                  33,                                    SL_MAX_VERSION,                        0, 0,     8 * YAPF_TILE_LENGTH,         0,                    20000,                        0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_longer_platform_per_tile_penalty,  SLE_UINT,                  33,                                    SL_MAX_VERSION,                        0, 0,     0 * YAPF_TILE_LENGTH,         0,                    20000,                        0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_shorter_platform_penalty,          SLE_UINT,                  33,                                    SL_MAX_VERSION,                        0, 0,     40 * YAPF_TILE_LENGTH,        0,                    20000,                        0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT,                  33,                                    SL_MAX_VERSION,                        0, 0,     0 * YAPF_TILE_LENGTH,         0,                    20000,                        0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.road_slope_penalty,                     SLE_UINT,                  33,                                    SL_MAX_VERSION,                        0, 0,     2 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.road_curve_penalty,                     SLE_UINT,                  33,                                    SL_MAX_VERSION,                        0, 0,     1 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.road_crossing_penalty,                  SLE_UINT,                  33,                                    SL_MAX_VERSION,                        0, 0,     3 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.road_trafficlight_penalty,              SLE_UINT,                  TL_SV,                                 SL_MAX_VERSION,                        0, 0,     2 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.road_stop_penalty,                      SLE_UINT,                  47,                                    SL_MAX_VERSION,                        0, 0,     8 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.road_stop_occupied_penalty,             SLE_UINT,                  130,                                   SL_MAX_VERSION,                        0, 0,     8 * YAPF_TILE_LENGTH,         0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.road_stop_bay_occupied_penalty,         SLE_UINT,                  130,                                   SL_MAX_VERSION,                        0, 0,     15 * YAPF_TILE_LENGTH,        0,                    1000000,                      0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.maximum_go_to_depot_penalty,            SLE_UINT,                  131,                                   SL_MAX_VERSION,                        0, 0,     20 * YAPF_TILE_LENGTH,        0,                    1000000,                      0,     STR_NULL,                                               NULL),
+
+	 SDT_CONDVAR(GameSettings, game_creation.land_generator,                   SLE_UINT8,                 30,                                    SL_MAX_VERSION,                        0, MS,    1,                            0,                    1,                            0,     STR_CONFIG_SETTING_LAND_GENERATOR,                      NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.oil_refinery_limit,               SLE_UINT8,                 30,                                    SL_MAX_VERSION,                        0, 0,     32,                           12,                   48,                           0,     STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE,               NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.tgen_smoothness,                  SLE_FILE_U8 | SLE_VAR_U8,  30,                                    MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, 0, MS,    1,                            0,                    3,                            0,     STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN,                NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.tgen_smoothness,                  SLE_UINT8,                 MORE_HEIGHTLEVEL_SAVEGAME_VERSION,     SL_MAX_VERSION,                        0, MS,    1,                            0,                    6,                            0,     STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN,                NULL),
+	     SDT_VAR(GameSettings, game_creation.variety,                          SLE_UINT8,                                                                                               S, 0,     0,                            0,                    5,                            0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.generation_seed,                  SLE_UINT32,                30,                                    SL_MAX_VERSION,                        0, 0,     GENERATE_NEW_SEED,            0,                    UINT32_MAX,                   0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.tree_placer,                      SLE_UINT8,                 30,                                    SL_MAX_VERSION,                        0, MS,    2,                            0,                    2,                            0,     STR_CONFIG_SETTING_TREE_PLACER,                         NULL),
+	     SDT_VAR(GameSettings, game_creation.heightmap_rotation,               SLE_UINT8,                                                                                               S, MS,    0,                            0,                    1,                            0,     STR_CONFIG_SETTING_HEIGHTMAP_ROTATION,                  NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.se_flat_world_height,             SLE_FILE_U8 | SLE_VAR_U32, 0,                                     MORE_HEIGHTLEVEL_SAVEGAME_VERSION - 1, S, 0,     1,                            0,                    15,                           0,     STR_CONFIG_SETTING_SE_FLAT_WORLD_HEIGHT,                NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.se_flat_world_height,             SLE_UINT32,                MORE_HEIGHTLEVEL_SAVEGAME_VERSION,     SL_MAX_VERSION,                        S, 0,     1,                            0,                    255,                          0,     STR_CONFIG_SETTING_SE_FLAT_WORLD_HEIGHT,                NULL),
+
+	     SDT_VAR(GameSettings, game_creation.map_x,                            SLE_UINT8,                                                                                               S, 0,     8,                            MIN_MAP_SIZE_BITS,    MAX_MAP_SIZE_BITS,            0,     STR_NULL,                                               NULL),
+	     SDT_VAR(GameSettings, game_creation.map_y,                            SLE_UINT8,                                                                                               S, 0,     8,                            MIN_MAP_SIZE_BITS,    MAX_MAP_SIZE_BITS,            0,     STR_NULL,                                               NULL),
+	SDT_CONDBOOL(GameSettings, construction.freeform_edges,                                               111,                                   SL_MAX_VERSION,                        0, 0,     true,                                                                                    STR_CONFIG_SETTING_ENABLE_FREEFORM_EDGES,               CheckFreeformEdges),
+	 SDT_CONDVAR(GameSettings, game_creation.water_borders,                    SLE_UINT8,                 111,                                   SL_MAX_VERSION,                        0, 0,     15,                           0,                    16,                           0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.custom_town_number,               SLE_UINT16,                115,                                   SL_MAX_VERSION,                        0, 0,     1,                            1,                    5000,                         0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, construction.extra_tree_placement,              SLE_UINT8,                 132,                                   SL_MAX_VERSION,                        0, MS,    2,                            0,                    2,                            0,     STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT,                NULL),
+	 SDT_CONDVAR(GameSettings, construction.tree_placement_drag_limit,         SLE_UINT8,                 TREEDRAG_SV,                           SL_MAX_VERSION,                        0, 0,    20,                           20,                   128,                          0,     STR_CONFIG_SETTING_TREE_PLACEMENT_DRAG_LIMIT,           NULL),
+	 SDT_CONDVAR(GameSettings, construction.ingame_tree_line_height,           SLE_UINT8,                 INGAME_TREELINE_SV,                    SL_MAX_VERSION,                        0, 0,     DEF_TREELINE_HEIGHT_EXTENDED, MIN_TREELINE_HEIGHT,  MAX_TREELINE_HEIGHT_EXTENDED, 0,     STR_CONFIG_SETTING_INGAME_TREELINE_HEIGHT,              NULL),
+	 SDT_CONDVAR(GameSettings, construction.tree_growth_rate,                  SLE_UINT8,                 TREE_GROWTH_RATE_SL,                   SL_MAX_VERSION,                        0, MS,    0,                            0,                    3,                            1,     STR_CONFIG_SETTING_TREE_GROWTH,                         NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.custom_sea_level,                 SLE_UINT8,                 149,                                   BEFORE_ADDING_PATCHES_SL,              0, 0,     1,                            2,                    90,                           0,     STR_NULL,                                               NULL),
+	 SDT_CONDVAR(GameSettings, game_creation.custom_sea_level,                 SLE_UINT8,                 KEEP_COMPATIBLE_4_SV,                  SL_MAX_VERSION,                        0, 0,     1,                            2,                    90,                           0,     STR_NULL,                                               NULL),
+
+   SDT_CONDOMANY(GameSettings, locale.currency,                                SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        N, 0,     0,                            CUSTOM_CURRENCY_ID,  _locale_currencies,                   STR_NULL, RedrawScreen,                                 NULL),
+   SDT_CONDOMANY(GameSettings, locale.units,                                   SLE_UINT8,                 97,                                    SL_MAX_VERSION,                        N, 0,     1,                            2, _locale_units,                                          STR_NULL, RedrawScreen,                                 NULL),
+	 SDT_CONDSTR(GameSettings, locale.digit_group_separator,                   SLE_STRQ,                  118,                                   SL_MAX_VERSION,                        N, 0,     NULL,                                                                                    STR_NULL, RedrawScreen),
+	 SDT_CONDSTR(GameSettings, locale.digit_group_separator_currency,          SLE_STRQ,                  118,                                   SL_MAX_VERSION,                        N, 0,     NULL,                                                                                    STR_NULL, RedrawScreen),
+	 SDT_CONDSTR(GameSettings, locale.digit_decimal_separator,                 SLE_STRQ,                  126,                                   SL_MAX_VERSION,                        N, 0,     NULL,                                                                                    STR_NULL, RedrawScreen),
+
+	/***************************************************************************/
+	/* Unsaved setting variables. */
+	 SDTC_OMANY(gui.autosave,                      SLE_UINT8,  S, 0,        3,                    6,   _autosave_interval,    STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.threaded_saves,                            S, 0,        true,                                             STR_NULL,                                            NULL),
+	 SDTC_OMANY(gui.date_format_in_default_names,  SLE_UINT8,  S, MS,       0,                    2,   _savegame_date,        STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES,        NULL),
+	  SDTC_BOOL(gui.vehicle_speed,                             S, 0,        true,                                             STR_CONFIG_SETTING_VEHICLESPEED,                     NULL),
+	  SDTC_BOOL(gui.show_finances,                             S, 0,        true,                                             STR_CONFIG_SETTING_SHOWFINANCES,                     NULL),
+	  SDTC_BOOL(gui.autoscroll,                                S, 0,        false,                                            STR_CONFIG_SETTING_AUTOSCROLL,                       NULL),
+	  SDTC_BOOL(gui.reverse_scroll,                            S, 0,        false,                                            STR_CONFIG_SETTING_REVERSE_SCROLLING,                NULL),
+	  SDTC_BOOL(gui.smooth_scroll,                             S, 0,        false,                                            STR_CONFIG_SETTING_SMOOTH_SCROLLING,                 NULL),
+	  SDTC_BOOL(gui.left_mouse_btn_scrolling,                  S, 0,        false,                                            STR_CONFIG_SETTING_LEFT_MOUSE_BTN_SCROLLING,         NULL),
+	  SDTC_BOOL(gui.measure_tooltip,                           S, 0,        true,                                             STR_CONFIG_SETTING_MEASURE_TOOLTIP,                  NULL),
+	   SDTC_VAR(gui.errmsg_duration,               SLE_UINT8,  S, 0,        5,                    0,        20,            0, STR_CONFIG_SETTING_ERRMSG_DURATION,                  NULL),
+	   SDTC_VAR(gui.hover_delay,                   SLE_UINT8,  S, D0,       2,                    1,        5,             0, STR_CONFIG_SETTING_HOVER_DELAY,                      NULL),
+	   SDTC_VAR(gui.toolbar_pos,                   SLE_UINT8,  S, MS,       1,                    0,        2,             0, STR_CONFIG_SETTING_TOOLBAR_POS,                      v_PositionMainToolbar),
+	   SDTC_VAR(gui.statusbar_pos,                 SLE_UINT8,  S, MS,       1,                    0,        2,             0, STR_CONFIG_SETTING_STATUSBAR_POS,                    v_PositionStatusbar),
+	   SDTC_VAR(gui.window_snap_radius,            SLE_UINT8,  S, D0,       10,                   1,        32,            0, STR_CONFIG_SETTING_SNAP_RADIUS,                      NULL),
+	   SDTC_VAR(gui.window_soft_limit,             SLE_UINT8,  S, D0,       20,                   5,        255,           1, STR_CONFIG_SETTING_SOFT_LIMIT,                       NULL),
+	  SDTC_BOOL(gui.population_in_label,                       S, 0,        true,                                             STR_CONFIG_SETTING_POPULATION_IN_LABEL,              PopulationInLabelActive),
+	  SDTC_BOOL(gui.population_in_label_coloured,              S, 0,        true,                                             STR_CONFIG_SETTING_POPULATION_IN_LABEL_COLOURED,     PopulationInLabelActive),
+	  SDTC_BOOL(gui.link_terraform_toolbar,                    S, 0,        false,                                            STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR,           NULL),
+	   SDTC_VAR(gui.smallmap_land_colour,          SLE_UINT8,  S, MS,       0,                    0,        2,             0, STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR,             RedrawSmallmap),
+	  SDTC_BOOL(gui.smallmap_flood_warning,                    S, 0,        false,                                            STR_CONFIG_SETTING_SMALLMAP_FLOOD_WARNING,           RedrawSmallmap),
+	   SDTC_VAR(gui.linkgraph_companies,           SLE_UINT8,  S, MS,       0,                    0,        1,             0, STR_CONFIG_SETTING_SMALLMAP_LINKGRAPH_COMPANIES,     RedrawSmallmap),
+
+	   SDTC_VAR(gui.liveries,                      SLE_UINT8,  S, MS,       2,                    0,        2,             0, STR_CONFIG_SETTING_LIVERIES,                         InvalidateCompanyLiveryWindow),
+	  SDTC_BOOL(gui.prefer_teamchat,                           S, 0,        false,                                            STR_CONFIG_SETTING_PREFER_TEAMCHAT,                  NULL),
+	   SDTC_VAR(gui.scrollwheel_scrolling,         SLE_UINT8,  S, MS,       0,                    0,        2,             0, STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING,            NULL),
+	   SDTC_VAR(gui.scrollwheel_multiplier,        SLE_UINT8,  S, 0,        5,                    1,        15,            1, STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER,           NULL),
+	  SDTC_BOOL(gui.pause_on_newgame,                          S, 0,        false,                                            STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME,                NULL),
+	   SDTC_VAR(gui.advanced_vehicle_list,         SLE_UINT8,  S, MS,       1,                    0,        2,             0, STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS,           NULL),
+	  SDTC_BOOL(gui.timetable_in_ticks,                        S, 0,        false,                                            STR_CONFIG_SETTING_TIMETABLE_IN_TICKS,               InvalidateVehTimetableWindow),
+	  SDTC_BOOL(gui.time_in_minutes,                           S, 0,        false,                                            STR_CONFIG_SETTING_TIME_IN_MINUTES,                  InvalidateVehTimetableWindow),
+	   SDTC_VAR(gui.ticks_per_minute,              SLE_UINT8,  S, NC,       74,                   1,        255,           0, STR_CONFIG_SETTING_TICKS_PER_MINUTE,                 RedrawScreen),
+	   SDTC_VAR(gui.date_with_time,                SLE_UINT8,  S, MS,       0,                    0,        3,             1, STR_CONFIG_SETTING_DATE_WITH_TIME,                   RedrawScreen),
+	  SDTC_BOOL(gui.timetable_arrival_departure,               S, 0,        true,                                             STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE, InvalidateVehTimetableWindow),
+	   SDTC_VAR(gui.max_departures,                SLE_UINT8,  S, NC,       10,                   1,        30,            1, STR_CONFIG_MAX_DEPARTURES,                           NULL),
+	   SDTC_VAR(gui.max_departure_time,            SLE_UINT16, S, NC,       120,                  30,       240,           1, STR_CONFIG_MAX_DEPARTURE_TIME,                       NULL),
+	   SDTC_VAR(gui.departure_calc_frequency,      SLE_UINT16, S, NC,       10,                   1,        120,           1, STR_CONFIG_DEPARTURE_CALC_FREQUENCY,                 NULL),
+	  SDTC_BOOL(gui.departure_show_vehicle,                    S, 0,        false,                                            STR_CONFIG_DEPARTURE_VEHICLE_NAME,                   NULL),
+	  SDTC_BOOL(gui.departure_show_group,                      S, 0,        false,                                            STR_CONFIG_DEPARTURE_GROUP_NAME,                     NULL),
+	  SDTC_BOOL(gui.departure_show_company,                    S, 0,        true,                                             STR_CONFIG_DEPARTURE_COMPANY_NAME,                   NULL),
+	  SDTC_BOOL(gui.departure_show_vehicle_type,               S, 0,        false,                                            STR_CONFIG_DEPARTURE_VEHICLE_TYPE,                   NULL),
+	  SDTC_BOOL(gui.departure_show_vehicle_color,              S, 0,        false,                                            STR_CONFIG_DEPARTURE_VEHICLE_COLOR,                  NULL),
+	  SDTC_BOOL(gui.departure_larger_font,                     S, 0,        false,                                            STR_CONFIG_DEPARTURE_LARGER_FONT,                    NULL),
+	  SDTC_BOOL(gui.departure_destination_type,                S, 0,        false,                                            STR_CONFIG_DEPARTURE_DESTINATION_TYPE,               NULL),
+	  SDTC_BOOL(gui.departure_show_both,                       S, 0,        false,                                            STR_CONFIG_DEPARTURE_SHOW_BOTH,                      NULL),
+	  SDTC_BOOL(gui.departure_only_passengers,                 S, 0,        false,                                            STR_CONFIG_DEPARTURE_ONLY_PASSENGERS,                NULL),
+	   SDTC_VAR(gui.departure_conditionals,         SLE_UINT8, S, MS,       0,        0,          2,                       0, STR_CONFIG_DEPARTURE_CONDITIONALS,                   RedrawScreen),
+	  SDTC_BOOL(gui.quick_goto,                                S, 0,        false,                                            STR_CONFIG_SETTING_QUICKGOTO,                        NULL),
+	  SDTC_BOOL(gui.departure_show_all_stops,                  S, 0,        false,                                            STR_CONFIG_DEPARTURE_SHOW_ALL_STOPS,                 NULL),
+	   SDTC_VAR(gui.loading_indicators,             SLE_UINT8, S, MS,       1,                    0,        2,             0, STR_CONFIG_SETTING_LOADING_INDICATORS,               RedrawScreen),
+	   SDTC_VAR(gui.default_rail_type,              SLE_UINT8, S, MS,       0,                    0,        2,             0, STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE,                NULL),
+	  SDTC_BOOL(gui.enable_signal_gui,                         S, 0,        true,                                             STR_CONFIG_SETTING_ENABLE_SIGNAL_GUI,                CloseSignalGUI),
+	   SDTC_VAR(gui.coloured_news_year,             SLE_INT32, S, NC,       2000,                 MIN_YEAR, MAX_YEAR,      1, STR_CONFIG_SETTING_COLOURED_NEWS_YEAR,               NULL),
+	   SDTC_VAR(gui.drag_signals_density,           SLE_UINT8, S, 0,        4,                    1,        20,            0, STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY,             DragSignalsDensityChanged),
+	   SDTC_VAR(gui.semaphore_build_before,         SLE_INT32, S, NC,       1950,                 MIN_YEAR, MAX_YEAR,      1, STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE,      ResetSignalVariant),
+	  SDTC_BOOL(gui.vehicle_income_warn,                       S, 0,        true,                                             STR_CONFIG_SETTING_WARN_INCOME_LESS,                 NULL),
+	   SDTC_VAR(gui.order_review_system,            SLE_UINT8, S, MS,       2,                    0,        2,             0, STR_CONFIG_SETTING_ORDER_REVIEW,                     NULL),
+	  SDTC_BOOL(gui.lost_vehicle_warn,                         S, 0,        true,                                             STR_CONFIG_SETTING_WARN_LOST_VEHICLE,                NULL),
+	  SDTC_BOOL(gui.disable_unsuitable_building,               S, 0,        true,                                             STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING,      RedrawScreen),
+	  SDTC_BOOL(gui.new_nonstop,                               S, 0,        false,                                            STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT,               NULL),
+	   SDTC_VAR(gui.stop_location,                  SLE_UINT8, S, MS,       2,                    0,        2,             1, STR_CONFIG_SETTING_STOP_LOCATION,                    NULL),
+	  SDTC_BOOL(gui.keep_all_autosave,                         S, 0,        false,                                            STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.autosave_on_exit,                          S, 0,        false,                                            STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.max_num_autosaves,              SLE_UINT8, S, 0,        16,                   0,        255,           0, STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.bridge_pillars,                            S, 0,        true,                                             STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.auto_euro,                                 S, 0,        true,                                             STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.news_message_timeout,           SLE_UINT8, S, 0,        2,                    1,        255,           0, STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.show_track_reservation,                    S, 0,        false,                                            STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION,           RedrawScreen),
+	   SDTC_VAR(gui.default_signal_type,            SLE_UINT8, S, MS,       1,                    0,        2,             1, STR_CONFIG_SETTING_DEFAULT_SIGNAL_TYPE,              NULL),
+	   SDTC_VAR(gui.cycle_signal_types,             SLE_UINT8, S, MS,       2,                    0,        2,             1, STR_CONFIG_SETTING_CYCLE_SIGNAL_TYPES,               NULL),
+	   SDTC_VAR(gui.station_numtracks,              SLE_UINT8, S, 0,        1,                    1,        7,             0, STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.station_platlength,             SLE_UINT8, S, 0,        5,                    1,        7,             0, STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.station_dragdrop,                          S, 0,        true,                                             STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.station_show_coverage,                     S, 0,        false,                                            STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.persistent_buildingtools,                  S, 0,        true,                                             STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS,         NULL),
+	  SDTC_BOOL(gui.expenses_layout,                           S, 0,        false,                                            STR_CONFIG_SETTING_EXPENSES_LAYOUT,                  RedrawScreen),
+
+/* For the dedicated build we'll enable dates in logs by default. */
+#ifdef DEDICATED
+	  SDTC_BOOL(gui.show_date_in_logs,                         S, 0,        true,                                             STR_NULL,                                            NULL),
+#else
+	  SDTC_BOOL(gui.show_date_in_logs,                         S, 0,        false,                                            STR_NULL,                                            NULL),
+#endif
+	   SDTC_VAR(gui.developer,                     SLE_UINT8,  S, 0,        1,                    0,        2,             0, STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.newgrf_developer_tools,                    S, 0,        false,                                            STR_NULL,                                            InvalidateNewGRFChangeWindows),
+	  SDTC_BOOL(gui.ai_developer_tools,                        S, 0,        false,                                            STR_NULL,                                            NULL),
+	  SDTC_BOOL(gui.scenario_developer,                        S, 0,        false,                                            STR_NULL,                                            InvalidateNewGRFChangeWindows),
+	  SDTC_BOOL(gui.newgrf_show_old_versions,                  S, 0,        false,                                            STR_NULL,                                            NULL),
+SDTC_VAR(gui.newgrf_default_palette,               SLE_UINT8,  S, MS,       1,                    0,        1,             1, STR_CONFIG_SETTING_NEWGRF_DEFAULT_PALETTE,           UpdateNewGRFConfigPalette),
+	   SDTC_VAR(gui.console_backlog_timeout,       SLE_UINT16, S, 0,        100,                  10,       65500,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.console_backlog_length,        SLE_UINT16, S, 0,        100,                  10,       65500,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.station_gui_group_order,       SLE_UINT8,  S, 0,        0,                    0,        5,             1, STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.station_gui_sort_by,           SLE_UINT8,  S, 0,        0,                    0,        1,             1, STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.station_gui_sort_order,        SLE_UINT8,  S, 0,        0,                    0,        1,             1, STR_NULL,                                            NULL),
+#ifdef ENABLE_NETWORK
+	   SDTC_VAR(gui.network_chat_box_width,        SLE_UINT16, S, 0,        620,                  200,      65535,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.network_chat_box_height,       SLE_UINT8,  S, 0,        25,                   5,        255,           0, STR_NULL,                                            NULL),
+	   SDTC_VAR(gui.network_chat_timeout,          SLE_UINT16, S, 0,        20,                   1,        65535,         0, STR_NULL,                                            NULL),
+
+	   SDTC_VAR(network.sync_freq,                 SLE_UINT16,    C|S,NO,   100,                  0,        100,           0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.frame_freq,                SLE_UINT8,     C|S,NO,   0,                    0,        100,           0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.commands_per_frame,        SLE_UINT16, S, NO,       2,                    1,        65535,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.max_commands_in_queue,     SLE_UINT16, S, NO,       16,                   1,        65535,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.bytes_per_frame,           SLE_UINT16, S, NO,       8,                    1,        65535,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.bytes_per_frame_burst,     SLE_UINT16, S, NO,       256,                  1,        65535,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.max_join_time,             SLE_UINT16, S, NO,       500,                  0,        32000,         0, STR_NULL,                                            NULL),
+	  SDTC_BOOL(network.pause_on_join,                         S, NO,       true,                                             STR_NULL,                                            NULL),
+	   SDTC_VAR(network.server_port,               SLE_UINT16, S, NO,       NETWORK_DEFAULT_PORT, 0,        65535,         0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.server_admin_port,         SLE_UINT16, S, NO,       NETWORK_ADMIN_PORT,   0,        65535,         0, STR_NULL,                                            NULL),
+	  SDTC_BOOL(network.server_admin_chat,                     S, NO,       true,                                             STR_NULL,                                            NULL),
+	  SDTC_BOOL(network.server_advertise,                      S, NO,       false,                                            STR_NULL,                                            NULL),
+	   SDTC_VAR(network.lan_internet,              SLE_UINT8,  S, NO,       0,                    0,        1,             0, STR_NULL,                                            NULL),
+	   SDTC_STR(network.client_name,               SLE_STRB,   S, 0,        NULL,                                             STR_NULL,                                            UpdateClientName),
+	   SDTC_STR(network.server_password,           SLE_STRB,   S, NO,       NULL,                                             STR_NULL,                                            UpdateServerPassword),
+	   SDTC_STR(network.rcon_password,             SLE_STRB,   S, NO,       NULL,                                             STR_NULL,                                            UpdateRconPassword),
+	   SDTC_STR(network.admin_password,            SLE_STRB,   S, NO,       NULL,                                             STR_NULL,                                            NULL),
+	   SDTC_STR(network.default_company_pass,      SLE_STRB,   S, 0,        NULL,                                             STR_NULL,                                            NULL),
+	   SDTC_STR(network.server_name,               SLE_STRB,   S, NO,       NULL,                                             STR_NULL,                                            NULL),
+	   SDTC_STR(network.connect_to_ip,             SLE_STRB,   S, 0,        NULL,                                             STR_NULL,                                            NULL),
+	   SDTC_STR(network.network_id,                SLE_STRB,   S, NO,       NULL,                                             STR_NULL,                                            NULL),
+	  SDTC_BOOL(network.autoclean_companies,                   S, NO,       false,                                            STR_NULL,                                            NULL),
+	   SDTC_VAR(network.autoclean_unprotected,     SLE_UINT8,  S, D0|NO,    12,                   0,        240,           0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.autoclean_protected,       SLE_UINT8,  S, D0|NO,    36,                   0,        240,           0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.autoclean_novehicles,      SLE_UINT8,  S, D0|NO,    0,                    0,        240,           0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.max_companies,             SLE_UINT8,  S, NO,       15,                   1,        MAX_COMPANIES, 0, STR_NULL,                                            UpdateClientConfigValues),
+	   SDTC_VAR(network.max_clients,               SLE_UINT8,  S, NO,       25,                   2,        MAX_CLIENTS,   0, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.max_spectators,            SLE_UINT8,  S, NO,       15,                   0,        MAX_CLIENTS,   0, STR_NULL,                                            UpdateClientConfigValues),
+	   SDTC_VAR(network.restart_game_year,         SLE_INT32,  S, D0|NO|NC, 0,                    MIN_YEAR, MAX_YEAR,      1, STR_NULL,                                            NULL),
+	   SDTC_VAR(network.min_active_clients,        SLE_UINT8,  S, NO,       0,                    0,        MAX_CLIENTS,   0, STR_NULL,                                            NULL),
+	 SDTC_OMANY(network.server_lang,               SLE_UINT8,  S, NO,       0,                    35,   _server_langs,        STR_NULL,                                            NULL),
+	  SDTC_BOOL(network.reload_cfg,                            S, NO,       false,                                            STR_NULL,                                            NULL),
+	   SDTC_STR(network.last_host,                 SLE_STRB,   S, 0,        "",                                               STR_NULL,                                            NULL),
+	   SDTC_VAR(network.last_port,                 SLE_UINT16, S, 0,        0,                    0,        UINT16_MAX,    0, STR_NULL,                                            NULL),
+	  SDTC_BOOL(network.no_http_content_downloads,             S, 0,        false,                                            STR_NULL,                                            NULL),
+#endif /* ENABLE_NETWORK */
+
+	/*
+	 * Since the network code (CmdChangeSetting and friends) use the index in this array to decide
+	 * which setting the server is talking about all conditional compilation of this array must be at the
+	 * end. This isn't really the best solution, the settings the server can tell the client about should
+	 * either use a seperate array or some other form of identifier.
+	 */
+
+#ifdef __APPLE__
+	/* We might need to emulate a right mouse button on mac */
+	 SDTC_VAR(gui.right_mouse_btn_emulation,                 SLE_UINT8, S, MS,    0,      0,   2,       0, STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU,   NULL),
+#endif
+
+	 /* Copy & Paste related patch options */
+	 SDTC_VAR(gui.cp_paste_speed,                            SLE_UINT8, S, 0,     5,      1,   255,     1, STR_CONFIG_PATCHES_CP_PASTE_SPEED,        NULL),
+
+	SDT_END()
+};
+
+static const SettingDesc _company_settings[] = {
+	   SDT_BOOL(CompanySettings, engine_renew,                          0, PC,    false,                   STR_CONFIG_SETTING_AUTORENEW_VEHICLE,     NULL),
+	    SDT_VAR(CompanySettings, engine_renew_months,       SLE_INT16,  0, PC,    6,      -12, 12,      0, STR_CONFIG_SETTING_AUTORENEW_MONTHS,      NULL),
+	    SDT_VAR(CompanySettings, engine_renew_money,        SLE_UINT,   0, PC|CR, 100000, 0,   2000000, 0, STR_CONFIG_SETTING_AUTORENEW_MONEY,       NULL),
+	   SDT_BOOL(CompanySettings, renew_keep_length,                     0, PC,    false,                   STR_NULL,                                 NULL),
+	   SDT_BOOL(CompanySettings, vehicle.servint_ispercent,             0, PC,    false,                   STR_CONFIG_SETTING_SERVINT_ISPERCENT,     CheckInterval),
+	    SDT_VAR(CompanySettings, vehicle.servint_trains,    SLE_UINT16, 0, PC|D0, 150,    5,   800,     0, STR_CONFIG_SETTING_SERVINT_TRAINS,        InvalidateDetailsWindow),
+	    SDT_VAR(CompanySettings, vehicle.servint_roadveh,   SLE_UINT16, 0, PC|D0, 150,    5,   800,     0, STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES, InvalidateDetailsWindow),
+	    SDT_VAR(CompanySettings, vehicle.servint_ships,     SLE_UINT16, 0, PC|D0, 360,    5,   800,     0, STR_CONFIG_SETTING_SERVINT_SHIPS,         InvalidateDetailsWindow),
+	    SDT_VAR(CompanySettings, vehicle.servint_aircraft,  SLE_UINT16, 0, PC|D0, 100,    5,   800,     0, STR_CONFIG_SETTING_SERVINT_AIRCRAFT,      InvalidateDetailsWindow),
+	    SDT_END()
+};
+
+static const SettingDesc _currency_settings[] = {
+	   SDT_VAR(CurrencySpec, rate,      SLE_UINT16, S, 0, 1,         0,        UINT16_MAX, 0, STR_NULL, NULL),
+	   SDT_CHR(CurrencySpec, separator,             S, 0, ".",                                STR_NULL, NULL),
+	   SDT_VAR(CurrencySpec, to_euro,   SLE_INT32,  S, 0, 0,         MIN_YEAR, MAX_YEAR,   0, STR_NULL, NULL),
+	   SDT_STR(CurrencySpec, prefix,    SLE_STRBQ,  S, 0, NULL,                               STR_NULL, NULL),
+	   SDT_STR(CurrencySpec, suffix,    SLE_STRBQ,  S, 0, " credits",                         STR_NULL, NULL),
+	   SDT_END()
+};
+
+/* Undefine for the shortcut macros above */
+#undef S
+#undef C
+#undef N
+
+#undef D0
+#undef NC
+#undef MS
+#undef NO
+#undef CR
diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble
--- a/src/table/settings.h.preamble
+++ b/src/table/settings.h.preamble
@@ -9,118 +9,5 @@
 
 /** @file table/settings.h Settings to save in the savegame and config file. */
 
-/* Callback function used in _settings[] as well as _company_settings[] */
-static size_t ConvertLandscape(const char *value);
+// thanks but no thanks for now.
 
-
-/****************************
- * OTTD specific INI stuff
- ****************************/
-
-/**
- * Settings-macro usage:
- * The list might look daunting at first, but is in general easy to understand.
- * We have two types of list:
- * 1. SDTG_something
- * 2. SDT_something
- * The 'G' stands for global, so this is the one you will use for a
- * SettingDescGlobVarList section meaning global variables. The other uses a
- * Base/Offset and runtime variable selection mechanism, known from the saveload
- * convention (it also has global so it should not be hard).
- * Now there are a lot of types. Easy ones are:
- * - VAR:  any number type, 'type' field specifies what number. eg int8 or uint32
- * - BOOL: a boolean number type
- * - STR:  a string or character. 'type' field specifies what string. Normal, string, or quoted
- * A bit more difficult to use are MMANY (meaning ManyOfMany) and OMANY (OneOfMany)
- * These are actually normal numbers, only bitmasked. In MMANY several bits can
- * be set, in the other only one.
- * If nothing fits you, you can use the GENERAL macros, but it exposes the
- * internal structure somewhat so it needs a little looking. There are _NULL()
- * macros as well, these fill up space so you can add more settings there (in
- * place) and you DON'T have to increase the savegame version.
- *
- * While reading values from openttd.cfg, some values may not be converted
- * properly, for any kind of reasons.  In order to allow a process of self-cleaning
- * mechanism, a callback procedure is made available.  You will have to supply the function, which
- * will work on a string, one function per setting. And of course, enable the callback param
- * on the appropriate macro.
- */
-
-#define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, strval, proc, load)\
-	{name, (const void*)(size_t)(def), {(byte)cmd}, {(uint16)guiflags}, min, max, interval, many, str, strval, proc, load}
-
-/* Macros for various objects to go in the configuration file.
- * This section is for global variables */
-#define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strval, proc, from, to)\
-	{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strval, proc, NULL), SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to)}
-
-#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strval, proc, from, to)\
-	SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, NULL, str, strval, proc, from, to)
-
-#define SDTG_BOOL(name, flags, guiflags, var, def, str, strval, proc, from, to)\
-	SDTG_GENERAL(name, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, var, 0, def, 0, 1, 0, NULL, str, strval, proc, from, to)
-
-#define SDTG_LIST(name, type, length, flags, guiflags, var, def, str, strval, proc, from, to)\
-	SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, NULL, str, strval, proc, from, to)
-
-#define SDTG_STR(name, type, flags, guiflags, var, def, str, strval, proc, from, to)\
-	SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, lengthof(var), def, 0, 0, 0, NULL, str, strval, proc, from, to)
-
-#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strval, proc, from, to)\
-	SDTG_GENERAL(name, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, max, 0, full, str, strval, proc, from, to)
-
-#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strval, proc, from, to)\
-	SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strval, proc, from, to)
-
-#define SDTG_NULL(length, from, to)\
-	{{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, NULL, NULL}, SLEG_NULL(length, from, to)}
-
-#define SDTG_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, NULL, NULL}, SLEG_END()}
-
-/* Macros for various objects to go in the configuration file.
- * This section is for structures where their various members are saved */
-#define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strval, proc, load, from, to)\
-	{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strval, proc, load), SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to)}
-
-#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strval, proc, from, to)\
-	SDT_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, NULL, str, strval, proc, NULL, from, to)
-
-#define SDT_BOOL(base, var, flags, guiflags, def, str, strval, proc, from, to)\
-	SDT_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, base, var, 1, def, 0, 1, 0, NULL, str, strval, proc, NULL, from, to)
-
-#define SDT_LIST(base, var, type, flags, guiflags, def, str, strval, proc, from, to)\
-	SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, strval, proc, NULL, from, to)
-
-#define SDT_STR(base, var, type, flags, guiflags, def, str, strval, proc, from, to)\
-	SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, strval, proc, NULL, from, to)
-
-#define SDT_CHR(base, var, flags, guiflags, def, str, strval, proc, from, to)\
-	SDT_GENERAL(#var, SDT_STRING, SL_VAR, SLE_CHAR, flags, guiflags, base, var, 1, def, 0, 0, 0, NULL, str, strval, proc, NULL, from, to)
-
-#define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strval, proc, from, to, load)\
-	SDT_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, max, 0, full, str, strval, proc, load, from, to)
-
-#define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strval, from, to)\
-	SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, strval, proc, NULL, from, to)
-
-#define SDT_NULL(length, from, to)\
-	{{"", NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, NULL, NULL}, SLE_CONDNULL(length, from, to)}
-
-
-#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strval, proc, from, to)\
-	SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, NULL, str, strval, proc, from, to)
-
-#define SDTC_BOOL(var, flags, guiflags, def, str, strval, proc, from, to)\
-	SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, NULL, str, strval, proc, from, to)
-
-#define SDTC_LIST(var, type, flags, guiflags, def, str, strval, proc, from, to)\
-	SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, strval, proc, from, to)
-
-#define SDTC_STR(var, type, flags, guiflags, def, str, strval, proc, from, to)\
-	SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, strval, proc, from, to)
-
-#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strval, proc, from, to)\
-	SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strval, proc, from, to)
-
-#define SDT_END() {{NULL, NULL, {0}, {0}, 0, 0, 0, NULL, STR_NULL, STR_NULL, NULL, NULL}, SLE_END()}
-
diff --git a/src/table/sprites.h b/src/table/sprites.h
--- a/src/table/sprites.h
+++ b/src/table/sprites.h
@@ -192,7 +192,19 @@
 static const SpriteID SPR_ELRAIL_BASE   = SPR_AUTORAIL_BASE + AUTORAIL_SPRITE_COUNT;
 static const uint16 ELRAIL_SPRITE_COUNT = 48;
 
-static const SpriteID SPR_2CCMAP_BASE   = SPR_ELRAIL_BASE + ELRAIL_SPRITE_COUNT;
+static const SpriteID SPR_COPYPASTE_BASE = SPR_ELRAIL_BASE + ELRAIL_SPRITE_COUNT;
+static const uint16 COPYPASTE_SPRITE_COUNT = 22;
+
+static const SpriteID SPR_TRAFFICLIGHTS_BASE   = SPR_OPENTTD_BASE + 181;
+static const uint16 TRAFFICLIGHTS_SPRITE_COUNT = 22;
+
+static const SpriteID SPR_SPEEDSIGNAL_BASE   = SPR_OPENTTD_BASE + 203;
+static const uint16 SPEEDSIGNAL_SPRITE_COUNT = 32;
+
+static const SpriteID SPR_PROGSIGNAL_BASE   = SPR_OPENTTD_BASE + 235;
+static const uint16 PROGSIGNAL_SPRITE_COUNT = 32;
+
+static const SpriteID SPR_2CCMAP_BASE   = SPR_COPYPASTE_BASE + COPYPASTE_SPRITE_COUNT;
 static const uint16 TWOCCMAP_SPRITE_COUNT = 256;
 
 /** shore tiles - action 05-0D */
@@ -551,6 +563,8 @@
 static const SpriteID SPR_FLAT_2_QUART_SNOW_DESERT_TILE = 4512;
 static const SpriteID SPR_FLAT_3_QUART_SNOW_DESERT_TILE = 4531;
 static const SpriteID SPR_FLAT_SNOW_DESERT_TILE         = 4550;
+/* Blacktiles all slopes. */
+static const SpriteID SPR_FLAT_BLACKTILES               = SPR_OPENTTD_BASE + 162;
 
 /* Hedge, Farmland-fence sprites */
 static const SpriteID SPR_HEDGE_BUSHES            = 4090;
@@ -1075,6 +1089,51 @@
 static const SpriteID SPR_IMG_SIGN            = 4082;
 static const SpriteID SPR_IMG_BUY_LAND        = 4791;
 
+/* copy_paste_gui.cpp */
+static const SpriteID SPR_IMG_COPY              = SPR_COPYPASTE_BASE;
+static const SpriteID SPR_IMG_PASTE             = SPR_COPYPASTE_BASE + 1;
+static const SpriteID SPR_IMG_ROTATE_LEFT       = SPR_COPYPASTE_BASE + 2;
+static const SpriteID SPR_IMG_ROTATE_RIGHT      = SPR_COPYPASTE_BASE + 3;
+static const SpriteID SPR_IMG_LOAD              = SPR_COPYPASTE_BASE + 4;
+static const SpriteID SPR_IMG_MINUS_TERRAIN     = SPR_COPYPASTE_BASE + 5;
+static const SpriteID SPR_IMG_NEUTRAL_TERRAIN   = SPR_COPYPASTE_BASE + 6;
+static const SpriteID SPR_IMG_PLUS_TERRAIN      = SPR_COPYPASTE_BASE + 7;
+static const SpriteID SPR_IMG_MINUS_DYNAMITE    = SPR_COPYPASTE_BASE + 10;
+static const SpriteID SPR_IMG_MIRROR_HORIZONTAL = SPR_COPYPASTE_BASE + 12;
+static const SpriteID SPR_IMG_MIRROR_VERTICAL   = SPR_COPYPASTE_BASE + 13;
+static const SpriteID SPR_IMG_MINUS_SIGNAL      = SPR_COPYPASTE_BASE + 14;
+static const SpriteID SPR_IMG_NO_RAIL           = SPR_COPYPASTE_BASE + 16;
+static const SpriteID SPR_IMG_NO_ROAD           = SPR_COPYPASTE_BASE + 18;
+static const SpriteID SPR_IMG_ONLY_OWN          = SPR_COPYPASTE_BASE + 20;
+
+/* Traffic lights */
+static const SpriteID SPR_IMG_TRAFFIC_LIGHT     = SPR_TRAFFICLIGHTS_BASE;
+static const SpriteID SPR_CURSOR_TRAFFIC_LIGHT  = SPR_TRAFFICLIGHTS_BASE + 1;
+
+static const SpriteID SPR_TL_SW_RED             = SPR_TRAFFICLIGHTS_BASE + 2;
+static const SpriteID SPR_TL_SW_RED_YELLOW      = SPR_TRAFFICLIGHTS_BASE + 3;
+static const SpriteID SPR_TL_SW_GREEN           = SPR_TRAFFICLIGHTS_BASE + 4;
+static const SpriteID SPR_TL_SW_YELLOW          = SPR_TRAFFICLIGHTS_BASE + 5;
+static const SpriteID SPR_TL_SW_NONE            = SPR_TRAFFICLIGHTS_BASE + 6;
+
+static const SpriteID SPR_TL_SE_RED             = SPR_TRAFFICLIGHTS_BASE + 7;
+static const SpriteID SPR_TL_SE_RED_YELLOW      = SPR_TRAFFICLIGHTS_BASE + 8;
+static const SpriteID SPR_TL_SE_GREEN           = SPR_TRAFFICLIGHTS_BASE + 9;
+static const SpriteID SPR_TL_SE_YELLOW          = SPR_TRAFFICLIGHTS_BASE + 10;
+static const SpriteID SPR_TL_SE_NONE            = SPR_TRAFFICLIGHTS_BASE + 11;
+
+static const SpriteID SPR_TL_NW_RED             = SPR_TRAFFICLIGHTS_BASE + 12;
+static const SpriteID SPR_TL_NW_RED_YELLOW      = SPR_TRAFFICLIGHTS_BASE + 13;
+static const SpriteID SPR_TL_NW_GREEN           = SPR_TRAFFICLIGHTS_BASE + 14;
+static const SpriteID SPR_TL_NW_YELLOW          = SPR_TRAFFICLIGHTS_BASE + 15;
+static const SpriteID SPR_TL_NW_NONE            = SPR_TRAFFICLIGHTS_BASE + 16;
+
+static const SpriteID SPR_TL_NE_RED             = SPR_TRAFFICLIGHTS_BASE + 17;
+static const SpriteID SPR_TL_NE_RED_YELLOW      = SPR_TRAFFICLIGHTS_BASE + 18;
+static const SpriteID SPR_TL_NE_GREEN           = SPR_TRAFFICLIGHTS_BASE + 19;
+static const SpriteID SPR_TL_NE_YELLOW          = SPR_TRAFFICLIGHTS_BASE + 20;
+static const SpriteID SPR_TL_NE_NONE            = SPR_TRAFFICLIGHTS_BASE + 21;
+
 /* OpenTTD in gamescreen */
 static const SpriteID SPR_OTTD_O                = 4842;
 static const SpriteID SPR_OTTD_P                = 4841;
@@ -1286,12 +1345,16 @@
 static const SpriteID SPR_IMG_SIGNAL_ELECTRIC_COMBO    = SPR_SIGNALS_BASE +  44;
 static const SpriteID SPR_IMG_SIGNAL_ELECTRIC_PBS      = SPR_SIGNALS_BASE + 124;
 static const SpriteID SPR_IMG_SIGNAL_ELECTRIC_PBS_OWAY = SPR_SIGNALS_BASE + 140;
+static const SpriteID SPR_IMG_SIGNAL_ELECTRIC_PROG     = SPR_PROGSIGNAL_BASE + 28;
+static const SpriteID SPR_IMG_SIGNAL_ELECTRIC_SPEED    = SPR_SPEEDSIGNAL_BASE + 28;
 static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_NORM    = SPR_SIGNALS_BASE +  60;
 static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_ENTRY   = SPR_SIGNALS_BASE +  76;
 static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_EXIT    = SPR_SIGNALS_BASE +  92;
 static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_COMBO   = SPR_SIGNALS_BASE + 108;
 static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_PBS     = SPR_SIGNALS_BASE + 188;
 static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_PBS_OWAY= SPR_SIGNALS_BASE + 204;
+static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_PROG    = SPR_PROGSIGNAL_BASE + 12;
+static const SpriteID SPR_IMG_SIGNAL_SEMAPHORE_SPEED   = SPR_SPEEDSIGNAL_BASE + 12;
 static const SpriteID SPR_IMG_SIGNAL_CONVERT           = SPR_OPENTTD_BASE + 135;
 
 static const SpriteID SPR_IMG_TUNNEL_RAIL   = 2430;
@@ -1411,6 +1474,9 @@
 static const CursorID SPR_CURSOR_CLONE_SHIP     = SPR_OPENTTD_BASE + 112;
 static const CursorID SPR_CURSOR_CLONE_AIRPLANE = SPR_OPENTTD_BASE + 113;
 
+static const CursorID SPR_CURSOR_COPY  = SPR_COPYPASTE_BASE + 8;
+static const CursorID SPR_CURSOR_PASTE = SPR_COPYPASTE_BASE + 9;
+
 /** Animation macro in table/animcursors.h (_animcursors[]) */
 
 static const CursorID SPR_CURSOR_DEMOLISH_FIRST = 704;
diff --git a/src/table/strgen_tables.h b/src/table/strgen_tables.h
--- a/src/table/strgen_tables.h
+++ b/src/table/strgen_tables.h
@@ -86,6 +86,10 @@
 	{"DATE_SHORT",      EmitSingleChar, SCC_DATE_SHORT,         1, C_CASE},
 	{"DATE_LONG",       EmitSingleChar, SCC_DATE_LONG,          1, C_CASE},
 	{"DATE_ISO",        EmitSingleChar, SCC_DATE_ISO,           1, C_NONE},
+	{"DATE_WALLCLOCK_TINY",       EmitSingleChar, SCC_DATE_WALLCLOCK_TINY,          1, C_NONE},
+	{"DATE_WALLCLOCK_SHORT",      EmitSingleChar, SCC_DATE_WALLCLOCK_SHORT,         1, C_NONE},
+	{"DATE_WALLCLOCK_LONG",       EmitSingleChar, SCC_DATE_WALLCLOCK_LONG,          1, C_NONE},
+	{"DATE_WALLCLOCK_ISO",        EmitSingleChar, SCC_DATE_WALLCLOCK_ISO,           1, C_NONE},
 
 	{"STRING",          EmitSingleChar, SCC_STRING,             1, C_CASE | C_GENDER},
 	{"RAW_STRING",      EmitSingleChar, SCC_RAW_STRING_POINTER, 1, C_NONE | C_GENDER},
diff --git a/src/table/win32_settings.ini b/src/table/win32_settings.ini
--- a/src/table/win32_settings.ini
+++ b/src/table/win32_settings.ini
@@ -6,59 +6,4 @@
 ; See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 ;
 
-[pre-amble]
-/* win32_v.cpp only settings */
-#if defined(WIN32) && !defined(DEDICATED)
-extern bool _force_full_redraw, _window_maximize;
-extern uint _display_hz, _fullscreen_bpp;
-
-static const SettingDescGlobVarList _win32_settings[] = {
-[post-amble]
-};
-#endif /* WIN32 */
-[templates]
-SDTG_BOOL = SDTG_BOOL($name,        $flags, $guiflags, $var, $def,                        $str, $strval, $proc, $from, $to),
-SDTG_VAR  =  SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strval, $proc, $from, $to),
-SDTG_END  = SDTG_END()
-
-[defaults]
-flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
-guiflags = 0
-interval = 0
-str      = STR_NULL
-strval   = STR_NULL
-proc     = NULL
-load     = NULL
-from     = 0
-to       = SL_MAX_VERSION
-
-
-
-[SDTG_VAR]
-name     = ""display_hz""
-type     = SLE_UINT
-var      = _display_hz
-def      = 0
-min      = 0
-max      = 120
-
-[SDTG_BOOL]
-name     = ""force_full_redraw""
-var      = _force_full_redraw
-def      = false
-
-[SDTG_VAR]
-name     = ""fullscreen_bpp""
-type     = SLE_UINT
-var      = _fullscreen_bpp
-def      = 8
-min      = 8
-max      = 32
-
-[SDTG_BOOL]
-name     = ""window_maximize""
-var      = _window_maximize
-def      = false
-
-[SDTG_END]
-
+; thanks but no thanks for now.
diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp
--- a/src/terraform_cmd.cpp
+++ b/src/terraform_cmd.cpp
@@ -19,41 +19,18 @@
 #include "object_base.h"
 #include "company_base.h"
 #include "company_func.h"
+#include "tunnelbridge.h"
 
 #include "table/strings.h"
 
-/*
- * In one terraforming command all four corners of a initial tile can be raised/lowered (though this is not available to the player).
- * The maximal amount of height modifications is archieved when raising a complete flat land from sea level to MAX_TILE_HEIGHT or vice versa.
- * This affects all corners with a manhatten distance smaller than MAX_TILE_HEIGHT to one of the initial 4 corners.
- * Their maximal amount is computed to 4 * \sum_{i=1}^{h_max} i  =  2 * h_max * (h_max + 1).
- */
-static const int TERRAFORMER_MODHEIGHT_SIZE = 2 * MAX_TILE_HEIGHT * (MAX_TILE_HEIGHT + 1);
-
-/*
- * The maximal amount of affected tiles (i.e. the tiles that incident with one of the corners above, is computed similiar to
- * 1 + 4 * \sum_{i=1}^{h_max} (i+1)  =  1 + 2 * h_max + (h_max + 3).
- */
-static const int TERRAFORMER_TILE_TABLE_SIZE = 1 + 2 * MAX_TILE_HEIGHT * (MAX_TILE_HEIGHT + 3);
-
-struct TerraformerHeightMod {
-	TileIndex tile;   ///< Referenced tile.
-	byte height;      ///< New TileHeight (height of north corner) of the tile.
-};
+#include <map>
+#include <set>
 
 struct TerraformerState {
-	int modheight_count;  ///< amount of entries in "modheight".
-	int tile_table_count; ///< amount of entries in "tile_table".
+	int modheight_count;  ///< amount of entries in "modheight". Used for limiting the number of terraformcommands over time.
+	std::set<TileIndex> dirty_tiles;
 
-	/**
-	 * Dirty tiles, i.e.\ at least one corner changed.
-	 *
-	 * This array contains the tiles which are or will be marked as dirty.
-	 *
-	 * @ingroup dirty
-	 */
-	TileIndex tile_table[TERRAFORMER_TILE_TABLE_SIZE];
-	TerraformerHeightMod modheight[TERRAFORMER_MODHEIGHT_SIZE];  ///< Height modifications.
+	std::map<TileIndex, uint16> tile_to_new_height;
 };
 
 TileIndex _terraform_err_tile; ///< first tile we couldn't terraform
@@ -65,16 +42,13 @@
  * @param tile Tile.
  * @return TileHeight.
  */
-static int TerraformGetHeightOfTile(const TerraformerState *ts, TileIndex tile)
+static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
 {
-	const TerraformerHeightMod *mod = ts->modheight;
-
-	for (int count = ts->modheight_count; count != 0; count--, mod++) {
-		if (mod->tile == tile) return mod->height;
+	if (ts->tile_to_new_height.find(tile) != ts->tile_to_new_height.end()) {
+		return ts->tile_to_new_height[tile];
+	} else {
+		return TileHeight(tile);
 	}
-
-	/* TileHeight unchanged so far, read value from map. */
-	return TileHeight(tile);
 }
 
 /**
@@ -86,26 +60,7 @@
  */
 static void TerraformSetHeightOfTile(TerraformerState *ts, TileIndex tile, int height)
 {
-	/* Find tile in the "modheight" table.
-	 * Note: In a normal user-terraform command the tile will not be found in the "modheight" table.
-	 *       But during house- or industry-construction multiple corners can be terraformed at once. */
-	TerraformerHeightMod *mod = ts->modheight;
-	int count = ts->modheight_count;
-
-	while ((count > 0) && (mod->tile != tile)) {
-		mod++;
-		count--;
-	}
-
-	/* New entry? */
-	if (count == 0) {
-		assert(ts->modheight_count < TERRAFORMER_MODHEIGHT_SIZE);
-		ts->modheight_count++;
-	}
-
-	/* Finally store the new value */
-	mod->tile = tile;
-	mod->height = (byte)height;
+	ts->tile_to_new_height[tile] = (uint16)height;
 }
 
 /**
@@ -117,15 +72,7 @@
  */
 static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
 {
-	int count = ts->tile_table_count;
-
-	for (TileIndex *t = ts->tile_table; count != 0; count--, t++) {
-		if (*t == tile) return;
-	}
-
-	assert(ts->tile_table_count < TERRAFORMER_TILE_TABLE_SIZE);
-
-	ts->tile_table[ts->tile_table_count++] = tile;
+	ts->dirty_tiles.insert(tile);
 }
 
 /**
@@ -158,7 +105,7 @@
 
 	/* Check range of destination height */
 	if (height < 0) return_cmd_error(STR_ERROR_ALREADY_AT_SEA_LEVEL);
-	if (height > (int)MAX_TILE_HEIGHT) return_cmd_error(STR_ERROR_TOO_HIGH);
+	if (height > (int)GetMaxTileHeight()) return_cmd_error(STR_ERROR_TOO_HIGH);
 
 	/*
 	 * Check if the terraforming has any effect.
@@ -229,6 +176,100 @@
 	return total_cost;
 }
 
+static void MarkTilesDirty(TerraformerState &ts)
+{
+	for (std::set<TileIndex>::const_iterator it = ts.dirty_tiles.begin(); it != ts.dirty_tiles.end(); it++) {
+		TileIndex ti = *it;
+		MarkTileDirtyByTile(ti);
+		int height = TerraformGetHeightOfTile(&ts, ti);
+
+		/* Now, if we alter the height of the map edge, we need to take care
+		 * about repainting the affected areas outside map as well.
+		 * Remember:
+		 * Outside map, we assume that our landscape descends to
+		 * height zero as fast as possible.
+		 * Those simulated tiles (they don't exist as datastructure,
+		 * only as concept in code) need to be repainted properly,
+		 * otherwise we will get ugly glitches.
+		 *
+		 * Furthermore, note that we have to take care about the possibility,
+		 * that landscape was higher before the change,
+		 * so also tiles a bit outside need to be repainted. */
+		int x = TileX(ti);
+		int y = TileY(ti);
+
+		if (x == 0) {
+
+			if (y == 0) {
+				/* Height of the northern corner is altered. */
+				for (int cx = 0; cx >= -height - 1; cx--) {
+					for (int cy = 0; cy >= -height - 1; cy--) {
+						/* This means, tiles in the sector north of that
+						 * corner need to be repainted. */
+
+						if (cx + cy >= -height - 2) {
+							/* But only tiles that actually might have changed. */
+							MarkTileDirtyByTileOutsideMap(cx, cy);
+						}
+					}
+				}
+			} else if (y < (int)MapMaxY()) {
+				for (int cx = 0; cx >= -height - 1; cx--) {
+					MarkTileDirtyByTileOutsideMap(cx, y);
+				}
+			} else {
+				for (int cx = 0; cx >= -height - 1; cx--) {
+					for (int cy = (int)MapMaxY(); cy <= (int)MapMaxY() + height + 1; cy++) {
+
+						if (cx + ((int)MapMaxY() - cy) >= -height - 2) {
+							MarkTileDirtyByTileOutsideMap(cx, cy);
+						}
+					}
+				}
+			}
+
+		} else if (x < (int)MapMaxX()) {
+
+			if (y == 0) {
+				for (int cy = 0; cy >= -height - 1; cy--) {
+					MarkTileDirtyByTileOutsideMap(x, cy);
+				}
+			} else if (y < (int)MapMaxY()) {
+				/* Nothing to be done here, we are inside the map. */
+			} else {
+				for (int cy = (int)MapMaxY(); cy <= (int)MapMaxY() + height + 1; cy++) {
+					MarkTileDirtyByTileOutsideMap(x, cy);
+				}
+			}
+
+		} else {
+
+			if (y == 0) {
+				for (int cx = (int)MapMaxX(); cx <= (int)MapMaxX() + height + 1; cx++) {
+					for (int cy = 0; cy >= -height - 1; cy--) {
+						if (((int)MapMaxX() - cx) + cy >= -height - 2) {
+							MarkTileDirtyByTileOutsideMap(cx, cy);
+						}
+					}
+				}
+			} else if (y < (int)MapMaxY()) {
+				for (int cx = (int)MapMaxX(); cx <= (int)MapMaxX() + height + 1; cx++) {
+					MarkTileDirtyByTileOutsideMap(cx, y);
+				}
+			} else {
+				for (int cx = (int)MapMaxX(); cx <= (int)MapMaxX() + height + 1; cx++) {
+					for (int cy = (int)MapMaxY(); cy <= (int)MapMaxY() + height + 1; cy++) {
+
+						if (((int)MapMaxX() - cx) + ((int)MapMaxY() - cy) >= -height - 2) {
+							MarkTileDirtyByTileOutsideMap(cx, cy);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
 /**
  * Terraform land
  * @param tile tile to terraform
@@ -246,7 +287,7 @@
 	int direction = (p2 != 0 ? 1 : -1);
 	TerraformerState ts;
 
-	ts.modheight_count = ts.tile_table_count = 0;
+	ts.modheight_count = 0;
 
 	/* Compute the costs and the terraforming result in a model of the landscape */
 	if ((p1 & SLOPE_W) != 0 && tile + TileDiffXY(1, 0) < MapSize()) {
@@ -281,10 +322,8 @@
 	 * Pass == 0: Collect tileareas which are caused to be auto-cleared.
 	 * Pass == 1: Collect the actual cost. */
 	for (int pass = 0; pass < 2; pass++) {
-		TileIndex *ti = ts.tile_table;
-
-		for (int count = ts.tile_table_count; count != 0; count--, ti++) {
-			TileIndex tile = *ti;
+		for (std::set<TileIndex>::const_iterator it = ts.dirty_tiles.begin(); it != ts.dirty_tiles.end(); it++) {
+			TileIndex tile = *it;
 
 			assert(tile < MapSize());
 			/* MP_VOID tiles can be terraformed but as tunnels and bridges
@@ -357,24 +396,20 @@
 	if (flags & DC_EXEC) {
 		/* change the height */
 		{
-			int count;
-			TerraformerHeightMod *mod;
+			for (std::map<TileIndex, uint16>::const_iterator it = ts.tile_to_new_height.begin();
+					it != ts.tile_to_new_height.end(); it++) {
+				TileIndex tile = it->first;
+				uint16 height = it->second;
 
-			mod = ts.modheight;
-			for (count = ts.modheight_count; count != 0; count--, mod++) {
-				TileIndex til = mod->tile;
+				ts.modheight_count += 1; // TODO: replace 1 by number of tiles affected.
 
-				SetTileHeight(til, mod->height);
+				SetTileHeight(tile, height);
 			}
 		}
 
 		/* 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);
-			}
+			MarkTilesDirty(ts);
 		}
 
 		if (c != NULL) c->terraform_limit -= ts.modheight_count << 16;
@@ -382,7 +417,6 @@
 	return total_cost;
 }
 
-
 /**
  * Levels a selected (rectangle) area of land
  * @param tile end tile of area-drag
@@ -414,7 +448,7 @@
 	}
 
 	/* Check range of destination height */
-	if (h > MAX_TILE_HEIGHT) return_cmd_error((oldh == 0) ? STR_ERROR_ALREADY_AT_SEA_LEVEL : STR_ERROR_TOO_HIGH);
+	if (h > GetMaxTileHeight()) return_cmd_error((oldh == 0) ? STR_ERROR_ALREADY_AT_SEA_LEVEL : STR_ERROR_TOO_HIGH);
 
 	Money money = GetAvailableMoneyForCommand();
 	CommandCost cost(EXPENSES_CONSTRUCTION);
@@ -463,8 +497,9 @@
 			cost.AddCost(ret);
 			curh += (curh > h) ? -1 : 1;
 			had_success = true;
+
+			limit -= 1; // TODO: replace 1 by number of tiles affected.
 		}
-
 		if (limit <= 0) break;
 	}
 
diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp
--- a/src/terraform_gui.cpp
+++ b/src/terraform_gui.cpp
@@ -31,6 +31,7 @@
 #include "object.h"
 #include "hotkeys.h"
 #include "engine_base.h"
+#include "tile_map.h"
 
 #include "table/strings.h"
 
@@ -153,6 +154,8 @@
 	TTW_PLANT_TREES,                      ///< Plant trees button (note: opens seperate window, no place-push-button)
 	TTW_PLACE_SIGN,                       ///< Place sign button
 	TTW_PLACE_OBJECT,                     ///< Place object button
+	TTW_MEASUREMENT_TOOL,                 ///< Ruler tool button
+	TTW_COPY_PASTE,                       ///< CopyPaste button
 };
 
 /** Terra form toolbar managing class. */
@@ -228,6 +231,17 @@
 				}
 				break;
 
+			case TTW_MEASUREMENT_TOOL: // Ruler tool button
+				HandlePlacePushButton(this, TTW_MEASUREMENT_TOOL, SPR_CURSOR_QUERY, HT_RECT);
+				this->last_user_action = widget;
+				break;
+
+			case TTW_COPY_PASTE: // CopyPaste button
+				/* This button is NOT a place-push-button, so don't treat it as such */
+				this->HandleButtonClick(TTW_COPY_PASTE);
+				ShowCopyPasteToolbarGui();
+				break;
+
 			default: NOT_REACHED();
 		}
 	}
@@ -277,6 +291,10 @@
 				PlaceProc_Object(tile);
 				break;
 
+			case TTW_MEASUREMENT_TOOL: // Ruler tool button
+				VpStartPlaceSizing(tile, VPM_A_B_LINE, DDSP_MEASURE);
+				break;
+
 			default: NOT_REACHED();
 		}
 	}
@@ -304,6 +322,9 @@
 				case DDSP_LEVEL_AREA:
 					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
 					break;
+				case DDSP_MEASURE:
+					/* nothing to do, just draw a tooltip */
+					break;
 			}
 		}
 	}
@@ -326,6 +347,7 @@
 	Hotkey<TerraformToolbarWindow>('I', "trees", TTW_PLANT_TREES),
 	Hotkey<TerraformToolbarWindow>('O', "placesign", TTW_PLACE_SIGN),
 	Hotkey<TerraformToolbarWindow>('P', "placeobject", TTW_PLACE_OBJECT),
+	Hotkey<TerraformToolbarWindow>('R' | WKC_SHIFT, "ruler", TTW_MEASUREMENT_TOOL),
 	HOTKEY_LIST_END(TerraformToolbarWindow)
 };
 Hotkey<TerraformToolbarWindow> *_terraform_hotkeys = TerraformToolbarWindow::terraform_hotkeys;
@@ -358,6 +380,10 @@
 			NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_PLACE_OBJECT), SetMinimalSize(22, 22),
 								SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT),
 		EndContainer(),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_MEASUREMENT_TOOL), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_QUERY, STR_LANDSCAPING_TOOLTIP_RULER_TOOL),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_COPY_PASTE), SetMinimalSize(22,22),
+								SetFill(0, 1), SetDataTip(SPR_IMG_COPY, STR_COPY_PASTE_TOOLTIP),
 	EndContainer(),
 };
 
@@ -436,7 +462,7 @@
 		uint h;
 		if (mode != 0) {
 			/* Raise land */
-			h = MAX_TILE_HEIGHT;
+			h = GetMaxTileHeight();
 			TILE_AREA_LOOP(tile2, ta) {
 				h = min(h, TileHeight(tile2));
 			}
@@ -480,6 +506,7 @@
 	ETTW_PLACE_ROCKS,                      ///< Place rocks button
 	ETTW_PLACE_DESERT,                     ///< Place desert button (in tropical climate)
 	ETTW_PLACE_OBJECT,                     ///< Place transmitter button
+	ETTW_MEASUREMENT_TOOL,                 ///< Ruler tool button
 	ETTW_BUTTONS_END,                      ///< End of pushable buttons
 	ETTW_INCREASE_SIZE = ETTW_BUTTONS_END, ///< Upwards arrow button to increase terraforming size
 	ETTW_DECREASE_SIZE,                    ///< Downwards arrow button to decrease terraforming size
@@ -513,6 +540,8 @@
 			EndContainer(),
 			NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_PLACE_OBJECT), SetMinimalSize(23, 22),
 										SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_SCENEDIT_TOOLBAR_PLACE_OBJECT),
+			NWidget(WWT_IMGBTN, COLOUR_GREY, ETTW_MEASUREMENT_TOOL), SetMinimalSize(22,22),
+									SetFill(0, 1), SetDataTip(SPR_IMG_QUERY, STR_LANDSCAPING_TOOLTIP_RULER_TOOL),
 			NWidget(NWID_SPACER), SetFill(1, 0),
 		EndContainer(),
 		NWidget(NWID_HORIZONTAL),
@@ -661,6 +690,11 @@
 				}
 				break;
 
+			case ETTW_MEASUREMENT_TOOL: // Ruler tool button
+				HandlePlacePushButton(this, ETTW_MEASUREMENT_TOOL, SPR_CURSOR_QUERY, HT_RECT);
+				this->last_user_action = widget;
+				break;
+
 			case ETTW_INCREASE_SIZE:
 			case ETTW_DECREASE_SIZE: { // Increase/Decrease terraform size
 				int size = (widget == ETTW_INCREASE_SIZE) ? 1 : -1;
@@ -730,6 +764,10 @@
 				PlaceProc_Object(tile);
 				break;
 
+			case ETTW_MEASUREMENT_TOOL: // Ruler tool button
+				VpStartPlaceSizing(tile, VPM_A_B_LINE, DDSP_MEASURE);
+				break;
+
 			default: NOT_REACHED();
 		}
 	}
@@ -752,6 +790,9 @@
 				case DDSP_DEMOLISH_AREA:
 					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
 					break;
+				case DDSP_MEASURE:
+					/* nothing to do, just draw a tooltip */
+					break;
 			}
 		}
 	}
@@ -774,6 +815,7 @@
 	Hotkey<ScenarioEditorLandscapeGenerationWindow>('R', "rocky", ETTW_PLACE_ROCKS),
 	Hotkey<ScenarioEditorLandscapeGenerationWindow>('T', "desert", ETTW_PLACE_DESERT),
 	Hotkey<ScenarioEditorLandscapeGenerationWindow>('O', "object", ETTW_PLACE_OBJECT),
+	Hotkey<ScenarioEditorLandscapeGenerationWindow>('R' | WKC_SHIFT, "ruler", ETTW_MEASUREMENT_TOOL),
 	HOTKEY_LIST_END(ScenarioEditorLandscapeGenerationWindow)
 };
 
diff --git a/src/texteff.hpp b/src/texteff.hpp
--- a/src/texteff.hpp
+++ b/src/texteff.hpp
@@ -41,6 +41,6 @@
 void HideFillingPercent(TextEffectID *te_id);
 
 void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost);
-void ShowFeederIncomeAnimation(int x, int y, int z, Money cost);
+void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income);
 
 #endif /* TEXTEFF_HPP */
diff --git a/src/tgp.cpp b/src/tgp.cpp
--- a/src/tgp.cpp
+++ b/src/tgp.cpp
@@ -17,6 +17,8 @@
 #include "core/alloc_func.hpp"
 #include "core/random_func.hpp"
 #include "landscape_type.h"
+#include "tgp.h"
+#include "debug.h"
 
 /*
  *
@@ -201,34 +203,77 @@
 /** Walk through all items of _height_map.h */
 #define FOR_ALL_TILES_IN_HEIGHT(h) for (h = _height_map.h; h < &_height_map.h[_height_map.total_size]; h++)
 
-/** Maximum index into array of noise amplitudes */
-static const int TGP_FREQUENCY_MAX = 6;
+/**
+ * Noise amplitudes(multiplied by 1024).
+ * - indexed by "smoothness setting" and log2(frequency).
+ *
+ * @note TGP_FREQUENCY_MAX + 1 values as the first value is the scale.
+ * @see HeightMapGenerate()
+ */
+static const amplitude_t _amplitudes_by_smoothness_and_frequency[7][TGP_FREQUENCY_MAX + 1] = {
+	/* lowest frequency....  ...highest (every corner) */
+	/* Very smooth */
+	{ 2143, 27832, 51429, 51657, 41657, 51429, 1597, 233, 37, 16},   // backup good one except mountainous 2048 * 2048
+	/* Smooth */
+	{ 6448, 911, 27832, 31131, 16511, 1427, 1597, 233, 29, 8},       // test reduce peaks
+	/* Rough */
+	{17657, 29832, 36832, 51429, 16511, 51429, 233, 1597, 1301, 16}, // backup good one except mountainous 2048 * 2048
+	/* Very Rough */
+	{17657, 6448, 36832, 51429, 16511, 17657, 233, 1597, 1301, 16},  // backup good one except mountainous 2048 * 2048
+	/* Cereally rough -bonus- */
+	{ 17657, 31832, 39832, 29832, 16511, 43429, 233, 2597, 37, 16},  // test reduce peaks
+	/* CommutorZ -bonus- */
+	{25000, 10000, 8000, 24000, 12000, 2500, 250, 100, 80, 25},      // backup good one. all mapsizes. No islands.
+	/* Go with the flow -bonus- */
+	{13511, 22739, 51429, 253, 421, 21131, 137, 7, 37, 261}          // backup good one. all mapsizes. No islands.
+};
 
 /**
- * Noise amplitudes (multiplied by 1024)
- * - indexed by "smoothness setting" and log2(frequency)
+ * Array holding some extra smoothing parameters that are applied after _amplitudes_and_frequency.
+ * They represent in order of appearance :
+ * { smoothing radius, power of smoothing (1= smoothest, 10 = almost unsmoothed), min. smoothing step size }
+ *
+ * @see Smooth()
  */
-static const amplitude_t _amplitudes_by_smoothness_and_frequency[4][TGP_FREQUENCY_MAX + 1] = {
-	/* lowest frequncy....  ...highest (every corner) */
-	/* Very smooth */
-	{16000,  5600,  1968,   688,   240,    16,    16},
-	/* Smooth */
-	{16000, 16000,  6448,  3200,  1024,   128,    16},
-	/* Rough */
-	{16000, 19200, 12800,  8000,  3200,   256,    64},
-	/* Very Rough */
-	{24000, 16000, 19200, 16000,  8000,   512,   320},
+static const int _smoothing_parameters[7][3] = {
+	{3, 3, 8}, ///< Very  smooth
+	{4, 3, 8}, ///< Smooth
+	{2, 7, 8}, ///< Rough
+	{2, 4, 8}, ///< Very rough
+	{2, 5, 8}, ///< Cereally rough - bonus -
+	{2, 6, 8}, ///< CommutorZ - bonus -
+	{2, 5, 4}  ///< Go with the flow - bonus -
 };
 
 /** Desired water percentage (100% == 1024) - indexed by _settings_game.difficulty.quantity_sea_lakes */
-static const amplitude_t _water_percent[4] = {20, 80, 250, 400};
+static const amplitude_t _water_percent[4] = {70, 170, 270, 420};
 
-/** Desired maximum height - indexed by _settings_game.difficulty.terrain_type */
-static const int8 _max_height[4] = {
-	6,       ///< Very flat
-	9,       ///< Flat
-	12,      ///< Hilly
-	15       ///< Mountainous
+/**
+ * Desired maximum height - indexed by _settings_game.difficulty.terrain_type and the map size.
+ *
+ * Sense of indexing by mapsize too:
+ * Below, h_max_new is calculated as min(map_size_x, map_size_y) / the constant defined here.
+ * Later, for calculating the height of some individual tile, the formula:
+ *  h_max_new * (h - h_waterlevel) / (h_max - h_waterlevel), where h_max is the maximal heightlevel
+ * existing anywhere on the map at the time of that computation step.
+ * So, to summarize:
+ * For mapsize 64x64, the above division gives 1. And, h - h_waterlevel is always
+ * smaller than h_max - h_waterlevel. So, the result is a map consisting just of water
+ * - i.e. at heightlevel 0 :-/.
+ * My conclusion was:
+ * Indexing this setting by the mapsize is a good thing, as one gains much more
+ * control on the heightlevel distribution of maps now and small maps work at all.
+ * The n-th value of the second component is for log(min(map_size_x, map_size_y)) - 6, so
+ * index 0 is for map size 64, whereas index 8 is for map size 8192.
+ */
+static const int _max_height[7][9] = {
+	{32, 48, 72, 170, 340, 680, 1360, 2720, 5440}, ///< Fallen... cant get up
+	{21, 40, 50,  64, 128, 380,  760, 1520, 3040}, ///< Very flat
+	{16, 27, 38,  51, 102, 204,  408,  916, 1832}, ///< Flat
+	{12, 21, 30,  39,  60, 120,  240,  480,  960}, ///< Bumpy
+	{10, 13, 17,  20,  33,  66,  132,  264,  528}, ///< Hilly
+	{9,  10, 11,  12,  13,  24,   48,   96,  192}, ///< Mountainous
+	{5,   6,  7,   7,   7,  12,   24,   48,   96}  ///< Alpinist
 };
 
 /**
@@ -242,7 +287,6 @@
 	return ((int)x) >= 0 && x < _height_map.size_x && ((int)y) >= 0 && y < _height_map.size_y;
 }
 
-
 /**
  * Allocate array of (MapSizeX()+1)*(MapSizeY()+1) heights and init the _height_map structure members
  * @return true on success
@@ -308,8 +352,11 @@
 static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
 {
 	uint size_min = min(_height_map.size_x, _height_map.size_y);
-	uint step = size_min >> log_frequency;
-	uint x, y;
+	int step = size_min >> log_frequency;
+	int x, y;
+
+	height_t* temp_height_map;
+	temp_height_map = CallocT<height_t>(_height_map.total_size);
 
 	/* Trying to apply noise to uninitialized height map */
 	assert(_height_map.h != NULL);
@@ -319,8 +366,8 @@
 
 	if (log_frequency == 0) {
 		/* This is first round, we need to establish base heights with step = size_min */
-		for (y = 0; y <= _height_map.size_y; y += step) {
-			for (x = 0; x <= _height_map.size_x; x += step) {
+		for (y = 0; y <= (int)_height_map.size_y; y += step) {
+			for (x = 0; x <= (int)_height_map.size_x; x += step) {
 				height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
 				_height_map.height(x, y) = height;
 			}
@@ -330,8 +377,8 @@
 
 	/* It is regular iteration round.
 	 * Interpolate height values at odd x, even y tiles */
-	for (y = 0; y <= _height_map.size_y; y += 2 * step) {
-		for (x = 0; x < _height_map.size_x; x += 2 * step) {
+	for (y = 0; y <= (int)_height_map.size_y; y += 2 * step) {
+		for (x = 0; x < (int)_height_map.size_x; x += 2 * step) {
 			height_t h00 = _height_map.height(x + 0 * step, y);
 			height_t h02 = _height_map.height(x + 2 * step, y);
 			height_t h01 = (h00 + h02) / 2;
@@ -340,8 +387,8 @@
 	}
 
 	/* Interpolate height values at odd y tiles */
-	for (y = 0; y < _height_map.size_y; y += 2 * step) {
-		for (x = 0; x <= _height_map.size_x; x += step) {
+	for (y = 0; y < (int)_height_map.size_y; y += 2 * step) {
+		for (x = 0; x <= (int)_height_map.size_x; x += step) {
 			height_t h00 = _height_map.height(x, y + 0 * step);
 			height_t h20 = _height_map.height(x, y + 2 * step);
 			height_t h10 = (h00 + h20) / 2;
@@ -350,8 +397,8 @@
 	}
 
 	/* Add noise for next higher frequency (smaller steps) */
-	for (y = 0; y <= _height_map.size_y; y += step) {
-		for (x = 0; x <= _height_map.size_x; x += step) {
+	for (y = 0; y <= (int)_height_map.size_y; y += step) {
+		for (x = 0; x <= (int)_height_map.size_x; x += step) {
 			_height_map.height(x, y) += RandomHeight(amplitude);
 		}
 	}
@@ -359,6 +406,60 @@
 	return (step > 1);
 }
 
+/**
+ * This function prevents inverted pyramids on map generation by applying some extra smoothing.
+ *
+ * @param log_frequency what round of mapgeneration are we in?
+ * @param radius   The radius to use for the extra smoothing.
+ * @param weakness The strongness / weakness  for the extra smoothing.
+ * @param min_step The step in tiles before I apply the extra smoothing again.
+ * @see HeightMapGenerate()
+ */
+void Smooth(uint log_frequency, int radius, int weakness, int min_step)
+{
+	uint size_min = min(_height_map.size_x, _height_map.size_y);
+	int step = size_min >> log_frequency;
+
+	if(step < min_step) {
+		return;
+	} else {
+		if(step < min_step * 2) {
+			weakness += 4;
+		}
+	}
+
+	height_t* temp_height_map;
+	temp_height_map = CallocT<height_t>(_height_map.total_size);
+
+	for (uint y = 0; y <= _height_map.size_y; y += step) {
+		for (uint x = 0; x <= _height_map.size_x; x += step) {
+			temp_height_map[x + y * _height_map.size_x] = _height_map.height(x, y);
+		}
+	}
+
+	for (uint y = 0; y <= _height_map.size_y; y += step) {
+		for (uint x = 0; x <= _height_map.size_x; x += step) {
+			height_t current = temp_height_map[x + y * _height_map.size_x];
+			int sum = current * 100 * weakness;
+			int weights = 100 * weakness; // the inmost tile has the highest weight
+
+			for(int i = -radius; i <= radius; i++){
+				for(int j = -radius; j <= radius; j++){
+					if((i != 0 || j != 0) && x + i * step <= _height_map.size_x
+							&& x + i * step > 0 && y + j * step <= _height_map.size_y
+							&& y + j * step > 0) {
+						int square = (int) sqrt((double)(i * i + j * j));
+						sum += temp_height_map[x + i * step + (y + j * step) * _height_map.size_x] * 100 / square;
+						weights += 100 / square;
+					}
+				}
+			}
+
+			_height_map.height(x, y) = sum / weights;
+		}
+	}
+}
+
 /** Base Perlin noise generator - fills height map with raw Perlin noise */
 static void HeightMapGenerate()
 {
@@ -379,6 +480,7 @@
 	/* Keep increasing the frequency until we reach the step size equal to one tile */
 	do {
 		log_frequency = iteration_round - log_frequency_min;
+
 		if (log_frequency >= 0) {
 			/* Apply noise for the next frequency */
 			assert(log_frequency <= TGP_FREQUENCY_MAX);
@@ -387,10 +489,26 @@
 			/* Amplitude for the low frequencies on big maps is 0, i.e. initialise with zero height */
 			amplitude = 0;
 		}
+
 		continue_iteration = ApplyNoise(iteration_round, amplitude);
+
+		if(amplitude > 0) {
+			/* Apply some extra parameters to prevent inverted pyramids. */
+			Smooth(iteration_round, _smoothing_parameters[_settings_game.game_creation.tgen_smoothness][0],
+					_smoothing_parameters[_settings_game.game_creation.tgen_smoothness][1],
+					_smoothing_parameters[_settings_game.game_creation.tgen_smoothness][2]);
+		}
+
 		iteration_round++;
+
 	} while (continue_iteration);
-	assert(log_frequency == TGP_FREQUENCY_MAX);
+
+	assert(log_frequency <= TGP_FREQUENCY_MAX);
+
+	if (log_frequency != TGP_FREQUENCY_MAX) {
+		DEBUG(map, 0, "Frequency wrong: log_frequency = %i, TGP_FREQUENCY_MAX = %i",
+				log_frequency, TGP_FREQUENCY_MAX);
+	}
 }
 
 /** Returns min, max and average height from height map */
@@ -434,6 +552,12 @@
 /** Applies sine wave redistribution onto height map */
 static void HeightMapSineTransform(height_t h_min, height_t h_max)
 {
+	if ((_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_VERY_ROUGH)
+			|| (_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_CEREALLY_ROUGH)) {
+		/* Make the map really rough for very rough and cereally rough settings, skip this function. */
+		return;
+	}
+
 	height_t *h;
 
 	FOR_ALL_TILES_IN_HEIGHT(h) {
@@ -447,12 +571,14 @@
 		switch (_settings_game.game_creation.landscape) {
 			case LT_TOYLAND:
 			case LT_TEMPERATE:
-				/* Move and scale 0..1 into -1..+1 */
-				fheight = 2 * fheight - 1;
-				/* Sine transform */
-				fheight = sin(fheight * M_PI_2);
-				/* Transform it back from -1..1 into 0..1 space */
-				fheight = 0.5 * (fheight + 1);
+				{
+					/* Move and scale 0..1 into -1..+1 */
+					fheight = 2 * fheight - 1;
+					/* Sine transform */
+					fheight = sin(fheight * M_PI_2);
+					/* Transform it back from -1..1 into 0..1 space */
+					fheight = 0.5 * (fheight + 1);
+				}
 				break;
 
 			case LT_ARCTIC:
@@ -643,6 +769,61 @@
 	}
 }
 
+/* TODO:
+ * Temp solution for applying curves with the more heightlevels patch enabled.
+ * 1 / 2
+ * Cut untill End when fixed.
+ */
+
+/**
+ * Applies variation to the map if AllowMoreHeightlevels() is true and the variety setting is not set to none.
+ *
+ * @note for the moment there is only one variation for all settings
+ * @note It would be nice to have a few more variation options if AllowMoreHeigtlevels() is true.
+ */
+struct MHScontrol_point_t {
+	height_t x;
+	height_t y;
+};
+
+static const MHScontrol_point_t _curve_map[] = {
+	{ 0, 0 }, { 48, 48 }, { 96, 72 }, { 160, 128 }, { 192, 160 }, { 240, 255}, { 255, 255 }
+};
+
+static void MHSHeightMapCurves()
+{
+	height_t h_min, h_max, h_avg, h_diff;
+	HeightMapGetMinMaxAvg(&h_min, &h_max, &h_avg);
+	h_diff = h_max - h_min;
+
+	/* "Normalize" the control points to the height map data */
+	MHScontrol_point_t *cm = MallocT<MHScontrol_point_t>(lengthof(_curve_map));
+	for (uint i = 0; i < lengthof(_curve_map); i++) {
+		cm[i].x = _curve_map[i].x * h_diff / 255 + h_min;
+		cm[i].y = _curve_map[i].y * h_diff / 255 + h_min;
+	}
+
+	/* Apply curve */
+	height_t *h;
+	FOR_ALL_TILES_IN_HEIGHT(h) {
+		for (uint i = 0; i < lengthof(_curve_map) - 1; i++) {
+			MHScontrol_point_t &p1 = cm[i];
+			MHScontrol_point_t &p2 = cm[i + 1];
+
+			if (*h >= p1.x && *h <= p2.x) {
+				*h = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
+				break;
+			}
+		}
+	}
+
+	free(cm);
+}
+/*
+ * End temp solution for applying curves with the more heightlevels patch enabled.
+ * 1 / 2
+ */
+
 /** Adjusts heights in height map to contain required amount of water tiles */
 static void HeightMapAdjustWaterLevel(amplitude_t water_percent, height_t h_max_new)
 {
@@ -670,8 +851,8 @@
 	/* We now have the proper water level value.
 	 * Transform the height map into new (normalized) height map:
 	 *   values from range: h_min..h_water_level will become negative so it will be clamped to 0
-	 *   values from range: h_water_level..h_max are transformed into 0..h_max_new
-	 *   where h_max_new is 4, 8, 12 or 16 depending on terrain type (very flat, flat, hilly, mountains)
+	 *   values from range: h_water_level..h_max are transformed into 0..h_max_new,
+	 *   where h_max_new is dependant on _settings_game.difficulty.terrain_type. (_max_height)
 	 */
 	FOR_ALL_TILES_IN_HEIGHT(h) {
 		/* Transform height from range h_water_level..h_max into 0..h_max_new range */
@@ -705,6 +886,8 @@
  *
  * Please note that all the small numbers; 53, 101, 167, etc. are small primes
  * to help give the perlin noise a bit more of a random feel.
+ *
+ * @note This function shapes map border coasts.
  */
 static void HeightMapCoastLines(uint8 water_borders)
 {
@@ -719,7 +902,7 @@
 		if (HasBit(water_borders, BORDER_NE)) {
 			/* Top right */
 			max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.9, 53) + 0.25) * 5 + (perlin_coast_noise_2D(y, y, 0.35, 179) + 1) * 12);
-			max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
+			max_x = max((smallest_size * smallest_size / 64) + max_x, (smallest_size * smallest_size / 64) + margin - max_x);
 			if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
 			for (x = 0; x < max_x; x++) {
 				_height_map.height(x, y) = 0;
@@ -729,7 +912,7 @@
 		if (HasBit(water_borders, BORDER_SW)) {
 			/* Bottom left */
 			max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.85, 101) + 0.3) * 6 + (perlin_coast_noise_2D(y, y, 0.45,  67) + 0.75) * 8);
-			max_x = max((smallest_size * smallest_size / 16) + max_x, (smallest_size * smallest_size / 16) + margin - max_x);
+			max_x = max((smallest_size * smallest_size / 64) + max_x, (smallest_size * smallest_size / 64) + margin - max_x);
 			if (smallest_size < 8 && max_x > 5) max_x /= 1.5;
 			for (x = _height_map.size_x; x > (_height_map.size_x - 1 - max_x); x--) {
 				_height_map.height(x, y) = 0;
@@ -742,7 +925,7 @@
 		if (HasBit(water_borders, BORDER_NW)) {
 			/* Top left */
 			max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 2, 0.9, 167) + 0.4) * 5 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.4, 211) + 0.7) * 9);
-			max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
+			max_y = max((smallest_size * smallest_size / 64) + max_y, (smallest_size * smallest_size / 64) + margin - max_y);
 			if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
 			for (y = 0; y < max_y; y++) {
 				_height_map.height(x, y) = 0;
@@ -752,7 +935,7 @@
 		if (HasBit(water_borders, BORDER_SE)) {
 			/* Bottom right */
 			max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.85, 71) + 0.25) * 6 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.35, 193) + 0.75) * 12);
-			max_y = max((smallest_size * smallest_size / 16) + max_y, (smallest_size * smallest_size / 16) + margin - max_y);
+			max_y = max((smallest_size * smallest_size / 64) + max_y, (smallest_size * smallest_size / 64) + margin - max_y);
 			if (smallest_size < 8 && max_y > 5) max_y /= 1.5;
 			for (y = _height_map.size_y; y > (_height_map.size_y - 1 - max_y); y--) {
 				_height_map.height(x, y) = 0;
@@ -761,9 +944,19 @@
 	}
 }
 
-/** Start at given point, move in given direction, find and Smooth coast in that direction */
+/**
+ * Start at given point, move in given direction, find and Smooth coast in that direction
+ *
+ * @note This function shapes normal map coasts.
+ */
 static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int dir_y)
 {
+	if ((_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_VERY_ROUGH)
+			|| (_settings_game.game_creation.tgen_smoothness == SMOOTHNESS_CEREALLY_ROUGH)) {
+		/* Make the map really rough for very rough and cereally rough settings, skip this function. */
+		return;
+	}
+
 	const int max_coast_dist_from_edge = 35;
 	const int max_coast_Smooth_depth = 35;
 
@@ -771,7 +964,7 @@
 	int ed; // coast distance from edge
 	int depth;
 
-	height_t h_prev = 16;
+	height_t h_prev = min(_height_map.size_x + 1, _height_map.size_y + 1) / TGP_HEIGHT_FACTOR;
 	height_t h;
 
 	assert(IsValidXY(org_x, org_y));
@@ -779,7 +972,7 @@
 	/* Search for the coast (first non-water tile) */
 	for (x = org_x, y = org_y, ed = 0; IsValidXY(x, y) && ed < max_coast_dist_from_edge; x += dir_x, y += dir_y, ed++) {
 		/* Coast found? */
-		if (_height_map.height(x, y) > 15) break;
+		if (_height_map.height(x, y) > (int)(min(_height_map.size_x + 1, _height_map.size_y + 1) / TGP_HEIGHT_FACTOR - 1)) break;
 
 		/* Coast found in the neighborhood? */
 		if (IsValidXY(x + dir_y, y + dir_x) && _height_map.height(x + dir_y, y + dir_x) > 0) break;
@@ -839,6 +1032,21 @@
 }
 
 /**
+ * Gets the maximum allowed height while generating a map
+ * based on mapsize, terrain_type and the setting to allow moreheightlevels.
+ */
+static int TGPGetMaxAllowedHeight()
+{
+	/* Subtract 6 because the value for map size 64 = 2^6
+	 * is stored at index 0 in the array.
+	 * @See discussion at the definition of _max_height */
+	const int map_size_index_in_mh = min(MapLogX(), MapLogY()) - 6;
+	const int mh = _max_height[_settings_game.difficulty.terrain_type][map_size_index_in_mh];
+	const int retValue = I2H(min((min(_height_map.size_x + 1, _height_map.size_y + 1)) / mh, GetMaxTileHeight()));
+	return retValue;
+}
+
+/**
  * Height map terraform post processing:
  *  - water level adjusting
  *  - coast Smoothing
@@ -849,7 +1057,7 @@
 {
 	int sea_level_setting = _settings_game.difficulty.quantity_sea_lakes;
 	const amplitude_t water_percent = sea_level_setting != (int)CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY ? _water_percent[sea_level_setting] : _settings_game.game_creation.custom_sea_level * 1024 / 100;
-	const height_t h_max_new = I2H(_max_height[_settings_game.difficulty.terrain_type]);
+	const height_t h_max_new = TGPGetMaxAllowedHeight() + 1;
 	const height_t roughness = 7 + 3 * _settings_game.game_creation.tgen_smoothness;
 
 	HeightMapAdjustWaterLevel(water_percent, h_max_new);
@@ -865,10 +1073,27 @@
 
 	HeightMapSineTransform(12, h_max_new);
 
-	if (_settings_game.game_creation.variety > 0) {
+/* TODO:
+ * Temp solution for applying curves with the more heightlevels patch enabled.
+ * 2 / 2
+ * Revert to code below, untill End when fixed.
+//	if (_settings_game.game_creation.variety > 0) {
+//		HeightMapCurves(_settings_game.game_creation.variety);
+//	}
+ */
+	if ((_settings_game.game_creation.variety > 0) && (!AllowMoreHeightlevels()) && (_settings_game.game_creation.landscape == 1)) {
 		HeightMapCurves(_settings_game.game_creation.variety);
 	}
 
+	if ((_settings_game.game_creation.variety > 0) && (AllowMoreHeightlevels()) && (_settings_game.game_creation.landscape == 1)) {
+		MHSHeightMapCurves();
+	}
+
+/* TODO:
+ * End temp solution for applying curves with the more heightlevels patch enabled.
+ * 2 / 2
+ */
+
 	HeightMapSmoothSlopes(16);
 }
 
@@ -985,12 +1210,25 @@
 		for (x = 0; x < _height_map.size_x;     x++) MakeVoid(x);
 	}
 
+	const int mh = H2I(TGPGetMaxAllowedHeight());
+
 	/* Transfer height map into OTTD map */
 	for (y = 0; y < _height_map.size_y; y++) {
 		for (x = 0; x < _height_map.size_x; x++) {
 			int height = H2I(_height_map.height(x, y));
-			if (height < 0) height = 0;
-			if (height > 15) height = 15;
+
+			if (height < 0) {
+				height = 0;
+			}
+
+			if (height > mh - 1) {
+				height = mh - 1;
+			}
+
+			if (height > (int)GetMaxTileHeight()) {
+				height = GetMaxTileHeight();
+			}
+
 			TgenSetTileHeight(TileXY(x, y), height);
 		}
 	}
diff --git a/src/tgp.h b/src/tgp.h
--- a/src/tgp.h
+++ b/src/tgp.h
@@ -12,6 +12,21 @@
 #ifndef TGP_H
 #define TGP_H
 
+static const uint TGP_HEIGHT_FACTOR = 8;
+
+/** Maximum index into array of noise amplitudes. */
+static const int TGP_FREQUENCY_MAX = 9;
+
+enum Smoothness {
+	SMOOTHNESS_VERY_SMOOTH      = 0,
+	SMOOTHNESS_SMOOTH           = 1,
+	SMOOTHNESS_ROUGH            = 2,
+	SMOOTHNESS_VERY_ROUGH       = 3,
+	SMOOTHNESS_CEREALLY_ROUGH   = 4,
+	SMOOTHNESS_COMMUTORZ        = 5,
+	SMOOTHNESS_GO_WITH_THE_FLOW = 6,
+};
+
 void GenerateTerrainPerlin();
 
 #endif /* TGP_H */
diff --git a/src/tile_map.cpp b/src/tile_map.cpp
--- a/src/tile_map.cpp
+++ b/src/tile_map.cpp
@@ -12,8 +12,46 @@
 #include "stdafx.h"
 #include "tile_map.h"
 
+static Slope GetTileSlopeGivenHeight(uint hnorth, uint hwest, uint heast, uint hsouth, uint *h) {
+
+	/* Due to the fact that tiles must connect with each other without leaving gaps, the
+	 * biggest difference in height between any corner and 'min' is between 0, 1, or 2.
+	 *
+	 * Also, there is at most 1 corner with height difference of 2. */
+
+	uint hminnw = min(hnorth, hwest);
+	uint hmines = min(heast, hsouth);
+	uint hmin = min(hminnw, hmines);
+
+	uint hmaxnw = max(hnorth, hwest);
+	uint hmaxes = max(heast, hsouth);
+	uint hmax = max(hmaxnw, hmaxes);
+
+	uint r = SLOPE_FLAT; ///< Computed slope of the tile.
+
+	if (hnorth != hmin) {
+		r += SLOPE_N;
+	}
+	if (hwest != hmin) {
+		r += SLOPE_W;
+	}
+	if (heast != hmin) {
+		r += SLOPE_E;
+	}
+	if (hsouth != hmin) {
+		r += SLOPE_S;
+	}
+	if (hmax - hmin == 2) {
+		r += SLOPE_STEEP;
+	}
+
+	if (h != NULL) *h = hmin * TILE_HEIGHT;
+
+	return (Slope)r;
+}
+
 /**
- * Return the slope of a given tile
+ * Return the slope of a given tile inside the map.
  * @param tile Tile to compute slope of
  * @param h    If not \c NULL, pointer to storage of z height
  * @return Slope of the tile, except for the HALFTILE part
@@ -92,3 +130,21 @@
 
 	return h;
 }
+
+/**
+ * Get top height of the tile the outside map.
+ *
+ * @see Detailed description in header.
+ *
+ * @param tile Tile outside to compute height of.
+ * @return Maximum height of the tile.
+ */
+uint GetTileMaxZOutsideMap(int x, int y)
+{
+	uint h = TileHeightOutsideMap(x, y);
+	h = max(h, TileHeightOutsideMap(x + 1, y));
+	h = max(h, TileHeightOutsideMap(x, y + 1));
+	h = max(h, TileHeightOutsideMap(x + 1, y + 1));
+
+	return h * TILE_HEIGHT;
+}
diff --git a/src/tile_map.h b/src/tile_map.h
--- a/src/tile_map.h
+++ b/src/tile_map.h
@@ -15,40 +15,159 @@
 #include "slope_type.h"
 #include "map_func.h"
 #include "core/bitmath_func.hpp"
+#include "core/math_func.hpp"
 #include "settings_type.h"
 
 /**
- * Returns the height of a tile
+ * Returns wether more than 16 height levels are allowed.
+ * Basically, this returns the setting of the configuration variable
+ * allow_more_heightlevels.
+ * To avoid having to change multiple occurrences of the config variable
+ * in case some additional condition would get necessary,
+ * I introduced this function.
  *
- * This function returns the height of the northern corner of a tile.
+ * @return wether more than 16 height levels are allowed, based on allow_more_heightlevels and game mode.
+ */
+static inline bool AllowMoreHeightlevels()
+{
+	return _settings_game.construction.allow_more_heightlevels;
+}
+
+/**
+ * Returns the maximum heightlevel of a tile based on AllowMoreHeightlevels().
+ * This deduplicates a few if else statements in the code therefore it is usefull to have it here.
+ *
+ *@return MAX_TILE_HEIGHT_EXTENDED or MAX_TILE_HEIGHT_OLD based on AllowMoreHeightlevels().
+ */
+static inline uint GetMaxTileHeight()
+{
+	if (AllowMoreHeightlevels()) {
+		return MAX_TILE_HEIGHT_EXTENDED;
+	} else {
+		return MAX_TILE_HEIGHT_OLD;
+	}
+}
+
+/**
+ * Returns the maximum snowline height based on AllowMoreHeightlevels().
+ * This deduplicates a few if else statements in the code therefore it is usefull to have it here.
+ *
+ * @return MAX_SNOWLINE_HEIGHT_EXTENDED or MAX_SNOWLINE_HEIGHT_OLD based on AllowMoreHeightlevels(). 
+ */
+static inline uint GetMaxSnowlineHeight()
+{
+	if (AllowMoreHeightlevels()) {
+		return MAX_SNOWLINE_HEIGHT_EXTENDED;
+	} else {
+		return MAX_SNOWLINE_HEIGHT_OLD;
+	}
+}
+
+/**
+ * This function returns the maximum treeline height based on AllowMoreHeightlevels().
+ * This deduplicates a few if else statements in the code therefore it is usefull to have it here.
+ *
+ * @return MAX_TREELINE_HEIGHT_EXTENDED or MAX_TREELINE_HEIGHT_OLD based on AllowMoreHeightlevels().
+ */
+static inline uint GetMaxTreelineHeight()
+{
+	if (AllowMoreHeightlevels()) {
+		return MAX_TREELINE_HEIGHT_EXTENDED;
+	} else {
+		return MAX_TREELINE_HEIGHT_OLD;
+	}
+}
+
+/**
+ * This function returns the height of the northern corner of a tile based on AllowMoreHeightlevels().
  * This is saved in the global map-array. It does not take affect by
  * any slope-data of the tile.
  *
- * @param tile The tile to get the height from
- * @return the height of the tile
+ * @param tile The tile to get the height from.
+ * @return the height of the tile.
  * @pre tile < MapSize()
  */
 static inline uint TileHeight(TileIndex tile)
 {
 	assert(tile < MapSize());
-	return GB(_m[tile].type_height, 0, 4);
+
+	if (AllowMoreHeightlevels()) {
+		return _map_heightdata[tile].heightlevel;
+	} else {
+		return GB(_m[tile].type_height, 0, 4);
+	}
 }
 
 /**
- * Sets the height of a tile.
- *
- * This function sets the height of the northern corner of a tile.
+ * For a detailed description why we need this see discussion in
+ * GetTileMaxZOutsideMap in map_func.h.
+ */
+static inline uint TileHeightOutsideMap(int x, int y)
+{
+	/* In all cases: Descend to heightlevel 0 as fast as possible.
+	 * So: If we are at the 0-side of the map (x<0 or y<0), we must
+	 * subtract the distance to coordinate 0 from the heightlevel.
+	 * In other words: Subtract e.g. -x. If we are at the MapMax
+	 * side of the map, we also need to subtract the distance to
+	 * the edge of map, e.g. MapMaxX - x.
+	 *
+	 * NOTE: Assuming constant heightlevel outside map would be
+	 * simpler here. However, then we run into painting problems,
+	 * since whenever a heightlevel change at the map border occurs,
+	 * we would need to repaint anything outside map.
+	 * In contrast, by doing it this way, we can localize this change,
+	 * which means we may assume constant heightlevel for all tiles
+	 * at more than <heightlevel at map border> distance from the
+	 * map border. */
+	if (x < 0) {
+		if (y < 0) {
+			return max((int)TileHeight(TileXY(0, 0)) - (-x) - (-y), 0);
+		} else if (y < (int)MapMaxY()) {
+			return max((int)TileHeight(TileXY(0, y)) - (-x), 0);
+		} else {
+			return max((int)TileHeight(TileXY(0, (int)MapMaxY())) - (-x) - (y - (int)MapMaxY()), 0);
+		}
+	} else if (x < (int)MapMaxX()) {
+		if (y < 0) {
+			return max((int)TileHeight(TileXY(x, 0)) - (-y), 0);
+		} else if (y < (int)MapMaxY()) {
+			return TileHeight(TileXY(x, y));
+		} else {
+			return max((int)TileHeight(TileXY(x, (int)MapMaxY())) - (y - (int)MapMaxY()), 0);
+		}
+	} else {
+		if (y < 0) {
+			return max((int)TileHeight(TileXY((int)MapMaxX(), 0)) - (x - (int)MapMaxX()) - (-y), 0);
+		} else if (y < (int)MapMaxY()) {
+			return max((int)TileHeight(TileXY((int)MapMaxX(), y)) - (x - (int)MapMaxX()), 0);
+		} else {
+			return max((int)TileHeight(TileXY((int)MapMaxX(), (int)MapMaxY())) - (x - (int)MapMaxX()) - (y - (int)MapMaxY()), 0);
+		}
+	}
+}
+
+/**
+ * This function sets the height of the northern corner of a tile based on AllowMoreHeightlevels().
  *
  * @param tile The tile to change the height
  * @param height The new height value of the tile
  * @pre tile < MapSize()
- * @pre heigth <= MAX_TILE_HEIGHT
+ * @pre heigth <= GetMaxTileHeight()
  */
 static inline void SetTileHeight(TileIndex tile, uint height)
 {
 	assert(tile < MapSize());
-	assert(height <= MAX_TILE_HEIGHT);
-	SB(_m[tile].type_height, 0, 4, height);
+
+	if (height > GetMaxTileHeight()) {
+		/* Make sure height is within allowed range. */
+		height = GetMaxTileHeight();
+	}
+
+	if (AllowMoreHeightlevels()) {
+		_map_heightdata[tile].heightlevel = height;
+	} else {
+		SB(_m[tile].type_height, 0, 4, height);
+	}
 }
 
 /**
diff --git a/src/tile_type.h b/src/tile_type.h
--- a/src/tile_type.h
+++ b/src/tile_type.h
@@ -18,12 +18,24 @@
 static const uint TILE_PIXELS    = 32;            ///< a tile is 32x32 pixels
 static const uint TILE_HEIGHT    =  8;            ///< The standard height-difference between tiles on two levels is 8 (z-diff 8)
 
-static const uint MAX_TILE_HEIGHT     = 15;                    ///< Maximum allowed tile height
+static const uint MAX_TILE_HEIGHT_OLD          = 15;  ///< Maximum allowed tile height - originally :-)
+static const uint MAX_TILE_HEIGHT_EXTENDED     = 255; ///< Maximum allowed tile height using the more heightlevels patch
 
-static const uint MIN_SNOWLINE_HEIGHT = 2;                     ///< Minimum snowline height
-static const uint DEF_SNOWLINE_HEIGHT = 7;                     ///< Default snowline height
-static const uint MAX_SNOWLINE_HEIGHT = (MAX_TILE_HEIGHT - 2); ///< Maximum allowed snowline height
+static const uint MIN_SNOWLINE_HEIGHT          = 2;                              ///< Minimum snowline height
+static const uint DEF_SNOWLINE_HEIGHT_OLD      = 7;                              ///< Default snowline height - originally
+static const uint DEF_SNOWLINE_HEIGHT_EXTENDED = 24;                             ///< Default snowline height using the more heightlevels patch
+static const uint MAX_SNOWLINE_HEIGHT_OLD      = (MAX_TILE_HEIGHT_OLD - 2);      ///< Maximum allowed snowline height - originally
+static const uint MAX_SNOWLINE_HEIGHT_EXTENDED = (MAX_TILE_HEIGHT_EXTENDED - 2); ///< Maximum allowed snowline height using the more heightlevels patch
 
+static const uint MIN_DESERT_AMOUNT = 4;   ///< Minimum allowed desert amount.
+static const uint DEF_DESERT_AMOUNT = 7;   ///< Default desert amount.
+static const uint MAX_DESERT_AMOUNT = 200; ///< Maximum allowed desert amount.
+
+static const uint MIN_TREELINE_HEIGHT          = 0;                        ///< Minimum allowed treeline height
+static const uint DEF_TREELINE_HEIGHT_OLD      = MAX_TILE_HEIGHT_OLD;      ///< Default treeline height - originally
+static const uint DEF_TREELINE_HEIGHT_EXTENDED = MAX_TILE_HEIGHT_EXTENDED; ///< Default treeline height using the more heightlevels patch 
+static const uint MAX_TREELINE_HEIGHT_OLD      = MAX_TILE_HEIGHT_OLD;      ///< Maximum allowed treeline height -originally
+static const uint MAX_TREELINE_HEIGHT_EXTENDED = MAX_TILE_HEIGHT_EXTENDED; ///< Maximum allowed treeline height using the more heightlevels patch
 
 /**
  * The different types of tiles.
diff --git a/src/tilehighlight_type.h b/src/tilehighlight_type.h
--- a/src/tilehighlight_type.h
+++ b/src/tilehighlight_type.h
@@ -17,6 +17,7 @@
 #include "tile_type.h"
 #include "viewport_type.h"
 
+
 /** Highlighting draw styles */
 enum HighLightStyle {
 	HT_NONE      = 0x000, ///< default
@@ -28,7 +29,8 @@
 	HT_RAIL      = 0x080, ///< autorail (one piece), lower bits: direction
 	HT_VEHICLE   = 0x100, ///< vehicle is accepted as target as well (bitmask)
 	HT_DIAGONAL  = 0x200, ///< Also allow 'diagonal rectangles'. Only usable in combination with #HT_RECT or #HT_POINT.
-	HT_DRAG_MASK = 0x0F8, ///< Mask for the tile drag-type modes.
+	HT_PREVIEW   = 0x400, ///< used for CopyPaste Preview
+	HT_DRAG_MASK = 0x4F8, ///< Mask for the tile drag-type modes.
 
 	/* lower bits (used with HT_LINE and HT_RAIL):
 	 * (see ASCII art in table/autorail.h for a visual interpretation) */
diff --git a/src/timetable.h b/src/timetable.h
--- a/src/timetable.h
+++ b/src/timetable.h
@@ -15,6 +15,8 @@
 #include "date_type.h"
 #include "vehicle_type.h"
 
+#define WALLCLOCK_NETWORK_COMPATIBLE 0 ///< Whether wallclock should preserve network compatibility. If so, then timetable start dates cannot be set exactly using minutes.
+
 void ShowTimetableWindow(const Vehicle *v);
 void UpdateVehicleTimetable(Vehicle *v, bool travelling);
 void SetTimetableParams(int param1, int param2, Ticks ticks);
diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp
--- a/src/timetable_cmd.cpp
+++ b/src/timetable_cmd.cpp
@@ -15,6 +15,8 @@
 #include "date_func.h"
 #include "window_func.h"
 #include "vehicle_base.h"
+#include "tile_cmd.h"
+#include "settings_type.h"
 
 #include "table/strings.h"
 
@@ -67,6 +69,8 @@
  */
 CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
+	if (!_settings_game.order.timetabling) return CMD_ERROR;
+
 	VehicleID veh = GB(p1, 0, 20);
 
 	Vehicle *v = Vehicle::GetIfValid(veh);
@@ -124,6 +128,8 @@
  */
 CommandCost CmdSetVehicleOnTime(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
+	if (!_settings_game.order.timetabling) return CMD_ERROR;
+
 	VehicleID veh = GB(p1, 0, 20);
 
 	Vehicle *v = Vehicle::GetIfValid(veh);
@@ -151,17 +157,24 @@
  */
 CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
+	if (!_settings_game.order.timetabling) return CMD_ERROR;
+
 	Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20));
 	if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
 
 	CommandCost ret = CheckOwnership(v->owner);
 	if (ret.Failed()) return ret;
 
+	DateTicks start_date = (Date)p2 / DAY_TICKS;
+
+#if WALLCLOCK_NETWORK_COMPATIBLE
 	/* Don't let a timetable start more than 15 years into the future or 1 year in the past. */
-	Date start_date = (Date)p2;
 	if (start_date < 0 || start_date > MAX_DAY) return CMD_ERROR;
 	if (start_date - _date > 15 * DAYS_IN_LEAP_YEAR) return CMD_ERROR;
 	if (_date - start_date > DAYS_IN_LEAP_YEAR) return CMD_ERROR;
+#else
+	start_date = ((DateTicks)_date * DAY_TICKS) + _date_fract + (DateTicks)(int32)p2;
+#endif
 
 	if (flags & DC_EXEC) {
 		v->lateness_counter = 0;
@@ -190,6 +203,8 @@
  */
 CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
+	if (!_settings_game.order.timetabling) return CMD_ERROR;
+
 	VehicleID veh = GB(p1, 0, 20);
 
 	Vehicle *v = Vehicle::GetIfValid(veh);
@@ -230,6 +245,161 @@
 }
 
 /**
+ * Start or stop automatic management of the timetable.
+ * @param tile Not used.
+ * @param flags Operation to perform.
+ * @param p1 Vehicle index.
+ * @param p2 Various bitstuffed elements
+ * - p2 = (bit 0) - Set to 1 to enable, 0 to disable automation.
+ * - p2 = (bit 1) - Ctrl was pressed. Used when disabling to keep times.
+ * @param text unused
+ * @return the cost of this operation or an error
+ */
+CommandCost CmdAutomateTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	if (!_settings_game.order.timetable_automated) return CMD_ERROR;
+
+	VehicleID veh = GB(p1, 0, 16);
+
+	Vehicle *v = Vehicle::GetIfValid(veh);
+	if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
+
+	CommandCost ret = CheckOwnership(v->owner);
+	if (ret.Failed()) return ret;
+
+	if (flags & DC_EXEC) {
+		for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
+			if (HasBit(p2, 0)) {
+				/* Automate timetable. Set flags and clear current times. */
+				SetBit(v2->vehicle_flags, VF_AUTOMATE_TIMETABLE);
+				ClrBit(v2->vehicle_flags, VF_AUTOFILL_TIMETABLE);
+				ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
+				ClrBit(v2->vehicle_flags, VF_TIMETABLE_STARTED);
+				v2->timetable_start = 0;
+				v2->lateness_counter = 0;
+				v2->current_loading_time = 0;
+				v2->ClearSeparation();
+			} else {
+				/* De-automate timetable. Clear flags. */
+				ClrBit(v2->vehicle_flags, VF_AUTOMATE_TIMETABLE);
+				ClrBit(v2->vehicle_flags, VF_AUTOFILL_TIMETABLE);
+				ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
+				v2->ClearSeparation();
+				if (!HasBit(p2, 1)) {
+					/* Ctrl wasn't pressed, so clear all timetabled times. */
+					SetBit(v2->vehicle_flags, VF_TIMETABLE_STARTED);
+					v2->timetable_start = 0;
+					v2->lateness_counter = 0;
+					v2->current_loading_time = 0;
+					OrderList *orders = v2->orders.list;
+					if (orders != NULL) {
+						for (int i = 0; i < orders->GetNumOrders(); i++) {
+							ChangeTimetable(v2, i, 0, false);
+							ChangeTimetable(v2, i, 0, true);
+						}
+					}
+				}
+			}
+			SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
+		}
+	}
+
+	return CommandCost();
+}
+
+int TimeToFinishOrder(Vehicle *v, int n)
+{
+	int left;
+	Order *order = v->GetOrder(n);
+	assert(order != NULL);
+	if ((v->cur_real_order_index == n) && (v->last_station_visited == order->GetDestination())) {
+		if (order->wait_time == 0) return -1;
+		if (v->current_loading_time > 0) {
+			left = order->wait_time - v->current_order_time;
+		} else {
+			left = order->wait_time;
+		}
+		if (left < 0) left = 0;
+	} else {
+		left = order->travel_time;
+		if (v->cur_real_order_index == n) left -= v->current_order_time;
+		if (order->travel_time == 0 || order->wait_time == 0) return -1;
+		if (left < 0) left = 0;
+		left += order->wait_time;
+	}
+	return left;
+}
+
+int SeparationBetween(Vehicle *v1, Vehicle *v2)
+{
+	if(v1 == v2) return -1;
+	int separation = 0;
+	int time;
+	int n = v1->cur_real_order_index;
+	while (n != v2->cur_real_order_index) {
+		time = TimeToFinishOrder(v1, n);
+		if (time == -1) return -1;
+		separation += time;
+		n++;
+		if (n >= v1->GetNumOrders()) n = 0;
+	}
+	int time1 = TimeToFinishOrder(v1, n);
+	int time2 = TimeToFinishOrder(v2, n);
+	if (time1 == -1 || time2 == -1) return -1;
+	time = time1 - time2;
+	if (time < 0) {
+		for (n = 0; n < v1->GetNumOrders(); n++) {
+			Order *order = v1->GetOrder(n);
+			if (order->travel_time == 0 || order->wait_time == 0) return -1;
+			time += order->travel_time + order->wait_time;
+		}
+	}
+	separation += time;
+	assert(separation >= 0);
+	if (separation == 0) return -1;
+	return separation;
+}
+
+void UpdateSeparationOrder(Vehicle *v_start)
+{
+	/* First check if we have a vehicle ahead, and if not search for one. */
+	if (v_start->AheadSeparation() == NULL) {
+		v_start->InitSeparation();
+	}
+	if (v_start->AheadSeparation() == NULL) {
+		return;
+	}
+	/* Switch positions if necessary. */
+	int swaps = 0;
+	bool done = false;
+	while (!done) {
+		done = true;
+		int min_sep = SeparationBetween(v_start, v_start->AheadSeparation());
+		Vehicle *v = v_start;
+		do {
+			if (v != v_start) {
+				int tmp_sep = SeparationBetween(v_start, v);
+				if (tmp_sep < min_sep && tmp_sep != -1) {
+					swaps++;
+					if (swaps >= 50) {
+						return;
+					}
+					done = false;
+					v_start->ClearSeparation();
+					v_start->AddToSeparationBehind(v);
+					break;
+				}
+			}
+			int separation_ahead = SeparationBetween(v, v->AheadSeparation());
+			int separation_behind = SeparationBetween(v->BehindSeparation(), v);
+			v->lateness_counter = (separation_ahead - separation_behind) / 2;
+			if (separation_ahead == -1 || separation_behind == -1) v->lateness_counter = 0;
+			v = v->AheadSeparation();
+		} while (v != v_start);
+	}
+}
+
+/**
  * Update the timetable for the vehicle.
  * @param v The vehicle to update the timetable for.
  * @param travelling Whether we just travelled or waited at a station.
@@ -237,10 +407,14 @@
 void UpdateVehicleTimetable(Vehicle *v, bool travelling)
 {
 	uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time;
+	if (!travelling) v->current_loading_time++; // +1 because this time is one tick behind
 	uint time_taken = v->current_order_time;
+	uint time_loading = v->current_loading_time;
 
 	v->current_order_time = 0;
+	v->current_loading_time = 0;
 
+	if (!_settings_game.order.timetabling) return;
 	if (v->current_order.IsType(OT_IMPLICIT)) return; // no timetabling of auto orders
 
 	VehicleOrderID first_manual_order = 0;
@@ -250,6 +424,18 @@
 
 	bool just_started = false;
 
+	/* Start automated timetables at first opportunity */
+	if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED) && HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE)) {
+		if (_settings_game.order.timetable_separation) v->ClearSeparation();
+		SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
+		v->lateness_counter = 0;
+		if (_settings_game.order.timetable_separation) UpdateSeparationOrder(v);
+		for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
+			SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
+		}
+		return;
+	}
+
 	/* This vehicle is arriving at the first destination in the timetable. */
 	if (v->cur_real_order_index == first_manual_order && travelling) {
 		/* If the start date hasn't been set, or it was set automatically when
@@ -259,7 +445,11 @@
 		just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
 
 		if (v->timetable_start != 0) {
+#if WALLCLOCK_NETWORK_COMPATIBLE
 			v->lateness_counter = (_date - v->timetable_start) * DAY_TICKS + _date_fract;
+#else
+			v->lateness_counter = (_date * DAY_TICKS) + _date_fract - v->timetable_start;
+#endif
 			v->timetable_start = 0;
 		}
 
@@ -289,7 +479,7 @@
 			 * the timetable entry like is done for road vehicles/ships.
 			 * Thus always make sure at least one tick is used between the
 			 * processing of different orders when filling the timetable. */
-			time_taken = CeilDiv(max(time_taken, 1U), DAY_TICKS) * DAY_TICKS;
+			time_taken = CeilDiv(max(time_taken, 1U), DATE_UNIT_SIZE) * DATE_UNIT_SIZE;
 
 			ChangeTimetable(v, v->cur_real_order_index, time_taken, travelling);
 		}
@@ -304,14 +494,71 @@
 		return;
 	}
 
+	/* If the vehicle's lateness is greater than the entire duration of its
+	 * timetable, then make it 'skip' one run of its timetable. */
+	if (v->orders.list->IsCompleteTimetable()) {
+		Ticks duration = v->orders.list->GetTimetableTotalDuration();
+		while (v->lateness_counter > duration) {
+			v->lateness_counter -= duration;
+		}
+	}
+
 	if (just_started) return;
 
+	/* Update the timetable to gradually shift order times towards the actual travel times. */
+	if (timetabled != 0 && HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE)) {
+		int32 new_time;
+		if (travelling) {
+			new_time = time_taken;
+		} else {
+			new_time = time_loading;
+		}
+
+		/* Check for too large a difference from expected time, and if so don't average. */
+		if (!(new_time > (int32)timetabled * 2 || new_time < (int32)timetabled / 2)) {
+			int arrival_error = timetabled - new_time;
+			/* Compute running average, with sign conversion to avoid negative overflow */
+			new_time = ((int32)timetabled * 4 + new_time + 2) / 5;
+			/* Use arrival_error to finetune order ticks. */
+			if (arrival_error < 0) new_time++;
+			if (arrival_error > 0) new_time--;
+		} else if (new_time > (int32)timetabled * 10 && travelling) {
+			/* Possible jam, clear time and restart timetable for all vehicles.
+			 * Otherwise we risk trains blocking 1-lane stations for long times. */
+			ChangeTimetable(v, v->cur_real_order_index, 0, travelling);
+			for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
+				if (_settings_game.order.timetable_separation) v2->ClearSeparation();
+				ClrBit(v2->vehicle_flags, VF_TIMETABLE_STARTED);
+				SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
+			}
+			return;
+		}
+
+		if (new_time < 1) new_time = 1;
+		if (new_time != (int32)timetabled)
+			ChangeTimetable(v, v->cur_real_order_index, new_time, travelling);
+	} else if (timetabled == 0 && HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE)) {
+		/* Add times for orders that are not yet timetabled, even while not autofilling */
+		if (travelling)
+			ChangeTimetable(v, v->cur_real_order_index, time_taken, travelling);
+		else
+			ChangeTimetable(v, v->cur_real_order_index, time_loading, travelling);
+	}
+
 	/* Vehicles will wait at stations if they arrive early even if they are not
 	 * timetabled to wait there, so make sure the lateness counter is updated
 	 * when this happens. */
 	if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
 
-	v->lateness_counter -= (timetabled - time_taken);
+	if (_settings_game.order.timetable_separation && HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) { //TODO: Adjust to allow for separation per group. (move separation setting away from advanced settings)
+		v->current_order_time = time_taken;
+		v->current_loading_time = time_loading;
+		UpdateSeparationOrder(v);
+		v->current_order_time = 0;
+		v->current_loading_time = 0;
+	} else {
+		v->lateness_counter -= (timetabled - time_taken);
+	}
 
 	/* When we are more late than this timetabled bit takes we (somewhat expensively)
 	 * check how many ticks the (fully filled) timetable has. If a timetable cycle is
diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp
--- a/src/timetable_gui.cpp
+++ b/src/timetable_gui.cpp
@@ -40,9 +40,11 @@
 	TTV_CLEAR_TIME,
 	TTV_RESET_LATENESS,
 	TTV_AUTOFILL,
+	TTV_AUTOMATE,
 	TTV_EXPECTED,                    ///< Toggle between expected and scheduled arrivals
 	TTV_SHARED_ORDER_LIST,           ///< Show the shared order list
 	TTV_ARRIVAL_DEPARTURE_SELECTION, ///< Disable/hide the arrival departure panel
+	TTV_AUTO_SELECTION,              ///< Disable/hide the automate button
 	TTV_EXPECTED_SELECTION,          ///< Disable/hide the expected selection button
 };
 
@@ -61,11 +63,14 @@
 void SetTimetableParams(int param1, int param2, Ticks ticks)
 {
 	if (_settings_client.gui.timetable_in_ticks) {
+		SetDParam(param2, ticks);
 		SetDParam(param1, STR_TIMETABLE_TICKS);
-		SetDParam(param2, ticks);
+	} else if (_settings_client.gui.time_in_minutes) {
+		SetDParam(param2, ticks / DATE_UNIT_SIZE);
+		SetDParam(param1, STR_TIMETABLE_MINUTES);
 	} else {
+		SetDParam(param2, ticks / DATE_UNIT_SIZE);
 		SetDParam(param1, STR_TIMETABLE_DAYS);
-		SetDParam(param2, ticks / DAY_TICKS);
 	}
 }
 
@@ -77,8 +82,18 @@
  */
 static void SetArrivalDepartParams(int param1, int param2, Ticks ticks)
 {
-	SetDParam(param1, STR_JUST_DATE_TINY);
-	SetDParam(param2, _date + (ticks / DAY_TICKS));
+	SetDParam(param1, STR_JUST_DATE_WALLCLOCK_TINY);
+	SetDParam(param2, ((DateTicks)_date * DAY_TICKS) + ticks);
+}
+
+/**
+ * Check whether the order's time can be changed manually.
+ * @param order the order to check
+ * @return true if the order's time can be changed.
+ */
+static bool CanChangeTime(const Order *order)
+{
+	return !(order == NULL || ((!order->IsType(OT_GOTO_STATION) || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) && !order->IsType(OT_CONDITIONAL)));
 }
 
 /**
@@ -165,9 +180,13 @@
  * @param window the window related to the setting of the date
  * @param date the actually chosen date
  */
-static void ChangeTimetableStartCallback(const Window *w, Date date)
+static void ChangeTimetableStartCallback(const Window *w, DateTicks date)
 {
-	DoCommandP(0, w->window_number, date, CMD_SET_TIMETABLE_START | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+#if WALLCLOCK_NETWORK_COMPATIBLE
+	DoCommandP(0, w->window_number, (Date)(date / DAY_TICKS), CMD_SET_TIMETABLE_START | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+#else
+	DoCommandP(0, w->window_number, (Ticks)(date - (((DateTicks)_date * DAY_TICKS) + _date_fract)), CMD_SET_TIMETABLE_START | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+#endif
 }
 
 
@@ -177,6 +196,7 @@
 	bool show_expected;     ///< Whether we show expected arrival or scheduled
 	uint deparr_time_width; ///< The width of the departure/arrival time
 	uint deparr_abbr_width; ///< The width of the departure/arrival abbreviation
+	int ctrl_pressed;       // We need this to influence the ShowQueryString result.
 	Scrollbar *vscroll;
 
 	TimetableWindow(const WindowDesc *desc, WindowNumber window_number) :
@@ -215,8 +235,8 @@
 	{
 		switch (widget) {
 			case TTV_ARRIVAL_DEPARTURE_PANEL:
-				SetDParam(0, MAX_YEAR * DAYS_IN_YEAR);
-				this->deparr_time_width = GetStringBoundingBox(STR_JUST_DATE_TINY).width;
+				SetDParam(0, _settings_client.gui.time_in_minutes ? 0 : MAX_YEAR * DAYS_IN_YEAR);
+				this->deparr_time_width = GetStringBoundingBox(STR_JUST_DATE_WALLCLOCK_TINY).width;
 				this->deparr_abbr_width = max(GetStringBoundingBox(STR_TIMETABLE_ARRIVAL_ABBREVIATION).width, GetStringBoundingBox(STR_TIMETABLE_DEPARTURE_ABBREVIATION).width);
 				size->width = WD_FRAMERECT_LEFT + this->deparr_abbr_width + 10 + this->deparr_time_width + WD_FRAMERECT_RIGHT;
 				/* FALL THROUGH */
@@ -332,7 +352,7 @@
 				if (selected % 2 == 1) {
 					disable = order != NULL && (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT));
 				} else {
-					disable = order == NULL || ((!order->IsType(OT_GOTO_STATION) || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) && !order->IsType(OT_CONDITIONAL));
+					disable = !CanChangeTime(order);
 				}
 			}
 
@@ -343,16 +363,23 @@
 			this->EnableWidget(TTV_START_DATE);
 			this->EnableWidget(TTV_RESET_LATENESS);
 			this->EnableWidget(TTV_AUTOFILL);
+			this->EnableWidget(TTV_AUTOMATE);
 		} else {
 			this->DisableWidget(TTV_START_DATE);
 			this->DisableWidget(TTV_CHANGE_TIME);
 			this->DisableWidget(TTV_CLEAR_TIME);
 			this->DisableWidget(TTV_RESET_LATENESS);
 			this->DisableWidget(TTV_AUTOFILL);
+			this->DisableWidget(TTV_AUTOMATE);
 			this->DisableWidget(TTV_SHARED_ORDER_LIST);
 		}
 
 		this->SetWidgetLoweredState(TTV_AUTOFILL, HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE));
+		this->SetWidgetLoweredState(TTV_AUTOMATE, HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE));
+		this->SetWidgetDisabledState(TTV_START_DATE, _settings_game.order.timetable_separation);
+		this->SetWidgetDisabledState(TTV_CHANGE_TIME, HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE));
+		this->SetWidgetDisabledState(TTV_AUTOFILL, HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE));
+		this->SetWidgetDisabledState(TTV_CLEAR_TIME, HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE));
 
 		this->DrawWidgets();
 	}
@@ -439,7 +466,7 @@
 
 				int y = r.top + WD_FRAMERECT_TOP;
 
-				bool show_late = this->show_expected && v->lateness_counter > DAY_TICKS;
+				bool show_late = this->show_expected && v->lateness_counter > DATE_UNIT_SIZE;
 				Ticks offset = show_late ? 0 : -v->lateness_counter;
 
 				bool rtl = _current_text_dir == TD_RTL;
@@ -488,14 +515,18 @@
 				if (v->timetable_start != 0) {
 					/* We are running towards the first station so we can start the
 					 * timetable at the given time. */
-					SetDParam(0, STR_JUST_DATE_TINY);
+					SetDParam(0, STR_JUST_DATE_WALLCLOCK_TINY);
+#if WALLCLOCK_NETWORK_COMPATIBLE
+					SetDParam(1, v->timetable_start * DAY_TICKS);
+#else
 					SetDParam(1, v->timetable_start);
+#endif
 					DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_TIMETABLE_STATUS_START_AT);
 				} else if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) {
 					/* We aren't running on a timetable yet, so how can we be "on time"
 					 * when we aren't even "on service"/"on duty"? */
 					DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_TIMETABLE_STATUS_NOT_STARTED);
-				} else if (v->lateness_counter == 0 || (!_settings_client.gui.timetable_in_ticks && v->lateness_counter / DAY_TICKS == 0)) {
+				} else if (v->lateness_counter == 0 || (!_settings_client.gui.timetable_in_ticks && v->lateness_counter / DATE_UNIT_SIZE == 0)) {
 					DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_TIMETABLE_STATUS_ON_TIME);
 				} else {
 					SetTimetableParams(0, 1, abs(v->lateness_counter));
@@ -519,6 +550,7 @@
 	virtual void OnClick(Point pt, int widget, int click_count)
 	{
 		const Vehicle *v = this->vehicle;
+		ctrl_pressed = _ctrl_pressed;
 
 		switch (widget) {
 			case TTV_ORDER_VIEW: // Order view button
@@ -534,7 +566,7 @@
 			}
 
 			case TTV_START_DATE: // Change the date that the timetable starts.
-				ShowSetDateWindow(this, v->index, _date, _cur_year, _cur_year + 15, ChangeTimetableStartCallback);
+				ShowSetDateWindow(this, v->index, ((DateTicks)_date * DAY_TICKS) + _date_fract, _cur_year, _cur_year + 15, ChangeTimetableStartCallback);
 				break;
 
 			case TTV_CHANGE_TIME: { // "Wait For" button.
@@ -548,7 +580,7 @@
 
 				if (order != NULL) {
 					uint time = (selected % 2 == 1) ? order->travel_time : order->wait_time;
-					if (!_settings_client.gui.timetable_in_ticks) time /= DAY_TICKS;
+					if (!_settings_client.gui.timetable_in_ticks) time /= DATE_UNIT_SIZE;
 
 					if (time != 0) {
 						SetDParam(0, time);
@@ -573,11 +605,19 @@
 			case TTV_AUTOFILL: { // Autofill the timetable.
 				uint32 p2 = 0;
 				if (!HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(p2, 0);
-				if (_ctrl_pressed) SetBit(p2, 1);
+				if (!_ctrl_pressed) SetBit(p2, 1);
 				DoCommandP(0, v->index, p2, CMD_AUTOFILL_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
 				break;
 			}
 
+			case TTV_AUTOMATE: {
+				uint32 p2 = 0;
+				if (!HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE)) SetBit(p2, 0);
+				if (!_ctrl_pressed) SetBit(p2, 1);
+				DoCommandP(0, v->index, p2, CMD_AUTOMATE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+				break;
+			}
+
 			case TTV_EXPECTED:
 				this->show_expected = !this->show_expected;
 				break;
@@ -596,14 +636,26 @@
 
 		const Vehicle *v = this->vehicle;
 
-		uint32 p1 = PackTimetableArgs(v, this->sel_index);
-
 		uint64 time = StrEmpty(str) ? 0 : strtoul(str, NULL, 10);
-		if (!_settings_client.gui.timetable_in_ticks) time *= DAY_TICKS;
+		if (!_settings_client.gui.timetable_in_ticks) time *= DATE_UNIT_SIZE;
 
 		uint32 p2 = minu(time, UINT16_MAX);
 
-		DoCommandP(0, p1, p2, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+		if (!ctrl_pressed) {
+			/* Do a normal update. */
+			uint32 p1 = PackTimetableArgs(v, this->sel_index);
+			DoCommandP(0, p1, p2, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+		} else {
+			/* Update all valid stations. */
+			for (int i = 0, num_orders=v->GetNumOrders(); i < num_orders; ++i) {
+				const Order *order = v->GetOrder(i);
+
+				if (CanChangeTime(order)) {
+					uint32 p1 = PackTimetableArgs(v, i*2);
+					DoCommandP(0, p1, p2, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+				}
+			}
+		}
 	}
 
 	virtual void OnResize()
@@ -650,6 +702,7 @@
 			EndContainer(),
 			NWidget(NWID_VERTICAL, NC_EQUALSIZE),
 				NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TTV_AUTOFILL), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_AUTOFILL, STR_TIMETABLE_AUTOFILL_TOOLTIP),
+				NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TTV_AUTOMATE), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_AUTOMATE, STR_TIMETABLE_AUTOMATE_TOOLTIP),
 				NWidget(NWID_SELECTION, INVALID_COLOUR, TTV_EXPECTED_SELECTION),
 					NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TTV_EXPECTED), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_BLACK_STRING, STR_TIMETABLE_EXPECTED_TOOLTIP),
 					NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
@@ -658,6 +711,7 @@
 		EndContainer(),
 		NWidget(NWID_VERTICAL, NC_EQUALSIZE),
 			NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TTV_SHARED_ORDER_LIST), SetFill(0, 1), SetDataTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
+			NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
 			NWidget(WWT_RESIZEBOX, COLOUR_GREY), SetFill(0, 1),
 		EndContainer(),
 	EndContainer(),
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
--- a/src/toolbar_gui.cpp
+++ b/src/toolbar_gui.cpp
@@ -467,9 +467,10 @@
 	MME_SHOW_SMALLMAP        = 0,
 	MME_SHOW_EXTRAVIEWPORTS,
 	MME_SHOW_SIGNLISTS,
+	MME_WATCH_COMPANY,
 	MME_SHOW_TOWNDIRECTORY,    ///< This entry is only used in Editor mode
-	MME_MENUCOUNT_NORMAL     = 3,
-	MME_MENUCOUNT_EDITOR     = 4,
+	MME_MENUCOUNT_NORMAL     = 4,
+	MME_MENUCOUNT_EDITOR     = 5,
 };
 
 static CallBackFunction ToolbarMapClick(Window *w)
@@ -496,6 +497,7 @@
 		case MME_SHOW_SMALLMAP:       ShowSmallMap();            break;
 		case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
 		case MME_SHOW_SIGNLISTS:      ShowSignList();            break;
+		case MME_WATCH_COMPANY:       ShowWatchWindow(INVALID_COMPANY); break;
 		case MME_SHOW_TOWNDIRECTORY:  if (_game_mode == GM_EDITOR) ShowTownDirectory(); break;
 	}
 	return CBF_NONE;
@@ -1555,6 +1557,9 @@
 	MTHK_EXTRA_VIEWPORT,
 	MTHK_CLIENT_LIST,
 	MTHK_SIGN_LIST,
+	MTHK_CLEAR_COPY_PASTE_COMMAND_QUEUE, // Stop pasting in multiplayer
+	MTHK_COPY,                // Invoke Copy
+	MTHK_PASTE,               // Invoke Paste
 };
 
 /** Main toolbar. */
@@ -1639,6 +1644,9 @@
 			case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
 #endif
 			case MTHK_SIGN_LIST: ShowSignList(); break;
+			case MTHK_CLEAR_COPY_PASTE_COMMAND_QUEUE: _copy_paste_command_queue.ClearCopyPasteCommandQueue(); break; // Stop pasting in multiplayer
+			case MTHK_COPY: ShowCopyPasteToolbar(6); break;                           // Invoke Copy
+			case MTHK_PASTE: ShowCopyPasteToolbar(7); break;                          //  Invoke Paste
 			default: return ES_NOT_HANDLED;
 		}
 		return ES_HANDLED;
@@ -1702,6 +1710,8 @@
 const uint16 _maintoolbar_zoomin_keys[] = {WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS, WKC_SHIFT | WKC_F5, 0};
 const uint16 _maintoolbar_zoomout_keys[] = {WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS, WKC_SHIFT | WKC_F6, 0};
 const uint16 _maintoolbar_smallmap_keys[] = {WKC_F4, 'M', 0};
+const uint16 _maintoolbar_copy_keys[] = {WKC_CTRL | 'C', WKC_CTRL | WKC_INSERT, 0};
+const uint16 _maintoolbar_paste_keys[] = {WKC_CTRL | 'V', WKC_SHIFT | WKC_INSERT, 0};
 
 Hotkey<MainToolbarWindow> MainToolbarWindow::maintoolbar_hotkeys[] = {
 	Hotkey<MainToolbarWindow>(_maintoolbar_pause_keys, "pause", MTHK_PAUSE),
@@ -1741,6 +1751,9 @@
 	Hotkey<MainToolbarWindow>((uint16)0, "client_list", MTHK_CLIENT_LIST),
 #endif
 	Hotkey<MainToolbarWindow>((uint16)0, "sign_list", MTHK_SIGN_LIST),
+	Hotkey<MainToolbarWindow>(WKC_CTRL | 'A', "clear_copy_paste_command_queue", MTHK_CLEAR_COPY_PASTE_COMMAND_QUEUE), // Stop pasting in multiplayer
+	Hotkey<MainToolbarWindow>(_maintoolbar_copy_keys, "copy", MTHK_COPY),    // Invoke Copy
+	Hotkey<MainToolbarWindow>(_maintoolbar_paste_keys, "paste", MTHK_PASTE), // Invoke Paste
 	HOTKEY_LIST_END(MainToolbarWindow)
 };
 Hotkey<MainToolbarWindow> *_maintoolbar_hotkeys = MainToolbarWindow::maintoolbar_hotkeys;
diff --git a/src/town.h b/src/town.h
--- a/src/town.h
+++ b/src/town.h
@@ -34,6 +34,37 @@
 typedef Pool<Town, TownID, 64, 64000> TownPool;
 extern TownPool _town_pool;
 
+/**
+ * How hard do we want the number of required cargo
+ * for the towns to be able to grow at max rate.
+ */
+static const uint8 _difficulty_town_needed_for_growth[] = {
+	2,   // Off (@note: this value is never used but if defined as zero the game will crash !!).
+	2,   // Very Easy.
+	3,   // Easy.
+	4,   // Average.
+	5,   // Hard.
+	6,   // very hard.
+	10,  // Drive me nuts please.
+};
+
+/** What is needed for town growth. */
+enum TownNeededForGrowth {
+	GROWTH_STANDARD,
+	GROWTH_NEED_STATION,
+	GROWTH_NEED_MORE_PASS,
+	GROWTH_NEED_MORE_MAIL,
+	GROWTH_NEED_MORE_FOOD,
+	GROWTH_NEED_MORE_WATER,
+	GROWTH_NEED_MORE_GOODS,
+	GROWTH_NEED_PASS,
+	GROWTH_NEED_MAIL,
+	GROWTH_NEED_FOOD,
+	GROWTH_NEED_WATER,
+	GROWTH_NEED_GOODS,
+	GROWTH_SATISFIED,
+};
+
 /** Town data structure. */
 struct Town : TownPool::PoolItem<&_town_pool> {
 	TileIndex xy;                  ///< town center tile
@@ -116,6 +147,55 @@
 
 	void InitializeLayout(TownLayout layout);
 
+	void UpdateLabel();
+
+	/**
+	 * Returns the correct town label, based on rating.
+	 */
+	FORCEINLINE StringID Label() const{
+		if (!(_game_mode == GM_EDITOR) && (_local_company < MAX_COMPANIES)) {
+			/**
+			 * <)- Option to display population string always in white.
+			 *
+			 * Little bit of a hack here: we abuse the fact that the very good string is white
+			 * @note By doing this here we do not mess with actual company rating.
+			 */
+			if (_settings_client.gui.population_in_label) {
+				if (!_settings_client.gui.population_in_label_coloured) {
+					return STR_VIEWPORT_TOWN_POP;
+				} else {
+					return STR_VIEWPORT_TOWN_POP_VERY_POOR_RATING + this->town_label;
+				}			
+			} else {
+				return STR_VIEWPORT_TOWN;
+			}
+		} else {
+			return STR_VIEWPORT_TOWN;
+		}
+	}
+		
+	/**
+	 * Returns the correct town small label, based on rating.
+	 */
+	FORCEINLINE StringID SmallLabel() const{
+		if (!(_game_mode == GM_EDITOR) && (_local_company < MAX_COMPANIES)) {
+			/**
+			 * <)- Option to display population string always in white.
+			 *
+			 * Little bit of a hack here: we abuse the fact that the very good string is white
+			 * 
+			 * @note By doing this here we do not mess with actual company rating.
+			 */
+			if (_settings_client.gui.population_in_label_coloured && _settings_client.gui.population_in_label) {
+				return STR_VIEWPORT_TOWN_TINY_VERY_POOR_RATING + this->town_label;
+			} else {
+				return STR_VIEWPORT_TOWN_TINY_WHITE;
+			}
+		} else {
+			return STR_VIEWPORT_TOWN_TINY_WHITE;
+		}
+	}
+
 	/**
 	 * Calculate the max town noise.
 	 * The value is counted using the population divided by the content of the
@@ -139,6 +219,44 @@
 
 	static Town *GetRandom();
 	static void PostDestructor(size_t index);
+
+	/* Growthrate displayed in the gui.
+	 * 100% is normal growth rate. */
+	inline uint16 GrowthRatePercent() const {
+		int16 default_growth_rate = 320;
+		uint growth_multiplier = _settings_game.economy.town_growth_rate != 0 ? _settings_game.economy.town_growth_rate - 1 : 1;
+		default_growth_rate >>= growth_multiplier;
+		default_growth_rate /= (num_houses / 50 + 1);
+		if (larger_town) default_growth_rate /= 2;
+		/* If some required cargotypes are not transported return 1.
+		 * If growth patch is off or town is too small to demand goods calculate normally. */
+		if (((!larger_town && _settings_game.economy.town_growth_cargo) || (larger_town && _settings_game.economy.larger_town_growth_cargo))&&
+				((!larger_town && population > _settings_game.economy.town_pop_need_goods) ||
+				(larger_town && population > _settings_game.economy.larger_town_pop_need_goods))) {
+			if ((_settings_game.game_creation.landscape == LT_TEMPERATE ||
+					_settings_game.game_creation.landscape == LT_TOYLAND ||
+					(_settings_game.game_creation.landscape == LT_ARCTIC && TilePixelHeight(this->xy) < GetSnowLine()) ||
+					(_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(this->xy) == TROPICZONE_DESERT)) &&
+					(act_pass == 0 || act_mail == 0 || act_goods == 0)) {
+				return 1;
+			} else if (_settings_game.game_creation.landscape == LT_ARCTIC &&
+					TilePixelHeight(this->xy) >= GetSnowLine() &&
+					(act_pass == 0 || act_mail == 0 || act_goods == 0 || act_food == 0)) {
+				return 1;		
+			} else if (_settings_game.game_creation.landscape == LT_TROPIC &&
+					GetTropicZone(this->xy) == TROPICZONE_DESERT &&
+					(act_pass == 0 || act_mail == 0 || act_goods == 0  || act_food == 0|| act_water == 0)) {
+				return 1;
+			} else {
+				return 320 * this->transported_goods_percent / 100;
+			}
+		} else {
+			return (uint16)((1 / (double)growth_rate) * default_growth_rate * 320);
+		}
+	}
+
+	byte transported_goods_percent; ///< Percentage of transported goods last month.
+	byte needed_for_growth;	        ///< What is most needed for town growth?
 };
 
 uint32 GetWorldPopulation();
@@ -183,7 +301,8 @@
 void ResetHouses();
 
 void ClearTownHouse(Town *t, TileIndex tile);
-void UpdateTownMaxPass(Town *t);
+void UpdateTownGenCargo(Town *t);
+void UpdateTownDemands(Town *t);
 void UpdateTownRadius(Town *t);
 CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags);
 Town *ClosestTownFromTile(TileIndex tile, uint threshold);
@@ -193,7 +312,6 @@
 uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t);
 bool GenerateTowns(TownLayout layout);
 
-
 /** Town actions of a company. */
 enum TownActions {
 	TACT_NONE             = 0x00, ///< Empty action set.
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -160,6 +160,26 @@
 }
 
 /**
+ * Updates the town label of the town after changes in rating. The colour scheme is:
+ * Red: Appalling and Very poor ratings.
+ * Orange: Poor and mediocre ratings.
+ * Yellow: Good rating.
+ * White: Very good rating (standard).
+ * Green: Excellent and outstanding ratings.
+ */
+void Town::UpdateLabel()
+{
+	if (!(_game_mode == GM_EDITOR) && (_local_company < MAX_COMPANIES)) {
+		int r = this->ratings[_local_company];
+		(this->town_label = 0, r <= RATING_VERYPOOR)  || // Appalling and Very Poor
+		(this->town_label++,   r <= RATING_MEDIOCRE)  || // Poor and Mediocre
+		(this->town_label++,   r <= RATING_GOOD)      || // Good
+		(this->town_label++,   r <= RATING_VERYGOOD)  || // Very Good
+		(this->town_label++,   true);                    // Excellent and Outstanding
+	}
+}
+
+/**
  * Get the cost for removing this house
  * @return the cost (inflation corrected etc)
  */
@@ -352,11 +372,11 @@
  */
 void Town::UpdateVirtCoord()
 {
+	this->UpdateLabel();
 	Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
 	SetDParam(0, this->index);
 	SetDParam(1, this->population);
-	this->sign.UpdatePosition(pt.x, pt.y - 24,
-		_settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN);
+	this->sign.UpdatePosition(pt.x, pt.y - 24, this->Label());
 
 	SetWindowDirty(WC_TOWN_VIEW, this->index);
 }
@@ -436,6 +456,61 @@
 }
 
 /**
+ * Generate cargo for a town (house).
+ *
+ * The amount of cargo should be and will be greater than zero.
+ *
+ * @param t current town
+ * @param ct type of cargo to generate, usually CT_PASSENGERS or CT_MAIL
+ * @param amount how many units of cargo
+ * @param stations available stations for this house
+ */
+static void TownGenerateCargo (Town *t, CargoID ct, uint amount, StationFinder &stations)
+{
+	/* custom cargo generation factor */
+	int cf = _settings_game.economy.town_cargo_factor;
+
+	/* when the economy flunctuates, everyone wants to stay at home */
+	if (EconomyIsInRecession())
+		amount = (amount + 1) >> 1; 
+	
+	/* apply custom factor? */
+	if (cf < 0) {
+		/* approx (amount / 2^cf)
+		 * adjust with a constant offset of {(2 ^ cf) - 1} (i.e. add cf * 1-bits) before dividing to ensure that it doesn't become zero
+		 * this skews the curve a little so that isn't entirely exponential, but will still decrease */
+		amount = (amount + ((1 << -cf) - 1)) >> -cf;
+	} else if (cf > 0) {
+		/* approx (amount * 2^cf) */
+		/* XXX: overflow? */
+		amount = amount << cf;
+	}
+
+	/* with the adjustments above, this should never happen */
+	assert(amount > 0);
+	
+	/* send cargo to station */
+	uint moved = MoveGoodsToStation(ct, amount, ST_TOWN, t->index, stations.GetStations());
+	
+	/* calculate for town stats */
+	const CargoSpec *cs = CargoSpec::Get(ct);
+	switch (cs->town_effect) {
+		case TE_PASSENGERS:
+			t->new_gen_max_pass += amount;
+			t->new_gen_act_pass += moved;
+			break;
+
+		case TE_MAIL:
+			t->new_gen_max_mail += amount;
+			t->new_gen_act_mail += moved;
+			break;
+
+		default:
+			break;
+	}
+}
+
+/**
  * Tile callback function.
  *
  * Periodic tic handler for houses and town
@@ -487,15 +562,32 @@
 			const CargoSpec *cs = CargoSpec::Get(cargo);
 			switch (cs->town_effect) {
 				case TE_PASSENGERS:
+					TownGenerateCargo(t, cargo, amt, stations); // XXX: no economy flunctuation for GRF cargos?
 					t->new_max_pass += amt;
 					t->new_act_pass += moved;
 					break;
 
 				case TE_MAIL:
+					TownGenerateCargo(t, cargo, amt, stations); // XXX: no economy flunctuation for GRF cargos?
 					t->new_max_mail += amt;
 					t->new_act_mail += moved;
 					break;
 
+				case TE_FOOD:
+					t->new_max_food += amt;
+					t->new_act_food += moved;
+					break;
+
+				case TE_WATER:
+					t->new_max_water += amt;
+					t->new_act_water += moved;
+					break;
+
+				case TE_GOODS:
+					t->new_max_goods += amt;
+					t->new_act_goods += moved;
+					break;
+
 				default:
 					break;
 			}
@@ -503,19 +595,17 @@
 	} else {
 		if (GB(r, 0, 8) < hs->population) {
 			uint amt = GB(r, 0, 8) / 8 + 1;
-
-			if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
-			t->new_max_pass += amt;
-			t->new_act_pass += MoveGoodsToStation(CT_PASSENGERS, amt, ST_TOWN, t->index, stations.GetStations());
+			
+			TownGenerateCargo(t, CT_PASSENGERS, amt, stations);
 		}
 
 		if (GB(r, 8, 8) < hs->mail_generation) {
 			uint amt = GB(r, 8, 8) / 8 + 1;
 
-			if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
-			t->new_max_mail += amt;
-			t->new_act_mail += MoveGoodsToStation(CT_MAIL, amt, ST_TOWN, t->index, stations.GetStations());
+			TownGenerateCargo(t, CT_MAIL, amt, stations);
 		}
+
+		UpdateTownDemands(t);
 	}
 
 	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
@@ -523,7 +613,7 @@
 	if ((hs->building_flags & BUILDING_HAS_1_TILE) &&
 			HasBit(t->flags, TOWN_IS_FUNDED) &&
 			CanDeleteHouse(tile) &&
-			GetHouseAge(tile) >= hs->minimum_life &&
+			GetHouseAge(tile) >= (hs->minimum_life  * _date_daylength_factor) &&
 			--t->time_until_rebuild == 0) {
 		t->time_until_rebuild = GB(r, 16, 8) + 192;
 
@@ -1399,10 +1489,52 @@
 	}
 }
 
-void UpdateTownMaxPass(Town *t)
+/**
+ * Calculates town generated cargo.
+ * @param t This Town.
+ */
+void UpdateTownGenCargo(Town *t)
 {
-	t->max_pass = t->population >> 3;
-	t->max_mail = t->population >> 4;
+	t->gen_max_pass = t->population >> 3;
+	t->gen_max_mail = t->population >> 4;
+}
+
+ /**
+ * Calculate demanded goods for towngrowth.
+ * @param t This town.
+ */
+void UpdateTownDemands(Town *t)
+{
+	byte dtg;
+	if(!t->larger_town) {
+		dtg = _difficulty_town_needed_for_growth[_settings_game.economy.town_growth_cargo];
+	} else {
+		dtg = _difficulty_town_needed_for_growth[_settings_game.economy.larger_town_growth_cargo];
+	}
+	int cf = _settings_game.economy.town_cargo_factor;
+	uint popul = t->population;
+	if (t->larger_town) popul *= 2;
+
+	/* Devided by 4 before multiplying by difficulty so that "average" can be equal to max generated passengers and mail. */
+	t->max_pass = ((popul >> 3) / 4 * dtg) * _date_daylength_factor;
+	t->max_mail = ((popul >> 4) / 4 * dtg) * _date_daylength_factor;
+	/* Apply town cargo generation factor for passengers and mail too. */
+	if (cf < 0) {
+		/* approx (amount / 2^cf)
+		 * adjust with a constant offset of {(2 ^ cf) - 1} (i.e. add cf * 1-bits) before dividing to ensure that it doesn't become zero
+		 * this skews the curve a little so that isn't entirely exponential, but will still decrease */
+		t->max_pass = (t->max_pass + ((1 << -cf) - 1)) >> -cf;
+		t->max_mail = (t->max_mail + ((1 << -cf) - 1)) >> -cf;
+	} else if (cf > 0) {
+		/* approx (amount * 2^cf) */
+		/* XXX: overflow? */
+		t->max_pass = t->max_pass << cf;
+		t->max_mail = t->max_mail << cf;
+	}
+
+	t->max_food = ((popul >> 2) / 7 / 4) * dtg;
+	t->max_water = ((popul >> 4) * 5 / 9 / 4) * dtg;
+	t->max_goods = ((popul >> 2) / 5 / 4) * dtg;
 }
 
 /**
@@ -1482,7 +1614,8 @@
 
 	t->num_houses -= x;
 	UpdateTownRadius(t);
-	UpdateTownMaxPass(t);
+	UpdateTownGenCargo(t);
+	UpdateTownDemands(t);
 	UpdateAirportsNoise();
 }
 
@@ -2249,6 +2382,7 @@
 static void DoClearTownHouseHelper(TileIndex tile, Town *t, HouseID house)
 {
 	assert(IsTileType(tile, MP_HOUSE));
+
 	DecreaseBuildingCount(t, house);
 	DoClearSquare(tile);
 	DeleteAnimatedTile(tile);
@@ -2375,7 +2509,8 @@
 		t->num_houses -= amount;
 		UpdateTownRadius(t);
 
-		UpdateTownMaxPass(t);
+		UpdateTownGenCargo(t);
+		UpdateTownDemands(t);
 	}
 
 	return CommandCost();
@@ -2593,7 +2728,7 @@
 	if (!_settings_game.economy.exclusive_rights) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
-		t->exclusive_counter = 12;
+		t->exclusive_counter = 12 * _date_daylength_factor;
 		t->exclusivity = _current_company;
 
 		ModifyStationRatingAround(t->xy, _current_company, 130, 17);
@@ -2626,6 +2761,7 @@
 			 */
 			if (t->ratings[_current_company] > RATING_BRIBE_DOWN_TO) {
 				t->ratings[_current_company] = RATING_BRIBE_DOWN_TO;
+				t->UpdateVirtCoord();
 				SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
 			}
 		} else {
@@ -2758,6 +2894,7 @@
 		t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
 	}
 
+	t->UpdateVirtCoord();
 	SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
 
 	ClrBit(t->flags, TOWN_IS_FUNDED);
@@ -2983,6 +3120,7 @@
 	} else {
 		SetBit(t->have_ratings, _current_company);
 		t->ratings[_current_company] = rating;
+		t->UpdateVirtCoord();
 		SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
 	}
 }
diff --git a/src/town_gui.cpp b/src/town_gui.cpp
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -362,20 +362,11 @@
 	{
 		if (widget != TVW_INFOPANEL) return;
 
+		StringID str;
 		uint y = r.top + WD_FRAMERECT_TOP;
 
-		SetDParam(0, this->town->population);
-		SetDParam(1, this->town->num_houses);
-		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y, STR_TOWN_VIEW_POPULATION_HOUSES);
-
-		SetDParam(0, this->town->act_pass);
-		SetDParam(1, this->town->max_pass);
-		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_PASSENGERS_LAST_MONTH_MAX);
-
-		SetDParam(0, this->town->act_mail);
-		SetDParam(1, this->town->max_mail);
-		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_MAIL_LAST_MONTH_MAX);
-
+/* needed for old style gui 1/2 */
+		/* Required delivered cargos for growth in artic and tropic climate. */
 		StringID required_text = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED;
 		uint cargo_needed_for_growth = 0;
 		switch (_settings_game.game_creation.landscape) {
@@ -390,45 +381,193 @@
 
 			default: break;
 		}
+/* needed for old style gui 1/2 end*/
 
-		if (cargo_needed_for_growth > 0) {
-			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH);
+		/* Needed for cases where the towneffect of cargos is changed by means of GRF. */
+		const CargoSpec *passengers = FindFirstCargoWithTownEffect(TE_PASSENGERS);
+		StringID passengers_name    = (passengers != NULL) ? passengers->name    : STR_CARGO_PLURAL_PASSENGERS;
 
-			bool rtl = _current_text_dir == TD_RTL;
-			uint cargo_text_left = r.left + WD_FRAMERECT_LEFT + (rtl ? 0 : 20);
-			uint cargo_text_right = r.right - WD_FRAMERECT_RIGHT - (rtl ? 20 : 0);
+		const CargoSpec *mail       = FindFirstCargoWithTownEffect(TE_MAIL);
+		StringID mail_name          = (mail != NULL) ? mail->name    : STR_CARGO_PLURAL_MAIL;
 
-			const CargoSpec *food = FindFirstCargoWithTownEffect(TE_FOOD);
-			CargoID first_food_cargo = (food != NULL) ? food->Index() : (CargoID)CT_INVALID;
-			StringID food_name       = (food != NULL) ? food->name    : STR_CARGO_PLURAL_FOOD;
+		const CargoSpec *food = FindFirstCargoWithTownEffect(TE_FOOD);
+		CargoID first_food_cargo = (food != NULL) ? food->Index() : (CargoID)CT_INVALID;
+		StringID food_name       = (food != NULL) ? food->name    : STR_CARGO_PLURAL_FOOD;
 
-			const CargoSpec *water = FindFirstCargoWithTownEffect(TE_WATER);
-			CargoID first_water_cargo = (water != NULL) ? water->Index() : (CargoID)CT_INVALID;
-			StringID water_name       = (water != NULL) ? water->name    : STR_CARGO_PLURAL_WATER;
+		const CargoSpec *water = FindFirstCargoWithTownEffect(TE_WATER);
+		CargoID first_water_cargo = (water != NULL) ? water->Index() : (CargoID)CT_INVALID;
+		StringID water_name       = (water != NULL) ? water->name    : STR_CARGO_PLURAL_WATER;
 
-			if (first_food_cargo != CT_INVALID && this->town->act_food > 0) {
-				SetDParam(0, first_food_cargo);
-				SetDParam(1, this->town->act_food);
-				DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH);
-			} else {
-				SetDParam(0, food_name);
-				DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, required_text);
+		const CargoSpec *goods      = FindFirstCargoWithTownEffect(TE_GOODS);
+		StringID goods_name         = (goods != NULL) ? goods->name    : STR_CARGO_PLURAL_GOODS;
+
+		/* Population and number of houses. */
+		SetDParam(0, this->town->population);
+		SetDParam(1, this->town->num_houses);
+		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y, STR_TOWN_VIEW_POPULATION_HOUSES);
+
+		/* Empty line. */
+		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_EMPTY);
+
+		/* Generated cargo titel. */
+		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_GENERATED_CARGO_LAST_MONTH);
+
+		/* Generated and max possible generated passengers. */
+		SetDParam(0, this->town->gen_act_pass);
+		SetDParam(1, this->town->gen_max_pass);
+		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_GENERATED_PASS_LAST_MONTH_MAX);
+
+		/* Generated and max possible generated mail. */
+		SetDParam(0, this->town->gen_act_mail);
+		SetDParam(1, this->town->gen_max_mail);
+		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_GENERATED_MAIL_LAST_MONTH_MAX);
+
+		/* Empty line. */
+		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_EMPTY);
+
+		/* Transported goods rate of this town. Only displayed if we have enabled the town_growth_patch and the population is big enough. */
+		if (((!this->town->larger_town && _settings_game.economy.town_growth_cargo) || (this->town->larger_town && _settings_game.economy.larger_town_growth_cargo)) &&
+				((!this->town->larger_town && this->town->population > _settings_game.economy.town_pop_need_goods) ||
+				(this->town->larger_town && this->town->population > _settings_game.economy.larger_town_pop_need_goods))) {
+			/* Growth rate last month. */
+			SetDParam(0, this->town->GrowthRatePercent());
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_GROWTH_RATE_LAST_MONTH);
+
+			/* Transported goods ratio last month. */
+			SetDParam(0, this->town->transported_goods_percent);
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_TRANSPORTED_RATE_LAST_MONTH);
+
+			/* Most demanded for growth last month. */
+			str = STR_TOWN_VIEW_GROWTH_STANDARD;
+			if (_settings_game.economy.town_growth_rate == 0) {
+				str = STR_TOWN_VIEW_GROWTH_SPEED_DISABLED;
+			} else if (this->town->transported_goods_percent <= 99) {
+				str += this->town->needed_for_growth;
+				// long if else ... need to fetch the correct cago name -> grfs changing TE_xxx
+				if (this->town->needed_for_growth == GROWTH_NEED_STATION) {
+					str = STR_TOWN_VIEW_GROWTH_NEED_STATION;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_MORE_PASS) {
+					SetDParam(1 , passengers_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_MORE_PASS;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_MORE_MAIL) {
+					SetDParam(1 , mail_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_MORE_MAIL;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_MORE_FOOD) {
+					SetDParam(1 , food_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_MORE_FOOD;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_MORE_WATER) {
+					SetDParam(1 , water_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_MORE_WATER;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_MORE_GOODS) {
+					SetDParam(1 , goods_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_MORE_GOODS;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_PASS) {
+					SetDParam(1 , passengers_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_PASS;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_MAIL) {
+					SetDParam(1 , mail_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_MAIL;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_FOOD) {
+					SetDParam(1 , food_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_FOOD;}
+				else if (this->town->needed_for_growth == GROWTH_NEED_WATER) {
+					SetDParam(1 , water_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_WATER;
+				} else if (this->town->needed_for_growth == GROWTH_NEED_GOODS) {
+					SetDParam(1 , goods_name);
+					str = STR_TOWN_VIEW_GROWTH_NEED_GOODS;
+				} else {
+					SetDParam(1, STR_EMPTY);
+				}
+			} else if (this->town->transported_goods_percent >= 100) {
+				str = STR_TOWN_VIEW_GROWTH_SATISFIED;
+			}
+			SetDParam(0, str);
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_DEMAND_LAST_MONTH);
+
+			/* Empty line. */
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_EMPTY);
+
+			/* Requirements "titel" (Needed to clarify that the values are this month's). */
+ 			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_THIS_MONTH);
+ 
+			/* Delivered and needed passengers. */
+			SetDParam(0, passengers_name);
+			SetDParam(1, this->town->act_pass);
+			SetDParam(2, this->town->max_pass);
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_PASSENGERS_THIS_MONTH_MAX);
+
+			/* Delivered and needed mail. */
+			SetDParam(0, mail_name);
+			SetDParam(1, this->town->act_mail);
+			SetDParam(2, this->town->max_mail);
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_MAIL_THIS_MONTH_MAX);
+
+			/* Delivered and needed food (Fizzy Drinks if we are playing in toyland). */
+			if ((_settings_game.game_creation.landscape == LT_ARCTIC && TilePixelHeight(this->town->xy) >= LowestSnowLine()) ||
+					(_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(this->town->xy) == TROPICZONE_DESERT) ||
+					_settings_game.game_creation.landscape == LT_TOYLAND) {
+ 				SetDParam(0, food_name);
+ 				SetDParam(1, this->town->act_food);
+				SetDParam(2, this->town->max_food);
+				DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_FOOD_THIS_MONTH_MAX);
 			}
 
-			if (cargo_needed_for_growth > 1) {
-				if (first_water_cargo != CT_INVALID && this->town->act_water > 0) {
-					SetDParam(0, first_water_cargo);
-					SetDParam(1, this->town->act_water);
-					DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH);
-				} else {
-					SetDParam(0, water_name);
-					DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, required_text);
+			/* Delivered and needed water in desert. */
+			if (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(this->town->xy) == TROPICZONE_DESERT) {
+				SetDParam(0, water_name);
+				SetDParam(1, this->town->act_water);
+				SetDParam(2, this->town->max_water);
+				DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_WATER_THIS_MONTH_MAX);
+			}
+
+			/* Delivered and needed goods (Sweets if we play in toyland climate). */
+			SetDParam(0, goods_name);
+			SetDParam(1, this->town->act_goods);
+			SetDParam(2, this->town->max_goods);
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_GOODS_THIS_MONTH_MAX);
+		}
+
+/* Old style gui 2/2 */
+		/* What is the town needing to be able to grow. */
+		if ((cargo_needed_for_growth > 0 &&
+				(((!this->town->larger_town && !_settings_game.economy.town_growth_cargo) || (this->town->larger_town && !_settings_game.economy.larger_town_growth_cargo)) ||
+				((!this->town->larger_town && _settings_game.economy.town_growth_cargo) || (this->town->larger_town && _settings_game.economy.larger_town_growth_cargo))) &&
+				((!this->town->larger_town && this->town->population < _settings_game.economy.town_pop_need_goods) ||
+				(this->town->larger_town && this->town->population < _settings_game.economy.larger_town_pop_need_goods)))) {
+			if (_settings_game.game_creation.landscape != LT_TEMPERATE && _settings_game.game_creation.landscape != LT_TOYLAND) {
+				bool rtl = _current_text_dir == TD_RTL;
+				uint cargo_text_left = r.left + WD_FRAMERECT_LEFT + (rtl ? 0 : 20);
+				uint cargo_text_right = r.right - WD_FRAMERECT_RIGHT - (rtl ? 20 : 0);
+
+				if (first_food_cargo != CT_INVALID && this->town->act_food > 0) {
+					SetDParam(0, first_food_cargo);
+					SetDParam(1, this->town->act_food);
+ 					DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH);
+ 				} else {
+					SetDParam(0, food_name);
+ 					DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, required_text);
+ 				}
+
+				if (cargo_needed_for_growth > 1) {
+					if (first_water_cargo != CT_INVALID && this->town->act_water > 0) {
+						SetDParam(0, first_water_cargo);
+						SetDParam(1, this->town->act_water);
+						DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_LAST_MONTH);
+					} else {
+						SetDParam(0, water_name);
+						DrawString(cargo_text_left, cargo_text_right, y += FONT_HEIGHT_NORMAL, required_text);
+					}
 				}
-			}
-		}
+ 			}
+/* end old style gui 2/2 */
+ 		}
 
 		/* only show the town noise, if the noise option is activated. */
 		if (_settings_game.economy.station_noise_level) {
+			/* Empty line. */
+			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_EMPTY);
+
 			SetDParam(0, this->town->noise_reached);
 			SetDParam(1, this->town->MaxTownNoise());
 			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_LEFT, y += FONT_HEIGHT_NORMAL, STR_TOWN_VIEW_NOISE_IN_TOWN);
@@ -572,7 +711,7 @@
 };
 
 static const WindowDesc _town_game_view_desc(
-	WDP_AUTO, 260, TownViewWindow::TVW_HEIGHT_NORMAL,
+	WDP_AUTO, 340, TownViewWindow::TVW_HEIGHT_NORMAL,
 	WC_TOWN_VIEW, WC_NONE,
 	WDF_UNCLICK_BUTTONS,
 	_nested_town_game_view_widgets, lengthof(_nested_town_game_view_widgets)
diff --git a/src/trafficlight.cpp b/src/trafficlight.cpp
new file mode 100644
--- /dev/null
+++ b/src/trafficlight.cpp
@@ -0,0 +1,291 @@
+/* $Id: trafficlight.cpp $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file trafficlight.cpp Handling of trafficlights. */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "landscape.h"
+#include "sprite.h"
+#include "viewport_func.h"
+#include "road_map.h"
+#include "command_func.h"
+#include "cheat_func.h"
+#include "animated_tile_func.h"
+#include "economy_func.h"
+#include "road_cmd.h"
+#include "company_func.h"
+#include "company_base.h"
+#include "settings_type.h"
+#include "trafficlight.h"
+#include "trafficlight_type.h"
+#include "date_func.h"
+#include "company_func.h"
+
+#include "table/sprites.h"
+#include "table/strings.h"
+
+#include <set>
+
+
+/* A traffic light consist (TLC) is a set of adjacent tiles with traffic lights on them.
+ * They are linked together to form a big traffic light junction. */
+typedef std::set<TileIndex> TLC;
+
+/**
+ * Gets the traffic light consist (a set of adjacent tiles with traffic lights).
+ * If specified by the checkroadworks parameter, it returns 0 instead if road works are found within the consist.
+ * @param tile           Tile of the traffic light consist.
+ * @param checkroadworks Should we check for roadworks in the consist (and return 0 if found).
+ * @return visited       The traffic light consist (TLC); if checkroadworks == true and roadworks were found, return 0 instead.
+ */
+TLC *GetTrafficLightConsist(TileIndex tile, bool checkroadworks)
+{
+	TLC *visited;
+	TLC *candidates;
+
+	visited = new TLC;
+	candidates = new TLC;
+	candidates->insert(tile);
+
+	while (!candidates->empty()) {
+		TLC::iterator cur = candidates->begin();
+		if (checkroadworks && HasRoadWorks(*cur)) {
+			delete visited;
+			delete candidates;
+			return 0;
+		}
+		uint8 distance_between_traffic_lights = _tlc_distance[_settings_game.construction.max_tlc_distance];
+		for (int i = 0; i < distance_between_traffic_lights; i++) {
+			TileIndex neighbor = *cur + ToTileIndexDiff(_tl_check_offsets[i]);
+			if (HasTrafficLights(neighbor) && (visited->find(neighbor) == visited->end())) candidates->insert(neighbor);
+		}
+		visited->insert(*cur);
+		candidates->erase(cur);
+	}
+	delete candidates;
+	return visited;
+}
+
+/**
+ * Gets the lowest TileIndex of the traffic light consist or 0 if roadworks
+ * are found in the consist.
+ * @param tile    Tile of the traffic light consist.
+ * @return lowest TileIndex in the consist or 0 if roadworks were found.
+ */
+TileIndex GetTLCLowestTileIndexOrRoadWorks(TileIndex tile)
+{
+	TLC *consist = GetTrafficLightConsist(tile, true);
+	TileIndex result = 0;
+	if (consist != 0) result = *(consist->begin());
+	delete consist;
+	return result;
+}
+
+/**
+ * Returns the state of the trafficlights on a tile.
+ * @note In the scenario editor trafficlights are disabled.
+ * @param tile This tile.
+ * @pre        The tile must have trafficlights.
+ * @return     Trafficlights state or disabled state.
+ */
+TrafficLightState GetTLState(TileIndex tile)
+{
+	assert(HasTrafficLights(tile));
+	if (_game_mode == GM_EDITOR) return TLS_OFF;    ///< All lights are off in scenario editor.
+	tile = GetTLCLowestTileIndexOrRoadWorks(tile);
+	if (tile == 0) return TLS_OFF;                  ///< All lights are off when roadworks are in the consist.
+
+	uint16 tl_total = 16 * _settings_game.construction.traffic_lights_green_phase;          // There are (16 * patchsetting) "TL ticks".
+	uint16 tl_tick = ((_tick_counter / 16) + 5 * TileX(tile) + 7 * TileY(tile)) % tl_total; // Each "TL tick" consists of 16 gameticks.
+
+	if (tl_tick < ((tl_total / 2) - 2)) return TLS_X_GREEN_Y_RED;      ///< SW and NE are green, NW and SE are red.
+	if (tl_tick < ((tl_total / 2) - 1)) return TLS_X_YELLOW_Y_RED;     ///< SW and NE are yellow, NW and SE are red.
+	if (tl_tick < (tl_total / 2))       return TLS_X_RED_Y_REDYELLOW;  ///< SW and NE are red, NW and SE are red-yellow.
+	if (tl_tick < (tl_total - 2))       return TLS_X_RED_Y_GREEN;      ///< SW and NE are red, NW and SE are green.
+	if (tl_tick < (tl_total - 1))       return TLS_X_RED_Y_YELLOW;     ///< SW and NE are red, NW and SE are yellow.
+	if (tl_tick < tl_total)             return TLS_X_REDYELLOW_Y_RED;  ///< SW and NE are red-yellow, NW and SE are red.
+
+	NOT_REACHED();
+	return TLS_OFF;
+}
+
+/**
+ * Which directions are disallowed due to the TLState (red lights..).
+ */
+static const TrackdirBits _tls_to_trackdir[7] = {
+	TRACKDIR_BIT_MASK,                                ///< 0) all directions disallowed
+	TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE |           ///< 1) all directions from
+		TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LOWER_W |    ///<    y sides
+		TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_RIGHT_N,      ///<    are disallowed
+	TRACKDIR_BIT_MASK,                                ///< 2) all directions disallowed
+	TRACKDIR_BIT_MASK,                                ///< 3) all directions disallowed
+	TRACKDIR_BIT_X_SW | TRACKDIR_BIT_X_NE |           ///< 4) all directions from
+		TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_LOWER_E |    ///<    x sides
+		TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_RIGHT_S,      ///<    are disallowed
+	TRACKDIR_BIT_MASK,                                ///< 5) all directions disallowed
+	TRACKDIR_BIT_MASK,                                ///< 6) all directions disallowed
+};
+
+/**
+ * Which directions in tile are allowed to be taken due to adjacent traffic lights (traffic light consist).
+ * @param tile          Tile to search on.
+ * @return trackdirbits Bitmask of allowed directions.
+ */
+TrackdirBits GetIntraTLCAllowedDirections(TileIndex tile)
+{
+	TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
+
+	if (HasTrafficLights(tile + TileDiffXY( 1,  0))) // SW.
+		trackdirbits |= TRACKDIR_BIT_X_NE | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LEFT_N;
+	if (HasTrafficLights(tile + TileDiffXY( 0,  1))) // SE
+		trackdirbits |= TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_RIGHT_N;
+	if (HasTrafficLights(tile + TileDiffXY( 0, -1))) // NW.
+		trackdirbits |= TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LEFT_S;
+	if (HasTrafficLights(tile + TileDiffXY(-1,  0))) // NE.
+		trackdirbits |= TRACKDIR_BIT_X_SW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_RIGHT_S;
+
+	return trackdirbits;
+}
+
+/**
+ * Get a bitmask of the directions forbidden to drive on due to traffic light(s).
+ * @param tile Tile to check.
+ * @return     Bitmask of forbidden directions.
+ */
+TrackdirBits GetTrafficLightDisallowedDirections(TileIndex tile)
+{
+	return (_tls_to_trackdir[GetTLState(tile)] & ~GetIntraTLCAllowedDirections(tile));
+}
+
+/**
+ * Checks if the size of a traffic light consist is within the allowed range.
+ * @param tile    Tile to check (can also be a new tile to be added to the TLC).
+ * @return result True if the TLC size is within the allowed range, else false.
+ */
+bool CheckTLCSize(TileIndex tile)
+{
+	if (_settings_game.construction.max_tlc_size == 0) return true;
+	TLC *consist = GetTrafficLightConsist(tile, false);
+	bool result = (consist->size() <= _settings_game.construction.max_tlc_size);
+	delete consist;
+	return result;
+}
+
+/**
+ * Build traffic lights on a crossing.
+ * @param tile         Tile where to place the traffic lights.
+ * @param flags        Operation to perform.
+ * @param p1           Unused.
+ * @param p2           Unused.
+ * @return CommandCost Cost or error.
+ */
+CommandCost CmdBuildTrafficLights(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	/* Check if traffic lights are enabled. */
+	if (!_settings_game.construction.traffic_lights) return CMD_ERROR; // Sanity check.
+
+	/* Check for correct location (road). */
+	if (!IsTileType(tile, MP_ROAD) || GetRoadTileType(tile) != ROAD_TILE_NORMAL) return_cmd_error(STR_ERROR_THERE_IS_NO_ROAD);
+
+	/* Check owner only if a valid player is executing this command. */
+	if (Company::IsValidID(_current_company)) {
+		Owner owner = GetTileOwner(tile);
+		if (owner == OWNER_TOWN) {
+			if (!_settings_game.construction.allow_building_tls_in_towns) return_cmd_error(STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS);
+		} else {
+			if (owner != OWNER_NONE && !IsTileOwner(tile, _current_company)) return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER); // Owned by ... already displayed in CheckOwnership.
+		}
+	}
+
+	/* Check junction and already built. */
+	if (CountBits(GetAllRoadBits(tile)) < 3) return_cmd_error(STR_ERROR_CAN_ONLY_BE_PLACED_ON_ROAD_JUNCTIONS);
+	if (HasTrafficLights(tile)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
+
+	if (!CheckTLCSize(tile)) return_cmd_error(STR_ERROR_TRAFFIC_LIGHT_CONSIST_TOO_BIG);
+
+	/* Now we may build the traffic lights. */
+	if (flags & DC_EXEC) {
+		MakeTrafficLights(tile);
+		AddAnimatedTile(tile);
+		MarkTileDirtyByTile(tile);
+	}
+	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS]);
+}
+
+/**
+ * Removes traffic lights from a tile.
+ * @param tile         Tile where to remove the traffic lights.
+ * @param flags        Operation to perform.
+ * @param p1           Unused.
+ * @param p2           Unused.
+ * @return CommandCost Cost or error.
+ */
+CommandCost CmdRemoveTrafficLights(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	/* Check for correct location (road with traffic lights). */
+	if (!IsTileType(tile, MP_ROAD) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || !HasTrafficLights(tile)) return CMD_ERROR;
+
+	/* Check owner, but only if a valid player is executing this command. */
+	if (Company::IsValidID(_current_company)) {
+		Owner owner = GetTileOwner(tile);
+		if (owner == OWNER_TOWN) {
+			if (!_settings_game.construction.allow_building_tls_in_towns && !_cheats.magic_bulldozer.value) return_cmd_error(STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS);
+		} else {
+			if (owner != OWNER_NONE && !IsTileOwner(tile, _current_company)) return CMD_ERROR; // Owned by ... already displayed in CheckOwnership.
+		}
+	}
+
+	/* Now we may remove the traffic lights. */
+	if (flags & DC_EXEC) {
+		DeleteAnimatedTile(tile);
+		ClearTrafficLights(tile);
+		MarkTileDirtyByTile(tile);
+	}
+	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS]);
+}
+/**
+ * Clear all traffic lights from the map.
+ */
+void ClearAllTrafficLights()
+{
+	/* Iterate over the whole map and remove any trafficlights found. */
+	for (TileIndex tile = 0; tile < MapSize(); tile++) {
+		if (HasTrafficLights(tile)) {
+			DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_TRAFFICLIGHTS);
+		}
+	}
+}
+
+/**
+ * Draws traffic lights on a tile.
+ * @param ti TileInfo of the tile to draw on.
+ */
+void DrawTrafficLights(TileInfo* ti)
+{
+	RoadBits road = GetAllRoadBits(ti->tile);
+	TrafficLightState state = GetTLState(ti->tile);
+
+	const TileIndex neighbor[4] = { ti->tile + TileDiffXY(1, 0), // SW.
+					ti->tile + TileDiffXY(0, 1),                 // SE.
+					ti->tile + TileDiffXY(0, -1),                // NW.
+					ti->tile + TileDiffXY(-1, 0)};               // NE.
+	const RoadBits rb[4] = {ROAD_SW, ROAD_SE, ROAD_NW, ROAD_NE};
+
+	/* Draw the four directions. */
+	byte rs = _settings_game.vehicle.road_side;
+	for (int i = 0; i < 4; i++) {
+		if (road & rb[i] && !HasTrafficLights(neighbor[i])) {
+			DisallowedRoadDirections drd = DRD_NONE;
+			if (IsTileType(neighbor[i], MP_ROAD) && IsNormalRoad(neighbor[i])) drd = GetDisallowedRoadDirections(neighbor[i]);
+			if (drd != ((i % 2 == 0) ? DRD_SOUTHBOUND : DRD_NORTHBOUND) && drd != DRD_BOTH)
+				DrawRoadDetail(_tls_to_sprites[state][i], ti, _tl_offsets[rs][i].x, _tl_offsets[rs][i].y, 12);
+		}
+	}
+}
diff --git a/src/trafficlight.h b/src/trafficlight.h
new file mode 100644
--- /dev/null
+++ b/src/trafficlight.h
@@ -0,0 +1,133 @@
+/* $Id: trafficlight.h $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file trafficlight.h variables used for handling trafficlights. */
+
+
+/**
+ * Used for synchronising traffic light signals.
+ * Number below is how far we look into the _tl_check_offsets array when
+ * placing trafficlights, based on _settings_game.construction.max_tlc_distance.
+ */
+static const uint8 _tlc_distance[5] = {
+0,  ///< no synchronizing.
+8,  ///< adjecant tiles only.
+24, ///< 2 tiles away.
+48, ///< 3 tiles away.
+80  ///< 4 tiles away.
+};
+
+/* TileDiffs for the eight adjacent tiles. */
+static const TileIndexDiffC _tl_check_offsets[80] = {
+	/* Tiles next to this tile (8 tiles). */
+	{-1, -1},
+	{ 0, -1},
+	{ 1, -1},
+	{ 1,  0},
+	{ 1,  1},
+	{ 0,  1},
+	{-1,  1},
+	{-1,  0},
+	/* Tiles two tiles from this tile (16 tile). */
+	{-2, -2},
+	{-1, -2},
+	{ 0, -2},
+	{ 1, -2},
+	{ 2, -2},
+	{ 2, -1},
+	{ 2,  0},
+	{ 2,  1},
+	{ 2,  2},
+	{ 1,  2},
+	{ 0,  2},
+	{-1,  2},
+	{-2,  2},
+	{-2,  1},
+	{-2,  0},
+	{-2, -1},
+	/* Tiles three tiles from this tiles (24 tiles). */
+	{-3, -3},
+	{-3, -2},
+	{-3, -1},
+	{-3,  0},
+	{-3,  1},
+	{-3,  2},
+	{-3,  3},
+	{-2,  3},
+	{-1,  3},
+	{ 0,  3},
+	{ 1,  3},
+	{ 2,  3},
+	{ 3,  3},
+	{ 3,  2},
+	{ 3,  1},
+	{ 3,  0},
+	{ 3, -1},
+	{ 3, -2},
+	{ 3, -3},
+	{ 2, -3},
+	{ 1, -3},
+	{ 0, -3},
+	{-1, -3},
+	{-2, -3},
+	/* Tiles three tiles away from this tile (32 tiles). */
+	{-4, -4},
+	{-3, -4},
+	{-2, -4},
+	{-1, -4},
+	{ 0, -4},
+	{ 1, -4},
+	{ 2, -4},
+	{ 3, -4},
+	{ 4, -4},
+	{ 4, -3},
+	{ 4, -2},
+	{ 4, -1},
+	{ 4,  0},
+	{ 4,  1},
+	{ 4,  2},
+	{ 4,  3},
+	{ 4,  4},
+	{ 3,  4},
+	{ 2,  4},
+	{ 1,  4},
+	{ 0,  4},
+	{-1,  4},
+	{-2,  4},
+	{-3,  4},
+	{-4,  4},
+	{-4,  3},
+	{-4,  2},
+	{-4,  1},
+	{-4,  0},
+	{-4, -1},
+	{-4, -2},
+	{-4, -3}
+};
+
+/**
+ * Drawing offsets for the traffic light posts [roadside (left, right)][direction (SW, SE, NW, NE)].
+ */
+static const Point _tl_offsets[2][4] = {
+	{{15, 1}, {14, 15}, {1, 0}, {0, 14}},  // Left side driving.
+	{{15, 14}, {1, 15}, {14, 0}, {0, 1}}   // Right side driving.
+};
+
+/**
+ * Sprites needed for the various states of a TL crossing [state][direction].
+ */
+static const SpriteID _tls_to_sprites[7][4] = {
+	{SPR_TL_SW_NONE,       SPR_TL_SE_NONE,       SPR_TL_NW_NONE,       SPR_TL_NE_NONE},
+	{SPR_TL_SW_GREEN,      SPR_TL_SE_RED,        SPR_TL_NW_RED,        SPR_TL_NE_GREEN},
+	{SPR_TL_SW_YELLOW,     SPR_TL_SE_RED,        SPR_TL_NW_RED,        SPR_TL_NE_YELLOW},
+	{SPR_TL_SW_RED,        SPR_TL_SE_RED_YELLOW, SPR_TL_NW_RED_YELLOW, SPR_TL_NE_RED},
+	{SPR_TL_SW_RED,        SPR_TL_SE_GREEN,      SPR_TL_NW_GREEN,      SPR_TL_NE_RED},
+	{SPR_TL_SW_RED,        SPR_TL_SE_YELLOW,     SPR_TL_NW_YELLOW,     SPR_TL_NE_RED},
+	{SPR_TL_SW_RED_YELLOW, SPR_TL_SE_RED,        SPR_TL_NW_RED,        SPR_TL_NE_RED_YELLOW},
+};
diff --git a/src/trafficlight_func.h b/src/trafficlight_func.h
new file mode 100644
--- /dev/null
+++ b/src/trafficlight_func.h
@@ -0,0 +1,19 @@
+/* $Id: trafficlight_func.h $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file trafficlight_func.h Functions related to trafficlights. */
+
+#include "road_map.h"
+
+TrackdirBits GetTrafficLightDisallowedDirections(TileIndex tile);
+void DrawTrafficLights(TileInfo* ti);
+
+CommandCost CmdBuildTrafficLights(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text);
+CommandCost CmdRemoveTrafficLights(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text);
+void ClearAllTrafficLights();
diff --git a/src/trafficlight_type.h b/src/trafficlight_type.h
new file mode 100644
--- /dev/null
+++ b/src/trafficlight_type.h
@@ -0,0 +1,21 @@
+/* $Id: trafficlight_type.h $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file trafficlight_type.h Types related to the states of trafficlights.*/
+
+/* Which state a traffic light is in. */
+enum TrafficLightState {
+	TLS_OFF,                        ///< all lights are off (during roadworks; always in scedit)
+	TLS_X_GREEN_Y_RED,              ///< SW and NE are green, NW and SE are red
+	TLS_X_YELLOW_Y_RED,             ///< SW and NE are yellow, NW and SE are red
+	TLS_X_RED_Y_REDYELLOW,          ///< SW and NE are red, NW and SE are red-yellow
+	TLS_X_RED_Y_GREEN,              ///< SW and NE are red, NW and SE are green
+	TLS_X_RED_Y_YELLOW,             ///< SW and NE are red, NW and SE are yellow
+	TLS_X_REDYELLOW_Y_RED,          ///< SW and NE are red-yellow, NW and SE are red
+};
diff --git a/src/train.h b/src/train.h
--- a/src/train.h
+++ b/src/train.h
@@ -31,6 +31,15 @@
 	VRF_TOGGLE_REVERSE                = 7, ///< Used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle only).
 	VRF_TRAIN_STUCK                   = 8, ///< Train can't get a path reservation.
 	VRF_LEAVING_STATION               = 9, ///< Train is just leaving a station.
+
+	VRF_BREAKDOWN_BRAKING             = 10, ///< Used to mark a train that is braking because it is broken down.
+	VRF_BREAKDOWN_POWER               = 11, ///< Used to mark a train in which the power of one (or more) of the engines is reduced because of a breakdown.
+	VRF_BREAKDOWN_SPEED               = 12, ///< Used to mark a train that has a reduced maximum speed because of a breakdown.
+	VRF_BREAKDOWN_STOPPED             = 13, ///< Used to mark a train that is stopped because of a breakdown.
+	/* Bitmask of all flags that indicate a broken train (braking is not included). */
+	VRF_IS_BROKEN = (1 << VRF_BREAKDOWN_POWER) | (1 << VRF_BREAKDOWN_SPEED) | (1 << VRF_BREAKDOWN_STOPPED),
+	VRF_NEED_REPAIR                   = 14, ///< Used to mark a train that has a reduced maximum speed because of a critical breakdown.
+	VRF_TO_HEAVY                      = 15,
 };
 
 /** Modes for ignoring signals. */
@@ -48,8 +57,12 @@
 void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
 bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
 
+void DeleteVisibleTrain(Train *v);
+
 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
 
+void CheckBreakdownFlags(Train *v);
+
 /** Variables that are cached to improve performance and such */
 struct TrainCache {
 	/* Cached wagon override spritegroup */
@@ -57,6 +70,7 @@
 
 	/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
 	bool cached_tilt;           ///< train can tilt; feature provides a bonus in curves
+	uint8 cached_num_engines;   ///< total number of engines, including rear ends of multiheaded engines
 
 	byte user_def_data;         ///< Cached property 0x25. Can be set by Callback 0x36.
 
@@ -81,11 +95,14 @@
 	RailTypeByte railtype;
 	RailTypes compatible_railtypes;
 
+	/** The maximum speed of the last speed-signal passed by the train. */
+	uint16 signal_speedlimit;
+
 	/** Ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through signals. */
 	uint16 wait_counter;
 
 	/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
-	Train() : GroundVehicleBase() {}
+	Train() : GroundVehicleBase(), signal_speedlimit(UINT16_MAX) {}
 	/** We want to 'destruct' the right class. */
 	virtual ~Train() { this->PreDestructor(); }
 
@@ -150,6 +167,24 @@
 
 
 protected: // These functions should not be called outside acceleration code.
+	/**
+	 * Gets the speed a broken down train (low speed breakdown) is limited to.
+	 * @note This value is not cached, because changing cached_max_speed would have unwanted consequences (e.g. in the GUI).
+	 * @param v The front engine of the vehicle.
+	 * @return The speed the train is limited to.
+	 */
+	FORCEINLINE uint16 GetBreakdownSpeed() const
+	{
+		assert(this->IsFrontEngine());
+		uint16 speed = UINT16_MAX;
+
+		for (const Train *w = this; w != NULL; w = w->Next()) {
+			if (w->breakdown_ctr == 1 && w->breakdown_type == BREAKDOWN_LOW_SPEED) {
+				speed = min(speed, w->breakdown_severity);
+			}
+		}
+		return speed;
+	}
 
 	/**
 	 * Allows to know the power value that this vehicle will use.
@@ -237,7 +272,7 @@
 	 */
 	FORCEINLINE AccelStatus GetAccelerationStatus() const
 	{
-		return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK) ? AS_BRAKE : AS_ACCEL;
+		return (this->vehstatus & VS_STOPPED) || HasBit(this->flags, VRF_REVERSING) || HasBit(this->flags, VRF_TRAIN_STUCK ) || HasBit(this->flags, VRF_BREAKDOWN_BRAKING) ? AS_BRAKE : AS_ACCEL;
 	}
 
 	/**
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -36,10 +36,14 @@
 #include "company_base.h"
 #include "newgrf.h"
 #include "order_backup.h"
+#include "programmable_signals.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/train_cmd.h"
 
+extern SpeedLimits _speedlimits;
+
 static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck);
 static bool TrainCheckIfLineEnds(Train *v);
 static void TrainController(Train *v, Vehicle *nomove);
@@ -129,6 +133,34 @@
 }
 
 /**
+ * Checks the breakdown flags (VehicleRailFlags 9-12) and sets the correct value in the first vehicle of the consist.
+ * This function is generally only called to check if a flag may be cleared.
+ * @param v     Front engine.
+ * @param flags Bitmask of the flags to check.
+ */
+void CheckBreakdownFlags(Train *v)
+{
+	assert(v->IsFrontEngine());
+	/* Clear the flags we're gonna check first, we'll set them again later (if applicable). */
+	CLRBITS(v->flags, (1 << VRF_BREAKDOWN_BRAKING) | VRF_IS_BROKEN);
+
+	for (const Train *w = v; w != NULL; w = w->Next()) {
+		if (v->IsEngine() || w->IsMultiheaded()) {
+			if (w->breakdown_ctr == 2) {
+				SetBit(v->flags, VRF_BREAKDOWN_BRAKING);
+			} else if (w->breakdown_ctr == 1) {
+				switch (w->breakdown_type) {
+					case BREAKDOWN_CRITICAL:
+					case BREAKDOWN_EM_STOP:   SetBit(v->flags, VRF_BREAKDOWN_STOPPED); break;
+					case BREAKDOWN_LOW_SPEED: SetBit(v->flags, VRF_BREAKDOWN_SPEED);   break;
+					case BREAKDOWN_LOW_POWER: SetBit(v->flags, VRF_BREAKDOWN_POWER);   break;
+				}
+			}
+		}
+	}
+}
+
+/**
  * Recalculates the cached stuff of a train. Should be called each time a vehicle is added
  * to/removed from the chain, and when the game is loaded.
  * Note: this needs to be called too for 'wagon chains' (in the depot, without an engine)
@@ -144,6 +176,7 @@
 	EngineID first_engine = this->IsFrontEngine() ? this->engine_type : INVALID_ENGINE;
 	this->gcache.cached_total_length = 0;
 	this->compatible_railtypes = RAILTYPES_NONE;
+	this->tcache.cached_num_engines = 0;
 
 	bool train_can_tilt = true;
 
@@ -212,8 +245,13 @@
 			/* max speed is the minimum of the speed limits of all vehicles in the consist */
 			if ((rvi_u->railveh_type != RAILVEH_WAGON || _settings_game.vehicle.wagon_speed_limits) && !UsesWagonOverride(u)) {
 				uint16 speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, rvi_u->max_speed);
+				if (HasBit(u->flags, VRF_NEED_REPAIR)) speed = u->vcache.cached_max_speed;
 				if (speed != 0) max_speed = min(speed, max_speed);
 			}
+			
+			if(u->IsEngine() || u-> IsMultiheaded()) {
+				this->tcache.cached_num_engines++;
+			}
 		}
 
 		u->cargo_cap = e_u->DetermineCapacity(u);
@@ -423,6 +461,10 @@
 		}
 	}
 
+	if ( HasBit(this->flags, VRF_BREAKDOWN_SPEED) ) {
+		max_speed = min(max_speed, this->GetBreakdownSpeed());
+	}
+
 	return min(max_speed, this->gcache.cached_max_track_speed);
 }
 
@@ -434,6 +476,9 @@
 	uint weight = this->gcache.cached_weight;
 	assert(weight != 0);
 	this->acceleration = Clamp(power / weight * 4, 1, 255);
+	
+	/* For non-realistic acceleration, breakdown chance is 128, corrected by the multiengine factor of 3/(n+2). */
+	this->breakdown_chance = min(128 * 3 / (this->tcache.cached_num_engines + 2), 5);
 }
 
 /**
@@ -645,6 +690,8 @@
 	u->cargo_cap = v->cargo_cap;
 	u->railtype = v->railtype;
 	u->engine_type = v->engine_type;
+	u->reliability = v->reliability;
+	u->reliability_spd_dec = v->reliability_spd_dec;
 	u->build_year = v->build_year;
 	u->cur_image = SPR_IMG_QUERY;
 	u->random_bits = VehicleRandomBits();
@@ -671,6 +718,13 @@
 {
 	const RailVehicleInfo *rvi = &e->u.rail;
 
+	if (flags & DC_QUERY_COST) return CommandCost();
+
+	/* Check if the train is actually being built in a depot belonging
+	 * to the company. Doesn't matter if only the cost is queried */
+	if (!IsRailDepotTile(tile)) return CMD_ERROR;
+	if (!IsInfraUsageAllowed(VEH_TRAIN, _current_company, GetTileOwner(tile))) return CMD_ERROR;
+
 	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(tile, flags, e, ret);
 
 	/* Check if depot and new engine uses the same kind of tracks *
@@ -695,7 +749,9 @@
 		v->spritenum = rvi->image_index;
 		v->cargo_type = e->GetDefaultCargoType();
 		v->cargo_cap = rvi->capacity;
+
 		v->last_station_visited = INVALID_STATION;
+		v->last_loading_station = INVALID_STATION;
 
 		v->engine_type = e->index;
 		v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
@@ -1571,19 +1627,31 @@
 	return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum);
 }
 
+/** Check if the crossing should be closed // TODO: allow vehicles to exit a closed block but not let them enter it -> complicated ...
+ *  @return train on crossing || train approaching crossing || reserved
+ */
+static inline bool CheckLevelCrossing(TileIndex tile)
+{
+	return HasCrossingReservation(tile) || HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
+}
 
 /**
  * Sets correct crossing state
  * @param tile tile to update
  * @param sound should we play sound?
+ * @param force_state force close the crossing due to an adjacent tile
  * @pre tile is a rail-road crossing
  */
-void UpdateLevelCrossing(TileIndex tile, bool sound)
+static void UpdateLevelCrossingTile(TileIndex tile, bool sound, bool force_state = false)
 {
 	assert(IsLevelCrossingTile(tile));
-
-	/* train on crossing || train approaching crossing || reserved */
-	bool new_state = HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile) || HasCrossingReservation(tile);
+	bool new_state;
+
+	if (force_state) {
+		new_state = force_state;
+	} else {
+		new_state = CheckLevelCrossing(tile);
+	}
 
 	if (new_state != IsCrossingBarred(tile)) {
 		if (new_state && sound) {
@@ -1594,6 +1662,28 @@
 	}
 }
 
+/**
+ * Cycles the adjacent crossings and sets their state
+ * @param tile tile to update
+ * @param sound should we play sound?
+ */
+void UpdateLevelCrossing(TileIndex tile, bool sound)
+{
+	bool is_forced = false;
+	for (TileIndex t = tile; !is_forced && IsTileType(t, MP_ROAD) && IsLevelCrossingTile(t); t = TileAddByDiagDir(t, AxisToDiagDir(GetCrossingRoadAxis(t)))) {
+		is_forced |= CheckLevelCrossing(t);
+	}
+	for (TileIndex t = tile; !is_forced && IsTileType(t, MP_ROAD) && IsLevelCrossingTile(t); t = TileAddByDiagDir(t, ReverseDiagDir(AxisToDiagDir(GetCrossingRoadAxis(t))))) {
+		is_forced |= CheckLevelCrossing(t);
+	}
+	
+	for (TileIndex t = tile; IsTileType(t, MP_ROAD) && IsLevelCrossingTile(t); t = TileAddByDiagDir(t, AxisToDiagDir(GetCrossingRoadAxis(t)))) {
+		UpdateLevelCrossingTile(t, sound, is_forced);
+	}
+	for (TileIndex t = tile; IsTileType(t, MP_ROAD) && IsLevelCrossingTile(t); t = TileAddByDiagDir(t, ReverseDiagDir(AxisToDiagDir(GetCrossingRoadAxis(t))))) {
+		UpdateLevelCrossingTile(t, sound, is_forced);
+	}
+}
 
 /**
  * Bars crossing and plays ding-ding sound if not barred already
@@ -1603,9 +1693,8 @@
 static inline void MaybeBarCrossingWithSound(TileIndex tile)
 {
 	if (!IsCrossingBarred(tile)) {
-		BarCrossing(tile);
-		SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
-		MarkTileDirtyByTile(tile);
+		SetCrossingReservation(tile, true);
+		UpdateLevelCrossing(tile, true);
 	}
 }
 
@@ -1751,6 +1840,17 @@
 		return;
 	}
 
+	/*We are inside tunnel bidge with signals reversing will close the entrance */
+	if (HasWormholeSignals(v->tile)) {
+		/* Flip signal on tunnel entrance tile red */
+		SetBitTunnelBridgeExit(v->tile); 
+		MarkTileDirtyByTile(v->tile);
+		/* clear counters to avoid overflow*/
+		v->wait_counter = 0;
+		v->load_unload_ticks = 0;
+		return;
+	}
+
 	/* TrainExitDir does not always produce the desired dir for depots and
 	 * tunnels/bridges that is needed for UpdateSignalsOnSegment. */
 	DiagDirection dir = TrainExitDir(v->direction, v->track);
@@ -1820,7 +1920,7 @@
 		}
 	} else {
 		/* turn the whole train around */
-		if ((v->vehstatus & VS_CRASHED) || v->breakdown_ctr != 0) return CMD_ERROR;
+		if ((v->vehstatus & VS_CRASHED) || HasBit(v->flags, VRF_BREAKDOWN_STOPPED)) return CMD_ERROR;
 
 		if (flags & DC_EXEC) {
 			/* Properly leave the station if we are loading and won't be loading anymore */
@@ -1865,7 +1965,7 @@
 	Train *t = Train::GetIfValid(p1);
 	if (t == NULL) return CMD_ERROR;
 
-	CommandCost ret = CheckOwnership(t->owner);
+	CommandCost ret = CheckVehicleControlAllowed(t);
 	if (ret.Failed()) return ret;
 
 
@@ -1966,10 +2066,19 @@
 
 	Trackdir td = v->GetVehicleTrackdir();
 
-	/* On a tile with a red non-pbs signal, don't look ahead. */
 	if (IsTileType(v->tile, MP_RAILWAY) && HasSignalOnTrackdir(v->tile, td) &&
-			!IsPbsSignal(GetSignalType(v->tile, TrackdirToTrack(td))) &&
-			GetSignalStateByTrackdir(v->tile, td) == SIGNAL_STATE_RED) return;
+			!IsPbsSignal(GetSignalType(v->tile, TrackdirToTrack(td)))) {
+		/* On a tile with a speed-signal, apply its speed limit. */
+		if (IsSpeedSignal(GetSignalType(v->tile, TrackdirToTrack(td))) &&
+				HasSignalOnTrackdir(v->tile, td)) {
+			v->signal_speedlimit = GetSignalSpeed(SignalReference(v->tile, TrackdirToTrack(td)));
+		}
+
+		/* On a tile with a red non-pbs signal, don't look ahead. */
+		if (GetSignalStateByTrackdir(v->tile, td) == SIGNAL_STATE_RED) {
+			return;
+		}
+	}
 
 	CFollowTrackRail ft(v);
 	if (!ft.Follow(v->tile, td)) return;
@@ -2064,6 +2173,46 @@
 	return false;
 }
 
+/* Maximum bridge size is 100 tiles, 16 bit available for signals in m2 =>
+ * 25 blocks of 4 tiles available between ramps */
+static const uint8 bridge_signal_block_size = TILE_SIZE * 4;
+ 
+static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDirection dir, bool free)
+{
+	if (IsBridge(end) && _m[end].m2 > 0){
+		/* clearing last bridge signal */
+		uint16 m = _m[end].m2;
+		byte i = 15;
+		while((m & 0x8000) == 0 && --i > 0) m <<= 1;
+		ClrBit(_m[end].m2, i);
+
+		uint x = TileX(end)* TILE_SIZE;
+		uint y = TileY(end)* TILE_SIZE;
+		uint distance = bridge_signal_block_size * ++i;
+		switch (dir) {
+			default: NOT_REACHED();
+			case DIAGDIR_NE: MarkTileDirtyByTile(TileVirtXY(x - distance, y)); break;
+			case DIAGDIR_SE: MarkTileDirtyByTile(TileVirtXY(x, y + distance)); break;
+			case DIAGDIR_SW: MarkTileDirtyByTile(TileVirtXY(x + distance, y)); break;
+			case DIAGDIR_NW: MarkTileDirtyByTile(TileVirtXY(x, y - distance)); break;
+		}
+		MarkTileDirtyByTile(tile);
+	}
+	if (free) {
+	/* Open up the wormhole and clear m2*/
+		_m[tile].m2 = 0;
+		_m[end].m2 = 0;
+
+		if (IsTunnelBridgeWithSignRed(end)) {
+			ClrBitTunnelBridgeExit(end);
+			if (!_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(end);
+		} else if (IsTunnelBridgeWithSignRed(tile)) {
+			ClrBitTunnelBridgeExit(tile);
+			if (!_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(tile);
+		}
+	}
+}
+
 /** Clear the reservation of a tile that was just left by a wagon on track_dir. */
 static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir)
 {
@@ -2074,7 +2223,8 @@
 		if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
 			TileIndex end = GetOtherTunnelBridgeEnd(tile);
 
-			if (TunnelBridgeIsFree(tile, end, v).Succeeded()) {
+			bool free = TunnelBridgeIsFree(tile, end, v).Succeeded();
+			if (free) {
 				/* Free the reservation only if no other train is on the tiles. */
 				SetTunnelBridgeReservation(tile, false);
 				SetTunnelBridgeReservation(end, false);
@@ -2084,6 +2234,7 @@
 					MarkTileDirtyByTile(end);
 				}
 			}
+			if (HasWormholeSignals(tile)) HandleLastTunnelBridgeSignals(tile, end, dir, free);
 		}
 	} else if (IsRailStationTile(tile)) {
 		TileIndex new_tile = TileAddByDiagDir(tile, dir);
@@ -2121,7 +2272,7 @@
 		if (!IsValidTrackdir(td)) break;
 
 		if (IsTileType(tile, MP_RAILWAY)) {
-			if (HasSignalOnTrackdir(tile, td) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(td)))) {
+			if (HasSignalOnTrackdir(tile, td) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(td))) && !IsSpeedSignal(GetSignalType(tile, TrackdirToTrack(td)))) {
 				/* Conventional signal along trackdir: remove reservation and stop. */
 				UnreserveRailTrack(tile, TrackdirToTrack(td));
 				break;
@@ -2135,7 +2286,9 @@
 					SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED);
 					MarkTileDirtyByTile(tile);
 				}
-			} else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
+			} else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) &&
+					IsOnewaySignal(tile, TrackdirToTrack(td)) &&
+					!IsSpeedSignal(tile, TrackdirToTrack(td))) {
 				break;
 			}
 		}
@@ -2653,6 +2806,26 @@
 }
 
 /**
+ * Handle all breakdown related stuff for a train consist.
+ * @param v Front engine.
+ */
+static bool HandlePossibleBreakdowns(Train *v)
+{
+	assert(v->IsFrontEngine());
+	for (Train *u = v; u != NULL; u = u->Next()) {
+		if (u->breakdown_ctr != 0 && (u->IsEngine() || u->IsMultiheaded())) {
+			if (u->breakdown_ctr <= 2) {
+				if ( u->HandleBreakdown() ) return true;
+				/* We check the order of v (the first vehicle) instead of u here! */
+			} else if (!v->current_order.IsType(OT_LOADING)) {
+				u->breakdown_ctr--;
+			}
+		}
+	}
+	return false;
+}
+
+/**
  * Trains enters a station, send out a news item if it is the first train, and start loading.
  * @param v Train that entered the station.
  * @param station Station visited.
@@ -2686,8 +2859,11 @@
 /* Check if the vehicle is compatible with the specified tile */
 static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
 {
-	return IsTileOwner(tile, v->owner) &&
-			(!v->IsFrontEngine() || HasBit(v->compatible_railtypes, GetRailType(tile)));
+	return
+		IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, tile) && (
+			!v->IsFrontEngine() ||
+			HasBit(v->compatible_railtypes, GetRailType(tile))
+		);
 }
 
 struct RailtypeSlowdownParams {
@@ -2906,6 +3082,101 @@
 	return t;
 }
 
+/** Find train in front and keep distance between trains in tunnel / bridge */
+static Vehicle *FindSpaceBetweenTrainsEnum(Vehicle *v, void *data)
+{
+	/* Don't look at wagons between front and back of train*/
+	if (v->type != VEH_TRAIN || (v->Previous() != NULL && v->Next() != NULL)) return NULL;
+
+	const Vehicle *u = (Vehicle*)data;
+	int32 a, b = 0;
+
+	switch (u->direction) {
+		default: NOT_REACHED();
+		case DIR_NE: a = u->x_pos; b = v->x_pos; break;
+		case DIR_SE: a = v->y_pos; b = u->y_pos; break;
+		case DIR_SW: a = v->x_pos; b = u->x_pos; break;
+		case DIR_NW: a = u->y_pos; b = v->y_pos; break;
+	}
+
+	if (a > b && a <= (b + (int)(Train::From(u)->wait_counter)) + (int)(TILE_SIZE)) return v;
+	return NULL;
+}
+
+static bool IsToCloseBehindTrain(Vehicle *v, TileIndex tile, bool check_endtile)
+{
+	Train *t = (Train *)v;
+	
+	if (t->force_proceed != 0) return false;
+
+	if (HasVehicleOnPos(t->tile, v, &FindSpaceBetweenTrainsEnum)) {
+		/* Revert train if not going with tunnel direction. */
+		if (DirToDiagDir(t->direction) != GetTunnelBridgeDirection(t->tile)) {
+			v->cur_speed = 0;
+			ToggleBit(t->flags, VRF_REVERSING);
+		}
+		return true;
+	}
+    /* cover blind spot at end of tunnel bridge */
+	if (check_endtile){
+		if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(t->tile), v, &FindSpaceBetweenTrainsEnum)) {
+			/* Revert train if not going with tunnel direction. */
+			if (DirToDiagDir(t->direction) != GetTunnelBridgeDirection(t->tile)) {
+				v->cur_speed = 0;
+				ToggleBit(t->flags, VRF_REVERSING);
+			}
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/** Simulate signals in tunnel / bridge */
+static bool CheckTrainStayInWormHole(Train *t, TileIndex tile)
+{
+	if (t->force_proceed != 0) return false;
+	
+	/* When not exit reverse train */
+	if (!IsTunnelBridgeExit(tile)) {
+		t->cur_speed = 0;
+		ToggleBit(t->flags, VRF_REVERSING);
+		return true;
+	}
+	SigSegState seg_state = _settings_game.pf.reserve_paths ? SIGSEG_PBS : UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, t->owner);
+	if (seg_state == SIGSEG_FULL || (seg_state == SIGSEG_PBS && !TryPathReserve(t))) {
+		t->cur_speed = 0;
+		return true;
+	}
+
+	return false; 
+}
+
+
+static void HandleSignalBehindTrain(Train *v, uint signal_number)
+{
+	TileIndex tile;
+	switch (v->direction) {
+		default: NOT_REACHED();
+		case DIR_NE: tile = TileVirtXY(v->x_pos + bridge_signal_block_size, v->y_pos); break;
+		case DIR_SE: tile = TileVirtXY(v->x_pos, v->y_pos - bridge_signal_block_size ); break;
+		case DIR_SW: tile = TileVirtXY(v->x_pos - bridge_signal_block_size, v->y_pos); break;
+		case DIR_NW: tile = TileVirtXY(v->x_pos, v->y_pos + bridge_signal_block_size); break;
+	}
+
+	if(tile == v->tile) {
+		/* flip signal on ramp */
+		if (IsTunnelBridgeWithSignRed(tile)) {
+			ClrBitTunnelBridgeExit(tile);
+			MarkTileDirtyByTile(tile);
+		}
+	} else if (IsBridge(v->tile) && signal_number <= 16) {
+		ClrBit(_m[v->tile].m2, signal_number);
+		MarkTileDirtyByTile(tile);
+	}
+		//DEBUG(misc, 0, "tile 0x%.4X, v->nº %u, tick %u", tile, v->First()->unitnumber, signal_number);
+}
+
 static void TrainController(Train *v, Vehicle *nomove)
 {
 	Train *first = v->First();
@@ -2917,6 +3188,10 @@
 		DiagDirection enterdir = DIAGDIR_BEGIN;
 		bool update_signals_crossing = false; // will we update signals or crossing state?
 
+		/* do not exceed any speed limit that has been applied */
+		if (v->signal_speedlimit > 0)
+			v->cur_speed = min(v->cur_speed, v->signal_speedlimit);
+
 		GetNewVehiclePosResult gp = GetNewVehiclePos(v);
 		if (v->track != TRACK_BIT_WORMHOLE) {
 			/* Not inside tunnel */
@@ -2926,6 +3201,7 @@
 					/* Inside depot */
 					gp.x = v->x_pos;
 					gp.y = v->y_pos;
+					v->signal_speedlimit = 0;
 				} else {
 					/* Not inside depot */
 
@@ -2999,6 +3275,10 @@
 						/* Don't handle stuck trains here. */
 						if (HasBit(v->flags, VRF_TRAIN_STUCK)) return;
 
+						/* this codepath seems to be run every 5 ticks, so increase counter twice every 20 ticks */
+						IncreaseStuckCounter(v->tile);
+						if (v->tick_counter % 4 == 0) IncreaseStuckCounter(v->tile);
+
 						if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) {
 							v->cur_speed = 0;
 							v->subspeed = 0;
@@ -3083,6 +3363,23 @@
 					goto invalid_rail;
 				}
 
+				if (HasWormholeSignals(gp.new_tile)) {
+					/* if red signal stop */
+					if (v->IsFrontEngine() && v->force_proceed == 0) {
+						if (IsTunnelBridgeWithSignRed(gp.new_tile)) {
+							v->cur_speed = 0;
+							return;
+						}
+						if (IsTunnelBridgeExit(gp.new_tile)) {
+							v->cur_speed = 0;
+							goto invalid_rail;
+						}
+						/* Flip signal on tunnel entrance tile red */
+						SetBitTunnelBridgeExit(gp.new_tile); 
+						MarkTileDirtyByTile(gp.new_tile);
+					}
+				}
+
 				if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
 					Track track = FindFirstTrack(chosen_track);
 					Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir);
@@ -3143,6 +3440,63 @@
 				first->cur_speed = min(first->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed);
 			}
 
+			/* handle signal simulation on tunnel bridge */
+			TileIndex old_tile = TileVirtXY(v->x_pos, v->y_pos);
+			if (old_tile != gp.new_tile && HasWormholeSignals(v->tile) && (v->IsFrontEngine() || v->Next() == NULL)){
+				if (old_tile == v->tile) {
+					if (v->IsFrontEngine() && v->force_proceed == 0 && IsTunnelBridgeExit(v->tile)) goto invalid_rail; 
+					/* Entered wormhole set counters*/
+					v->wait_counter = bridge_signal_block_size - TILE_SIZE;
+					v->load_unload_ticks = 0;
+				}
+
+				int distance = v->wait_counter;
+				bool leaving = false;
+				if (distance == 0) v->wait_counter = bridge_signal_block_size;
+
+				if (v->IsFrontEngine()) {
+					/* Check if track in front is free and see if we can leave wormhole */
+					int z = GetSlopeZ(gp.x, gp.y) - v->z_pos;
+					if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) &&	!(abs(z) > 2)) {
+						if (CheckTrainStayInWormHole(v, gp.new_tile)) return;
+						leaving = true;
+					} else {
+						if (IsToCloseBehindTrain(v, gp.new_tile, distance == 0)) {
+							if (distance == 0) v->wait_counter = 0;
+							v->cur_speed = 0;
+							return;
+						}
+						/* flip signal in front to red on bridges*/
+						if (distance == 0 && v->load_unload_ticks <= 15 && IsBridge(v->tile)){
+							SetBit(_m[v->tile].m2, v->load_unload_ticks);
+							MarkTileDirtyByTile(gp.new_tile);
+						}
+					}
+				}
+				if (v->Next() == NULL) {
+					if (v->load_unload_ticks > 0 && v->load_unload_ticks <= 16 && distance == bridge_signal_block_size - TILE_SIZE) HandleSignalBehindTrain(v, v->load_unload_ticks - 2);
+					if (old_tile == v->tile) {
+						/* We left ramp into wormhole */
+						v->x_pos = gp.x;
+						v->y_pos = gp.y;
+						UpdateSignalsOnSegment(old_tile, INVALID_DIAGDIR, v->owner);
+					}
+				}
+				if (distance == 0) v->load_unload_ticks++;
+				v->wait_counter -= TILE_SIZE;
+
+				if (leaving) { // reset counters
+					v->force_proceed = 0;
+					v->wait_counter = 0;
+					v->load_unload_ticks = 0;
+					v->x_pos = gp.x;
+					v->y_pos = gp.y;
+					VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
+					UpdateSignalsOnSegment(gp.new_tile, INVALID_DIAGDIR, v->owner);
+					continue;
+				}
+			}
+
 			if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
 				/* Perform look-ahead on tunnel exit. */
 				if (v->IsFrontEngine()) {
@@ -3157,7 +3511,7 @@
 			} else {
 				v->x_pos = gp.x;
 				v->y_pos = gp.y;
-				VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
+				VehicleMove(v, v->IsDrawn());
 				continue;
 			}
 		}
@@ -3497,12 +3851,8 @@
 {
 	/* First, handle broken down train */
 
-	int t = v->breakdown_ctr;
-	if (t > 1) {
+	if(HasBit(v->flags, VRF_BREAKDOWN_BRAKING)) {
 		v->vehstatus |= VS_TRAIN_SLOWING;
-
-		uint16 break_speed = _breakdown_speeds[GB(~t, 4, 4)];
-		if (break_speed < v->cur_speed) v->cur_speed = break_speed;
 	} else {
 		v->vehstatus &= ~VS_TRAIN_SLOWING;
 	}
@@ -3557,7 +3907,7 @@
 	}
 
 	/* train is broken down? */
-	if (v->HandleBreakdown()) return true;
+	if ( HandlePossibleBreakdowns(v) ) return true;
 
 	if (HasBit(v->flags, VRF_REVERSING) && v->cur_speed == 0) {
 		ReverseTrainDirection(v);
@@ -3603,6 +3953,7 @@
 	/* Handle stuck trains. */
 	if (!mode && HasBit(v->flags, VRF_TRAIN_STUCK)) {
 		++v->wait_counter;
+		if (v->tick_counter % 4 == 0) IncreaseStuckCounter(v->tile);
 
 		/* Should we try reversing this tick if still stuck? */
 		bool turn_around = v->wait_counter % (_settings_game.pf.wait_for_pbs_path * DAY_TICKS) == 0 && _settings_game.pf.reverse_at_signals;
@@ -3678,7 +4029,7 @@
 	}
 
 	for (Train *u = v; u != NULL; u = u->Next()) {
-		if ((u->vehstatus & VS_HIDDEN) != 0) continue;
+		if (!u->IsDrawn()) continue;
 
 		u->UpdateViewport(false, false);
 	}
@@ -3800,6 +4151,9 @@
 			/* running costs */
 			CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR  * DAY_TICKS));
 
+			/* sharing fee */
+			PayDailyTrackSharingFee(this);
+
 			this->profit_this_year -= cost.GetCost();
 			this->running_ticks = 0;
 
@@ -3809,6 +4163,10 @@
 			SetWindowClassesDirty(WC_TRAINS_LIST);
 		}
 	}
+	
+	if(IsEngine() || IsMultiheaded()) {
+		CheckVehicleBreakdown(this);
+	}
 }
 
 Trackdir Train::GetVehicleTrackdir() const
@@ -3827,3 +4185,49 @@
 
 	return TrackDirectionToTrackdir(FindFirstTrack(this->track), this->direction);
 }
+
+/**
+ * Delete a train while it is visible.
+ * This happens when a company bankrupts when infrastructure sharing is enabled.
+ * @param v The train to delete.
+ */
+void DeleteVisibleTrain(Train *v)
+{
+	FreeTrainTrackReservation(v);
+	TileIndex crossing = TrainApproachingCrossingTile(v);
+
+	/* delete train from back to front */
+	Train *u;
+	Train *prev = v->Last();
+	do {
+		u = prev;
+		prev = u->Previous();
+		if (prev != NULL) prev->SetNext(NULL);
+
+		/* 'u' shouldn't be accessed after it has been deleted */
+		TileIndex tile = u->tile;
+		TrackBits trackbits = u->track;
+
+		delete u;
+
+		if (trackbits == TRACK_BIT_WORMHOLE) {
+			/* Vehicle is inside a wormhole, u->track contains no useful value then. */
+			trackbits = DiagDirToDiagTrackBits(GetTunnelBridgeDirection(tile));
+		}
+
+		Track track = TrackBitsToTrack(trackbits);
+		if (HasReservedTracks(tile, trackbits)) UnreserveRailTrack(tile, track);
+		if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile);
+
+		/* Update signals */
+		if (IsTileType(tile, MP_TUNNELBRIDGE) || IsRailDepotTile(tile)) {
+			AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile));
+		} else {
+			AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
+		}
+	} while (prev != NULL);
+
+	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
+
+	UpdateSignalsInBuffer();
+}
diff --git a/src/train_gui.cpp b/src/train_gui.cpp
--- a/src/train_gui.cpp
+++ b/src/train_gui.cpp
@@ -211,17 +211,68 @@
  * @param right The right most coordinate to draw
  * @param y     The y coordinate
  */
-static void TrainDetailsInfoTab(const Vehicle *v, int left, int right, int y)
+static void TrainDetailsInfoTab(const Train *v, int left, int right, int y, byte line_number)
 {
-	if (RailVehInfo(v->engine_type)->railveh_type == RAILVEH_WAGON) {
+	const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
+	bool show_speed = !UsesWagonOverride(v) && (_settings_game.vehicle.wagon_speed_limits || rvi->railveh_type != RAILVEH_WAGON);
+	uint16 speed;
+
+	if (rvi->railveh_type == RAILVEH_WAGON) {
 		SetDParam(0, v->engine_type);
 		SetDParam(1, v->value);
-		DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+
+		if ( show_speed && (speed = GetVehicleProperty(v, PROP_TRAIN_SPEED, rvi->max_speed))) {
+			SetDParam(2, speed); // StringID++
+			DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_AND_SPEED, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+		} else {
+			DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+		}
 	} else {
-		SetDParam(0, v->engine_type);
-		SetDParam(1, v->build_year);
-		SetDParam(2, v->value);
-		DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+		switch (line_number) {
+			case 0:
+				SetDParam(0, v->engine_type);
+				SetDParam(1, v->build_year);
+				SetDParam(2, v->value);
+
+				if (show_speed && (speed = GetVehicleProperty(v, PROP_TRAIN_SPEED, rvi->max_speed))) {
+					SetDParam(3, speed); // StringID++
+					DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE_AND_SPEED, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+				} else {
+					DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+				}					
+				break;
+
+			case 1:
+				SetDParam(0, v->reliability * 100 >> 16);
+				SetDParam(1, v->breakdowns_since_last_service);
+				DrawString(left, right, y, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+				break;
+
+			case 2:
+				if (v->breakdown_ctr == 1) {
+					if (_settings_game.vehicle.improved_breakdowns) {
+						SetDParam(0, STR_VEHICLE_STATUS_BROKEN_DOWN_VEL);
+						SetDParam(1, STR_BREAKDOWN_TYPE_CRITICAL + v->breakdown_type);
+						if (v->breakdown_type == BREAKDOWN_LOW_SPEED) {
+							SetDParam(2, min(v->First()->GetCurrentMaxSpeed(), v->breakdown_severity));
+						} else if (v->breakdown_type == BREAKDOWN_LOW_POWER) {
+							SetDParam(2, v->breakdown_severity * 100 / 256);
+						}
+					} else {
+						SetDParam(0, STR_VEHICLE_STATUS_BROKEN_DOWN);
+					}
+				} else {
+					if (HasBit(v->flags, VRF_NEED_REPAIR)) {
+						SetDParam(0, STR_NEED_REPAIR);
+						SetDParam(1, v->vcache.cached_max_speed);
+					} else {
+						SetDParam(0, STR_RUNNING);
+					}
+				}
+				DrawString(left, right, y, STR_CURRENT_STATUS, TC_FROMSTRING, SA_LEFT | SA_STRIP);
+				break;
+			default: NOT_REACHED();
+		}
 	}
 }
 
@@ -322,6 +373,7 @@
 			uint length = GetLengthOfArticulatedVehicle(v);
 			if (length > TRAIN_DETAILS_MAX_INDENT) num++;
 		}
+		if (det_tab == 1) num += 2 * Train::Get(veh_id)->tcache.cached_num_engines;
 	}
 
 	return num;
@@ -345,6 +397,7 @@
 		bool rtl = _current_text_dir == TD_RTL;
 		Direction dir = rtl ? DIR_E : DIR_W;
 		int x = rtl ? right : left;
+		byte line_number = 0;
 		int sprite_y_offset = 4 + (FONT_HEIGHT_NORMAL - 10) / 2;
 		int line_height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
 		for (; v != NULL && vscroll_pos > -vscroll_cap; v = v->GetNextVehicle()) {
@@ -357,7 +410,7 @@
 			do {
 				Point offset;
 				int width = u->GetDisplayImageWidth(&offset);
-				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
+				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap && line_number == 0) {
 					PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
 					DrawSprite(u->GetImage(dir, EIT_IN_DETAILS), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + offset.y);
 				}
@@ -374,6 +427,13 @@
 
 			uint num_lines = max(1u, _cargo_summary.Length());
 			for (uint i = 0; i < num_lines; i++) {
+// TODO: While i++ is removed from the for loop the game will crash in the info tab when an improved breakdown occurs,
+//       but with it present the status line(s) of the engine(s) do(es) not show up in the information tab.
+//       Temporary fixes: (or not and)
+//	      - outcommenting the assert in strings_func.h line 81. (Not very bright, I know ;) )
+//        - Put back i++ in for loop above.
+//
+// For now i++ is put back so some info is missing in the gui. (outcommenting the assert may have other unwanted effects.)
 				int sprite_width = max<int>(dx, TRAIN_DETAILS_MIN_INDENT) + 3;
 				int data_left  = left + (rtl ? 0 : sprite_width);
 				int data_right = right - (rtl ? sprite_width : 0);
@@ -392,7 +452,7 @@
 							break;
 
 						case TDW_TAB_INFO:
-							if (i == 0) TrainDetailsInfoTab(v, data_left, data_right, py);
+							if (i == 0) TrainDetailsInfoTab(v, data_left, data_right, py, line_number);
 							break;
 
 						case TDW_TAB_CAPACITY:
@@ -406,6 +466,12 @@
 						default: NOT_REACHED();
 					}
 				}
+				if (det_tab != 1 || line_number >= (Train::From(v)->IsWagon() ? 0 : 2)) {
+					line_number = 0;
+					 i++;
+				} else {
+					line_number++;
+				}
 				vscroll_pos--;
 			}
 		}
diff --git a/src/transparency.h b/src/transparency.h
--- a/src/transparency.h
+++ b/src/transparency.h
@@ -31,6 +31,7 @@
 	TO_STRUCTURES, ///< other objects such as transmitters and lighthouses
 	TO_CATENARY,   ///< catenary
 	TO_LOADING,    ///< loading indicators
+	TO_TUNNELS,    ///< vehicles in tunnels
 	TO_END,
 	TO_INVALID,    ///< Invalid transparency option
 };
diff --git a/src/transparency_gui.cpp b/src/transparency_gui.cpp
--- a/src/transparency_gui.cpp
+++ b/src/transparency_gui.cpp
@@ -35,14 +35,14 @@
 	TTW_WIDGET_STRUCTURES,               ///< Object structure transparency toggle button.
 	TTW_WIDGET_CATENARY,                 ///< Catenary transparency toggle button.
 	TTW_WIDGET_LOADING,                  ///< Loading indicators transparency toggle button.
+	TTW_WIDGET_TUNNELS,                  ///< Vehicles in tunnels toggle button.
 	TTW_WIDGET_END,                      ///< End of toggle buttons.
 
 	/* Panel with buttons for invisibility */
 	TTW_WIDGET_BUTTONS,                  ///< Panel with 'invisibility' buttons.
 };
 
-class TransparenciesWindow : public Window
-{
+class TransparenciesWindow : public Window {
 public:
 	TransparenciesWindow(const WindowDesc *desc, int window_number) : Window()
 	{
@@ -66,14 +66,15 @@
 			case TTW_WIDGET_BRIDGES:
 			case TTW_WIDGET_STRUCTURES:
 			case TTW_WIDGET_CATENARY:
-			case TTW_WIDGET_LOADING: {
+			case TTW_WIDGET_LOADING:
+			case TTW_WIDGET_TUNNELS: {
 				uint i = widget - TTW_WIDGET_BEGIN;
 				if (HasBit(_transparency_lock, i)) DrawSprite(SPR_LOCK, PAL_NONE, r.left + 1, r.top + 1);
 				break;
 			}
 			case TTW_WIDGET_BUTTONS:
 				for (uint i = TTW_WIDGET_BEGIN; i < TTW_WIDGET_END; i++) {
-					if (i == TTW_WIDGET_LOADING) continue; // Do not draw button for invisible loading indicators.
+					if (i >= TTW_WIDGET_LOADING) continue; // Do not draw button for invisible loading indicators.
 
 					const NWidgetBase *wi = this->GetWidget<NWidgetBase>(i);
 					DrawFrameRect(wi->pos_x + 1, r.top + 2, wi->pos_x + wi->current_x - 2, r.bottom - 2, COLOUR_PALE_GREEN,
@@ -85,7 +86,7 @@
 
 	virtual void OnClick(Point pt, int widget, int click_count)
 	{
-		if (widget >= TTW_WIDGET_BEGIN && widget < TTW_WIDGET_END) {
+		if (IsInsideMM(widget, TTW_WIDGET_BEGIN, TTW_WIDGET_END)) {
 			if (_ctrl_pressed) {
 				/* toggle the bit of the transparencies lock variable */
 				ToggleTransparencyLock((TransparencyOption)(widget - TTW_WIDGET_BEGIN));
@@ -155,7 +156,8 @@
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_WIDGET_STRUCTURES), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRANSMITTER, STR_TRANSPARENT_STRUCTURES_TOOLTIP),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_WIDGET_CATENARY), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_BUILD_X_ELRAIL, STR_TRANSPARENT_CATENARY_TOOLTIP),
 		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_WIDGET_LOADING), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRAINLIST, STR_TRANSPARENT_LOADING_TOOLTIP),
-		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 1), EndContainer(),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, TTW_WIDGET_TUNNELS), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_TRANSPARENT_TUNNELS_TOOLTIP),
+	NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(1, 1), EndContainer(),
 	EndContainer(),
 	/* Panel with 'inivisibility' buttons. */
 	NWidget(WWT_PANEL, COLOUR_DARK_GREEN, TTW_WIDGET_BUTTONS), SetMinimalSize(219, 13), SetDataTip(0x0, STR_TRANSPARENT_INVISIBLE_TOOLTIP),
diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp
--- a/src/tree_cmd.cpp
+++ b/src/tree_cmd.cpp
@@ -75,7 +75,7 @@
 
 		case MP_CLEAR:
 			return !IsBridgeAbove(tile) && !IsClearGround(tile, CLEAR_FIELDS) && GetRawClearGround(tile) != CLEAR_ROCKS &&
-			       (allow_desert || !IsClearGround(tile, CLEAR_DESERT));
+			       (allow_desert || !IsClearGround(tile, CLEAR_DESERT)) && TileHeight(tile) <= _settings_newgame.game_creation.tree_line_height;
 
 		default: return false;
 	}
@@ -95,7 +95,6 @@
 static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, uint growth)
 {
 	assert(treetype != TREE_INVALID);
-	assert(CanPlantTreesOnTile(tile, true));
 
 	TreeGround ground;
 	uint density = 3;
@@ -388,6 +387,11 @@
 					continue;
 				}
 
+				if (TileHeight(tile) >= _settings_game.construction.ingame_tree_line_height) {
+					msg = STR_ERROR_TREE_ABOVE_TREE_LINE;
+					continue;
+				}
+
 				if (IsTileType(tile, MP_CLEAR)) {
 					/* Remove fields or rocks. Note that the ground will get barrened */
 					switch (GetRawClearGround(tile)) {
@@ -640,7 +644,14 @@
 		}
 	}
 	if (GetTreeCounter(tile) < 15) {
-		AddTreeCounter(tile, 1);
+		if (_settings_game.construction.tree_growth_rate > 0) {
+			/* Nature randomness */
+			uint8 grow_slowing_values[3] = { 5, 20, 120 }; // slow, very slow, extremely slow
+			uint16 prob = 0x10000 / grow_slowing_values[_settings_game.construction.tree_growth_rate - 1];
+			if (GB(Random(), 0, 16) < prob) AddTreeCounter(tile, 1);
+		} else {
+			AddTreeCounter(tile, 1);
+		}
 		return;
 	}
 	SetTreeCounter(tile, 0);
diff --git a/src/tree_gui.cpp b/src/tree_gui.cpp
--- a/src/tree_gui.cpp
+++ b/src/tree_gui.cpp
@@ -162,7 +162,7 @@
 	virtual void OnPlaceObject(Point pt, TileIndex tile)
 	{
 		VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_PLANT_TREES);
-		VpSetPlaceSizingLimit(20);
+		VpSetPlaceSizingLimit(_settings_game.construction.tree_placement_drag_limit);
 	}
 
 	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
diff --git a/src/tunnel_map.cpp b/src/tunnel_map.cpp
--- a/src/tunnel_map.cpp
+++ b/src/tunnel_map.cpp
@@ -11,6 +11,7 @@
 
 #include "stdafx.h"
 #include "tunnelbridge_map.h"
+#include "station_map.h"
 
 
 /**
@@ -37,6 +38,30 @@
 	return tile;
 }
 
+/**
+ * Helper function for under_water tunnel finding.
+ * Only one strech of water is allowed to be passed.
+ * @param tile Tile to be validated.
+ 
+ * @return true if first srtech of water is being crossed else false.
+ */
+bool IsWaterCrossingTunnel(TileIndex tile, DiagDirection dir)
+{
+	TileIndexDiff delta = TileOffsByDiagDir(dir);
+	uint height;
+	/* Initialize amount of tiles allowed to be passed backwards to find crossing water tunnel entrance.
+	 * and stops iteration to save time. */
+	int tiles = 5;
+
+	do {
+		tile -= delta;
+		if (!IsValidTile(tile)) return false;
+		height = GetTileZ(tile);
+		tiles--;
+	} while (height > 0 && tiles > 0);
+
+	return height == 0 && IsTunnelTile(tile) && GetTunnelBridgeDirection(tile) == dir;
+}
 
 /**
  * Is there a tunnel in the way in the given direction?
@@ -54,9 +79,22 @@
 		tile -= delta;
 		if (!IsValidTile(tile)) return false;
 		height = GetTileZ(tile);
-	} while (z < height);
+	} while (z < height ||
+			(height == 0 &&
+			GetTileMaxZ(tile) == 0 &&	// Flat tile.
+			(IsTileType(tile, MP_WATER) || IsBuoyTile(tile))));
 
-	return z == height && IsTunnelTile(tile) && GetTunnelBridgeDirection(tile) == dir;
+	if (z == height) {
+		if (IsTunnelTile(tile)) return GetTunnelBridgeDirection(tile) == dir;
+
+		if (height == 0) {
+			DiagDirection direction_slope = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
+			if (direction_slope == dir || direction_slope == ReverseDiagDir(dir)) {
+				return IsWaterCrossingTunnel(tile, ReverseDiagDir(direction_slope));
+			}
+		}
+	}
+	return false;
 }
 
 /**
@@ -70,3 +108,13 @@
 	return IsTunnelInWayDir(tile, z, (TileX(tile) > (MapMaxX() / 2)) ? DIAGDIR_NE : DIAGDIR_SW) ||
 			IsTunnelInWayDir(tile, z, (TileY(tile) > (MapMaxY() / 2)) ? DIAGDIR_NW : DIAGDIR_SE);
 }
+
+bool IsTunnelBelow(TileIndex tile)
+{
+	uint32 z = GetTileZ(tile);
+	while (z > 0) {
+		z -= TILE_HEIGHT;
+		if (IsTunnelInWay(tile, z)) return true;
+	}
+	return false;
+}
diff --git a/src/tunnelbridge.h b/src/tunnelbridge.h
--- a/src/tunnelbridge.h
+++ b/src/tunnelbridge.h
@@ -15,6 +15,12 @@
 #include "map_func.h"
 
 /**
+ * Maximum height of bridge above ground.
+ * Used when building bridges and terrafrming below bridges.
+ */
+static const uint MAX_BRIDGE_HEIGHT = 15; // TODO: fix glitches with bridge pillars so we can has higher bridges.
+
+/**
  * Calculates the length of a tunnel or a bridge (without end tiles)
  * @param begin The begin of the tunnel or bridge.
  * @param end   The end of the tunnel or bridge.
diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -23,6 +23,7 @@
 #include "ship.h"
 #include "roadveh.h"
 #include "water_map.h"
+#include "station_map.h"
 #include "pathfinder/yapf/yapf_cache.h"
 #include "newgrf_sound.h"
 #include "autoslope.h"
@@ -31,6 +32,7 @@
 #include "date_func.h"
 #include "clear_func.h"
 #include "vehicle_func.h"
+#include "vehicle_gui.h"
 #include "sound_func.h"
 #include "tunnelbridge.h"
 #include "cheat_type.h"
@@ -105,6 +107,29 @@
 }
 
 /**
+ * Returns the fastest currently available bridge for given length.
+ */
+BridgeType GetFastestAvailableBridgeType(uint bridge_len)
+{
+	BridgeType fastest_type = 0;
+	uint16 fastest_speed = 0;
+
+	for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
+		CommandCost ret = CheckBridgeAvailability(brd_type, bridge_len, DC_NONE);
+		if (!ret.Failed()) {
+			/* bridge is accepted, compare speeds */
+			const BridgeSpec *b = GetBridgeSpec(brd_type);
+			if (b->speed >= fastest_speed) {
+				fastest_type = brd_type;
+				fastest_speed = b->speed;
+			}
+		}
+	}
+
+	return fastest_type;
+}
+
+/**
  * Determines if the track on a bridge ramp is flat or goes up/down.
  *
  * @param tileh Slope of the tile under the bridge head
@@ -372,6 +397,13 @@
 		for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
 			if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN);
 
+			if (z_start + TILE_HEIGHT > (TileHeight(tile) + MAX_BRIDGE_HEIGHT) * TILE_HEIGHT) {
+				/* z_start seems to be one height level below the bridge level in all cases.
+				 * So add one TILE_HEIGHT. Then compare, if the currently tested tile is to low.
+				 * If yes, we have a problem... */
+				return_cmd_error(STR_ERROR_BRIDGE_TOO_HIGH_FOR_TERRAIN);
+			}
+
 			if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) {
 				/* Disallow crossing bridges for the time being */
 				return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
@@ -493,6 +525,46 @@
 	return cost;
 }
 
+/**
+ * CmdBuildTunnel helper function for crossing water tunnels.
+ *   __ __                                 __ __
+ * //      \~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/     \\
+ * @param end_tile coast tile fom where tunnel starts crossing water.
+ * @param delta tile index difference used to find next connecting tile.
+ * @param direction diagonal direction that crossing will be tested.
+ * @returns true if tunnel is allowed to cross water.
+ */
+bool IsCrossableWater(TileIndex end_tile, TileIndexDiff delta, DiagDirection direction)
+{
+	bool crossed_water = false; 
+	uint end_z; // chunnel patch v18 ...changed to uint because of old source.
+	/* Number of tiles after crossing water until end of tunnel */
+	int end_tiles = 1;
+	Slope end_tileh = GetTileSlope(end_tile, NULL);
+
+	if (end_tileh != InclinedSlope(ReverseDiagDir(direction))) return false;
+
+	for (;;) {
+		end_tile += delta;
+		if (!IsValidTile(end_tile)) break;
+		if (crossed_water) end_tiles++;
+		end_tileh = GetTileSlope(end_tile, &end_z);
+		if (end_z == 0) {
+			if (end_tileh == SLOPE_FLAT) {
+				if (!(IsWaterTile(end_tile) || IsBuoyTile(end_tile))) break;
+			} else {
+				if (end_tiles > 1) {
+					return (end_tiles > 3 && end_tiles < 7);
+				} else if (end_tileh == InclinedSlope(direction)) {
+					crossed_water = true;
+				} else {
+					break;
+				}
+			}
+		}
+	}
+	return false;
+}
 
 /**
  * Build Tunnel.
@@ -558,6 +630,14 @@
 	/* Number of tiles at which the cost increase coefficient per tile is halved */
 	int tiles_bump = 25;
 
+	/* Flag used while building crossing-water tunnel.
+	 * One stretch of water only.
+	 * 0 = Didn't cross water.
+	 * 1 = Not allowed to cross water.
+	 * 2 = Crossing water. 
+	 * 3 = Finished crossing water. */
+	int pass_water = 0;  
+
 	CommandCost cost(EXPENSES_CONSTRUCTION);
 	Slope end_tileh;
 	for (;;) {
@@ -565,7 +645,20 @@
 		if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER);
 		end_tileh = GetTileSlope(end_tile, &end_z);
 
-		if (start_z == end_z) break;
+		if (start_z == end_z) {
+			if (start_z > 0) break;
+			/* Tunnels crossing water only allowed at sea level. z == 0 */
+			if (end_tileh != SLOPE_FLAT) {
+				if (pass_water == 2) pass_water = 3;
+				if (pass_water == 0) {
+					/* 2 tiles between entrance and coast tile. */
+					(tiles > 1 && tiles < 5 && IsCrossableWater(end_tile, delta, direction)) ? pass_water = 2 : pass_water = 1;
+				}
+
+				if (pass_water == 1) break;
+				if (pass_water == 3) pass_water = 1; // Finish at next suitable inclined tile.
+			}
+		}
 
 		if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
 			return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY);
@@ -988,9 +1081,104 @@
 	}
 }
 
+/** Draws a signal on tunnel / bridge entrance tile. */
+static void DrawTunnelBridgeRampSignal(const TileInfo *ti)
+{
+	bool side = (_settings_game.vehicle.road_side != 0) &&_settings_game.construction.signal_side;
+
+	static const Point SignalPositions[2][4] = {
+		{      /* Signals on the left side */
+			{13,  3}, { 2, 13}, { 3,  4}, {13, 14}
+		}, {   /* Signals on the right side */
+			{14, 13}, { 3,  3}, {13,  2}, { 3, 13}
+		}
+	};
+
+	uint position;
+	DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
+	if (IsTunnelBridgeExit(ti->tile)) dir = ReverseDiagDir(dir);
+
+	switch (dir) {
+		default: NOT_REACHED();
+		case DIAGDIR_NE: position = 0; break;
+		case DIAGDIR_SE: position = 2; break;
+		case DIAGDIR_SW: position = 1; break;
+		case DIAGDIR_NW: position = 3; break;
+	}
+
+	uint x = ti->x + SignalPositions[side][position].x;
+	uint y = ti->y + SignalPositions[side][position].y;
+	uint z = ti->z;
+	if (ti->tileh != SLOPE_FLAT && IsBridge(ti->tile)) z += 8; // sloped bridge head
+	SignalVariant variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
+
+	SpriteID sprite;
+	if (variant == SIG_ELECTRIC) {
+		/* Normal electric signals are picked from original sprites. */
+		sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + IsTunnelBridgeWithSignGreen(ti->tile));
+	} else {
+		/* All other signals are picked from add on sprites. */
+		sprite = SPR_SIGNALS_BASE + ((SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1) + IsTunnelBridgeWithSignGreen(ti->tile));
+	}
+
+	AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, TILE_HEIGHT, z, false, 0, 0, BB_Z_SEPARATOR);
+}
+
+ /* Draws a signal on tunnel / bridge entrance tile. */
+static void DrawBrigeSignalOnMiddelPart(const TileInfo *ti, TileIndex bridge_start_tile, uint z)
+{
+
+	uint bridge_signal_position = 0;
+	int m2_position = 0;
+
+	uint bridge_section = GetTunnelBridgeLength(ti->tile, bridge_start_tile) + 1;
+	
+	while (bridge_signal_position <= bridge_section) {
+		bridge_signal_position += 4; // 4 tiles is block size, max 24 signals, 25 blocks * 4 = 102 on bridge of max length e.g. 100 tiles 
+		if (bridge_signal_position == bridge_section) {
+			bool side = (_settings_game.vehicle.road_side != 0) && _settings_game.construction.signal_side;
+
+			static const Point SignalPositions[2][4] = {
+				{      /* Signals on the left side */
+					{13,  3}, { 2, 13}, { 3,  4}, {13, 14}
+				}, {   /* Signals on the right side */
+					{10, 13}, { 4,  3}, {13,  2}, { 3, 3}
+				}
+			};
+			uint position;
+
+			switch (GetTunnelBridgeDirection(bridge_start_tile)) {
+				default: NOT_REACHED();
+				case DIAGDIR_NE: position = 0; z += 8; break;
+				case DIAGDIR_SE: position = 2; z += 8; break;
+				case DIAGDIR_SW: position = 1; break;
+				case DIAGDIR_NW: position = 3; break;
+			}
+
+
+			uint x = ti->x + SignalPositions[side][position].x;
+			uint y = ti->y + SignalPositions[side][position].y;
+
+			SignalVariant variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
+
+			SpriteID sprite;
+			if (variant == SIG_ELECTRIC) {
+				/* Normal electric signals are picked from original sprites. */
+				sprite = SPR_ORIGINAL_SIGNALS_BASE + ((position << 1) + !HasBit(_m[bridge_start_tile].m2, m2_position));
+			} else {
+				/* All other signals are picked from add on sprites. */
+				sprite = SPR_SIGNALS_BASE + ((SIGTYPE_NORMAL - 1) * 16 + variant * 64 + (position << 1) + !HasBit(_m[bridge_start_tile].m2, m2_position));
+			}
+
+			AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, TILE_HEIGHT, z, false, 0, 0, BB_Z_SEPARATOR);
+		}
+		m2_position++;
+	}
+}
+
 /**
  * Draws a tunnel of bridge tile.
- * For tunnels, this is rather simple, as you only needa draw the entrance.
+ * For tunnels, this is rather simple, as you only need to draw the entrance.
  * Bridges are a bit more complex. base_offset is where the sprite selection comes into play
  * and it works a bit like a bitmask.<p> For bridge heads:
  * @param ti TileInfo of the structure to draw
@@ -1087,6 +1275,9 @@
 		AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x,              ti->y,              BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
 		AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x + BB_data[4], ti->y + BB_data[5], BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
 
+		/*Draw signals for tunnel*/
+		if (IsTunnelBridgeEntrance(ti->tile)) DrawTunnelBridgeRampSignal(ti);
+
 		DrawBridgeMiddle(ti);
 	} else { // IsBridge(ti->tile)
 		const PalSpriteID *psid;
@@ -1181,12 +1372,13 @@
 				DrawCatenary(ti);
 			}
 		}
+		/*Draw signals for bridge*/
+		if (HasWormholeSignals(ti->tile)) DrawTunnelBridgeRampSignal(ti);
 
 		DrawBridgeMiddle(ti);
 	}
 }
 
-
 /**
  * Compute bridge piece. Computes the bridge piece to display depending on the position inside the bridge.
  * bridges pieces sequence (middle parts).
@@ -1320,6 +1512,10 @@
 		if (HasCatenaryDrawn(GetRailType(rampsouth))) {
 			DrawCatenaryOnBridge(ti);
 		}
+
+		if (HasWormholeSignals(rampsouth)) {
+			IsTunnelBridgeExit(rampsouth) ? DrawBrigeSignalOnMiddelPart(ti, rampnorth, z): DrawBrigeSignalOnMiddelPart(ti, rampsouth, z);
+		}
 	}
 
 	/* draw roof, the component of the bridge which is logically between the vehicle and the camera */
@@ -1352,7 +1548,7 @@
 
 			DrawGroundSpriteAt(image, pal, x - ti->x, y - ti->y, z - ti->z);
 		}
-	} else {
+	} else if (_settings_client.gui.bridge_pillars) {
 		/* draw pillars below for high bridges */
 		DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
 	}
@@ -1408,9 +1604,9 @@
 	TransportType tt = GetTunnelBridgeTransportType(tile);
 
 	if (IsTunnel(tile)) {
-		td->str = (tt == TRANSPORT_RAIL) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD;
-	} else { // IsBridge(tile)
-		td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
+		td->str = (tt == TRANSPORT_RAIL) ? HasWormholeSignals(tile) ? STR_LAI_TUNNEL_DESCRIPTION_RAILROAD_SIGNAL : STR_LAI_TUNNEL_DESCRIPTION_RAILROAD : STR_LAI_TUNNEL_DESCRIPTION_ROAD;
+ 	} else { // IsBridge(tile)
+		td->str = (tt == TRANSPORT_WATER) ? STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT : HasWormholeSignals(tile) ? STR_LAI_BRIDGE_DESCRIPTION_RAILROAD_SIGNAL : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
 	}
 	td->owner[0] = GetTileOwner(tile);
 
@@ -1477,6 +1673,26 @@
 	}
 }
 
+static bool ClickTile_TunnelBridge(TileIndex tile)
+{
+	/* Show vehicles found in tunnel */
+	if (IsTunnelTile(tile)) {
+		int count = 0;
+		const Train *t;
+		TileIndex tile_end = GetOtherTunnelBridgeEnd(tile);
+		FOR_ALL_TRAINS(t) {
+			if (!t->IsFrontEngine()) continue;
+			if (tile == t->tile || tile_end == t->tile) {
+				ShowVehicleViewWindow(t);
+				count++;
+			}
+			if (count > 19) break;  // no more than 20 windows open
+		}
+		if (count > 0) return true;
+	}
+	return false;
+}
+
 static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
 {
 	TransportType transport_type = GetTunnelBridgeTransportType(tile);
@@ -1705,7 +1921,7 @@
 	NULL,                            // add_accepted_cargo_proc
 	GetTileDesc_TunnelBridge,        // get_tile_desc_proc
 	GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc
-	NULL,                            // click_tile_proc
+	ClickTile_TunnelBridge,          // click_tile_proc
 	NULL,                            // animate_tile_proc
 	TileLoop_TunnelBridge,           // tile_loop_proc
 	ChangeTileOwner_TunnelBridge,    // change_tile_owner_proc
diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h
--- a/src/tunnelbridge_map.h
+++ b/src/tunnelbridge_map.h
@@ -121,4 +121,96 @@
 	return HasTunnelBridgeReservation(t) ? DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)) : TRACK_BIT_NONE;
 }
 
+/**
+ * Declare tunnel/bridge with signal simulation.
+ * @param t the tunnel/bridge tile.
+ */
+static inline void SetBitTunnelBridgeSignal(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	SetBit(_m[t].m5, 5);
+}
+
+/**
+ * Remove tunnel/bridge with signal simulation.
+ * @param t the tunnel/bridge tile.
+ */
+static inline void ClrBitTunnelBridgeSignal(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	ClrBit(_m[t].m5, 5);
+}
+
+/**
+ * Declare tunnel/bridge exit.
+ * @param t the tunnel/bridge tile.
+ */
+static inline void SetBitTunnelBridgeExit(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	SetBit(_m[t].m5, 6);
+}
+
+/**
+ * Remove tunnel/bridge exit declaration.
+ * @param t the tunnel/bridge tile.
+ */
+static inline void ClrBitTunnelBridgeExit(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	ClrBit(_m[t].m5, 6);
+}
+
+/**
+ * Is this a tunnel/bridge pair with signal simulation?
+ * On tunnel/bridge pair minimal one of the two bits is set.
+ * @param t the tile that might be a tunnel/bridge.
+ * @return true if and only if this tile is a tunnel/bridge with signal simulation.
+ */
+static inline bool HasWormholeSignals(TileIndex t)
+{
+	return IsTileType(t, MP_TUNNELBRIDGE) && (HasBit(_m[t].m5, 5) || HasBit(_m[t].m5, 6)) ;
+}
+
+/**
+ * Is this a tunnel/bridge with sign on green?
+ * @param t the tile that might be a tunnel/bridge with sign set green.
+ * @pre IsTileType(t, MP_TUNNELBRIDGE)
+ * @return true if and only if this tile is a tunnel/bridge entrance.
+ */
+static inline bool IsTunnelBridgeWithSignGreen(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	return HasBit(_m[t].m5, 5) && !HasBit(_m[t].m5, 6);
+}
+
+static inline bool IsTunnelBridgeWithSignRed(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	return HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6);
+}
+
+/**
+ * Is this a tunnel/bridge entrance tile with signal?
+ * Tunnel bridge signal simulation has allways bit 5 on at entrance.
+ * @param t the tile that might be a tunnel/bridge.
+ * @return true if and only if this tile is a tunnel/bridge entrance.
+ */
+static inline bool IsTunnelBridgeEntrance(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	return HasBit(_m[t].m5, 5) ;
+}
+
+/**
+ * Is this a tunnel/bridge exit?
+ * @param t the tile that might be a tunnel/bridge.
+ * @return true if and only if this tile is a tunnel/bridge exit.
+ */
+static inline bool IsTunnelBridgeExit(TileIndex t)
+{
+	assert(IsTileType(t, MP_TUNNELBRIDGE));
+	return !HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6);
+}
+
 #endif /* TUNNELBRIDGE_MAP_H */
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -170,7 +170,7 @@
  */
 bool Vehicle::NeedsAutomaticServicing() const
 {
-	if (this->HasDepotOrder()) return false;
+	if (_settings_game.order.gotodepot && this->HasDepotOrder()) return false;
 	if (this->current_order.IsType(OT_LOADING)) return false;
 	if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
 	return NeedsServicing();
@@ -191,6 +191,9 @@
 		MarkSingleVehicleDirty(v);
 	}
 
+	if (_settings_game.order.timetable_separation) this->ClearSeparation();
+	if (_settings_game.order.timetable_separation) ClrBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
+
 	/* Dirty some windows */
 	InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0);
 	SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
@@ -200,6 +203,13 @@
 	return pass;
 }
 
+bool Vehicle::IsDrawn() const
+{
+	return !(this->vehstatus & VS_HIDDEN) ||
+			(!IsTransparencySet(TO_TUNNELS) && !(_game_mode == GM_MENU) &&
+				((this->type == VEH_TRAIN && Train::From(this)->track == TRACK_BIT_WORMHOLE) ||
+				(this->type == VEH_ROAD && RoadVehicle::From(this)->state == RVSB_WORMHOLE)));
+}
 
 /**
  * Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking.
@@ -716,10 +726,11 @@
 	if (CleaningPool()) return;
 
 	if (Station::IsValidID(this->last_station_visited)) {
-		Station::Get(this->last_station_visited)->loading_vehicles.remove(this);
+		Station *st = Station::Get(this->last_station_visited);
+		st->loading_vehicles.remove(this);
 
 		HideFillingPercent(&this->fill_percent_te_id);
-
+		this->CancelReservation(INVALID_STATION, st);
 		delete this->cargo_payment;
 	}
 
@@ -786,7 +797,7 @@
 
 	/* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
 	 * it may happen that vehicle chain is deleted when visible */
-	if (!(this->vehstatus & VS_HIDDEN)) MarkSingleVehicleDirty(this);
+	if (this->IsDrawn()) MarkSingleVehicleDirty(this);
 
 	Vehicle *v = this->Next();
 	this->SetNext(NULL);
@@ -868,6 +879,16 @@
 			default: break;
 
 			case VEH_TRAIN:
+				if (HasBit(Train::From(v)->flags, VRF_TO_HEAVY)) {
+					_current_company = v->owner;
+					if (IsLocalCompany()) {
+						SetDParam(0, v->index);
+						SetDParam(1, STR_ERROR_TRAIN_TOO_HEAVY);
+						AddVehicleNewsItem(STR_ERROR_TRAIN_TOO_HEAVY, NS_ADVICE, v->index);
+						ClrBit(Train::From(v)->flags,VRF_TO_HEAVY);
+					}
+					_current_company = OWNER_NONE;
+				}
 			case VEH_ROAD:
 			case VEH_AIRCRAFT:
 			case VEH_SHIP:
@@ -1003,7 +1024,7 @@
 			const Vehicle *v = _vehicle_position_hash[x + y]; // already masked & 0xFFF
 
 			while (v != NULL) {
-				if (!(v->vehstatus & VS_HIDDEN) &&
+				if (v->IsDrawn() &&
 						l <= v->coord.right &&
 						t <= v->coord.bottom &&
 						r >= v->coord.left &&
@@ -1038,7 +1059,7 @@
 	y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
 
 	FOR_ALL_VEHICLES(v) {
-		if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 &&
+		if (v->IsDrawn() && !(v->vehstatus & VS_UNCLICKABLE) &&
 				x >= v->coord.left && x <= v->coord.right &&
 				y >= v->coord.top && y <= v->coord.bottom) {
 
@@ -1067,50 +1088,153 @@
 	SetWindowDirty(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,
+/**
+ * The chances for the different types of vehicles to suffer from different types of breakdowns.
+ * The chance for a given breakdown type n is _breakdown_chances[vehtype][n] - _breakdown_chances[vehtype][n-1]
+ */
+static const byte _breakdown_chances[4][4] = {
+	{ //Trains:
+		25,  ///< 10% chance for BREAKDOWN_CRITICAL.
+		51,  ///< 10% chance for BREAKDOWN_EM_STOP.
+		127, ///< 30% chance for BREAKDOWN_LOW_SPEED.
+		255, ///< 50% chance for BREAKDOWN_LOW_POWER.
+	},
+	{ //Road Vehicles:
+		51,  ///< 20% chance for BREAKDOWN_CRITICAL.
+		76,  ///< 10% chance for BREAKDOWN_EM_STOP.
+		153, ///< 30% chance for BREAKDOWN_LOW_SPEED.
+		255, ///< 40% chance for BREAKDOWN_LOW_POWER.
+	},
+	{ //Ships:
+		51,  ///< 20% chance for BREAKDOWN_CRITICAL.
+		76,  ///< 10% chance for BREAKDOWN_EM_STOP.
+		178, ///< 40% chance for BREAKDOWN_LOW_SPEED.
+		255, ///< 30% chance for BREAKDOWN_LOW_POWER.
+	},
+	{ //Aircraft:
+		178, ///< 70% chance for BREAKDOWN_AIRCRAFT_SPEED.
+		229, ///< 20% chance for BREAKDOWN_AIRCRAFT_DEPOT.
+		255, ///< 10% chance for BREAKDOWN_AIRCRAFT_EM_LANDING.
+		255, ///< Aircraft have only 3 breakdown types, so anything above 0% here will cause a crash.
+	},
 };
 
+/**
+ * Determine the type of breakdown a vehicle will have.
+ * Results are saved in breakdown_type and breakdown_severity.
+ * @param v Vehicle in question.
+ * @param r Random number to use. (Note that bits 0..6 are already used.)
+ */
+void
+DetermineBreakdownType( Vehicle *v, uint32 r ) {
+	/* If 'improved breakdowns' is off, just do the classic breakdown. */
+	if ( !_settings_game.vehicle.improved_breakdowns) {
+		v->breakdown_type = BREAKDOWN_CRITICAL;
+		v->breakdown_severity = 40; // Only used by aircraft (321 km/h).
+		return;
+	}
+
+	byte rand = GB(r, 8, 8);
+	const byte *breakdown_type_chance = _breakdown_chances[v->type];
+
+	if (v->type == VEH_AIRCRAFT) {
+		if (rand <= breakdown_type_chance[BREAKDOWN_AIRCRAFT_SPEED]) {
+			v->breakdown_type = BREAKDOWN_AIRCRAFT_SPEED;
+			/* All speed values here are 1/8th of the real max speed in km/h. */
+			byte max_speed = min(AircraftVehInfo(v->engine_type)->max_speed >> 3, 255);
+			byte min_speed = min(15 + (max_speed >> 2), AircraftVehInfo( v->engine_type)->max_speed >> 4);
+			v->breakdown_severity = min_speed + (((v->reliability + GB(r, 16, 16)) * (max_speed - min_speed)) >> 17);
+		} else if (rand <= breakdown_type_chance[BREAKDOWN_AIRCRAFT_DEPOT]) {
+			v->breakdown_type = BREAKDOWN_AIRCRAFT_DEPOT;
+		} else if (rand <= breakdown_type_chance[BREAKDOWN_AIRCRAFT_EM_LANDING]) {
+			/* Emergency landings only happen when reliability < 87%. */
+			if (v->reliability < 0xDDDD) {
+				v->breakdown_type = BREAKDOWN_AIRCRAFT_EM_LANDING;
+			} else {
+				/* Try again. */
+				DetermineBreakdownType(v, Random());
+			}
+		} else {
+			NOT_REACHED();
+		}
+		return;
+	}
+
+	if (rand <= breakdown_type_chance[BREAKDOWN_CRITICAL]) {
+		v->breakdown_type = BREAKDOWN_CRITICAL;
+	} else if (rand <= breakdown_type_chance[BREAKDOWN_EM_STOP]) {
+		/* Non-front engines cannot have emergency stops. */
+		if (v->type == VEH_TRAIN && !(Train::From(v)->IsFrontEngine())) {
+			return DetermineBreakdownType(v, Random());
+		}
+		v->breakdown_type = BREAKDOWN_EM_STOP;
+		v->breakdown_delay >>= 2; // Emergency stops don't last long (1/4 of normal).
+	} else if (rand <= breakdown_type_chance[BREAKDOWN_LOW_SPEED]) {
+		v->breakdown_type = BREAKDOWN_LOW_SPEED;
+		/* Average of random and reliability. */
+		uint16 rand2 = (GB(r, 16, 16) + v->reliability) >> 1;
+		uint16 max_speed =
+				(v->type == VEH_TRAIN) ? GetVehicleProperty(v, PROP_TRAIN_SPEED, RailVehInfo(v->engine_type)->max_speed) :
+				(v->type == VEH_ROAD) ? GetVehicleProperty(v, PROP_ROADVEH_SPEED, RoadVehInfo(v->engine_type)->max_speed) :
+				(v->type == VEH_SHIP) ? GetVehicleProperty(v,PROP_SHIP_SPEED, ShipVehInfo(v->engine_type)->max_speed) :
+				GetVehicleProperty(v, PROP_AIRCRAFT_SPEED, AircraftVehInfo(v->engine_type)->max_speed);
+		byte min_speed = min(41, max_speed >> 2);
+		/* We use the min() function here because we want to use the real value of max_speed for the min_speed calculation. */
+		max_speed = min(max_speed, 255);
+		v->breakdown_severity = Clamp((max_speed * rand2) >> 16, min_speed, max_speed);
+	} else if (rand <= breakdown_type_chance[BREAKDOWN_LOW_POWER]) {
+		v->breakdown_type = BREAKDOWN_LOW_POWER;
+		/** Within this type there are two possibilities: (50/50).
+		 * Power reduction (10-90%), or no power at all. */
+		if (GB(r, 7, 1)) {
+			v->breakdown_severity = Clamp((GB(r, 16, 16) + v->reliability) >> 9, 26, 231);
+		} else {
+			v->breakdown_severity = 0;
+		}
+	} else {
+		NOT_REACHED();
+	}
+}
+
 void CheckVehicleBreakdown(Vehicle *v)
 {
 	int rel, rel_old;
 
 	/* decrease reliability */
 	v->reliability = rel = max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
-	if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
-
-	if (v->breakdown_ctr != 0 || (v->vehstatus & VS_STOPPED) ||
+	if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->First()->index);
+
+	if (v->breakdown_ctr != 0 || (v->First()->vehstatus & VS_STOPPED) ||
 			_settings_game.difficulty.vehicle_breakdowns < 1 ||
-			v->cur_speed < 5 || _game_mode == GM_MENU) {
+			v->First()->cur_speed < 5 || _game_mode == GM_MENU ||
+			(v->type == VEH_AIRCRAFT && ((Aircraft*)v)->state != FLYING) ||
+			(v->type == VEH_TRAIN && !(Train::From(v)->IsFrontEngine()) && !_settings_game.vehicle.improved_breakdowns)) {
 		return;
 	}
 
-	uint32 r = Random();
-
-	/* increase chance of failure */
-	int 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;
-
-	/* reduced breakdowns? */
-	if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
-
-	/* check if to break down */
-	if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
-		v->breakdown_ctr    = GB(r, 16, 6) + 0x3F;
-		v->breakdown_delay  = GB(r, 24, 7) + 0x80;
-		v->breakdown_chance = 0;
+	uint32 r1 = Random();
+	uint32 r2 = Random();
+
+	byte chance = 128;
+	if (_settings_game.vehicle.improved_breakdowns) {
+		/* Dual engines have their breakdown chances reduced to 70% of the normal value */
+		chance = (v->type == VEH_TRAIN && Train::From(v)->IsMultiheaded()) ? v->First()->breakdown_chance * 7 / 10 : v->First()->breakdown_chance;
+	} else if (v->type == VEH_SHIP) {
+		chance = 64;
+	}
+
+	/**
+	 * Chance is (1 - reliability) * breakdown_setting * breakdown_chance / 10.
+	 * At 90% reliabilty, normal setting (2) and average breakdown_chance (128),
+	 * a vehicle will break down (on average) every 100 days.
+	 * This *should* mean that vehicles break down about as often as (or a little less than) they used to.
+	 * However, because breakdowns are no longer by definition a complete stop,
+	 * their impact will be significantly less.
+	 */
+	if ((uint32) (0xffff - v->reliability) * _settings_game.difficulty.vehicle_breakdowns * chance > GB(r1, 0, 24) * 10) {
+		v->breakdown_ctr = GB(r1, 24, 6) + 0xF;
+		v->breakdown_delay = GB(r2, 0, 7) + 0x80;
+		DetermineBreakdownType(v, r2);
 	}
 }
 
@@ -1169,11 +1293,17 @@
 			if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) {
 				if (--this->breakdown_delay == 0) {
 					this->breakdown_ctr = 0;
-					this->MarkDirty();
-					SetWindowDirty(WC_VEHICLE_VIEW, this->index);
+					if(this->type == VEH_TRAIN) {
+						CheckBreakdownFlags(Train::From(this->First()));
+						this->First()->MarkDirty();
+						SetWindowDirty(WC_VEHICLE_VIEW, this->First()->index);
+					} else {
+						this->MarkDirty();
+						SetWindowDirty(WC_VEHICLE_VIEW, this->index);
+					}
 				}
 			}
-			return true;
+			return (this->breakdown_type == BREAKDOWN_CRITICAL || this->breakdown_type == BREAKDOWN_EM_STOP);
 
 		default:
 			if (!this->current_order.IsType(OT_LOADING)) this->breakdown_ctr--;
@@ -1244,7 +1374,7 @@
 
 	/* Count up max and used */
 	for (; v != NULL; v = v->Next()) {
-		count += v->cargo.Count();
+		count += v->cargo.OnboardCount();
 		max += v->cargo_cap;
 		if (v->cargo_cap != 0 && colour != NULL) {
 			unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
@@ -1375,6 +1505,8 @@
 		}
 		if (t.GetDepotActionType() & ODATFB_HALT) {
 			/* Vehicles are always stopped on entering depots. Do not restart this one. */
+			if (_settings_game.order.timetable_separation) v->ClearSeparation();
+			if (_settings_game.order.timetable_separation) ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
 			_vehicles_to_autoreplace[v] = false;
 			if (v->owner == _local_company) {
 				SetDParam(0, v->index);
@@ -1930,9 +2062,26 @@
 		this->current_order.MakeLoading(false);
 	}
 
-	Station::Get(this->last_station_visited)->loading_vehicles.push_back(this);
-
-	PrepareUnload(this);
+	Station *curr_station = Station::Get(this->last_station_visited);
+	curr_station->loading_vehicles.push_back(this);
+
+	StationID next_station_id = INVALID_STATION;
+	OrderList *orders = this->orders.list;
+	if (orders != NULL) {
+		next_station_id = orders->GetNextStoppingStation(this->cur_implicit_order_index, this->last_station_visited);
+	}
+
+	if (this->last_loading_station != INVALID_STATION && this->last_loading_station != this->last_station_visited) {
+		IncreaseStats(Station::Get(this->last_loading_station), this, this->last_station_visited, false);
+	}
+
+	if (this->CanLeaveWithCargo() && next_station_id != INVALID_STATION) {
+		assert(next_station_id != this->last_station_visited);
+		/* freeze stats for the next link */
+		IncreaseStats(curr_station, this, next_station_id, true);
+	}
+
+	PrepareUnload(curr_station, this, next_station_id);
 
 	SetWindowDirty(GetWindowClassForVehicleType(this->type), this->owner);
 	SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
@@ -1945,6 +2094,36 @@
 }
 
 /**
+ * Return all reserved cargo packets to the station.
+ * @param st the station where the reserved packets should go.
+ */
+void Vehicle::CancelReservation(StationID next, Station *st)
+{
+	for (Vehicle *v = this; v != NULL; v = v->next) {
+		VehicleCargoList &cargo = v->cargo;
+		if (cargo.ReservedCount() > 0) {
+			DEBUG(misc, 1, "cancelling cargo reservation");
+			GoodsEntry &ge = st->goods[v->cargo_type];
+			cargo.Unreserve(next, &ge.cargo);
+			SetBit(ge.acceptance_pickup, GoodsEntry::GES_PICKUP);
+		}
+	}
+}
+
+/**
+ * A vehicle can leave the current station with cargo if:
+ * 1. it can load cargo here OR
+ * 2a. it could leave the last station with cargo AND
+ * 2b. it doesn't have to unload all cargo here.
+ */
+bool Vehicle::CanLeaveWithCargo()
+{
+	return (this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
+			((this->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == 0 &&
+			this->last_loading_station != INVALID_STATION);
+}
+
+/**
  * Perform all actions when leaving a station.
  * @pre this->current_order.IsType(OT_LOADING)
  */
@@ -1961,6 +2140,29 @@
 	Station *st = Station::Get(this->last_station_visited);
 	st->loading_vehicles.remove(this);
 
+	OrderList *orders = this->orders.list;
+	if (orders != NULL) {
+		StationID next_station_id = orders->GetNextStoppingStation(this->cur_implicit_order_index, this->last_station_visited);
+		this->CancelReservation(next_station_id, st);
+		if (next_station_id != INVALID_STATION && next_station_id != this->last_station_visited) {
+			DecreaseFrozen(st, this, next_station_id);
+		}
+	} else {
+		this->CancelReservation(INVALID_STATION, st);
+		DEBUG(misc, 1, "orders are NULL");
+		RecalcFrozen(st);
+	}
+
+	if (this->CanLeaveWithCargo()) {
+		/* if the vehicle could load here or could stop with cargo loaded set the last loading station */
+		this->last_loading_station = this->last_station_visited;
+	} else {
+		/* if the vehicle couldn't load and had to unload or transfer everything
+		 * set the last loading station to invalid as it will leave empty.
+		 */
+		this->last_loading_station = INVALID_STATION;
+	}
+
 	HideFillingPercent(&this->fill_percent_te_id);
 
 	if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
@@ -1983,8 +2185,16 @@
 		case OT_LOADING: {
 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
 
+			/* Save time just loading took since that is what goes into the timetable */
+			if (_settings_game.order.timetabling && !HasBit(this->vehicle_flags, VF_LOADING_FINISHED))
+				this->current_loading_time = this->current_order_time;
+
+			/* Pay the loading fee for using someone else's station, if appropriate */
+			if (!mode && this->type != VEH_TRAIN) PayStationSharingFee(this, Station::Get(this->last_station_visited));
+
 			/* Not the first call for this tick, or still loading */
-			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
+			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
+					(_settings_game.order.timetabling && this->current_order_time < wait_time)) return;
 
 			this->PlayLeaveStationSound();
 
@@ -2029,8 +2239,10 @@
 			 * Now we change the setting to apply the new one and let the vehicle head for the same depot.
 			 * Note: the if is (true for requesting service == true for ordered to stop in depot)          */
 			if (flags & DC_EXEC) {
-				this->current_order.SetDepotOrderType(ODTF_MANUAL);
+				if (!(this->current_order.GetDepotOrderType() & ODTFB_BREAKDOWN)) this->current_order.SetDepotOrderType(ODTF_MANUAL);
 				this->current_order.SetDepotActionType(halt_in_depot ? ODATF_SERVICE_ONLY : ODATFB_HALT);
+				if (_settings_game.order.timetable_separation) this->ClearSeparation();
+				if (_settings_game.order.timetable_separation) ClrBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
 				SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
 			}
 			return CommandCost();
@@ -2047,8 +2259,13 @@
 				SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
 			}
 
-			this->current_order.MakeDummy();
-			SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
+			/* We don't cancel a breakdown-related goto depot order, we only change whether to halt or not */
+			if (this->current_order.GetDepotOrderType() & ODTFB_BREAKDOWN) {
+				this->current_order.SetDepotActionType(this->current_order.GetDepotActionType() == ODATFB_HALT ? ODATF_SERVICE_ONLY : ODATFB_HALT);
+			} else {
+				this->current_order.MakeDummy();
+				SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
+			}
 		}
 		return CommandCost();
 	}
@@ -2062,6 +2279,9 @@
 	if (flags & DC_EXEC) {
 		if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
 
+		if (_settings_game.order.timetable_separation) this->ClearSeparation();
+		if (_settings_game.order.timetable_separation) ClrBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
+
 		if (this->IsGroundVehicle()) {
 			uint16 &gv_flags = this->GetGroundVehicleFlags();
 			SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
@@ -2308,6 +2528,66 @@
 	}
 }
 
+/** Clears a vehicles separation status, removing it from any chain. */
+void Vehicle::ClearSeparation()
+{
+	if (this->ahead_separation == NULL && this->behind_separation == NULL) return;
+
+	assert(this->ahead_separation != NULL);
+	assert(this->behind_separation != NULL);
+
+	this->ahead_separation->behind_separation = this->behind_separation;
+	this->behind_separation->ahead_separation = this->ahead_separation;
+
+	this->ahead_separation = NULL;
+	this->behind_separation = NULL;
+
+	SetWindowDirty(WC_VEHICLE_TIMETABLE, this->index);
+}
+
+/**
+ * Adds this vehicle to a shared vehicle separation chain.
+ * @param v_other a vehicle of the separation chain.
+ * @pre !this->IsOrderListShared()
+ */
+void Vehicle::InitSeparation()
+{
+	assert(this->ahead_separation == NULL && this->behind_separation == NULL);
+	Vehicle *best_match = this;
+	int lowest_separation;
+	for (Vehicle *v_other = this->FirstShared(); v_other != NULL; v_other = v_other->NextShared()) {
+		if ((HasBit(v_other->vehicle_flags, VF_TIMETABLE_STARTED)) && v_other != this) {
+			if (best_match == this) {
+				best_match = v_other;
+				lowest_separation = 0; // TODO call SeparationBetween() here
+			} else {
+				int temp_sep = 0; // TODO call SeparationBetween() here
+				if (temp_sep < lowest_separation && temp_sep != -1) {
+					best_match = v_other;
+					lowest_separation = temp_sep;
+				}
+			}
+		}
+	}
+	this->AddToSeparationBehind(best_match);
+}
+
+/**
+ * Adds this vehicle behind another in a separation chain.
+ * @param v_other a vehicle of the separation chain.
+ * @pre !this->IsOrderListShared()
+ */
+void Vehicle::AddToSeparationBehind(Vehicle *v_other)
+{
+	if (v_other->ahead_separation == NULL) v_other->ahead_separation = v_other;
+	if (v_other->behind_separation == NULL) v_other->behind_separation = v_other;
+
+	this->ahead_separation = v_other;
+	v_other->behind_separation->ahead_separation = this;
+	this->behind_separation = v_other->behind_separation;
+	v_other->behind_separation = this;
+}
+
 /**
  * Adds this vehicle to a shared vehicle chain.
  * @param shared_chain a vehicle of the chain with shared vehicles.
@@ -2365,6 +2645,9 @@
 
 	this->next_shared     = NULL;
 	this->previous_shared = NULL;
+
+	if (_settings_game.order.timetable_separation) this->ClearSeparation();
+	if (_settings_game.order.timetable_separation) ClrBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
 }
 
 void VehiclesYearlyLoop()
diff --git a/src/vehicle_base.h b/src/vehicle_base.h
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -21,6 +21,7 @@
 #include "order_func.h"
 #include "transport_type.h"
 #include "group_type.h"
+#include "timetable.h"
 
 /** Vehicle status bits in #Vehicle::vehstatus. */
 enum VehStatus {
@@ -43,6 +44,7 @@
 	VF_AUTOFILL_TIMETABLE,      ///< Whether the vehicle should fill in the timetable automatically.
 	VF_AUTOFILL_PRES_WAIT_TIME, ///< Whether non-destructive auto-fill should preserve waiting times
 	VF_STOP_LOADING,            ///< Don't load anymore during the next load cycle.
+	VF_AUTOMATE_TIMETABLE,      ///< Whether the vehicle should manage the timetable automatically.
 	VF_PATHFINDER_LOST,         ///< Vehicle's pathfinder is lost.
 };
 
@@ -129,6 +131,11 @@
 
 	Vehicle *next_shared;               ///< pointer to the next vehicle that shares the order
 	Vehicle *previous_shared;           ///< NOSAVE: pointer to the previous vehicle in the shared order chain
+
+	Vehicle *ahead_separation;  ///< pointer to the vehicle ahead in separation
+	Vehicle *behind_separation; ///< pointer to the vehicle behind in separation
+
+	bool CanLeaveWithCargo();
 public:
 	friend const SaveLoad *GetVehicleDescription(VehicleType vt); ///< So we can use private/protected variables in the saveload code
 	friend void FixOldVehicles();
@@ -154,8 +161,13 @@
 
 	/* Used for timetabling. */
 	uint32 current_order_time;          ///< How many ticks have passed since this order started.
+	uint32 current_loading_time;        ///< How long loading took. Less than current_order_time if vehicle is early.
 	int32 lateness_counter;             ///< How many ticks late (or early if negative) this vehicle is.
+#if WALLCLOCK_NETWORK_COMPATIBLE
 	Date timetable_start;               ///< When the vehicle is supposed to start the timetable.
+#else
+	DateTicks timetable_start;          ///< When the vehicle is supposed to start the timetable.
+#endif
 
 	Rect coord;                         ///< NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves.
 
@@ -166,6 +178,9 @@
 	Vehicle **prev_new_hash;            ///< NOSAVE: Previous vehicle in the tile location hash.
 	Vehicle **old_new_hash;             ///< NOSAVE: Cache of the current hash chain.
 
+	byte breakdown_severity;            ///< Severity of the breakdown. Note that lower means more severe.
+	BreakdownType breakdown_type;       ///< Type of breakdown.
+
 	SpriteID colourmap;                 ///< NOSAVE: cached colour mapping
 
 	/* Related to age and service time */
@@ -211,6 +226,7 @@
 	byte waiting_triggers;              ///< Triggers to be yet matched before rerandomizing the random bits.
 
 	StationID last_station_visited;     ///< The last station we stopped at.
+	StationID last_loading_station;     ///< Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
 
 	CargoID cargo_type;                 ///< type of cargo this vehicle is carrying
 	byte cargo_subtype;                 ///< Used for livery refits (NewGRF variations)
@@ -220,7 +236,7 @@
 
 	byte day_counter;                   ///< Increased by one for each day
 	byte tick_counter;                  ///< Increased by one for each tick
-	byte running_ticks;                 ///< Number of ticks this vehicle was not stopped this day
+	uint16 running_ticks;               ///< Number of ticks this vehicle was not stopped this day
 
 	byte vehstatus;                     ///< Status
 	Order current_order;                ///< The current order (+ status, like: loading)
@@ -248,6 +264,7 @@
 	virtual ~Vehicle();
 
 	void BeginLoading();
+	void CancelReservation(StationID next, Station *st);
 	void LeaveStation();
 
 	GroundVehicleCache *GetGroundVehicleCache();
@@ -261,6 +278,12 @@
 	void HandleLoading(bool mode = false);
 
 	/**
+	 * Is this vehicle drawn?
+	 * @return true if it is drawn
+	 */
+	bool IsDrawn() const;
+
+	/**
 	 * Marks the vehicles to be redrawn and updates cached variables
 	 *
 	 * This method marks the area of the vehicle on the screen as dirty.
@@ -527,6 +550,24 @@
 	 */
 	inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
 
+	/**
+	 * Get the vehicle ahead on track.
+	 * @return the vehicle ahead on track or NULL when there isn't one.
+	 */
+	inline Vehicle *AheadSeparation() const { return this->ahead_separation; }
+
+	/**
+	 * Get the vehicle behind on track.
+	 * @return the vehicle behind on track or NULL when there isn't one.
+	 */
+	inline Vehicle *BehindSeparation() const { return this->behind_separation; }
+
+	void ClearSeparation();
+
+	void InitSeparation();
+
+	void AddToSeparationBehind(Vehicle *v_other);
+
 	void AddToShared(Vehicle *shared_chain);
 	void RemoveFromShared();
 
@@ -585,6 +626,7 @@
 		this->profit_last_year = src->profit_last_year;
 
 		this->current_order_time = src->current_order_time;
+		this->current_loading_time = src->current_loading_time;
 		this->lateness_counter = src->lateness_counter;
 		this->timetable_start = src->timetable_start;
 
@@ -1011,6 +1053,10 @@
 	SpriteID image_override;            ///< Override for the default disaster vehicle sprite.
 	VehicleID big_ufo_destroyer_target; ///< The big UFO that this destroyer is supposed to bomb.
 
+	/* @see in_min/max_height_correction in aircraft.h */
+	bool in_max_height_correction;
+	bool in_min_height_correction;
+
 	/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
 	DisasterVehicle() : SpecializedVehicleBase() {}
 	/** We want to 'destruct' the right class. */
diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp
--- a/src/vehicle_cmd.cpp
+++ b/src/vehicle_cmd.cpp
@@ -84,9 +84,6 @@
  */
 CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
-	/* Elementary check for valid location. */
-	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
-
 	VehicleType type;
 	switch (GetTileType(tile)) {
 		case MP_RAILWAY: type = VEH_TRAIN;    break;
@@ -96,6 +93,9 @@
 		default: NOT_REACHED(); // Safe due to IsDepotTile()
 	}
 
+	/* Elementary check for valid location. */
+	if (!IsDepotTile(tile) || !IsInfraTileUsageAllowed(type, _current_company, tile)) return CMD_ERROR;
+
 	/* Validate the engine type. */
 	EngineID eid = GB(p1, 0, 16);
 	if (!IsEngineBuildable(eid, type, _current_company)) return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + type);
@@ -467,7 +467,7 @@
 	Vehicle *v = Vehicle::GetIfValid(p1);
 	if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
 
-	CommandCost ret = CheckOwnership(v->owner);
+	CommandCost ret = CheckVehicleControlAllowed(v);
 	if (ret.Failed()) return ret;
 
 	if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED);
@@ -520,6 +520,9 @@
 	if (flags & DC_EXEC) {
 		if (v->IsStoppedInDepot() && (flags & DC_AUTOREPLACE) == 0) DeleteVehicleNews(p1, STR_NEWS_TRAIN_IS_WAITING + v->type);
 
+		if (_settings_game.order.timetable_separation) v->ClearSeparation();
+		if (_settings_game.order.timetable_separation) ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
+
 		v->vehstatus ^= VS_STOPPED;
 		if (v->type != VEH_TRAIN) v->cur_speed = 0; // trains can stop 'slowly'
 		v->MarkDirty();
@@ -632,7 +635,7 @@
 	VehicleType vehicle_type = Extract<VehicleType, 0, 3>(p1);
 
 	if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR;
-	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsDepotTile(tile) || !IsInfraUsageAllowed(vehicle_type, _current_company, GetTileOwner(tile))) return CMD_ERROR;
 
 	/* Get the list of vehicles in the depot */
 	BuildDepotVehicleList(vehicle_type, tile, &list, &list, true);
diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -39,6 +39,8 @@
 #include "engine_func.h"
 #include "station_base.h"
 #include "tilehighlight_func.h"
+#include "infrastructure_func.h"
+#include "train.h"
 
 #include "table/strings.h"
 
@@ -277,6 +279,31 @@
 	return ret_refit_cyc;
 }
 
+/**
+ * Get the engine that suffers from the most severe breakdown.
+ * This means the engine with the lowest breakdown_type.
+ * If the breakdown types of 2 engines are equal, the one with the lowest breakdown_severity (most severe) is picked.
+ * @param v  Front engine of the train.
+ * @return w The most severly broken engine.
+ */
+const Vehicle *GetMostSeverelyBrokenEngine(const Train *v)
+{
+	assert(v->IsFrontEngine());
+	const Vehicle *w = v;
+	byte most_severe_type = 255;
+	for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+		if (u->breakdown_ctr == 1) {
+			if (u->breakdown_type < most_severe_type) {
+				most_severe_type = u->breakdown_type;
+				w = u;
+			} else if (u->breakdown_type == most_severe_type && u->breakdown_severity < w->breakdown_severity) {
+				w = u;
+			}
+		}
+	}
+	return w;
+}
+
 /** Option to refit a vehicle chain */
 struct RefitOption {
 	CargoID cargo;    ///< Cargo to refit to
@@ -351,6 +378,9 @@
 /** Widget numbers of the vehicle refit window. */
 enum VehicleRefitWidgets {
 	VRW_CAPTION,
+	VRW_SHOW_VEHICLEHEADER,
+	VRW_VEHICLEHEADER,
+	VRW_VEHICLE_SELECT_ALL,
 	VRW_VEHICLE_PANEL_DISPLAY,
 	VRW_SHOW_HSCROLLBAR,
 	VRW_HSCROLLBAR,
@@ -506,6 +536,7 @@
 		nwi->tool_tip    = STR_REFIT_TRAIN_REFIT_TOOLTIP + v->type;
 		this->GetWidget<NWidgetStacked>(VRW_SHOW_HSCROLLBAR)->SetDisplayedPlane(v->IsGroundVehicle() ? 0 : SZSP_HORIZONTAL);
 		this->GetWidget<NWidgetCore>(VRW_VEHICLE_PANEL_DISPLAY)->tool_tip = (v->type == VEH_TRAIN) ? STR_REFIT_SELECT_VEHICLES_TOOLTIP : STR_NULL;
+		this->GetWidget<NWidgetStacked>(VRW_SHOW_VEHICLEHEADER)->SetDisplayedPlane(v->type == VEH_TRAIN ? 0 : SZSP_HORIZONTAL);
 
 		this->FinishInitNested(desc, v->index);
 		this->owner = v->owner;
@@ -811,6 +842,15 @@
 	virtual void OnClick(Point pt, int widget, int click_count)
 	{
 		switch (widget) {
+			case VRW_VEHICLE_SELECT_ALL: {
+				/* Clear the selection. */
+				Vehicle *v = Vehicle::Get(this->window_number);
+				this->selected_vehicle = v->index;
+				this->num_vehicles = UINT8_MAX;
+				this->SetWidgetDirty(VRW_VEHICLE_PANEL_DISPLAY);
+				break;
+			}
+
 			case VRW_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
 				if (this->order != INVALID_VEH_ORDER_ID) break;
 				NWidgetBase *nwi = this->GetWidget<NWidgetBase>(VRW_VEHICLE_PANEL_DISPLAY);
@@ -891,6 +931,12 @@
 		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
 		NWidget(WWT_CAPTION, COLOUR_GREY, VRW_CAPTION), SetDataTip(STR_REFIT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 	EndContainer(),
+	NWidget(NWID_SELECTION, INVALID_COLOUR, VRW_SHOW_VEHICLEHEADER),
+		NWidget(NWID_HORIZONTAL),
+			NWidget(WWT_TEXTBTN, COLOUR_GREY, VRW_VEHICLEHEADER), SetDataTip(STR_REFIT_VEHICLE_SELECTION_TITLE, STR_NULL), SetFill(1, 0), SetResize(1, 0),
+			NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, VRW_VEHICLE_SELECT_ALL), SetDataTip(STR_REFIT_VEHICLE_SELECT_ALL, STR_REFIT_VEHICLE_SELECT_ALL_TOOLTIP),
+		EndContainer(),
+	EndContainer(),
 	/* Vehicle display + scrollbar. */
 	NWidget(NWID_VERTICAL),
 		NWidget(WWT_PANEL, COLOUR_GREY, VRW_VEHICLE_PANEL_DISPLAY), SetMinimalSize(228, 14), SetResize(1, 0), SetScrollbar(VRW_HSCROLLBAR), EndContainer(),
@@ -1246,7 +1292,7 @@
 	} while (oid != start);
 }
 
-/**
+ /**
  * Draws an image of a vehicle chain
  * @param v         Front vehicle
  * @param left      The minimum horizontal position
@@ -2000,8 +2046,25 @@
 				y += FONT_HEIGHT_NORMAL;
 
 				/* Draw breakdown & reliability */
-				SetDParam(0, ToPercent16(v->reliability));
-				SetDParam(1, v->breakdowns_since_last_service);
+				byte total_engines = 0;
+				if (v->type == VEH_TRAIN) {
+					/* We want to draw the average reliability and total number of breakdowns. */
+					uint32 total_reliability = 0;
+					uint16 total_breakdowns  = 0;
+					for (const Vehicle *w = v; w != NULL; w = w->Next()) {
+						if (Train::From(w)->IsEngine() || Train::From(w)->IsMultiheaded()) {
+							total_reliability += w->reliability;
+							total_breakdowns += w->breakdowns_since_last_service;
+						}
+					}
+					total_engines = Train::From(v)->tcache.cached_num_engines;
+					assert(total_engines > 0);
+					SetDParam(0, ToPercent16(total_reliability / total_engines));
+					SetDParam(1, total_breakdowns);
+				} else {
+					SetDParam(0, ToPercent16(v->reliability));
+					SetDParam(1, v->breakdowns_since_last_service);
+				}
 				DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS);
 				break;
 			}
@@ -2288,6 +2351,13 @@
 	DoCommandP(v->tile, v->index, 0, _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type], texteffect ? CcStartStopVehicle : NULL);
 }
 
+/** Strings for aircraft breakdown types. */
+static const StringID _aircraft_breakdown_strings[] = {
+	STR_BREAKDOWN_TYPE_LOW_SPEED,
+	STR_BREAKDOWN_TYPE_DEPOT,
+	STR_BREAKDOWN_TYPE_LANDING,
+};
+
 /** Checks whether the vehicle may be refitted at the moment.*/
 static bool IsVehicleRefitable(const Vehicle *v)
 {
@@ -2419,6 +2489,7 @@
 	{
 		const Vehicle *v = Vehicle::Get(this->window_number);
 		bool is_localcompany = v->owner == _local_company;
+		bool can_control = IsVehicleControlAllowed(v, _local_company);
 		bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
 
 		this->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localcompany);
@@ -2427,8 +2498,8 @@
 
 		if (v->type == VEH_TRAIN) {
 			this->SetWidgetLoweredState(VVW_WIDGET_FORCE_PROCEED, Train::From(v)->force_proceed == TFP_SIGNAL);
-			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localcompany);
-			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localcompany);
+			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !can_control);
+			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !can_control);
 		}
 
 		this->DrawWidgets();
@@ -2450,8 +2521,31 @@
 		StringID str;
 		if (v->vehstatus & VS_CRASHED) {
 			str = STR_VEHICLE_STATUS_CRASHED;
-		} else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
-			str = STR_VEHICLE_STATUS_BROKEN_DOWN;
+		} else if (v->breakdown_ctr == 1 || (v->type == VEH_TRAIN && Train::From(v)->flags & VRF_IS_BROKEN)) {
+			if (_settings_game.vehicle.improved_breakdowns) {
+				str = STR_VEHICLE_STATUS_BROKEN_DOWN_VEL;
+				SetDParam(2, v->GetDisplaySpeed());
+			} else {
+				str = STR_VEHICLE_STATUS_BROKEN_DOWN;
+			}
+
+			if (v->type == VEH_AIRCRAFT) {
+				SetDParam(0, _aircraft_breakdown_strings[v->breakdown_type]);
+				if (v->breakdown_type == BREAKDOWN_AIRCRAFT_SPEED) {
+					SetDParam(1, v->breakdown_severity << 3);
+				} else {
+					SetDParam(1, v->current_order.GetDestination());
+				}
+			} else {
+				const Vehicle *w = (v->type == VEH_TRAIN) ? GetMostSeverelyBrokenEngine(Train::From(v)) : v;
+				SetDParam(0, STR_BREAKDOWN_TYPE_CRITICAL + w->breakdown_type);
+
+				if (w->breakdown_type == BREAKDOWN_LOW_SPEED) {
+					SetDParam(1, min( w->First()->GetDisplayMaxSpeed(), w->breakdown_severity >> (v->type == VEH_TRAIN ? 0 : 1 )));
+				} else if (w->breakdown_type == BREAKDOWN_LOW_POWER) {
+					SetDParam(1, w->breakdown_severity * 100 / 256);
+				}
+			}
 		} else if (v->vehstatus & VS_STOPPED) {
 			if (v->type == VEH_TRAIN) {
 				if (v->cur_speed == 0) {
@@ -2462,7 +2556,7 @@
 					}
 				} else {
 					SetDParam(0, v->GetDisplaySpeed());
-					str = STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL;
+					str = STR_VEHICLE_STATUS_TRAIN_STOPPING + _settings_client.gui.vehicle_speed;
 				}
 			} else { // no train
 				str = STR_VEHICLE_STATUS_STOPPED;
@@ -2474,7 +2568,7 @@
 				case OT_GOTO_STATION: {
 					SetDParam(0, v->current_order.GetDestination());
 					SetDParam(1, v->GetDisplaySpeed());
-					str = STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL;
+					str = STR_VEHICLE_STATUS_HEADING_FOR_STATION + _settings_client.gui.vehicle_speed;
 					break;
 				}
 
@@ -2491,9 +2585,9 @@
 						 * evaluating the string in the status bar. */
 						str = STR_EMPTY;
 					} else if (v->current_order.GetDepotActionType() & ODATFB_HALT) {
-						str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL;
+						str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT + _settings_client.gui.vehicle_speed;
 					} else {
-						str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL;
+						str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE + _settings_client.gui.vehicle_speed;
 					}
 					break;
 				}
@@ -2505,7 +2599,7 @@
 				case OT_GOTO_WAYPOINT: {
 					assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
 					SetDParam(0, v->current_order.GetDestination());
-					str = STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL;
+					str = STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT + _settings_client.gui.vehicle_speed;
 					SetDParam(1, v->GetDisplaySpeed());
 					break;
 				}
@@ -2519,7 +2613,7 @@
 
 				default:
 					if (v->GetNumManualOrders() == 0) {
-						str = STR_VEHICLE_STATUS_NO_ORDERS_VEL;
+						str = STR_VEHICLE_STATUS_NO_ORDERS + _settings_client.gui.vehicle_speed;
 						SetDParam(0, v->GetDisplaySpeed());
 					} else {
 						str = STR_EMPTY;
diff --git a/src/vehicle_type.h b/src/vehicle_type.h
--- a/src/vehicle_type.h
+++ b/src/vehicle_type.h
@@ -72,7 +72,19 @@
 	DEPOT_COMMAND_MASK  = 0xFU << 28,
 };
 
-static const uint MAX_LENGTH_VEHICLE_NAME_CHARS = 32; ///< The maximum length of a vehicle name in characters including '\0'
+static const uint MAX_LENGTH_VEHICLE_NAME_CHARS  =  32; ///< The maximum length of a vehicle name in characters including '\0'
+
+/* The different types of breakdowns. */
+enum BreakdownType {
+	BREAKDOWN_CRITICAL  = 0,                             ///< Old style breakdown (black smoke).
+	BREAKDOWN_EM_STOP   = 1,                             ///< Emergency stop.
+	BREAKDOWN_LOW_SPEED = 2,                             ///< Lower max speed.
+	BREAKDOWN_LOW_POWER = 3,                             ///< Power reduction.
+	/* Aircraft have totally different breakdowns, so we use aliases to make things clearer. */
+	BREAKDOWN_AIRCRAFT_SPEED      = BREAKDOWN_CRITICAL,  ///< Lower speed until the next airport.
+	BREAKDOWN_AIRCRAFT_DEPOT      = BREAKDOWN_EM_STOP,   ///< We have to visit a depot at the next airport.
+	BREAKDOWN_AIRCRAFT_EM_LANDING = BREAKDOWN_LOW_SPEED, ///< Emergency landing at the closest airport (with hangar!) we can find.
+};
 
 /** The length of a vehicle in tile units. */
 static const uint VEHICLE_LENGTH = 8;
diff --git a/src/viewport.cpp b/src/viewport.cpp
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -41,13 +41,20 @@
 #include "zoom_func.h"
 #include "vehicle_func.h"
 #include "company_func.h"
+#include "core/alloc_func.hpp"
+#include "core/alloc_type.hpp"
+#include "core/smallvec_type.hpp"
 #include "waypoint_func.h"
 #include "window_func.h"
 #include "tilehighlight_func.h"
 #include "window_gui.h"
+#include "slope_func.h"
+#include "copy_paste.h"
 
 #include "table/strings.h"
 
+#include <map>
+
 Point _tile_fract_coords;
 
 struct StringSpriteToDraw {
@@ -92,8 +99,8 @@
 	int32 xmax;                     ///< maximal world X coordinate of bounding box
 	int32 ymin;                     ///< minimal world Y coordinate of bounding box
 	int32 ymax;                     ///< maximal world Y coordinate of bounding box
-	int zmin;                       ///< minimal world Z coordinate of bounding box
-	int zmax;                       ///< maximal world Z coordinate of bounding box
+	int zmin;                     ///< minimal world Z coordinate of bounding box
+	int zmax;                     ///< maximal world Z coordinate of bounding box
 
 	int first_child;                ///< the first child to draw.
 	bool comparison_done;           ///< Used during sprite sorting: true if sprite has been compared with all other sprites
@@ -385,9 +392,9 @@
 
 	/* we need to move variables in to the valid range, as the
 	 * GetTileZoomCenterWindow() function can call here with invalid x and/or y,
-	 * when the user tries to zoom out along the sides of the map */
-	a = Clamp(a, -4 * (int)TILE_SIZE, (int)(MapMaxX() * TILE_SIZE) - 1);
-	b = Clamp(b, -4 * (int)TILE_SIZE, (int)(MapMaxY() * TILE_SIZE) - 1);
+	 * when the user tries to zoom out along the sides of the map. */
+	a = Clamp(a, ((uint)GetMaxTileHeight() + 1) / 4 * -(int)TILE_SIZE, (int)(MapMaxX() * TILE_SIZE) - 1);
+	b = Clamp(b, ((uint)GetMaxTileHeight() + 1) / 4 * -(int)TILE_SIZE, (int)(MapMaxY() * TILE_SIZE) - 1);
 
 	/* (a, b) is the X/Y-world coordinate that belongs to (x,y) if the landscape would be completely flat on height 0.
 	 * Now find the Z-world coordinate by fix point iteration.
@@ -478,7 +485,7 @@
  * @param extra_offs_x Pixel X offset for the sprite position.
  * @param extra_offs_y Pixel Y offset for the sprite position.
  */
-static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32 x, int32 y, int z, const SubSprite *sub = NULL, int extra_offs_x = 0, int extra_offs_y = 0)
+static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32 x, int32 y, int32 z, const SubSprite *sub = NULL, int extra_offs_x = 0, int extra_offs_y = 0)
 {
 	assert((image & SPRITE_MASK) < MAX_SPRITES);
 
@@ -891,6 +898,12 @@
 	DrawSelectionSprite(sel, pal, ti, 7, FOUNDATION_PART_NORMAL);
 }
 
+static void DrawPreviewSprite(SpriteID image, SpriteID pal, uint x, uint y, uint z)
+{
+	//DrawGroundSpriteAt(image, x, y, z + 7);
+	AddSortableSpriteToDraw(image, pal, x, y, 0x10, 0x10, 1, z + 7);
+}
+
 static bool IsPartOfAutoLine(int px, int py)
 {
 	px -= _thd.selstart.x;
@@ -922,6 +935,50 @@
 
 #include "table/autorail.h"
 
+/*
+static uint GetTileHFromCopyBuffer(TileIndex index, uint32 baseh, uint32* h)
+{
+	return GetTileh((uint)_copy_heightmap[index] + baseh, (uint)_copy_heightmap[index+1] + baseh, (uint)_copy_heightmap[index + _copy_width] + baseh, (uint)_copy_heightmap[index + _copy_width + 1] + baseh, h);
+}
+*/
+
+static void DrawPreviewTile(const TileInfo *ti)
+{
+	uint32 image;
+	//We have to get the index within our _copy_paste.m_rail[] structure
+	uint32 tile_x = ti->x / TILE_SIZE;
+	uint32 tile_y = ti->y / TILE_SIZE;
+	uint32 pos_x = _thd.pos.x / TILE_SIZE;
+	uint32 pos_y = _thd.pos.y / TILE_SIZE;
+	uint32 bindex = (tile_x - pos_x) + ((_copy_paste.GetWidth() - 1) * (tile_y - pos_y));
+	//uint32 baseh = TileHeight(TileXY(pos_x, pos_y));
+	//uint32 tindex = (tile_x - pos_x) + ((_copy_width) * (tile_y - pos_y));
+	//uint32 minh;
+	//uint32 tileh = GetTileHFromCopyBuffer(tindex, baseh, &minh);
+	
+	if (((tile_x - pos_x) == 0) || ((tile_x - pos_x) == (_copy_paste.GetWidth() - 2)) || ((tile_y - pos_y) == 0) || ((tile_y - pos_y) == (_copy_paste.GetHeight() - 2))) {
+		//Highlight BorderTiles
+		image = SPR_SELECT_TILE + SlopeToSpriteOffset(ti->tileh);
+		DrawPreviewSprite(image, PAL_NONE, ti->x, ti->y, ti->z);
+	}
+	
+	image = SPR_AUTORAIL_BASE;
+	TrackBits tracktodraw = _copy_paste.GetCPTrackBits(bindex);
+	for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
+		if (tracktodraw & TrackToTrackBits(t)) DrawPreviewSprite(image + _AutorailTilehSprite[SLOPE_FLAT][t], PAL_NONE, ti->x, ti->y, ti->z);
+	}
+	
+	/*
+	if ((_copy_rail[bindex] & (1U << TRACK_X))>0) DrawPreviewSprite(image, ti->x, ti->y, minh);
+	if ((_copy_rail[bindex] & (1U << TRACK_Y))>0) DrawPreviewSprite(image + 8, ti->x, ti->y, minh);
+	if ((_copy_rail[bindex] & (1U << TRACK_UPPER))>0) DrawPreviewSprite(image + 16, ti->x, ti->y, minh);
+	if ((_copy_rail[bindex] & (1U << TRACK_LOWER))>0) DrawPreviewSprite(image + 25, ti->x, ti->y, minh);
+	if ((_copy_rail[bindex] & (1U << TRACK_LEFT))>0) DrawPreviewSprite(image + 34, ti->x, ti->y, minh);
+	if ((_copy_rail[bindex] & (1U << TRACK_RIGHT))>0) DrawPreviewSprite(image + 42, ti->x, ti->y, minh);
+	
+	*/
+}
+
 /**
  * Draws autorail highlights.
  *
@@ -1004,6 +1061,8 @@
 			HighLightStyle type = _thd.drawstyle & HT_DIR_MASK;
 			assert(type < HT_DIR_END);
 			DrawAutorailSelection(ti, _autorail_type[type][0]);
+		} else if (_thd.drawstyle & HT_PREVIEW) {
+			DrawPreviewTile(ti);
 		} else if (IsPartOfAutoLine(ti->x, ti->y)) {
 			/* autorail highlighting long line */
 			HighLightStyle dir = _thd.drawstyle & HT_DIR_MASK;
@@ -1167,8 +1226,7 @@
 	const Town *t;
 	FOR_ALL_TOWNS(t) {
 		ViewportAddString(dpi, ZOOM_LVL_OUT_4X, &t->sign,
-				_settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN,
-				STR_VIEWPORT_TOWN_TINY_WHITE, STR_VIEWPORT_TOWN_TINY_BLACK,
+				t->Label(), t->SmallLabel(), STR_VIEWPORT_TOWN_TINY_BLACK,
 				t->index, t->population);
 	}
 }
@@ -1528,6 +1586,20 @@
 	dpi->top -= this->top;
 }
 
+/**
+ * How far should I allow scrolling outside the map?
+ *
+ * @see ClampViewportToMap()
+ */
+uint16 GetMaxScrollOutsideMap() {
+	/* Allow scrolling to high peaks at the NE/NW border if AllowMoreHeightlevels is true. */
+	if (AllowMoreHeightlevels()) {
+		return MAXSCROLL_NEW;
+	} else {
+		return MAXSCROLL_OLD;
+	}
+}
+
 static inline void ClampViewportToMap(const ViewPort *vp, int &x, int &y)
 {
 	/* Centre of the viewport is hot spot */
@@ -1539,9 +1611,9 @@
 	int vx = -x + y * 2;
 	int vy =  x + y * 2;
 
-	/* clamp to size of map */
-	vx = Clamp(vx, 0, MapMaxX() * TILE_SIZE * 4);
-	vy = Clamp(vy, 0, MapMaxY() * TILE_SIZE * 4);
+	/* Clamp to size of map. */
+	vx = Clamp(vx, - (uint16)GetMaxScrollOutsideMap(), MapMaxX() * TILE_SIZE * 4);
+	vy = Clamp(vy, - (uint16)GetMaxScrollOutsideMap(), MapMaxY() * TILE_SIZE * 4);
 
 	/* Convert map coordinates to viewport coordinates */
 	x = (-vx + vy) / 2;
@@ -1661,6 +1733,20 @@
 	);
 }
 
+void MarkTileDirtyByTileOutsideMap(int x, int y)
+{
+	Point pt = RemapCoords(x * TILE_SIZE, y * TILE_SIZE, GetTileZOutsideMap(x, y));
+	/* Since tiles painted outside the map don't contain buildings, trees, etc.,
+	 * this reduced area for repainting should suffice. If not, adjust the offsets
+	 * used below. */
+	MarkAllViewportsDirty(
+		pt.x - TILE_SIZE + 1,
+		pt.y,
+		pt.x + TILE_SIZE - 1,
+		pt.y + TILE_SIZE + TILE_HEIGHT - 1
+	);
+}
+
 /**
  * Marks the selected tiles as dirty.
  *
@@ -2139,6 +2225,9 @@
 					_thd.selstart.x = x1 & ~TILE_UNIT_MASK;
 					_thd.selstart.y = y1 & ~TILE_UNIT_MASK;
 					break;
+				case HT_PREVIEW:
+					new_drawstyle = HT_PREVIEW & HT_DRAG_MASK;
+					break;
 				default:
 					NOT_REACHED();
 					break;
@@ -2809,6 +2898,39 @@
 			}
 			break;
 
+		case VPM_A_B_LINE: { // drag an A to B line
+			TileIndex t0 = TileVirtXY(sx, sy);
+			TileIndex t1 = TileVirtXY(x, y);
+			uint dx = Delta(TileX(t0), TileX(t1)) + 1;
+			uint dy = Delta(TileY(t0), TileY(t1)) + 1;
+			byte index = 0;
+			uint64 params[5];
+
+			/* If dragging an area (eg dynamite tool) and it is actually a single
+			 * row/column, change the type to 'line' to get proper calculation for height */
+			style = (HighLightStyle)_thd.next_drawstyle;
+			if (style & HT_RECT) {
+				if (dx == 1) {
+					style = HT_LINE | HT_DIR_Y;
+				} else if (dy == 1) {
+					style = HT_LINE | HT_DIR_X;
+				}
+			}
+
+			if (dx != 1 || dy != 1) {
+				int heightdiff = CalcHeightdiff(style, 0, t0, t1);
+
+				params[index++] = DistanceManhattan(t0, t1);
+				params[index++] = sqrtl(dx * dx + dy * dy); //DistanceSquare does not like big numbers
+				params[index++] = DistanceFromEdge(t1);
+				params[index++] = GetTileMaxZ(t1) / TILE_HEIGHT * TILE_HEIGHT_STEP;
+				if (heightdiff != 0) params[index++] = heightdiff;
+			}
+			/* Show always the measurement tooltip */
+			GuiShowTooltips(_thd.GetCallbackWnd(), STR_MEASURE_DIST_HEIGHTDIFF, index, params);
+		break;
+ 		}
+
 		default: NOT_REACHED();
 	}
 
diff --git a/src/viewport_func.h b/src/viewport_func.h
--- a/src/viewport_func.h
+++ b/src/viewport_func.h
@@ -19,6 +19,27 @@
 
 static const int TILE_HEIGHT_STEP = 50; ///< One Z unit tile height difference is displayed as 50m.
 
+/**
+ * Indexed by GetMaxScrollOutsideMap()
+ *
+ * Considering,when increasing height at tile (1, 1)
+ * the first overlapping tile on tile(1, 1, 0) is tile(4, 4, 1),
+ * or the first tile completely drawn outside the map(no height) is tile(1, 1, 4),
+ * value below has been calculated as follows:
+ *
+ * extra_pixels_needed_for heightlevels = (max_possible_height / overlap * TILE_SIZE / 2)
+ * eg. 256 / 4 * 8 / 2 = 256 pixels for tile(1, 1, 255) to be inside viewport when fully zoomed in 
+ * 22 pixels for the toolbar.
+ * 150 pixels to be safe with tall buildings on tile(1, 1, 255).
+ *
+ * @note Subtract 8 for each pixel needed.
+ * @note Tuned for heightlevel 255.
+ */
+enum  ScrollMaxOutsideMap {
+MAXSCROLL_OLD  = 0,    ///< Before MoreHeightLevels
+MAXSCROLL_NEW  = 3424, ///< tile(1, 1) having height 255
+};
+
 void SetSelectionRed(bool);
 
 void DeleteWindowViewport(Window *w);
@@ -53,7 +74,6 @@
 void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool transparent = false, const SubSprite *sub = NULL);
 void ViewportAddString(const DrawPixelInfo *dpi, ZoomLevel small_from, const ViewportSign *sign, StringID string_normal, StringID string_small, StringID string_small_shadow, uint64 params_1, uint64 params_2 = 0, Colours colour = INVALID_COLOUR);
 
-
 void StartSpriteCombine();
 void EndSpriteCombine();
 
@@ -66,6 +86,7 @@
 
 bool ScrollWindowToTile(TileIndex tile, Window *w, bool instant = false);
 bool ScrollWindowTo(int x, int y, int z, Window *w, bool instant = false);
+uint16 GetMaxScrollOutsideMap();
 
 bool ScrollMainWindowToTile(TileIndex tile, bool instant = false);
 bool ScrollMainWindowTo(int x, int y, int z = -1, bool instant = false);
@@ -75,5 +96,8 @@
 extern Point _tile_fract_coords;
 
 void MarkTileDirtyByTile(TileIndex tile);
+void MarkTileDirtyByTileOutsideMap(int x, int y);
+
+int GetRowAtTile(int viewport_y, Point tile);
 
 #endif /* VIEWPORT_FUNC_H */
diff --git a/src/viewport_type.h b/src/viewport_type.h
--- a/src/viewport_type.h
+++ b/src/viewport_type.h
@@ -14,6 +14,7 @@
 
 #include "zoom_type.h"
 #include "strings_type.h"
+#include "math.h"
 
 /**
  * Data structure for viewport, display of a part of the world
@@ -81,6 +82,7 @@
 	VPM_FIX_VERTICAL    =    6, ///< drag only in vertical direction
 	VPM_X_LIMITED       =    7, ///< Drag only in X axis with limited size
 	VPM_Y_LIMITED       =    8, ///< Drag only in Y axis with limited size
+	VPM_A_B_LINE        =    9, ///< Drag a line from tile A to tile B
 	VPM_RAILDIRS        = 0x40, ///< all rail directions
 	VPM_SIGNALDIRS      = 0x80, ///< similiar to VMP_RAILDIRS, but with different cursor
 };
@@ -101,6 +103,8 @@
 	DDSP_CREATE_RIVER,         ///< Create rivers
 	DDSP_PLANT_TREES,          ///< Plant trees
 	DDSP_BUILD_BRIDGE,         ///< Bridge placement
+	DDSP_COPY_AREA,            ///< Copy & paste
+	DDSP_MEASURE,              ///< Measurement tool // TODO: fix selecting 1 tile and reset values on mouse release.
 
 	/* Rail specific actions */
 	DDSP_PLACE_RAIL,           ///< Rail placement
diff --git a/src/void_cmd.cpp b/src/void_cmd.cpp
--- a/src/void_cmd.cpp
+++ b/src/void_cmd.cpp
@@ -13,13 +13,14 @@
 #include "tile_cmd.h"
 #include "command_func.h"
 #include "viewport_func.h"
+#include "slope_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
 
 static void DrawTile_Void(TileInfo *ti)
 {
-	DrawGroundSprite(SPR_SHADOW_CELL, PAL_NONE);
+	DrawGroundSprite(SPR_FLAT_BLACKTILES + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
 }
 
 
@@ -35,7 +36,8 @@
 
 static CommandCost ClearTile_Void(TileIndex tile, DoCommandFlag flags)
 {
-	return_cmd_error(STR_ERROR_OFF_EDGE_OF_MAP);
+	CommandCost cost(EXPENSES_CONSTRUCTION);
+	return cost;
 }
 
 
@@ -62,7 +64,8 @@
 
 static CommandCost TerraformTile_Void(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
 {
-	return_cmd_error(STR_ERROR_OFF_EDGE_OF_MAP);
+	CommandCost cost(EXPENSES_CONSTRUCTION);
+	return cost;
 }
 
 extern const TileTypeProcs _tile_type_void_procs = {
diff --git a/src/watch_gui.cpp b/src/watch_gui.cpp
new file mode 100644
--- /dev/null
+++ b/src/watch_gui.cpp
@@ -0,0 +1,428 @@
+/* $Id: watch_gui.cpp  17678 2009-10-07 20:54:05  muxy $ */
+
+/** @file watch_gui.cpp GUI that follow other company building. */
+
+#include "stdafx.h"
+#include "watch_gui.h"
+#include "widget_type.h"
+#include "gfx_type.h"
+#include "gfx_func.h"
+#include "company_base.h"
+#include "company_gui.h"
+#include "viewport_func.h"
+#include "window_func.h"
+#include "strings_func.h"
+#include "zoom_func.h"
+#include "map_func.h"
+
+#include "network/network.h"
+#include "network/network_func.h"
+#include "network/network_base.h"
+
+#include "table/sprites.h"
+#include "table/strings.h"
+
+/** Make the widgets columns for company button, has_client and activity Blot.
+ * @param biggest_index Storage for collecting the biggest index used in the returned tree.
+ * @return Horizontal container with butons columns.
+ * @post \c *biggest_index contains the largest used index in the tree.
+ */
+static NWidgetBase *MakeCompanyButtons(int *biggest_index)
+{
+	NWidgetHorizontal *widget_container_horiz = NULL;         // Storage for all cols.
+	NWidgetVertical *widget_container_company = NULL;         // Storage for company Col.
+	NWidgetVertical *widget_container_hasclient = NULL;       // Storage for Has Client Blot.
+	NWidgetVertical *widget_container_activity = NULL;        // Storage for Activity Blot.
+	//NWidgetVertical *widget_container_action1 = NULL;         // Storage for Action 1
+
+	widget_container_horiz = new NWidgetHorizontal();
+	widget_container_company = new NWidgetVertical();
+	widget_container_hasclient  = new NWidgetVertical();
+	widget_container_activity = new NWidgetVertical();
+	//widget_container_action1 = new NWidgetVertical();
+
+	Dimension company_sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
+	company_sprite_size.width  += WD_MATRIX_LEFT + WD_MATRIX_RIGHT;
+	company_sprite_size.height += WD_MATRIX_TOP + WD_MATRIX_BOTTOM + 1; // 1 for the 'offset' of being pressed
+
+	Dimension blot_sprite_size = GetSpriteSize(SPR_BLOT);
+	blot_sprite_size.width  += WD_MATRIX_LEFT + WD_MATRIX_RIGHT;
+	blot_sprite_size.height += WD_MATRIX_TOP + WD_MATRIX_BOTTOM + 1; // 1 for the 'offset' of being pressed
+
+
+	for (int company_num = COMPANY_FIRST; company_num < MAX_COMPANIES; company_num++) {
+
+		/* Manage Company Buttons */
+		NWidgetBackground *company_panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_PB_COMPANY_FIRST + company_num);
+		company_panel->SetMinimalSize(company_sprite_size.width, company_sprite_size.height);
+		company_panel->SetResize(0, 0);
+		company_panel->SetFill(1, 0);
+		company_panel->SetDataTip(0x0, STR_WATCH_CLICK_TO_WATCH_COMPANY);
+		widget_container_company->Add(company_panel);
+
+		/* Manage Has Client Blot */
+		NWidgetBackground *hasclient_panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_HAS_CLIENT_FIRST + company_num);
+		company_panel->SetMinimalSize(blot_sprite_size.width, blot_sprite_size.height);
+		company_panel->SetResize(0, 0);
+		company_panel->SetFill(1, 0);
+		widget_container_hasclient->Add(hasclient_panel);
+
+		/* Manage Activit Blot */
+		/*
+		NWidgetBackground *activity_panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_ACTIVITY_FIRST + company_num);
+		company_panel->SetMinimalSize(blot_sprite_size.width, blot_sprite_size.height);
+		company_panel->SetResize(0, 0);
+		company_panel->SetFill(1, 0);
+		widget_container_activity->Add(activity_panel);
+		*/
+
+		/* Button Action1 */
+		/*
+		NWidgetBackground *action1_panel =  new NWidgetBackground(WWT_PANEL, COLOUR_GREY, EWW_PB_ACTION1_FIRST + company_num);
+		company_panel->SetResize(0, 0);
+		company_panel->SetFill(1, 0);
+		widget_container_action1->Add(action1_panel);
+		*/
+	}
+
+	/* Add the verticals widgets to the horizontal container */
+	widget_container_horiz->Add(widget_container_company);
+	widget_container_horiz->Add(widget_container_hasclient);
+	/* widget_container_horiz->Add(widget_container_activity); */
+	//widget_container_horiz->Add(widget_container_action1);
+
+	/* return the horizontal widget container */
+	return widget_container_horiz;
+}
+
+
+/**
+ * Watch Company Window Widgets Array
+ * The Company Button, Has Client Blot and Activity Blot Columns
+ * Are made through a function regarding MAX_COMPANIES value
+ */
+static const NWidgetPart _nested_watch_company_widgets[] = {
+	/* Title Bar with close box, title, shade and stick boxes */
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+		NWidget(WWT_CAPTION, COLOUR_GREY, EWW_CAPTION), SetDataTip(STR_WATCH_WINDOW_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_SHADEBOX, COLOUR_GREY),
+		NWidget(WWT_STICKYBOX, COLOUR_GREY),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(NWID_VERTICAL),
+			NWidgetFunction(MakeCompanyButtons),
+			/* Buton Zoom Out, In, Scrollto */
+			NWidget(NWID_HORIZONTAL),
+				NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, EWW_ZOOMOUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
+				NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, EWW_ZOOMIN),  SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
+				NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, EWW_CENTER),  SetDataTip(SPR_CENTRE_VIEW_VEHICLE, STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT),
+				NWidget(WWT_PANEL, COLOUR_GREY, EWW_NEW_WINDOW),   SetDataTip(0, STR_WATCH_CLICK_NEW_WINDOW), EndContainer(),
+			EndContainer(),
+			/* Background panel for resize purpose */
+			NWidget(WWT_PANEL, COLOUR_GREY), SetResize(0, 1), EndContainer(),
+		EndContainer(),
+		/* Watch Pannel */
+		NWidget(WWT_PANEL, COLOUR_GREY),
+			NWidget(NWID_VIEWPORT, INVALID_COLOUR, EWW_WATCH), SetPadding(2, 2, 2, 2), SetResize(1, 1), SetFill(1, 1),
+		EndContainer(),
+	EndContainer(),
+	/* Status Bar with resize buton */
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
+		NWidget(WWT_RESIZEBOX, COLOUR_GREY),
+	EndContainer(),
+};
+
+/**
+ * Watch Company Window Descriptor
+ */
+static const WindowDesc _watch_company_desc(
+	WDP_AUTO, 300, 257,
+	WC_WATCH_COMPANY, WC_NONE,
+	WDF_UNCLICK_BUTTONS,
+	_nested_watch_company_widgets, lengthof(_nested_watch_company_widgets)
+);
+
+//static int WatchCompany::button1_state[MAX_COMPANIES];
+
+/** Watch Company Class Constructor
+ * @param desc Window Descriptor The Window Descriptor
+ * @param window_number The window number for the class
+ * @param company_to_watch Company ID for watching a particular company
+ */
+WatchCompany::WatchCompany(const WindowDesc *desc, int window_number, CompanyID company_to_watch = INVALID_COMPANY) : Window()
+{
+	this->watched_company = company_to_watch;
+
+	this->InitNested(desc, window_number);
+	this->owner = this->watched_company;
+
+	/* Reset activity and client count for all companies */
+	for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
+		this->company_activity[i] = 0;
+		this->company_count_client[i] = 0;
+	}
+	
+	GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
+	
+	/* Init the viewport area */
+	NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(EWW_WATCH);
+	nvp->InitializeViewport(this, 0, ZOOM_LVL_NORMAL);
+	
+	Point pt;
+	/* the main window with the main view */
+	const Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
+	
+	/* center on same place as main window (zoom is maximum, no adjustment needed) */
+	pt.x = w->viewport->scrollpos_x + w->viewport->virtual_width / 2;
+	pt.y = w->viewport->scrollpos_y + w->viewport->virtual_height / 2;
+
+	this->viewport->scrollpos_x = pt.x - this->viewport->virtual_width / 2;
+	this->viewport->scrollpos_y = pt.y - this->viewport->virtual_height / 2;
+	this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x;
+	this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y;
+
+	if (this->watched_company != INVALID_COMPANY) {
+		Company *c = Company::Get( this->watched_company);
+		this->ScrollToTile(c->last_build_coordinate);
+	}
+	this->InvalidateData();
+}
+
+void WatchCompany::SetStringParameters(int widget) const
+{
+	switch (widget) {
+		case EWW_CAPTION:
+			SetDParamStr(0, this->company_name);
+			break;
+	}
+}
+
+/*
+void WatchCompany::OnPaint()
+{
+	this->DrawWidgets();
+}
+*/
+
+void WatchCompany::DrawWidget(const Rect &r, int widget) const
+{
+	/* draw the widget */
+	/* Company Button */
+	if (IsInsideMM(widget, EWW_PB_COMPANY_FIRST, EWW_PB_COMPANY_LAST + 1)) {
+		if (this->IsWidgetDisabled(widget)) return;
+		if ( Company::IsValidID( widget - EWW_PB_COMPANY_FIRST ) ) {
+		    CompanyID cid = (CompanyID)(widget - (EWW_PB_COMPANY_FIRST));
+		    int offset = (cid == this->watched_company) ? 1 : 0;
+		    Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
+		    DrawCompanyIcon(cid, (r.left + r.right - sprite_size.width) / 2 + offset, (r.top + r.bottom - sprite_size.height) / 2 + offset);
+		}
+		return;
+	}
+	/* Has Client Blot */
+	if (IsInsideMM( widget, EWW_HAS_CLIENT_FIRST, EWW_HAS_CLIENT_LAST + 1)) {
+		if (Company::IsValidID( widget-EWW_HAS_CLIENT_FIRST)) {
+			/* Draw the Blot only if Company Exists */
+			Dimension sprite_size = GetSpriteSize(SPR_BLOT);
+#ifdef ENABLE_NETWORK
+			if (!_networking) { // Local game, draw the Blot
+				DrawSprite(SPR_BLOT, Company::IsValidAiID(widget-EWW_HAS_CLIENT_FIRST)?PALETTE_TO_ORANGE:PALETTE_TO_GREEN, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
+			} else { // Network game, draw the blot according to company client count
+				DrawSprite(SPR_BLOT, this->company_count_client[widget-EWW_HAS_CLIENT_FIRST]>0?(company_activity[widget-EWW_HAS_CLIENT_FIRST]>0?PALETTE_TO_RED:PALETTE_TO_GREEN):PALETTE_TO_GREY, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
+			}
+#else
+			DrawSprite(SPR_BLOT, Company::IsValidAiID(widget-EWW_HAS_CLIENT_FIRST)?PALETTE_TO_ORANGE:PALETTE_TO_GREEN, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
+#endif
+		}
+	}
+	/* Activity Blot */
+	/*
+	if (IsInsideMM( widget, EWW_ACTIVITY_FIRST, EWW_ACTIVITY_LAST + 1)) {
+		if (Company::IsValidID(widget-EWW_ACTIVITY_FIRST)) {
+			// Draw the Blot only if Company Exists
+			Dimension sprite_size = GetSpriteSize(SPR_BLOT);
+			DrawSprite(SPR_BLOT, company_activity[widget-EWW_ACTIVITY_FIRST]>0?PALETTE_TO_RED:PALETTE_TO_GREY, (r.left + r.right - sprite_size.width) / 2, (r.top + r.bottom - sprite_size.height) / 2);
+		}
+	}
+	*/
+}
+
+void WatchCompany::OnResize()
+{
+	if (this->viewport != NULL) {
+		NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(EWW_WATCH);
+		nvp->UpdateViewportCoordinates(this);
+	}
+}
+
+void WatchCompany::OnScroll(Point delta)
+{
+	const ViewPort *vp = IsPtInWindowViewport(this, _cursor.pos.x, _cursor.pos.y);
+	if (vp == NULL) return;
+
+	this->viewport->scrollpos_x += ScaleByZoom(delta.x, vp->zoom);
+	this->viewport->scrollpos_y += ScaleByZoom(delta.y, vp->zoom);
+	this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x;
+	this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y;
+}
+
+void WatchCompany::OnMouseWheel(int wheel)
+{
+	ZoomInOrOutToCursorWindow(wheel < 0, this);
+}
+
+void WatchCompany::OnClick(Point pt, int widget, int click_count)
+{
+	if (IsInsideMM(widget, EWW_PB_COMPANY_FIRST, EWW_PB_COMPANY_LAST + 1)) {
+		/* Click on Company Button */
+		if (!this->IsWidgetDisabled(widget)) {
+			if (this->watched_company != INVALID_COMPANY) {
+				/* Raise the watched company button  */
+				this->RaiseWidget(this->watched_company + EWW_PB_COMPANY_FIRST);
+			}
+			if (this->watched_company == (CompanyID)(widget - EWW_PB_COMPANY_FIRST)) {
+				/* Stop watching watched_company */
+				this->watched_company = INVALID_COMPANY;
+				GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
+			} else {
+				/* Lower the new watched company button */
+				this->watched_company = (CompanyID)(widget - EWW_PB_COMPANY_FIRST);
+				this->LowerWidget(this->watched_company + EWW_PB_COMPANY_FIRST);
+				Company *c = Company::Get( this->watched_company);
+				SetDParam(0, c->index);
+				GetString(this->company_name, STR_COMPANY_NAME, lastof(this->company_name));
+
+				this->ScrollToTile( c->last_build_coordinate);
+			}
+			this->owner = this->watched_company;
+			this->SetDirty();
+		}
+	} else if ( IsInsideMM(widget, EWW_PB_ACTION1_FIRST, EWW_PB_ACTION1_LAST + 1)) {
+		if (!this->IsWidgetDisabled(widget)) {
+			this->ToggleWidgetLoweredState(widget);
+			this->SetDirty();
+		}
+	} else {
+		switch (widget) {
+			case EWW_ZOOMOUT: DoZoomInOutWindow(ZOOM_OUT, this); break;
+			case EWW_ZOOMIN: DoZoomInOutWindow(ZOOM_IN,  this); break;
+
+			case EWW_CENTER: { // location button (move main view to same spot as this view) 'Center Main View'
+				Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
+				int x = this->viewport->scrollpos_x; // Where is the watch looking at
+				int y = this->viewport->scrollpos_y;
+
+				/* set the main view to same location. Based on the center, adjusting for zoom */
+				w->viewport->dest_scrollpos_x =  x - (w->viewport->virtual_width -  this->viewport->virtual_width) / 2;
+				w->viewport->dest_scrollpos_y =  y - (w->viewport->virtual_height - this->viewport->virtual_height) / 2;
+			} break;
+				
+			case EWW_NEW_WINDOW:
+				ShowWatchWindow(this->watched_company);
+				break;
+		}
+	}
+}
+
+void WatchCompany::OnInvalidateData(int data, bool gui_scope)
+{
+	if (!gui_scope) return;
+
+	for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
+		this->SetWidgetDisabledState(EWW_PB_COMPANY_FIRST + i , !Company::IsValidID(i));
+		this->SetWidgetDisabledState(EWW_PB_ACTION1_FIRST + i , !Company::IsValidID(i));
+	}
+	/* Check if the currently selected company is still active. */
+	if (this->watched_company != INVALID_COMPANY) {
+		/* Make sure the widget is lowered */
+		this->LowerWidget(EWW_PB_COMPANY_FIRST + this->watched_company);
+		/* Check if the watched Company is still a valid one */
+		if (!Company::IsValidID(this->watched_company)) {
+			/* Invalid Company Raise the associated widget. */
+			this->RaiseWidget(this->watched_company + EWW_PB_COMPANY_FIRST);
+			this->watched_company = INVALID_COMPANY;
+			GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
+		} else {
+			Company *c = Company::Get(this->watched_company);
+			SetDParam(0, c->index);
+			GetString(this->company_name, STR_COMPANY_NAME, lastof(this->company_name));
+		}
+	} else {
+		GetString(this->company_name, STR_JUST_NOTHING, lastof(this->company_name));
+	}
+#ifdef ENABLE_NETWORK
+	if (_networking) { // Local game, draw the Blot
+		/* Reset company count - network only */
+		for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
+			this->company_count_client[i] = 0;
+		}
+		/* Calculate client count into company - network only */
+		NetworkClientInfo *ci;
+		FOR_ALL_CLIENT_INFOS(ci) {
+			if (Company::IsValidID(ci->client_playas)) {
+				company_count_client[ci->client_playas]+=1;
+			}
+		}
+	}
+#endif
+	HandleZoomMessage(this, this->viewport, EWW_ZOOMIN, EWW_ZOOMOUT);
+}
+
+void WatchCompany::ScrollToTile(TileIndex tile)
+{
+	/* Scroll window to the tile, only if not zero */
+	if (tile != 0) {
+		ScrollWindowTo(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2, -1, this);
+	}
+}
+
+/** OnDoCommand function - Called by the DoCommand
+ *  @param company The company ID who's client is building
+ *  @param tile The tile number where action took place
+ */
+void WatchCompany::OnDoCommand(CompanyByte company, TileIndex tile)
+{
+	/* Check if its my company */
+	if (this->watched_company == company)
+	{
+		this->ScrollToTile(tile);
+	}
+	/* set the company_activity to its max in order to paint the BLOT in red
+	 * This will result by having the activity blot set to red for all companies
+	 * even the one watched. To avoid this behaviour and not to light the blot of
+	 * the watched company, the code can be moved just after the ScrollToTile call.
+	 */
+	if (tile != 0) {
+		this->company_activity[company] = MAX_ACTIVITY;
+		this->SetDirty();
+	}
+}
+
+/** Used to decrement the activity counter
+ *
+ */
+void WatchCompany::OnTick()
+{
+	bool set_dirty = false;
+	for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
+		if (this->company_activity[i]>0) {
+			this->company_activity[i]--;
+			if (this->company_activity[i]==0) {
+				set_dirty = true;
+			}
+		}
+	}
+	/* If one company_activity reaches 0, then redraw */
+	if (set_dirty) {
+		this->SetDirty();
+	}
+}
+
+void ShowWatchWindow(CompanyID company_to_watch = INVALID_COMPANY)
+{
+	int i = 0;
+	/* find next free window number for watch viewport */
+	while (FindWindowById(WC_WATCH_COMPANY, i) != NULL) i++;
+	new WatchCompany(&_watch_company_desc, i, company_to_watch);
+}
diff --git a/src/watch_gui.h b/src/watch_gui.h
new file mode 100644
--- /dev/null
+++ b/src/watch_gui.h
@@ -0,0 +1,63 @@
+/* $Id: watch_gui.h 17678 2009-10-07 20:54:05  muxy $ */
+
+/** @file watch_gui.h GUI Functions related to watching. */
+
+#ifndef WATCH_GUI_H
+#define WATCH_GUI_H
+
+#include "window_gui.h"
+#include "company_base.h"
+
+#define MAX_ACTIVITY 30
+
+enum WatchCompanyWidgets {
+	EWW_CAPTION,
+	EWW_PB_COMPANY_FIRST,
+	EWW_PB_COMPANY_LAST  = EWW_PB_COMPANY_FIRST + MAX_COMPANIES - 1,
+	EWW_HAS_CLIENT_FIRST,
+	EWW_HAS_CLIENT_LAST = EWW_HAS_CLIENT_FIRST + MAX_COMPANIES - 1,
+	EWW_ACTIVITY_FIRST,
+	EWW_ACTIVITY_LAST = EWW_ACTIVITY_FIRST + MAX_COMPANIES - 1,
+	EWW_PB_ACTION1_FIRST,
+	EWW_PB_ACTION1_LAST = EWW_PB_ACTION1_FIRST + MAX_COMPANIES - 1,
+	EWW_WATCH,
+	EWW_ZOOMIN,
+	EWW_ZOOMOUT,
+	EWW_CENTER,
+	EWW_NEW_WINDOW
+};
+
+class WatchCompany : public Window
+{
+
+protected:
+
+	CompanyID watched_company;                            // Company ID beeing watched.
+	int company_activity[MAX_COMPANIES];                  // int array for activity blot.
+	int company_count_client[MAX_COMPANIES];              // company client count.
+	char company_name[MAX_LENGTH_COMPANY_NAME_CHARS];     // company name for title display
+
+	void SetWatchWindowTitle();
+	void ScrollToTile(TileIndex tile);
+
+
+public:
+
+	WatchCompany(const WindowDesc *desc, int window_number, CompanyID company_to_watch);
+
+	virtual void SetStringParameters(int widget) const;
+//	virtual void OnPaint();
+	virtual void DrawWidget(const Rect &r, int widget) const;
+	virtual void OnClick(Point pt, int widget, int click_count);
+	virtual void OnResize();
+	virtual void OnScroll(Point delta);
+	virtual void OnMouseWheel(int wheel);
+	virtual void OnInvalidateData(int data, bool gui_scope);
+	virtual void OnTick();
+	
+	void OnDoCommand(CompanyByte company, TileIndex tile);
+};
+
+void ShowWatchWindow(CompanyID company_to_watch);
+
+#endif // COMPANY_GUI_H 
diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -401,6 +401,9 @@
 				return_cmd_error(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
 			}
 
+			/* Check to see if crossing-water tunnel present. */
+			if (GetTileZ(tile) == 0 && IsTunnelInWay(tile, 0)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST);
+
 			/* Make sure no vehicle is on the tile */
 			CommandCost ret = EnsureNoVehicleOnGround(tile);
 			if (ret.Failed()) return ret;
diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp
--- a/src/waypoint_gui.cpp
+++ b/src/waypoint_gui.cpp
@@ -22,6 +22,7 @@
 #include "company_base.h"
 #include "window_func.h"
 #include "waypoint_base.h"
+#include "departures_gui.h"
 
 #include "table/strings.h"
 
@@ -31,6 +32,7 @@
 	WAYPVW_VIEWPORT,
 	WAYPVW_CENTERVIEW,
 	WAYPVW_RENAME,
+	WAYPVW_DEPARTURES,
 	WAYPVW_SHOW_VEHICLES,
 };
 
@@ -116,6 +118,10 @@
 			case WAYPVW_SHOW_VEHICLES: // show list of vehicles having this waypoint in their orders
 				ShowVehicleListWindow(this->owner, this->vt, this->wp->index);
 				break;
+
+			case WAYPVW_DEPARTURES: // show departure times of vehicles
+				ShowWaypointDepartures((StationID)this->wp->index);
+				break;
 		}
 	}
 
@@ -171,6 +177,7 @@
 	NWidget(NWID_HORIZONTAL),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WAYPVW_CENTERVIEW), SetMinimalSize(100, 12), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BUTTON_LOCATION, STR_BUOY_VIEW_CENTER_TOOLTIP),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WAYPVW_RENAME), SetMinimalSize(100, 12), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BUTTON_RENAME, STR_BUOY_VIEW_CHANGE_BUOY_NAME),
+		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WAYPVW_DEPARTURES), SetMinimalSize(100, 12), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_STATION_VIEW_DEPARTURES_BUTTON, STR_STATION_VIEW_DEPARTURES_TOOLTIP),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WAYPVW_SHOW_VEHICLES), SetMinimalSize(15, 12), SetDataTip(STR_SHIP, STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP),
 		NWidget(WWT_RESIZEBOX, COLOUR_GREY),
 	EndContainer(),
diff --git a/src/window_type.h b/src/window_type.h
--- a/src/window_type.h
+++ b/src/window_type.h
@@ -78,6 +78,7 @@
 	WC_DROPDOWN_MENU,
 	WC_BUILD_INDUSTRY,
 	WC_GAME_OPTIONS,
+	WC_SYSTEM_TIME,
 	WC_NETWORK_WINDOW,
 	WC_INDUSTRY_DIRECTORY,
 	WC_MESSAGE_HISTORY,
