1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-26 16:09:10 +00:00

Compare commits

..

1 Commits
0.4.0 ... 0.3.6

Author SHA1 Message Date
darkvater
7423777a18 (svn r1663) Release 0.3.6. 2005-01-25 00:10:06 +00:00
231 changed files with 73735 additions and 92267 deletions

454
Makefile
View File

@@ -57,13 +57,14 @@
# MANUAL_CONFIG: do not use Makefile.config, config options set manually
# DEBUG: build in debug mode
# PROFILE: build in profile mode, disables -s and -fomit-frame-pointer
# DISPLAY_WARNINGS: when off, some errors are not displayed while compiling
# TRANSLATOR: build in translator mode (untranslated strings are prepended by
# a <TODO> mark)
# RELEASE: this will be the released version number. It replaces all places
# where it normally would print the revision number
# MIDI: if set, it will use it as custom path to midi player.
# If unset, it will use the hardcoded path in the c code
# This can still be overriden by the music.extmidi openttd.cfg option.
# If unset, it will use the hardcoded path in the c code
# VERBOSE: actually show the commands used for compilation.
# WITH_NETWORK: enable networking
# DEDICATED: allows compilation on UNIX without SDL. Useful for dedicated servers
#
@@ -90,7 +91,7 @@
# USE_HOMEDIR: If this variable is set, PERSONAL_DIR will be prefixed with
# ~/ at runtime (the user's homedir)
# SECOND_DATA_PATH Use this data dir if a file is not found in the data dir in the data path
# CUSTOM_LANG_PATH If this is set, it will use the path given to search for lng files
# CUSTOM_LANG_PATH If this is set, it will use the path given to search for lng files
# instead of the lang dir in the data path
# NOTE: both SECOND_DATA_PATH and CUSTOM_LANG_PATH uses paths relative to where OTTD is opened
#
@@ -99,22 +100,11 @@
# ordinary users, currently it is only used for the debian
# packaging. This value should only be set when calling `make
# install' and is not saved in Makefile.config
# (Note that DESTDIR is checked if DEST_DIR is not set.)
#
# STATIC: link statically
# CYGWIN: build in Cygwin environment
# MINGW: build with MingW compiler, link with MingW libraries
#
# VERBOSE: show full compiler invocations instead of brief progress messages
#
# Special for crosscompiling there are some commands available:
#
# ENDIAN_FORCE: forces the endian-check to give a certain result. Can be either BE or LE.
# WINDRES: the location of your windres
# CC_HOST: the gcc of your localhost if you are making a target that produces incompatible executables
# CFLAGS_HOST: cflags used for CC_HOST. Make it something if you are getting errors when you try to compi
# windows executables on linux. (just: CFLAGS_HOST:='-I' or something)
#
# Experimental (does not work properly):
# WITH_DIRECTMUSIC: enable DirectMusic MIDI support
@@ -124,10 +114,13 @@
# Configuration
#
ifndef RELEASE
RELEASE:=0.3.6
endif
# Makefile version tag
# it checks if the version tag in Makefile.config is the same and force update outdated config files
MAKEFILE_VERSION:=7
# it checks if the version tag in makefile.config is the same and force update outdated config files
MAKEFILE_VERSION:=6
# CONFIG_WRITER has to be found even for manual configuration
CONFIG_WRITER=makefiledir/Makefile.config_writer
@@ -147,7 +140,7 @@ else
CONFIG_INCLUDED:=1
endif
# updates Makefile.config if it's outdated
# updates makefile.config if it's outdated
ifneq ($(MAKEFILE_VERSION),$(CONFIG_VERSION))
ifndef MANUAL_CONFIG # manual config should not check this
UPDATECONFIG:=upgradeconf
@@ -160,14 +153,16 @@ ifneq ($(MAKEFILE_VERSION),$(CONFIG_VERSION))
SDL-CONFIG:=sdl-config
endif
endif
else
# this should define SDL-CONFIG for manual configuration
ifeq ($(shell uname),FreeBSD)
SDL-CONFIG:=sdl11-config
else
SDL-CONFIG:=sdl-config
endif
endif
ifndef SDL-CONFIG
UPDATECONFIG:=upgradeconf
CONFIG_INCLUDED:=
endif
# this is used if there aren't any Makefile.config
# this is used if there aren't any makefile.config
ifndef CONFIG_INCLUDED
# sets network on by default if there aren't any config file
ENABLE_NETWORK:=1
@@ -183,6 +178,12 @@ ENABLE_NETWORK:=1
-include $(LIB_DETECTION)
endif
ifdef DISPLAY_WARNINGS
WARNING_DISPLAY:=-fstrict-aliasing
else
WARNING_DISPLAY:=-fno-strict-aliasing
endif
ifdef SUPRESS_LANG_ERRORS
LANG_ERRORS = >/dev/null 2>&1
endif
@@ -192,7 +193,7 @@ ifndef WIN32
ifndef OSX
ifndef MORPHOS
ifndef SKIP_STATIC_CHECK
$(error Static is only known to work on MorphOS and MacOSX!!! --- Check Makefile.config for more info and howto bypass this check)
$(error Static is only known to work on MorphOS and MacOSX!!! --- Check makefile.config for more info and howto bypass this check)
endif
endif
endif
@@ -226,6 +227,13 @@ endif
#
# Compiler configuration
#
CC=gcc
CXX=g++
ifdef MORPHOS
CC += -noixemul -pipe
CXX += -noixemul -pipe
endif
# Executable file extension
ifdef WIN32
@@ -267,23 +275,6 @@ endwarnings:=endwarnings
BASECFLAGS += -m64
endif
# Check if there is a windres override
ifndef WINDRES
WINDRES = windres
endif
# Check if we have a new target
ifdef CC_TARGET
CC = $(CC_TARGET)
endif
# Check if CC_HOST is defined. If not, it is CC
ifndef CC_HOST
CC_HOST = $(CC)
endif
ifndef CFLAGS_HOST
CFLAGS_HOST = $(BASECFLAGS)
endif
# When calling the compiler, use these flags
# -g debugging symbols
@@ -300,7 +291,7 @@ CC_VERSION = $(shell $(CC) -dumpversion | cut -c 1,3)
# this is a workaround to test for >=
ifeq ($(shell if test $(CC_VERSION) -ge 29; then echo true; fi), true)
CFLAGS += -O -Wall -Wno-multichar -Wsign-compare -Wstrict-prototypes
CFLAGS += -Wwrite-strings -Wpointer-arith
CFLAGS += -Wwrite-strings
endif
ifeq ($(shell if test $(CC_VERSION) -ge 30; then echo true; fi), true)
CFLAGS += -W -Wno-unused-parameter
@@ -309,54 +300,41 @@ ifeq ($(shell if test $(CC_VERSION) -ge 34; then echo true; fi), true)
CFLAGS += -Wdeclaration-after-statement -Wold-style-definition
endif
ifdef DEBUG
ifeq ($(shell expr $(DEBUG) \>= 1), 1)
CFLAGS += -g -D_DEBUG
endif
ifeq ($(shell expr $(DEBUG) \>= 2), 1)
CFLAGS += -fno-inline
endif
ifeq ($(shell expr $(DEBUG) \>= 3), 1)
CFLAGS += -O0
endif
endif
ifdef PROFILE
CFLAGS += -pg
LDFLAGS += -pg
endif
CDEFS=-DWITH_REV
LDFLAGS=
LIBS=
ifndef DEBUG
ifndef PROFILE
ifdef DEBUG
# Debug mode
CDEFS += -D_DEBUG
BASECFLAGS += -g
else
ifdef PROFILE
BASECFLAGS += -pg
LDFLAGS += -pg
else
# Release mode
ifndef MORPHOS
ifndef IRIX
# automatical strip breaks under morphos
BASECFLAGS += -s
LDFLAGS += -s
endif
endif
endif
ifdef OSX
# these compilerflags makes the app run as fast as possible without making the app unstable. It works on G3 or newer
BASECFLAGS += -O3 -funroll-loops -fsched-interblock -falign-loops=16 -falign-jumps=16 -falign-functions=16 -falign-jumps-max-skip=15 -falign-loops-max-skip=15 -mdynamic-no-pic -mpowerpc-gpopt -force_cpusubtype_ALL
BASECFLAGS += -O3 -funroll-loops -fsched-interblock -falign-loops=16 -falign-jumps=16 -falign-functions=16 -falign-jumps-max-skip=15 -falign-loops-max-skip=15 -mdynamic-no-pic -mpowerpc-gpopt -force_cpusubtype_ALL $(WARNING_DISPLAY)
else
ifdef MORPHOS
BASECFLAGS += -O2 -noixemul -fstrict-aliasing -fexpensive-optimizations
BASECFLAGS += -mcpu=604 -fno-inline -mstring -mmultiple
BASECFLAGS += -O3 -funroll-loops -fexpensive-optimizations -mstring -mmultiple $(WARNING_DISPLAY)
else
BASECFLAGS += -O2
BASECFLAGS += -O2 $(WARNING_DISPLAY)
endif
ifndef PROFILE
ifndef IRIX
BASECFLAGS += -fomit-frame-pointer
endif
endif
endif
endif
ifdef STATIC
ifndef OSX # OSX can't build static if -static flag is used
@@ -395,11 +373,6 @@ ifdef WITH_NETWORK
endif
endif
ifdef MORPHOS
# -Wstrict-prototypes generates much noise because of system headers
CFLAGS += -Wno-strict-prototypes
endif
ifdef SUNOS
CDEFS += -DSUNOS
ifdef WITH_NETWORK
@@ -410,11 +383,11 @@ endif
# SDL config
ifdef WITH_SDL
CDEFS += -DWITH_SDL
CFLAGS += $(shell $(SDL-CONFIG) --cflags)
CFLAGS += `$(SDL-CONFIG) --cflags`
ifdef STATIC
LIBS += $(shell $(SDL-CONFIG) --static-libs)
LIBS += `$(SDL-CONFIG) --static-libs`
else
LIBS += $(shell $(SDL-CONFIG) --libs)
LIBS += `$(SDL-CONFIG) --libs`
endif
endif
@@ -429,7 +402,7 @@ ifdef WITH_ZLIB
else
ifndef STATIC_ZLIB_PATH
ifndef MANUAL_CONFIG
# updates Makefile.config with the zlib path
# updates makefile.config with the zlib path
UPDATECONFIG:=upgradeconf
endif
TEMP:=$(shell ls /lib 2>/dev/null | grep "zlib.a")$(shell ls /lib 2>/dev/null | grep "libz.a")
@@ -461,19 +434,19 @@ CDEFS += -DWITH_PNG
ifdef FREEBSD
LIBS += -lpng
else
CFLAGS += $(shell libpng-config --cflags)
CFLAGS += `libpng-config --cflags`
# seems like older libpng versions are broken and need this
PNGCONFIG_FLAGS = --ldflags --libs
ifdef STATIC
ifdef OSX
# Seems like we need a tiny hack for OSX static to work
LIBS += $(shell libpng-config --prefix)/lib/libpng.a
LIBS += `libpng-config --prefix`/lib/libpng.a
else
LIBS += $(shell libpng-config --static $(PNGCONFIG_FLAGS))
LIBS += `libpng-config --static $(PNGCONFIG_FLAGS)`
endif
else
LIBS += $(shell libpng-config --L_opts $(PNGCONFIG_FLAGS))
LIBS += `libpng-config --L_opts $(PNGCONFIG_FLAGS)`
endif
endif
endif
@@ -500,13 +473,13 @@ endif
# MIDI setup
ifdef OSX
ifndef MIDI
MIDI:=$(OSXAPP)/Contents/macosx/track_starter
MIDI:=$(OSXAPP)/contents/macos/track_starter
endif
ifndef SECOND_DATA_PATH
SECOND_DATA_PATH:="$(OSXAPP)/Contents/Data/"
SECOND_DATA_PATH:="$(OSXAPP)/contents/data/"
endif
ifndef CUSTOM_LANG_DIR
CUSTOM_LANG_DIR:="$(OSXAPP)/Contents/Lang/"
CUSTOM_LANG_DIR:="$(OSXAPP)/contents/lang/"
endif
endif
@@ -547,17 +520,10 @@ CDEFS += -DWIN32_ENABLE_DIRECTMUSIC_SUPPORT
endif
ifdef WIN32
LIBS += -lws2_32 -lwinmm -lgdi32 -ldxguid -lole32
ifdef WITH_DIRECTMUSIC
LIBS += -lstdc++
endif
LIBS += -lws2_32 -lwinmm -lgdi32 -ldxguid -lole32 -lstdc++
TTDLDFLAGS += -Wl,--subsystem,windows
endif
ifndef DEST_DIR
DEST_DIR = $(DESTDIR)
endif
# sets up the paths for use for make install
ifdef INSTALL
# We use _PREFIXED vars here, so the paths are recalculated every time, and
@@ -607,9 +573,7 @@ C_SOURCES += clear_cmd.c
C_SOURCES += command.c
C_SOURCES += console.c
C_SOURCES += console_cmds.c
C_SOURCES += debug.c
C_SOURCES += dedicated.c
C_SOURCES += depot.c
C_SOURCES += disaster_cmd.c
C_SOURCES += dock_gui.c
C_SOURCES += dummy_land.c
@@ -631,7 +595,6 @@ C_SOURCES += minilzo.c
C_SOURCES += misc.c
C_SOURCES += misc_cmd.c
C_SOURCES += misc_gui.c
C_SOURCES += mixer.c
C_SOURCES += music_gui.c
C_SOURCES += namegen.c
C_SOURCES += network.c
@@ -642,14 +605,12 @@ C_SOURCES += network_gui.c
C_SOURCES += network_server.c
C_SOURCES += network_udp.c
C_SOURCES += news_gui.c
C_SOURCES += npf.c
C_SOURCES += oldloader.c
C_SOURCES += order_cmd.c
C_SOURCES += order_gui.c
C_SOURCES += pathfind.c
C_SOURCES += player_gui.c
C_SOURCES += players.c
C_SOURCES += pool.c
C_SOURCES += queue.c
C_SOURCES += rail_cmd.c
C_SOURCES += rail_gui.c
@@ -671,12 +632,10 @@ C_SOURCES += sprite.c
C_SOURCES += spritecache.c
C_SOURCES += station_cmd.c
C_SOURCES += station_gui.c
C_SOURCES += string.c
C_SOURCES += strings.c
C_SOURCES += subsidy_gui.c
C_SOURCES += terraform_gui.c
C_SOURCES += texteff.c
C_SOURCES += tile.c
C_SOURCES += town_cmd.c
C_SOURCES += town_gui.c
C_SOURCES += train_cmd.c
@@ -689,7 +648,6 @@ C_SOURCES += vehicle.c
C_SOURCES += vehicle_gui.c
C_SOURCES += viewport.c
C_SOURCES += water_cmd.c
C_SOURCES += waypoint.c
C_SOURCES += widget.c
C_SOURCES += window.c
@@ -705,7 +663,7 @@ else
C_SOURCES += extmidi.c unix.c
endif
OBJS = $(C_SOURCES:%.c=%.o) $(CXX_SOURCES:%.cpp=%.o)
ttd_OBJS = $(C_SOURCES:%.c=%.o) $(CXX_SOURCES:%.cpp=%.o)
ifdef BEOS
CXX_SOURCES += os/beos/bemidi.cpp
@@ -714,57 +672,27 @@ endif
ifdef WIN32
# Resource file
OBJS += winres.o
ttd_OBJS += winres.o
endif
ifdef WITH_DIRECTMUSIC
CXX_SOURCES += w32dm2.cpp
endif
DEPS = $(OBJS:%.o=.deps/%.d)
ttd_DEPS1 = $(foreach obj,$(ttd_OBJS),.deps/$(obj))
ttd_DEPS = $(ttd_DEPS1:%.o=%.P)
LANG_TXT = $(filter-out %.unfinished.txt,$(wildcard lang/*.txt))
LANGS = $(LANG_TXT:%.txt=%.lng)
C_COMPILE = $(CC) $(CFLAGS) $(CDEFS)
CXX_COMPILE = $(CXX) $(CFLAGS) $(CDEFS)
##############################################################################
#
# Build commands
#
C_BUILD = $(C_COMPILE) -c
CXX_BUILD = $(CXX_COMPILE) -c
# If we are verbose, we will show commands prefixed by $(Q) (which acts as
# @ in the non-verbose mode), and we will show the "real" cmds instead of
# their quiet versions (which are used in the non-verbose mode).
# Inspired by the Linux kernel build system.
ifdef VERBOSE
Q =
quiet =
else
Q = @
quiet = quiet_
endif
C_LINK = $(CC) $(LDFLAGS) -o
# Show the command (quiet or non-quiet version based on the assignment
# just above) and then execute it.
cmd = @$(if $($(quiet)cmd_$(1)),echo $($(quiet)cmd_$(1)) &&) $(cmd_$(1))
# The build commands themselves. Note that if you omit the quiet version,
# nothing will be shown in the non-verbose mode.
quiet_cmd_compile_link = '===> Compiling and Linking $@'
cmd_compile_link = $(CC_HOST) $(CFLAGS_HOST) $(CDEFS) $< -o $@
quiet_cmd_ttd_link = '===> Linking $@'
cmd_ttd_link = $(CC) $(LDFLAGS) $(TTDLDFLAGS) $(OBJS) $(LIBS) -o $@
COMPILE_PARAMS=$(CFLAGS) $(CDEFS) -MD -c $< -o $@
quiet_cmd_c_compile = '===> Compiling $<'
cmd_c_compile = $(CC) $(COMPILE_PARAMS)
quiet_cmd_cxx_compile = '===> Compiling $<'
cmd_cxx_compile = $(CXX) $(COMPILE_PARAMS)
##############################################################################
@@ -778,43 +706,41 @@ quiet_cmd_cxx_compile = '===> Compiling $<'
ifdef OSX
OSX:=OSX
OSX_MIDI_PLAYER_FILE:=os/macosx/OpenTTDMidi.class
endif
all: endian_target.h endian_host.h $(UPDATECONFIG) $(LANGS) $(TTD) $(OSX) $(endwarnings)
all: endian.h $(UPDATECONFIG) $(LANGS) $(TTD) $(OSX) $(endwarnings)
endian_host.h: $(ENDIAN_CHECK)
@echo '===> Testing endianness for host'
$(Q)./$(ENDIAN_CHECK) > $@
endian_target.h: $(ENDIAN_CHECK)
@echo '===> Testing endianness for target'
$(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@
endian.h: $(ENDIAN_CHECK)
@echo '===> Testing endianness'
@./$(ENDIAN_CHECK) > $@
$(ENDIAN_CHECK): endian_check.c
$(call cmd,compile_link)
@echo '===> Compiling and Linking $@'
@$(CC) $(BASECFLAGS) $(CDEFS) endian_check.c -o $@
$(TTD): table/strings.h $(OBJS) $(MAKE_CONFIG)
$(call cmd,ttd_link)
$(TTD): table/strings.h $(ttd_OBJS) $(MAKE_CONFIG)
@echo '===> Linking $@'
@$(if $(VERBOSE), echo '$(C_LINK) $@ $(TTDLDFLAGS) $(ttd_OBJS) $(LIBS)')
@$(C_LINK) $@ $(TTDLDFLAGS) $(ttd_OBJS) $(LIBS)
$(OSX): $(TTD)
$(Q)rm -fr "$(OSXAPP)"
$(Q)mkdir -p "$(OSXAPP)"/Contents/MacOS
$(Q)mkdir -p "$(OSXAPP)"/Contents/Resources
$(Q)mkdir -p "$(OSXAPP)"/Contents/Data
$(Q)mkdir -p "$(OSXAPP)"/Contents/Lang
$(Q)echo "APPL????" > "$(OSXAPP)"/Contents/PkgInfo
$(Q)cp os/macosx/openttd.icns "$(OSXAPP)"/Contents/Resources/openttd.icns
$(Q)os/macosx/plistgen.sh "$(OSXAPP)" "$(REV)"
$(Q)cp os/macosx/track_starter "$(OSXAPP)"/Contents/MacOS
$(Q)ls os/macosx | grep -q "\.class" || \
javac os/macosx/OpenTTDMidi.java
$(Q)cp os/macosx/OpenTTDMidi.class "$(OSXAPP)"/Contents/MacOS
$(Q)cp data/* "$(OSXAPP)"/Contents/Data/
$(Q)cp lang/*.lng "$(OSXAPP)"/Contents/Lang/
$(Q)cp $(TTD) "$(OSXAPP)"/Contents/MacOS/$(TTD)
@rm -fr "$(OSXAPP)"
@mkdir -p "$(OSXAPP)"/Contents/MacOS
@mkdir -p "$(OSXAPP)"/Contents/Resources
@mkdir -p "$(OSXAPP)"/Contents/Data
@mkdir -p "$(OSXAPP)"/Contents/Lang
@echo "APPL????" > "$(OSXAPP)"/Contents/PkgInfo
@cp os/macos/openttd.icns "$(OSXAPP)"/Contents/Resources/openttd.icns
@os/macos/plistgen.sh "$(OSXAPP)" "$(REV)"
@cp os/macos/track_starter "$(OSXAPP)"/contents/macos
@ls os/macos | grep -q "\.class" || \
javac os/macos/OpenTTDMidi.java
@cp os/macos/OpenTTDMidi.class "$(OSXAPP)"/contents/macos
@cp data/* "$(OSXAPP)"/Contents/data/
@cp lang/*.lng "$(OSXAPP)"/Contents/lang/
@cp $(TTD) "$(OSXAPP)"/Contents/MacOS/$(TTD)
$(endwarnings): $(64_bit_warnings)
@@ -822,89 +748,90 @@ $(64_bit_warnings):
$(warning 64 bit CPUs will get some 64 bit specific bugs!)
$(warning If you see any bugs, include in your bug report that you use a 64 bit CPU)
$(STRGEN): strgen/strgen.c endian_host.h
$(call cmd,compile_link)
$(STRGEN): strgen/strgen.c endian.h
@echo '===> Compiling and Linking $@'
@$(CC) $(BASECFLAGS) $(CDEFS) -o $@ $<
table/strings.h: lang/english.txt $(STRGEN)
@echo '===> Generating $@'
$(Q)$(STRGEN)
@$(STRGEN)
lang/%.lng: lang/%.txt $(STRGEN) lang/english.txt
@echo '===> Compiling language $(*F)'
$(Q)$(STRGEN) $(STRGEN_FLAGS) $< $(LANG_ERRORS)
@$(STRGEN) $(STRGEN_FLAGS) $< $(LANG_ERRORS)
winres.o: ttd.rc
@echo '===> Compiling resource $<'
$(Q)$(WINDRES) -o $@ $<
@windres -o $@ $<
ifdef MORPHOS
release: all
$(Q)rm -fr "/t/openttd-$(RELEASE)-morphos.lha"
$(Q)mkdir -p "/t/"
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos"
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/docs"
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/data"
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/lang"
$(Q)mkdir -p "/t/openttd-$(RELEASE)-morphos/scenario"
$(Q)cp -R $(TTD) "/t/openttd-$(RELEASE)-morphos/"
$(Q)cp data/* "/t/openttd-$(RELEASE)-morphos/data/"
$(Q)cp lang/*.lng "/t/openttd-$(RELEASE)-morphos/lang/"
$(Q)cp scenario/* "/t/openttd-$(RELEASE)-morphos/scenario/"
$(Q)cp readme.txt "/t/openttd-$(RELEASE)-morphos/docs/ReadMe"
$(Q)cp docs/console.txt "/t/openttd-$(RELEASE)-morphos/docs/Console"
$(Q)cp COPYING "/t/openttd-$(RELEASE)-morphos/docs/"
$(Q)cp changelog.txt "/t/openttd-$(RELEASE)-morphos/docs/ChangeLog"
$(Q)cp known-bugs.txt "/t/openttd-$(RELEASE)-morphos/docs/known-bugs.txt"
$(Q)cp os/morphos/icons/openttd.info "/t/openttd-$(RELEASE)-morphos/$(TTD).info"
$(Q)cp os/morphos/icons/docs.info "/t/openttd-$(RELEASE)-morphos/docs.info"
$(Q)cp os/morphos/icons/drawer.info "/t/openttd-$(RELEASE)-morphos.info"
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/ReadMe.info"
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/Console.info"
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/COPYING.info"
$(Q)cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/ChangeLog.info"
$(Q)strip --strip-all --strip-unneeded --remove-section .comment "/t/openttd-$(RELEASE)-morphos/$(TTD)"
$(Q)lha a -r "t:openttd-$(RELEASE)-morphos.lha" "t:openttd-$(RELEASE)-morphos"
$(Q)lha a "t:openttd-$(RELEASE)-morphos.lha" "t:openttd-$(RELEASE)-morphos.info"
$(Q)rm -fr "/t/openttd-$(RELEASE)-morphos"
$(Q)rm -fr "/t/openttd-$(RELEASE)-morphos.info"
@rm -fr "/t/openttd-$(RELEASE)-morphos.lha"
@mkdir -p "/t/"
@mkdir -p "/t/openttd-$(RELEASE)-morphos"
@mkdir -p "/t/openttd-$(RELEASE)-morphos/docs"
@mkdir -p "/t/openttd-$(RELEASE)-morphos/data"
@mkdir -p "/t/openttd-$(RELEASE)-morphos/lang"
@mkdir -p "/t/openttd-$(RELEASE)-morphos/scenario"
@cp -R $(TTD) "/t/openttd-$(RELEASE)-morphos/"
@cp data/* "/t/openttd-$(RELEASE)-morphos/data/"
@cp lang/*.lng "/t/openttd-$(RELEASE)-morphos/lang/"
@cp scenario/* "/t/openttd-$(RELEASE)-morphos/scenario/"
@cp readme.txt "/t/openttd-$(RELEASE)-morphos/docs/ReadMe"
@cp docs/console.txt "/t/openttd-$(RELEASE)-morphos/docs/Console"
@cp COPYING "/t/openttd-$(RELEASE)-morphos/docs/"
@cp changelog.txt "/t/openttd-$(RELEASE)-morphos/docs/ChangeLog"
@cp known-bugs.txt "/t/openttd-$(RELEASE)-morphos/docs/known-bugs.txt"
@cp os/morphos/icons/openttd.info "/t/openttd-$(RELEASE)-morphos/$(TTD).info"
@cp os/morphos/icons/docs.info "/t/openttd-$(RELEASE)-morphos/docs.info"
@cp os/morphos/icons/drawer.info "/t/openttd-$(RELEASE)-morphos.info"
@cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/ReadMe.info"
@cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/Console.info"
@cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/COPYING.info"
@cp os/morphos/icons/document.info "/t/openttd-$(RELEASE)-morphos/docs/ChangeLog.info"
@strip --strip-all --strip-unneeded --remove-section .comment "/t/openttd-$(RELEASE)-morphos/$(TTD)"
@lha a -r "t:openttd-$(RELEASE)-morphos.lha" "t:openttd-$(RELEASE)-morphos"
@lha a "t:openttd-$(RELEASE)-morphos.lha" "t:openttd-$(RELEASE)-morphos.info"
@rm -fr "/t/openttd-$(RELEASE)-morphos"
@rm -fr "/t/openttd-$(RELEASE)-morphos.info"
@echo "Release archive can be found in RAM:t/ now."
.PHONY: release
.PHONY: release
endif
ifdef OSX
release: all
$(Q)mkdir -p "OpenTTD $(RELEASE)"
$(Q)mkdir -p "OpenTTD $(RELEASE)"/docs
$(Q)mkdir -p "OpenTTD $(RELEASE)"/scenario
$(Q)cp -R $(OSXAPP) "OpenTTD $(RELEASE)"/
$(Q)cp docs/OSX_where_did_the_package_go.txt "OpenTTD $(RELEASE)"/Where\ did\ the\ package\ go.txt
$(Q)cp readme.txt "OpenTTD $(RELEASE)"/docs/
$(Q)cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD $(RELEASE)"/docs/readme\ if\ crashed\ on\ OSX.txt
$(Q)cp docs/console.txt "OpenTTD $(RELEASE)"/docs/
$(Q)cp COPYING "OpenTTD $(RELEASE)"/docs/
$(Q)cp changelog.txt "OpenTTD $(RELEASE)"/docs/
$(Q)cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD $(RELEASE)"/docs/
$(Q)cp os/macosx/*.webloc "OpenTTD $(RELEASE)"
$(Q)cp known-bugs.txt "OpenTTD $(RELEASE)"/known-bugs.txt
$(Q)cp scenario/* "OpenTTD $(RELEASE)"/scenario/
$(Q)/usr/bin/hdiutil create -ov -format UDZO -srcfolder "OpenTTD $(RELEASE)" openttd-"$(RELEASE)"-osx.dmg
$(Q)rm -fr "OpenTTD $(RELEASE)"
@mkdir -p "OpenTTD $(RELEASE)"
@mkdir -p "OpenTTD $(RELEASE)"/docs
@mkdir -p "OpenTTD $(RELEASE)"/scenario
@cp -R $(OSXAPP) "OpenTTD $(RELEASE)"/
@cp docs/OSX_where_did_the_package_go.txt "OpenTTD $(RELEASE)"/Where\ did\ the\ package\ go.txt
@cp readme.txt "OpenTTD $(RELEASE)"/docs/
@cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD $(RELEASE)"/docs/readme\ if\ crashed\ on\ OSX.txt
@cp docs/console.txt "OpenTTD $(RELEASE)"/docs/
@cp COPYING "OpenTTD $(RELEASE)"/docs/
@cp changelog.txt "OpenTTD $(RELEASE)"/docs/
@cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD $(RELEASE)"/docs/
@cp os/macos/*.webloc "OpenTTD $(RELEASE)"
@cp known-bugs.txt "OpenTTD $(RELEASE)"/known-bugs.txt
@cp scenario/* "OpenTTD $(RELEASE)"/scenario/
@/usr/bin/hdiutil create -ov -format UDZO -srcfolder "OpenTTD $(RELEASE)" openttd-"$(RELEASE)"-osx.dmg
@rm -fr "OpenTTD $(RELEASE)"
nightly_build: all
$(Q)mkdir -p "OpenTTD_nightly_$(DATE)"
$(Q)mkdir -p "OpenTTD_nightly_$(DATE)"/docs
$(Q)cp -R $(OSXAPP) "OpenTTD_nightly_$(DATE)"/
$(Q)cp docs/OSX_where_did_the_package_go.txt "OpenTTD_nightly_$(DATE)"/Where\ did\ the\ package\ go.txt
$(Q)cp readme.txt "OpenTTD_nightly_$(DATE)"/docs/
$(Q)cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD_nightly_$(DATE)"/docs/readme\ if\ crashed\ on\ OSX.txt
$(Q)cp docs/console.txt "OpenTTD_nightly_$(DATE)"/docs/
$(Q)cp COPYING "OpenTTD_nightly_$(DATE)"/docs/
$(Q)cp revisionlog.txt "OpenTTD_nightly_$(DATE)"/revisionlog.txt
$(Q)cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD_nightly_$(DATE)"/docs/
$(Q)cp os/macosx/*.webloc "OpenTTD_nightly_$(DATE)"/
$(Q)/usr/bin/hdiutil create -ov -format UDZO -srcfolder "OpenTTD_nightly_$(DATE)" openttd-nightly-"$(DATE)".dmg
$(Q)rm -fr "OpenTTD_nightly_$(DATE)"
@mkdir -p "OpenTTD_nightly_$(DATE)"
@mkdir -p "OpenTTD_nightly_$(DATE)"/docs
@cp -R $(OSXAPP) "OpenTTD_nightly_$(DATE)"/
@cp docs/OSX_where_did_the_package_go.txt "OpenTTD_nightly_$(DATE)"/Where\ did\ the\ package\ go.txt
@cp readme.txt "OpenTTD_nightly_$(DATE)"/docs/
@cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD_nightly_$(DATE)"/docs/readme\ if\ crashed\ on\ OSX.txt
@cp docs/console.txt "OpenTTD_nightly_$(DATE)"/docs/
@cp COPYING "OpenTTD_nightly_$(DATE)"/docs/
@cp revisionlog.txt "OpenTTD_nightly_$(DATE)"/revisionlog.txt
@cp docs/README_if_game_crashed_on_OSX.txt "OpenTTD_nightly_$(DATE)"/docs/
@cp os/macos/*.webloc "OpenTTD_nightly_$(DATE)"/
@/usr/bin/hdiutil create -ov -format UDZO -srcfolder "OpenTTD_nightly_$(DATE)" openttd-nightly-"$(DATE)".dmg
@rm -fr "OpenTTD_nightly_$(DATE)"
.PHONY: release nightly_build
endif
@@ -927,44 +854,43 @@ FORCE:
clean:
@echo '===> Cleaning up'
# endian.h is out-dated and no longer in use, so it can be removed soon
$(Q)rm -rf .deps *~ $(TTD) $(STRGEN) core table/strings.h $(LANGS) $(OBJS) $(OSX_MIDI_PLAYER_FILE) endian.h endian_host.h endian_target.h $(ENDIAN_CHECK)
@rm -rf .deps *~ $(TTD) $(STRGEN) core table/strings.h $(LANGS) $(ttd_OBJS) endian.h $(ENDIAN_CHECK)
mrproper: clean
$(Q)rm -rf $(MAKE_CONFIG)
@rm -rf $(MAKE_CONFIG)
ifndef OSX
ifndef MORPHOS
install:
ifeq ($(INSTALL),)
$(error make install is highly experimental at his state and not\
tested very much - use at your own risk - to use run \"make install INSTALL:=1\" - make sure Makefile.config\
tested very much - use at your own risk - to use run \"make install INSTALL:=1\" - make sure makefile.config\
is set correctly up - run \"make upgradeconf\")
endif
ifeq ($(PREFIX), )
$(error no prefix set - check Makefile.config)
$(error no prefix set - check makefile.config)
endif
# We compare against the non prefixed version here, so we won't install
# if only the prefix has been set
ifeq ($(DATA_DIR),)
$(error no data path set - check Makefile.config)
$(error no data path set - check makefile.config)
endif
ifeq ($(BINARY_DIR),)
$(error no binary path set - check Makefile.config)
$(error no binary path set - check makefile.config)
endif
# We'll install in $DEST_DIR instead of root if it is set (we don't
# care about extra /'s
install -d $(DATA_DIR_INSTALL)/lang \
$(DATA_DIR_INSTALL)/data \
$(DATA_DIR_INSTALL)/gm \
$(BINARY_DIR_INSTALL)
mkdir -p $(PERSONAL_DIR)/scenario
install $(TTD) $(BINARY_DIR_INSTALL)
install -m 644 lang/*.lng $(DATA_DIR_INSTALL)/lang
install -m 644 data/*.grf $(DATA_DIR_INSTALL)/data
install -m 644 data/opntitle.dat $(DATA_DIR_INSTALL)/data
install -m 644 media/openttd.64.png $(DATA_DIR_INSTALL)
mkdir -p $(DATA_DIR_INSTALL)/lang
mkdir -p $(DATA_DIR_INSTALL)/data
mkdir -p $(DATA_DIR_INSTALL)/gm
mkdir -p $(BINARY_DIR_INSTALL)
mkdir -p $(PERSONAL_DIR)/scenario
cp $(TTD) $(BINARY_DIR_INSTALL)
cp lang/*.lng $(DATA_DIR_INSTALL)/lang
cp data/*.grf $(DATA_DIR_INSTALL)/data
cp data/opntitle.dat $(DATA_DIR_INSTALL)/data
cp media/openttd.64.png $(DATA_DIR_INSTALL)
cp scenario/* $(PERSONAL_DIR)/scenario/
else #MorphOS
install:
@@ -989,8 +915,8 @@ love:
# Export all variables set to subprocesses (a bit dirty)
.EXPORT_ALL_VARIABLES:
upgradeconf: $(MAKE_CONFIG)
$(Q)rm $(MAKE_CONFIG)
$(Q)$(MAKE) $(MAKE_CONFIG)
@rm $(MAKE_CONFIG)
@$(MAKE) $(MAKE_CONFIG)
.PHONY: upgradeconf
@@ -1001,27 +927,25 @@ upgradeconf: $(MAKE_CONFIG)
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
# Introduce the dependencies
-include $(DEPS)
-include $(ttd_DEPS)
# This compiles the object file as well as silently updating its dependencies
# list at the same time. It is not an issue that they aren't around during the
# first compilation round as we just build everything at that time anyway,
# therefore we do not need to watch deps.
%.o: %.c $(MAKE_CONFIG) endian_target.h table/strings.h
$(call cmd,c_compile)
@mv $(<:%.c=%.d) $(<:%.c=.deps/%.d)
%.o: %.cpp $(MAKE_CONFIG) endian_target.h table/strings.h
$(call cmd,cxx_compile)
@mv $(<:%.cpp=%.d) $(<:%.cpp=.deps/%.d)
%.o: %.c $(MAKE_CONFIG) endian.h table/strings.h
@echo '===> Compiling $<'
@$(if $(VERBOSE), echo '$(C_BUILD) $<')
@$(C_BUILD) $< -Wp,-MD,.deps/$(*F).pp
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
# Silence stale header dependencies
%.h:
@true
info:
@echo 'CFLAGS = $(CFLAGS)'
@echo 'LDFLAGS = $(LDFLAGS)'
@echo 'LIBS = $(LIBS)'
# For DirectMusic build and BeOS specific parts
%.o: %.cpp $(MAKE_CONFIG) endian.h table/strings.h
@echo '===> Compiling $<'
@$(CXX_BUILD) $< -o $@

237
ai.c
View File

@@ -1,7 +1,6 @@
#include "stdafx.h"
#include "ttd.h"
#include "map.h"
#include "tile.h"
#include "player.h"
#include "vehicle.h"
#include "engine.h"
@@ -12,7 +11,6 @@
#include "pathfind.h"
#include "economy.h"
#include "airport.h"
#include "depot.h"
// remove some day perhaps?
static Player *_cur_ai_player;
@@ -117,11 +115,11 @@ static void AiStateVehLoop(Player *p)
p->ai.state_counter = 0;
}
static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex tile)
static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag)
{
int best_veh_index = -1;
byte best_veh_score = 0;
int32 ret;
int32 r;
int i;
for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
@@ -132,8 +130,10 @@ static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex
|| !HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
continue;
ret = DoCommandByTile(tile, i, 0, 0, CMD_BUILD_RAIL_VEHICLE);
if (!CmdFailed(ret) && (!(_cmd_build_rail_veh_var1&1) || !(flag&1)) && ret <= money &&
r = DoCommandByTile(0, i, 0, 0, CMD_BUILD_RAIL_VEHICLE);
if (r != CMD_ERROR &&
(!(_cmd_build_rail_veh_var1&1) || !(flag&1)) &&
r <= money &&
_cmd_build_rail_veh_score >= best_veh_score) {
best_veh_score = _cmd_build_rail_veh_score;
best_veh_index = i;
@@ -143,11 +143,11 @@ static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex
return best_veh_index;
}
static int AiChooseRoadVehToBuild(byte cargo, int32 money, TileIndex tile)
static int AiChooseRoadVehToBuild(byte cargo, int32 money)
{
int best_veh_index = -1;
int32 best_veh_cost = 0;
int32 ret;
int32 r;
int i = _cargoc.ai_roadveh_start[cargo];
int end = i + _cargoc.ai_roadveh_count[cargo];
@@ -156,9 +156,9 @@ static int AiChooseRoadVehToBuild(byte cargo, int32 money, TileIndex tile)
if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D)
continue;
ret = DoCommandByTile(tile, i, 0, 0, CMD_BUILD_ROAD_VEH);
if (!CmdFailed(ret) && ret <= money && ret >= best_veh_cost) {
best_veh_cost = ret;
r = DoCommandByTile(0, i, 0, 0, CMD_BUILD_ROAD_VEH);
if (r != CMD_ERROR && r <= money && r >= best_veh_cost) {
best_veh_cost = r;
best_veh_index = i;
}
} while (++e, ++i != end);
@@ -170,7 +170,7 @@ static int AiChooseAircraftToBuild(int32 money, byte flag)
{
int best_veh_index = -1;
int32 best_veh_cost = 0;
int32 ret;
int32 r;
int i = AIRCRAFT_ENGINES_INDEX;
int end = i + NUM_AIRCRAFT_ENGINES;
@@ -185,9 +185,9 @@ static int AiChooseAircraftToBuild(int32 money, byte flag)
if (i>=253) continue;
}
ret = DoCommandByTile(0, i, 0, 0, CMD_BUILD_AIRCRAFT);
if (!CmdFailed(ret) && ret <= money && ret >= best_veh_cost) {
best_veh_cost = ret;
r = DoCommandByTile(0, i, 0, 0, CMD_BUILD_AIRCRAFT);
if (r != CMD_ERROR && r <= money && r >= best_veh_cost) {
best_veh_cost = r;
best_veh_index = i;
}
} while (++e, ++i != end);
@@ -217,7 +217,7 @@ static int AiChooseShipToBuild(byte cargo, int32 money)
static int AiChooseRoadVehToReplaceWith(Player *p, Vehicle *v)
{
int32 avail_money = p->player_money + v->value;
return AiChooseRoadVehToBuild(v->cargo_type, avail_money, v->tile);
return AiChooseRoadVehToBuild(v->cargo_type, avail_money);
}
static int AiChooseAircraftToReplaceWith(Player *p, Vehicle *v)
@@ -237,7 +237,7 @@ static int AiChooseTrainToReplaceWith(Player *p, Vehicle *v)
}
// XXX: check if a wagon
return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0, v->tile);
return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0);
}
static int AiChooseShipToReplaceWith(Player *p, Vehicle *v)
@@ -270,7 +270,7 @@ static void AiRestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
int i;
for (i = 0; bak->order[i].type != OT_NOTHING; i++)
if (CmdFailed(DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)))
if (!DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK))
break;
}
@@ -282,7 +282,7 @@ static void AiHandleReplaceTrain(Player *p)
uint tile;
// wait until the vehicle reaches the depot.
if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT);
return;
}
@@ -292,8 +292,8 @@ static void AiHandleReplaceTrain(Player *p)
BackupVehicleOrders(v, orderbak);
tile = v->tile;
if (!CmdFailed(DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON)) &&
!CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE)) ) {
if (DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON) != CMD_ERROR &&
DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE) != CMD_ERROR) {
veh = _new_train_id;
AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN);
@@ -310,7 +310,7 @@ static void AiHandleReplaceRoadVeh(Player *p)
int veh;
uint tile;
if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT);
return;
}
@@ -320,8 +320,8 @@ static void AiHandleReplaceRoadVeh(Player *p)
BackupVehicleOrders(v, orderbak);
tile = v->tile;
if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH)) &&
!CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH)) ) {
if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH) != CMD_ERROR &&
DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH) != CMD_ERROR) {
veh = _new_roadveh_id;
AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
@@ -348,8 +348,8 @@ static void AiHandleReplaceAircraft(Player *p)
BackupVehicleOrders(v, orderbak);
tile = v->tile;
if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT)) &&
!CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT)) ) {
if (DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT) != CMD_ERROR &&
DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT) != CMD_ERROR) {
veh = _new_aircraft_id;
AiRestoreVehicleOrders(GetVehicle(veh), orderbak);
DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT);
@@ -461,7 +461,7 @@ static void AiFindSubsidyIndustryRoute(FoundRoute *fr)
to_xy = to_ind->xy;
}
fr->distance = DistanceManhattan(from->xy, to_xy);
fr->distance = GetTileDist(from->xy, to_xy);
}
static void AiFindSubsidyPassengerRoute(FoundRoute *fr)
@@ -492,7 +492,7 @@ static void AiFindSubsidyPassengerRoute(FoundRoute *fr)
if (from->population < 400 || to->population < 400)
return;
fr->distance = DistanceManhattan(from->xy, to->xy);
fr->distance = GetTileDist(from->xy, to->xy);
}
static void AiFindRandomIndustryRoute(FoundRoute *fr)
@@ -530,7 +530,7 @@ static void AiFindRandomIndustryRoute(FoundRoute *fr)
return;
fr->to = i2;
fr->distance = DistanceManhattan(i->xy, i2->xy);
fr->distance = GetTileDist(i->xy, i2->xy);
} else {
// pick a dest town, and see if it's big enough
t = AiFindRandomTown();
@@ -538,7 +538,7 @@ static void AiFindRandomIndustryRoute(FoundRoute *fr)
return;
fr->to = t;
fr->distance = DistanceManhattan(i->xy, t->xy);
fr->distance = GetTileDist(i->xy, t->xy);
}
}
@@ -560,7 +560,7 @@ static void AiFindRandomPassengerRoute(FoundRoute *fr)
if (dest == NULL || source == dest || dest->population < 400)
return;
fr->distance = DistanceManhattan(source->xy, dest->xy);
fr->distance = GetTileDist(source->xy, dest->xy);
}
// Warn: depends on 'xy' being the first element in both Town and Industry
@@ -579,9 +579,9 @@ static bool AiCheckIfRouteIsGood(Player *p, FoundRoute *fr, byte bitmask)
dist = 0xFFFF;
FOR_ALL_STATIONS(st) if (st->xy != 0 && st->owner == _current_player) {
cur = DistanceMax(from_tile, st->xy);
cur = GetTileDist1D(from_tile, st->xy);
if (cur < dist) dist = cur;
cur = DistanceMax(to_tile, st->xy);
cur = GetTileDist1D(to_tile, st->xy);
if (cur < dist) dist = cur;
if (to_tile == from_tile && st->xy == to_tile)
same_station++;
@@ -1418,7 +1418,7 @@ static void AiWantOilRigAircraftRoute(Player *p)
// Find a random oil rig industry
in = GetIndustry(RandomRange(_total_industries));
if (in != NULL && in->type == IT_OIL_RIG) {
if (DistanceManhattan(t->xy, in->xy) < 60)
if (GetTileDist(t->xy, in->xy) < 60)
break;
}
}
@@ -1565,7 +1565,7 @@ static bool AiCheckTrackResources(TileIndex tile, const AiDefaultBlockData *p, b
static int32 AiDoBuildDefaultRailTrack(TileIndex tile, const AiDefaultBlockData *p, byte flag)
{
int32 ret;
int32 r;
int32 total_cost = 0;
Town *t = NULL;
int rating = 0;
@@ -1580,14 +1580,14 @@ static int32 AiDoBuildDefaultRailTrack(TileIndex tile, const AiDefaultBlockData
if (p->mode < 2) {
if (p->mode == 0) {
// Depot
ret = DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, p->attr, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_TRAIN_DEPOT);
r = DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, p->attr, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_TRAIN_DEPOT);
} else {
// Station
ret = DoCommandByTile(c, (p->attr&1) | (p->attr>>4)<<8 | (p->attr>>1&7)<<16, _cur_ai_player->ai.railtype_to_use, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_RAILROAD_STATION);
r = DoCommandByTile(c, (p->attr&1) | (p->attr>>4)<<8 | (p->attr>>1&7)<<16, _cur_ai_player->ai.railtype_to_use, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_RAILROAD_STATION);
}
if (CmdFailed(ret)) return CMD_ERROR;
total_cost += ret;
if (r == CMD_ERROR) return CMD_ERROR;
total_cost += r;
clear_town_stuff:;
if (_cleared_town != NULL) {
@@ -1608,35 +1608,36 @@ clear_town_stuff:;
for(i=0; i!=6; i++,j>>=1) {
if (j&1) {
k = i;
ret = DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, i, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
if (CmdFailed(ret)) return CMD_ERROR;
total_cost += ret;
r = DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, i, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
if (r == CMD_ERROR) return CMD_ERROR;
total_cost += r;
}
}
/* signals too? */
if (j&3) {
// Can't build signals on a road.
if (IsTileType(c, MP_STREET)) return CMD_ERROR;
if (IsTileType(c, MP_STREET))
return CMD_ERROR;
if (flag & DC_EXEC) {
j = 4 - j;
do {
ret = DoCommandByTile(c, k, 0, flag, CMD_BUILD_SIGNALS);
r = DoCommandByTile(c, k, 0, flag, CMD_BUILD_SIGNALS);
} while (--j);
} else {
ret = _price.build_signals;
r = _price.build_signals;
}
if (CmdFailed(ret)) return CMD_ERROR;
total_cost += ret;
if (r == CMD_ERROR) return CMD_ERROR;
total_cost += r;
}
} else if (p->mode == 3) {
//Clear stuff and then build single rail.
if (GetTileSlope(c,NULL) != 0)
return CMD_ERROR;
ret = DoCommandByTile(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) return CMD_ERROR;
total_cost += ret + _price.build_rail;
r = DoCommandByTile(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR);
if (r == CMD_ERROR) return CMD_ERROR;
total_cost += r + _price.build_rail;
if (flag & DC_EXEC) {
DoCommandByTile(c, _cur_ai_player->ai.railtype_to_use, p->attr&1, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_SINGLE_RAIL);
@@ -1705,7 +1706,7 @@ static void AiDoTerraformLand(TileIndex tile, int dir, int unk, int mode)
byte old_player;
uint32 r;
uint slope;
uint h;
int h;
old_player = _current_player;
_current_player = OWNER_NONE;
@@ -1841,7 +1842,7 @@ static bool AiEnumFollowTrack(uint tile, AiRailPathFindData *a, int track, uint
return true;
}
if (DistanceMax(tile, a->tile2) < 4)
if (GetTileDist1D(tile, a->tile2) < 4)
a->count++;
return false;
@@ -1960,7 +1961,7 @@ static inline void AiCheckBuildRailBridgeHere(AiRailFinder *arf, TileIndex tile,
// Allow bridges directly over bottom tiles
flag = arf->ti.z == 0;
for(;;) {
if ((TileIndexDiff)tile_new < -TileOffsByDir(dir2)) return; // Wraping around map, no bridge possible!
if (tile_new < -TileOffsByDir(dir2)) return; // Wraping around map, no bridge possible!
tile_new = TILE_MASK(tile_new + TileOffsByDir(dir2));
FindLandscapeHeightByTile(&arf->ti, tile_new);
if (arf->ti.tileh != 0 || arf->ti.type == MP_CLEAR || arf->ti.type == MP_TREES) {
@@ -1973,8 +1974,8 @@ static inline void AiCheckBuildRailBridgeHere(AiRailFinder *arf, TileIndex tile,
}
// Is building a (rail)bridge possible at this place (type doesn't matter)?
if (CmdFailed(DoCommandByTile(tile_new, tile, 0 | arf->player->ai.railtype_to_use << 8,
DC_AUTO, CMD_BUILD_BRIDGE)) )
if (DoCommandByTile(tile_new, tile, arf->player->ai.railtype_to_use<<8,
DC_AUTO, CMD_BUILD_BRIDGE) == CMD_ERROR)
return;
AiBuildRailRecursive(arf, tile_new, dir2);
@@ -1993,7 +1994,7 @@ static inline void AiCheckBuildRailTunnelHere(AiRailFinder *arf, TileIndex tile,
if (arf->ti.tileh == _dir_table_2[p[0]&3] && arf->ti.z!=0) {
int32 cost = DoCommandByTile(tile, arf->player->ai.railtype_to_use, 0, DC_AUTO, CMD_BUILD_TUNNEL);
if (!CmdFailed(cost) && cost <= (arf->player->player_money>>4)) {
if (cost != CMD_ERROR && cost <= (arf->player->player_money>>4)) {
AiBuildRailRecursive(arf, _build_tunnel_endtile, p[0]&3);
if (arf->depth == 1) {
AiCheckRailPathBetter(arf, p);
@@ -2026,7 +2027,7 @@ static void AiBuildRailRecursive(AiRailFinder *arf, TileIndex tile, int dir)
// Depth too deep?
if (arf->depth >= 4) {
uint dist = DistanceMaxPlusManhattan(tile, arf->final_tile);
uint dist = GetTileDist1Db(tile, arf->final_tile);
if (dist < arf->cur_best_dist) {
// Store the tile that is closest to the final position.
arf->cur_best_depth = arf->depth;
@@ -2051,7 +2052,7 @@ static void AiBuildRailRecursive(AiRailFinder *arf, TileIndex tile, int dir)
do {
// Make sure the tile is not in the list of banned tiles and that a rail can be built here.
if (!AiIsTileBanned(arf->player, tile, p[0]) &&
!CmdFailed(DoCommandByTile(tile, arf->player->ai.railtype_to_use, p[0], DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL))) {
DoCommandByTile(tile, arf->player->ai.railtype_to_use, p[0], DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL) != CMD_ERROR) {
AiBuildRailRecursive(arf, tile, p[1]);
}
@@ -2136,16 +2137,16 @@ static void AiBuildRailConstruct(Player *p)
unnecessary to check for worse bridge (i=0), since AI will always build that.
AI is so fucked up that fixing this small thing will probably not solve a thing
*/
for (i = MAX_BRIDGES - 1; i != 0; i--) {
for(i = 10 + (p->ai.railtype_to_use << 8); i != 0; i--) {
if (CheckBridge_Stuff(i, bridge_len)) {
int32 cost = DoCommandByTile(arf.bridge_end_tile, p->ai.cur_tile_a, i | (p->ai.railtype_to_use << 8), DC_AUTO, CMD_BUILD_BRIDGE);
if (!CmdFailed(cost) && cost < (p->player_money >> 5))
int32 cost = DoCommandByTile(arf.bridge_end_tile, p->ai.cur_tile_a, i, DC_AUTO, CMD_BUILD_BRIDGE);
if (cost != CMD_ERROR && cost < (p->player_money >> 5))
break;
}
}
// Build it
DoCommandByTile(arf.bridge_end_tile, p->ai.cur_tile_a, i | (p->ai.railtype_to_use << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
DoCommandByTile(arf.bridge_end_tile, p->ai.cur_tile_a, i, DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
p->ai.cur_tile_a = arf.bridge_end_tile;
p->ai.state_counter = 0;
@@ -2180,7 +2181,7 @@ static bool AiRemoveTileAndGoForward(Player *p)
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
if (!(_map5[tile] & 0x80)) {
// Clear the tunnel and continue at the other side of it.
if (CmdFailed(DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)) )
if (DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR) == CMD_ERROR)
return false;
p->ai.cur_tile_a = TILE_MASK(_build_tunnel_endtile - TileOffsByDir(p->ai.cur_dir_a));
return true;
@@ -2201,7 +2202,7 @@ static bool AiRemoveTileAndGoForward(Player *p)
tilenew = TILE_MASK(tile - offs);
// And clear the bridge.
if (CmdFailed(DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)) )
if (DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR) == CMD_ERROR)
return false;
p->ai.cur_tile_a = tilenew;
return true;
@@ -2223,7 +2224,7 @@ static bool AiRemoveTileAndGoForward(Player *p)
}
// And also remove the rail.
if (CmdFailed(DoCommandByTile(tile, 0, bit, DC_EXEC, CMD_REMOVE_SINGLE_RAIL)) )
if (DoCommandByTile(tile, 0, bit, DC_EXEC, CMD_REMOVE_SINGLE_RAIL) == CMD_ERROR)
return false;
// Find the direction at the other edge of the rail.
@@ -2379,7 +2380,7 @@ static void AiStateBuildRailVeh(Player *p)
if (p->ai.wagon_list[i] == INVALID_VEHICLE) {
veh = _cargoc.ai_railwagon[p->ai.railtype_to_use][cargo];
cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE);
if (CmdFailed(cost)) goto handle_nocash;
if (cost == CMD_ERROR) goto handle_nocash;
p->ai.wagon_list[i] = _new_wagon_id;
p->ai.wagon_list[i+1] = INVALID_VEHICLE;
return;
@@ -2391,14 +2392,14 @@ static void AiStateBuildRailVeh(Player *p)
}
// Which locomotive to build?
veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, (cargo!=CT_PASSENGERS)?1:0, tile);
veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, (cargo!=CT_PASSENGERS)?1:0);
if (veh == -1) {
handle_nocash:
// after a while, if AI still doesn't have cash, get out of this block by selling the wagons.
if (++p->ai.state_counter == 1000) {
for(i=0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) {
cost = DoCommandByTile(tile, p->ai.wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
assert(!CmdFailed(cost));
assert(cost != CMD_ERROR);
}
p->ai.state = AIS_0;
}
@@ -2407,7 +2408,7 @@ handle_nocash:
// Try to build the locomotive
cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE);
assert(!CmdFailed(cost));
assert(cost != CMD_ERROR);
loco_id = _new_train_id;
// Sell a vehicle if the train is double headed.
@@ -2528,7 +2529,7 @@ static int AiFindBestDefaultRoadBlock(TileIndex tile, byte direction, byte cargo
static int32 AiDoBuildDefaultRoadBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag)
{
int32 ret;
int32 r;
int32 total_cost = 0;
Town *t = NULL;
int rating = 0;
@@ -2550,29 +2551,30 @@ static int32 AiDoBuildDefaultRoadBlock(TileIndex tile, const AiDefaultBlockData
continue;
}
ret = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
if (CmdFailed(ret)) return CMD_ERROR;
total_cost += ret;
r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
if (r == CMD_ERROR)
return CMD_ERROR;
total_cost += r;
continue;
}
if (p->mode == 0) {
// Depot
ret = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_DEPOT);
r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_DEPOT);
goto clear_town_stuff;
} else if (p->mode == 1) {
if (_want_road_truck_station) {
// Truck station
ret = DoCommandByTile(c, p->attr, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_STOP);
r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_TRUCK_STATION);
} else {
// Bus station
ret = DoCommandByTile(c, p->attr, RS_BUS, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_STOP);
r = DoCommandByTile(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_BUS_STATION);
}
clear_town_stuff:;
if (CmdFailed(ret)) return CMD_ERROR;
total_cost += ret;
if (r == CMD_ERROR) return CMD_ERROR;
total_cost += r;
if (_cleared_town != NULL) {
if (t != NULL && t != _cleared_town)
@@ -2588,8 +2590,8 @@ clear_town_stuff:;
return CMD_ERROR;
if (!(IsTileType(c, MP_STREET) && (_map5[c] & 0xF0) == 0)) {
ret = DoCommandByTile(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) return CMD_ERROR;
r = DoCommandByTile(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR);
if (r == CMD_ERROR) return CMD_ERROR;
}
}
@@ -2617,7 +2619,7 @@ static bool AiCheckBlockDistances(Player *p, TileIndex tile)
do {
if (aib->cur_building_rule != 255) {
if (DistanceManhattan(aib->use_tile, tile) < 9)
if (GetTileDist(aib->use_tile, tile) < 9)
return false;
}
} while (++aib, --num);
@@ -2765,7 +2767,7 @@ static bool AiCheckRoadPathBetter(AiRoadFinder *arf, const byte *p)
static bool AiEnumFollowRoad(uint tile, AiRoadEnum *a, int track, uint length, byte *state)
{
uint dist = DistanceManhattan(tile, a->dest);
uint dist = GetTileDist(tile, a->dest);
uint tile2;
if (dist <= a->best_dist) {
@@ -2810,7 +2812,7 @@ static bool AiCheckRoadFinished(Player *p)
FollowTrack(tile, 0x3000 | TRANSPORT_ROAD, _dir_by_track[i], (TPFEnumProc*)AiEnumFollowRoad, NULL, &are);
}
if (DistanceManhattan(tile, are.dest) <= are.best_dist)
if (GetTileDist(tile, are.dest) <= are.best_dist)
return false;
if (are.best_dist == 0)
@@ -2832,7 +2834,7 @@ static bool AiBuildRoadHelper(uint tile, int flags, int type)
1+2,
8+4,
};
return !CmdFailed(DoCommandByTile(tile, _road_bits[type], 0, flags, CMD_BUILD_ROAD));
return DoCommandByTile(tile, _road_bits[type], 0, flags, CMD_BUILD_ROAD) != CMD_ERROR;
}
static inline void AiCheckBuildRoadBridgeHere(AiRoadFinder *arf, TileIndex tile, const byte *p)
@@ -2848,7 +2850,7 @@ static inline void AiCheckBuildRoadBridgeHere(AiRoadFinder *arf, TileIndex tile,
// Allow bridges directly over bottom tiles
flag = arf->ti.z == 0;
for(;;) {
if ((TileIndexDiff)tile_new < -TileOffsByDir(dir2)) return; // Wraping around map, no bridge possible!
if (tile_new < -TileOffsByDir(dir2)) return; // Wraping around map, no bridge possible!
tile_new = TILE_MASK(tile_new + TileOffsByDir(dir2));
FindLandscapeHeightByTile(&arf->ti, tile_new);
if (arf->ti.tileh != 0 || arf->ti.type == MP_CLEAR || arf->ti.type == MP_TREES) {
@@ -2863,7 +2865,7 @@ static inline void AiCheckBuildRoadBridgeHere(AiRoadFinder *arf, TileIndex tile,
}
// Is building a (rail)bridge possible at this place (type doesn't matter)?
if (CmdFailed(DoCommandByTile(tile_new, tile, 0x8000, DC_AUTO, CMD_BUILD_BRIDGE)))
if (DoCommandByTile(tile_new, tile, 0x8000, DC_AUTO, CMD_BUILD_BRIDGE) == CMD_ERROR)
return;
AiBuildRoadRecursive(arf, tile_new, dir2);
@@ -2882,7 +2884,7 @@ static inline void AiCheckBuildRoadTunnelHere(AiRoadFinder *arf, TileIndex tile,
if (arf->ti.tileh == _dir_table_2[p[0]&3] && arf->ti.z!=0) {
int32 cost = DoCommandByTile(tile, 0x200, 0, DC_AUTO, CMD_BUILD_TUNNEL);
if (!CmdFailed(cost) && cost <= (arf->player->player_money>>4)) {
if (cost != CMD_ERROR && cost <= (arf->player->player_money>>4)) {
AiBuildRoadRecursive(arf, _build_tunnel_endtile, p[0]&3);
if (arf->depth == 1) {
AiCheckRoadPathBetter(arf, p);
@@ -2910,7 +2912,7 @@ static void AiBuildRoadRecursive(AiRoadFinder *arf, TileIndex tile, int dir)
// Depth too deep?
if (arf->depth >= 4) {
uint dist = DistanceMaxPlusManhattan(tile, arf->final_tile);
uint dist = GetTileDist1Db(tile, arf->final_tile);
if (dist < arf->cur_best_dist) {
// Store the tile that is closest to the final position.
arf->cur_best_dist = dist;
@@ -3022,7 +3024,7 @@ do_some_terraform:
for(i = 10; i != 0; i--) {
if (CheckBridge_Stuff(i, bridge_len)) {
int32 cost = DoCommandByTile(tile, p->ai.cur_tile_a, i + (0x80 << 8), DC_AUTO, CMD_BUILD_BRIDGE);
if (!CmdFailed(cost) && cost < (p->player_money >> 5))
if (cost != CMD_ERROR && cost < (p->player_money >> 5))
break;
}
}
@@ -3164,18 +3166,21 @@ static void AiStateBuildRoadVehicles(Player *p)
const AiDefaultBlockData *ptr;
uint tile,loco_id;
int veh, i;
int32 cost;
ptr = _road_default_block_data[p->ai.src.cur_building_rule]->data;
for(;ptr->mode != 0;ptr++) {}
tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs));
veh = AiChooseRoadVehToBuild(p->ai.cargo_type, p->player_money, tile);
veh = AiChooseRoadVehToBuild(p->ai.cargo_type, p->player_money);
if (veh == -1) {
p->ai.state = AIS_0;
return;
}
if (CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH))) return;
cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH);
if (cost == CMD_ERROR)
return;
loco_id = _new_roadveh_id;
@@ -3286,7 +3291,7 @@ static void AiStateAirportStuff(Player *p)
continue;
// Dismiss airports too far away.
if (DistanceMax(st->airport_tile, aib->spec_tile) > aib->rand_rng)
if (GetTileDist1D(st->airport_tile, aib->spec_tile) > aib->rand_rng)
continue;
// It's ideal airport, let's take it!
@@ -3329,14 +3334,15 @@ static void AiStateAirportStuff(Player *p)
static int32 AiDoBuildDefaultAirportBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag)
{
int32 total_cost = 0, ret;
int32 total_cost = 0, r;
for(;p->mode == 0;p++) {
if (!HASBIT(_avail_aircraft, p->attr))
return CMD_ERROR;
ret = DoCommandByTile(TILE_MASK(tile + ToTileIndexDiff(p->tileoffs)), p->attr,0,flag | DC_AUTO | DC_NO_WATER,CMD_BUILD_AIRPORT);
if (CmdFailed(ret)) return CMD_ERROR;
total_cost += ret;
r = DoCommandByTile(TILE_MASK(tile + ToTileIndexDiff(p->tileoffs)), p->attr,0,flag | DC_AUTO | DC_NO_WATER,CMD_BUILD_AIRPORT);
if (r == CMD_ERROR)
return CMD_ERROR;
total_cost += r;
}
return total_cost;
@@ -3481,6 +3487,7 @@ static void AiStateBuildAircraftVehicles(Player *p)
const AiDefaultBlockData *ptr;
uint tile;
int veh;
int32 cost;
int i;
uint loco_id;
@@ -3494,7 +3501,9 @@ static void AiStateBuildAircraftVehicles(Player *p)
return;
}
if (CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) return;
cost = DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT);
if (cost == CMD_ERROR)
return;
loco_id = _new_aircraft_id;
for(i=0; p->ai.order_list_blocks[i] != 0xFF; i++) {
@@ -3550,7 +3559,7 @@ static void AiStateSellVeh(Player *p)
if (v->owner == _current_player) {
if (v->type == VEH_Train) {
if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
if (v->current_order.type != OT_GOTO_DEPOT)
DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_TRAIN_GOTO_DEPOT);
goto going_to_depot;
@@ -3560,7 +3569,7 @@ static void AiStateSellVeh(Player *p)
DoCommandByTile(v->tile, v->index, 1, DC_EXEC, CMD_SELL_RAIL_WAGON);
} else if (v->type == VEH_Road) {
if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
if (v->current_order.type != OT_GOTO_DEPOT)
DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
goto going_to_depot;
@@ -3598,29 +3607,27 @@ return_to_loop:;
static void AiStateRemoveStation(Player *p)
{
// Remove stations that aren't in use by any vehicle
byte *in_use;
const byte *used;
byte in_use[256], *used;
const Order *ord;
const Station *st;
TileIndex tile;
Station *st;
uint tile;
// Go to this state when we're done.
p->ai.state = AIS_1;
// Get a list of all stations that are in use by a vehicle
in_use = malloc(GetStationPoolSize());
memset(in_use, 0, GetStationPoolSize());
memset(in_use, 0, sizeof(in_use));
FOR_ALL_ORDERS(ord) {
if (ord->type == OT_GOTO_STATION)
in_use[ord->station] = 1;
}
// Go through all stations and delete those that aren't in use
used = in_use;
used=in_use;
FOR_ALL_STATIONS(st) {
if (st->xy != 0 && st->owner == _current_player && !*used &&
( (st->bus_stops != NULL && (tile = st->bus_stops->xy) != 0) ||
(st->truck_stops != NULL && (tile = st->truck_stops->xy)) != 0 ||
((tile = st->bus_tile) != 0 ||
(tile = st->lorry_tile) != 0 ||
(tile = st->train_tile) != 0 ||
(tile = st->dock_tile) != 0 ||
(tile = st->airport_tile) != 0)) {
@@ -3629,10 +3636,9 @@ static void AiStateRemoveStation(Player *p)
used++;
}
free(in_use);
}
static void AiRemovePlayerRailOrRoad(Player *p, TileIndex tile)
static void AiRemovePlayerRailOrRoad(Player *p, uint tile)
{
byte m5;
@@ -3750,14 +3756,13 @@ pos_3:
static void AiStateRemoveTrack(Player *p)
{
/* Was 1000 for standard 8x8 maps. */
int num = MapSizeX() * 4;
int num = 1000;
do {
TileIndex tile = ++p->ai.state_counter;
uint tile = ++p->ai.state_counter;
// Iterated all tiles?
if (tile >= MapSize()) {
if (tile == 0) {
p->ai.state = AIS_REMOVE_STATION;
return;
}
@@ -3882,14 +3887,14 @@ static void AiAdjustLoan(Player *p)
if (p->player_money > base * 1400) {
// Decrease loan
if (p->current_loan != 0) {
DoCommandByTile(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
DoCommandByTile(0, _current_player, 0, DC_EXEC, CMD_DECREASE_LOAN);
}
} else if (p->player_money < base * 500) {
// Increase loan
if (p->current_loan < _economy.max_loan &&
p->num_valid_stat_ent >= 2 &&
-(p->old_economy[0].expenses+p->old_economy[1].expenses) < base * 60) {
DoCommandByTile(0, 0, 0, DC_EXEC, CMD_INCREASE_LOAN);
DoCommandByTile(0, _current_player, 0, DC_EXEC, CMD_INCREASE_LOAN);
}
}
}

2
ai.h
View File

@@ -37,8 +37,6 @@
#define AI_PATHFINDER_PENALTY 150
// The penalty given to a tile that is going up
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
// The penalty given to a tile which would have to use fundation
#define AI_PATHFINDER_FOUNDATION_PENALTY 100
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
// Same penalty, only for when road already exists

View File

@@ -1,18 +1,15 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "tile.h"
#include "command.h"
#include "ai.h"
#include "engine.h"
#include "station.h"
// Build HQ
// Params:
// tile : tile where HQ is going to be build
bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
if (CmdFailed(DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
if (DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ) == CMD_ERROR)
return false;
DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
return true;
@@ -29,11 +26,10 @@ bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag) {
if (type == AI_TRAIN)
return DoCommandByTile(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
if (type == AI_BUS)
return DoCommandByTile(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
return DoCommandByTile(tile, direction, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
else if (type == AI_BUS)
return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_BUS_STATION);
else
return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRUCK_STATION);
}
// Builds a brdige. The second best out of the ones available for this player
@@ -62,8 +58,8 @@ int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag) {
// Now, simply, build the bridge!
if (p->ainew.tbt == AI_TRAIN)
return DoCommandByTile(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
return DoCommandByTile(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
else
return DoCommandByTile(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
}
@@ -98,7 +94,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
cost += DoCommandByTile(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
if (cost == CMD_ERROR) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
return 0;
}
@@ -109,7 +105,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
if (cost == CMD_ERROR) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
return 0;
}
@@ -127,7 +123,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
old_dir = dir;
// Build the tile
res = DoCommandByTile(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
if (CmdFailed(res)) {
if (res == CMD_ERROR) {
// Problem.. let's just abort it all!
p->ainew.state = AI_STATE_NOTHING;
return 0;
@@ -148,7 +144,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
cost += DoCommandByTile(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
if (cost == CMD_ERROR) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
return 0;
}
@@ -159,7 +155,7 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
if (cost == CMD_ERROR) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
return 0;
}
@@ -182,14 +178,15 @@ int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte fla
// Build the tile
res = DoCommandByTile(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
// Currently, we ignore CMD_ERRORs!
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
// Problem.. let's just abort it all!
DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
p->ainew.state = AI_STATE_NOTHING;
return 0;
}
if (!CmdFailed(res)) cost += res;
if (res == CMD_ERROR && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
// Problem.. let's just abort it all!
DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
p->ainew.state = AI_STATE_NOTHING;
return 0;
} else {
if (res != CMD_ERROR)
cost += res;
}
}
// Go to the next tile
part++;
@@ -213,7 +210,7 @@ int AiNew_PickVehicle(Player *p) {
// Not supported yet
return -1;
} else {
int start, count, i, ret = CMD_ERROR;
int start, count, i, r = CMD_ERROR;
start = _cargoc.ai_roadveh_start[p->ainew.cargo];
count = _cargoc.ai_roadveh_count[p->ainew.cargo];
@@ -223,11 +220,11 @@ int AiNew_PickVehicle(Player *p) {
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
if (!HASBIT(_engines[i].player_avail, _current_player) || _engines[i].reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
// Can we build it?
ret = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
if (!CmdFailed(ret)) break;
r = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
if (r != CMD_ERROR) break;
}
// We did not find a vehicle :(
if (CmdFailed(ret)) { return -1; }
if (r == CMD_ERROR) { return -1; }
return i;
}
}
@@ -237,24 +234,25 @@ int AiNew_Build_Vehicle(Player *p, uint tile, byte flag) {
int i = AiNew_PickVehicle(p);
if (i == -1) return CMD_ERROR;
if (p->ainew.tbt == AI_TRAIN)
if (p->ainew.tbt == AI_TRAIN) {
return CMD_ERROR;
return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
} else {
return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
}
}
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag)
{
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag) {
static const byte _roadbits_by_dir[4] = {2,1,8,4};
int ret, ret2;
if (p->ainew.tbt == AI_TRAIN)
int r, r2;
if (p->ainew.tbt == AI_TRAIN) {
return DoCommandByTile(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
ret = DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
if (CmdFailed(ret)) return ret;
// Try to build the road from the depot
ret2 = DoCommandByTile(tile + TileOffsByDir(direction), _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
// If it fails, ignore it..
if (CmdFailed(ret2)) return ret;
return ret + ret2;
} else {
r = DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
if (r == CMD_ERROR) return r;
// Try to build the road from the depot
r2 = DoCommandByTile(tile + TileOffsByDir(direction), _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
// If it fails, ignore it..
if (r2 == CMD_ERROR) return r;
return r + r2;
}
}

111
ai_new.c
View File

@@ -9,18 +9,14 @@
// TODO: als er iets in path komt, bouwt AI gewoon verder :(
// TODO: mail routes
// FIXME: This code is horrible. Indisputably from the style POV, at least. --pasky
/*
* End of Dutch part
*/
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "command.h"
#include "ai.h"
#include "town.h"
@@ -28,7 +24,6 @@
#include "station.h"
#include "engine.h"
#include "gui.h"
#include "depot.h"
// This function is called after StartUp. It is the init of an AI
static void AiNew_State_FirstTime(Player *p) {
@@ -86,15 +81,15 @@ static void AiNew_State_Nothing(Player *p) {
// - Check route
// - Build HQ
static void AiNew_State_WakeUp(Player *p) {
int32 money;
int c;
assert(p->ainew.state == AI_STATE_WAKE_UP);
int32 money;
int c;
assert(p->ainew.state == AI_STATE_WAKE_UP);
// First, check if we have a HQ
if (p->location_of_house == 0) {
// We have no HQ yet, build one on a random place
// Random till we found a place for it!
// TODO: this should not be on a random place..
AiNew_Build_CompanyHQ(p, Random() % MapSize());
while (!AiNew_Build_CompanyHQ(p, (Random()&0xFFFF))) { }
// Enough for now, but we want to come back here the next time
// so we do not change any status
return;
@@ -183,8 +178,8 @@ static void AiNew_State_WakeUp(Player *p) {
}
static void AiNew_State_ActionDone(Player *p) {
p->ainew.action = AI_ACTION_NONE;
p->ainew.state = AI_STATE_NOTHING;
p->ainew.action = AI_ACTION_NONE;
p->ainew.state = AI_STATE_NOTHING;
}
// Check if a city or industry is good enough to start a route there
@@ -192,7 +187,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
if (type == AI_CITY) {
Town *t = GetTown(ic);
Station *st;
uint count = 0;
int count = 0;
int j = 0;
// We don't like roadconstructions, don't even true such a city
@@ -228,7 +223,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
// to build there
if (!st->goods[CT_PASSENGERS].last_speed) continue;
// Is it around our city
if (DistanceManhattan(st->xy, t->xy) > 10) continue;
if (GetTileDist(st->xy, t->xy) > 10) continue;
// It does take this cargo.. what is his rating?
if (st->goods[CT_PASSENGERS].rating < AI_CHECKCITY_CARGO_RATING) continue;
j++;
@@ -291,7 +286,7 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
// It does not take this cargo
if (!st->goods[i->produced_cargo[0]].last_speed) continue;
// Is it around our industry
if (DistanceManhattan(st->xy, i->xy) > 5) continue;
if (GetTileDist(st->xy, i->xy) > 5) continue;
// It does take this cargo.. what is his rating?
if (st->goods[i->produced_cargo[0]].rating < AI_CHECKCITY_CARGO_RATING) continue;
j++;
@@ -370,11 +365,11 @@ static void AiNew_State_LocateRoute(Player *p) {
// increase the temp with one, and return. We will come back later here
// to try again
p->ainew.temp++;
if (p->ainew.from_type == AI_CITY) {
if (p->ainew.temp >= (int)_total_towns) p->ainew.temp = 0;
} else {
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
}
if (p->ainew.from_type == AI_CITY) {
if (p->ainew.temp >= _total_towns) p->ainew.temp = 0;
} else {
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
}
// Don't do an attempt if we are trying the same id as the last time...
if (p->ainew.last_id == p->ainew.temp) return;
@@ -414,17 +409,12 @@ static void AiNew_State_LocateRoute(Player *p) {
max_cargo -= GetTown(p->ainew.from_ic)->act_pass + GetTown(p->ainew.temp)->act_pass;
// max_cargo is now the amount of cargo we can move between the two cities
// If it is more than the distance, we allow it
if (DistanceManhattan(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
if (GetTileDist(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
// We found a good city/industry, save the data of it
p->ainew.to_ic = p->ainew.temp;
p->ainew.state = AI_STATE_FIND_STATION;
DEBUG(ai,1)(
"[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",
DistanceManhattan(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy),
p->ainew.from_ic,
p->ainew.temp
);
DEBUG(ai,1)("[AiNew - LocateRoute] Found bus-route of %d tiles long (from %d to %d)",GetTileDist(GetTown(p->ainew.from_ic)->xy, GetTown(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp);
p->ainew.from_tile = 0;
p->ainew.to_tile = 0;
@@ -467,8 +457,8 @@ static void AiNew_State_LocateRoute(Player *p) {
if (found) {
// Yeah, they are compatible!!!
// Check the length against the amount of goods
if (DistanceManhattan(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
DistanceManhattan(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
if (GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy) <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
p->ainew.to_ic = p->ainew.temp;
if (p->ainew.from_deliver) {
p->ainew.cargo = GetIndustry(p->ainew.from_ic)->produced_cargo[0];
@@ -477,12 +467,7 @@ static void AiNew_State_LocateRoute(Player *p) {
}
p->ainew.state = AI_STATE_FIND_STATION;
DEBUG(ai,1)(
"[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",
DistanceManhattan(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy),
p->ainew.from_ic,
p->ainew.temp
);
DEBUG(ai,1)("[AiNew - LocateRoute] Found truck-route of %d tiles long (from %d to %d)",GetTileDist(GetIndustry(p->ainew.from_ic)->xy, GetIndustry(p->ainew.temp)->xy), p->ainew.from_ic, p->ainew.temp);
p->ainew.from_tile = 0;
p->ainew.to_tile = 0;
@@ -493,15 +478,15 @@ static void AiNew_State_LocateRoute(Player *p) {
}
}
// It was not a valid city
// increase the temp with one, and return. We will come back later here
// to try again
p->ainew.temp++;
if (p->ainew.to_type == AI_CITY) {
if (p->ainew.temp >= (int)_total_towns) p->ainew.temp = 0;
} else {
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
}
// It was not a valid city
// increase the temp with one, and return. We will come back later here
// to try again
p->ainew.temp++;
if (p->ainew.to_type == AI_CITY) {
if (p->ainew.temp >= _total_towns) p->ainew.temp = 0;
} else {
if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
}
// Don't do an attempt if we are trying the same id as the last time...
if (p->ainew.last_id == p->ainew.temp) return;
@@ -651,7 +636,7 @@ static void AiNew_State_FindStation(Player *p) {
for (x=0;x<i;x++) {
if (found_best[x] > best ||
(found_best[x] == best && DistanceManhattan(tile, new_tile) > DistanceManhattan(tile, found_spot[x]))) {
(found_best[x] == best && GetTileDist(tile, new_tile) > GetTileDist(tile, found_spot[x]))) {
new_tile = found_spot[x];
best = found_best[x];
}
@@ -994,7 +979,7 @@ static void AiNew_State_BuildPath(Player *p) {
// We don't want that, so try building some road left or right of the station
int dir1, dir2, dir3;
TileIndex tile;
int i, ret;
int i, r;
for (i=0;i<2;i++) {
if (i == 0) {
tile = p->ainew.from_tile + TileOffsByDir(p->ainew.from_direction);
@@ -1012,36 +997,36 @@ static void AiNew_State_BuildPath(Player *p) {
dir3 = p->ainew.to_direction;
}
ret = DoCommandByTile(tile, _roadbits_by_dir[dir1], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (!CmdFailed(ret)) {
r = DoCommandByTile(tile, _roadbits_by_dir[dir1], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (r != CMD_ERROR) {
dir1 = TileOffsByDir(dir1);
if (IsTileType(tile + dir1, MP_CLEAR) || IsTileType(tile + dir1, MP_TREES)) {
ret = DoCommandByTile(tile+dir1, AiNew_GetRoadDirection(tile, tile+dir1, tile+dir1+dir1), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (!CmdFailed(ret)) {
r = DoCommandByTile(tile+dir1, AiNew_GetRoadDirection(tile, tile+dir1, tile+dir1+dir1), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (r != CMD_ERROR) {
if (IsTileType(tile + dir1 + dir1, MP_CLEAR) || IsTileType(tile + dir1 + dir1, MP_TREES))
DoCommandByTile(tile+dir1+dir1, AiNew_GetRoadDirection(tile+dir1, tile+dir1+dir1, tile+dir1+dir1+dir1), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
}
}
}
ret = DoCommandByTile(tile, _roadbits_by_dir[dir2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (!CmdFailed(ret)) {
r = DoCommandByTile(tile, _roadbits_by_dir[dir2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (r != CMD_ERROR) {
dir2 = TileOffsByDir(dir2);
if (IsTileType(tile + dir2, MP_CLEAR) || IsTileType(tile + dir2, MP_TREES)) {
ret = DoCommandByTile(tile+dir2, AiNew_GetRoadDirection(tile, tile+dir2, tile+dir2+dir2), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (!CmdFailed(ret)) {
r = DoCommandByTile(tile+dir2, AiNew_GetRoadDirection(tile, tile+dir2, tile+dir2+dir2), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (r != CMD_ERROR) {
if (IsTileType(tile + dir2 + dir2, MP_CLEAR) || IsTileType(tile + dir2 + dir2, MP_TREES))
DoCommandByTile(tile+dir2+dir2, AiNew_GetRoadDirection(tile+dir2, tile+dir2+dir2, tile+dir2+dir2+dir2), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
}
}
}
ret = DoCommandByTile(tile, _roadbits_by_dir[dir3^2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (!CmdFailed(ret)) {
r = DoCommandByTile(tile, _roadbits_by_dir[dir3^2], 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (r != CMD_ERROR) {
dir3 = TileOffsByDir(dir3);
if (IsTileType(tile + dir3, MP_CLEAR) || IsTileType(tile + dir3, MP_TREES)) {
ret = DoCommandByTile(tile+dir3, AiNew_GetRoadDirection(tile, tile+dir3, tile+dir3+dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (!CmdFailed(ret)) {
r = DoCommandByTile(tile+dir3, AiNew_GetRoadDirection(tile, tile+dir3, tile+dir3+dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
if (r != CMD_ERROR) {
if (IsTileType(tile + dir3 + dir3, MP_CLEAR) || IsTileType(tile + dir3 + dir3, MP_TREES))
DoCommandByTile(tile+dir3+dir3, AiNew_GetRoadDirection(tile+dir3, tile+dir3+dir3, tile+dir3+dir3+dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
}
@@ -1169,7 +1154,7 @@ static void AiNew_State_GiveOrders(Player *p) {
idx = 2;
order.type = OT_GOTO_DEPOT;
order.flags = OF_UNLOAD;
order.station = GetDepotByTile(p->ainew.depot_tile)->index;
order.station = GetDepotByTile(p->ainew.depot_tile);
DoCommandByTile(0, p->ainew.veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
}
@@ -1191,7 +1176,7 @@ static void AiNew_State_StartVehicle(Player *p) {
static void AiNew_State_RepayMoney(Player *p) {
int i;
for (i=0;i<AI_LOAN_REPAY;i++)
DoCommandByTile(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
DoCommandByTile(0, _current_player, 0, DC_EXEC, CMD_DECREASE_LOAN);
p->ainew.state = AI_STATE_ACTION_DONE;
}
@@ -1215,7 +1200,7 @@ static void AiNew_CheckVehicle(Player *p, Vehicle *v) {
// We are already sending him back
if (AiNew_GetSpecialVehicleFlag(p, v) & AI_VEHICLEFLAG_SELL) {
if (v->type == VEH_Road && IsTileDepotType(v->tile, TRANSPORT_ROAD) &&
if (v->type == VEH_Road && IsRoadDepotTile(v->tile) &&
(v->vehstatus&VS_STOPPED)) {
// We are at the depot, sell the vehicle
DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
@@ -1225,11 +1210,11 @@ static void AiNew_CheckVehicle(Player *p, Vehicle *v) {
if (!AiNew_SetSpecialVehicleFlag(p, v, AI_VEHICLEFLAG_SELL)) return;
{
int ret = 0;
int res = 0;
if (v->type == VEH_Road)
ret = DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
res = DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
// This means we can not find a depot :s
// if (CmdFailed(ret))
// if (res == CMD_ERROR)
}
}
}

View File

@@ -1,11 +1,8 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "tile.h"
#include "command.h"
#include "ai.h"
#include "depot.h"
#define TEST_STATION_NO_DIR 0xFF
@@ -13,21 +10,22 @@
// TODO: make it train compatible
static bool TestCanBuildStationHere(uint tile, byte dir)
{
Player *p = DEREF_PLAYER(_current_player);
if (dir == TEST_STATION_NO_DIR) {
int32 ret;
// TODO: currently we only allow spots that can be access from al 4 directions...
// should be fixed!!!
for (dir = 0; dir < 4; dir++) {
ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
if (!CmdFailed(ret)) return true;
}
return false;
}
// return true if command succeeded, so the inverse of CmdFailed()
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
Player *p = DEREF_PLAYER(_current_player);
if (dir == TEST_STATION_NO_DIR) {
// TODO: currently we only allow spots that can be access from al 4 directions...
// should be fixed!!!
for (dir=0;dir<4;dir++) {
int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
if (res != CMD_ERROR)
return true;
}
return false;
} else {
int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
if (res == CMD_ERROR)
return false;
}
return true;
}
@@ -35,7 +33,7 @@ static bool IsRoad(TileIndex tile)
{
return
// MP_STREET, but not a road depot?
(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
(IsTileType(tile, MP_STREET) && !(_map5[tile] & 0x20)) ||
(IsTileType(tile, MP_TUNNELBRIDGE) && (
// road tunnel?
((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) ||
@@ -56,8 +54,8 @@ static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *curr
if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
return AYSTAR_FOUND_END_NODE;
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile,AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
return AYSTAR_FOUND_END_NODE;
return AYSTAR_DONE;
}
@@ -82,11 +80,9 @@ static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *curre
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
// This creates the AiPathFinder
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
{
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo) {
PathNode start_node;
uint x;
uint y;
uint x,y;
// Create AyStar
AyStar *result = malloc(sizeof(AyStar));
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
@@ -115,8 +111,8 @@ AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFin
// Now we add all the starting tiles
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
start_node.node.tile = TILE_XY(x, y);
result->addstart(result, &start_node.node, 0);
start_node.node.tile = TILE_XY(x,y);
result->addstart(result, &start_node.node);
}
}
@@ -124,11 +120,9 @@ AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFin
}
// To reuse AyStar we sometimes have to clean all the memory
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
{
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo) {
PathNode start_node;
uint x;
uint y;
uint x,y;
aystar->clear(aystar);
@@ -144,27 +138,26 @@ void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo
// Now we add all the starting tiles
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
if (!(IsTileType(TILE_XY(x, y), MP_CLEAR) || IsTileType(TILE_XY(x, y), MP_TREES))) continue;
if (!TestCanBuildStationHere(TILE_XY(x, y), TEST_STATION_NO_DIR)) continue;
start_node.node.tile = TILE_XY(x, y);
aystar->addstart(aystar, &start_node.node, 0);
if (!(IsTileType(TILE_XY(x,y), MP_CLEAR) || IsTileType(TILE_XY(x,y), MP_TREES))) continue;
if (!TestCanBuildStationHere(TILE_XY(x,y),TEST_STATION_NO_DIR)) continue;
start_node.node.tile = TILE_XY(x,y);
aystar->addstart(aystar, &start_node.node);
}
}
}
// The h-value, simple calculation
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
int r, r2;
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDir(PathFinderInfo->end_direction));
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDir(PathFinderInfo->end_direction));
r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDir(PathFinderInfo->end_direction));
r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br + TileOffsByDir(PathFinderInfo->end_direction));
} else {
// No direction, so just get the fastest route to the station
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl);
r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br);
}
// See if the bottomright is faster than the topleft..
if (r2 < r) r = r2;
@@ -172,200 +165,197 @@ static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current,
}
// We found the end.. let's get the route back and put it in an array
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
{
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current) {
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
uint i = 0;
PathNode *parent = &current->path;
do {
PathFinderInfo->route_extra[i] = parent->node.user_data[0];
PathFinderInfo->route_extra[i] = parent->node.user_data[0];
PathFinderInfo->route[i++] = parent->node.tile;
if (i > lengthof(PathFinderInfo->route)) {
// We ran out of space for the PathFinder
DEBUG(ai, 0)("[AiPathFinder] Ran out of space in the route[] array!!!");
DEBUG(ai,0)("[AiPathFinder] Ran out of spacein the route[] array!!!");
PathFinderInfo->route_length = -1; // -1 indicates out of space
return;
}
parent = parent->parent;
} while (parent != NULL);
PathFinderInfo->route_length = i;
DEBUG(ai, 1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
DEBUG(ai,1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching",i,Hash_Size(&aystar->ClosedListHash));
}
// What tiles are around us.
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
{
uint i;
int ret;
int dir;
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current) {
uint i;
int r;
int dir;
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
aystar->num_neighbours = 0;
aystar->num_neighbours = 0;
// Go through all surrounding tiles and check if they are within the limits
for (i = 0; i < 4; i++) {
TileIndex ctile = current->path.node.tile; // Current tile
TileIndex atile = ctile + TileOffsByDir(i); // Adjacent tile
// Go through all surrounding tiles and check if they are within the limits
for (i=0;i<4;i++) {
if (TileX(TileOffsByDir(i) + current->path.node.tile) > 1 &&
TileX(TileOffsByDir(i) + current->path.node.tile) < MapMaxX() - 1 &&
TileY(TileOffsByDir(i) + current->path.node.tile) > 1 &&
TileY(TileOffsByDir(i) + current->path.node.tile) < MapMaxY() - 1) {
// We also directly test if the current tile can connect to this tile..
// We do this simply by just building the tile!
if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
// We also directly test if the current tile can connect to this tile..
// We do this simply by just building the tile!
// If the next step is a bridge, we have to enter it the right way
if (!PathFinderInfo->rail_or_road && IsRoad(current->path.node.tile + TileOffsByDir(i))) {
if (IsTileType(current->path.node.tile + TileOffsByDir(i), MP_TUNNELBRIDGE)) {
// An existing bridge... let's test the direction ;)
if ((_map5[current->path.node.tile + TileOffsByDir(i)] & 1U) != (i & 1)) continue;
// This problem only is valid for tunnels:
// When the last tile was not yet a tunnel, check if we enter from the right side..
if (!IsTileType(current->path.node.tile, MP_TUNNELBRIDGE) && (_map5[current->path.node.tile + TileOffsByDir(i)] & 0x80) == 0) {
if (i != (_map5[current->path.node.tile + TileOffsByDir(i)] & 3U)) continue;
}
}
}
// But also if we are on a bridge, we can only move a certain direction
if (!PathFinderInfo->rail_or_road && IsRoad(current->path.node.tile)) {
if (IsTileType(current->path.node.tile, MP_TUNNELBRIDGE)) {
// An existing bridge/tunnel... let's test the direction ;)
if ((_map5[current->path.node.tile] & 1U) != (i & 1)) continue;
}
}
// If the next step is a bridge, we have to enter it the right way
if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
if (IsTileType(atile, MP_TUNNELBRIDGE)) {
// An existing bridge... let's test the direction ;)
if ((_map5[atile] & 1U) != (i & 1)) continue;
// This problem only is valid for tunnels:
// When the last tile was not yet a tunnel, check if we enter from the right side..
if ((_map5[atile] & 0x80) == 0) {
if (i != (_map5[atile] & 3U)) continue;
}
}
}
// But also if we are on a bridge, we can only move a certain direction
if (!PathFinderInfo->rail_or_road && IsRoad(ctile)) {
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
// An existing bridge/tunnel... let's test the direction ;)
if ((_map5[ctile] & 1U) != (i & 1)) continue;
}
}
if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
// We are a bridge/tunnel, how cool!!
// This means we can only point forward.. get the direction from the user_data
if (i != (current->path.node.user_data[0] >> 8)) continue;
}
dir = 0;
if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
// We are a bridge/tunnel, how cool!!
// This means we can only point forward.. get the direction from the user_data
if (i != (current->path.node.user_data[0] >> 8)) continue;
}
dir = 0;
// First, check if we have a parent
if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
// If not, this means we are at the starting station
if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
// We do need a direction?
if (AiNew_GetDirection(ctile, atile) != PathFinderInfo->start_direction) {
// We are not pointing the right way, invalid tile
continue;
}
}
} else if (current->path.node.user_data[0] == 0) {
if (PathFinderInfo->rail_or_road) {
// Rail check
dir = AiNew_GetRailDirection(current->path.parent->node.tile, ctile, atile);
ret = DoCommandByTile(ctile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
if (CmdFailed(ret)) continue;
// First, check if we have a parent
if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
// If not, this means we are at the starting station
if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
// We do need a direction?
if (AiNew_GetDirection(current->path.node.tile, current->path.node.tile + TileOffsByDir(i)) != PathFinderInfo->start_direction)
// We are not pointing the right way, invalid tile
continue;
}
} else if (current->path.node.user_data[0] == 0) {
if (PathFinderInfo->rail_or_road) {
// Rail check
dir = AiNew_GetRailDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + TileOffsByDir(i));
r = DoCommandByTile(current->path.node.tile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
if (r == CMD_ERROR) continue;
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
if (current->path.parent->parent != NULL) {
// Check if we don't make a 90degree curve
int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, ctile);
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
continue;
}
}
if (current->path.parent->parent != NULL) {
// Check if we don't make a 90degree curve
int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, current->path.node.tile);
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
continue;
}
}
#endif
} else {
// Road check
dir = AiNew_GetRoadDirection(current->path.parent->node.tile, ctile, atile);
if (IsRoad(ctile)) {
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
// We have a bridge, how nicely! We should mark it...
dir = 0;
} else {
// It already has road.. check if we miss any bits!
if ((_map5[ctile] & dir) != dir) {
// We do miss some pieces :(
dir &= ~_map5[ctile];
} else {
dir = 0;
}
}
}
// Only destruct things if it is MP_CLEAR of MP_TREES
if (dir != 0) {
ret = DoCommandByTile(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
if (CmdFailed(ret)) continue;
}
}
}
} else {
// Road check
dir = AiNew_GetRoadDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + TileOffsByDir(i));
if (IsRoad(current->path.node.tile)) {
if (IsTileType(current->path.node.tile, MP_TUNNELBRIDGE)) {
// We have a bridge, how nicely! We should mark it...
dir = 0;
} else {
// It already has road.. check if we miss any bits!
if ((_map5[current->path.node.tile] & dir) != dir) {
// We do miss some pieces :(
dir &= ~_map5[current->path.node.tile];
} else {
dir = 0;
}
}
}
// Only destruct things if it is MP_CLEAR of MP_TREES
if (dir != 0) {
r = DoCommandByTile(current->path.node.tile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
if (r == CMD_ERROR) continue;
}
}
}
// The tile can be connected
aystar->neighbours[aystar->num_neighbours].tile = atile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
aystar->neighbours[aystar->num_neighbours++].direction = 0;
}
}
aystar->neighbours[aystar->num_neighbours].tile = TileOffsByDir(i) + current->path.node.tile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
aystar->neighbours[aystar->num_neighbours++].direction = 0;
}
}
// Next step, check for bridges and tunnels
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
TileInfo ti;
// First we get the dir from this tile and his parent
int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
// It means we can only walk with the track, so the bridge has to be in the same direction
TileIndex tile = current->path.node.tile;
TileIndex new_tile = tile;
// Next step, check for bridges and tunnels
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
FindLandscapeHeightByTile(&ti, tile);
TileInfo ti;
// First we get the dir from this tile and his parent
int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
// It means we can only walk with the track, so the bridge has to be in the same direction
TileIndex tile = current->path.node.tile;
TileIndex new_tile = tile;
// Bridges can only be build on land that is not flat
// And if there is a road or rail blocking
if (ti.tileh != 0 ||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_STREET)) ||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_RAILWAY))) {
FindLandscapeHeightByTile(&ti, tile);
for (;;) {
new_tile += TileOffsByDir(dir);
// Bridges can only be build on land that is not flat
// And if there is a road or rail blocking
if (ti.tileh != 0 ||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_STREET)) ||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_RAILWAY))) {
// Precheck, is the length allowed?
if (!CheckBridge_Stuff(0, GetBridgeLength(tile, new_tile))) break;
for (;;) {
new_tile += TileOffsByDir(dir);
// Check if we hit the station-tile.. we don't like that!
if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
// Precheck, is the length allowed?
if (!CheckBridge_Stuff(0,GetBridgeLength(tile, new_tile))) break;
// Try building the bridge..
ret = DoCommandByTile(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
if (CmdFailed(ret)) continue;
// We can build a bridge here.. add him to the neighbours
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
aystar->neighbours[aystar->num_neighbours++].direction = 0;
// Check if we hit the station-tile.. we don't like that!
if (TILES_BETWEEN(new_tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) break;
// Try building the bridge..
r = DoCommandByTile(tile, new_tile, (0<<8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
if (r == CMD_ERROR) continue;
// We can build a bridge here.. add him to the neighbours
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
aystar->neighbours[aystar->num_neighbours++].direction = 0;
// We can only have 12 neighbours, and we need 1 left for tunnels
if (aystar->num_neighbours == 11) break;
}
}
}
// Next, check for tunnels!
// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
// For now, we check both sides for this tile.. terraforming gives fuzzy result
if ((dir == 0 && ti.tileh == 12) ||
(dir == 1 && ti.tileh == 6) ||
(dir == 2 && ti.tileh == 3) ||
(dir == 3 && ti.tileh == 9)) {
// Now simply check if a tunnel can be build
ret = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
if (!CmdFailed(ret) && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
aystar->neighbours[aystar->num_neighbours++].direction = 0;
}
}
}
// Next, check for tunnels!
// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
// For now, we check both sides for this tile.. terraforming gives fuzzy result
if ((dir == 0 && ti.tileh == 12) ||
(dir == 1 && ti.tileh == 6) ||
(dir == 2 && ti.tileh == 3) ||
(dir == 3 && ti.tileh == 9)) {
// Now simply check if a tunnel can be build
r = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
if (r != CMD_ERROR && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
aystar->neighbours[aystar->num_neighbours++].direction = 0;
}
}
}
}
extern uint GetRailFoundation(uint tileh, uint bits);
extern uint GetRoadFoundation(uint tileh, uint bits);
extern uint GetBridgeFoundation(uint tileh, byte direction);
enum {
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
};
// The most important function: it calculates the g-value
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
int r, res = 0;
TileInfo ti, parent_ti;
@@ -375,7 +365,7 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
FindLandscapeHeightByTile(&parent_ti, parent->path.node.tile);
// Check if we hit the end-tile
if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
if (TILES_BETWEEN(current->tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) {
// We are at the end-tile, check if we had a direction or something...
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction)
// We are not pointing the right way, invalid tile
@@ -396,11 +386,7 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
}
// We should give a penalty when the tile is going up or down.. this is one way to do so!
// Too bad we have to count it from the parent.. but that is not so bad.
// We also dislike long routes on slopes, since they do not look too realistic
// when there is a flat land all around, they are more expensive to build, and
// especially they essentially block the ability to connect or cross the road
// from one side.
// Too bad we have to count it from the parent.. but that is not so bad
if (parent_ti.tileh != 0 && parent->path.parent != NULL) {
// Skip if the tile was from a bridge or tunnel
if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
@@ -409,16 +395,12 @@ static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current,
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
if (r >= 15 || (r == 0 && (BRIDGE_NO_FOUNDATION & (1 << ti.tileh)))) {
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
} else {
res += AI_PATHFINDER_FOUNDATION_PENALTY;
}
} else {
if (!(IsRoad(parent->path.node.tile) && IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE))) {
r = GetRoadFoundation(parent_ti.tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
if (r >= 15 || r == 0)
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
else
res += AI_PATHFINDER_FOUNDATION_PENALTY;
}
}
}

View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "ai.h"
#include "vehicle.h"

View File

@@ -1,11 +1,8 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "vehicle.h"
#include "depot.h"
#include "engine.h"
#include "command.h"
#include "station.h"
@@ -14,7 +11,6 @@
#include "sound.h"
#include "player.h"
#include "airport.h"
#include "vehicle_gui.h"
static bool AirportMove(Vehicle *v, const AirportFTAClass *Airport);
static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *Airport);
@@ -37,57 +33,7 @@ static const SpriteID _aircraft_sprite[] = {
0x0EBD, 0x0EC5
};
/* Find the nearest hangar to v
* INVALID_STATION is returned, if the player does not have any suitable
* airports (like helipads only)
*/
static StationID FindNearestHangar(const Vehicle *v)
{
const Station *st;
uint best = 0;
StationID index = INVALID_STATION;
FOR_ALL_STATIONS(st) {
if (st->owner == v->owner && st->facilities & FACIL_AIRPORT &&
GetAirport(st->airport_type)->nof_depots > 0) {
uint distance;
// don't crash the plane if we know it can't land at the airport
if (HASBIT(v->subtype, 1) && st->airport_type == AT_SMALL &&
!_cheats.no_jetcrash.value)
continue;
distance = DistanceSquare(v->tile, st->airport_tile);
if (distance < best || index == INVALID_STATION) {
best = distance;
index = st->index;
}
}
}
return index;
}
#if 0
// returns true if vehicle v have an airport in the schedule, that has a hangar
static bool HaveHangarInOrderList(Vehicle *v)
{
const Order *order;
FOR_VEHICLE_ORDERS(v, order) {
const Station *st = GetStation(order->station);
if (st->owner == v->owner && st->facilities & FACIL_AIRPORT) {
// If an airport doesn't have terminals (so no landing space for airports),
// it surely doesn't have any hangars
if (GetAirport(st->airport_type)->terminals != NULL)
return true;
}
}
return false;
}
#endif
int GetAircraftImage(const Vehicle *v, byte direction)
int GetAircraftImage(Vehicle *v, byte direction)
{
int spritenum = v->spritenum;
@@ -103,19 +49,21 @@ int GetAircraftImage(const Vehicle *v, byte direction)
void DrawAircraftEngine(int x, int y, int engine, uint32 image_ormod)
{
int spritenum = AircraftVehInfo(engine)->image_index;
int sprite = (6 + _aircraft_sprite[spritenum]);
if (is_custom_sprite(spritenum)) {
sprite = GetCustomVehicleIcon(engine, 6);
if (!sprite)
sprite = _engine_original_sprites[engine];
int sprite = GetCustomVehicleIcon(engine, 6);
if (sprite) {
DrawSprite(sprite | image_ormod, x, y);
return;
}
spritenum = _engine_original_sprites[engine];
}
DrawSprite(sprite | image_ormod, x, y);
DrawSprite((6 + _aircraft_sprite[spritenum]) | image_ormod, x, y);
if ((AircraftVehInfo(engine)->subtype & 1) == 0) {
if ((AircraftVehInfo(engine)->subtype & 1) == 0)
DrawSprite(0xF3D, x, y-5);
}
}
void DrawAircraftEngineInfo(int engine, int x, int y, int maxw)
@@ -153,38 +101,28 @@ static bool AllocateVehicles(Vehicle **vl, int num)
return success;
}
int32 EstimateAircraftCost(EngineID engine_type)
int32 EstimateAircraftCost(uint16 engine_type)
{
return AircraftVehInfo(engine_type)->base_cost * (_price.aircraft_base>>3)>>5;
}
/** Build an aircraft.
* @param x,y tile coordinates of depot where aircraft is built
* @param p1 aircraft type being built (engine)
* @param p2 unused
*/
/* p1 = engine */
int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
int32 value;
Vehicle *vl[3], *v, *u, *w;
UnitID unit_num;
TileIndex tile = TILE_FROM_XY(x,y);
byte unit_num;
uint tile = TILE_FROM_XY(x,y);
const AircraftVehicleInfo *avi = AircraftVehInfo(p1);
Engine *e;
if (!IsEngineBuildable(p1, VEH_Aircraft)) return CMD_ERROR;
// Workaround: TODO: make AI players try to build planes in a hangar instead of just an airport tile.
if (!IsAircraftHangarTile(tile) && IS_HUMAN_PLAYER(_current_player)) return CMD_ERROR;
if (_map_owner[tile] != _current_player && IS_HUMAN_PLAYER(_current_player)) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
value = EstimateAircraftCost(p1);
if (flags & DC_QUERY_COST) return value;
if (flags & DC_QUERY_COST)
return value;
// allocate 2 or 3 vehicle structs, depending on type
if (!AllocateVehicles(vl, (avi->subtype & 1) == 0 ? 3 : 2) ||
@@ -243,7 +181,7 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
// v->load_unload_time_rem = 0;
// v->progress = 0;
v->last_station_visited = INVALID_STATION;
v->last_station_visited = 0xFFFF;
// v->destination_coords = 0;
v->max_speed = avi->max_speed;
@@ -272,16 +210,19 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
->layout for #th position of depot. Since layout must start with depots, it is simple
*/
{
const Station* st = GetStation(_map2[tile]);
const AirportFTAClass* Airport = GetAirport(st->airport_type);
uint i;
for (i = 0; i < Airport->nof_depots; i++) {
if (st->airport_tile + ToTileIndexDiff(Airport->airport_depots[i]) == tile) {
Station *st;
const AirportFTAClass *Airport;
const TileIndexDiffC *cur_depot;
byte i = 0;
st = GetStation(_map2[tile]);
Airport = GetAirport(st->airport_type);
for (cur_depot = Airport->airport_depots; i != Airport->nof_depots; cur_depot++) {
if ((uint)(st->airport_tile + ToTileIndexDiff(*cur_depot)) == tile) {
assert(Airport->layout[i].heading == HANGAR);
v->u.air.pos = Airport->layout[i].position;
break;
}
i++;
}
// to ensure v->u.air.pos has been given a value
assert(v->u.air.pos != MAX_ELEMENTS);
@@ -302,7 +243,7 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
VehiclePositionChanged(v);
VehiclePositionChanged(u);
// Aircraft with 3 vehicles (chopper)?
// Aircraft with 3 vehicles?
if (v->subtype == 0) {
w = vl[2];
@@ -326,9 +267,10 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Aircraft); //updates the replace Aircraft window
}
InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Aircraft); //updates the replace Aircraft window
return value;
}
@@ -343,7 +285,8 @@ bool IsAircraftHangarTile(TileIndex tile)
static bool CheckStoppedInHangar(Vehicle *v)
{
if (!(v->vehstatus & VS_STOPPED) || !IsAircraftHangarTile(v->tile)) {
if (!(v->vehstatus&VS_STOPPED) ||
!IsAircraftHangarTile(v->tile)) {
_error_message = STR_A01B_AIRCRAFT_MUST_BE_STOPPED;
return false;
}
@@ -361,52 +304,45 @@ static void DoDeleteAircraft(Vehicle *v)
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
}
/** Sell an aircraft.
* @param x,y unused
* @param p1 vehicle ID to be sold
* @param p2 unused
*/
// p1 = vehicle
int32 CmdSellAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
if (!IsVehicleIndex(p1)) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
v = GetVehicle(p1);
if (v->type != VEH_Aircraft || !CheckOwnership(v->owner) || !CheckStoppedInHangar(v))
if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v))
return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
if (flags & DC_EXEC) {
// Invalidate depot
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
DoDeleteAircraft(v);
InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Aircraft); // updates the replace Aircraft window
}
InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Aircraft); // updates the replace Aircraft window
return -(int32)v->value;
}
/** Start/Stop an aircraft.
* @param x,y unused
* @param p1 aircraft ID to start/stop
* @param p2 unused
*/
// p1 = vehicle
int32 CmdStartStopAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
if (!IsVehicleIndex(p1)) return CMD_ERROR;
v = GetVehicle(p1);
if (v->type != VEH_Aircraft || !CheckOwnership(v->owner)) return CMD_ERROR;
if (!CheckOwnership(v->owner))
return CMD_ERROR;
// cannot stop airplane when in flight, or when taking off / landing
if (v->u.air.state >= STARTTAKEOFF)
if (v->u.air.state >= STARTTAKEOFF) {
return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT);
}
if (flags & DC_EXEC) {
v->vehstatus ^= VS_STOPPED;
@@ -418,25 +354,21 @@ int32 CmdStartStopAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
/** Send an aircraft to the hangar.
* @param x,y unused
* @param p1 vehicle ID to send to the hangar
* @param p2 various bitmasked elements
* - p2 = 0 - aircraft goes to the depot and stays there (user command)
* - p2 non-zero - aircraft will try to goto a depot, but not stop there (eg forced servicing)
* - p2 (bit 17) - aircraft will try to goto a depot at the next airport
*/
// p1 = vehicle
// p2 = if set, the aircraft will try to goto a depot, but not stop
int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
if (!IsVehicleIndex(p1)) return CMD_ERROR;
Station *st;
v = GetVehicle(p1);
if (v->type != VEH_Aircraft || !CheckOwnership(v->owner)) return CMD_ERROR;
if (p2 != 0) v->set_for_replacement = true; //now all clients knows that the vehicle wants to be replaced
if (v->current_order.type == OT_GOTO_DEPOT && p2 == 0) {
if (!CheckOwnership(v->owner))
return CMD_ERROR;
if (v->current_order.type == OT_GOTO_DEPOT && p2 != 0) {
if (flags & DC_EXEC) {
if (v->current_order.flags & OF_UNLOAD) v->cur_order_index++;
v->current_order.type = OT_DUMMY;
@@ -444,98 +376,62 @@ int32 CmdSendAircraftToHangar(int x, int y, uint32 flags, uint32 p1, uint32 p2)
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
}
} else {
bool next_airport_has_hangar = true;
/* XXX - I don't think p2 is any valid station cause all calls use either 0, 1, or 1<<16!!!!!!!!! */
StationID next_airport_index = (HASBIT(p2, 17)) ? (StationID)p2 : v->u.air.targetairport;
const Station *st = GetStation(next_airport_index);
st = GetStation(v->u.air.targetairport);
// If an airport doesn't have terminals (so no landing space for airports),
// it surely doesn't have any hangars
if (!IsValidStation(st) || st->airport_tile == 0 || GetAirport(st->airport_type)->nof_depots == 0) {
StationID station;
if (p2 != 0) return CMD_ERROR;
// the aircraft has to search for a hangar on its own
station = FindNearestHangar(v);
next_airport_has_hangar = false;
if (station == INVALID_STATION) return CMD_ERROR;
st = GetStation(station);
next_airport_index = station;
}
if (st->xy == 0 || st->airport_tile == 0 || GetAirport(st->airport_type)->terminals == NULL)
return CMD_ERROR;
if (flags & DC_EXEC) {
v->current_order.type = OT_GOTO_DEPOT;
v->current_order.flags = HASBIT(p2, 16) ? 0 : OF_NON_STOP | OF_FULL_LOAD;
v->current_order.station = next_airport_index;
v->current_order.flags = p2 == 0 ? OF_NON_STOP | OF_FULL_LOAD : 0;
v->current_order.station = v->u.air.targetairport;
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
if (HASBIT(p2, 17) || (p2 == 0 && v->u.air.state == FLYING && !next_airport_has_hangar)) {
// the aircraft is now heading for a different hangar than the next in the orders
AircraftNextAirportPos_and_Order(v);
v->u.air.targetairport = next_airport_index;
}
}
}
return 0;
}
/** Change the service interval for aircraft.
* @param x,y unused
* @param p1 vehicle ID that is being service-interval-changed
* @param p2 new service interval
*/
// p1 = vehicle
// p2 = new service int
int32 CmdChangeAircraftServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
uint16 serv_int = GetServiceIntervalClamped(p2); /* Double check the service interval from the user-input */
if (serv_int != p2 || !IsVehicleIndex(p1)) return CMD_ERROR;
v = GetVehicle(p1);
if (v->type != VEH_Aircraft || !CheckOwnership(v->owner)) return CMD_ERROR;
if (!CheckOwnership(v->owner))
return CMD_ERROR;
if (flags & DC_EXEC) {
v->service_interval = serv_int;
v->service_interval = (uint16)p2;
InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 7);
}
return 0;
}
/** Refits an aircraft to the specified cargo type.
* @param x,y unused
* @param p1 vehicle ID of the aircraft to refit
* @param p2 various bitstuffed elements
* - p2 = (bit 0-7) - the new cargo type to refit to (p2 & 0xFF)
* - p2 = (bit 8) - skip check for stopped in hangar, used by autoreplace (p2 & 0x100)
* @todo p2 bit8 check <b>NEEDS TO GO</b>
*/
// p1 = vehicle
// p2 = new cargo type(0xFF)
// p2 = skip check for stopped in hanger (0x0100)
int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
Vehicle *v,*u;
int pass, mail;
int32 cost;
bool SkipStoppedInHangerCheck = !!HASBIT(p2, 8); // XXX - needs to go, yes?
CargoID new_cid = p2 & 0xFF; //gets the cargo number
const AircraftVehicleInfo *avi;
if (!IsVehicleIndex(p1)) return CMD_ERROR;
v = GetVehicle(p1);
if (v->type != VEH_Aircraft || !CheckOwnership(v->owner)) return CMD_ERROR;
if (!SkipStoppedInHangerCheck && !CheckStoppedInHangar(v)) return_cmd_error(STR_A01B_AIRCRAFT_MUST_BE_STOPPED);
avi = AircraftVehInfo(v->engine_type);
/* Check cargo */
if (new_cid > NUM_CARGO || !CanRefitTo(v, new_cid)) return CMD_ERROR;
byte SkipStoppedInHangerCheck = (p2 & 0x100) >> 8; //excludes the cargo value
byte new_cargo_type = p2 & 0xFF; //gets the cargo number
AircraftVehicleInfo *avi;
SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
switch (new_cid) {
v = GetVehicle(p1);
avi = AircraftVehInfo(v->engine_type);
if (!CheckOwnership(v->owner) || (!CheckStoppedInHangar(v) && !(SkipStoppedInHangerCheck)))
return CMD_ERROR;
switch (new_cargo_type) {
case CT_PASSENGERS:
pass = avi->passenger_capacity;
break;
@@ -554,22 +450,24 @@ int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
_aircraft_refit_capacity = pass;
cost = 0;
if (IS_HUMAN_PLAYER(v->owner) && new_cid != v->cargo_type) {
if (IS_HUMAN_PLAYER(v->owner) && new_cargo_type != v->cargo_type) {
cost = _price.aircraft_base >> 7;
}
if (flags & DC_EXEC) {
Vehicle *u;
v->cargo_cap = pass;
u = v->next;
mail = (new_cid != CT_PASSENGERS) ? 0 : avi->mail_capacity;
mail = avi->mail_capacity;
if (new_cargo_type != CT_PASSENGERS) {
mail = 0;
}
u->cargo_cap = mail;
//autorefitted planes wants to keep the cargo
//it will be checked if the cargo is valid in CmdReplaceVehicle
if (!(SkipStoppedInHangerCheck))
v->cargo_count = u->cargo_count = 0;
v->cargo_type = new_cid;
v->cargo_type = new_cargo_type;
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
@@ -595,7 +493,7 @@ static void CheckIfAircraftNeedsService(Vehicle *v)
return;
if (v->current_order.type == OT_GOTO_DEPOT &&
v->current_order.flags & OF_HALT_IN_DEPOT)
v->current_order.flags & OF_FULL_LOAD)
return;
if (_patches.gotodepot && VehicleHasDepotOrders(v))
@@ -830,7 +728,7 @@ static byte GetAircraftFlyingAltitude(const Vehicle *v)
return maxz;
}
static bool AircraftController(Vehicle *v)
static bool Aircraft_5(Vehicle *v)
{
Station *st;
const AirportMovingData *amd;
@@ -885,7 +783,7 @@ static bool AircraftController(Vehicle *v)
if (amd->flag & AMED_HELI_LOWER) {
if (UpdateAircraftSpeed(v)) {
if (st->airport_tile == 0) {
// FIXME - AircraftController -> if station no longer exists, do not land
// FIXME - Aircraft_5 -> if station no longer exists, do not land
// helicopter will circle until sign disappears, then go to next order
// * what to do when it is the only order left, right now it just stays in 1 place
v->u.air.state = FLYING;
@@ -997,6 +895,8 @@ static bool AircraftController(Vehicle *v)
if (amd->flag & AMED_LAND) {
if (st->airport_tile == 0) {
//FIXME -- FIXED - Aircraft_5 -> if station no longer exists, do not land
// * what to do when it is the only order left, right now it just stays in 1 place?
v->u.air.state = FLYING;
AircraftNextAirportPos_and_Order(v);
// get aircraft back on running altitude
@@ -1064,7 +964,7 @@ static void HandleCrashedAircraft(Vehicle *v)
4 + (r&0xF),
4 + ((r>>4)&0xF),
((r>>8)&0xF),
EV_EXPLOSION_SMALL);
EV_DEMOLISH);
}
} else if (v->u.air.crashed_counter >= 10000) {
// remove rubble of crashed airplane
@@ -1115,7 +1015,7 @@ static void HandleAircraftSmoke(Vehicle *v)
_aircraft_smoke_xy[v->direction],
_aircraft_smoke_xy[v->direction + 8],
2,
EV_SMOKE
EV_SMOKE_3
);
}
}
@@ -1134,7 +1034,8 @@ static void ProcessAircraftOrder(Vehicle *v)
if (v->current_order.type == OT_GOTO_DEPOT &&
(v->current_order.flags & (OF_UNLOAD | OF_FULL_LOAD)) == (OF_UNLOAD | OF_FULL_LOAD) &&
!VehicleNeedsService(v)) {
!VehicleNeedsService(v) &&
v->set_for_replacement == false) {
v->cur_order_index++;
}
@@ -1212,7 +1113,7 @@ static void CrashAirplane(Vehicle *v)
v->vehstatus |= VS_CRASHED;
v->u.air.crashed_counter = 0;
CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
CreateEffectVehicleRel(v, 4, 4, 8, EV_CRASHED_SMOKE);
InvalidateWindow(WC_VEHICLE_VIEW, v->index);
@@ -1333,9 +1234,9 @@ static void AircraftEnterHangar(Vehicle *v)
v->current_order.type = OT_NOTHING;
v->current_order.flags = 0;
if (HASBIT(old_order.flags, OFB_PART_OF_ORDERS)) {
if (old_order.flags & OF_UNLOAD) {
v->cur_order_index++;
} else if (HASBIT(old_order.flags, OFB_HALT_IN_DEPOT)) { // force depot visit
} else if (old_order.flags & OF_FULL_LOAD) { // force depot visit
v->vehstatus |= VS_STOPPED;
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
@@ -1538,8 +1439,8 @@ static void AircraftEventHandler_HeliTakeOff(Vehicle *v, const AirportFTAClass *
AircraftNextAirportPos_and_Order(v);
// check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
if ((v->owner == _local_player && _autoreplace_array[v->engine_type] != v->engine_type) ||
(v->owner == _local_player && _patches.autorenew && v->age - v->max_age > (_patches.autorenew_months * 30))) {
if (v->current_order.type != OT_GOTO_DEPOT && ((v->owner == _local_player && _autoreplace_array[v->engine_type] != v->engine_type) ||
(v->owner == _local_player && _patches.autorenew && v->age - v->max_age > (_patches.autorenew_months * 30)))) {
_current_player = _local_player;
DoCommandP(v->tile, v->index, 1, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR);
_current_player = OWNER_NONE;
@@ -1597,17 +1498,6 @@ static void AircraftEventHandler_Landing(Vehicle *v, const AirportFTAClass *Airp
{
AircraftLandAirplane(v); // maybe crash airplane
v->u.air.state = ENDLANDING;
// check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) {
// only the vehicle owner needs to calculate the rest (locally)
if ((_autoreplace_array[v->engine_type] != v->engine_type) ||
(_patches.autorenew && v->age - v->max_age > (_patches.autorenew_months * 30))) {
// send the aircraft to the hangar at next airport (bit 17 set)
_current_player = _local_player;
DoCommandP(v->tile, v->index, 1 << 16, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_SHOW_NO_ERROR);
_current_player = OWNER_NONE;
}
}
}
static void AircraftEventHandler_HeliLanding(Vehicle *v, const AirportFTAClass *Airport)
@@ -1686,7 +1576,7 @@ static void AirportClearBlock(Vehicle *v, const AirportFTAClass *Airport)
static void AirportGoToNextPosition(Vehicle *v, const AirportFTAClass *Airport)
{
// if aircraft is not in position, wait until it is
if (!AircraftController(v)) {return;}
if (!Aircraft_5(v)) {return;}
AirportClearBlock(v, Airport);
AirportMove(v, Airport); // move aircraft to next position
@@ -2060,7 +1950,7 @@ void UpdateAirplanesOnNewStation(Station *st)
v->u.air.pos = v->u.air.previous_pos = ap->entry_point;
v->u.air.state = FLYING;
// landing plane needs to be reset to flying height (only if in pause mode upgrade,
// in normal mode, plane is reset in AircraftController. It doesn't hurt for FLYING
// in normal mode, plane is reset in Aircraft_5. It doesn't hurt for FLYING
GetNewVehiclePos(v, &gp);
// set new position x,y,z
SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v));

View File

@@ -1,9 +1,7 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "window.h"
#include "gui.h"
#include "vehicle.h"
@@ -13,7 +11,6 @@
#include "engine.h"
#include "viewport.h"
#include "player.h"
#include "depot.h"
void Set_DPARAM_Aircraft_Build_Window(uint16 engine_number)
@@ -36,7 +33,7 @@ void Set_DPARAM_Aircraft_Build_Window(uint16 engine_number)
}
static void DrawAircraftImage(const Vehicle *v, int x, int y, VehicleID selection)
static void DrawAircraftImage(Vehicle *v, int x, int y, VehicleID selection)
{
int image = GetAircraftImage(v, 6);
uint32 ormod = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(v->owner));
@@ -151,11 +148,11 @@ static void NewAircraftWndProc(Window *w, WindowEvent *e)
break;
case WE_ON_EDIT_TEXT: {
if (e->edittext.str[0] != '\0') {
_cmd_text = e->edittext.str;
DoCommandP(0, WP(w, buildtrain_d).rename_engine, 0, NULL,
CMD_RENAME_ENGINE | CMD_MSG(STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE));
}
byte *b = e->edittext.str;
if (*b == 0)
return;
memcpy(_decode_parameters, b, 32);
DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE));
} break;
case WE_RESIZE:
@@ -205,11 +202,64 @@ static void ShowBuildAircraftWindow(uint tile)
}
}
#define MAX_REFIT 0xFF
const byte _aircraft_refit_normal[] = {
CT_PASSENGERS,
CT_MAIL,
CT_GOODS,
CT_VALUABLES,
MAX_REFIT
};
const byte _aircraft_refit_arctic[] = {
CT_PASSENGERS,
CT_MAIL,
CT_GOODS,
CT_FOOD,
MAX_REFIT
};
const byte _aircraft_refit_desert[] = {
CT_PASSENGERS,
CT_MAIL,
CT_FRUIT,
CT_GOODS,
CT_DIAMONDS,
MAX_REFIT
};
const byte _aircraft_refit_candy[] = {
CT_PASSENGERS,
CT_SUGAR,
CT_TOYS,
CT_CANDY,
CT_COLA,
CT_COTTON_CANDY,
CT_BUBBLES,
CT_TOFFEE,
CT_BATTERIES,
CT_PLASTIC,
CT_FIZZY_DRINKS,
MAX_REFIT
};
const byte * const _aircraft_refit_types[4] = {
_aircraft_refit_normal, _aircraft_refit_arctic, _aircraft_refit_desert, _aircraft_refit_candy
};
#undef MAX_REFIT
static void AircraftRefitWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
switch(e->event) {
case WE_PAINT: {
const Vehicle *v = GetVehicle(w->window_number);
Vehicle *v = GetVehicle(w->window_number);
const byte *b;
int sel;
int x,y;
byte color;
int cargo;
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
@@ -218,31 +268,72 @@ static void AircraftRefitWndProc(Window *w, WindowEvent *e)
DrawString(1, 15, STR_A040_SELECT_CARGO_TYPE_TO_CARRY, 0);
/* TODO: Support for custom GRFSpecial-specified refitting! --pasky */
WP(w,refit_d).cargo = DrawVehicleRefitWindow(v, WP(w, refit_d).sel);
if (WP(w,refit_d).cargo != CT_INVALID) {
int32 cost = DoCommandByTile(v->tile, v->index, WP(w,refit_d).cargo, DC_QUERY_COST, CMD_REFIT_AIRCRAFT);
if (!CmdFailed(cost)) {
cargo = -1;
x = 6;
y = 25;
sel = WP(w,refit_d).sel;
#define show_cargo(ctype) { \
color = 16; \
if (sel == 0) { \
cargo = ctype; \
color = 12; \
} \
sel--; \
DrawString(x, y, _cargoc.names_s[ctype], color); \
y += 10; \
}
if (_engine_refit_masks[v->engine_type]) {
uint32 mask = _engine_refit_masks[v->engine_type];
int cid = 0;
for (; mask; mask >>= 1, cid++) {
if (!(mask & 1)) // not this cid
continue;
if (!(_local_cargo_id_landscape[cid] & (1 << _opt.landscape))) // not in this landscape
continue;
show_cargo(_local_cargo_id_ctype[cid]);
}
} else { // generic refit list
b = _aircraft_refit_types[_opt.landscape];
do {
show_cargo(*b);
} while (*++b != 0xFF);
}
#undef show_cargo
WP(w,refit_d).cargo = cargo;
if (cargo != -1) {
int32 cost = DoCommandByTile(v->tile, v->index, cargo, DC_QUERY_COST, CMD_REFIT_AIRCRAFT);
if (cost != CMD_ERROR) {
SetDParam(2, cost);
SetDParam(0, _cargoc.names_long_p[WP(w,refit_d).cargo]);
SetDParam(0, _cargoc.names_long_p[cargo]);
SetDParam(1, _aircraft_refit_capacity);
DrawString(1, 137, STR_A041_NEW_CAPACITY_COST_OF_REFIT, 0);
}
}
} break;
break;
}
case WE_CLICK:
switch(e->click.widget) {
case 2: { /* listbox */
int y = e->click.pt.y - 25;
if (y >= 0) {
WP(w,refit_d).sel = y / 10;
SetWindowDirty(w);
}
} break;
int y = e->click.pt.y - 25;
if (y >= 0) {
WP(w,refit_d).sel = y / 10;
SetWindowDirty(w);
}
} break;
case 4: /* refit button */
if (WP(w,refit_d).cargo != CT_INVALID) {
const Vehicle *v = GetVehicle(w->window_number);
if (WP(w,refit_d).cargo != 0xFF) {
Vehicle *v = GetVehicle(w->window_number);
if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT)))
DeleteWindow(w);
}
@@ -284,10 +375,11 @@ static void ShowAircraftRefitWindow(Vehicle *v)
static void AircraftDetailsWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
const Vehicle *v = GetVehicle(w->window_number);
int mod;
Vehicle *v = GetVehicle(w->window_number), *u;
switch(e->event) {
case WE_PAINT:
w->disabled_state = v->owner == _local_player ? 0 : (1 << 2);
if (!_patches.servint_aircraft) // disable service-scroller when interval is set to disabled
w->disabled_state |= (1 << 5) | (1 << 6);
@@ -345,7 +437,6 @@ static void AircraftDetailsWndProc(Window *w, WindowEvent *e)
DrawAircraftImage(v, 3, 57, INVALID_VEHICLE);
{
const Vehicle *u;
int y = 57;
do {
@@ -377,32 +468,34 @@ static void AircraftDetailsWndProc(Window *w, WindowEvent *e)
}
} while ( (v=v->next) != NULL);
}
} break;
break;
case WE_CLICK: {
int mod;
const Vehicle *v;
switch (e->click.widget) {
case WE_CLICK:
switch(e->click.widget) {
case 2: /* rename */
v = GetVehicle(w->window_number);
SetDParam(0, v->unitnumber);
ShowQueryString(v->string_id, STR_A030_NAME_AIRCRAFT, 31, 150, w->window_class, w->window_number);
break;
case 5: /* increase int */
mod = _ctrl_pressed? 5 : 10;
goto do_change_service_int;
goto change_int;
case 6: /* decrease int */
mod = _ctrl_pressed?- 5 : -10;
do_change_service_int:
v = GetVehicle(w->window_number);
change_int:
mod += v->service_interval;
mod = GetServiceIntervalClamped(mod + v->service_interval);
if (mod == v->service_interval) return;
/* %-based service interval max 5%-90%
day-based service interval max 30-800 days */
mod = _patches.servint_ispercent ? clamp(mod, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(mod, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS+1);
if (mod == v->service_interval)
return;
DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_AIRCRAFT_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING));
DoCommandP(v->tile, v->index, mod, NULL,
CMD_CHANGE_AIRCRAFT_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING));
break;
}
} break;
break;
case WE_4:
if (FindWindowById(WC_VEHICLE_VIEW, w->window_number) == NULL)
@@ -410,11 +503,11 @@ do_change_service_int:
break;
case WE_ON_EDIT_TEXT: {
if (e->edittext.str[0] != '\0') {
_cmd_text = e->edittext.str;
DoCommandP(0, w->window_number, 0, NULL,
CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT));
}
byte *b = e->edittext.str;
if (*b == 0)
return;
memcpy(_decode_parameters, b, 32);
DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT));
} break;
}
@@ -460,20 +553,18 @@ static void ShowAircraftDetailsWindow(Vehicle *v)
static const Widget _aircraft_view_widgets[] = {
{ WWT_TEXTBTN, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 237, 0, 13, STR_A00A, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_STICKYBOX, RESIZE_LR, 14, 238, 249, 0, 13, 0x0, STR_STICKY_BUTTON },
{ WWT_IMGBTN, RESIZE_RB, 14, 0, 231, 14, 103, 0x0, STR_NULL },
{ WWT_6, RESIZE_RB, 14, 2, 229, 16, 101, 0x0, STR_NULL },
{ WWT_PUSHIMGBTN, RESIZE_RTB, 14, 0, 237, 104, 115, 0x0, STR_A027_CURRENT_AIRCRAFT_ACTION },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 14, 31, 0x2AB, STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 32, 49, 0x2AF, STR_A02A_SEND_AIRCRAFT_TO_HANGAR },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 50, 67, 0x2B4, STR_A03B_REFIT_AIRCRAFT_TO_CARRY },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 68, 85, 0x2B2, STR_A028_SHOW_AIRCRAFT_S_ORDERS },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 86, 103, 0x2B3, STR_A02B_SHOW_AIRCRAFT_DETAILS },
{ WWT_PANEL, RESIZE_LRB, 14, 232, 249, 104, 103, 0x0, STR_NULL },
{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 238, 249, 104, 115, 0x0, STR_NULL },
{ WIDGETS_END }
{ WWT_TEXTBTN, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 237, 0, 13, STR_A00A, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 14, 238, 249, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 231, 14, 103, 0x0, STR_NULL},
{ WWT_6, RESIZE_NONE, 14, 2, 229, 16, 101, 0x0, STR_NULL},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 0, 249, 104, 115, 0x0, STR_A027_CURRENT_AIRCRAFT_ACTION},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 232, 249, 14, 31, 0x2AB, STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 232, 249, 32, 49, 0x2AF, STR_A02A_SEND_AIRCRAFT_TO_HANGAR},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 232, 249, 50, 67, 0x2B4, STR_A03B_REFIT_AIRCRAFT_TO_CARRY},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 232, 249, 68, 85, 0x2B2, STR_A028_SHOW_AIRCRAFT_S_ORDERS},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 232, 249, 86, 103, 0x2B3, STR_A02B_SHOW_AIRCRAFT_DETAILS},
{ WIDGETS_END},
};
static void AircraftViewWndProc(Window *w, WindowEvent *e)
@@ -502,8 +593,7 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e)
DrawWindowWidgets(w);
/* draw the flag */
DrawSprite(v->vehstatus & VS_STOPPED ? 0xC12 : 0xC13, 2,
w->widget[5].top + 1);
DrawSprite((v->vehstatus & VS_STOPPED) ? 0xC12 : 0xC13, 2, 105);
if (v->vehstatus & VS_CRASHED) {
str = STR_8863_CRASHED;
@@ -537,8 +627,7 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e)
}
}
DrawStringCentered((w->widget[5].right - w->widget[5].left) / 2,
w->widget[5].top + 1, str, 0);
DrawStringCentered(125, 105, str, 0);
DrawWindowViewport(w);
} break;
@@ -567,13 +656,6 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e)
}
} break;
case WE_RESIZE:
w->viewport->width += e->sizing.diff.x;
w->viewport->height += e->sizing.diff.y;
w->viewport->virtual_width += e->sizing.diff.x;
w->viewport->virtual_height += e->sizing.diff.y;
break;
case WE_DESTROY:
DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number);
DeleteWindowById(WC_VEHICLE_REFIT, w->window_number);
@@ -586,7 +668,7 @@ static void AircraftViewWndProc(Window *w, WindowEvent *e)
static const WindowDesc _aircraft_view_desc = {
-1,-1, 250, 116,
WC_VEHICLE_VIEW ,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
_aircraft_view_widgets,
AircraftViewWndProc
};
@@ -929,7 +1011,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
w->widget[1].unkA = STR_A009_AIRCRAFT;
} else {
/* Station Name -- (###) Aircraft */
SetDParam(0, station);
SetDParam(0, GetStation(station)->index);
SetDParam(1, w->vscroll.count);
w->widget[1].unkA = STR_SCHEDULED_AIRCRAFT;
}
@@ -938,7 +1020,8 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
/* draw sorting criteria string */
DrawString(85, 15, _vehicle_sort_listing[vl->sort_type], 0x10);
/* draw arrow pointing up/down for ascending/descending sorting */
DoDrawString(vl->flags & VL_DESC ? "\xAA" : "\xA0", 69, 15, 0x10);
DoDrawString(
vl->flags & VL_DESC ? "\xAA" : "\xA0", 69, 15, 0x10);
max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
for (i = w->vscroll.pos; i < max; ++i) {
@@ -977,7 +1060,6 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
case 3: /* Flip sorting method ascending/descending */
vl->flags ^= VL_DESC;
vl->flags |= VL_RESORT;
_sorting.aircraft.order = !!(vl->flags & VL_DESC);
SetWindowDirty(w);
break;
@@ -1040,19 +1122,18 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
// value has changed -> resort
vl->flags |= VL_RESORT;
vl->sort_type = e->dropdown.index;
_sorting.aircraft.criteria = vl->sort_type;
// enable 'Sort By' if a sorter criteria is chosen
if (vl->sort_type != SORT_BY_UNSORTED)
CLRBIT(w->disabled_state, 3);
w->disabled_state &= ~(1 << 3);
}
SetWindowDirty(w);
break;
case WE_CREATE: /* set up resort timer */
vl->sort_list = NULL;
vl->flags = VL_REBUILD | (_sorting.aircraft.order << (VL_DESC - 1));
vl->sort_type = _sorting.aircraft.criteria;
vl->flags = VL_REBUILD;
vl->sort_type = SORT_BY_UNSORTED;
vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
break;

View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "airport.h"

View File

@@ -48,20 +48,4 @@ void InitializeAirports(void);
void UnInitializeAirports(void);
const AirportFTAClass* GetAirport(const byte airport_type);
/** Get buildable airport bitmask.
* @return get all buildable airports at this given time, bitmasked.
* Bit 0 means the small airport is buildable, etc.
* @todo set availability of airports by year, instead of airplane
*/
static inline uint32 GetValidAirports(void)
{
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
// 1980-1-1 is --> 21915
// 1990-1-1 is --> 25568
if (_date >= 21915) {SETBIT(bytemask, 3);} // metropilitan airport 1980
if (_date >= 25568) {SETBIT(bytemask, 4);} // international airport 1990
return bytemask;
}
#endif /* AIRPORT_H */

View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "map.h"
#include "window.h"
@@ -12,7 +11,6 @@
#include "vehicle.h"
#include "station.h"
#include "airport.h"
#include "depot.h"
static byte _selected_airport_type;
@@ -135,25 +133,24 @@ void ShowBuildAirToolbar(void)
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
switch(e->event) {
case WE_PAINT: {
int sel;
int rad = 4; // default catchment radious
uint32 avail_airports;
if (WP(w,def_d).close) return;
if (WP(w,def_d).close)
return;
w->disabled_state = 0;
sel = _selected_airport_type;
avail_airports = GetValidAirports();
if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
/* 'Country Airport' starts at widget 3, and if its bit is set, it is available,
* so take its opposite value to set the disabled_state. There are only 5 available
* airports, so XOr with 0x1F (1 1111) */
w->disabled_state = (avail_airports ^ 0x1F) << 3;
// FIXME -- BuildAirportPickerWndProc - set availability of airports by year, instead of airplane
if (!(_avail_aircraft & 1)) { w->disabled_state |= (1<<3); if (sel == AT_SMALL) sel = AT_LARGE; }
if (!(_avail_aircraft & 2)) { w->disabled_state |= (1<<4); if (sel == AT_LARGE) sel = AT_SMALL; }
if (!(_avail_aircraft & 4)) { w->disabled_state |= (1<<5); } // heliport
// 1980-1-1 is --> 21915
// 1990-1-1 is --> 25568
if (_date < 21915) {w->disabled_state |= (1<<6);} // metropilitan airport 1980
if (_date < 25568) {w->disabled_state |= (1<<7);} // international airport 1990
_selected_airport_type = sel;
// select default the coverage area to 'Off' (8)
w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage);

View File

@@ -56,7 +56,7 @@ static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
// Adds a node to the OpenList
// It makes a copy of node, and puts the pointer of parent in the struct
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g)
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g, int userdata)
{
// Add a new Node to the OpenList
OpenListNode* new_node = malloc(sizeof(OpenListNode));
@@ -120,7 +120,7 @@ int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *pare
aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
} else {
// A new node, add him to the OpenList
AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g);
AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g, 0);
}
return AYSTAR_DONE;
@@ -248,14 +248,13 @@ int AyStarMain_Main(AyStar *aystar) {
* if wanted. You should make sure that clear() is called before adding nodes
* if the AyStar has been used before (though the normal main loop calls
* clear() automatically when the algorithm finishes
* g is the cost for starting with this node.
*/
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g) {
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node) {
#ifdef AYSTAR_DEBUG
printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n",
TileX(start_node->tile), TileY(start_node->tile), start_node->direction);
#endif
AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, g);
AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, 0, 0);
}
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets) {

View File

@@ -56,14 +56,6 @@ typedef struct AyStar AyStar;
* AYSTAR_FOUND_END_NODE : indicates this is the end tile
* AYSTAR_DONE : indicates this is not the end tile (or direction was wrong)
*/
/*
* The 2nd parameter should be OpenListNode, and NOT AyStarNode. AyStarNode is
* part of OpenListNode and so it could be accessed without any problems.
* The good part about OpenListNode is, and how AIs use it, that you can
* access the parent of the current node, and so check if you, for example
* don't try to enter the file tile with a 90-degree curve. So please, leave
* this an OpenListNode, it works just fine -- TrueLight
*/
typedef int32 AyStar_EndNodeCheck(AyStar *aystar, OpenListNode *current);
/*
@@ -97,7 +89,7 @@ typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current);
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
// For internal use, see aystar.c
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node, uint g);
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode* start_node);
typedef int AyStar_Main(AyStar *aystar);
typedef int AyStar_Loop(AyStar *aystar);
typedef int AyStar_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
@@ -161,7 +153,7 @@ struct AyStar {
};
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node);
int AyStarMain_Main(AyStar *aystar);
int AyStarMain_Loop(AyStar *aystar);
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);

View File

@@ -161,6 +161,7 @@ void ShowBuildBridgeWindow(uint start, uint end, byte bridge_type)
w->vscroll.cap = 4;
w->vscroll.count = (byte)j;
} else {
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * 16, TileY(end) * 16);
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE,
TileX(end) * 16, TileY(end) * 16);
}
}

View File

@@ -71,4 +71,4 @@ CommandCallback *_callback_table[] = {
/* 0x14 */ CcTerraform
};
const int _callback_table_count = lengthof(_callback_table);
const int _callback_table_count = sizeof (_callback_table) / sizeof (*_callback_table);

View File

@@ -1,82 +1,3 @@
0.4.0 (2005-05-15)
------------------------------------------------------------------------
- Feature: Bigger maps. Enjoy playing up to 2028x2048 (64 times as big as you were used to!)
- Feature: New realistic acceleration; should be much better. Inlcudes gigger penalty on narrow curves and speedlimits in depots/stations
- Feature: It is now possible to build multiple road stations (up to 8) on a single station (multibus).
- Feature: New PathFinder (NPF). Support for train/road and ship based on A*. No more braindead pathfinding
- Feature: Dynamic towns/industries/stations/vehicles/signs/orders/everything, up to 64K
- Feature: Brand new OldLoader so OpenTTD is TTD(Patch) compatible again. Also endian safe
- Feature: Even better newgrf support, except for callbacks, everything works (ok, almost)
- Feature: Improved multiplayer. More console options, less desyncs and more fun
- Feature: Protected OpenTTD from interference of hacked clients, so it should be safe to play again.
- Feature: [ 1093261 ] Saving vehicle sorting criteria for each vehicle type
- Feature: [ 1107690 ] Resizable orders GUI
- Feature: [ 1166978 ] Focus keyboard on input-box in Multiplayer Menu
- Feature: [ 1174313 ] terrain hotkeys nonfunctional in scenario editor (D,Q,W,E,R,T,Y,U fltr)
- Feature: Complete rework of console and new commands like ls, save, load, help, etc.
- Feature: Signs are shown in the colour of the player who created them
- Feature: Add cheat option to set production of raw-material industries in game
- Feature: Replace trian GUI remembers railtype selected from the dropdown menu
- Feature: Improved Autoreplace
- Feature: many more smaller features :D
- Fix: [ 1108618 ] A wrong error message was displayed when trying to
- Fix: [ 1110407 ] Game does not crash any more when a newgrf file doesn't exist
- Fix: [ 1112469 ] Clearing land for free by reallocating HQ
- Fix: [ 1112469 ] Clearing land for free by reallocating HQ
- Fix: [ 1113037 ] crash when accessing hi-scores in editor, it is now disabled.
- Fix: [ 1113399 ] Game no longer crashes when right-clicking a disabled Full Load button
- Fix: [ 1114100 ] Dedicated server boots again
- Fix: [ 1114950 ] Game crashed sometimes when there were no industries in the map
- Fix: [ 1115200 ] In the main menu, when starting a new game while the load game dialog is open, openttd asserts.
- Fix: [ 1117538 ] non-stop orders are no longer accidently skipped
- Fix: [ 1116619 ] Generate the correct smoke type for diesel trains
- Fix: [ 1119308 ] Max passengers / mail variables are now 32 bit
- Fix: [ 1109400 ] Better test if a string actually contains any console command
- Fix: [ 1108637 ] 'Play scenario' now loads game options and difficulty, 'Load game' starts game with user-selected values.
- Fix: [ 1143587 ] carriages of newgrfs can be refitted again
- Fix: [ 1117730 ] Production values of temperate-climate banks can now be altered
- Fix: [ 1118810 ] openttd: ship_cmd.c:642 ... Assertion failed. Mapwrap fixed in ship_cmd.c (was implicitely ok before biggermaps).
- Fix: [ 1117327 ] Assertion error on kick. When a company is cleaned all its windows need to be closed. For global vehicle lists, the no-staiton index of -1 was not taken into account
- Fix: [ 1114261 ] Speeding up when pressing ALT+TAB (Windows)
- Fix: [ 1149403 ] Signals dissaper after typing text and pressing enter!. Signs in Scenario Editor have no owner so ignore that.
- Fix: [ 1149766 ] Single tile Bridge in Volcano City scenario. Some bridges still had the old single-tile bridge bug that was caused by improper town growth in combination with DC_AUTO. Fixed the scenario.
- Fix: [ 1119147 ] Stop startup memory corruption crash using optimized MSVC6. MSVC6 workaround as it's too stupid again for its own good
- Fix: [ 1101874 ] Dedicated server now accepts '-g' (load game) as param
- Fix: [ 1155696 ] Crash with german umlauts in station names.
- Fix: [ 1158618 ] Segmentation fault when loading savegame, out of bounds array check.
- Fix: [ 1149487 ] Autosave ignoring settings
- Fix: [ 1024703 ] Infinite access for A:\ (win32). Patch [1171208]. Only requery drive(s) if the user changes a directory, also surpress the OS error box that pops up on some windows machines.
- Fix: [ 1095110 ] Create Lake and draggable Create Desert tools
- Fix: [ 1172878 ] Trains "Go to depot" button: click twice skip to next order
- Fix: [ 1146215 ] Engine power not updated w/auto replace" autoreplace now forces an update of the cache.
- Fix: [ 1173690 ] Path displaying as "C:\\" in saveload window win32-only
- Fix: [ 1179892 ] click & drag removal of road assertion fail.
- Fix: [ 1174237 ] Max loan always in euros, use _opt_ptr instead of _opt
- Fix: [ 1184201 ] AI orders its vehicles to a competitor's truck stop.
- Fix: [ 1188986 ] Song in main menu screen should loop when it ends.
- Fix: [ 1188777 ] Non-existing sprite #5125 (presignal). The DOS grf file trgi.grf has 6 less sprites than the windows one.
- Fix: [ 1190625 ] Changing mapsize crashes game with highlighting.
- Fix: [ 1190896 1184378 ] [NPF] Trains ignoring their railtype (mono, maglev)
- Fix: [ 1202115 ] Clicking shipslist on bouy asserts GetPlayer().
- Fix: [ 1187613 ] No HQ present for competitor, disable 'View HQ' button
- Fix: [ 1193048 ] Pre-signal stays red when there is only a single exit signal
- Fix: [ 1185176 ] Train in tunnel is not properly detected by signal code
- Fix: [newgrf] rotors of custom helicopters are displayed correctly in the hangar window
- Fix: Scenario Editor now handles human-made roads better (try to build a city layout before placing the city, finally that works very nice)
- Fix: [Newgrf] helicopters are correctly recognized
- Fix: [autoreplace] made sure that planes only show planes in replace GUI and helicopters only show helicopters
- Fix: (Work around?) crash when generating tropical maps
- Fix: [autoreplace] Cheaters can no longer exploit autoreplace to get vehicles, that's not invented yet
- Fix: [autoreplace] Fixed a stupid bug introduced in r1687, that made a crash if anybody tried to autoreplace anything but an aircraft
- Fix: expand railroad stations beyond maximum spread
- Fix: [autoreplace] fixed a typo that could prevent autoreplaced aircraft from automatically go to a hangar
- Fix: Hacked clients can no longer be used to build vehicles that are not available yet
- Fix: Minimum profit of vehicles was calculated wrong for Performance Rating
- Fix: no longer a station where you only unload is bad for your town-rating
- Fix: Crash in scenario-editor with terraforming out-of-map bounds.
- Fix: Game would crash if you full-screened with the 'fullscreen' button than chose a resolution from the dropdown box that was no longer valid.
- Fix: Scrolling with the arrow keys is now smooth and it now also scrolls exactly in tile direction if e.g. up and left are pressed
- Fix: many more fixes but I am too tired to list them all
0.3.6 (2005-01-24)
------------------------------------------------------------------------
- Feature: resizable windows. All useful windows are already made resizable.
@@ -207,6 +128,7 @@
- Fix: When deleting an order, the next pointer was not cleared, resulting in some unusual behavoir from time to time
- Fix: You can now also delete automatically found servers by pressing "del"
- Fix: You should no longer be able to delete bridges on any type of underground when there is a vehicle on it
- Fix: your loan is now substracted from your company value
- Add: A brand new set of icons.
- Change: AutoRenew is now a client-side patch instead of a game-side patch
- Change: Removed the 'close ALL windows' from the toolbar since shift+del does this.

View File

@@ -2,7 +2,6 @@
#include "ttd.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "viewport.h"
#include "command.h"
@@ -210,15 +209,15 @@ static bool TerraformTileHeight(TerraformerState *ts, uint tile, int height)
return true;
}
/** Terraform land
* @param x,y coordinates to terraform
* @param p1 corners to terraform.
* @param p2 direction; eg up or down
/* Terraform land
* p1 - corners
* p2 - direction
*/
int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TerraformerState ts;
TileIndex tile;
uint tile;
int direction;
TerraformerHeightMod modheight_data[576];
@@ -267,7 +266,7 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
for(count = ts.tile_table_count; count != 0; count--, ti++) {
uint z, t;
uint tile = *ti;
@@ -289,7 +288,7 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
for(count = ts.tile_table_count; count != 0; count--, ti++) {
DoCommandByTile(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
}
@@ -301,7 +300,7 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
uint til;
mod = ts.modheight;
for (count = ts.modheight_count; count != 0; count--, mod++) {
for(count = ts.modheight_count; count != 0; count--, mod++) {
til = mod->tile;
SetTileHeight(til, mod->height);
@@ -313,7 +312,7 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
for(count = ts.tile_table_count; count != 0; count--, ti++) {
MarkTileDirtyByTile(*ti);
}
}
@@ -322,21 +321,18 @@ int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
/** Levels a selected (rectangle) area of land
* @param x,y end tile of area-drag
* @param p1 start tile of area drag
* @param p2 unused
/*
* p1 - start
*/
int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
{
int size_x, size_y;
int sx, sy;
uint h, curh;
TileIndex tile;
uint tile;
int32 ret, cost, money;
if (p1 > MapSize()) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
// remember level height
@@ -357,11 +353,11 @@ int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
money = GetAvailableMoneyForCommand();
cost = 0;
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile)
curh = TileHeight(tile2);
while (curh != h) {
ret = DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
if (CmdFailed(ret)) break;
ret = DoCommandByTile(tile2, 8, (curh > h)?0:1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
if (ret == CMD_ERROR) break;
cost += ret;
if (flags & DC_EXEC) {
@@ -369,38 +365,42 @@ int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
_additional_cash_required = ret;
return cost - ret;
}
DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
DoCommandByTile(tile2, 8, (curh > h)?0:1, flags, CMD_TERRAFORM_LAND);
}
curh += (curh > h) ? -1 : 1;
}
} END_TILE_LOOP(tile2, size_x, size_y, tile)
END_TILE_LOOP(tile2, size_x, size_y, tile)
return (cost == 0) ? CMD_ERROR : cost;
if (cost == 0) return CMD_ERROR;
return cost;
}
/** Purchase a land area. Actually you only purchase one tile, so
* the name is a bit confusing ;p
* @param x,y the tile the player is purchasing
* @param p1 unused
* @param p2 unused
/* Purchase a land area
* p1 = unused
* p2 = unused
*/
int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TileIndex tile;
uint tile;
int32 cost;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
tile = TILE_FROM_XY(x,y);
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
if (!EnsureNoVehicle(tile))
return CMD_ERROR;
if (IsTileType(tile, MP_UNMOVABLE) && _map5[tile] == 3 && _map_owner[tile] == _current_player)
if (IsTileType(tile, MP_UNMOVABLE) &&
_map5[tile] == 3 &&
_map_owner[tile] == _current_player)
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(cost)) return CMD_ERROR;
if (cost == CMD_ERROR)
return CMD_ERROR;
if (flags & DC_EXEC) {
ModifyTile(tile,
@@ -435,15 +435,9 @@ static int32 ClearTile_Clear(uint tile, byte flags)
return *price;
}
/** Sell a land area. Actually you only sell one tile, so
* the name is a bit confusing ;p
* @param x,y the tile the player is selling
* @param p1 unused
* @param p2 unused
*/
int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TileIndex tile;
uint tile;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -452,12 +446,13 @@ int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER)
return CMD_ERROR;
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
if (!EnsureNoVehicle(tile))
return CMD_ERROR;
if (flags & DC_EXEC)
DoClearSquare(tile);
return - _price.purchase_land * 2;
return - _price.purchase_land*2;
}
@@ -549,49 +544,28 @@ static void AnimateTile_Clear(uint tile)
/* unused */
}
void TileLoopClearHelper(TileIndex tile)
void TileLoopClearHelper(uint tile)
{
byte img_1;
byte img_2;
static const byte img_by_map5[] = { 0, 0, 0, 2, 1, 1, 0, 0 };
TileIndex dirty = INVALID_TILE;
byte img_1, img_2;
static byte img_by_map5[8] = { 0,0,0,2, 1,1,0,0, };
uint dirty = -1;
switch (GetTileType(tile)) {
case MP_CLEAR:
img_1 = img_by_map5[(_map5[tile] & 0x1C) >> 2];
break;
case MP_TREES:
if ((_map2[tile] & 0x30) == 0x20)
img_1 = 1;
else
img_1 = 0;
break;
default:
img_1 = 0;
break;
img_1 = 0;
if (IsTileType(tile, MP_CLEAR)) {
img_1 = img_by_map5[(_map5[tile] & 0x1C) >> 2];
} else if (IsTileType(tile, MP_TREES) && (_map2[tile] & 0x30) == 0x20) {
img_1 = 1;
}
switch (GetTileType(TILE_ADDXY(tile, 1, 0))) {
case MP_CLEAR:
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 1, 0)] & 0x1C) >> 2];
break;
case MP_TREES:
if ((_map2[TILE_ADDXY(tile, 1, 0)] & 0x30) == 0x20)
img_2 = 1;
else
img_2 = 0;
break;
default:
img_2 = 0;
break;
img_2 = 0;
if (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR)) {
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 1, 0)] & 0x1C) >> 2];
} else if (IsTileType(TILE_ADDXY(tile, 1, 0), MP_TREES) && (_map2[TILE_ADDXY(tile, 1, 0)] & 0x30) == 0x20) {
img_2 = 1;
}
if ((_map3_hi[tile] & 0xE0) == 0) {
if ((img_1 & 2) != (img_2 & 2)) {
if (!(_map3_hi[tile] & 0xE0)) {
if ( (img_1&2) != (img_2&2) ) {
_map3_hi[tile] |= 3 << 5;
dirty = tile;
}
@@ -602,25 +576,15 @@ void TileLoopClearHelper(TileIndex tile)
}
}
switch (GetTileType(TILE_ADDXY(tile, 0, 1))) {
case MP_CLEAR:
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 0, 1)] & 0x1C) >> 2];
break;
case MP_TREES:
if ((_map2[TILE_ADDXY(tile, 0, 1)] & 0x30) == 0x20)
img_2 = 1;
else
img_2 = 0;
break;
default:
img_2 = 0;
break;
img_2 = 0;
if (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR)) {
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 0, 1)] & 0x1C) >> 2];
} else if (IsTileType(TILE_ADDXY(tile, 0, 1), MP_TREES) && (_map2[TILE_ADDXY(tile, 0, 1)] & 0x30) == 0x20) {
img_2 = 1;
}
if ((_map3_hi[tile] & 0x1C) == 0) {
if ((img_1 & 2) != (img_2 & 2)) {
if (!(_map3_hi[tile] & 0x1C)) {
if ( (img_1&2) != (img_2&2) ) {
_map3_hi[tile] |= 3 << 2;
dirty = tile;
}
@@ -631,7 +595,7 @@ void TileLoopClearHelper(TileIndex tile)
}
}
if (dirty != INVALID_TILE)
if (dirty != (uint) -1)
MarkTileDirtyByTile(dirty);
}
@@ -776,7 +740,7 @@ void GenerateClearTile(void)
uint32 r;
/* add hills */
i = ScaleByMapSize((Random() & 0x3FF) + 0x400);
i = (Random() & 0x3FF) | 0x400;
do {
tile = TILE_MASK(Random());
if (IsTileType(tile, MP_CLEAR))
@@ -784,7 +748,7 @@ void GenerateClearTile(void)
} while (--i);
/* add grey squares */
i = ScaleByMapSize((Random() & 0x7F) + 0x80);
i = (Random() & 0x7F) | 0x80;
do {
r = Random();
tile = TILE_MASK(r);

307
command.c
View File

@@ -7,8 +7,6 @@
#include "player.h"
#include "network.h"
const char* _cmd_text = NULL;
#define DEF_COMMAND(yyyy) int32 yyyy(int x, int y, uint32 flags, uint32 p1, uint32 p2)
DEF_COMMAND(CmdBuildRailroadTrack);
@@ -24,8 +22,8 @@ DEF_COMMAND(CmdBuildRailroadStation);
DEF_COMMAND(CmdRemoveFromRailroadStation);
DEF_COMMAND(CmdConvertRail);
DEF_COMMAND(CmdBuildSingleSignal);
DEF_COMMAND(CmdRemoveSingleSignal);
DEF_COMMAND(CmdBuildSignals);
DEF_COMMAND(CmdRemoveSignals);
DEF_COMMAND(CmdTerraformLand);
@@ -39,7 +37,9 @@ DEF_COMMAND(CmdBuildTrainWaypoint);
DEF_COMMAND(CmdRenameWaypoint);
DEF_COMMAND(CmdRemoveTrainWaypoint);
DEF_COMMAND(CmdBuildRoadStop);
DEF_COMMAND(CmdBuildTruckStation);
DEF_COMMAND(CmdBuildBusStation);
DEF_COMMAND(CmdBuildLongRoad);
DEF_COMMAND(CmdRemoveLongRoad);
@@ -65,7 +65,7 @@ DEF_COMMAND(CmdStartStopTrain);
DEF_COMMAND(CmdSellRailWagon);
DEF_COMMAND(CmdSendTrainToDepot);
DEF_COMMAND(CmdTrainGotoDepot);
DEF_COMMAND(CmdForceTrainProceed);
DEF_COMMAND(CmdReverseTrainDirection);
@@ -77,8 +77,10 @@ DEF_COMMAND(CmdChangeTrainServiceInt);
DEF_COMMAND(CmdRestoreOrderIndex);
DEF_COMMAND(CmdBuildIndustry);
//DEF_COMMAND(CmdDestroyIndustry);
DEF_COMMAND(CmdBuildCompanyHQ);
DEF_COMMAND(CmdDestroyCompanyHQ);
DEF_COMMAND(CmdSetPlayerFace);
DEF_COMMAND(CmdSetPlayerColor);
@@ -113,6 +115,7 @@ DEF_COMMAND(CmdTurnRoadVeh);
DEF_COMMAND(CmdChangeRoadVehServiceInt);
DEF_COMMAND(CmdPause);
DEF_COMMAND(CmdResume);
DEF_COMMAND(CmdBuyShareInCompany);
DEF_COMMAND(CmdSellShareInCompany);
@@ -124,6 +127,7 @@ DEF_COMMAND(CmdRenameTown);
DEF_COMMAND(CmdDoTownAction);
DEF_COMMAND(CmdSetRoadDriveSide);
DEF_COMMAND(CmdSetTownNameType);
DEF_COMMAND(CmdChangeDifficultyLevel);
DEF_COMMAND(CmdChangePatchSetting);
@@ -135,6 +139,15 @@ DEF_COMMAND(CmdSendShipToDepot);
DEF_COMMAND(CmdChangeShipServiceInt);
DEF_COMMAND(CmdRefitShip);
DEF_COMMAND(CmdStartNewGame);
DEF_COMMAND(CmdLoadGame);
DEF_COMMAND(CmdCreateScenario);
DEF_COMMAND(CmdSetSinglePlayer);
DEF_COMMAND(CmdSetNewLandscapeType);
DEF_COMMAND(CmdGenRandomNewGame);
DEF_COMMAND(CmdCloneOrder);
DEF_COMMAND(CmdClearArea);
@@ -150,152 +163,153 @@ DEF_COMMAND(CmdLevelLand);
DEF_COMMAND(CmdRefitRailVehicle);
DEF_COMMAND(CmdBuildSignalTrack);
DEF_COMMAND(CmdRemoveSignalTrack);
DEF_COMMAND(CmdStartScenario);
DEF_COMMAND(CmdBuildManySignals);
DEF_COMMAND(CmdReplaceVehicle);
/* The master command table */
static const Command _command_proc_table[] = {
{CmdBuildRailroadTrack, 0}, /* 0 */
{CmdRemoveRailroadTrack, 0}, /* 1 */
{CmdBuildSingleRail, 0}, /* 2 */
{CmdRemoveSingleRail, 0}, /* 3 */
{CmdLandscapeClear, 0}, /* 4 */
{CmdBuildBridge, 0}, /* 5 */
{CmdBuildRailroadStation, 0}, /* 6 */
{CmdBuildTrainDepot, 0}, /* 7 */
{CmdBuildSingleSignal, 0}, /* 8 */
{CmdRemoveSingleSignal, 0}, /* 9 */
{CmdTerraformLand, 0}, /* 10 */
{CmdPurchaseLandArea, 0}, /* 11 */
{CmdSellLandArea, 0}, /* 12 */
{CmdBuildTunnel, 0}, /* 13 */
{CmdRemoveFromRailroadStation, 0}, /* 14 */
{CmdConvertRail, 0}, /* 15 */
{CmdBuildTrainWaypoint, 0}, /* 16 */
{CmdRenameWaypoint, 0}, /* 17 */
{CmdRemoveTrainWaypoint, 0}, /* 18 */
{NULL, 0}, /* 19 */
{NULL, 0}, /* 20 */
{CmdBuildRoadStop, 0}, /* 21 */
{NULL, 0}, /* 22 */
{CmdBuildLongRoad, 0}, /* 23 */
{CmdRemoveLongRoad, 0}, /* 24 */
{CmdBuildRoad, 0}, /* 25 */
{CmdRemoveRoad, 0}, /* 26 */
{CmdBuildRoadDepot, 0}, /* 27 */
{NULL, 0}, /* 28 */
{CmdBuildAirport, 0}, /* 29 */
{CmdBuildDock, 0}, /* 30 */
{CmdBuildShipDepot, 0}, /* 31 */
{CmdBuildBuoy, 0}, /* 32 */
{CmdPlantTree, 0}, /* 33 */
{CmdBuildRailVehicle, 0}, /* 34 */
{CmdMoveRailVehicle, 0}, /* 35 */
{CmdStartStopTrain, 0}, /* 36 */
{NULL, 0}, /* 37 */
{CmdSellRailWagon, 0}, /* 38 */
{CmdSendTrainToDepot, 0}, /* 39 */
{CmdForceTrainProceed, 0}, /* 40 */
{CmdReverseTrainDirection, 0}, /* 41 */
static CommandProc * const _command_proc_table[] = {
CmdBuildRailroadTrack, /* 0 */
CmdRemoveRailroadTrack, /* 1 */
CmdBuildSingleRail, /* 2 */
CmdRemoveSingleRail, /* 3 */
CmdLandscapeClear, /* 4 */
CmdBuildBridge, /* 5 */
CmdBuildRailroadStation, /* 6 */
CmdBuildTrainDepot, /* 7 */
CmdBuildSignals, /* 8 */
CmdRemoveSignals, /* 9 */
CmdTerraformLand, /* 10 */
CmdPurchaseLandArea, /* 11 */
CmdSellLandArea, /* 12 */
CmdBuildTunnel, /* 13 */
CmdRemoveFromRailroadStation, /* 14 */
CmdConvertRail, /* 15 */
CmdBuildTrainWaypoint, /* 16 */
CmdRenameWaypoint, /* 17 */
CmdRemoveTrainWaypoint, /* 18 */
CmdBuildTruckStation, /* 19 */
NULL, /* 20 */
CmdBuildBusStation, /* 21 */
NULL, /* 22 */
CmdBuildLongRoad, /* 23 */
CmdRemoveLongRoad, /* 24 */
CmdBuildRoad, /* 25 */
CmdRemoveRoad, /* 26 */
CmdBuildRoadDepot, /* 27 */
NULL, /* 28 */
CmdBuildAirport, /* 29 */
CmdBuildDock, /* 30 */
CmdBuildShipDepot, /* 31 */
CmdBuildBuoy, /* 32 */
CmdPlantTree, /* 33 */
CmdBuildRailVehicle, /* 34 */
CmdMoveRailVehicle, /* 35 */
CmdStartStopTrain, /* 36 */
NULL, /* 37 */
CmdSellRailWagon, /* 38 */
CmdTrainGotoDepot, /* 39 */
CmdForceTrainProceed, /* 40 */
CmdReverseTrainDirection, /* 41 */
{CmdModifyOrder, 0}, /* 42 */
{CmdSkipOrder, 0}, /* 43 */
{CmdDeleteOrder, 0}, /* 44 */
{CmdInsertOrder, 0}, /* 45 */
CmdModifyOrder, /* 42 */
CmdSkipOrder, /* 43 */
CmdDeleteOrder, /* 44 */
CmdInsertOrder, /* 45 */
{CmdChangeTrainServiceInt, 0}, /* 46 */
CmdChangeTrainServiceInt, /* 46 */
{CmdBuildIndustry, 0}, /* 47 */
{CmdBuildCompanyHQ, 0}, /* 48 */
{CmdSetPlayerFace, 0}, /* 49 */
{CmdSetPlayerColor, 0}, /* 50 */
CmdBuildIndustry, /* 47 */
CmdBuildCompanyHQ, /* 48 */
CmdSetPlayerFace, /* 49 */
CmdSetPlayerColor, /* 50 */
{CmdIncreaseLoan, 0}, /* 51 */
{CmdDecreaseLoan, 0}, /* 52 */
CmdIncreaseLoan, /* 51 */
CmdDecreaseLoan, /* 52 */
{CmdWantEnginePreview, 0}, /* 53 */
CmdWantEnginePreview, /* 53 */
{CmdNameVehicle, 0}, /* 54 */
{CmdRenameEngine, 0}, /* 55 */
CmdNameVehicle, /* 54 */
CmdRenameEngine, /* 55 */
{CmdChangeCompanyName, 0}, /* 56 */
{CmdChangePresidentName, 0}, /* 57 */
CmdChangeCompanyName, /* 56 */
CmdChangePresidentName, /* 57 */
{CmdRenameStation, 0}, /* 58 */
CmdRenameStation, /* 58 */
{CmdSellAircraft, 0}, /* 59 */
{CmdStartStopAircraft, 0}, /* 60 */
CmdSellAircraft, /* 59 */
CmdStartStopAircraft, /* 60 */
CmdBuildAircraft, /* 61 */
CmdSendAircraftToHangar, /* 62 */
CmdChangeAircraftServiceInt, /* 63 */
CmdRefitAircraft, /* 64 */
{CmdBuildAircraft, 0}, /* 61 */
{CmdSendAircraftToHangar, 0}, /* 62 */
{CmdChangeAircraftServiceInt, 0}, /* 63 */
{CmdRefitAircraft, 0}, /* 64 */
CmdPlaceSign, /* 65 */
CmdRenameSign, /* 66 */
{CmdPlaceSign, 0}, /* 65 */
{CmdRenameSign, 0}, /* 66 */
CmdBuildRoadVeh, /* 67 */
CmdStartStopRoadVeh, /* 68 */
CmdSellRoadVeh, /* 69 */
CmdSendRoadVehToDepot, /* 70 */
CmdTurnRoadVeh, /* 71 */
CmdChangeRoadVehServiceInt, /* 72 */
{CmdBuildRoadVeh, 0}, /* 67 */
{CmdStartStopRoadVeh, 0}, /* 68 */
{CmdSellRoadVeh, 0}, /* 69 */
{CmdSendRoadVehToDepot, 0}, /* 70 */
{CmdTurnRoadVeh, 0}, /* 71 */
{CmdChangeRoadVehServiceInt, 0}, /* 72 */
CmdPause, /* 73 */
{CmdPause, CMD_SERVER}, /* 73 */
CmdBuyShareInCompany, /* 74 */
CmdSellShareInCompany, /* 75 */
CmdBuyCompany, /* 76 */
{CmdBuyShareInCompany, 0}, /* 74 */
{CmdSellShareInCompany, 0}, /* 75 */
{CmdBuyCompany, 0}, /* 76 */
CmdBuildTown, /* 77 */
NULL, /* 78 */
NULL, /* 79 */
CmdRenameTown, /* 80 */
CmdDoTownAction, /* 81 */
{CmdBuildTown, CMD_OFFLINE}, /* 77 */
{NULL, 0}, /* 78 */
{NULL, 0}, /* 79 */
{CmdRenameTown, CMD_SERVER}, /* 80 */
{CmdDoTownAction, 0}, /* 81 */
CmdSetRoadDriveSide, /* 82 */
CmdSetTownNameType, /* 83 */
NULL, /* 84 */
CmdChangeDifficultyLevel, /* 85 */
{CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */
{NULL, 0}, /* 83 */
{NULL, 0}, /* 84 */
{CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */
CmdStartStopShip, /* 86 */
CmdSellShip, /* 87 */
CmdBuildShip, /* 88 */
CmdSendShipToDepot, /* 89 */
CmdChangeShipServiceInt, /* 90 */
CmdRefitShip, /* 91 */
{CmdStartStopShip, 0}, /* 86 */
{CmdSellShip, 0}, /* 87 */
{CmdBuildShip, 0}, /* 88 */
{CmdSendShipToDepot, 0}, /* 89 */
{CmdChangeShipServiceInt, 0}, /* 90 */
{CmdRefitShip, 0}, /* 91 */
CmdStartNewGame, /* 92 */
CmdLoadGame, /* 93 */
CmdCreateScenario, /* 94 */
CmdSetSinglePlayer, /* 95 */
NULL, /* 96 */
CmdSetNewLandscapeType, /* 97 */
{NULL, 0}, /* 92 */
{NULL, 0}, /* 93 */
{NULL, 0}, /* 94 */
{NULL, 0}, /* 95 */
{NULL, 0}, /* 96 */
{NULL, 0}, /* 97 */
{NULL, 0}, /* 98 */
CmdGenRandomNewGame, /* 98 */
{CmdCloneOrder, 0}, /* 99 */
CmdCloneOrder, /* 99 */
{CmdClearArea, 0}, /* 100 */
{NULL, 0}, /* 101 */
CmdClearArea, /* 100 */
CmdResume, /* 101 */
{CmdMoneyCheat, CMD_OFFLINE}, /* 102 */
{CmdBuildCanal, 0}, /* 103 */
{CmdPlayerCtrl, 0}, /* 104 */
CmdMoneyCheat, /* 102 */
CmdBuildCanal, /* 103 */
CmdPlayerCtrl, /* 104 */
{CmdLevelLand, 0}, /* 105 */
CmdLevelLand, /* 105 */
{CmdRefitRailVehicle, 0}, /* 106 */
{CmdRestoreOrderIndex, 0}, /* 107 */
{CmdBuildLock, 0}, /* 108 */
{NULL, 0}, /* 109 */
{CmdBuildSignalTrack, 0}, /* 110 */
{CmdRemoveSignalTrack, 0}, /* 111 */
{NULL, 0}, /* 112 */
{CmdGiveMoney, 0}, /* 113 */
{CmdChangePatchSetting, CMD_SERVER}, /* 114 */
{CmdReplaceVehicle, 0}, /* 115 */
CmdRefitRailVehicle, /* 106 */
CmdRestoreOrderIndex, /* 107 */
CmdBuildLock, /* 108 */
CmdStartScenario, /* 109 */
CmdBuildManySignals, /* 110 */
//CmdDestroyIndustry, /* 109 */
CmdDestroyCompanyHQ, /* 111 */
CmdGiveMoney, /* 112 */
CmdChangePatchSetting, /* 113 */
CmdReplaceVehicle, /* 114 */
};
/* This function range-checks a cmd, and checks if the cmd is not NULL */
@@ -303,14 +317,12 @@ bool IsValidCommand(uint cmd)
{
cmd = cmd & 0xFF;
if (cmd >= lengthof(_command_proc_table) || _command_proc_table[cmd].proc == NULL)
if (cmd >= lengthof(_command_proc_table) || _command_proc_table[cmd] == NULL)
return false;
return true;
}
byte GetCommandFlags(uint cmd) {return _command_proc_table[cmd & 0xFF].flags;}
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
{
return DoCommand(TileX(tile) * 16, TileY(tile) * 16, p1, p2, flags, procc);
@@ -324,13 +336,7 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
int32 res;
CommandProc *proc;
/* Do not even think about executing out-of-bounds tile-commands */
if (TILE_FROM_XY(x,y) > MapSize()) {
_cmd_text = NULL;
return CMD_ERROR;
}
proc = _command_proc_table[procc].proc;
proc = _command_proc_table[procc];
if (_docommand_recursive == 0) {
_error_message = INVALID_STRING_ID;
@@ -345,7 +351,7 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
// only execute the test call if it's toplevel, or we're not execing.
if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
res = proc(x, y, flags&~DC_EXEC, p1, p2);
if (CmdFailed(res)) {
if ((uint32)res >> 16 == 0x8000) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
goto error;
}
@@ -357,7 +363,6 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
if (!(flags & DC_EXEC)) {
_docommand_recursive--;
_cmd_text = NULL;
return res;
}
}
@@ -365,11 +370,10 @@ int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
/* Execute the command here. All cost-relevant functions set the expenses type
* themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */
res = proc(x, y, flags, p1, p2);
if (CmdFailed(res)) {
if ((uint32)res >> 16 == 0x8000) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
error:
_docommand_recursive--;
_cmd_text = NULL;
return CMD_ERROR;
}
@@ -378,13 +382,12 @@ error:
SubtractMoneyFromPlayer(res);
}
_cmd_text = NULL;
return res;
}
int32 GetAvailableMoneyForCommand(void)
{
PlayerID pid = _current_player;
uint pid = _current_player;
if (pid >= MAX_PLAYERS) return 0x7FFFFFFF; // max int
return DEREF_PLAYER(pid)->player_money;
}
@@ -401,12 +404,6 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
int x = TileX(tile) * 16;
int y = TileY(tile) * 16;
/* Do not even think about executing out-of-bounds tile-commands */
if (tile > MapSize()) {
_cmd_text = NULL;
return false;
}
assert(_docommand_recursive == 0);
_error_message = INVALID_STRING_ID;
@@ -416,7 +413,6 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
// spectator has no rights.
if (_current_player == OWNER_SPECTATOR) {
ShowErrorMessage(_error_message, _error_message_2, x, y);
_cmd_text = NULL;
return false;
}
@@ -426,7 +422,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
// get pointer to command handler
assert((cmd & 0xFF) < lengthof(_command_proc_table));
proc = _command_proc_table[cmd & 0xFF].proc;
proc = _command_proc_table[cmd & 0xFF];
// Some commands have a different output in dryrun than the realrun
// e.g.: if you demolish a whole town, the dryrun would say okay.
@@ -441,8 +437,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
(cmd & 0xFF) == CMD_CLEAR_AREA ||
(cmd & 0xFF) == CMD_CONVERT_RAIL ||
(cmd & 0xFF) == CMD_LEVEL_LAND ||
(cmd & 0xFF) == CMD_REMOVE_ROAD ||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
(cmd & 0xFF) == CMD_REMOVE_ROAD;
_docommand_recursive = 1;
@@ -450,7 +445,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
if (_shift_pressed && _current_player == _local_player && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
// estimate the cost.
res = proc(x, y, flags, p1, p2);
if (CmdFailed(res)) {
if ((uint32)res >> 16 == 0x8000) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
ShowErrorMessage(_error_message, _error_message_2, x, y);
} else {
@@ -458,7 +453,6 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
}
_docommand_recursive = 0;
_cmd_text = NULL;
return false;
}
@@ -466,7 +460,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
// first test if the command can be executed.
res = proc(x,y, flags, p1, p2);
if (CmdFailed(res)) {
if ((uint32)res >> 16 == 0x8000) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
goto show_error;
}
@@ -480,7 +474,6 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
NetworkSend_Command(tile, p1, p2, cmd, callback);
_docommand_recursive = 0;
_cmd_text = NULL;
return true;
}
#endif /* ENABLE_NETWORK */
@@ -498,7 +491,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
assert(res == res2); // sanity check
} else {
if (CmdFailed(res2)) {
if ((uint32)res2 >> 16 == 0x8000) {
if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
goto show_error;
}
@@ -519,7 +512,6 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
_docommand_recursive = 0;
if (callback) callback(true, tile, p1, p2);
_cmd_text = NULL;
return true;
show_error:
@@ -531,6 +523,5 @@ callb_err:
_docommand_recursive = 0;
if (callback) callback(false, tile, p1, p2);
_cmd_text = NULL;
return false;
}

View File

@@ -24,7 +24,8 @@ enum {
CMD_RENAME_WAYPOINT = 17,
CMD_REMOVE_TRAIN_WAYPOINT = 18,
CMD_BUILD_ROAD_STOP = 21,
CMD_BUILD_TRUCK_STATION = 19,
CMD_BUILD_BUS_STATION = 21,
CMD_BUILD_LONG_ROAD = 23,
CMD_REMOVE_LONG_ROAD = 24,
CMD_BUILD_ROAD = 25,
@@ -104,6 +105,8 @@ enum {
CMD_DO_TOWN_ACTION = 81,
CMD_SET_ROAD_DRIVE_SIDE = 82,
CMD_SET_TOWN_NAME_TYPE = 83,
CMD_CHANGE_DIFFICULTY_LEVEL = 85,
@@ -114,9 +117,20 @@ enum {
CMD_CHANGE_SHIP_SERVICE_INT = 90,
CMD_REFIT_SHIP = 91,
CMD_START_NEW_GAME = 92,
CMD_LOAD_GAME = 93,
CMD_CREATE_SCENARIO = 94,
CMD_SET_SINGLE_PLAYER = 95,
CMD_SET_NEW_LANDSCAPE_TYPE = 97,
CMD_GEN_RANDOM_NEW_GAME = 98,
CMD_CLONE_ORDER = 99,
CMD_CLEAR_AREA = 100,
CMD_RESUME = 101,
CMD_MONEY_CHEAT = 102,
CMD_BUILD_CANAL = 103,
@@ -127,13 +141,15 @@ enum {
CMD_RESTORE_ORDER_INDEX = 107,
CMD_BUILD_LOCK = 108,
CMD_BUILD_SIGNAL_TRACK = 110,
CMD_REMOVE_SIGNAL_TRACK = 111,
CMD_START_SCENARIO = 109,
CMD_BUILD_MANY_SIGNALS = 110,
CMD_GIVE_MONEY = 113,
CMD_CHANGE_PATCH_SETTING = 114,
//CMD_DESTROY_INDUSTRY = 109,
CMD_DESTROY_COMPANY_HQ = 111,
CMD_GIVE_MONEY = 112,
CMD_CHANGE_PATCH_SETTING = 113,
CMD_REPLACE_VEHICLE = 115,
CMD_REPLACE_VEHICLE = 114,
};
enum {
@@ -159,41 +175,14 @@ enum {
CMD_SHOW_NO_ERROR = 0x2000,
};
/** Command flags for the command table
* @see _command_proc_table
*/
enum {
CMD_SERVER = 0x1, /// the command can only be initiated by the server
CMD_OFFLINE = 0x2, /// the command cannot be executed in a multiplayer game; single-player only
};
typedef struct Command {
CommandProc *proc;
byte flags;
} Command;
//#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
#define return_cmd_error(errcode) do { return CMD_ERROR | (errcode); } while (0)
/**
* Check the return value of a DoCommand*() function
* @param res the resulting value from the command to be checked
* @return Return true if the command failed, false otherwise
*/
static inline bool CmdFailed(int32 res)
{
// lower 16bits are the StringID of the possible error
return res <= (CMD_ERROR | INVALID_STRING_ID);
}
/* command.c */
int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc);
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
extern const char* _cmd_text; // Text, which gets sent with a command
bool IsValidCommand(uint cmd);
byte GetCommandFlags(uint cmd);
int32 GetAvailableMoneyForCommand(void);
#endif /* COMMAND_H */

1936
console.c

File diff suppressed because it is too large Load Diff

220
console.h
View File

@@ -1,118 +1,112 @@
#ifndef CONSOLE_H
#define CONSOLE_H
// maximum length of a typed in command
#define ICON_CMDLN_SIZE 255
// maximum length of a totally expanded command
#define ICON_MAX_STREAMSIZE 1024
// ** console parser ** //
typedef enum IConsoleVarTypes {
typedef enum _iconsole_var_types {
ICONSOLE_VAR_NONE,
ICONSOLE_VAR_BOOLEAN,
ICONSOLE_VAR_BYTE,
ICONSOLE_VAR_UINT8,
ICONSOLE_VAR_UINT16,
ICONSOLE_VAR_UINT32,
ICONSOLE_VAR_INT16,
ICONSOLE_VAR_INT32,
ICONSOLE_VAR_STRING
} IConsoleVarTypes;
ICONSOLE_VAR_STRING,
ICONSOLE_VAR_POINTER,
ICONSOLE_VAR_REFERENCE,
ICONSOLE_VAR_UNKNOWN
} _iconsole_var_types;
typedef enum IConsoleModes {
typedef enum {
ICONSOLE_FULL,
ICONSOLE_OPENED,
ICONSOLE_CLOSED
} IConsoleModes;
} _iconsole_modes;
typedef enum IConsoleHookTypes {
typedef enum _iconsole_hook_types {
ICONSOLE_HOOK_ACCESS,
ICONSOLE_HOOK_PRE_ACTION,
ICONSOLE_HOOK_POST_ACTION
} IConsoleHookTypes;
ICONSOLE_HOOK_BEFORE_CHANGE,
ICONSOLE_HOOK_BEFORE_EXEC,
ICONSOLE_HOOK_AFTER_CHANGE,
ICONSOLE_HOOK_AFTER_EXEC
} _iconsole_hook_types;
/** --Hooks--
* Hooks are certain triggers get get accessed/executed on either
* access, before execution/change or after execution/change. This allows
* for general flow of permissions or special action needed in some cases
*/
typedef bool IConsoleHook(void);
typedef struct IConsoleHooks{
IConsoleHook *access; // trigger when accessing the variable/command
IConsoleHook *pre; // trigger before the variable/command is changed/executed
IConsoleHook *post; // trigger after the variable/command is changed/executed
} IConsoleHooks;
struct _iconsole_var;
typedef bool (*iconsole_var_hook)(struct _iconsole_var* hook_var);
/** --Commands--
* Commands are commands, or functions. They get executed once and any
* effect they produce are carried out. The arguments to the commands
* are given to them, each input word seperated by a double-quote (") is an argument
* If you want to handle multiple words as one, enclose them in double-quotes
* eg. 'say "hello sexy boy"'
*/
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
typedef struct _iconsole_var {
// --------------- //
union {
void* addr;
bool* bool_;
byte* byte_;
uint16* uint16_;
uint32* uint32_;
int16* int16_;
int32* int32_;
char* string_;
struct _iconsole_var* reference_;
} data;
char* name;
_iconsole_var_types type;
// -------------- //
iconsole_var_hook hook_access;
iconsole_var_hook hook_before_change;
iconsole_var_hook hook_after_change;
// -------------- //
struct _iconsole_var* _next;
bool _malloc;
} _iconsole_var;
struct IConsoleCmd;
typedef struct IConsoleCmd {
char *name; // name of command
struct IConsoleCmd *next; // next command in list
struct _iconsole_cmd;
typedef bool (*iconsole_cmd_hook)(struct _iconsole_cmd* hook_cmd);
IConsoleCmdProc *proc; // process executed when command is typed
IConsoleHooks hook; // any special trigger action that needs executing
} IConsoleCmd;
typedef _iconsole_var* (*_iconsole_cmd_addr)(byte argc, char* argv[], byte argt[]);
/** --Variables--
* Variables are pointers to real ingame variables which allow for
* changing while ingame. After changing they keep their new value
* and can be used for debugging, gameplay, etc. It accepts:
* - no arguments; just print out current value
* - '= <new value>' to assign a new value to the variable
* - '++' to increase value by one
* - '--' to decrease value by one
*/
struct IConsoleVar;
typedef struct IConsoleVar {
char *name; // name of the variable
struct IConsoleVar *next; // next variable in list
typedef struct _iconsole_cmd {
// -------------- //
_iconsole_cmd_addr addr;
char* name;
// -------------- //
iconsole_cmd_hook hook_access;
iconsole_cmd_hook hook_before_exec;
iconsole_cmd_hook hook_after_exec;
// -------------- //
void* _next;
} _iconsole_cmd;
void *addr; // the address where the variable is pointing at
uint32 size; // size of the variable, used for strings
char *help; // the optional help string shown when requesting information
IConsoleVarTypes type; // type of variable (for correct assignment/output)
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
IConsoleHooks hook; // any special trigger action that needs executing
} IConsoleVar;
void IConsoleAliasRegister(const char* name, const char* cmdline);
/** --Aliases--
* Aliases are like shortcuts for complex functions, variable assignments,
* etc. You can use a simple alias to rename a longer command (eg 'lv' for
* 'list_vars' for example), or concatenate more commands into one
* (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
* given to them in the command line.
* - "%A - %Z" substitute arguments 1 t/m 26
* - "%+" lists all parameters keeping them seperated
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
* - ";" allows for combining commands (see example 'ng')
*/
struct IConsoleAlias;
typedef struct IConsoleAlias {
char *name; // name of the alias
struct IConsoleAlias *next; // next alias in list
typedef struct _iconsole_alias {
// -------------- //
char * cmdline;
char* name;
void* _next;
} _iconsole_alias;
char *cmdline; // command(s) that is/are being aliased
} IConsoleAlias;
_iconsole_alias* IConsoleAliasGet(const char* name);
// ** console parser ** //
IConsoleCmd *_iconsole_cmds; // list of registred commands
IConsoleVar *_iconsole_vars; // list of registred vars
IConsoleAlias *_iconsole_aliases; // list of registred aliases
// ** console colors/modes ** //
VARDEF byte _icolour_def;
VARDEF byte _icolour_err;
VARDEF byte _icolour_warn;
VARDEF byte _icolour_dbg;
VARDEF byte _icolour_cmd;
VARDEF IConsoleModes _iconsole_mode;
_iconsole_cmd* _iconsole_cmds; // list of registred commands
_iconsole_var* _iconsole_vars; // list of registred vars
_iconsole_alias* _iconsole_aliases; // list of registred aliases
// ** console colors ** //
VARDEF byte _iconsole_color_default;
VARDEF byte _iconsole_color_error;
VARDEF byte _iconsole_color_warning;
VARDEF byte _iconsole_color_debug;
VARDEF byte _iconsole_color_commands;
VARDEF _iconsole_modes _iconsole_mode;
// ** ttd.c functions ** //
void SetDebugString(const char* s);
// ** console functions ** //
void IConsoleInit(void);
void IConsoleClear(void);
void IConsoleFree(void);
@@ -122,42 +116,44 @@ void IConsoleClose(void);
void IConsoleOpen(void);
// ** console cmd buffer ** //
void IConsoleHistoryAdd(const char *cmd);
void IConsoleHistoryNavigate(signed char direction);
void IConsoleCmdBufferAdd(const char* cmd);
void IConsoleCmdBufferNavigate(signed char direction);
// ** console output ** //
void IConsolePrint(uint16 color_code, const char *string);
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
void IConsoleDebug(const char *string);
void IConsoleWarning(const char *string);
void IConsoleError(const char *string);
void IConsolePrint(uint16 color_code, const char* string);
void CDECL IConsolePrintF(uint16 color_code, const char* s, ...);
void IConsoleDebug(const char* string);
void IConsoleError(const char* string);
void IConsoleWarning(const char* string);
// *** Commands *** //
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
void IConsoleAliasRegister(const char *name, const char *cmd);
IConsoleCmd *IConsoleCmdGet(const char *name);
IConsoleAlias *IConsoleAliasGet(const char *name);
void IConsoleCmdRegister(const char* name, _iconsole_cmd_addr addr);
_iconsole_cmd* IConsoleCmdGet(const char* name);
// *** Variables *** //
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
IConsoleVar* IConsoleVarGet(const char *name);
void IConsoleVarPrintGetValue(const IConsoleVar *var);
void IConsoleVarPrintSetValue(const IConsoleVar *var);
void IConsoleVarRegister(const char* name, void* addr, _iconsole_var_types type);
void IConsoleVarMemRegister(const char* name, _iconsole_var_types type);
void IConsoleVarInsert(_iconsole_var* item_new, const char* name);
_iconsole_var* IConsoleVarGet(const char* name);
_iconsole_var* IConsoleVarAlloc(_iconsole_var_types type);
void IConsoleVarFree(_iconsole_var* var);
void IConsoleVarSetString(_iconsole_var* var, const char* string);
void IConsoleVarSetValue(_iconsole_var* var, int value);
void IConsoleVarDump(const _iconsole_var* var, const char* dump_desc);
// *** Parser *** //
void IConsoleCmdExec(const char *cmdstr);
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[]);
// ** console std lib (register ingame commands/aliases/variables) ** //
void IConsoleCmdExec(const char* cmdstr);
// ** console std lib ** //
void IConsoleStdLibRegister(void);
// ** Hooking code ** //
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
// ** hook code ** //
void IConsoleVarHook(const char* name, _iconsole_hook_types type, iconsole_var_hook proc);
void IConsoleCmdHook(const char* name, _iconsole_hook_types type, iconsole_cmd_hook proc);
bool IConsoleVarHookHandle(_iconsole_var* hook_var, _iconsole_hook_types type);
bool IConsoleCmdHookHandle(_iconsole_cmd* hook_cmd, _iconsole_hook_types type);
// ** Supporting functions **//
bool GetArgumentInteger(uint32 *value, const char *arg);
#endif /* CONSOLE_H */

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

98
debug.c
View File

@@ -1,98 +0,0 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdarg.h>
#include "ttd.h"
#include "console.h"
#include "debug.h"
int _debug_ai_level;
int _debug_grf_level;
int _debug_map_level;
int _debug_misc_level;
int _debug_ms_level;
int _debug_net_level;
int _debug_spritecache_level;
int _debug_oldloader_level;
int _debug_npf_level;
void CDECL debug(const char *s, ...)
{
va_list va;
char buf[1024];
va_start(va, s);
vsnprintf(buf, lengthof(buf), s, va);
va_end(va);
fprintf(stderr, "dbg: %s\n", buf);
IConsoleDebug(buf);
}
void SetDebugString(const char *s)
{
int v;
char *end;
const char *t;
typedef struct DebugLevel {
const char* name;
int* level;
} DebugLevel;
#define DEBUG_LEVEL(x) { #x, &_debug_##x##_level }
static const DebugLevel debug_level[] = {
DEBUG_LEVEL(ai),
DEBUG_LEVEL(grf),
DEBUG_LEVEL(map),
DEBUG_LEVEL(misc),
DEBUG_LEVEL(ms),
DEBUG_LEVEL(net),
DEBUG_LEVEL(spritecache),
DEBUG_LEVEL(oldloader),
DEBUG_LEVEL(npf)
};
#undef DEBUG_LEVEL
// global debugging level?
if (*s >= '0' && *s <= '9') {
const DebugLevel *i;
v = strtoul(s, &end, 0);
s = end;
for (i = debug_level; i != endof(debug_level); ++i)
*i->level = v;
}
// individual levels
for(;;) {
const DebugLevel *i;
int *p;
// skip delimiters
while (*s == ' ' || *s == ',' || *s == '\t') s++;
if (*s == '\0') break;
t = s;
while (*s >= 'a' && *s <= 'z') s++;
// check debugging levels
p = NULL;
for (i = debug_level; i != endof(debug_level); ++i)
if (s == t + strlen(i->name) && strncmp(t, i->name, s - t) == 0) {
p = i->level;
break;
}
if (*s == '=') s++;
v = strtoul(s, &end, 0);
s = end;
if (p != NULL)
*p = v;
else {
ShowInfoF("Unknown debug level '%.*s'", s - t, t);
return;
}
}
}

24
debug.h
View File

@@ -1,24 +0,0 @@
#ifndef DEBUG_H
#define DEBUG_H
#ifdef NO_DEBUG_MESSAGES
#define DEBUG(name, level)
#else
#define DEBUG(name, level) if (level == 0 || _debug_ ## name ## _level >= level) debug
extern int _debug_ai_level;
extern int _debug_grf_level;
extern int _debug_map_level;
extern int _debug_misc_level;
extern int _debug_ms_level;
extern int _debug_net_level;
extern int _debug_spritecache_level;
extern int _debug_oldloader_level;
extern int _debug_npf_level;
#endif
void CDECL debug(const char *s, ...);
void SetDebugString(const char *s);
#endif

View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "network.h"
#include "hal.h"
@@ -33,27 +32,24 @@
# define STDIN 0 /* file descriptor for standard input */
#endif
#ifdef __MORPHOS__
/* Voids the fork, option will be disabled for MorphOS build anyway, because
* MorphOS doesn't support forking (could only implemented with lots of code
* changes here). */
int fork(void) { return -1; }
int dup2(int oldd, int newd) { return -1; }
/* voids the fork, option will be disabled for morphos build anyway, because MorphOS
* doesn't support forking (could only implemented with lots of code changes here).
*/
int morphos_dummy_fork() { return -1; }
#define fork morphos_dummy_fork
#endif
// This file handles all dedicated-server in- and outputs
static void *_dedicated_video_mem;
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
extern void SwitchMode(int new_mode);
#ifdef UNIX
/* We want to fork our dedicated server */
void DedicatedFork(void)
{
/* Fork the program */
pid_t pid = fork();
switch (pid) {
_dedicated_pid = fork();
switch (_dedicated_pid) {
case -1:
perror("Unable to fork");
exit(1);
@@ -68,18 +64,18 @@ void DedicatedFork(void)
}
/* Redirect stdout and stderr to log-file */
if (dup2(fileno(_log_file_fd), fileno(stdout)) == -1) {
perror("Rerouting stdout");
perror("Re-routing stdout");
exit(1);
}
if (dup2(fileno(_log_file_fd), fileno(stderr)) == -1) {
perror("Rerouting stderr");
perror("Re-routing stderr");
exit(1);
}
break;
default:
// We're the parent
printf("Loading dedicated server...\n");
printf(" - Forked to background with pid %d\n", pid);
printf(" - Forked to background with pid %d\n", _dedicated_pid);
exit(0);
}
}
@@ -110,13 +106,12 @@ void WINAPI CheckForConsoleInput(void)
void CreateWindowsConsoleThread(void)
{
static char tbuffer[9];
DWORD dwThreadId;
/* Create event to signal when console input is ready */
hEvent = CreateEvent(NULL, false, false, _strtime(tbuffer));
if (hEvent == NULL)
error("Cannot create console event!");
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, NULL, 0, &dwThreadId);
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, 0, 0, NULL);
if (hThread == NULL)
error("Cannot create console thread!");
@@ -132,8 +127,7 @@ void CloseWindowsConsoleThread(void)
#endif
static const char *DedicatedVideoStart(const char * const *parm)
{
static const char *DedicatedVideoStart(char **parm) {
_screen.width = _screen.pitch = _cur_resolution[0];
_screen.height = _cur_resolution[1];
_dedicated_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]);
@@ -259,31 +253,14 @@ static int DedicatedVideoMainLoop(void)
// Load the dedicated server stuff
_is_network_server = true;
_network_dedicated = true;
_switch_mode = SM_NONE;
_network_playas = OWNER_SPECTATOR;
_local_player = OWNER_SPECTATOR;
/* If SwitchMode is SM_LOAD, it means that the user used the '-g' options */
if (_switch_mode != SM_LOAD) {
_switch_mode = SM_NONE;
GenRandomNewGame(Random(), InteractiveRandom());
} else {
_switch_mode = SM_NONE;
/* First we need to test if the savegame can be loaded, else we will end up playing the
* intro game... */
if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) {
/* Loading failed, pop out.. */
DEBUG(net, 0)("Loading requested map failed. Aborting.");
_networking = false;
} else {
/* We can load this game, so go ahead */
SwitchMode(SM_LOAD);
}
}
DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_GEN_RANDOM_NEW_GAME);
// Done loading, start game!
if (!_networking) {
DEBUG(net, 1)("Dedicated server could not be launched. Aborting.");
DEBUG(net, 1)("Dedicated server could not be launced. Aborting..");
return ML_QUIT;
}
@@ -328,9 +305,8 @@ const HalVideoDriver _dedicated_video_driver = {
static void *_dedicated_video_mem;
static const char *DedicatedVideoStart(const char * const *parm)
{
DEBUG(misc, 0) ("OpenTTD compiled without network support, exiting.");
static const char *DedicatedVideoStart(char **parm) {
DEBUG(misc,0)("OpenTTD compiled without network-support, quiting...");
return NULL;
}

142
depot.c
View File

@@ -1,142 +0,0 @@
#include "stdafx.h"
#include "ttd.h"
#include "depot.h"
#include "tile.h"
#include "map.h"
#include "table/strings.h"
#include "saveload.h"
#include "order.h"
enum {
/* Max depots: 64000 (8 * 8000) */
DEPOT_POOL_BLOCK_SIZE_BITS = 3, /* In bits, so (1 << 3) == 8 */
DEPOT_POOL_MAX_BLOCKS = 8000,
};
/**
* Called if a new block is added to the depot-pool
*/
static void DepotPoolNewBlock(uint start_item)
{
Depot *depot;
FOR_ALL_DEPOTS_FROM(depot, start_item)
depot->index = start_item++;
}
/* Initialize the town-pool */
MemoryPool _depot_pool = { "Depots", DEPOT_POOL_MAX_BLOCKS, DEPOT_POOL_BLOCK_SIZE_BITS, sizeof(Depot), &DepotPoolNewBlock, 0, 0, NULL };
/**
* Gets a depot from a tile
*
* @return Returns the depot if the tile had a depot, else it returns NULL
*/
Depot *GetDepotByTile(uint tile)
{
Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (depot->xy == tile)
return depot;
}
return NULL;
}
/**
* Allocate a new depot
*/
Depot *AllocateDepot(void)
{
Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (!IsValidDepot(depot)) {
uint index = depot->index;
memset(depot, 0, sizeof(Depot));
depot->index = index;
return depot;
}
}
/* Check if we can add a block to the pool */
if (AddBlockToPool(&_depot_pool))
return AllocateDepot();
return NULL;
}
/**
* Delete a depot
*/
void DoDeleteDepot(uint tile)
{
Order order;
Depot *depot;
/* Get the depot */
depot = GetDepotByTile(tile);
/* Clear the tile */
DoClearSquare(tile);
/* Clear the depot */
depot->xy = 0;
/* Clear the depot from all order-lists */
order.type = OT_GOTO_DEPOT;
order.station = depot->index;
DeleteDestinationFromVehicleOrder(order);
/* Delete the depot-window */
DeleteWindowById(WC_VEHICLE_DEPOT, tile);
}
void InitializeDepot(void)
{
CleanPool(&_depot_pool);
AddBlockToPool(&_depot_pool);
}
static const byte _depot_desc[] = {
SLE_CONDVAR(Depot, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Depot, xy, SLE_UINT32, 6, 255),
SLE_VAR(Depot,town_index, SLE_UINT16),
SLE_END()
};
static void Save_DEPT(void)
{
Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (IsValidDepot(depot)) {
SlSetArrayIndex(depot->index);
SlObject(depot, _depot_desc);
}
}
}
static void Load_DEPT(void)
{
int index;
while ((index = SlIterateArray()) != -1) {
Depot *depot;
if (!AddBlockIfNeeded(&_depot_pool, index))
error("Depots: failed loading savegame: too many depots");
depot = GetDepot(index);
SlObject(depot, _depot_desc);
}
}
const ChunkHandler _depot_chunk_handlers[] = {
{ 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY | CH_LAST},
};

120
depot.h
View File

@@ -1,120 +0,0 @@
#ifndef DEPOT_H
#define DEPOT_H
#include "pool.h"
#include "tile.h"
struct Depot {
TileIndex xy;
uint16 town_index;
uint16 index;
};
extern MemoryPool _depot_pool;
/**
* Get the pointer to the depot with index 'index'
*/
static inline Depot *GetDepot(uint index)
{
return (Depot*)GetItemFromPool(&_depot_pool, index);
}
/**
* Get the current size of the DepotPool
*/
static inline uint16 GetDepotPoolSize(void)
{
return _depot_pool.total_items;
}
static inline bool IsDepotIndex(uint index)
{
return index < GetDepotPoolSize();
}
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1 < GetDepotPoolSize()) ? GetDepot(d->index + 1) : NULL)
#define FOR_ALL_DEPOTS(d) FOR_ALL_DEPOTS_FROM(d, 0)
#define MIN_SERVINT_PERCENT 5
#define MAX_SERVINT_PERCENT 90
#define MIN_SERVINT_DAYS 30
#define MAX_SERVINT_DAYS 800
/** Get the service interval domain.
* Get the new proposed service interval for the vehicle is indeed, clamped
* within the given bounds. @see MIN_SERVINT_PERCENT ,etc.
* @param index proposed service interval
*/
static inline uint16 GetServiceIntervalClamped(uint index)
{
return (_patches.servint_ispercent) ? clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
}
VARDEF TileIndex _last_built_train_depot_tile;
VARDEF TileIndex _last_built_road_depot_tile;
VARDEF TileIndex _last_built_aircraft_depot_tile;
VARDEF TileIndex _last_built_ship_depot_tile;
/**
* Check if a depot really exists.
*/
static inline bool IsValidDepot(const Depot* depot)
{
return depot->xy != 0; /* XXX: Replace by INVALID_TILE someday */
}
/**
* Check if a tile is a depot of the given type.
*/
static inline bool IsTileDepotType(TileIndex tile, TransportType type)
{
switch(type)
{
case TRANSPORT_RAIL:
return IsTileType(tile, MP_RAILWAY) && (_map5[tile] & 0xFC) == 0xC0;
break;
case TRANSPORT_ROAD:
return IsTileType(tile, MP_STREET) && (_map5[tile] & 0xF0) == 0x20;
break;
case TRANSPORT_WATER:
return IsTileType(tile, MP_WATER) && (_map5[tile] & ~3) == 0x80;
break;
default:
assert(0);
return false;
}
}
/**
* Returns the direction the exit of the depot on the given tile is facing.
*/
static inline uint GetDepotDirection(TileIndex tile, TransportType type)
{
assert(IsTileDepotType(tile, type));
switch (type)
{
case TRANSPORT_RAIL:
case TRANSPORT_ROAD:
/* Rail and road store a diagonal direction in bits 0 and 1 */
return _map5[tile] & 3;
case TRANSPORT_WATER:
/* Water is stubborn, it stores the directions in a different order. */
switch (_map5[tile] & 3) {
case 0: return 0;
case 1: return 2;
case 2: return 3;
case 3: return 1;
}
default:
return 0; /* Not reached */
}
}
Depot *GetDepotByTile(uint tile);
void InitializeDepot(void);
Depot *AllocateDepot(void);
void DoDeleteDepot(uint tile);
#endif /* DEPOT_H */

View File

@@ -2,7 +2,6 @@
#include "ttd.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "vehicle.h"
#include "command.h"
#include "news.h"
@@ -19,7 +18,7 @@ static void DisasterClearSquare(TileIndex tile)
if (!EnsureNoVehicle(tile))
return;
switch (GetTileType(tile)) {
switch (TileType(tile)) {
case MP_RAILWAY:
if (IS_HUMAN_PLAYER(_map_owner[tile])) DoClearSquare(tile);
break;
@@ -166,13 +165,12 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
}
if ((v->tick_counter&7)==0) {
CreateEffectVehicleRel(v, 0, -17, 2, EV_SMOKE);
CreateEffectVehicleRel(v, 0, -17, 2, EV_SMOKE_3);
}
} else if (v->current_order.station == 0) {
tile = v->tile; /**/
if (IsValidTile(tile) &&
IsTileType(tile, MP_STATION) &&
if (IsTileType(tile, MP_STATION) &&
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
IS_HUMAN_PLAYER(_map_owner[tile])) {
@@ -197,8 +195,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
tile = v->tile; /**/
if (IsValidTile(tile) &&
IsTileType(tile, MP_STATION) &&
if (IsTileType(tile, MP_STATION) &&
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
IS_HUMAN_PLAYER(_map_owner[tile])) {
@@ -219,7 +216,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
SetDisasterVehiclePos(v, x, y, z);
if (++v->age == 1) {
CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
CreateEffectVehicleRel(v, 0, 7, 8, EV_CRASHED_SMOKE);
SndPlayVehicleFx(SND_12_EXPLOSION, v);
v->u.disaster.image_override = 0xF42;
} else if (v->age == 70) {
@@ -232,7 +229,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
-7 + (r&0xF),
-7 + (r>>4&0xF),
5 + (r>>8&0x7),
EV_EXPLOSION_SMALL);
EV_DEMOLISH);
}
} else if (v->age == 350) {
v->current_order.station = 3;
@@ -240,8 +237,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
}
tile = v->tile;/**/
if (IsValidTile(tile) &&
IsTileType(tile, MP_STATION) &&
if (IsTileType(tile, MP_STATION) &&
IS_BYTE_INSIDE(_map5[tile], 8, 0x43) &&
IS_HUMAN_PLAYER(_map_owner[tile])) {
@@ -323,7 +319,7 @@ static void DisasterTick_UFO(Vehicle *v)
// destroy?
if (v->age > 50) {
CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
CreateEffectVehicleRel(v, 0, 7, 8, EV_CRASHED_SMOKE);
SndPlayVehicleFx(SND_12_EXPLOSION, v);
DeleteDisasterVeh(v);
}
@@ -370,7 +366,7 @@ static void DisasterTick_2(Vehicle *v)
x + (r & 0x3F),
y + (r >> 6 & 0x3F),
(r >> 12 & 0xF),
EV_EXPLOSION_SMALL);
EV_DEMOLISH);
if (++v->age >= 55)
v->current_order.station = 3;
@@ -441,7 +437,7 @@ static void DisasterTick_3(Vehicle *v)
x + (r & 0x3F),
y + (r >> 6 & 0x3F),
(r >> 12 & 0xF),
EV_EXPLOSION_SMALL);
EV_DEMOLISH);
if (++v->age >= 55)
v->current_order.station = 3;
@@ -614,7 +610,7 @@ static void DisasterTick_4b(Vehicle *v)
return;
v->current_order.station = 1;
CreateEffectVehicleRel(u, 0, 7, 8, EV_EXPLOSION_LARGE);
CreateEffectVehicleRel(u, 0, 7, 8, EV_CRASHED_SMOKE);
SndPlayVehicleFx(SND_12_EXPLOSION, u);
DeleteDisasterVeh(u);
@@ -625,7 +621,7 @@ static void DisasterTick_4b(Vehicle *v)
v->x_pos-32+(r&0x3F),
v->y_pos-32+(r>>5&0x3F),
0,
EV_EXPLOSION_SMALL);
EV_DEMOLISH);
}
BEGIN_TILE_LOOP(tile,6,6,v->tile - TILE_XY(3,3))

View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "map.h"
#include "window.h"
@@ -47,7 +46,7 @@ static void PlaceDocks_Buoy(uint tile)
static void PlaceDocks_DemolishArea(uint tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
VpStartPlaceSizing(tile, VPM_X_AND_Y);
}
static void PlaceDocks_BuildCanal(uint tile)
@@ -145,9 +144,9 @@ static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
case WE_PLACE_MOUSEUP:
if (e->click.pt.x != -1) {
if ((e->place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
GUIPlaceProcDragXY(e);
} else if(e->place.userdata == VPM_X_OR_Y)
if (e->place.userdata == VPM_X_AND_Y)
DoCommandP(e->place.tile, e->place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
else if(e->place.userdata == VPM_X_OR_Y)
DoCommandP(e->place.tile, e->place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
}
break;
@@ -182,8 +181,8 @@ static const Widget _build_docks_toolb_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 145, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 7, 146, 157, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP},
{ WWT_PANEL, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_BUILD_LOCK, STR_BUILD_LOCKS_TIP},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_OPENTTD_BASE+65, STR_BUILD_CANALS_TIP},
{ WWT_PANEL, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_CANALS_BASE+69, STR_BUILD_LOCKS_TIP},
{ WWT_PANEL, RESIZE_NONE, 7, 44, 47, 14, 35, 0x0, STR_NULL},

View File

@@ -66,14 +66,13 @@ Compiler
Open Watcom 1.3 was used to build OpenTTD (earlier versions will
NOT work). See http://www.openwatcom.org/ to download it. It may
also be possible to build OpenTTD with GCC: I attempted this
also be possible to build OpenTTD under OS/2: I attempted this
before using Open Watcom, but found the tools available for OS/2
at the time to be a bit more tricky to get working.
Due to complexities in my set-up, I actually used the Win32 version
of Open Watcom to initially compile OpenTTD for OS/2. There should
be no reason of course why the OS/2 version cannot be used, and I
have subsequently built OpenTTD successfully this way.
be no reason of course why the OS/2 version cannot be used.
Libraries Required
------------------
@@ -85,10 +84,10 @@ provided, they are not designed for Watcom (apart from SDL):
- zlib
http://www.zlib.org/ - contains a makefile for OS/2, but is out
of date and uses EMX, ignore this
of date and uses EMX
- libpng
http://www.libpng.org/ - contains an EMX/gcc makefile, ignore this
http://www.libpng.org/ - contains an EMX/gcc makefile
- SDL for OS/2
For 0.3.5, I used ftp://ftp.netlabs.org/pub/sdl/SDL-1.2.7-src-20040908a.zip -
@@ -99,18 +98,6 @@ If you do not wish to build the libraries yourself, pre-built versions
can be downloaded from the Files section at
http://sourceforge.net/projects/openttd/ - see "os2-useful.zip".
A Note About Subversion Revision Numbers
----------------------------------------
The project file uses a bit of a hack to find out the SVN revision number and
create an appropriate rev.c file. You'll need the SVN tools in your path
(specifically, "svnversion"). If "svnversion" can't be found, a generic rev.c
with the revision set to "norev000" will be created. To specifically force a
version number, set the environment variable "RELEASE" to the number (eg, "0.3.6")
-before- starting the Open Watcom IDE (which must be launched from the same shell
session). Also, beware, as you WILL cause incompatibilities if you try to
play a multiplayer game with a different version.
Compiling
---------
@@ -128,4 +115,4 @@ If you have any questions regarding OS/2 issues, please contact me
(owen@owenrudge.net) and I'll try to help you out. For general OpenTTD
issues, see the Contacting section of readme.txt.
- Owen Rudge
- Owen Rudge, 26th December 2004

View File

@@ -2,19 +2,22 @@
<html>
<head>
<meta name="Author" content="Marcin Grzegorczyk">
<meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays">
<meta name="Description" content="Structure of Transport Tycoon Deluxe (TTD) savegame files">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>OpenTTD Landscape Internals</title>
<title>Transport Tycoon Deluxe savegame internals</title>
</head>
<body>
<h3><a name="Landscape">Landscape</a></h3>
<p>
Five arrays are used to encode the information of the contents of each tile. These arrays are referred to as "<span style="font-weight: bold;">map_owner</span>", "<span style="font-weight: bold;">map2</span>", "<span style="font-weight: bold;">map3_lo|_hi</span>", "<span style="font-weight: bold;">map_type_and_height</span>" and "<span style="font-weight: bold;">map5</span>". The known encodings are listed in the table below. The most important value is the class of a tile, stored in the upper 4 bits of the type_and_height array. The lower 4 bits are used to encode the height and slope data. For a graphical represenation of the tile-layout have a look at <a href="landscape_grid.html">Landscape grid</a> page.
Five arrays are used to encode the information of the contents of each tile. These arrays are referred to as <a href="#_landscape1">map_owner</a>, <a href="#_landscape2">map2</a>, <a href="#_landscape3">map3_lo</a>, <a href="#_landscape4">type_and_height</a> and <a href="#_landscape5">map5</a>. The known encodings are listed in the table below. The most important value is the class of a tile, stored in the upper 4 bits of the type_and_height array.
</p>
<p>
OTTD's class-specific periodic tile processing routine is called once every +256 ticks for each tile.
<a name="OwnershipInfo">Owner values</a> <tt>00</tt> through <tt>07</tt> are companies (they're indices into the <a href="#_CompanyArray">array of companies</a>), <tt>10</tt> is no owner, <tt>11</tt> appears to be reserved for water, <tt>80</tt> and above are towns (in this case the low 7 bits contain an index into the <a href="#_TownArray">town array</a>).
</p>
<p>
TTD's class-specific periodic tile processing routine is called once every +256 ticks for each tile.
</p>
<table border=1 cellpadding=3>
@@ -148,9 +151,7 @@ map5 bits 7..4 clear: road
<tr><td nowrap valign=top>bit 3: </td><td align=left>NE piece</td></tr>
</table></li>
<li>map_owner: <a href="#OwnershipInfo">owner</a> of the road</li>
<li>map2: Index into the array of towns, 0 for non-town roads</li>
<li>map3_hi bits 0..3: counter for the roadworks</li>
<li>map3_hi bits 4..6: <tt>0</tt> - on bare land, <tt>1</tt> - on grass, <tt>2</tt> - paved, <tt>3</tt> - with streetlights, <tt>5</tt> - tree-lined, <tt>6</tt> - on grass with road works, <tt>7</tt> - paved with road works</li>
<li>map2 bits 0..2: <tt>0</tt> - on bare land, <tt>1</tt> - on grass, <tt>2</tt> - paved, <tt>3</tt> - with streetlights, <tt>5</tt> - tree-lined, <tt>6</tt> - on grass with road works, <tt>7</tt> - paved with road works</li>
<li>map3_hi bit 7 set = on snow or desert</li>
</ul>
map5 bit 4 set, bits 7..5 clear: level crossing
@@ -158,10 +159,9 @@ map5 bit 4 set, bits 7..5 clear: level crossing
<li>map5 bit 3: clear - road in the X direction, set - road in the Y direction (railway track always perpendicular)</li>
<li>map5 bit 2: set if crossing lights are on</li>
<li>map_owner: <a href="#OwnershipInfo">owner</a> of the railway track</li>
<li>map2: Index into the array of towns, 0 for non-town roads</li>
<li>map2 bits 0..2: <tt>0</tt> - on bare land, <tt>1</tt> - on grass, <tt>2</tt> or higher - paved</li>
<li>map3_lo bits 0..7: <a href="#OwnershipInfo">owner</a> of the road</li>
<li>map3_hi bits 3..0: <a href="#TrackType">track type</a></li>
<li>map3_hi bits 4..6: <tt>0</tt> - on bare land, <tt>1</tt> - on grass, <tt>2</tt> or higher - paved</li>
<li>map3_hi bit 7 set = on snow or desert</li>
</ul>
map5 bit 5 set: road depot
@@ -175,8 +175,7 @@ map5 bit 5 set: road depot
<tr><td valign=top nowrap><a name="Class3"><tt> 3 </tt></a></td><td>
Town building
<ul>
<li>map2: Index into the array of towns</li>
<li>map3_hi: <a name="HouseTypes">town building type</a>:
<li>map2: <a name="HouseTypes">town building type</a>:
<p><small>Note: In the climate list, 'sub-arctic' means below the <a href="#_snowline">snow line</a>, and 'snow' means above the snow line in the sub-arctic climate.</small></p>
<table>
<tr><th align=left>Type&nbsp;</th><th align=left>Size&nbsp;</th><th align=left>Climates&nbsp;</th><th align=left>Description</th></tr>
@@ -603,13 +602,13 @@ map5 bit 5 set:
</td></tr>
<tr><td colspan=2>
Classes <tt>B</tt> through <tt>F</tt> are reserved. The presence of a tile in one of the reserved classes will crash OTTD.
Classes <tt>B</tt> through <tt>F</tt> are reserved. The presence of a tile in one of the reserved classes will crash TTD.
</td></tr>
</table>
<hr>
Original Copyright &copy; 2003 by Marcin Grzegorczyk for TTDLX.<br>
Copyright &copy; 2003 by Marcin Grzegorczyk.<br>
Transport Tycoon and Transport Tycoon Deluxe are Copyright &copy; by Chris Sawyer. All the other trademarks are the property of their respective owners.<br>
</body>

View File

@@ -1,239 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays #2">
<title>OpenTTD Landscape Internals - #2</title>
<style type="text/css">
.freebits { background-color: rgb(30, 178, 54);}
.abuse { background-color: rgb(255, 58, 31);}
</style>
</head>
<body style="direction: ltr;">
<h3 style="font-weight: bold;">Landscape</h3>
<span style="font-weight: bold;"></span>Five arrays are used to encode the information of the contents of the tile.
This can be seen in the <a href="landscape.html">Landscape</a> document. This page tries to give an overview of used and free bits of
the array so you can quickly see what is used and what is not.
<ul>
<li><span style="font-weight: bold;"><span class="freebits">O</span></span> - bit is free</li>
<li><span style="font-weight: bold;">X</span> - bit is used</li>
<li><span style="font-weight: bold;"><span class="abuse">&nbsp;&nbsp;&nbsp;</span></span> - bit of _map_* is abused for different purposes</li>
</ul>
<p>
<ul>
<li><span style="font-weight: bold;">_map_owner[]</span> - 8 bits in size, used to identify the owner of that tile (eg piece of rail, bridge, etc.).</li>
<li><span style="font-weight: bold;">_map2[]</span> - 16 bits in size, used to identify the index of the given tile (object) in the (object-)array.</li>
<li><span style="font-weight: bold;">_map3[]</span> - 16 bits in size, which is split up into _map3lo[] and _map3hi[] is used for general storage.</li>
<li><span style="font-weight: bold;">_map_type_and_height[]</span> - 8 bits in size, stores tile height (lower 4 bits) and tile class (upper 4 bits).</li>
<li><span style="font-weight: bold;">_map5[]</span> - 8 bits in size, is used for general storage.</li>
</ul>
<table style="text-align: left;" border="1" cellpadding="2"
cellspacing="2" width="100%">
<tbody>
<tr>
<th style="white-space: nowrap; text-align: left;">class</th>
<th style="white-space: nowrap; text-align: center;">_map_owner[L1] (8)</th>
<th style="white-space: nowrap; text-align: center;">_map2[L2] (16)</th>
<th style="white-space: nowrap; text-align: center;">_map3[lo&amp; hi,L3] (16)</th>
<th style="white-space: nowrap; text-align: center;">_map_type_and_height[L4] (8)</th>
<th style="white-space: nowrap; text-align: center;">_map5[L5] (8)</th>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(0) ground</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX <span class="freebits">OOOO OO</span>XX XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX X<span class="freebits">O</span>XX</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(1) rail</td>
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX <span class="freebits">OOOO OOOO</span><br>
</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXX<span class="freebits">O OOOO</span><br>
</td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX<br>
</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">depot/checkpoint</li>
</ul>
</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="text-align: center;">XXXX X<span class="freebits">OOO</span> XXXX XXXX</td>
<td style="text-align: center;">-inherit-</td>
<td style="white-space: nowrap; text-align: center;">XXX<span class="freebits">O OO</span>XX</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(2) road</td>
<td style="text-align: center;">XXXX XXXX</td>
<td style="text-align: center;"><span class="abuse">XXXX XXXX XXXX XXXX</span></td>
<td style="text-align: center;"><span class="freebits">OOOO OOOO</span> XXXX XXXX</td>
<td style="text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="text-align: center;">XXXX XXXX</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">level crossing</li>
</ul>
</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;"><span class="abuse">XXXX XXXX XXXX XXXX</span></td>
<td style="text-align: center;">XXXX XXXX XXXX XXXX</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;"><span class="freebits">OO</span>XX XXXX</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">road depot</li>
</ul>
</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="text-align: center;"><span class="freebits">OOOO OOOO OOOO OOO</span>X</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">XXXX XXXX</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(3) town</td>
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX<br>
</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX<br>
</td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XX<span class="freebits">O</span>X</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(4) trees</td>
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX XXXX</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX XX<span class="freebits">OO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX <span class="freebits">OO</span>XX XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXX<span class="freebits">O OO</span>XX</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(5) station</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX X<span class="freebits">OOO</span> XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(6) water</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(8) industry</td>
<td style="white-space: nowrap; text-align: center;"><span class="abuse">XXXX X</span><span class="freebits">OO</span><span class="abuse">X</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">bubble/sugar/toffee</li>
</ul>
</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">XXXX XXXX <span class="freebits">OOOO OOOO</span></td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">toy factory</li>
</ul>
</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">XXXX XXXX XXXX XXXX</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">gold/copper/coal</li>
</ul>
</td>
<td style="text-align: center;">XXXX XXXX</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">oil wells</li>
</ul>
</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">power station</li>
</ul>
</td>
<td style="text-align: center;">XXXX XX<span class="freebits">O</span>X</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
<td style="text-align: center;">-inherit-</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(9) tunnel</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX <span class="freebits">OOOO OOOO OOO</span>X</td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
</tr>
<tr>
<td>
<ul>
<li style="white-space: nowrap; text-align: left;">bridge</li>
</ul>
</td>
<td style="text-align: center;">XXXX XXXX</td>
<td style="text-align: center;"><span class="abuse">XXXX XXXX</span> <span class="freebits">OOOO OOOO</span></td>
<td style="text-align: center;">XXXX XXXX <span class="freebits">OOOO OOO</span>X</td>
<td style="text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="text-align: center;">XXXX XXXX</td>
</tr>
<tr>
<td style="white-space: nowrap; text-align: left;">(10) various (HQ)</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;"><span class="freebits">OOOO OOOO OOOO OOOO</span></td>
<td style="white-space: nowrap; text-align: center;">XXXX&nbsp;&nbsp;&nbsp;&nbsp;XXXX</td>
<td style="white-space: nowrap; text-align: center;">XXXX XXXX</td>
</tr>
</tbody>
</table>
</body>
</html>

195
economy.c
View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "strings.h" // XXX InjectDParam()
#include "table/strings.h"
#include "map.h"
#include "news.h"
@@ -108,7 +107,7 @@ int64 CalculateCompanyValue(Player *p) {
value += p->money64 - p->current_loan; // add real money value
return max64(value, 1);
return max(value, 1);
}
// if update is set to true, the economy is updated with this score
@@ -123,7 +122,7 @@ int UpdateCompanyRatingAndValue(Player *p, bool update)
/* Count vehicles */
{
Vehicle *v;
int32 min_profit = score_info[SCORE_MIN_PROFIT].needed;
int32 min_profit = MAX_INT;
uint num = 0;
FOR_ALL_VEHICLES(v) {
@@ -142,7 +141,8 @@ int UpdateCompanyRatingAndValue(Player *p, bool update)
}
_score_part[owner][SCORE_VEHICLES] = num;
if (min_profit > 0)
if (min_profit != MAX_INT && min_profit > 0)
_score_part[owner][SCORE_MIN_PROFIT] = min_profit;
}
@@ -259,44 +259,45 @@ int UpdateCompanyRatingAndValue(Player *p, bool update)
}
// use 255 as new_player to delete the player.
void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
void ChangeOwnershipOfPlayerItems(byte old_player, byte new_player)
{
PlayerID old = _current_player;
byte old = _current_player;
_current_player = old_player;
if (new_player == OWNER_SPECTATOR) {
if (new_player == 255) {
Subsidy *s;
for (s = _subsidies; s != endof(_subsidies); s++) {
for(s=_subsidies; s != endof(_subsidies); s++) {
if (s->cargo_type != 0xff && s->age >= 12) {
if (GetStation(s->to)->owner == old_player)
Station *st = GetStation(s->to);
if (st->owner == old_player)
s->cargo_type = 0xff;
}
}
}
/* Take care of rating in towns */
{ Town *t;
if (new_player != OWNER_SPECTATOR) {
FOR_ALL_TOWNS(t) {
/* If a player takes over, give the ratings to that player. */
if (IsValidTown(t) && HASBIT(t->have_ratings, old_player)) {
if (HASBIT(t->have_ratings, new_player)) {
// use max of the two ratings.
t->ratings[new_player] = max(t->ratings[new_player], t->ratings[old_player]);
} else {
SETBIT(t->have_ratings, new_player);
t->ratings[new_player] = t->ratings[old_player];
}
}
// take care of rating in towns
{
Town *t;
/* Reset ratings for the town */
if (IsValidTown(t)) {
t->ratings[old_player] = 500;
CLRBIT(t->have_ratings, old_player);
// if a player takes over, give the ratings to that player.
if (new_player != 255) {
FOR_ALL_TOWNS(t) if (t->xy && HASBIT(t->have_ratings, old_player)) {
if (HASBIT(t->have_ratings, new_player)) {
// use max of the two ratings.
t->ratings[new_player] = max(t->ratings[new_player], t->ratings[old_player]);
} else {
SETBIT(t->have_ratings, new_player);
t->ratings[new_player] = t->ratings[old_player];
}
}
}
// reset rating for the towns.
FOR_ALL_TOWNS(t) if (t->xy) {
t->ratings[old_player] = 500;
CLRBIT(t->have_ratings, old_player);
}
}
{
@@ -309,27 +310,20 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
// Determine Ids for the new vehicles
FOR_ALL_VEHICLES(v) {
if (v->owner == new_player) {
switch (v->type) {
case VEH_Train:
if (v->subtype == TS_Front_Engine) num_train++;
break;
case VEH_Road:
num_road++;
break;
case VEH_Ship:
num_ship++;
break;
case VEH_Aircraft:
if (v->subtype <= 2) num_aircraft++;
break;
default: break;
}
if (v->type == VEH_Train && v->subtype == TS_Front_Engine)
num_train++;
else if (v->type == VEH_Road)
num_road++;
else if (v->type == VEH_Ship)
num_ship++;
else if (v->type == VEH_Aircraft && v->subtype <= 2)
num_aircraft++;
}
}
FOR_ALL_VEHICLES(v) {
if (v->owner == old_player && IS_BYTE_INSIDE(v->type, VEH_Train, VEH_Aircraft+1) ) {
if (new_player == OWNER_SPECTATOR) {
if (new_player == 255) {
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
@@ -351,16 +345,16 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
// Change ownership of tiles
{
TileIndex tile = 0;
uint tile = 0;
do {
ChangeTileOwner(tile, old_player, new_player);
} while (++tile != MapSize());
}
// Change color of existing windows
if (new_player != OWNER_SPECTATOR) {
if (new_player != 255) {
Window *w;
for (w = _windows; w != _last_window; w++) {
for(w=_windows; w != _last_window; w++) {
if (w->caption_color == old_player)
w->caption_color = new_player;
}
@@ -372,7 +366,7 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
/* Check for shares */
FOR_ALL_PLAYERS(p) {
for (i = 0; i < 4; i++) {
for(i = 0; i < 4; i++) {
/* 'Sell' the share if this player has any */
if (p->share_owners[i] == _current_player)
p->share_owners[i] = 0xFF;
@@ -380,7 +374,7 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
}
p = DEREF_PLAYER(_current_player);
/* Sell all the shares that people have on this company */
for (i = 0; i < 4; i++)
for(i = 0; i < 4; i++)
p->share_owners[i] = 0xFF;
}
@@ -902,7 +896,7 @@ static void FindSubsidyPassengerRoute(FoundRoute *fr)
if (from==to || to->xy == 0 || to->population < 400 || to->pct_pass_transported > 42)
return;
fr->distance = DistanceManhattan(from->xy, to->xy);
fr->distance = GetTileDist(from->xy, to->xy);
}
static void FindSubsidyCargoRoute(FoundRoute *fr)
@@ -943,7 +937,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
// Only want big towns
if (t->xy == 0 || t->population < 900)
return;
fr->distance = DistanceManhattan(i->xy, t->xy);
fr->distance = GetTileDist(i->xy, t->xy);
fr->to = t;
} else {
// The destination is an industry
@@ -955,7 +949,7 @@ static void FindSubsidyCargoRoute(FoundRoute *fr)
cargo != i2->accepts_cargo[1] &&
cargo != i2->accepts_cargo[2]))
return;
fr->distance = DistanceManhattan(i->xy, i2->xy);
fr->distance = GetTileDist(i->xy, i2->xy);
fr->to = i2;
}
}
@@ -1138,7 +1132,7 @@ static void DeliverGoodsToIndustry(TileIndex xy, byte cargo_type, int num_pieces
== ind->accepts_cargo[1] || cargo_type == ind->accepts_cargo[2]) &&
ind->produced_cargo[0] != 0xFF &&
ind->produced_cargo[0] != cargo_type &&
(t = DistanceManhattan(ind->xy, xy)) < 2 * u) {
(t=GetTileDist(ind->xy, xy)) < u) {
u = t;
best = ind;
}
@@ -1177,7 +1171,7 @@ static bool CheckSubsidised(Station *from, Station *to, byte cargo_type)
} else {
xy = (GetIndustry(s->from))->xy;
}
if (DistanceMax(xy, from->xy) > 9)
if (GetTileDist1D(xy, from->xy) > 9)
continue;
/* Check distance from dest */
@@ -1187,7 +1181,7 @@ static bool CheckSubsidised(Station *from, Station *to, byte cargo_type)
xy = (GetIndustry(s->to))->xy;
}
if (DistanceMax(xy, to->xy) > 9)
if (GetTileDist1D(xy, to->xy) > 9)
continue;
/* Found a subsidy, change the values to indicate that it's in use */
@@ -1197,7 +1191,7 @@ static bool CheckSubsidised(Station *from, Station *to, byte cargo_type)
/* Add a news item */
pair = SetupSubsidyDecodeParam(s, 0);
InjectDParam(2);
INJECT_DPARAM(2);
p = DEREF_PLAYER(_current_player);
SetDParam(0, p->name_1);
@@ -1214,7 +1208,7 @@ static bool CheckSubsidised(Station *from, Station *to, byte cargo_type)
return false;
}
static int32 DeliverGoods(int num_pieces, byte cargo_type, uint16 source, uint16 dest, byte days_in_transit)
static int32 DeliverGoods(int num_pieces, byte cargo_type, byte source, byte dest, byte days_in_transit)
{
bool subsidised;
Station *s_from, *s_to;
@@ -1240,7 +1234,7 @@ static int32 DeliverGoods(int num_pieces, byte cargo_type, uint16 source, uint16
{
Town *t = s_to->town;
if (cargo_type == CT_FOOD) t->new_act_food += num_pieces;
if (cargo_type == CT_WATER) t->new_act_water += num_pieces;
if (cargo_type == CT_STEEL) t->new_act_water += num_pieces;
}
// Give the goods to the industry.
@@ -1248,7 +1242,7 @@ static int32 DeliverGoods(int num_pieces, byte cargo_type, uint16 source, uint16
// Determine profit
{
int t = DistanceManhattan(s_from->xy, s_to->xy);
int t = GetTileDist(s_from->xy, s_to->xy);
int r = num_pieces;
profit = 0;
do {
@@ -1341,7 +1335,7 @@ int LoadUnloadVehicle(Vehicle *v)
int unloading_time = 20;
Vehicle *u = v;
int result = 0;
uint16 last_visited;
int last_visited;
Station *st;
GoodsEntry *ge;
int t;
@@ -1352,7 +1346,6 @@ int LoadUnloadVehicle(Vehicle *v)
assert(v->current_order.type == OT_LOADING);
v->cur_speed = 0;
old_player = _current_player;
_current_player = v->owner;
@@ -1365,10 +1358,8 @@ int LoadUnloadVehicle(Vehicle *v)
/* unload? */
if (v->cargo_count != 0) {
if (v->cargo_source != last_visited && ge->waiting_acceptance & 0x8000) {
if (v->cargo_source != (byte)last_visited && ge->waiting_acceptance & 0x8000) {
// deliver goods to the station
st->time_since_unload = 0;
unloading_time += v->cargo_count; /* TTDBUG: bug in original TTD */
profit += DeliverGoods(v->cargo_count, v->cargo_type, v->cargo_source, last_visited, v->cargo_days);
result |= 1;
@@ -1385,7 +1376,7 @@ int LoadUnloadVehicle(Vehicle *v)
// Goods already waiting at station. Set counters to the worst value.
if (v->cargo_days >= ge->enroute_time)
ge->enroute_time = v->cargo_days;
if (last_visited != ge->enroute_from)
if ((byte)last_visited != ge->enroute_from)
ge->enroute_from = v->cargo_source;
}
// Update amount of waiting cargo
@@ -1486,7 +1477,7 @@ int LoadUnloadVehicle(Vehicle *v)
void PlayersMonthlyLoop(void)
{
PlayersGenStatistics();
if (_patches.inflation && _cur_year < MAX_YEAR_END)
if (_patches.inflation)
AddInflation();
PlayersPayInterest();
// Reset the _current_player flag
@@ -1533,40 +1524,41 @@ static void DoAcquireCompany(Player *p)
extern int GetAmountOwnedBy(Player *p, byte owner);
/** Acquire shares in an opposing company.
* @param x,y unused
* @param p1 player to buy the shares from
* @param p2 unused
*/
int32 CmdBuyShareInCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Player *p;
int64 cost;
/* Check if buying shares is allowed (protection against modified clients */
if (p1 >= MAX_PLAYERS || !_patches.allow_shares) return CMD_ERROR;
byte *b;
int i;
SET_EXPENSES_TYPE(EXPENSES_OTHER);
p = DEREF_PLAYER(p1);
/* Protect new companies from hostile takeovers */
if (_cur_year - p->inaugurated_year < 6) return_cmd_error(STR_7080_PROTECTED);
if (_cur_year - p->inaugurated_year < 6) {
_error_message = STR_7080_PROTECTED;
return CMD_ERROR;
}
/* Check if buying shares is allowed (protection against modified clients */
if (!_patches.allow_shares)
return CMD_ERROR;
/* Those lines are here for network-protection (clients can be slow) */
if (GetAmountOwnedBy(p, OWNER_SPECTATOR) == 0) return 0;
if (GetAmountOwnedBy(p, OWNER_SPECTATOR) == 0)
return 0;
/* We can not buy out a real player (temporarily). TODO: well, enable it obviously */
if (GetAmountOwnedBy(p, OWNER_SPECTATOR) == 1 && !p->is_ai) return 0;
/* We can not buy out a real player in networking */
if (GetAmountOwnedBy(p, OWNER_SPECTATOR) == 1 && !p->is_ai)
return 0;
cost = CalculateCompanyValue(p) >> 2;
if (flags & DC_EXEC) {
int i;
byte *b = p->share_owners;
b = p->share_owners;
while (*b != 0xFF) b++; /* share owners is guaranteed to contain at least one 0xFF */
*b = _current_player;
for (i = 0; p->share_owners[i] == _current_player;) {
for(i=0;p->share_owners[i] == _current_player;) {
if (++i == 4) {
p->bankrupt_value = 0;
DoAcquireCompany(p);
@@ -1578,31 +1570,29 @@ int32 CmdBuyShareInCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return cost;
}
/** Sell shares in an opposing company.
* @param x,y unused
* @param p1 player to sell the shares from
* @param p2 unused
*/
int32 CmdSellShareInCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Player *p;
int64 cost;
/* Check if buying shares is allowed (protection against modified clients */
if (p1 >= MAX_PLAYERS || !_patches.allow_shares) return CMD_ERROR;
byte *b;
SET_EXPENSES_TYPE(EXPENSES_OTHER);
p = DEREF_PLAYER(p1);
/* Check if selling shares is allowed (protection against modified clients */
if (!_patches.allow_shares)
return CMD_ERROR;
/* Those lines are here for network-protection (clients can be slow) */
if (GetAmountOwnedBy(p, _current_player) == 0) return 0;
if (GetAmountOwnedBy(p, _current_player) == 0)
return 0;
/* adjust it a little to make it less profitable to sell and buy */
cost = CalculateCompanyValue(p) >> 2;
cost = -(cost - (cost >> 7));
if (flags & DC_EXEC) {
byte *b = p->share_owners;
b = p->share_owners;
while (*b != _current_player) b++; /* share owners is guaranteed to contain player */
*b = 0xFF;
InvalidateWindow(WC_COMPANY, (int)p1);
@@ -1610,27 +1600,12 @@ int32 CmdSellShareInCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return cost;
}
/** Buy up another company.
* When a competing company is gone bankrupt you get the chance to purchase
* that company.
* @todo currently this only works for AI players
* @param x,y unused
* @param p1 player/company to buy up
* @param p2 unused
*/
int32 CmdBuyCompany(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Player *p;
/* Disable takeovers in multiplayer games */
if (p1 >= MAX_PLAYERS || _networking) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_OTHER);
p = DEREF_PLAYER(p1);
if (!p->is_ai) return CMD_ERROR;
if (flags & DC_EXEC) {
if (flags & 1) {
DoAcquireCompany(p);
}
return p->bankrupt_value;
@@ -1672,3 +1647,7 @@ const ChunkHandler _economy_chunk_handlers[] = {
{ 'SUBS', Save_SUBS, Load_SUBS, CH_ARRAY},
{ 'ECMY', SaveLoad_ECMY, SaveLoad_ECMY, CH_RIFF | CH_LAST},
};

View File

@@ -8,18 +8,10 @@
// that says or TTD_LITTLE_ENDIAN, or TTD_BIG_ENDIAN. Makefile takes
// care of the real writing to the file.
int main (int argc, char *argv[]) {
int main () {
unsigned char EndianTest[2] = { 1, 0 };
int force_BE = 0, force_LE = 0;
if (argc > 1 && strcmp(argv[1], "BE") == 0)
force_BE = 1;
if (argc > 1 && strcmp(argv[1], "LE") == 0)
force_LE = 1;
printf("#ifndef ENDIAN_H\n#define ENDIAN_H\n");
if ( (*(short *) EndianTest == 1 && force_BE != 1) || force_LE == 1)
if( *(short *) EndianTest == 1 )
printf("#define TTD_LITTLE_ENDIAN\n");
else
printf("#define TTD_BIG_ENDIAN\n");

346
engine.c
View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "table/strings.h"
#include "engine.h"
#include "table/engines.h"
@@ -20,74 +19,34 @@ enum {
ENGINE_PREVIEWING = 4,
};
/** TRANSLATE FROM LOCAL CARGO TO GLOBAL CARGO ID'S.
* This maps the per-landscape cargo ID's to globally unique cargo ID's usable ie. in
* the custom GRF files. It is basically just a transcribed table from TTDPatch's newgrf.txt.
*/
const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = {
/* LT_NORMAL */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_IRON_ORE, GC_STEEL, GC_VALUABLES, GC_PAPER_TEMP},
/* LT_HILLY */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_INVALID, GC_PAPER, GC_VALUABLES, GC_FOOD },
/* LT_DESERT */ {GC_PASSENGERS, GC_RUBBER,GC_MAIL, GC_OIL, GC_FRUIT, GC_GOODS, GC_GRAIN, GC_WOOD, GC_COPPER_ORE, GC_WATER, GC_VALUABLES, GC_FOOD },
/* LT_CANDY */ {GC_PASSENGERS, GC_SUGAR, GC_MAIL, GC_TOYS,GC_BATTERIES, GC_CANDY, GC_TOFFEE,GC_COLA, GC_COTTON_CANDY,GC_BUBBLES,GC_PLASTIC, GC_FIZZY_DRINKS },
/**
* - GC_INVALID (255) means that cargo is not available for that climate
* - GC_PAPER_TEMP (27) is paper in temperate climate in TTDPatch
* Following can be renumbered:
* - GC_DEFAULT (29) is the defa ult cargo for the purpose of spritesets
* - GC_PURCHASE (30) is the purchase list image (the equivalent of 0xff) for the purpose of spritesets
*/
/* This maps per-landscape cargo ids to globally unique cargo ids usable ie. in
* the custom GRF files. It is basically just a transcribed table from
* TTDPatch's newgrf.txt. */
byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = {
/* LT_NORMAL */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 },
/* LT_HILLY */ { 0, 1, 2, 3, 4, 5, 6, 7, 28, 11, 10, 12 },
/* LT_DESERT */ { 0, 16, 2, 3, 13, 5, 6, 7, 14, 15, 10, 12 },
/* LT_CANDY */ { 0, 17, 2, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
// 27 is paper in temperate climate in TTDPatch
// Following can be renumbered:
// 29 is the default cargo for the purpose of spritesets
// 30 is the purchase list image (the equivalent of 0xff) for the purpose of spritesets
};
/** BEGIN --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
/** Map global cargo ID's to local-cargo ID's */
const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID] = {
CT_PASSENGERS,CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK,CT_GOODS, CT_GRAIN, CT_WOOD, /* 0- 7 */
CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, /* 8-15 */
CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES,CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, /* 16-23 */
CT_BUBBLES, CT_PLASTIC,CT_FIZZY_DRINKS,CT_PAPER /* unsup. */,CT_HILLY_UNUSED, /* 24-28 */
CT_INVALID, CT_INVALID /* 29-30 */
/* These two arrays provide a reverse mapping. */
byte _local_cargo_id_ctype[NUM_CID] = {
CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, // 0-7
CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, // 8-15
CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES, CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, // 16-23
CT_BUBBLES, CT_PLASTIC, CT_FIZZY_DRINKS, CT_PAPER /* unsup. */, CT_HILLY_UNUSED // 24-28
};
#define MC(cargo) (1 << cargo)
/** Bitmasked value where the global cargo ID is available in landscape
* 0: LT_NORMAL, 1: LT_HILLY, 2: LT_DESERT, 3: LT_CANDY */
const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE] =
{ /* LT_NORMAL: temperate */
MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|
MC(GC_IRON_ORE)|MC(GC_STEEL)|MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_UNDEFINED),
/* LT_HILLY: arctic */
MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|
MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_VALUABLES)|MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_UNDEFINED),
/* LT_DESERT: rainforest/desert */
MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|
MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_RUBBER),
/* LT_CANDY: toyland */
MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_SUGAR)|MC(GC_TOYS)|MC(GC_BATTERIES)|MC(GC_CANDY)|
MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS)
/* LT'th bit is set of the particular landscape if cargo available there.
* 1: LT_NORMAL, 2: LT_HILLY, 4: LT_DESERT, 8: LT_CANDY */
byte _local_cargo_id_landscape[NUM_CID] = {
15, 3, 15, 7, 3, 7, 7, 7, 1, 1, 7, 2, 7, // 0-12
4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 2, // 13-28
};
/** END --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
/** Bitmasked values of what type of cargo is refittable for the given vehicle-type.
* This coupled with the landscape information (_landscape_global_cargo_mask) gives
* us exactly what is refittable and what is not */
const uint32 _default_refitmasks[NUM_VEHICLE_TYPES] = {
/* Trains */
MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_IRON_ORE)|
MC(GC_STEEL)|MC(GC_VALUABLES)|MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_SUGAR)|
MC(GC_TOYS)|MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
/* Road vehicles (not refittable by default) */
0,
/* Ships */
MC(GC_COAL)|MC(GC_MAIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_IRON_ORE)|MC(GC_STEEL)|MC(GC_VALUABLES)|
MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_RUBBER)|MC(GC_SUGAR)|MC(GC_TOYS)|MC(GC_BATTERIES)|
MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
/* Aircraft */
MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_GOODS)|MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_SUGAR)|MC(GC_TOYS)|
MC(GC_BATTERIES)|MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
/* Special/Disaster */
0,0
};
#undef MC
void ShowEnginePreviewWindow(int engine);
@@ -96,7 +55,7 @@ void DeleteCustomEngineNames(void)
uint i;
StringID old;
for (i = 0; i != TOTAL_NUM_ENGINES; i++) {
for(i=0; i!=TOTAL_NUM_ENGINES; i++) {
old = _engine_name_strings[i];
_engine_name_strings[i] = i + STR_8000_KIRBY_PAUL_TANK_STEAM;
DeleteName(old);
@@ -113,10 +72,10 @@ void LoadCustomEngineNames(void)
static void SetupEngineNames(void)
{
StringID *name;
uint i;
for (name = _engine_name_strings; name != endof(_engine_name_strings); name++)
*name = STR_SV_EMPTY;
for(i=0; i!=TOTAL_NUM_ENGINES; i++)
_engine_name_strings[i] = STR_SV_EMPTY;
DeleteCustomEngineNames();
LoadCustomEngineNames();
@@ -240,34 +199,32 @@ void StartupEngines(void)
AdjustAvailAircraft();
}
uint32 _engine_refit_masks[TOTAL_NUM_ENGINES];
uint32 _engine_refit_masks[256];
// TODO: We don't support cargo-specific wagon overrides. Pretty exotic... ;-) --pasky
typedef struct WagonOverride {
struct WagonOverride {
byte *train_id;
int trains;
SpriteGroup group;
} WagonOverride;
struct SpriteGroup group;
};
typedef struct WagonOverrides {
static struct WagonOverrides {
int overrides_count;
WagonOverride *overrides;
} WagonOverrides;
struct WagonOverride *overrides;
} _engine_wagon_overrides[256];
static WagonOverrides _engine_wagon_overrides[TOTAL_NUM_ENGINES];
void SetWagonOverrideSprites(byte engine, SpriteGroup *group, byte *train_id,
int trains)
void SetWagonOverrideSprites(byte engine, struct SpriteGroup *group,
byte *train_id, int trains)
{
WagonOverrides *wos;
WagonOverride *wo;
struct WagonOverrides *wos;
struct WagonOverride *wo;
wos = &_engine_wagon_overrides[engine];
wos->overrides_count++;
wos->overrides = realloc(wos->overrides,
wos->overrides_count * sizeof(*wos->overrides));
wos->overrides_count * sizeof(struct WagonOverride));
wo = &wos->overrides[wos->overrides_count - 1];
/* FIXME: If we are replacing an override, release original SpriteGroup
@@ -279,9 +236,9 @@ void SetWagonOverrideSprites(byte engine, SpriteGroup *group, byte *train_id,
memcpy(wo->train_id, train_id, trains);
}
static SpriteGroup *GetWagonOverrideSpriteSet(byte engine, byte overriding_engine)
static struct SpriteGroup *GetWagonOverrideSpriteSet(byte engine, byte overriding_engine)
{
WagonOverrides *wos = &_engine_wagon_overrides[engine];
struct WagonOverrides *wos = &_engine_wagon_overrides[engine];
int i;
// XXX: This could turn out to be a timesink on profiles. We could
@@ -290,7 +247,7 @@ static SpriteGroup *GetWagonOverrideSpriteSet(byte engine, byte overriding_engin
// that. --pasky
for (i = 0; i < wos->overrides_count; i++) {
WagonOverride *wo = &wos->overrides[i];
struct WagonOverride *wo = &wos->overrides[i];
int j;
for (j = 0; j < wo->trains; j++) {
@@ -302,14 +259,14 @@ static SpriteGroup *GetWagonOverrideSpriteSet(byte engine, byte overriding_engin
}
byte _engine_original_sprites[TOTAL_NUM_ENGINES];
byte _engine_original_sprites[256];
// 0 - 28 are cargos, 29 is default, 30 is the advert (purchase list)
// (It isn't and shouldn't be like this in the GRF files since new cargo types
// may appear in future - however it's more convenient to store it like this in
// memory. --pasky)
static SpriteGroup _engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_GLOBAL_CID];
static struct SpriteGroup _engine_custom_sprites[256][NUM_CID];
void SetCustomEngineSprites(byte engine, byte cargo, SpriteGroup *group)
void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteGroup *group)
{
/* FIXME: If we are replacing an override, release original SpriteGroup
* to prevent leaks. But first we need to refcount the SpriteGroup.
@@ -317,11 +274,13 @@ void SetCustomEngineSprites(byte engine, byte cargo, SpriteGroup *group)
_engine_custom_sprites[engine][cargo] = *group;
}
typedef RealSpriteGroup *(*resolve_callback)(SpriteGroup *spritegroup,
const Vehicle *veh, void *callback); /* XXX data pointer used as function pointer */
typedef struct RealSpriteGroup *(*resolve_callback)(struct SpriteGroup *spritegroup,
struct Vehicle *veh,
void *callback); /* XXX data pointer used as function pointer */
static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
const Vehicle *veh, resolve_callback callback)
static struct RealSpriteGroup *
ResolveVehicleSpriteGroup(struct SpriteGroup *spritegroup, struct Vehicle *veh,
resolve_callback callback)
{
//debug("spgt %d", spritegroup->type);
switch (spritegroup->type) {
@@ -329,8 +288,8 @@ static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
return &spritegroup->g.real;
case SGT_DETERMINISTIC: {
DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
SpriteGroup *target;
struct DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
struct SpriteGroup *target;
int value = -1;
//debug("[%p] Having fun resolving variable %x", veh, dsg->variable);
@@ -338,6 +297,7 @@ static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
if ((dsg->variable >> 6) == 0) {
/* General property */
value = GetDeterministicSpriteValue(dsg->variable);
} else {
/* Vehicle-specific property. */
@@ -374,8 +334,8 @@ static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
chain_after++;
};
value = chain_before | chain_after << 8
| (chain_before + chain_after) << 16;
value = chain_before << 16 | chain_after << 8
| (chain_before + chain_after + 1);
} else {
value = 1; /* 1 vehicle in the chain */
}
@@ -475,7 +435,7 @@ static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
}
case SGT_RANDOMIZED: {
RandomizedSpriteGroup *rsg = &spritegroup->g.random;
struct RandomizedSpriteGroup *rsg = &spritegroup->g.random;
if (veh == NULL) {
/* Purchase list of something. Show the first one. */
@@ -499,32 +459,34 @@ static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
}
}
static SpriteGroup *GetVehicleSpriteGroup(byte engine, const Vehicle *v)
static struct SpriteGroup *GetVehicleSpriteGroup(byte engine, Vehicle *v)
{
SpriteGroup *group;
byte cargo = GC_PURCHASE;
struct SpriteGroup *group;
uint16 overriding_engine = -1;
byte cargo = CID_PURCHASE;
if (v != NULL) {
overriding_engine = v->type == VEH_Train ? v->u.rail.first_engine : -1;
cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
assert(cargo != GC_INVALID);
}
group = &_engine_custom_sprites[engine][cargo];
if (v != NULL && v->type == VEH_Train) {
SpriteGroup *overset = GetWagonOverrideSpriteSet(engine, v->u.rail.first_engine);
if (overriding_engine != 0xffff) {
struct SpriteGroup *overset;
if (overset != NULL) group = overset;
overset = GetWagonOverrideSpriteSet(engine, overriding_engine);
if (overset) group = overset;
}
return group;
}
int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction)
int GetCustomEngineSprite(byte engine, Vehicle *v, byte direction)
{
SpriteGroup *group;
RealSpriteGroup *rsg;
byte cargo = GC_PURCHASE;
struct SpriteGroup *group;
struct RealSpriteGroup *rsg;
byte cargo = CID_PURCHASE;
byte loaded = 0;
bool in_motion = 0;
int totalsets, spriteset;
@@ -534,8 +496,6 @@ int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction)
int capacity = v->cargo_cap;
cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
assert(cargo != GC_INVALID);
if (capacity == 0) capacity = 1;
loaded = (v->cargo_count * 100) / capacity;
in_motion = (v->cur_speed != 0);
@@ -589,23 +549,21 @@ static byte _vsg_bits_to_reseed;
extern int _custom_sprites_base;
static RealSpriteGroup *TriggerVehicleSpriteGroup(SpriteGroup *spritegroup,
Vehicle *veh, resolve_callback callback)
static struct RealSpriteGroup *
TriggerVehicleSpriteGroup(struct SpriteGroup *spritegroup, struct Vehicle *veh,
resolve_callback callback)
{
if (spritegroup->type == SGT_RANDOMIZED) {
_vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits(
&spritegroup->g.random,
_vsg_random_triggers,
&veh->waiting_triggers
);
}
if (spritegroup->type == SGT_RANDOMIZED)
_vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits(&spritegroup->g.random,
_vsg_random_triggers,
&veh->waiting_triggers);
return ResolveVehicleSpriteGroup(spritegroup, veh, callback);
}
static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first)
static void DoTriggerVehicle(Vehicle *veh, enum VehicleTrigger trigger, byte base_random_bits, bool first)
{
RealSpriteGroup *rsg;
struct RealSpriteGroup *rsg;
byte new_random_bits;
_vsg_random_triggers = trigger;
@@ -658,27 +616,19 @@ static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_ran
}
}
void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger)
void TriggerVehicle(Vehicle *veh, enum VehicleTrigger trigger)
{
DoTriggerVehicle(veh, trigger, 0, true);
}
static char *_engine_custom_names[TOTAL_NUM_ENGINES];
void SetCustomEngineName(int engine, const char *name)
static char *_engine_custom_names[256];
void SetCustomEngineName(int engine, char *name)
{
_engine_custom_names[engine] = strdup(name);
}
void UnInitNewgrEngines(void)
{
char **i;
for (i = _engine_custom_names; i != endof(_engine_custom_names); i++) {
free(*i);
*i = NULL;
}
}
StringID GetCustomEngineName(int engine)
{
if (!_engine_custom_names[engine])
@@ -689,53 +639,34 @@ StringID GetCustomEngineName(int engine)
}
void AcceptEnginePreview(Engine *e, PlayerID player)
void AcceptEnginePreview(Engine *e, int player)
{
Player *p = DEREF_PLAYER(player);
Player *p;
SETBIT(e->player_avail, player);
UPDATE_PLAYER_RAILTYPE(e, p);
p = DEREF_PLAYER(player);
UPDATE_PLAYER_RAILTYPE(e,p);
e->preview_player = 0xFF;
InvalidateWindowClasses(WC_BUILD_VEHICLE);
InvalidateWindowClasses(WC_REPLACE_VEHICLE);
}
static PlayerID GetBestPlayer(PlayerID pp)
{
const Player *p;
int32 best_hist;
PlayerID best_player;
uint mask = 0;
do {
best_hist = -1;
best_player = -1;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->block_preview == 0 && !HASBIT(mask, p->index) &&
p->old_economy[0].performance_history > best_hist) {
best_hist = p->old_economy[0].performance_history;
best_player = p->index;
}
}
if (best_player == (PlayerID)-1) return -1;
SETBIT(mask, best_player);
} while (--pp != 0);
return best_player;
}
void EnginesDailyLoop(void)
{
Engine *e;
int i;
int i,num;
Player *p;
uint mask;
int32 best_hist;
int best_player;
if (_cur_year >= 130) return;
if (_cur_year >= 130)
return;
for (e = _engines, i = 0; i != TOTAL_NUM_ENGINES; e++, i++) {
for(e=_engines,i=0; i!=TOTAL_NUM_ENGINES; e++,i++) {
if (e->flags & ENGINE_INTRODUCING) {
if (e->flags & ENGINE_PREVIEWING) {
if (e->preview_player != 0xFF && !--e->preview_wait) {
@@ -743,45 +674,47 @@ void EnginesDailyLoop(void)
DeleteWindowById(WC_ENGINE_PREVIEW, i);
e->preview_player++;
}
} else if (e->preview_player != 0xFF) {
PlayerID best_player = GetBestPlayer(e->preview_player);
if (best_player == (PlayerID)-1) {
e->preview_player = 0xFF;
continue;
}
} else if (e->preview_player != 0xFF) {
num = e->preview_player;
mask = 0;
do {
best_hist = -1;
best_player = -1;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->block_preview == 0 && !HASBIT(mask,p->index) &&
p->old_economy[0].performance_history > best_hist) {
best_hist = p->old_economy[0].performance_history;
best_player = p->index;
}
}
if (best_player == -1) {
e->preview_player = 0xFF;
goto next_engine;
}
mask |= (1 << best_player);
} while (--num != 0);
if (!IS_HUMAN_PLAYER(best_player)) {
/* XXX - TTDBUG: TTD has a bug here ???? */
/* TTDBUG: TTD has a bug here */
AcceptEnginePreview(e, best_player);
} else {
e->flags |= ENGINE_PREVIEWING;
e->preview_wait = 20;
if (IS_INTERACTIVE_PLAYER(best_player))
if (IS_INTERACTIVE_PLAYER(best_player)) {
ShowEnginePreviewWindow(i);
}
}
}
}
next_engine:;
}
}
/** Accept an engine prototype. XXX - it is possible that the top-player
* changes while you are waiting to accept the offer? Then it becomes invalid
* @param x,y unused
* @param p1 engine-prototype offered
* @param p2 unused
*/
int32 CmdWantEnginePreview(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Engine *e;
if (!IsEngineIndex(p1)) return CMD_ERROR;
e = DEREF_ENGINE(p1);
if (GetBestPlayer(e->preview_player) != _current_player) return CMD_ERROR;
if (flags & DC_EXEC)
AcceptEnginePreview(e, _current_player);
if (flags & DC_EXEC) {
AcceptEnginePreview(&_engines[p1], _current_player);
}
return 0;
}
@@ -878,19 +811,13 @@ void EnginesMonthlyLoop(void)
AdjustAvailAircraft();
}
/** Rename an engine.
* @param x,y unused
* @param p1 engine ID to rename
* @param p2 unused
*/
int32 CmdRenameEngine(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
StringID str;
if (!IsEngineIndex(p1)) return CMD_ERROR;
str = AllocateNameUnique(_cmd_text, 0);
if (str == 0) return CMD_ERROR;
str = AllocateNameUnique((byte*)_decode_parameters, 0);
if (str == 0)
return CMD_ERROR;
if (flags & DC_EXEC) {
StringID old_str = _engine_name_strings[p1];
@@ -980,27 +907,4 @@ const ChunkHandler _engine_chunk_handlers[] = {
};
/*
* returns true if an engine is valid, of the specified type, and buildable by
* the current player, false otherwise
*
* engine = index of the engine to check
* type = the type the engine should be of (VEH_xxx)
*/
bool IsEngineBuildable(uint engine, byte type)
{
const Engine *e;
// check if it's an engine that is in the engine array
if (!IsEngineIndex(engine)) return false;
e = DEREF_ENGINE(engine);
// check if it's an engine of specified type
if (e->type != type) return false;
// check if it's available
if (!HASBIT(e->player_avail, _current_player)) return false;
return true;
}

View File

@@ -66,10 +66,10 @@ typedef struct Engine {
uint16 duration_phase_1, duration_phase_2, duration_phase_3;
byte lifelength;
byte flags;
PlayerID preview_player;
byte preview_player;
byte preview_wait;
byte railtype;
PlayerID player_avail;
byte player_avail;
byte type; // type, ie VEH_Road, VEH_Train, etc. Same as in vehicle.h
} Engine;
@@ -79,64 +79,31 @@ enum {
RVI_WAGON = 2,
};
enum {
NUM_VEHICLE_TYPES = 6
};
void AddTypeToEngines(void);
void StartupEngines(void);
enum GlobalCargo {
GC_PASSENGERS = 0,
GC_COAL = 1,
GC_MAIL = 2,
GC_OIL = 3,
GC_LIVESTOCK = 4,
GC_GOODS = 5,
GC_GRAIN = 6, // GC_WHEAT / GC_MAIZE
GC_WOOD = 7,
GC_IRON_ORE = 8,
GC_STEEL = 9,
GC_VALUABLES = 10, // GC_GOLD / GC_DIAMONDS
GC_PAPER = 11,
GC_FOOD = 12,
GC_FRUIT = 13,
GC_COPPER_ORE = 14,
GC_WATER = 15,
GC_RUBBER = 16,
GC_SUGAR = 17,
GC_TOYS = 18,
GC_BATTERIES = 19,
GC_CANDY = 20,
GC_TOFFEE = 21,
GC_COLA = 22,
GC_COTTON_CANDY = 23,
GC_BUBBLES = 24,
GC_PLASTIC = 25,
GC_FIZZY_DRINKS = 26,
GC_PAPER_TEMP = 27,
GC_UNDEFINED = 28, // undefined; unused slot in arctic climate
GC_DEFAULT = 29,
GC_PURCHASE = 30,
GC_INVALID = 255,
NUM_GLOBAL_CID = 31
extern byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO];
enum {
CID_DEFAULT = 29,
CID_PURCHASE = 30,
NUM_CID = 31,
};
extern byte _local_cargo_id_ctype[NUM_CID];
extern byte _local_cargo_id_landscape[NUM_CID];
VARDEF const uint32 _default_refitmasks[NUM_VEHICLE_TYPES];
VARDEF const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO];
VARDEF const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE];
VARDEF const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID];
extern uint32 _engine_refit_masks[256];
VARDEF uint32 _engine_refit_masks[256];
VARDEF byte _engine_original_sprites[256];
extern byte _engine_original_sprites[256];
void SetWagonOverrideSprites(byte engine, struct SpriteGroup *group, byte *train_id, int trains);
void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteGroup *group);
// loaded is in percents, overriding_engine 0xffff is none
int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction);
int GetCustomEngineSprite(byte engine, Vehicle *v, byte direction);
#define GetCustomVehicleSprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction)
#define GetCustomVehicleIcon(et, direction) GetCustomEngineSprite(et, NULL, direction)
typedef enum VehicleTrigger {
enum VehicleTrigger {
VEHICLE_TRIGGER_NEW_CARGO = 1,
// Externally triggered only for the first vehicle in chain
VEHICLE_TRIGGER_DEPOT = 2,
@@ -144,10 +111,10 @@ typedef enum VehicleTrigger {
VEHICLE_TRIGGER_EMPTY = 4,
// Not triggered externally (called for the whole chain if we got NEW_CARGO)
VEHICLE_TRIGGER_ANY_NEW_CARGO = 8,
} VehicleTrigger;
void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger);
};
void TriggerVehicle(Vehicle *veh, enum VehicleTrigger trigger);
void SetCustomEngineName(int engine, const char *name);
void SetCustomEngineName(int engine, char *name);
StringID GetCustomEngineName(int engine);
@@ -161,13 +128,11 @@ void DrawRoadVehEngineInfo(int engine, int x, int y, int maxw);
void DrawShipEngineInfo(int engine, int x, int y, int maxw);
void DrawAircraftEngineInfo(int engine, int x, int y, int maxw);
void AcceptEnginePreview(Engine *e, PlayerID player);
void AcceptEnginePreview(Engine *e, int player);
void LoadCustomEngineNames(void);
void DeleteCustomEngineNames(void);
bool IsEngineBuildable(uint engine, byte type);
void UnInitNewgrEngines(void);
enum {
NUM_NORMAL_RAIL_ENGINES = 54,
@@ -183,21 +148,9 @@ enum {
ROAD_ENGINES_INDEX = NUM_TRAIN_ENGINES,
};
VARDEF Engine _engines[TOTAL_NUM_ENGINES];
#define FOR_ALL_ENGINES(e) for (e = _engines; e != endof(_engines); e++)
#define DEREF_ENGINE(i) (GetEngine(i))
static inline Engine* GetEngine(uint i)
{
assert(i < lengthof(_engines));
return &_engines[i];
}
#define DEREF_ENGINE(i) (&_engines[i])
VARDEF StringID _engine_name_strings[TOTAL_NUM_ENGINES];
static inline bool IsEngineIndex(uint index)
{
return index < TOTAL_NUM_ENGINES;
}
/* Access Vehicle Data */
//#include "table/engines.h"
extern EngineInfo _engine_info[TOTAL_NUM_ENGINES];

135
extmidi.c
View File

@@ -4,9 +4,6 @@
#include "ttd.h"
#include "hal.h"
#include "sound.h"
#include "string.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -14,97 +11,93 @@
#include <sys/stat.h>
#include <errno.h>
static struct {
char song[MAX_PATH];
int pid;
} _midi;
#ifndef EXTERNAL_PLAYER
#define EXTERNAL_PLAYER "timidity"
#endif
static void DoPlay(void);
static void DoStop(void);
static pid_t _pid;
static const char* ExtMidiStart(const char* const * parm)
static void extmidi_kill(void)
{
_midi.song[0] = '\0';
_midi.pid = -1;
if (_pid > 0) {
kill(_pid, SIGKILL);
while (waitpid(_pid, NULL, WNOHANG) != _pid);
}
_pid = 0;
}
static char *extmidi_start(char **parm)
{
_pid = 0;
return NULL;
}
static void ExtMidiStop(void)
static void extmidi_stop(void)
{
_midi.song[0] = '\0';
DoStop();
extmidi_kill();
}
static void ExtMidiPlaySong(const char* filename)
static void extmidi_play_song(const char *filename)
{
ttd_strlcpy(_midi.song, filename, lengthof(_midi.song));
DoStop();
extmidi_kill();
_pid = fork();
if (_pid < 0) {
fprintf(stderr, "extmidi: couldn't fork: %s\n", strerror(errno));
_pid = 0;
return;
}
if (_pid == 0) {
#if defined(MIDI_ARG)
execlp(EXTERNAL_PLAYER, "extmidi", MIDI_ARG, filename, NULL);
#else
execlp(EXTERNAL_PLAYER, "extmidi", filename, NULL);
#endif
fprintf(stderr, "extmidi: couldn't execl: %s\n", strerror(errno));
exit(0);
}
usleep(500);
if (_pid == waitpid(_pid, NULL, WNOHANG)) {
fprintf(stderr, "extmidi: play song failed\n");
_pid = 0;
usleep(5000);
}
}
static void ExtMidiStopSong(void)
static void extmidi_stop_song(void)
{
_midi.song[0] = '\0';
DoStop();
extmidi_kill();
}
static bool ExtMidiIsPlaying(void)
static bool extmidi_is_playing(void)
{
if (_midi.pid != -1 && waitpid(_midi.pid, NULL, WNOHANG) == _midi.pid)
_midi.pid = -1;
if (_midi.pid == -1 && _midi.song[0] != '\0') DoPlay();
return _midi.pid != -1;
if (_pid == 0)
return 0;
if (waitpid(_pid, NULL, WNOHANG) == _pid) {
_pid = 0;
return 0;
}
return 1;
}
static void ExtMidiSetVolume(byte vol)
static void extmidi_set_volume(byte vol)
{
fprintf(stderr, "extmidi: set volume not implemented\n");
}
static void DoPlay(void)
{
_midi.pid = fork();
switch (_midi.pid) {
case 0: {
int d;
close(0);
close(1);
close(2);
d = open("/dev/null", O_RDONLY);
if (d != -1) {
if (dup2(d, 1) != -1 && dup2(d, 2) != -1) {
#if defined(MIDI_ARG)
execlp(msf.extmidi, "extmidi", MIDI_ARG, _midi.song, NULL);
#else
execlp(msf.extmidi, "extmidi", _midi.song, NULL);
#endif
}
}
exit(1);
}
case -1:
fprintf(stderr, "extmidi: couldn't fork: %s\n", strerror(errno));
/* FALLTHROUGH */
default:
_midi.song[0] = '\0';
break;
}
}
static void DoStop(void)
{
if (_midi.pid != -1) kill(_midi.pid, SIGTERM);
}
const HalMusicDriver _extmidi_music_driver = {
ExtMidiStart,
ExtMidiStop,
ExtMidiPlaySong,
ExtMidiStopSong,
ExtMidiIsPlaying,
ExtMidiSetVolume,
extmidi_start,
extmidi_stop,
extmidi_play_song,
extmidi_stop_song,
extmidi_is_playing,
extmidi_set_volume,
};
#endif /* __MORPHOS__ */

View File

@@ -100,42 +100,6 @@ void FioCloseAll(void)
FioCloseFile(i);
}
bool FiosCheckFileExists(const char *filename)
{
FILE *f;
char buf[MAX_PATH];
sprintf(buf, "%s%s", _path.data_dir, filename);
f = fopen(buf, "rb");
#if !defined(WIN32)
if (f == NULL) {
char *s;
// Make lower case and try again
for(s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
*s = tolower(*s);
f = fopen(buf, "rb");
#if defined SECOND_DATA_DIR
// tries in the 2nd data directory
if (f == NULL) {
sprintf(buf, "%s%s", _path.second_data_dir, filename);
for(s=buf + strlen(_path.second_data_dir) - 1; *s != 0; s++)
*s = tolower(*s);
f = fopen(buf, "rb");
}
#endif
}
#endif
if (f == NULL)
return false;
else {
fclose(f);
return true;
}
}
void FioOpenFile(int slot, const char *filename)
{
FILE *f;

View File

@@ -11,6 +11,5 @@ void FioCloseAll(void);
void FioOpenFile(int slot, const char *filename);
void FioReadBlock(void *ptr, uint size);
void FioSkipBytes(int n);
bool FiosCheckFileExists(const char *filename);
#endif /* FILEIO_H */

View File

@@ -8,24 +8,32 @@
/* landscape.c */
void FindLandscapeHeight(TileInfo *ti, uint x, uint y);
void FindLandscapeHeightByTile(TileInfo *ti, TileIndex tile);
void FindLandscapeHeightByTile(TileInfo *ti, uint tile);
uint GetTileSlope(uint tile, int *h);
int GetTileZ(uint tile);
void DoClearSquare(TileIndex tile);
void CDECL ModifyTile(TileIndex tile, uint flags, ...);
void DoClearSquare(uint tile);
void CDECL ModifyTile(uint tile, uint flags, ...);
void SetMapExtraBits(uint tile, byte flags);
uint GetMapExtraBits(uint tile);
void RunTileLoop(void);
uint GetPartialZ(int x, int y, int corners);
uint GetSlopeZ(int x, int y);
uint32 GetTileTrackStatus(TileIndex tile, TransportType mode);
void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac);
void ChangeTileOwner(TileIndex tile, byte old_player, byte new_player);
void AnimateTile(TileIndex tile);
void ClickTile(TileIndex tile);
void GetTileDesc(TileIndex tile, TileDesc *td);
uint32 GetTileTrackStatus(uint tile, TransportType mode);
void GetAcceptedCargo(uint tile, AcceptedCargo ac);
void ChangeTileOwner(uint tile, byte old_player, byte new_player);
void AnimateTile(uint tile);
void ClickTile(uint tile);
void GetTileDesc(uint tile, TileDesc *td);
void DrawTile(TileInfo *ti);
void UpdateTownMaxPass(Town *t);
bool IsValidTile(TileIndex tile);
uint TileAddWrap(TileIndex tile, int addx, int addy);
enum {
TILE_WRAPPED = (uint)-1
};
bool IsValidTile(uint tile);
static inline Point RemapCoords(int x, int y, int z)
{
@@ -46,18 +54,28 @@ static inline Point RemapCoords2(int x, int y)
return RemapCoords(x, y, GetSlopeZ(x, y));
}
/* game.c */
byte *GetString(byte *buffr, uint16 string);
void InjectDparam(int amount);
int32 GetParamInt32(void);
int GetParamInt16(void);
int GetParamInt8(void);
int GetParamUint16(void);
/* clear_land.c */
void DrawHillyLandTile(TileInfo *ti);
void DrawClearLandTile(TileInfo *ti, byte set);
void DrawClearLandFence(TileInfo *ti, byte img);
void TileLoopClearHelper(TileIndex tile);
void TileLoopClearHelper(uint tile);
/* station_land.c */
void StationPickerDrawSprite(int x, int y, int railtype, int image);
/* track_land.c */
void DrawTrainDepotSprite(int x, int y, int image, int railtype);
void DrawWaypointSprite(int x, int y, int image, int railtype);
/* road_land.c */
void DrawRoadDepotSprite(int x, int y, int image);
@@ -145,7 +163,7 @@ void NetworkShutDown(void);
void NetworkGameLoop(void);
void NetworkUDPGameLoop(void);
bool NetworkServerStart(void);
bool NetworkClientConnectGame(const char* host, unsigned short port);
bool NetworkClientConnectGame(const byte* host, unsigned short port);
void NetworkReboot(void);
void NetworkDisconnect(void);
void NetworkSend_Command(uint32 tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback);
@@ -153,20 +171,28 @@ void NetworkSend_Command(uint32 tile, uint32 p1, uint32 p2, uint32 cmd, CommandC
/* misc_cmd.c */
void PlaceTreesRandomly(void);
uint GetTileDist(TileIndex xy1, TileIndex xy2);
uint GetTileDist1D(TileIndex xy1, TileIndex xy2);
uint GetTileDist1Db(TileIndex xy1, TileIndex xy2);
uint GetTileDistAdv(TileIndex xy1, TileIndex xy2);
bool CheckDistanceFromEdge(TileIndex tile, uint distance);
void InitializeLandscapeVariables(bool only_constants);
/* misc.c */
void DeleteName(StringID id);
char *GetName(int id, char *buff);
byte *GetName(int id, byte *buff);
// AllocateNameUnique also tests if the name used is not used anywere else
// and if it is used, it returns an error.
#define AllocateNameUnique(name, skip) RealAllocateName(name, skip, true)
#define AllocateName(name, skip) RealAllocateName(name, skip, false)
StringID RealAllocateName(const char *name, byte skip, bool check_double);
StringID RealAllocateName(const byte *name, byte skip, bool check_double);
void ConvertDayToYMD(YearMonthDay *ymd, uint16 date);
uint ConvertYMDToDay(uint year, uint month, uint day);
uint ConvertIntDate(uint date);
void CSleep(int milliseconds);
/* misc functions */
void MarkTileDirty(int x, int y);
@@ -206,6 +232,7 @@ void ShowNetworkChatQueryWindow(byte desttype, byte dest);
void ShowNetworkGiveMoneyWindow(byte player);
void ShowNetworkNeedGamePassword(void);
void ShowNetworkNeedCompanyPassword(void);
void ShowRenameWaypointWindow(Waypoint *cp);
int FindFirstBit(uint32 x);
void ShowHighscoreTable(int difficulty, int8 rank);
void ShowEndGameChart(void);
@@ -226,8 +253,6 @@ enum SaveOrLoadMode {
int SaveOrLoad(const char *filename, int mode);
void AfterLoadTown(void);
void GenRandomNewGame(uint32 rnd1, uint32 rnd2);
void StartScenarioEditor(uint32 rnd1, uint32 rnd2);
void AskExitGame(void);
void AskExitToGameMenu(void);
@@ -246,24 +271,25 @@ enum {
};
void ShowSaveLoadDialog(int mode);
void ttd_strlcpy(char *dst, const char *src, size_t size);
void ttd_strlcat(char *dst, const char *src, size_t size);
// callback from drivers that is called if the game size changes dynamically
void GameSizeChanged(void);
bool FileExists(const char *filename);
bool ReadLanguagePack(int index);
void InitializeLanguagePacks(void);
void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
byte *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize);
int GetLanguageList(char **languages, int max);
void CheckSwitchToEuro(void);
void LoadFromConfig(void);
void SaveToConfig(void);
void CheckConfig(void);
int ttd_main(int argc, char* argv[]);
byte GetOSVersion(void);
void DeterminePaths(void);
char * CDECL str_fmt(const char *str, ...);
void bubblesort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
#endif /* FUNCTIONS_H */

197
gfx.c
View File

@@ -1,17 +1,15 @@
#include "stdafx.h"
#include "ttd.h"
#include "spritecache.h"
#include "strings.h"
#include "gfx.h"
#include "table/palettes.h"
#include "hal.h"
static void GfxMainBlitter(const Sprite *sprite, int x, int y, int mode);
static void GfxMainBlitter(byte *sprite, int x, int y, int mode);
static int _stringwidth_out;
static byte _cursor_backup[64*64];
static Rect _invalid_rect;
static const byte *_color_remap_ptr;
static byte *_color_remap_ptr;
static byte _string_colorremap[3];
#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH/64)
@@ -106,7 +104,7 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo) {
void GfxFillRect(int left, int top, int right, int bottom, int color) {
DrawPixelInfo *dpi = _cur_dpi;
byte *dst;
byte *dst,*ctab;
const int otop = top;
const int oleft = left;
@@ -144,8 +142,7 @@ void GfxFillRect(int left, int top, int right, int bottom, int color) {
} while (--bottom);
} else {
/* use colortable mode */
const byte* ctab = GetNonSprite(color & 0x3FFF) + 1;
ctab = GetSpritePtr(color & 0x3FFF) + 1;
do {
int i;
for(i=0; i!=right;i++)
@@ -244,6 +241,8 @@ void GfxDrawLine(int x, int y, int x2, int y2, int color)
enum {
ASCII_LETTERSTART = 32,
ASCII_SETX = 1,
ASCII_SETXY = 2,
@@ -258,31 +257,29 @@ enum {
/* returns right coordinate */
int DrawString(int x, int y, uint16 str, uint16 color)
{
char buffer[512];
GetString(buffer, str);
return DoDrawString(buffer, x, y, color);
GetString(str_buffr, str);
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
return DoDrawString(str_buffr, x, y, color);
}
void DrawStringRightAligned(int x, int y, uint16 str, uint16 color)
{
char buffer[512];
GetString(buffer, str);
DoDrawString(buffer, x - GetStringWidth(buffer), y, color);
GetString(str_buffr, str);
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
DoDrawString(str_buffr, x - GetStringWidth(str_buffr), y, color);
}
int DrawStringCentered(int x, int y, uint16 str, uint16 color)
{
char buffer[512];
int w;
GetString(buffer, str);
GetString(str_buffr, str);
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
w = GetStringWidth(buffer);
DoDrawString(buffer, x - w / 2, y, color);
w = GetStringWidth(str_buffr);
DoDrawString(str_buffr, x - (w>>1), y, color);
return w;
}
@@ -293,12 +290,12 @@ void DrawStringCenterUnderline(int x, int y, uint16 str, uint16 color)
GfxFillRect(x-(w>>1), y+10, x-(w>>1)+w, y+10, _string_colorremap[1]);
}
static uint32 FormatStringLinebreaks(char *str, int maxw)
static uint32 FormatStringLinebreaks(byte *str, int maxw)
{
int num = 0;
int base = _stringwidth_base;
int w;
char *last_space;
byte *last_space;
byte c;
for(;;) {
@@ -307,10 +304,10 @@ static uint32 FormatStringLinebreaks(char *str, int maxw)
for(;;) {
c = *str++;
if (c == ASCII_LETTERSTART) last_space = str;
if (c == ' ') last_space = str;
if (c >= ASCII_LETTERSTART) {
w += GetCharacterWidth(base + (byte)c);
w += _stringwidth_table[base + ((byte)c) - 0x20];
if (w > maxw) {
str = last_space;
if (str == NULL)
@@ -336,15 +333,15 @@ static uint32 FormatStringLinebreaks(char *str, int maxw)
void DrawStringMultiCenter(int x, int y, uint16 str, int maxw)
{
char buffer[512];
uint32 tmp;
int num, w, mt, t;
const char *src;
byte *src;
byte c;
GetString(buffer, str);
GetString(str_buffr, str);
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
tmp = FormatStringLinebreaks(buffer, maxw);
tmp = FormatStringLinebreaks(str_buffr, maxw);
num = (uint16)tmp;
t = tmp >> 16;
@@ -356,7 +353,7 @@ void DrawStringMultiCenter(int x, int y, uint16 str, int maxw)
y -= (mt >> 1) * num;
src = buffer;
src = str_buffr;
for(;;) {
w = GetStringWidth(src);
@@ -382,15 +379,15 @@ void DrawStringMultiCenter(int x, int y, uint16 str, int maxw)
}
void DrawStringMultiLine(int x, int y, uint16 str, int maxw) {
char buffer[512];
uint32 tmp;
int num, w, mt, t;
const char *src;
byte *src;
byte c;
GetString(buffer, str);
GetString(str_buffr, str);
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
tmp = FormatStringLinebreaks(buffer, maxw);
tmp = FormatStringLinebreaks(str_buffr, maxw);
num = (uint16)tmp;
t = tmp >> 16;
mt = 10;
@@ -399,7 +396,7 @@ void DrawStringMultiLine(int x, int y, uint16 str, int maxw) {
if (t != 244) mt = 18;
}
src = buffer;
src = str_buffr;
for(;;) {
w = GetStringWidth(src);
@@ -424,14 +421,17 @@ void DrawStringMultiLine(int x, int y, uint16 str, int maxw) {
}
}
int GetStringWidth(const char *str)
{
int w = 0;
int GetStringWidth(const byte *str) {
int w = -1;
byte c;
int base = _stringwidth_base;
for (c = *str; c != '\0'; c = *(++str)) {
for(;;) {
c = *str++;
if (c == 0)
return w;
if (c >= ASCII_LETTERSTART) {
w += GetCharacterWidth(base + c);
w += _stringwidth_table[base + c - ASCII_LETTERSTART];
} else {
if (c == ASCII_SETX) str++;
else if (c == ASCII_SETXY) str += 2;
@@ -439,7 +439,6 @@ int GetStringWidth(const char *str)
else if (c == ASCII_BIGFONT) base = 448;
}
}
return w;
}
void DrawFrameRect(int left, int top, int right, int bottom, int ctab, int flags) {
@@ -475,8 +474,7 @@ void DrawFrameRect(int left, int top, int right, int bottom, int ctab, int flags
}
}
int DoDrawString(const char *string, int x, int y, uint16 real_color)
{
int DoDrawString(const byte *string, int x, int y, uint16 real_color) {
DrawPixelInfo *dpi = _cur_dpi;
int base = _stringwidth_base;
byte c;
@@ -524,9 +522,9 @@ skip_cont:;
if (c >= ASCII_LETTERSTART) {
if (x >= dpi->left + dpi->width) goto skip_char;
if (x + 26 >= dpi->left) {
GfxMainBlitter(GetSprite(base + 2 + c - ASCII_LETTERSTART), x, y, 1);
GfxMainBlitter(GetSpritePtr(base + 2 + c - ASCII_LETTERSTART), x, y, 1);
}
x += GetCharacterWidth(base + c);
x += _stringwidth_table[base + c - ' '];
} else if (c == ASCII_NL) { // newline = {}
x = xo;
y += 10;
@@ -540,10 +538,10 @@ skip_cont:;
color = (byte)(c - ASCII_COLORSTART);
goto switch_color;
} else if (c == ASCII_SETX) { // {SETX}
x = xo + (byte)*string++;
x = xo + *string++;
} else if (c == ASCII_SETXY) {// {SETXY}
x = xo + (byte)*string++;
y = yo + (byte)*string++;
x = xo + *string++;
y = yo + *string++;
} else if (c == ASCII_TINYFONT) { // {TINYFONT}
base = 0xE0;
} else if (c == ASCII_BIGFONT) { // {BIGFONT}
@@ -556,20 +554,19 @@ skip_cont:;
void DrawSprite(uint32 img, int x, int y) {
if (img & 0x8000) {
_color_remap_ptr = GetNonSprite(img >> 16) + 1;
GfxMainBlitter(GetSprite(img & 0x3FFF), x, y, 1);
_color_remap_ptr = GetSpritePtr(img >> 16) + 1;
GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 1);
} else if (img & 0x4000) {
_color_remap_ptr = GetNonSprite(img >> 16) + 1;
GfxMainBlitter(GetSprite(img & 0x3FFF), x, y, 2);
_color_remap_ptr = GetSpritePtr(img >> 16) + 1;
GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 2);
} else {
GfxMainBlitter(GetSprite(img & 0x3FFF), x, y, 0);
GfxMainBlitter(GetSpritePtr(img & 0x3FFF), x, y, 0);
}
}
typedef struct BlitterParams {
int start_x, start_y;
const byte* sprite;
const byte* sprite_org;
byte *sprite, *sprite_org;
byte *dst;
int mode;
int width, height;
@@ -580,12 +577,10 @@ typedef struct BlitterParams {
static void GfxBlitTileZoomIn(BlitterParams *bp)
{
const byte* src_o = bp->sprite;
const byte* src;
byte *src_o = bp->sprite, *src;
int num, skip;
byte done;
byte *dst;
const byte* ctab;
byte *dst, *ctab;
if (bp->mode & 1) {
src_o += READ_LE_UINT16(src_o + bp->start_y * 2);
@@ -724,7 +719,7 @@ static void GfxBlitTileZoomIn(BlitterParams *bp)
static void GfxBlitZoomInUncomp(BlitterParams *bp)
{
const byte *src = bp->sprite;
byte *src = bp->sprite;
byte *dst = bp->dst;
int height = bp->height;
int width = bp->width;
@@ -735,7 +730,7 @@ static void GfxBlitZoomInUncomp(BlitterParams *bp)
if (bp->mode & 1) {
if (bp->info & 1) {
const byte *ctab = _color_remap_ptr;
byte *ctab = _color_remap_ptr;
byte b;
do {
@@ -749,8 +744,7 @@ static void GfxBlitZoomInUncomp(BlitterParams *bp)
}
} else if (bp->mode & 2) {
if (bp->info & 1) {
const byte *ctab = _color_remap_ptr;
byte *ctab = _color_remap_ptr;
do {
for(i=0; i!=width; i++)
if (src[i])
@@ -797,12 +791,10 @@ static void GfxBlitZoomInUncomp(BlitterParams *bp)
static void GfxBlitTileZoomMedium(BlitterParams *bp)
{
const byte* src_o = bp->sprite;
const byte* src;
byte *src_o = bp->sprite, *src;
int num, skip;
byte done;
byte *dst;
const byte* ctab;
byte *dst, *ctab;
if (bp->mode & 1) {
src_o += READ_LE_UINT16(src_o + bp->start_y * 2);
@@ -975,7 +967,7 @@ static void GfxBlitTileZoomMedium(BlitterParams *bp)
static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
{
const byte *src = bp->sprite;
byte *src = bp->sprite;
byte *dst = bp->dst;
int height = bp->height;
int width = bp->width;
@@ -986,9 +978,7 @@ static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
if (bp->mode & 1) {
if (bp->info & 1) {
const byte *ctab = _color_remap_ptr;
byte b;
byte *ctab = _color_remap_ptr,b;
height >>= 1;
if (height) do {
for(i=0; i!=width>>1; i++)
@@ -1000,8 +990,7 @@ static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
}
} else if (bp->mode & 2) {
if (bp->info & 1) {
const byte *ctab = _color_remap_ptr;
byte *ctab = _color_remap_ptr;
height >>= 1;
if (height) do {
for(i=0; i!=width>>1; i++)
@@ -1027,12 +1016,10 @@ static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
static void GfxBlitTileZoomOut(BlitterParams *bp)
{
const byte* src_o = bp->sprite;
const byte* src;
byte *src_o = bp->sprite, *src;
int num, skip;
byte done;
byte *dst;
const byte* ctab;
byte *dst, *ctab;
if (bp->mode & 1) {
src_o += READ_LE_UINT16(src_o + bp->start_y * 2);
@@ -1271,7 +1258,7 @@ static void GfxBlitTileZoomOut(BlitterParams *bp)
static void GfxBlitZoomOutUncomp(BlitterParams *bp)
{
const byte* src = bp->sprite;
byte *src = bp->sprite;
byte *dst = bp->dst;
int height = bp->height;
int width = bp->width;
@@ -1282,9 +1269,7 @@ static void GfxBlitZoomOutUncomp(BlitterParams *bp)
if (bp->mode & 1) {
if (bp->info & 1) {
const byte *ctab = _color_remap_ptr;
byte b;
byte *ctab = _color_remap_ptr,b;
height >>= 2;
if (height) do {
for(i=0; i!=width>>2; i++)
@@ -1296,8 +1281,7 @@ static void GfxBlitZoomOutUncomp(BlitterParams *bp)
}
} else if (bp->mode & 2) {
if (bp->info & 1) {
const byte *ctab = _color_remap_ptr;
byte *ctab = _color_remap_ptr;
height >>= 2;
if (height) do {
for(i=0; i!=width>>2; i++)
@@ -1323,7 +1307,7 @@ static void GfxBlitZoomOutUncomp(BlitterParams *bp)
typedef void (*BlitZoomFunc)(BlitterParams *bp);
static void GfxMainBlitter(const Sprite* sprite, int x, int y, int mode)
static void GfxMainBlitter(byte *sprite, int x, int y, int mode)
{
DrawPixelInfo *dpi = _cur_dpi;
int start_x, start_y;
@@ -1345,13 +1329,13 @@ static void GfxMainBlitter(const Sprite* sprite, int x, int y, int mode)
};
/* decode sprite header */
x += sprite->x_offs;
y += sprite->y_offs;
bp.width_org = bp.width = sprite->width;
bp.height_org = bp.height = sprite->height;
info = sprite->info;
x += (int16)READ_LE_UINT16(&((SpriteHdr*)sprite)->x_offs);
y += (int16)READ_LE_UINT16(&((SpriteHdr*)sprite)->y_offs);
bp.width_org = bp.width = READ_LE_UINT16(&((SpriteHdr*)sprite)->width);
bp.height_org = bp.height = ((SpriteHdr*)sprite)->height;
info = ((SpriteHdr*)sprite)->info;
bp.info = info;
bp.sprite_org = bp.sprite = sprite->data;
bp.sprite_org = bp.sprite = sprite + sizeof(SpriteHdr);
bp.dst = dpi->dst_ptr;
bp.mode = mode;
bp.pitch = dpi->pitch;
@@ -1448,7 +1432,7 @@ static void GfxMainBlitter(const Sprite* sprite, int x, int y, int mode)
if (info&2) {
int totpix = bp.height_org * bp.width_org;
byte *dst = (byte*)alloca(totpix);
const byte *src = bp.sprite_org;
byte *src = bp.sprite_org;
signed char b;
bp.sprite = dst + (bp.sprite - bp.sprite_org);
@@ -1638,15 +1622,15 @@ void LoadStringWidthTable(void)
// 2 equals space.
for(i=2; i != 0xE2; i++) {
*b++ = (byte)((i < 93 || i >= 129 || i == 98) ? GetSprite(i)->width : 0);
*b++ = (byte)((i < 93 || i >= 129 || i == 98) ? GetSpritePtr(i)[2] : 0);
}
for(i=0xE2; i != 0x1C2; i++) {
*b++ = (byte)((i < 317 || i >= 353) ? GetSprite(i)->width + 1 : 0);
*b++ = (byte)((i < 317 || i >= 353) ? GetSpritePtr(i)[2]+1 : 0);
}
for(i=0x1C2; i != 0x2A2; i++) {
*b++ = (byte)((i < 541 || i >= 577) ? GetSprite(i)->width + 1 : 0);
*b++ = (byte)((i < 541 || i >= 577) ? GetSpritePtr(i)[2]+1 : 0);
}
}
@@ -1916,17 +1900,17 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, DrawPixelInfo *o, int left, int top, in
static void SetCursorSprite(uint cursor)
{
CursorVars *cv = &_cursor;
const Sprite *p;
byte *p;
if (cv->sprite == cursor)
return;
p = GetSprite(cursor & 0x3FFF);
p = GetSpritePtr(cursor & 0x3FFF);
cv->sprite = cursor;
cv->size.y = p->height;
cv->size.x = p->width;
cv->offs.x = p->x_offs;
cv->offs.y = p->y_offs;
cv->size.y = *(byte*)(p+1);
cv->size.x = READ_LE_UINT16(p+2);
cv->offs.x = (int16)READ_LE_UINT16(p+4);
cv->offs.y = (int16)READ_LE_UINT16(p+6);
cv->dirty = true;
}
@@ -1979,16 +1963,15 @@ bool ChangeResInGame(int w, int h)
return true;
}
static int CDECL compare_res(const void *pa, const void *pb)
void ToggleFullScreen(const bool full_screen)
{
int x = ((const uint16*)pa)[0] - ((const uint16*)pb)[0];
if (x != 0) return x;
return ((const uint16*)pa)[1] - ((const uint16*)pb)[1];
}
void SortResolutions(int count)
{
qsort(_resolutions, count, sizeof(_resolutions[0]), compare_res);
_fullscreen = full_screen;
/* use preset resolutions, not _screen.height and _screen.width. On windows for example
if Desktop-size is 1280x1024, and gamesize is also 1280x1024, _screen.height will be
only 1000 because of possible start-bar. For this reason you cannot switch to
fullscreen mode from this resolution. Use of preset resolution will fix this */
if (!_video_driver->change_resolution(_cur_resolution[0], _cur_resolution[1]))
_fullscreen ^= true; // switching resolution failed, put back full_screen to original status
}
uint16 GetDrawStringPlayerColor(byte player)

33
gfx.h
View File

@@ -17,6 +17,14 @@ struct DrawPixelInfo {
};
typedef struct SpriteHdr {
byte info;
byte height;
uint16 width;
int16 x_offs, y_offs;
} SpriteHdr;
assert_compile(sizeof(SpriteHdr) == 8);
typedef struct CursorVars {
Point pos, size, offs, delta;
Point draw_pos, draw_size;
@@ -37,14 +45,14 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo);
int DrawStringCentered(int x, int y, uint16 str, uint16 color);
int DrawString(int x, int y, uint16 str, uint16 color);
void DrawStringCenterUnderline(int x, int y, uint16 str, uint16 color);
int DoDrawString(const char *string, int x, int y, uint16 color);
int DoDrawString(const byte *string, int x, int y, uint16 color);
void DrawStringRightAligned(int x, int y, uint16 str, uint16 color);
void GfxFillRect(int left, int top, int right, int bottom, int color);
void GfxDrawLine(int left, int top, int right, int bottom, int color);
void DrawFrameRect(int left, int top, int right, int bottom, int color, int flags);
uint16 GetDrawStringPlayerColor(byte player);
int GetStringWidth(const char *str);
int GetStringWidth(const byte *str);
void LoadStringWidthTable(void);
void DrawStringMultiCenter(int x, int y, uint16 str, int maxw);
void DrawStringMultiLine(int x, int y, uint16 str, int maxw);
@@ -59,6 +67,11 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, DrawPixelInfo *o, int left, int top, in
/* window.c */
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom);
/* spritecache.c */
byte *GetSpritePtr(uint sprite);
void GfxInitSpriteMem(byte *ptr, uint32 size);
void GfxLoadSprites(void);
void SetMouseCursor(uint cursor);
void SetAnimatedMouseCursor(const uint16 *table);
void CursorTick(void);
@@ -66,18 +79,18 @@ void DrawMouseCursor(void);
void ScreenSizeChanged(void);
void UndrawMouseCursor(void);
bool ChangeResInGame(int w, int h);
void SortResolutions(int count);
void ToggleFullScreen(bool full_screen);
void ToggleFullScreen(const bool full_screen);
typedef struct {
int xoffs, yoffs;
int xsize, ysize;
} SpriteDimension;
const SpriteDimension *GetSpriteDimension(uint sprite);
/* gfx.c */
#define ASCII_LETTERSTART 32
VARDEF int _stringwidth_base;
VARDEF byte _stringwidth_table[0x2A0];
static inline byte GetCharacterWidth(uint key)
{
assert(key >= ASCII_LETTERSTART && key - ASCII_LETTERSTART < lengthof(_stringwidth_table));
return _stringwidth_table[key - ASCII_LETTERSTART];
}
VARDEF DrawPixelInfo _screen;
VARDEF DrawPixelInfo *_cur_dpi;

View File

@@ -6,9 +6,6 @@
#include "gfx.h"
#include "player.h"
#include "economy.h"
#include "signs.h"
#include "strings.h"
#include "debug.h"
static uint _legend_excludebits;
static uint _legend_cargobits;
@@ -1101,149 +1098,3 @@ void ShowPerformanceRatingDetail(void)
{
AllocateWindowDescFront(&_performance_rating_detail_desc, 0);
}
static uint16 _num_sign_sort;
static char _bufcache[64];
static uint16 _last_sign_idx;
static int CDECL SignNameSorter(const void *a, const void *b)
{
char buf1[64];
SignStruct *ss;
const uint16 cmp1 = *(const uint16 *)a;
const uint16 cmp2 = *(const uint16 *)b;
ss = GetSign(cmp1);
GetString(buf1, ss->str);
if (cmp2 != _last_sign_idx) {
_last_sign_idx = cmp2;
ss = GetSign(cmp2);
GetString(_bufcache, ss->str);
}
return strcmp(buf1, _bufcache); // sort by name
}
static void GlobalSortSignList(void)
{
const SignStruct *ss;
uint32 n = 0;
_num_sign_sort = 0;
/* Create array for sorting */
_sign_sort = realloc(_sign_sort, GetSignPoolSize() * sizeof(_sign_sort[0]));
if (_sign_sort == NULL)
error("Could not allocate memory for the sign-sorting-list");
FOR_ALL_SIGNS(ss) {
if(ss->str != STR_NULL) {
_sign_sort[n++] = ss->index;
_num_sign_sort++;
}
}
qsort(_sign_sort, n, sizeof(_sign_sort[0]), SignNameSorter);
_sign_sort_dirty = false;
DEBUG(misc, 1) ("Resorting global sign list...");
}
static void SignListWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
uint32 i;
int y = 16; // offset from top of widget
if (_sign_sort_dirty)
GlobalSortSignList();
SetVScrollCount(w, _num_sign_sort);
SetDParam(0, w->vscroll.count);
DrawWindowWidgets(w);
/* No signs? */
if (w->vscroll.count == 0) {
DrawString(2, y, STR_304A_NONE, 0);
return;
}
{
SignStruct *ss;
/* Start drawing the signs */
i = 0;
for (i = w->vscroll.pos; i < (uint)w->vscroll.cap + w->vscroll.pos && i < w->vscroll.count; i++) {
ss = GetSign(_sign_sort[i]);
if (ss->owner != OWNER_NONE)
DrawPlayerIcon(ss->owner, 4, y + 1);
DrawString(22, y, ss->str, 8);
y += 10;
}
}
} break;
case WE_CLICK: {
switch (e->click.widget) {
case 3: {
uint32 id_v = (e->click.pt.y - 15) / 10;
SignStruct *ss;
if (id_v >= w->vscroll.cap)
return;
id_v += w->vscroll.pos;
if (id_v >= w->vscroll.count)
return;
ss = GetSign(_sign_sort[id_v]);
ScrollMainWindowToTile(TILE_FROM_XY(ss->x, ss->y));
} break;
}
} break;
case WE_RESIZE:
w->vscroll.cap += e->sizing.diff.y / 10;
break;
}
}
static const Widget _sign_list_widget[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 345, 0, 13, STR_SIGN_LIST_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_LR, 14, 346, 357, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_PANEL, RESIZE_RB, 14, 0, 345, 14, 137, 0x0, STR_NULL},
{ WWT_SCROLLBAR, RESIZE_LRB, 14, 346, 357, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 346, 357, 126, 137, 0x0, STR_RESIZE_BUTTON},
{ WIDGETS_END},
};
static const WindowDesc _sign_list_desc = {
-1, -1, 358, 138,
WC_SIGN_LIST,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_sign_list_widget,
SignListWndProc
};
void ShowSignList(void)
{
Window *w;
w = AllocateWindowDescFront(&_sign_list_desc, 0);
if (w != NULL) {
w->vscroll.cap = 12;
w->resize.step_height = 10;
w->resize.height = w->height - 10 * 7; // minimum if 5 in the list
}
}

32
gui.h
View File

@@ -6,8 +6,6 @@
/* main_gui.c */
void SetupColorsAndInitialWindow(void);
void CcPlaySound10(bool success, uint tile, uint32 p1, uint32 p2);
void CcBuildCanal(bool success, uint tile, uint32 p1, uint32 p2);
void CcTerraform(bool success, uint tile, uint32 p1, uint32 p2);
/* settings_gui.c */
void ShowGameOptions(void);
@@ -59,21 +57,11 @@ void ShowBuildAirToolbar(void);
void ShowPlayerAircraft(int player, int station);
/* terraform_gui.c */
void ShowTerraformToolbar(void);
void PlaceProc_DemolishArea(uint tile);
void PlaceProc_LowerLand(uint tile);
void PlaceProc_RaiseLand(uint tile);
void PlaceProc_LevelLand(uint tile);
bool GUIPlaceProcDragXY(const WindowEvent *we);
enum { // max 32 - 4 = 28 types
GUI_PlaceProc_DemolishArea = 0 << 4,
GUI_PlaceProc_LevelArea = 1 << 4,
GUI_PlaceProc_DesertArea = 2 << 4,
GUI_PlaceProc_WaterArea = 3 << 4,
GUI_PlaceProc_ConvertRailArea = 4 << 4
};
void ShowTerraformToolbar(void);
/* misc_gui.c */
void PlaceLandBlockInfo(void);
@@ -86,7 +74,6 @@ void ShowSubsidiesList(void);
void ShowPlayerStations(int player);
void ShowPlayerFinances(int player);
void ShowPlayerCompany(int player);
void ShowSignList(void);
void ShowEstimatedCostOrIncome(int32 cost, int x, int y);
void ShowErrorMessage(StringID msg_1, StringID msg_2, int x, int y);
@@ -99,22 +86,13 @@ void ShowExtraViewPortWindow(void);
void SetVScrollCount(Window *w, int num);
void SetVScroll2Count(Window *w, int num);
void SetHScrollCount(Window *w, int num);
int HandleEditBoxKey(Window *w, int wid, WindowEvent *we);
void ShowCheatWindow(void);
void AskForNewGameToStart(void);
void DrawEditBox(Window *w, int wid);
void HandleEditBox(Window *w, int wid);
int HandleEditBoxKey(Window *w, int wid, WindowEvent *we);
bool HandleCaret(Textbuf *tb);
bool DeleteTextBufferChar(Textbuf *tb, int delmode);
bool InsertTextBufferChar(Textbuf *tb, byte key);
bool InsertTextBufferClipboard(Textbuf *tb);
bool MoveTextBufferPos(Textbuf *tb, int navmode);
void UpdateTextBufferSize(Textbuf *tb);
/* IS_INT_INSIDE = filter for ascii-function codes like BELL and so on [we need an special filter here later] */
static inline bool IsValidAsciiChar(byte key) {return IS_INT_INSIDE(key, ' ', 256);}
void BuildFileList(void);
void SetFiosType(const byte fiostype);
@@ -138,16 +116,14 @@ enum {
bool DoZoomInOutWindow(int how, Window * w);
void ShowBuildIndustryWindow(void);
void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number);
void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number);
void ShowMusicWindow(void);
/* main_gui.c */
VARDEF byte _newspaper_flag;
VARDEF byte _construct_mode;
VARDEF byte _station_show_coverage;
VARDEF PlaceProc *_place_proc;
VARDEF bool _no_button_sound;
/* vehicle_gui.c */
void InitializeGUI(void);
#endif /* GUI_H */

34
hal.h
View File

@@ -2,12 +2,12 @@
#define HAL_H
typedef struct {
const char *(*start)(const char * const *parm);
char *(*start)(char **parm);
void (*stop)(void);
} HalCommonDriver;
typedef struct {
const char *(*start)(const char * const *parm);
const char *(*start)(char **parm);
void (*stop)(void);
void (*make_dirty)(int left, int top, int width, int height);
int (*main_loop)(void);
@@ -20,12 +20,12 @@ enum {
};
typedef struct {
const char *(*start)(const char * const *parm);
char *(*start)(char **parm);
void (*stop)(void);
} HalSoundDriver;
typedef struct {
const char *(*start)(const char * const *parm);
char *(*start)(char **parm);
void (*stop)(void);
void (*play_song)(const char *filename);
@@ -88,9 +88,9 @@ extern bool _dbg_screen_rect;
void LoadDriver(int driver, const char *name);
const char *GetDriverParam(const char * const *parm, const char *name);
bool GetDriverParamBool(const char * const *parm, const char *name);
int GetDriverParamInt(const char * const *parm, const char *name, int def);
char *GetDriverParam(char **parm, const char *name);
bool GetDriverParamBool(char **parm, const char *name);
int GetDriverParamInt(char **parm, const char *name, int def);
@@ -101,8 +101,20 @@ typedef struct {
uint64 mtime;
char title[64];
char name[256-12-64];
int old_extension;
} FiosItem;
// extensions of old savegames, scenarios
static const char* const _old_extensions[] = {
// old savegame types
"ss1", // Transport Tycoon Deluxe preset game
"sv1", // Transport Tycoon Deluxe (Patch) saved game
"sv2", // Transport Tycoon Deluxe (Patch) saved 2-player game
// old scenario game type
"sv0", // Transport Tycoon Deluxe (Patch) scenario
"ss0", // Transport Tycoon Deluxe preset scenario
};
enum {
FIOS_TYPE_DRIVE = 0,
FIOS_TYPE_PARENT = 1,
@@ -132,15 +144,15 @@ FiosItem *FiosGetScenarioList(int *num, int mode);
void FiosFreeSavegameList(void);
// Browse to. Returns a filename w/path if we reached a file.
char *FiosBrowseTo(const FiosItem *item);
// Return path, free space and stringID
StringID FiosGetDescText(const char **path, uint32 *tot);
// Get descriptive texts.
// Returns a path as well as a
// string describing the path.
StringID FiosGetDescText(const char **path);
// Delete a name
void FiosDelete(const char *name);
// Make a filename from a name
void FiosMakeSavegameName(char *buf, const char *name);
int CDECL compare_FiosItems(const void *a, const void *b);
void CreateConsole(void);
#endif /* HAL_H */

View File

@@ -1,8 +1,6 @@
#ifndef INDUSTRY_H
#define INDUSTRY_H
#include "pool.h"
struct Industry {
TileIndex xy;
byte width; /* swapped order of w/h with town */
@@ -29,40 +27,22 @@ struct Industry {
uint16 index;
};
extern MemoryPool _industry_pool;
/**
* Check if an Industry really exists.
*/
static inline bool IsValidIndustry(Industry* industry)
{
return industry->xy != 0; /* XXX: Replace by INVALID_TILE someday */
}
/**
* Get the pointer to the industry with index 'index'
*/
static inline Industry *GetIndustry(uint index)
{
return (Industry*)GetItemFromPool(&_industry_pool, index);
}
/**
* Get the current size of the IndustryPool
*/
static inline uint16 GetIndustryPoolSize(void)
{
return _industry_pool.total_items;
}
#define FOR_ALL_INDUSTRIES_FROM(i, start) for (i = GetIndustry(start); i != NULL; i = (i->index + 1 < GetIndustryPoolSize()) ? GetIndustry(i->index + 1) : NULL)
#define FOR_ALL_INDUSTRIES(i) FOR_ALL_INDUSTRIES_FROM(i, 0)
VARDEF int _total_industries; // For the AI: the amount of industries active
VARDEF uint16 *_industry_sort;
VARDEF bool _industry_sort_dirty;
VARDEF Industry _industries[90];
VARDEF uint _industries_size;
VARDEF uint16 *_industry_sort;
static inline Industry *GetIndustry(uint index)
{
assert(index < _industries_size);
return &_industries[index];
}
#define FOR_ALL_INDUSTRIES(i) for(i = _industries; i != &_industries[_industries_size]; i++)
VARDEF bool _industry_sort_dirty;
void DeleteIndustry(Industry *is);
enum {

View File

@@ -2,7 +2,6 @@
#include "ttd.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "viewport.h"
#include "command.h"
#include "industry.h"
@@ -13,26 +12,6 @@
#include "economy.h"
#include "sound.h"
enum {
/* Max industries: 64000 (8 * 8000) */
INDUSTRY_POOL_BLOCK_SIZE_BITS = 3, /* In bits, so (1 << 3) == 8 */
INDUSTRY_POOL_MAX_BLOCKS = 8000,
};
/**
* Called if a new block is added to the industry-pool
*/
void IndustryPoolNewBlock(uint start_item)
{
Industry *i;
FOR_ALL_INDUSTRIES_FROM(i, start_item)
i->index = start_item++;
}
/* Initialize the industry-pool */
MemoryPool _industry_pool = { "Industry", INDUSTRY_POOL_MAX_BLOCKS, INDUSTRY_POOL_BLOCK_SIZE_BITS, sizeof(Industry), &IndustryPoolNewBlock, 0, 0, NULL };
byte _industry_sound_ctr;
TileIndex _industry_sound_tile;
@@ -64,13 +43,18 @@ typedef struct DrawIndustrySpec4Struct {
byte image_3;
} DrawIndustrySpec4Struct;
#include "table/industry_land.h"
typedef struct IndustryTileTable {
TileIndexDiffC ti;
byte map5;
} IndustryTileTable;
typedef struct IndustrySpec {
const IndustryTileTable *const *table;
const IndustryTileTable * const * table;
byte num_table;
byte a,b,c;
byte produced_cargo[2];
@@ -79,54 +63,10 @@ typedef struct IndustrySpec {
byte check_proc;
} IndustrySpec;
#include "table/industry_land.h"
#include "table/build_industry.h"
typedef enum IndustryType {
INDUSTRY_NOT_CLOSABLE, //! Industry can never close
INDUSTRY_PRODUCTION, //! Industry can close and change of production
INDUSTRY_CLOSABLE, //! Industry can only close (no production change)
} IndustryType;
static const IndustryType _industry_close_mode[37] = {
/* COAL_MINE */ INDUSTRY_PRODUCTION,
/* POWER_STATION */ INDUSTRY_NOT_CLOSABLE,
/* SAWMILL */ INDUSTRY_CLOSABLE,
/* FOREST */ INDUSTRY_PRODUCTION,
/* OIL_REFINERY */ INDUSTRY_CLOSABLE,
/* OIL_RIG */ INDUSTRY_PRODUCTION,
/* FACTORY */ INDUSTRY_CLOSABLE,
/* PRINTING_WORKS */ INDUSTRY_CLOSABLE,
/* STEEL_MILL */ INDUSTRY_CLOSABLE,
/* FARM */ INDUSTRY_PRODUCTION,
/* COPPER_MINE */ INDUSTRY_PRODUCTION,
/* OIL_WELL */ INDUSTRY_PRODUCTION,
/* BANK */ INDUSTRY_NOT_CLOSABLE,
/* FOOD_PROCESS */ INDUSTRY_CLOSABLE,
/* PAPER_MILL */ INDUSTRY_CLOSABLE,
/* GOLD_MINE */ INDUSTRY_PRODUCTION,
/* BANK_2, */ INDUSTRY_NOT_CLOSABLE,
/* DIAMOND_MINE */ INDUSTRY_PRODUCTION,
/* IRON_MINE */ INDUSTRY_PRODUCTION,
/* FRUIT_PLANTATION */ INDUSTRY_PRODUCTION,
/* RUBBER_PLANTATION */ INDUSTRY_PRODUCTION,
/* WATER_SUPPLY */ INDUSTRY_PRODUCTION,
/* WATER_TOWER */ INDUSTRY_NOT_CLOSABLE,
/* FACTORY_2 */ INDUSTRY_CLOSABLE,
/* FARM_2 */ INDUSTRY_PRODUCTION,
/* LUMBER_MILL */ INDUSTRY_CLOSABLE,
/* COTTON_CANDY */ INDUSTRY_PRODUCTION,
/* CANDY_FACTORY */ INDUSTRY_CLOSABLE,
/* BATTERY_FARM */ INDUSTRY_PRODUCTION,
/* COLA_WELLS */ INDUSTRY_PRODUCTION,
/* TOY_SHOP */ INDUSTRY_NOT_CLOSABLE,
/* TOY_FACTORY */ INDUSTRY_CLOSABLE,
/* PLASTIC_FOUNTAINS */ INDUSTRY_PRODUCTION,
/* FIZZY_DRINK_FACTORY */INDUSTRY_CLOSABLE,
/* BUBBLE_GENERATOR */ INDUSTRY_PRODUCTION,
/* TOFFEE_QUARRY */ INDUSTRY_PRODUCTION,
/* SUGAR_MINE */ INDUSTRY_PRODUCTION
static const byte _industry_close_mode[37] = {
1,0,2,1,2,1,2,2,2,1,1,1,0,2,2,1,0,1,1,1,1,1,0,2,1,2,1,2,1,1,0,2,1,2,1,1,1,
};
static const StringID _industry_prod_up_strings[] = {
@@ -450,6 +390,30 @@ static int32 ClearTile_Industry(uint tile, byte flags)
return 0;
}
/* p1 index of industry to destroy */
/* Destroy Industry button costing money removed per request of dominik
int32 CmdDestroyIndustry(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
uint tile = TILE_FROM_XY(x,y);
Industry *i = GetIndustry((uint16)p1);
Town *t = ClosestTownFromTile(tile, (uint)-1); // find closest town to penaltize (ALWAYS penaltize)
SET_EXPENSES_TYPE(EXPENSES_OTHER);
// check if you're allowed to remove the industry. Minimum amount
// of ratings to remove the industry depends on difficulty setting
if (!CheckforTownRating(tile, flags, t, INDUSTRY_REMOVE))
return CMD_ERROR;
if (flags & DC_EXEC) {
DeleteIndustry(i);
CreateEffectVehicleAbove(x + 8,y + 8, 2, EV_DEMOLISH);
ChangeTownRating(t, RATING_INDUSTRY_DOWN_STEP, RATING_INDUSTRY_MINIMUM);
}
return (_price.build_industry >> 5) * _industry_type_costs[i->type]*2;
}
*/
static const byte _industry_min_cargo[] = {
5, 5, 5, 30, 5, 5, 5, 5,
@@ -665,7 +629,7 @@ static void MakeIndustryTileBiggerCase8(uint tile)
{
TileInfo ti;
FindLandscapeHeight(&ti, TileX(tile) * 16, TileY(tile) * 16);
CreateEffectVehicle(ti.x + 15, ti.y + 14, ti.z + 59 + (ti.tileh != 0 ? 8 : 0), EV_CHIMNEY_SMOKE);
CreateEffectVehicle(ti.x + 15, ti.y + 14, ti.z + 59 + (ti.tileh != 0 ? 8 : 0), EV_INDUSTRYSMOKE);
}
static void MakeIndustryTileBigger(uint tile, byte size)
@@ -731,7 +695,7 @@ static void TileLoopIndustryCase161(uint tile)
TileX(tile) * 16 + _tileloop_ind_case_161[dir + 0],
TileY(tile) * 16 + _tileloop_ind_case_161[dir + 4],
_tileloop_ind_case_161[dir + 8],
EV_BUBBLE
EV_INDUSTRY_SMOKE
);
if (v != NULL)
@@ -815,7 +779,7 @@ static void TileLoop_Industry(uint tile)
break;
case 49: {
CreateEffectVehicleAbove(TileX(tile) * 16 + 6, TileY(tile) * 16 + 6, 43, EV_SMOKE);
CreateEffectVehicleAbove(TileX(tile) * 16 + 6, TileY(tile) * 16 + 6, 43, EV_SMOKE_3);
} break;
@@ -892,7 +856,7 @@ static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5,
static bool IsBadFarmFieldTile(TileIndex tile)
{
switch (GetTileType(tile)) {
switch (TileType(tile)) {
case MP_CLEAR: {
byte m5 = _map5[tile] & 0x1C;
return m5 == 0xC || m5 == 0x10;
@@ -908,7 +872,7 @@ static bool IsBadFarmFieldTile(TileIndex tile)
static bool IsBadFarmFieldTile2(TileIndex tile)
{
switch (GetTileType(tile)) {
switch (TileType(tile)) {
case MP_CLEAR: {
byte m5 = _map5[tile] & 0x1C;
return m5 == 0x10;
@@ -955,7 +919,7 @@ static void PlantFarmField(uint tile)
int type, type2;
if (_opt.landscape == LT_HILLY) {
if (GetTileZ(tile) + 16 >= _opt.snow_line)
if (GetTileZ(tile) >= (_opt.snow_line - 16))
return;
}
@@ -1013,7 +977,7 @@ static void MaybePlantFarmField(Industry *i)
int x = (i->width>>1) + Random() % 31 - 16;
int y = (i->height>>1) + Random() % 31 - 16;
tile = TileAddWrap(i->xy, x, y);
if (tile != INVALID_TILE)
if (tile != TILE_WRAPPED)
PlantFarmField(tile);
}
}
@@ -1165,7 +1129,7 @@ static bool CheckNewIndustry_NULL(uint tile, int type)
static bool CheckNewIndustry_Forest(uint tile, int type)
{
if (_opt.landscape == LT_HILLY) {
if (GetTileZ(tile) < _opt.snow_line + 16U) {
if (GetTileZ(tile) < (_opt.snow_line + 16) ) {
_error_message = STR_4831_FOREST_CAN_ONLY_BE_PLANTED;
return false;
}
@@ -1175,16 +1139,20 @@ static bool CheckNewIndustry_Forest(uint tile, int type)
extern bool _ignore_restrictions;
/* Oil Rig and Oil Refinery */
static bool CheckNewIndustry_Oil(uint tile, int type)
static bool CheckNewIndustry_Oilwell(uint tile, int type)
{
int x,y;
if(_ignore_restrictions && _game_mode == GM_EDITOR)
return true;
if (type != IT_OIL_RIG && _game_mode == GM_EDITOR)
return true;
if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < 16)
x = TileX(tile);
y = TileY(tile);
if ( x < 15 || y < 15 || x > 238 || y > 238)
return true;
_error_message = STR_483B_CAN_ONLY_BE_POSITIONED;
@@ -1194,7 +1162,7 @@ static bool CheckNewIndustry_Oil(uint tile, int type)
static bool CheckNewIndustry_Farm(uint tile, int type)
{
if (_opt.landscape == LT_HILLY) {
if (GetTileZ(tile) + 16 >= _opt.snow_line) {
if (GetTileZ(tile) >= (_opt.snow_line - 16)) {
_error_message = STR_0239_SITE_UNSUITABLE;
return false;
}
@@ -1243,7 +1211,7 @@ typedef bool CheckNewIndustryProc(uint tile, int type);
static CheckNewIndustryProc * const _check_new_industry_procs[] = {
CheckNewIndustry_NULL,
CheckNewIndustry_Forest,
CheckNewIndustry_Oil,
CheckNewIndustry_Oilwell,
CheckNewIndustry_Farm,
CheckNewIndustry_Plantation,
CheckNewIndustry_Water,
@@ -1377,7 +1345,7 @@ static bool CheckIfIndustryTilesAreFree(uint tile, const IndustryTileTable *it,
return false;
}
} else if (type == IT_TOY_SHOP) {
if (DistanceMax(t->xy, cur_tile) > 9)
if (GetTileDist1D(t->xy, cur_tile) > 9)
return false;
if (ti.type != MP_HOUSE) goto do_clear;
} else if (type == IT_WATER_TOWER) {
@@ -1410,7 +1378,7 @@ static bool CheckIfTooCloseToIndustry(uint tile, int type)
FOR_ALL_INDUSTRIES(i) {
// check if an industry that accepts the same goods is nearby
if (i->xy != 0 &&
(DistanceMax(tile, i->xy) <= 14) &&
(GetTileDist1D(tile, i->xy) <= 14) &&
spec->accepts_cargo[0] != 0xFF &&
spec->accepts_cargo[0] == i->accepts_cargo[0] &&
!(_game_mode == GM_EDITOR &&
@@ -1423,7 +1391,7 @@ static bool CheckIfTooCloseToIndustry(uint tile, int type)
// check "not close to" field.
if (i->xy != 0 &&
(i->type == spec->a || i->type == spec->b || i->type == spec->c) &&
DistanceMax(tile, i->xy) <= 14) {
GetTileDist1D(tile, i->xy) <= 14) {
_error_message = STR_INDUSTRY_TOO_CLOSE;
return false;
}
@@ -1437,22 +1405,12 @@ static Industry *AllocateIndustry(void)
FOR_ALL_INDUSTRIES(i) {
if (i->xy == 0) {
uint index = i->index;
if (i->index > _total_industries)
_total_industries = i->index;
memset(i, 0, sizeof(Industry));
i->index = index;
return i;
}
}
/* Check if we can add a block to the pool */
if (AddBlockToPool(&_industry_pool))
return AllocateIndustry();
return NULL;
}
@@ -1537,7 +1495,7 @@ static void DoCreateNewIndustry(Industry *i, uint tile, int type, const Industry
int x = Random() % 31 - 16;
int y = Random() % 31 - 16;
uint new_tile = TileAddWrap(tile, x, y);
if (new_tile != INVALID_TILE)
if (new_tile != TILE_WRAPPED)
PlantFarmField(new_tile);
}
}
@@ -1545,60 +1503,47 @@ static void DoCreateNewIndustry(Industry *i, uint tile, int type, const Industry
InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
}
/** Build/Fund an industry
* @param x,y coordinates where industry is built
* @param p1 industry type @see build_industry.h and @see industry.h
* @param p2 unused
*/
/* p1 = industry type 0-36 */
int32 CmdBuildIndustry(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
uint tile = TILE_FROM_XY(x,y);
Town *t;
Industry *i;
TileIndex tile = TILE_FROM_XY(x,y);
int num;
const IndustryTileTable * const *itt;
const IndustryTileTable *it;
Industry *i;
const IndustrySpec *spec;
SET_EXPENSES_TYPE(EXPENSES_OTHER);
if (!CheckSuitableIndustryPos(tile)) return CMD_ERROR;
/* Check if the to-be built/founded industry is available for this climate.
* Unfortunately we have no easy way of checking, except for looping the table */
{ const byte *i;
bool found = false;
for (i = &_build_industry_types[_opt_ptr->landscape][0]; i != endof(_build_industry_types[_opt_ptr->landscape]); i++) {
if (*i == p1) {found = true; break;}
}
if (!found) return CMD_ERROR;
}
if (!CheckSuitableIndustryPos(tile))
return CMD_ERROR;
spec = &_industry_spec[p1];
/* If the patch for non-raw-material industries is not on, you cannot build raw-material industries.
* Raw material industries are industries that do not accept cargo (at least for now)
* Exclude industry 25, which is the lumber mill (only "raw" industry that can be built)*/
if (!_patches.build_rawmaterial_ind && spec->accepts_cargo[0] == 255 &&
spec->accepts_cargo[1] == 255 && spec->accepts_cargo[2] == 255 && p1 != 25) return CMD_ERROR;
if (!_check_new_industry_procs[spec->check_proc](tile, p1)) return CMD_ERROR;
if (!_check_new_industry_procs[spec->check_proc](tile, p1))
return CMD_ERROR;
if ((t = CheckMultipleIndustryInTown(tile, p1)) == NULL) return CMD_ERROR;
if ((t=CheckMultipleIndustryInTown(tile, p1)) == NULL)
return CMD_ERROR;
num = spec->num_table;
itt = spec->table;
do {
if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE);
} while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1, t));
if (--num < 0)
return_cmd_error(STR_0239_SITE_UNSUITABLE);
} while (!CheckIfIndustryTilesAreFree(tile, it=itt[num], p1, t));
if (!CheckIfTooCloseToIndustry(tile, p1)) return CMD_ERROR;
if (!CheckIfTooCloseToIndustry(tile, p1))
return CMD_ERROR;
if ( (i = AllocateIndustry()) == NULL) return CMD_ERROR;
if ( (i = AllocateIndustry()) == NULL)
return CMD_ERROR;
if (flags & DC_EXEC)
DoCreateNewIndustry(i, tile, p1, it, t, OWNER_NONE);
DoCreateNewIndustry(i, tile, p1, it, t, 0x10);
return (_price.build_industry >> 5) * _industry_type_costs[p1];
}
@@ -1649,8 +1594,7 @@ static const byte _numof_industry_table[4][12] = {
static void PlaceInitialIndustry(byte type, int amount)
{
int num =
ScaleByMapSize(_numof_industry_table[_opt.diff.number_industries][amount]);
int num = _numof_industry_table[_opt.diff.number_industries][amount];
if (_opt.diff.number_industries != 0)
{
@@ -1682,64 +1626,57 @@ void GenerateIndustries(void)
static void ExtChangeIndustryProduction(Industry *i)
{
bool closeit = true;
bool closeit;
int j;
switch (_industry_close_mode[i->type]) {
case INDUSTRY_NOT_CLOSABLE:
return;
if (_industry_close_mode[i->type] == 0) return;
case INDUSTRY_CLOSABLE:
if ((byte)(_cur_year - i->last_prod_year) < 5 || !CHANCE16(1, 180))
closeit = true;
if (_industry_close_mode[i->type] == 2) {
if ( (byte)(_cur_year - i->last_prod_year) < 5 || !CHANCE16(1,180))
closeit = false;
} else {
for (j=0; j != 2 && i->produced_cargo[j]!=255; j++){
uint32 r;
int change,percent,old;
int mag;
change = old = i->production_rate[j];
if (CHANCE16R(20,1024,r))change -= ((RandomRange(50) + 10)*old) >> 8;
if (CHANCE16I(20+(i->pct_transported[j]*20>>8),1024,r>>16)) change += ((RandomRange(50) + 10)*old) >> 8;
// make sure it doesn't exceed 255 or goes below 0
change = clamp(change, 0, 255);
if (change == old) {
closeit = false;
break;
default: /* INDUSTRY_PRODUCTION */
for (j = 0; j < 2 && i->produced_cargo[j] != 255; j++){
uint32 r = Random();
int old, new, percent;
int mag;
new = old = i->production_rate[j];
if (CHANCE16I(20, 1024, r))
new -= ((RandomRange(50) + 10) * old) >> 8;
if (CHANCE16I(20 + (i->pct_transported[j] * 20 >> 8), 1024, r >> 16))
new += ((RandomRange(50) + 10) * old) >> 8;
// make sure it doesn't exceed 255 or goes below 0
new = clamp(new, 0, 255);
if (new == old) {
closeit = false;
continue;
}
percent = new * 100 / old - 100;
i->production_rate[j] = new;
if (new >= _industry_spec[i->type].production_rate[j] / 4)
closeit = false;
mag = abs(percent);
if (mag >= 10) {
SetDParam(3, mag);
SetDParam(0, _cargoc.names_s[i->produced_cargo[j]]);
SetDParam(1, i->town->index);
SetDParam(2, i->type + STR_4802_COAL_MINE);
AddNewsItem(percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN,
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0),
i->xy + TILE_XY(1,1), 0);
}
continue;
}
break;
percent = change*100/old - 100;
i->production_rate[j] = change;
if (change >= _industry_spec[i->type].production_rate[j]/4)
closeit = false;
mag = abs(percent);
if (mag >= 10) {
SetDParam(3, mag);
SetDParam(0,_cargoc.names_s[i->produced_cargo[j]]);
SetDParam(1, i->town->index);
SetDParam(2, i->type + STR_4802_COAL_MINE);
AddNewsItem(percent>=0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN,
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0),
i->xy + TILE_XY(1,1), 0);
}
}
}
if (closeit) {
i->prod_level = 0;
SetDParam(1, i->type + STR_4802_COAL_MINE);
SetDParam(0, i->town->index);
AddNewsItem(_industry_close_strings[i->type],
NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0),
i->xy + TILE_XY(1,1), 0);
AddNewsItem(_industry_close_strings[i->type], NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0), i->xy + TILE_XY(1,1), 0);
}
}
@@ -1822,71 +1759,58 @@ static void MaybeNewIndustry(uint32 r)
AddNewsItem( STR_482D_NEW_UNDER_CONSTRUCTION + (type == IT_FOREST), NEWS_FLAGS(NM_THIN,NF_VIEWPORT|NF_TILE,NT_ECONOMY,0), i->xy, 0);
}
static void ChangeIndustryProduction(Industry *i)
static void MaybeCloseIndustry(Industry *i)
{
bool only_decrease = false;
StringID str = STR_NULL;
uint32 r;
StringID str;
int type = i->type;
switch (_industry_close_mode[type]) {
case INDUSTRY_NOT_CLOSABLE:
return;
if (_industry_close_mode[type] == 1) {
/* decrease or increase */
if (type == IT_OIL_WELL && _opt.landscape == LT_NORMAL) goto decrease_production;
if (CHANCE16I(1,3,r=Random())) {
if ((i->pct_transported[0] > 153) ^ CHANCE16I(1,3,r>>16)) {
case INDUSTRY_PRODUCTION:
/* decrease or increase */
if (type == IT_OIL_WELL && _opt.landscape == LT_NORMAL)
only_decrease = true;
/* Increase production */
if (i->prod_level != 0x80) {
byte b;
if (only_decrease || CHANCE16(1,3)) {
/* If you transport > 60%, 66% chance we increase, else 33% chance we increase */
if (!only_decrease && (i->pct_transported[0] > 153) != CHANCE16(1,3)) {
/* Increase production */
if (i->prod_level != 0x80) {
byte b;
i->prod_level <<= 1;
i->prod_level <<= 1;
b = i->production_rate[0]*2;
if (i->production_rate[0] >= 128) b=255;
i->production_rate[0] = b;
b = i->production_rate[1]*2;
if (i->production_rate[1] >= 128) b=255;
i->production_rate[1] = b;
b = i->production_rate[0] * 2;
if (i->production_rate[0] >= 128)
b = 0xFF;
i->production_rate[0] = b;
b = i->production_rate[1] * 2;
if (i->production_rate[1] >= 128)
b = 0xFF;
i->production_rate[1] = b;
str = _industry_prod_up_strings[type];
}
} else {
/* Decrease production */
if (i->prod_level == 4) {
i->prod_level = 0;
str = _industry_close_strings[type];
} else {
i->prod_level >>= 1;
i->production_rate[0] = (i->production_rate[0] + 1) >> 1;
i->production_rate[1] = (i->production_rate[1] + 1) >> 1;
str = _industry_prod_down_strings[type];
}
str = _industry_prod_up_strings[type];
goto add_news;
}
}
break;
} else {
decrease_production:
case INDUSTRY_CLOSABLE:
/* maybe close */
if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1,2)) {
i->prod_level = 0;
str = _industry_close_strings[type];
}
break;
}
/* Decrease production */
if (i->prod_level == 4) goto close_industry;
i->prod_level>>=1;
i->production_rate[0] = (i->production_rate[0]+1) >> 1;
i->production_rate[1] = (i->production_rate[1]+1) >> 1;
if (str != STR_NULL) {
SetDParam(1, type + STR_4802_COAL_MINE);
SetDParam(0, i->town->index);
AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0), i->xy + TILE_XY(1,1), 0);
str = _industry_prod_down_strings[type];
goto add_news;
}
}
} else if (_industry_close_mode[type] > 1) {
/* maybe close */
if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1,2)) {
close_industry:
i->prod_level = 0;
str = _industry_close_strings[type];
add_news:
SetDParam(1, type + STR_4802_COAL_MINE);
SetDParam(0, i->town->index);
AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0), i->xy + TILE_XY(1,1), 0);
}
}
}
@@ -1901,13 +1825,14 @@ void IndustryMonthlyLoop(void)
UpdateIndustryStatistics(i);
}
/* 3% chance that we start a new industry */
if (CHANCE16(3, 100)) {
MaybeNewIndustry(Random());
} else if (!_patches.smooth_economy && _total_industries > 0) {
i = GetIndustry(RandomRange(_total_industries));
if (i->xy != 0)
ChangeIndustryProduction(i);
i = GetIndustry(RandomRange(_industries_size));
if (i->xy == 0) {
uint32 r;
if (CHANCE16I(1,9,r=Random()))
MaybeNewIndustry(r);
} else if (!_patches.smooth_economy) {
MaybeCloseIndustry(i);
}
_current_player = old_player;
@@ -1920,9 +1845,14 @@ void IndustryMonthlyLoop(void)
void InitializeIndustries(void)
{
Industry *i;
int j;
CleanPool(&_industry_pool);
AddBlockToPool(&_industry_pool);
memset(_industries, 0, sizeof(_industries[0]) * _industries_size);
j = 0;
FOR_ALL_INDUSTRIES(i)
i->index = j++;
_total_industries = 0;
_industry_sort_dirty = true;
@@ -1946,8 +1876,7 @@ const TileTypeProcs _tile_type_industry_procs = {
};
static const byte _industry_desc[] = {
SLE_CONDVAR(Industry, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Industry, xy, SLE_UINT32, 6, 255),
SLE_VAR(Industry,xy, SLE_UINT16),
SLE_VAR(Industry,width, SLE_UINT8),
SLE_VAR(Industry,height, SLE_UINT8),
SLE_REF(Industry,town, REF_TOWN),
@@ -1992,20 +1921,12 @@ static void Save_INDY(void)
static void Load_INDY(void)
{
int index;
_total_industries = 0;
while ((index = SlIterateArray()) != -1) {
Industry *i;
Industry *i = GetIndustry(index);
if (!AddBlockIfNeeded(&_industry_pool, index))
error("Industries: failed loading savegame: too many industries");
i = GetIndustry(index);
SlObject(i, _industry_desc);
if (index > _total_industries)
_total_industries = index;
if (index > _total_industries) _total_industries = index;
}
}

View File

@@ -1,10 +1,8 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "strings.h"
#include "table/strings.h"
#include "map.h"
#include "gui.h"
//#include "gui.h"
#include "window.h"
#include "gfx.h"
#include "command.h"
@@ -12,12 +10,18 @@
#include "industry.h"
#include "town.h"
/* Present in table/build_industry.h" */
extern const byte _build_industry_types[4][12];
static const byte _build_industry_types[4][12] = {
{ 1, 2, 4, 6, 8, 0, 3, 5, 9, 11, 18 },
{ 1, 14, 4, 13, 7, 0, 3, 9, 11, 15 },
{ 25, 13, 4, 23, 22, 11, 17, 10, 24, 19, 20, 21 },
{ 27, 30, 31, 33, 26, 28, 29, 32, 34, 35, 36 },
};
extern const byte _industry_type_costs[37];
static void UpdateIndustryProduction(Industry *i);
extern void DrawArrowButtons(int x, int y, int state);
extern void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number);
static void BuildIndustryWndProc(Window *w, WindowEvent *e)
{
@@ -25,7 +29,7 @@ static void BuildIndustryWndProc(Window *w, WindowEvent *e)
case WE_PAINT:
DrawWindowWidgets(w);
if (_thd.place_mode == 1 && _thd.window_class == WC_BUILD_INDUSTRY) {
int ind_type = _build_industry_types[_opt_ptr->landscape][WP(w,def_d).data_1];
int ind_type = _build_industry_types[_opt.landscape][WP(w,def_d).data_1];
SetDParam(0, (_price.build_industry >> 5) * _industry_type_costs[ind_type]);
DrawStringCentered(85, w->height - 21, STR_482F_COST, 0);
@@ -41,7 +45,7 @@ static void BuildIndustryWndProc(Window *w, WindowEvent *e)
} break;
case WE_PLACE_OBJ:
if (DoCommandP(e->place.tile, _build_industry_types[_opt_ptr->landscape][WP(w,def_d).data_1], 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)))
if (DoCommandP(e->place.tile, _build_industry_types[_opt.landscape][WP(w,def_d).data_1], 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)))
ResetObjectToPlace();
break;
@@ -262,10 +266,10 @@ static const WindowDesc * const _industry_window_desc[2][4] = {
void ShowBuildIndustryWindow(void)
{
AllocateWindowDescFront(_industry_window_desc[_patches.build_rawmaterial_ind][_opt_ptr->landscape],0);
AllocateWindowDescFront(_industry_window_desc[_patches.build_rawmaterial_ind][_opt.landscape],0);
}
#define NEED_ALTERB ((_game_mode == GM_EDITOR || _cheats.setup_prod.value) && (i->accepts_cargo[0] == CT_INVALID || i->accepts_cargo[0] == CT_VALUABLES))
#define NEED_ALTERB (_game_mode == GM_EDITOR && i->accepts_cargo[0] == CT_INVALID)
static void IndustryViewWndProc(Window *w, WindowEvent *e)
{
// WP(w,vp2_d).data_1 is for the editbox line
@@ -335,8 +339,12 @@ static void IndustryViewWndProc(Window *w, WindowEvent *e)
i = GetIndustry(w->window_number);
// We should work if needed..
if (!NEED_ALTERB)
// We should only work in editor
if (_game_mode != GM_EDITOR)
return;
// And if the industry is raw-material producer
if (i->accepts_cargo[0] != CT_INVALID)
return;
x = e->click.pt.x;
@@ -377,6 +385,17 @@ static void IndustryViewWndProc(Window *w, WindowEvent *e)
i = GetIndustry(w->window_number);
ScrollMainWindowToTile(i->xy + TILE_XY(1,1));
break;
case 7:
// Destroy Industry button costing money removed per request of dominik
//i = GetIndustry(w->window_number);
/* passing only i->xy is not safe if industry has a weird shape like:
_ X X
X X X
_ <--- grass, no industry, but i->xy points there (first top-left tile)!,
so passing i->xy to destroy industry will fail in called procedure
*/
//DoCommandP(i->xy, w->window_number, 0, CcPlaySound10, CMD_DESTROY_INDUSTRY | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
break;
}
}
break;
@@ -478,7 +497,7 @@ static byte _industry_sort_order;
static int CDECL GeneralIndustrySorter(const void *a, const void *b)
{
char buf1[96];
uint16 val;
byte val;
Industry *i = GetIndustry(*(const uint16*)a);
Industry *j = GetIndustry(*(const uint16*)b);
int r = 0;
@@ -542,7 +561,7 @@ static void MakeSortedIndustryList(void)
int n = 0;
/* Create array for sorting */
_industry_sort = realloc(_industry_sort, GetIndustryPoolSize() * sizeof(_industry_sort[0]));
_industry_sort = realloc(_industry_sort, _industries_size * sizeof(_industry_sort[0]));
if (_industry_sort == NULL)
error("Could not allocate memory for the industry-sorting-list");
@@ -573,7 +592,7 @@ static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
MakeSortedIndustryList();
}
SetVScrollCount(w, _num_industry_sort);
w->vscroll.count = _num_industry_sort;
DrawWindowWidgets(w);
DoDrawString(_industry_sort_order & 1 ? "\xAA" : "\xA0", _indicator_positions[_industry_sort_order>>1], 15, 0x10);

View File

@@ -12,106 +12,76 @@
extern void SwitchMode(int new_mode);
#if 0
static void ShowSelectTutorialWindow() {}
#endif
/*
static void ShowSelectTutorialWindow()
{
}
*/
static const Widget _select_game_widgets[] = {
{ WWT_CAPTION, RESIZE_NONE, 13, 0, 335, 0, 13, STR_0307_OPENTTD, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 13, 0, 335, 14, 196, STR_NULL, STR_NULL},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 22, 33, STR_0140_NEW_GAME, STR_02FB_START_A_NEW_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 22, 33, STR_0141_LOAD_GAME, STR_02FC_LOAD_A_SAVED_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 40, 51, STR_0220_CREATE_SCENARIO,STR_02FE_CREATE_A_CUSTOMIZED_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 40, 51, STR_029A_PLAY_SCENARIO, STR_0303_START_A_NEW_GAME_USING},
{ WWT_PANEL_2, RESIZE_NONE, 12, 10, 86, 59, 113, 0x1312, STR_030E_SELECT_TEMPERATE_LANDSCAPE},
{ WWT_PANEL_2, RESIZE_NONE, 12, 90, 166, 59, 113, 0x1314, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
{ WWT_PANEL_2, RESIZE_NONE, 12, 170, 246, 59, 113, 0x1316, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
{ WWT_PANEL_2, RESIZE_NONE, 12, 250, 326, 59, 113, 0x1318, STR_0311_SELECT_TOYLAND_LANDSCAPE},
{ WWT_PANEL, RESIZE_NONE, 12, 219, 254, 120, 131, STR_NULL, STR_NULL},
{ WWT_CLOSEBOX, RESIZE_NONE, 12, 255, 266, 120, 131, STR_0225, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 12, 279, 314, 120, 131, STR_NULL, STR_NULL},
{ WWT_CLOSEBOX, RESIZE_NONE, 12, 315, 326, 120, 131, STR_0225, STR_NULL},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 138, 149, STR_SINGLE_PLAYER, STR_02FF_SELECT_SINGLE_PLAYER_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 138, 149, STR_MULTIPLAYER, STR_0300_SELECT_MULTIPLAYER_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 159, 170, STR_0148_GAME_OPTIONS, STR_0301_DISPLAY_GAME_OPTIONS},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 159, 170, STR_01FE_DIFFICULTY, STR_0302_DISPLAY_DIFFICULTY_OPTIONS},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 177, 188, STR_CONFIG_PATCHES, STR_CONFIG_PATCHES_TIP},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 177, 188, STR_0304_QUIT, STR_0305_QUIT_OPENTTD},
{ WIDGETS_END },
{ WWT_CAPTION, RESIZE_NONE, 13, 0, 335, 0, 13, STR_0307_OPENTTD, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 13, 0, 335, 14, 196, 0x0, STR_NULL},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 22, 33, STR_0140_NEW_GAME, STR_02FB_START_A_NEW_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 22, 33, STR_0141_LOAD_GAME, STR_02FC_LOAD_A_SAVED_GAME},
//{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 177, 188, STR_0142_TUTORIAL_DEMONSTRATION, STR_02FD_VIEW_DEMONSTRATIONS_TUTORIALS},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 177, 188, STR_CONFIG_PATCHES, STR_CONFIG_PATCHES_TIP},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 40, 51, STR_0220_CREATE_SCENARIO,STR_02FE_CREATE_A_CUSTOMIZED_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 136, 147, STR_SINGLE_PLAYER, STR_02FF_SELECT_SINGLE_PLAYER_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 136, 147, STR_MULTIPLAYER, STR_0300_SELECT_MULTIPLAYER_GAME},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 10, 167, 159, 170, STR_0148_GAME_OPTIONS, STR_0301_DISPLAY_GAME_OPTIONS},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 159, 170, STR_01FE_DIFFICULTY, STR_0302_DISPLAY_DIFFICULTY_OPTIONS},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 40, 51, STR_029A_PLAY_SCENARIO, STR_0303_START_A_NEW_GAME_USING},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 12, 168, 325, 177, 188, STR_0304_QUIT, STR_0305_QUIT_OPENTTD},
{ WWT_PANEL_2, RESIZE_NONE, 12, 10, 85, 69, 122, 0x1312, STR_030E_SELECT_TEMPERATE_LANDSCAPE},
{ WWT_PANEL_2, RESIZE_NONE, 12, 90, 165, 69, 122, 0x1314, STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
{ WWT_PANEL_2, RESIZE_NONE, 12, 170, 245, 69, 122, 0x1316, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
{ WWT_PANEL_2, RESIZE_NONE, 12, 250, 325, 69, 122, 0x1318, STR_0311_SELECT_TOYLAND_LANDSCAPE},
{ WIDGETS_END},
};
extern void HandleOnEditText(WindowEvent *e);
extern void HandleOnEditTextCancel(void);
static inline void CreateScenario(void) {_switch_mode = SM_EDITOR;}
static inline void SetNewLandscapeType(byte landscape)
{
_opt_newgame.landscape = landscape;
InvalidateWindowClasses(WC_SELECT_GAME);
}
static void SelectGameWndProc(Window *w, WindowEvent *e)
{
/* We do +/- 6 for the map_xy because 64 is 2^6, but it is the lowest available element */
static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
switch (e->event) {
static void SelectGameWndProc(Window *w, WindowEvent *e) {
switch(e->event) {
case WE_PAINT:
w->click_state = (w->click_state & ~(1 << 14) & ~(0xF << 6)) | (1 << (_opt_newgame.landscape + 6)) | (1 << 14);
SetDParam(0, STR_6801_EASY + _opt_newgame.diff_level);
w->click_state = (w->click_state & ~(0xC0) & ~(0xF << 12)) | (1 << (_new_opt.landscape+12)) | (1<<6);
SetDParam(0, STR_6801_EASY + _new_opt.diff_level);
DrawWindowWidgets(w);
DrawStringRightAligned(216, 121, STR_MAPSIZE, 0);
DrawString(223, 121, mapsizes[_patches.map_x - 6], 0x10);
DrawString(270, 121, STR_BY, 0);
DrawString(283, 121, mapsizes[_patches.map_y - 6], 0x10);
break;
case WE_CLICK:
switch (e->click.widget) {
case 2: AskForNewGameToStart(); break;
switch(e->click.widget) {
case 2: DoCommandP(0, 0, 0, NULL, CMD_START_NEW_GAME); break;
case 3: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
case 4: CreateScenario(); break;
case 5: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
case 6: case 7: case 8: case 9:
SetNewLandscapeType(e->click.widget - 6);
break;
case 10: case 11: /* Mapsize X */
ShowDropDownMenu(w, mapsizes, _patches.map_x - 6, 11, 0, 0);
break;
case 12: case 13: /* Mapsize Y */
ShowDropDownMenu(w, mapsizes, _patches.map_y - 6, 13, 0, 0);
break;
case 15:
#ifdef ENABLE_NETWORK
case 4: ShowPatchesSelection(); break;
case 5: DoCommandP(0, InteractiveRandom(), 0, NULL, CMD_CREATE_SCENARIO); break;
case 7:
#ifdef ENABLE_NETWORK
if (!_network_available) {
ShowErrorMessage(-1, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
} else
ShowNetworkGameWindow();
#else
#else
ShowErrorMessage(-1 ,STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
#endif
#endif /* ENABLE_NETWORK */
break;
case 16: ShowGameOptions(); break;
case 17: ShowGameDifficulty(); break;
case 18: ShowPatchesSelection(); break;
case 19: AskExitGame(); break;
case 8: ShowGameOptions(); break;
case 9: ShowGameDifficulty(); break;
case 10:ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
case 11:AskExitGame(); break;
case 12: case 13: case 14: case 15:
DoCommandP(0, e->click.widget - 12, 0, NULL, CMD_SET_NEW_LANDSCAPE_TYPE);
break;
}
case WE_KEYPRESS:
switch(e->keypress.keycode) {
case WKC_BACKQUOTE: IConsoleSwitch(); break;
}
break;
case WE_ON_EDIT_TEXT: HandleOnEditText(e); break;
case WE_ON_EDIT_TEXT_CANCEL: HandleOnEditTextCancel(); break;
case WE_DROPDOWN_SELECT: /* Mapsize selection */
switch (e->dropdown.button) {
case 11: _patches.map_x = e->dropdown.index + 6; break;
case 13: _patches.map_y = e->dropdown.index + 6; break;
}
SetWindowDirty(w);
break;
}
}
@@ -129,29 +99,90 @@ void ShowSelectGameWindow(void)
AllocateWindowDesc(&_select_game_desc);
}
void GenRandomNewGame(uint32 rnd1, uint32 rnd2)
// p1 = mode
// 0 - start new game
// 1 - close new game dialog
int32 CmdStartNewGame(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
_random_seeds[0][0] = rnd1;
_random_seeds[0][1] = rnd2;
if (!(flags & DC_EXEC))
return 0;
switch(p1) {
case 0: // show select game window
AskForNewGameToStart();
break;
case 1: // close select game window
DeleteWindowById(WC_SAVELOAD, 0);
break;
}
return 0;
}
int32 CmdGenRandomNewGame(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
if (!(flags & DC_EXEC))
return 0;
// this forces stuff into test mode.
_docommand_recursive = 0;
_random_seeds[0][0] = p1;
_random_seeds[0][1] = p2;
SwitchMode(SM_NEWGAME);
return 0;
}
void StartScenarioEditor(uint32 rnd1, uint32 rnd2)
int32 CmdLoadGame(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
_random_seeds[0][0] = rnd1;
_random_seeds[0][1] = rnd2;
if (!(flags & DC_EXEC))
return 0;
// ShowSaveLoadDialog(0);
return 0;
}
int32 CmdCreateScenario(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
if (!(flags & DC_EXEC))
return 0;
_switch_mode = SM_EDITOR;
return 0;
}
int32 CmdSetSinglePlayer(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
printf("CmdSetSinglePlayer\n");
return 0;
}
int32 CmdStartScenario(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
if (!(flags & DC_EXEC))
return 0;
// this forces stuff into test mode.
_docommand_recursive = 0;
_random_seeds[0][0] = p1;
_random_seeds[0][1] = p2;
SwitchMode(SM_START_SCENARIO);
return 0;
}
static const Widget _ask_abandon_game_widgets[] = {
{ WWT_TEXTBTN, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
{ WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_00C7_QUIT, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 4, 0, 179, 14, 91, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
{ WIDGETS_END },
{ WWT_TEXTBTN, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
{ WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_00C7_QUIT, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 4, 0, 179, 14, 91, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
{ WIDGETS_END},
};
static void AskAbandonGameWndProc(Window *w, WindowEvent *e) {
@@ -187,7 +218,7 @@ static void AskAbandonGameWndProc(Window *w, WindowEvent *e) {
}
break;
case WE_KEYPRESS: /* Exit game on pressing 'Enter' */
if (e->keypress.keycode == WKC_RETURN || e->keypress.keycode == WKC_NUM_ENTER)
if (e->keypress.keycode == WKC_RETURN)
_exit_game = true;
break;
}
@@ -208,12 +239,12 @@ void AskExitGame(void)
static const Widget _ask_quit_game_widgets[] = {
{ WWT_TEXTBTN, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
{ WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_0161_QUIT_GAME, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 4, 0, 179, 14, 91, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
{ WIDGETS_END },
{ WWT_TEXTBTN, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL},
{ WWT_CAPTION, RESIZE_NONE, 4, 11, 179, 0, 13, STR_0161_QUIT_GAME, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 4, 0, 179, 14, 91, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 25, 84, 72, 83, STR_00C9_NO, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 12, 95, 154, 72, 83, STR_00C8_YES, STR_NULL},
{ WIDGETS_END},
};
static void AskQuitGameWndProc(Window *w, WindowEvent *e) {
@@ -258,3 +289,13 @@ void AskExitToGameMenu(void)
{
AllocateWindowDescFront(&_ask_quit_game_desc, 0);
}
int32 CmdSetNewLandscapeType(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
if (flags & DC_EXEC) {
// XXX: some stuff
_new_opt.landscape = p1;
InvalidateWindowClasses(WC_SELECT_GAME);
}
return 0;
}

View File

@@ -1,6 +1,6 @@
README
------------------------------------------------------------------------
All bugs listed below are marked as known. Please do not submit any bugs
All bugs listed below are marked as known. Please do not submit any bugs
that are the same as these. If you do, don't act surprised, because
we WILL flame you!!
@@ -14,59 +14,62 @@ by the number below on http://sourceforge.net/tracker/?group_id=103924&atid=6363
If the the bug report is closed, it has been fixed, which then can be verified
in the latest SVN version.
Bugs for 0.4.0
Bugs for 0.3.6
------------------------------------------------------------------------
URL: http://sourceforge.net/tracker/?atid=636365&group_id=103924&func=browse
- In certain circumstances the game can crash if you drag the minimap to a corner
-1197216 Error: !invalid string id 0 in GetString
-1197116 Some stations are cargo-less
-1188897 Station with cargo enroute_from INVALID_STATION
-1186802 Company value problem (loans)
-1181888 Invaild Station Order => Crash
-1174829 Waypoint / Orders Bug
-1168820 Some mouse and keyboard events are lost
-1167810 Cargo payment after deleting stations (st->xy = 0)
-1157244 Can't save game if name contains german umlauts
-1144510 Make install tries to install scenarios to the wrong place
-1116638 "More, but smaller changes" deficiency
-1106356 re-offered prototypes
-1099233 production down before it's working
-1085486 Subsidies: Only count when station is in right suburb
-992677 BeOS MIDI does not initialise on newer BeOS releases
-1108615 Catchment area mis-behaving
-1108610 console logging file type
-1108442 autorenew takes precedence over autoreplace
-1107889 server crash and assertion error
-1106356 re-offered prototypes
-1104670 Vans in the depot
-1104519 train pathfinding with new patch
-1104105 script error (r1547)
-1103068 game crashes after reversing train in deport
-1101874 load savegames (and autosave) with dedicated server
-1099694 incorrect player colors
-1099233 production down before it's working
-1098696 Airport shadow remains after crashing
-1098238 Crash after lone wagon sighting
-1093191 2 problems with multiplayer savegames
-1085486 Subsidies: Only count when station is in right suburb
-1083710 Reverse train in depot crashes OpenTTD
-1074610 overtaking at signals bug
-1060686 changing (load) order doesn't take effect immediately
-1053339 depot/station looping
-1033300 signal bug
-1030918 Negative city population
-1024703 Infinite access of A: when saving and no disk in drive
-997251 Realistic acceleration: Trains don't slow down in curves
-996503 Sound volume bug
-992677 BeOS MIDI does not initialise on newer BeOS releases
-985475 Different kinds of signals in same tile?
-978372 Inconsistent stopping
-968036 Ship blocked at the edge
Minor Bugs for 0.4.0
Minor Bugs for 0.3.6
------------------------------------------------------------------------
URL: http://sourceforge.net/tracker/?atid=669662&group_id=103924&func=browse
-1201284 permanent hilight in a depot
-1197258 Window Z-order locked when exiting openttd
-1193882 problems with dualhead engins in DB Set XL (v0.81)
-1193870 keep the date counter running
-1185852 Scrollbars get arbitrarily small
-1184634 Replace vehicles window bug
-1183253 Incorrect Load vs Loading Sprites
-1183251 Hangar sprite does not update when refit.
-1179933 autorail removal does not go completely red.
-1160732 little bug with transparency
-1153937 Game wont run from a start menu shortcut
-1117731 Editor-StartingDate
-1114237 Wrong autoreplace hint
-1112784 detailed sound options
-1108046 game freezes
-1106889 Chat Interface enhancements
-1104358 train lost message - history
-1102174 Bug if 3 people buy 25% shares in one company
-1087407 wrong message in history
-1084620 Minor bug considering buses/trucks
-1034310 color mauve in diagrams
-1030661 It's possible to build a tunnel under oil wells
-1009171 Canals and locks at sea level cause flooding
-993516 Canal + bouy -> wrong graphics.
-987891 Large UFO destruction bug
-987884 farm fences
-987883 Aircraft landing/taking off
-987880 company league table updating
-985924 aircraft taxi speed
-980276 Overflow in factory directory
-976824 transmitter base
-941694 Clipping problems stations/vehicles on slopes
-936997 Stationname too long to fit in trainwindow bug
-1106889 Chat Interface enhancements
-1104968 void order message
-1104358 train lost message - history
-1102174 Bug if 3 people buy 25% shares in one company
-1099429 show vehicle speed, text too long
-1090495 Bridges and straight lakesides
-1087407 wrong message in history
-1084620 Minor bug considering buses/trucks
-1034310 color mauve in diagrams
-1031184 Smoke visible through tunnel
-1030661 It's possible to build a tunnel under oil wells
-1009171 Canals and locks at sea level cause flooding
-993516 Canal + bouy -> wrong graphics.
-987891 Large UFO destruction bug
-987884 farm fences
-987883 Aircraft landing/taking off
-987880 company league table updating
-985924 aircraft taxi speed
-980276 Overflow in factory directory
-976824 transmitter base
-941694 Clipping problems stations/vehicles on slopes
-936997 Stationname too long to fit in trainwindow bug

View File

@@ -1,9 +1,6 @@
#include "stdafx.h"
#include "ttd.h"
#include "map.h"
#include "spritecache.h"
#include "table/sprites.h"
#include "tile.h"
#include <stdarg.h>
#include "gfx.h"
#include "viewport.h"
@@ -43,20 +40,69 @@ const byte _tileh_to_sprite[32] = {
0,0,0,0,0,0,0,16,0,0,0,17,0,15,18,0,
};
void FindLandscapeHeightByTile(TileInfo *ti, TileIndex tile)
uint GetTileSlope(uint tile, int *h)
{
assert(tile < MapSize());
uint a,b,c,d,min;
int r;
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY()) {
if (h)
*h = 0;
return 0;
}
assert(tile < MapSize() && TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY());
min = a = TileHeight(tile);
b = TileHeight(tile + TILE_XY(1,0));
if (min >= b) min = b;
c = TileHeight(tile + TILE_XY(0,1));
if (min >= c) min = c;
d = TileHeight(tile + TILE_XY(1,1));
if (min >= d) min = d;
r = 0;
if ((a-=min)!=0) { r += (--a << 4) + 8; }
if ((c-=min)!=0) { r += (--c << 4) + 4; }
if ((d-=min)!=0) { r += (--d << 4) + 2; }
if ((b-=min)!=0) { r += (--b << 4) + 1; }
if (h != 0)
*h = min * 8;
return r;
}
int GetTileZ(uint tile)
{
int h;
GetTileSlope(tile, &h);
return h;
}
void FindLandscapeHeightByTile(TileInfo *ti, uint tile)
{
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY()) {
ti->tileh = 0;
ti->type = MP_VOID;
ti->tile = 0;
ti->map5 = 0;
ti->z = 0;
return;
}
ti->tile = tile;
ti->map5 = _map5[tile];
ti->type = GetTileType(tile);
ti->type = TileType(tile);
ti->tileh = GetTileSlope(tile, &ti->z);
// ti->z = min * 8;
}
/* find the landscape height for the coordinates x y */
void FindLandscapeHeight(TileInfo *ti, uint x, uint y)
{
int tile;
ti->x = x;
ti->y = y;
@@ -69,7 +115,8 @@ void FindLandscapeHeight(TileInfo *ti, uint x, uint y)
return;
}
FindLandscapeHeightByTile(ti, TILE_FROM_XY(x,y));
tile = TILE_FROM_XY(x,y);
FindLandscapeHeightByTile(ti, tile);
}
uint GetPartialZ(int x, int y, int corners)
@@ -170,9 +217,18 @@ uint GetPartialZ(int x, int y, int corners)
uint GetSlopeZ(int x, int y)
{
TileInfo ti;
// int z;
FindLandscapeHeight(&ti, x, y);
/*
z = ti.z;
x &= 0xF;
y &= 0xF;
assert(z < 256);
*/
return _tile_type_procs[ti.type]->get_slope_z_proc(&ti);
}
@@ -227,7 +283,7 @@ void DrawFoundation(TileInfo *ti, uint f)
}
}
void DoClearSquare(TileIndex tile)
void DoClearSquare(uint tile)
{
ModifyTile(tile,
MP_SETTYPE(MP_CLEAR) |
@@ -237,30 +293,30 @@ void DoClearSquare(TileIndex tile)
);
}
uint32 GetTileTrackStatus(TileIndex tile, TransportType mode)
uint32 GetTileTrackStatus(uint tile, TransportType mode)
{
return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode);
return _tile_type_procs[TileType(tile)]->get_tile_track_status_proc(tile, mode);
}
void ChangeTileOwner(TileIndex tile, byte old_player, byte new_player)
void ChangeTileOwner(uint tile, byte old_player, byte new_player)
{
_tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_player, new_player);
_tile_type_procs[TileType(tile)]->change_tile_owner_proc(tile, old_player, new_player);
}
void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac)
void GetAcceptedCargo(uint tile, AcceptedCargo ac)
{
memset(ac, 0, sizeof(AcceptedCargo));
_tile_type_procs[GetTileType(tile)]->get_accepted_cargo_proc(tile, ac);
_tile_type_procs[TileType(tile)]->get_accepted_cargo_proc(tile, ac);
}
void AnimateTile(TileIndex tile)
void AnimateTile(uint tile)
{
_tile_type_procs[GetTileType(tile)]->animate_tile_proc(tile);
_tile_type_procs[TileType(tile)]->animate_tile_proc(tile);
}
void ClickTile(TileIndex tile)
void ClickTile(uint tile)
{
_tile_type_procs[GetTileType(tile)]->click_tile_proc(tile);
_tile_type_procs[TileType(tile)]->click_tile_proc(tile);
}
void DrawTile(TileInfo *ti)
@@ -268,39 +324,33 @@ void DrawTile(TileInfo *ti)
_tile_type_procs[ti->type]->draw_tile_proc(ti);
}
void GetTileDesc(TileIndex tile, TileDesc *td)
void GetTileDesc(uint tile, TileDesc *td)
{
_tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
_tile_type_procs[TileType(tile)]->get_tile_desc_proc(tile, td);
}
/** Clear a piece of landscape
* @param x,y coordinates of clearance
* @param p1 unused
* @param p2 unused
/* Clear a piece of landscape
* p1 = 0,
* p2 = 0
*/
int32 CmdLandscapeClear(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TileIndex tile = TILE_FROM_XY(x, y);
uint tile;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
return _tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags);
tile = TILE_FROM_XY(x,y);
return _tile_type_procs[TileType(tile)]->clear_tile_proc(tile, flags);
}
/** Clear a big piece of landscape
* @param x,y end coordinates of area dragging
* @param p1 start tile of area dragging
* @param p2 unused
*/
// p1 = end tile
int32 CmdClearArea(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
{
int32 cost, ret, money;
int32 cost,ret, money;
int sx,sy;
int x,y;
bool success = false;
if (p1 > MapSize()) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
// make sure sx,sy are smaller than ex,ey
@@ -312,37 +362,37 @@ int32 CmdClearArea(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
money = GetAvailableMoneyForCommand();
cost = 0;
for (x = sx; x <= ex; x += 16) {
for (y = sy; y <= ey; y += 16) {
for(x=sx; x<=ex; x+=16) {
for(y=sy; y<=ey; y+=16) {
ret = DoCommandByTile(TILE_FROM_XY(x,y), 0, 0, flags &~DC_EXEC, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) continue;
if (ret == CMD_ERROR) continue;
cost += ret;
success = true;
if (flags & DC_EXEC) {
if (ret > 0 && (money -= ret) < 0) {
if ( ret>0 && (money -= ret) < 0) {
_additional_cash_required = ret;
return cost - ret;
}
DoCommandByTile(TILE_FROM_XY(x,y), 0, 0, flags, CMD_LANDSCAPE_CLEAR);
// draw explosion animation...
if ((x == sx || x == ex) && (y == sy || y == ey)) {
if ((x==sx || x==ex) && (y==sy || y==ey)) {
// big explosion in each corner, or small explosion for single tiles
CreateEffectVehicleAbove(x + 8, y + 8, 2,
sy == ey && sx == ex ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
);
CreateEffectVehicleAbove(x + 8,y + 8, 2, sy==ey && sx==ex ? EV_DEMOLISH : EV_CRASHED_SMOKE);
}
}
}
}
return (success) ? cost : CMD_ERROR;
if (!success)
cost = CMD_ERROR;
return cost;
}
/* utility function used to modify a tile */
void CDECL ModifyTile(TileIndex tile, uint flags, ...)
void CDECL ModifyTile(uint tile, uint flags, ...)
{
va_list va;
int i;
@@ -387,6 +437,17 @@ void CDECL ModifyTile(TileIndex tile, uint flags, ...)
MarkTileDirtyByTile(tile);
}
void SetMapExtraBits(uint tile, byte bits)
{
_map_extra_bits[tile >> 2] &= ~(3 << ((tile&3)*2));
_map_extra_bits[tile >> 2] |= (bits&3) << ((tile&3)*2);
}
uint GetMapExtraBits(uint tile)
{
assert(tile < MapSize());
return (_map_extra_bits[tile >> 2] >> (tile & 3) * 2) & 3;
}
#define TILELOOP_BITS 4
#define TILELOOP_SIZE (1 << TILELOOP_BITS)
@@ -395,7 +456,7 @@ void CDECL ModifyTile(TileIndex tile, uint flags, ...)
void RunTileLoop(void)
{
TileIndex tile;
uint tile;
uint count;
tile = _cur_tileloop_tile;
@@ -403,7 +464,7 @@ void RunTileLoop(void)
assert( (tile & ~TILELOOP_ASSERTMASK) == 0);
count = (MapSizeX() / TILELOOP_SIZE) * (MapSizeY() / TILELOOP_SIZE);
do {
_tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
_tile_type_procs[TileType(tile)]->tile_loop_proc(tile);
if (TileX(tile) < MapSizeX() - TILELOOP_SIZE) {
tile += TILELOOP_SIZE; /* no overflow */
@@ -419,40 +480,43 @@ void RunTileLoop(void)
_cur_tileloop_tile = tile;
}
void InitializeLandscape(uint log_x, uint log_y)
void InitializeLandscape(void)
{
uint map_size;
uint map_size = MapSize();
uint i;
InitMap(log_x, log_y);
map_size = MapSize();
memset(_map_owner, OWNER_NONE, map_size);
memset(_map2, 0, map_size * sizeof(uint16));
memset(_map3_lo, 0, map_size);
memset(_map3_hi, 0, map_size);
memset(_map_extra_bits, 0, map_size / 4);
memset(_map_type_and_height, MP_CLEAR << 4, map_size);
memset(_map_owner, OWNER_NONE, map_size);
memset(_map2, 0, map_size * sizeof(_map2[0]));
memset(_map3_lo, 0, map_size);
memset(_map3_hi, 0, map_size);
memset(_map5, 3, map_size);
memset(_map_extra_bits, 0, map_size / 4);
// create void tiles at the border
for (i = 0; i < MapMaxY(); ++i)
SetTileType(i * MapSizeX() + MapMaxX(), MP_VOID);
for (i = 0; i < MapSizeX(); ++i)
SetTileType(MapSizeX() * MapMaxY() + i, MP_VOID);
// create void tiles on the border
for (i = 0; i != MapMaxY(); i++)
_map_type_and_height[ i * MapSizeX() + MapMaxY() ] = MP_VOID << 4;
memset(_map_type_and_height + MapMaxY() * MapSizeX(), MP_VOID << 4, MapSizeX());
memset(_map5, 3, map_size);
}
void ConvertGroundTilesIntoWaterTiles(void)
{
TileIndex tile = 0;
uint h;
uint tile = 0;
int h;
for (tile = 0; tile < MapSize(); ++tile) {
while(true) {
if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == 0 && h == 0) {
SetTileType(tile, MP_WATER);
_map5[tile] = 0;
_map_owner[tile] = OWNER_WATER;
}
tile++;
if (TileX(tile) == MapMaxX()) {
tile += TILE_XY(-(int)MapMaxX(), 1);
if (TileY(tile) == MapMaxY())
break;
}
}
}
@@ -462,17 +526,13 @@ static const byte _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
static void GenerateTerrain(int type, int flag)
{
uint32 r;
uint x;
uint y;
uint w;
uint h;
const Sprite* template;
const byte *p;
byte *tile;
uint x,y;
int w,h;
byte *p,*tile;
byte direction;
r = Random();
template = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845);
p = GetSpritePtr((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845);
x = r & MapMaxX();
y = (r >> MapLogX()) & MapMaxY();
@@ -481,37 +541,29 @@ static void GenerateTerrain(int type, int flag)
if (x < 2 || y < 2)
return;
direction = (r >> 22) & 3;
if (direction & 1) {
w = template->height;
h = template->width;
} else {
w = template->width;
h = template->height;
}
p = template->data;
direction = (byte)(r >> 22) & 3;
w = p[2];
h = p[1];
if (direction & 1) { w = p[1]; h = p[2]; }
p += 8;
if (flag & 4) {
uint xw = x * MapSizeY();
uint yw = y * MapSizeX();
uint bias = (MapSizeX() + MapSizeY()) * 16;
switch (flag & 3) {
case 0:
if (xw + yw > MapSize() - bias) return;
break;
case 1:
if (yw < xw + bias) return;
break;
case 2:
if (xw + yw < MapSize() + bias) return;
break;
case 3:
if (xw < yw + bias) return;
break;
if (!(flag & 2)) {
if (!(flag & 1)) {
if (x + y > 190)
return;
} else {
if (y < 30 + x)
return;
}
} else {
if (!(flag & 1)) {
if (x + y < 256)
return;
} else {
if (x < 30 + y)
return;
}
}
}
@@ -521,66 +573,54 @@ static void GenerateTerrain(int type, int flag)
if (y + h >= MapMaxY() - 1)
return;
tile = &_map_type_and_height[TILE_XY(x, y)];
tile = &_map_type_and_height[TILE_XY(x,y)];
switch (direction) {
case 0:
if (direction == 0) {
do {
int w_cur = w;
byte *tile_cur = tile;
do {
byte *tile_cur = tile;
uint w_cur;
for (w_cur = w; w_cur != 0; --w_cur) {
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur++;
}
tile += TILE_XY(0, 1);
} while (--h != 0);
break;
case 1:
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur++;
} while (--w_cur != 0);
tile += TILE_XY(0,1);
} while (--h != 0);
} else if (direction == 1) {
do {
int h_cur = h;
byte *tile_cur = tile;
do {
byte *tile_cur = tile;
uint h_cur;
for (h_cur = h; h_cur != 0; --h_cur) {
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur += TILE_XY(0, 1);
}
tile++;
} while (--w != 0);
break;
case 2:
tile += TILE_XY(w - 1, 0);
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur+=TILE_XY(0,1);
} while (--h_cur != 0);
tile++;
} while (--w != 0);
} else if (direction == 2) {
tile += w - 1;
do {
int w_cur = w;
byte *tile_cur = tile;
do {
byte *tile_cur = tile;
uint w_cur;
for (w_cur = w; w_cur != 0; --w_cur) {
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur--;
}
tile += TILE_XY(0, 1);
} while (--h != 0);
break;
case 3:
tile += TILE_XY(0, h - 1);
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur--;
} while (--w_cur != 0);
tile += TILE_XY(0,1);
} while (--h != 0);
} else {
tile += (h - 1) * TILE_XY(0,1);
do {
int h_cur = h;
byte *tile_cur = tile;
do {
byte *tile_cur = tile;
uint h_cur;
for (h_cur = h; h_cur != 0; --h_cur) {
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur -= TILE_XY(0, 1);
}
tile++;
} while (--w != 0);
break;
if (*p >= *tile_cur) *tile_cur = *p;
p++;
tile_cur-=TILE_XY(0,1);
} while (--h_cur != 0);
tile++;
} while (--w != 0);
}
}
@@ -589,21 +629,21 @@ static void GenerateTerrain(int type, int flag)
static void CreateDesertOrRainForest(void)
{
TileIndex tile;
uint tile;
const TileIndexDiffC *data;
uint i;
int i;
for (tile = 0; tile != MapSize(); ++tile) {
for (data = _make_desert_or_rainforest_data;
data != endof(_make_desert_or_rainforest_data); ++data) {
TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data));
TileIndex t = tile + ToTileIndexDiff(*data);
if (TileHeight(t) >= 4 || IsTileType(t, MP_WATER)) break;
}
if (data == endof(_make_desert_or_rainforest_data))
SetMapExtraBits(tile, 1);
}
for (i = 0; i != 256; i++)
for(i=0; i!=256; i++)
RunTileLoop();
for (tile = 0; tile != MapSize(); ++tile) {
@@ -619,35 +659,45 @@ static void CreateDesertOrRainForest(void)
void GenerateLandscape(void)
{
uint i;
uint flag;
int i,flag;
uint32 r;
if (_opt.landscape == LT_HILLY) {
for (i = ScaleByMapSize((Random() & 0x7F) + 950); i != 0; --i)
i = ((Random() & 0x7F) + 950) * LANDSCAPE_SIZE_FACTOR;
do {
GenerateTerrain(2, 0);
} while (--i);
r = Random();
flag = (r & 3) | 4;
for (i = ScaleByMapSize(((r >> 16) & 0x7F) + 450); i != 0; --i)
i = (((r >> 16) & 0x7F) + 450) * LANDSCAPE_SIZE_FACTOR;
do {
GenerateTerrain(4, flag);
} while (--i);
} else if (_opt.landscape == LT_DESERT) {
for (i = ScaleByMapSize((Random()&0x7F) + 170); i != 0; --i)
i = ((Random()&0x7F) + 170) * LANDSCAPE_SIZE_FACTOR;
do {
GenerateTerrain(0, 0);
} while (--i);
r = Random();
flag = (r & 3) | 4;
for (i = ScaleByMapSize(((r >> 16) & 0xFF) + 1700); i != 0; --i)
i = (((r >> 16) & 0xFF) + 1700) * LANDSCAPE_SIZE_FACTOR;
do {
GenerateTerrain(0, flag);
} while (--i);
flag ^= 2;
for (i = ScaleByMapSize((Random() & 0x7F) + 410); i != 0; --i)
i = ((Random() & 0x7F) + 410) * LANDSCAPE_SIZE_FACTOR;
do {
GenerateTerrain(3, flag);
} while (--i);
} else {
i = ScaleByMapSize((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100);
for (; i != 0; --i)
i = ((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes)*256 + 100) * LANDSCAPE_SIZE_FACTOR;
do {
GenerateTerrain(_opt.diff.terrain_type, 0);
} while (--i);
}
ConvertGroundTilesIntoWaterTiles();
@@ -680,13 +730,32 @@ TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng)
int rn = rng;
uint32 r = Random();
return TILE_MASK(TILE_XY(
return TILE_XY(
TileX(a) + ((byte)r * rn * 2 >> 8) - rn,
TileY(a) + ((byte)(r >> 8) * rn * 2 >> 8) - rn
));
);
}
bool IsValidTile(TileIndex tile)
// This function checks if we add addx/addy to tile, if we
// do wrap around the edges. For example, tile = (10,2) and
// addx = +3 and addy = -4. This function will now return
// TILE_WRAPPED, because the y is wrapped. This is needed in
// for example, farmland. When the tile is not wrapped,
// the result will be tile + TILE_XY(addx, addy)
uint TileAddWrap(TileIndex tile, int addx, int addy)
{
uint x, y;
x = TileX(tile) + addx;
y = TileY(tile) + addy;
// Are we about to wrap?
if (x < MapMaxX() && y < MapMaxY())
return tile + TILE_XY(addx, addy);
return TILE_WRAPPED;
}
bool IsValidTile(uint tile)
{
return (tile < MapSizeX() * MapMaxY() && TileX(tile) != MapMaxX());
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
##name Original vehicle names (ENG)
##ownname Original vehicle names (ENG)
##isocode xx
##id 0x8000
STR_8000_KIRBY_PAUL_TANK_STEAM :Collett Pannier Tank (Steam)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,366 +0,0 @@
##name Frisian
##ownname Frysk
##isocode fy
##id 0x0000
STR_NULL :
STR_0001_OFF_EDGE_OF_MAP :{WHITE}Off edge of map
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Too close to edge of map
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Not enough cash - requires {CURRENCY}
STR_0004 :{WHITE}{CURRENCY64}
STR_0005 :{RED}{CURRENCY64}
STR_EMPTY :
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Flat land required
STR_0008_WAITING :{BLACK}Waiting: {WHITE}{STRING}
STR_0009 :{WHITE}{STRING}
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (en-route from
STR_000B :{YELLOW}{STATION})
STR_000C_ACCEPTS :{BLACK}Accepts: {WHITE}
STR_000D_ACCEPTS :{BLACK}Accepts: {GOLD}
STR_000E :
STR_000F_PASSENGERS :Passengers
STR_0010_COAL :Coal
STR_0011_MAIL :Post
STR_0012_OIL :Oalje
STR_0013_LIVESTOCK :Livestock
STR_0014_GOODS :Guod
STR_0015_GRAIN :Graan
STR_0016_WOOD :Hout
STR_0017_IRON_ORE :Iron Ore
STR_0018_STEEL :Stiel
STR_0019_VALUABLES :Kostbere spullen
STR_001A_COPPER_ORE :Koper erts
STR_001B_MAIZE :Mais
STR_001C_FRUIT :Fruit
STR_001D_DIAMONDS :Diamant
STR_001E_FOOD :Iten
STR_001F_PAPER :Papier
STR_0020_GOLD :Goud
STR_0021_WATER :Wetter
STR_0022_WHEAT :Weet
STR_0023_RUBBER :Rubber
STR_0024_SUGAR :S<>ker
STR_0025_TOYS :Boartersguod
STR_0026_CANDY :Snobbersguod
STR_0027_COLA :Cola
STR_0028_COTTON_CANDY :S<>kerspin
STR_0029_BUBBLES :Bubbels
STR_002A_TOFFEE :Toffee
STR_002B_BATTERIES :Batterijen
STR_002C_PLASTIC :Plestik
STR_002E :
STR_002F_PASSENGER :Passazjier
STR_0030_COAL :Coal
STR_0031_MAIL :Post
STR_0032_OIL :Oalje
STR_0033_LIVESTOCK :Fee
STR_0034_GOODS :Guod
STR_0035_GRAIN :N<>t
STR_0036_WOOD :Hout
STR_0037_IRON_ORE :Izer Erts
STR_0038_STEEL :Stiel
STR_0039_VALUABLES :Kostber guod
STR_003A_COPPER_ORE :Koper Erts
STR_003B_MAIZE :Mais
STR_003C_FRUIT :Fruit
STR_003D_DIAMOND :Diamant
STR_003E_FOOD :Iten
STR_003F_PAPER :Papier
STR_0040_GOLD :Goud
STR_0041_WATER :Wetter
STR_0043_RUBBER :Rubber
STR_0044_SUGAR :S<>ker
STR_0045_TOY :Boartesguod
STR_0046_CANDY :Snobbersguod
STR_0047_COLA :Cola
STR_004A_TOFFEE :Toffee
STR_004B_BATTERY :Batterij
STR_004C_PLASTIC :Plestik
STR_004E :
STR_004F_PASSENGER :{COMMA16} passazjier
STR_0050_TON_OF_COAL :{COMMA16} ton coal
STR_0051_BAG_OF_MAIL :{COMMA16} tassen mei post
STR_0052_OF_OIL :{VOLUME} oalje
STR_0055_TON_OF_GRAIN :{COMMA16} ton graan
STR_0056_TON_OF_WOOD :{COMMA16} ton hout
STR_0058_TON_OF_STEEL :{COMMA16} ton stiel
STR_0059_BAG_OF_VALUABLES :{COMMA16} tas kostber guod
STR_005B_TON_OF_MAIZE :{COMMA16} ton mais
STR_005C_TON_OF_FRUIT :{COMMA16} ton fruit
STR_005E_TON_OF_FOOD :{COMMA16} ton iten
STR_005F_TON_OF_PAPER :{COMMA16} ton papier
STR_0060_BAG_OF_GOLD :{COMMA16} tas goud
STR_0061_OF_WATER :{VOLUME} wetter
STR_00B2_MESSAGE :{YELLOW}Bericht
STR_00B3_MESSAGE_FROM :{YELLOW}Bericht fan {STRING}
STR_00B7_VERSION :{BLACK}OpenTTD fersje {REV}
STR_00C8_YES :{BLACK}Ja
STR_00C9_NO :{BLACK}Nee
STR_00D1_DARK_BLUE :Tsjuster Blauw
STR_00D3_PINK :Roze
STR_00D4_YELLOW :Giel
STR_00D5_RED :Read
STR_00D6_LIGHT_BLUE :Ljocht Blauw
STR_00D7_GREEN :Grien
STR_00D8_DARK_GREEN :Tsjuster Grien
STR_00D9_BLUE :Blauw
STR_00DC_PURPLE :Pears
STR_00DD_ORANGE :Oranje
STR_00DE_BROWN :Br<42>n
STR_00DF_GREY :Griis
STR_00E0_WHITE :Wyt
############ range for menu starts
############ range for menu ends
############ range for months starts
############ range for months ends
############ range for service numbers starts
############ range for service numbers ends
############ range for days starts
STR_01B0_5TH :5
STR_01B1_6TH :6
STR_01B2_7TH :7
STR_01B3_8TH :8
STR_01B4_9TH :9
STR_01B5_10TH :10
STR_01B6_11TH :11
STR_01B7_12TH :12
STR_01B8_13TH :13
STR_01B9_14TH :14
STR_01BA_15TH :15
STR_01BB_16TH :16
STR_01BC_17TH :17
STR_01BD_18TH :18
STR_01BE_19TH :19
STR_01BF_20TH :20
STR_01C0_21ST :21
STR_01C1_22ND :22
STR_01C2_23RD :23
STR_01C3_24TH :24
STR_01C4_25TH :25
STR_01C5_26TH :26
STR_01C6_27TH :27
STR_01C7_28TH :28
STR_01C8_29TH :29
############ range for days ends
############ range for cargo acecpted starts
############ range for cargo acecpted ends
############ range for menu starts
############ range ends here
############ range for menu starts
############ range ends here
############ range for menu starts
############ range ends here
############ start of townname region
############ end of townname region
# Start of order review system.
# DON'T ADD OR REMOVE LINES HERE
# end of order system
############ network gui strings
############ Leave those lines in this order!!
############ End of leave-in-this-order
############ Leave those lines in this order!!
############ End of leave-in-this-order
############ Leave those lines in this order!!
############ End of leave-in-this-order
############ end network gui strings
##id 0x0800
##id 0x1000
##id 0x1800
##id 0x2000
##id 0x2800
##id 0x3000
############ range for rating starts
############ range for rating ends
##id 0x3800
##id 0x4000
##id 0x4800
############ range for requires starts
############ range for requires ends
##id 0x5000
##id 0x5800
############ WARNING, using range 0x6000 for strings that are stored in the savegame
############ These strings may never get a new id, or savegames will break!
##id 0x6000
############ end of savegame specific region!
##id 0x6800
############ range for difficulty levels starts
############ range for difficulty levels ends
############ range for difficulty settings starts
############ range for difficulty settings ends
##id 0x7000
##id 0x8000
##id 0x8800
##id 0x9000
##id 0x9800
##id 0xA000
##id 0xB000
############ Those following lines need to be in this order!!
############ End of order list
############ Lists rail types
############ End of list of rail types

424
lang/unfinished/latvian.txt Normal file
View File

@@ -0,0 +1,424 @@
##name Latvian
##ownname Latvie<69>u valoda
##id 0x0000
STR_NULL :
STR_0001_OFF_EDGE_OF_MAP :{WHITE}&#256;rpus kartes robe<62>as
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}P&#257;r&#257;k tuvu kartes malai
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Nav diezgan naudas - vajag {CURRENCY}
STR_0004 :{WHITE}{CURRENCY64}
STR_0005 :{RED}{CURRENCY64}
STR_EMPTY :
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Zemei j&#257;b&#363;t plakanai
STR_0008_WAITING :{BLACK}Gaidam: {WHITE}{STRING}
STR_0009 :{WHITE}{STRING}
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (ce&#316;&#257; no
STR_000B :{YELLOW}{STATION})
STR_000C_ACCEPTS :{BLACK}Pie&#326;em: {WHITE}
STR_000D_ACCEPTS :{BLACK}Pie&#326;em: {GOLD}
STR_000E :
STR_000F_PASSENGERS :Pasa<73>ierus
STR_0010_COAL :Ogles
STR_0011_MAIL :Pastu
STR_0012_OIL :Naftu
STR_0013_LIVESTOCK :Liellopus
STR_0014_GOODS :Preces
STR_0015_GRAIN :Graudus
STR_0016_WOOD :Kokmatere&#257;lus
STR_0017_IRON_ORE :Dzelzs r&#363;du
STR_0018_STEEL :T&#275;raudu
STR_0019_VALUABLES :V&#275;rtspap&#299;ri
STR_001A_COPPER_ORE :Vara r&#363;da
STR_001B_MAIZE :Kukur&#363;za
STR_001C_FRUIT :Aug&#316;i
STR_001D_DIAMONDS :Dimanti
STR_001E_FOOD :P&#257;rtika
STR_001F_PAPER :Pap&#299;rs
STR_0020_GOLD :Zelts
STR_0021_WATER :&#362;dens
STR_0022_WHEAT :Kvie<69>i
STR_0023_RUBBER :Gumija
STR_0024_SUGAR :Cukurs
STR_0025_TOYS :Rota&#316;lietas
STR_0026_CANDY :Saldumi
STR_0027_COLA :Kola
STR_0028_COTTON_CANDY :Cukurvate
STR_0029_BUBBLES :Burbu&#316;i
STR_002A_TOFFEE :Cukurpl&#257;ksnes
STR_002B_BATTERIES :Baterijas
STR_002C_PLASTIC :Plastmasa
STR_002D_FIZZY_DRINKS :Burbu&#316;&#363;de&#326;i
STR_002E :
STR_002F_PASSENGER :Pasa<73>ieris
STR_0030_COAL :Ogle
STR_0031_MAIL :Pasts
STR_0032_OIL :Nafta
STR_0033_LIVESTOCK :Liellopi
STR_0034_GOODS :Preces
STR_0035_GRAIN :Graudi
STR_0036_WOOD :Kokmatere&#257;li
STR_0037_IRON_ORE :Dzelzs r&#363;da
STR_0038_STEEL :T&#275;rauds
STR_0039_VALUABLES :V&#275;rtspap&#299;ri
STR_003A_COPPER_ORE :Vara r&#363;da
STR_003B_MAIZE :Kukur&#363;za
STR_003C_FRUIT :Aug&#316;i
STR_003D_DIAMOND :Dimanti
STR_003E_FOOD :P&#257;rtika
STR_003F_PAPER :pap&#299;rs
STR_0040_GOLD :Zelts
STR_0041_WATER :&#362;dens
STR_0042_WHEAT :Kvie<69>i
STR_0043_RUBBER :Gumija
STR_0044_SUGAR :Cukurs
STR_0045_TOY :Rota&#316;lieta
STR_0046_CANDY :Saldumi
STR_0047_COLA :Kola
STR_0048_COTTON_CANDY :Cukurvate
STR_0049_BUBBLE :Burbulis
STR_004A_TOFFEE :Cukurpl&#257;ksn&#299;te
STR_004B_BATTERY :Baterijas
STR_004C_PLASTIC :Plastmasas
STR_004D_FIZZY_DRINK :Burbu&#316;&#363;de&#326;u
STR_004E :
STR_004F_PASSENGER :{COMMA16} pasa<73>ieris
STR_0050_TON_OF_COAL :{COMMA16} tonna og&#316;u
STR_0051_BAG_OF_MAIL :{COMMA16} pasta maiss
STR_0052_OF_OIL :{VOLUME} naftas
STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} liellops
STR_0054_CRATE_OF_GOODS :{COMMA16} pre&#269;u kaste
STR_0055_TON_OF_GRAIN :{COMMA16} tonna graudu
STR_0056_TON_OF_WOOD :{COMMA16} tonna kokmatere&#257;lu
STR_0057_TON_OF_IRON_ORE :{COMMA16} tonna dzelzs r&#363;das
STR_0058_TON_OF_STEEL :{COMMA16} tonna t&#275;rauda
STR_0059_BAG_OF_VALUABLES :{COMMA16} maiss ar v&#275;rtspap&#299;riem
STR_005A_TON_OF_COPPER_ORE :{COMMA16} tonna vara r&#363;das
STR_005B_TON_OF_MAIZE :{COMMA16} tonna kukur&#363;zas
STR_005C_TON_OF_FRUIT :{COMMA16} tonna aug&#316;u
STR_005D_BAG_OF_DIAMONDS :{COMMA16} maiss ar dimantiem
STR_005E_TON_OF_FOOD :{COMMA16} tonna p&#257;rtikas pre&#269;u
STR_005F_TON_OF_PAPER :{COMMA16} tonna pap&#299;ra
STR_0060_BAG_OF_GOLD :{COMMA16} zelta maiss
STR_0061_OF_WATER :{VOLUME} &#363;dens
STR_0062_TON_OF_WHEAT :{COMMA16} tonna kvie<69>u
STR_0063_OF_RUBBER :{VOLUME} tonna gumijas
STR_0064_TON_OF_SUGAR :{COMMA16} tonna cukura
STR_0065_TOY :{COMMA16} rota&#316;lieta
STR_0066_BAG_OF_CANDY :{COMMA16} saldumu maiss
STR_0067_OF_COLA :{VOLUME} kolas
STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tonna cukurvates
STR_0069_BUBBLE :{COMMA16} burbulis
STR_006A_TON_OF_TOFFEE :{COMMA16} tonna cukurpl&#257;ksn&#299;<3B>u
STR_006B_BATTERY :{COMMA16} baterija
STR_006C_OF_PLASTIC :{VOLUME} plastmasas
STR_006D_FIZZY_DRINK :{COMMA16} burbu&#316;&#363;denis
STR_006E :
STR_006F_PASSENGERS :{COMMA16} pasa<73>ieri
STR_0070_TONS_OF_COAL :{COMMA16} tonnas og&#316;u
STR_0071_BAGS_OF_MAIL :{COMMA16} pasta maisi
STR_0072_OF_OIL :{VOLUME} naftas
STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} liellopi
STR_0074_CRATES_OF_GOODS :{COMMA16} kastes ar prec&#275;m
STR_0075_TONS_OF_GRAIN :{COMMA16} tonnas graudu
STR_0076_TONS_OF_WOOD :{COMMA16} tonnas kokmatere&#257;lu
STR_0077_TONS_OF_IRON_ORE :{COMMA16} tonnas dzelzs r&#363;das
STR_0078_TONS_OF_STEEL :{COMMA16} tonnas t&#275;rauda
STR_0079_BAGS_OF_VALUABLES :{COMMA16} maisi ar v&#275;rtsliet&#257;m
STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tonnas vara r&#363;das
STR_007B_TONS_OF_MAIZE :{COMMA16} tonnas kukur&#363;zas
STR_007C_TONS_OF_FRUIT :{COMMA16} tonnas aug&#316;u
STR_007D_BAGS_OF_DIAMONDS :{COMMA16} maisi ar dimantiem
STR_007E_TONS_OF_FOOD :{COMMA16} tonnas p&#257;rtikas pre&#269;u
STR_007F_TONS_OF_PAPER :{COMMA16} tonnas pap&#299;ra
STR_0080_BAGS_OF_GOLD :{COMMA16} zelta maisi
STR_0081_OF_WATER :{VOLUME} &#363;dens
STR_0082_TONS_OF_WHEAT :{COMMA16} tonnas kvie<69>u
STR_0083_OF_RUBBER :{VOLUME} gumijas
STR_0084_TONS_OF_SUGAR :{COMMA16} tonnas cukura
STR_0085_TOYS :{COMMA16} rota&#316;lietas
STR_0086_BAGS_OF_CANDY :{COMMA16} saldumu maisi
STR_0087_OF_COLA :{VOLUME} kolas
STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tonnas cukurvates
STR_0089_BUBBLES :{COMMA16} burbu&#316;i
STR_008A_TONS_OF_TOFFEE :{COMMA16} tonnas cukurpl&#257;ksn&#299;<3B>u
STR_008B_BATTERIES :{COMMA16} baterijas
STR_008C_OF_PLASTIC :{VOLUME} plastmasas
STR_008D_FIZZY_DRINKS :{COMMA16} burbu&#316;&#363;de&#326;u
STR_008E :
STR_008F_PS :{TINYFONT}PA
STR_0090_CL :{TINYFONT}OG
STR_0091_ML :{TINYFONT}PT
STR_0092_OL :{TINYFONT}NF
STR_0093_LV :{TINYFONT}LL
STR_0094_GD :{TINYFONT}PR
STR_0095_GR :{TINYFONT}GR
STR_0096_WD :{TINYFONT}KM
STR_0097_OR :{TINYFONT}DZ
STR_0098_ST :{TINYFONT}TR
STR_0099_VL :{TINYFONT}VP
STR_009A_CO :{TINYFONT}VR
STR_009B_MZ :{TINYFONT}KU
STR_009C_FT :{TINYFONT}AU
STR_009D_DM :{TINYFONT}DM
STR_009E_FD :{TINYFONT}PP
STR_009F_PR :{TINYFONT}PS
STR_00A0_GD :{TINYFONT}ZE
STR_00A1_WR :{TINYFONT}UD
STR_00A2_WH :{TINYFONT}KV
STR_00A3_RB :{TINYFONT}GU
STR_00A4_SG :{TINYFONT}CU
STR_00A5_TY :{TINYFONT}RT
STR_00A6_SW :{TINYFONT}SA
STR_00A7_CL :{TINYFONT}KO
STR_00A8_CF :{TINYFONT}CV
STR_00A9_BU :{TINYFONT}BB
STR_00AA_TF :{TINYFONT}CP
STR_00AB_BA :{TINYFONT}BT
STR_00AC_PL :{TINYFONT}PL
STR_00AD_FZ :{TINYFONT}BU
STR_00AE :{WHITE}{DATE_SHORT}
STR_00AF :{WHITE}{DATE_LONG}
STR_00B0_MAP :{WHITE}Karte - {STRING}
STR_00B1_GAME_OPTIONS :{WHITE}Sp<53>les parametri
STR_00B2_MESSAGE :{YELLOW}Zi<5A>ojums
STR_00B3_MESSAGE_FROM :{YELLOW}Zi<5A>ojums no {STRING}
STR_00B4_CAN_T_DO_THIS :{WHITE}T<> nevar dar<61>t....
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}<7D>o laukumu nevar nol<6F>dzin<69>t....
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Ori<72>in<69>l<EFBFBD>s autorties<65>bas {COPYRIGHT} 1995 Chris Sawyer, Visas ties<65>bas rezerv<72>tas
STR_00B7_VERSION :{BLACK}OpenTTD versija {REV}
STR_00B8_ORIGINAL_DESIGN_PROGRAM :{BLACK}Ori<72>in<69>lais dizains: Chris Sawyer
STR_00B9_ORIGINAL_GRAPHICS :{BLACK}Ori<72>in<69>l<EFBFBD> grafika: Simon Foster
STR_SPECIAL_THANKS :{BLACK}<7D>pa<70>a pateic<69>ba sekojo<6A><6F>m person<6F>m:
STR_SPECIAL_THANKS_SIGNALS :{BLACK}<7D> Pirms-sign<67>li un semafori {COPYRIGHT} 2003 Michael Blunck
STR_SPECIAL_THANKS_CANALS :{BLACK}<7D> Pamati slied<65>m un ce<63>u nog<6F>z<EFBFBD>m {COPYRIGHT} Marcin Grzegorczyk
STR_SPECIAL_THANKS_FOUNDATIONS :{BLACK}<7D> Kan<61>lu/dambju grafika {COPYRIGHT} 2003-2004 George
STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2004 OpenTTD grupa
STR_00C5 :{BLACK}{CROSS}
STR_00C6 :{SILVER}{CROSS}
STR_00C7_QUIT :{WHITE}Beigt
STR_00C8_YES :{BLACK}J<>
STR_00C9_NO :{BLACK}N<>
STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Vai Tu tie<69><65>m gribi pamest <20>o sp<73>li un iet uz {STRING}?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
############ range for menu starts
############ range for menu ends
############ range for months starts
############ range for months ends
############ range for service numbers starts
############ range for service numbers ends
############ range for days starts
############ range for days ends
############ range for cargo acecpted starts
############ range for cargo acecpted ends
############ range for menu starts
############ range ends here
############ range for menu starts
############ range ends here
############ range for menu starts
############ range ends here
############ start of townname region
############ end of townname region
# Start of order review system.
# DON'T ADD OR REMOVE LINES HERE
# end of order system
############ network gui strings
############ Leave those lines in this order!!
############ End of leave-in-this-order
############ Leave those lines in this order!!
############ End of leave-in-this-order
############ Leave those lines in this order!!
############ End of leave-in-this-order
############ end network gui strings
##id 0x0800
##id 0x1000
##id 0x1800
##id 0x2000
##id 0x2800
##id 0x3000
############ range for rating starts
############ range for rating ends
##id 0x3800
##id 0x4000
##id 0x4800
############ range for requires starts
############ range for requires ends
##id 0x5000
##id 0x5800
############ WARNING, using range 0x6000 for strings that are stored in the savegame
############ These strings may never get a new id, or savegames will break!
##id 0x6000
############ end of savegame specific region!
##id 0x6800
############ range for difficulty levels starts
############ range for difficulty levels ends
############ range for difficulty settings starts
############ range for difficulty settings ends
##id 0x7000
##id 0x8000
##id 0x8800
##id 0x9000
##id 0x9800
##id 0xA000
##id 0xB000
############ Those following lines need to be in this order!!
############ End of order list

View File

@@ -1,209 +1,208 @@
##name Russian_latin_char
##ownname Russkiy
##isocode ru
##id 0x0000
STR_NULL :
STR_0001_OFF_EDGE_OF_MAP :{WHITE}Za krayami karti
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Blizko k krayu karti
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Ne hvataet deneg - neobhodimo {CURRENCY}
STR_0004 :{WHITE}{CURRENCY64}
STR_0005 :{RED}{CURRENCY64}
STR_EMPTY :
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Neobhodima ploskaya poverhnosty
STR_0008_WAITING :{BLACK}Ozhidanie: {WHITE}{STRING}
STR_0009 :{WHITE}{STRING}
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (marshrut iz
STR_000B :{YELLOW}{STATION})
STR_000C_ACCEPTS :{BLACK}Prinimaetsya: {WHITE}
STR_000D_ACCEPTS :{BLACK}Prinimaetsya: {GOLD}
STR_000E :
STR_000F_PASSENGERS :Passajiri
STR_0010_COAL :Ugoly
STR_0011_MAIL :Pochta
STR_0012_OIL :Nefty
STR_0013_LIVESTOCK :Domashniy skot
STR_0014_GOODS :Tovary
STR_0015_GRAIN :Zerno
STR_0016_WOOD :Derevo
STR_0017_IRON_ORE :Zheleznaya Ruda
STR_0018_STEEL :Staly
STR_0019_VALUABLES :Dragocennosti
STR_001A_COPPER_ORE :Mednaya Ruda
STR_001B_MAIZE :Kukuruza
STR_001C_FRUIT :Frukti
STR_001D_DIAMONDS :Almazi
STR_001E_FOOD :Prodovolstvie
STR_001F_PAPER :Bumaga
STR_0020_GOLD :Zoloto
STR_0021_WATER :Voda
STR_0022_WHEAT :Pshenica
STR_0023_RUBBER :Rezina
STR_0024_SUGAR :Sahar
STR_0025_TOYS :Igrushki
STR_0026_CANDY :Sladosti
STR_0027_COLA :Kola
STR_0028_COTTON_CANDY :Saharnaya vata
STR_0029_BUBBLES :Puzirki
STR_002A_TOFFEE :Iriska
STR_002B_BATTERIES :Batareyki
STR_002C_PLASTIC :Plastik
STR_002D_FIZZY_DRINKS :Shipuchie napitki
STR_002E :
STR_002F_PASSENGER :Passajiri
STR_0030_COAL :Ugoly
STR_0031_MAIL :Pochta
STR_0032_OIL :Nefty
STR_0033_LIVESTOCK :Domashniy skot
STR_0034_GOODS :Tovary
STR_0035_GRAIN :Zerno
STR_0036_WOOD :Derevo
STR_0037_IRON_ORE :Zheleznaya ruda
STR_0038_STEEL :Staly
STR_0039_VALUABLES :Dragocennosti
STR_003A_COPPER_ORE :Mednaya ruda
STR_003B_MAIZE :Kukuruza
STR_003C_FRUIT :Frukti
STR_003D_DIAMOND :Almazi
STR_003E_FOOD :Prodovolstvie
STR_003F_PAPER :Bumaga
STR_0040_GOLD :Zoloto
STR_0041_WATER :Voda
STR_0042_WHEAT :Pshenica
STR_0043_RUBBER :Rezina
STR_0044_SUGAR :Sahar
STR_0045_TOY :Igrushki
STR_0046_CANDY :Sladosti
STR_0047_COLA :Kola
STR_0048_COTTON_CANDY :Saharnaya vata
STR_0049_BUBBLE :Puzirki
STR_004A_TOFFEE :Iriska
STR_004B_BATTERY :Batareyki
STR_004C_PLASTIC :Plastik
STR_004D_FIZZY_DRINK :Shipuchie napitki
STR_004E :
STR_004F_PASSENGER :{COMMA16} passajirov
STR_0050_TON_OF_COAL :{COMMA16} tonna uglya
STR_0051_BAG_OF_MAIL :{COMMA16} sumka s pochtoy
STR_0052_OF_OIL :{VOLUME} nefti
STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} golov domashnego skota
STR_0054_CRATE_OF_GOODS :{COMMA16} korobka s tovarom
STR_0055_TON_OF_GRAIN :{COMMA16} tonna zerna
STR_0056_TON_OF_WOOD :{COMMA16} tonna dereva
STR_0057_TON_OF_IRON_ORE :{COMMA16} tonna zheleznoy rudi
STR_0058_TON_OF_STEEL :{COMMA16} tonna stali
STR_0059_BAG_OF_VALUABLES :{COMMA16} sumka s dragocennostyami
STR_005A_TON_OF_COPPER_ORE :{COMMA16} tonna mednoy rudi
STR_005B_TON_OF_MAIZE :{COMMA16} tonna kukuruzi
STR_005C_TON_OF_FRUIT :{COMMA16} tonna fruktov
STR_005D_BAG_OF_DIAMONDS :{COMMA16} meshok s almazami
STR_005E_TON_OF_FOOD :{COMMA16} tonna prodovolstviya
STR_005F_TON_OF_PAPER :{COMMA16} tonna bumagi
STR_0060_BAG_OF_GOLD :{COMMA16} meshok zolota
STR_0061_OF_WATER :{VOLUME} vodi
STR_0062_TON_OF_WHEAT :{COMMA16} tonna pshenici
STR_0063_OF_RUBBER :{VOLUME} rezini
STR_0064_TON_OF_SUGAR :{COMMA16} tonna sahara
STR_0065_TOY :{COMMA16} igrushka
STR_0066_BAG_OF_CANDY :{COMMA16} meshok sladostey
STR_0067_OF_COLA :{VOLUME} koli
STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tonna saharnoy vati
STR_0069_BUBBLE :{COMMA16} puzirki
STR_006A_TON_OF_TOFFEE :{COMMA16} tonna irisok
STR_006B_BATTERY :{COMMA16} batareyki
STR_006C_OF_PLASTIC :{VOLUME} plastika
STR_006D_FIZZY_DRINK :{COMMA16} shipuchie napitki
STR_006E :
STR_006F_PASSENGERS :{COMMA16} passajiri
STR_0070_TONS_OF_COAL :{COMMA16} tonn uglya
STR_0071_BAGS_OF_MAIL :{COMMA16} meshkov s pochtoy
STR_0072_OF_OIL :{VOLUME} nefti
STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} golov domashnego skota
STR_0074_CRATES_OF_GOODS :{COMMA16} korobok s tovarom
STR_0075_TONS_OF_GRAIN :{COMMA16} tonn zerna
STR_0076_TONS_OF_WOOD :{COMMA16} tonn dereva
STR_0077_TONS_OF_IRON_ORE :{COMMA16} tonn zheleznoy rudi
STR_0078_TONS_OF_STEEL :{COMMA16} tonn stali
STR_0079_BAGS_OF_VALUABLES :{COMMA16} meshkov s dragocennostyami
STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tonn mednoy rudi
STR_007B_TONS_OF_MAIZE :{COMMA16} tonn kukuruzi
STR_007C_TONS_OF_FRUIT :{COMMA16} tonn fruktov
STR_007D_BAGS_OF_DIAMONDS :{COMMA16} meshkov s almazami
STR_007E_TONS_OF_FOOD :{COMMA16} tonn prodovolstviya
STR_007F_TONS_OF_PAPER :{COMMA16} tonn bumagi
STR_0080_BAGS_OF_GOLD :{COMMA16} meshkov zolota
STR_0081_OF_WATER :{VOLUME} vodi
STR_0082_TONS_OF_WHEAT :{COMMA16} tonn pshenici
STR_0083_OF_RUBBER :{VOLUME} rezini
STR_0084_TONS_OF_SUGAR :{COMMA16} tonn sahara
STR_0085_TOYS :{COMMA16} igrushek
STR_0086_BAGS_OF_CANDY :{COMMA16} meshkov so sladostyami
STR_0087_OF_COLA :{VOLUME} koli
STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tonn saharnoy vati
STR_0089_BUBBLES :{COMMA16} puzirkov
STR_008A_TONS_OF_TOFFEE :{COMMA16} tonn irisok
STR_008B_BATTERIES :{COMMA16} batareek
STR_008C_OF_PLASTIC :{VOLUME} plastika
STR_008D_FIZZY_DRINKS :{COMMA16} shipuchih napitkov
STR_008E :
STR_008F_PS :{TINYFONT}PS
STR_0090_CL :{TINYFONT}CL
STR_0091_ML :{TINYFONT}ML
STR_0092_OL :{TINYFONT}OL
STR_0093_LV :{TINYFONT}LV
STR_0094_GD :{TINYFONT}GD
STR_0095_GR :{TINYFONT}GR
STR_00AF :{WHITE}{DATE_LONG}
STR_00B0_MAP :{WHITE}Karta - {STRING}
STR_00B1_GAME_OPTIONS :{WHITE}Igrovie Opcii
STR_00B2_MESSAGE :{YELLOW}Soobshenie
STR_00B3_MESSAGE_FROM :{YELLOW}Soobshenie ot {STRING}
STR_00B4_CAN_T_DO_THIS :{WHITE}Ne mogu eto sdelaty....
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Ne vozmozno ochistity etu mestnosty....
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Originalnie avtorskie prava {COPYRIGHT} 1995 Chris Sawyer, Vse prava sohraneni
STR_00B7_VERSION :{BLACK}OpenTTD versiya {REV}
STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2005 Komanda OpenTTD
STR_TRANSLATED_BY :{BLACK} Perevodchik(i) -
STR_NULL :
STR_0001_OFF_EDGE_OF_MAP :{WHITE}Za krayami karti
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Blizko k krayu karti
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Ne hvataet deneg - neobhodimo {CURRENCY}
STR_0004 :{WHITE}{CURRENCY64}
STR_0005 :{RED}{CURRENCY64}
STR_EMPTY :
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Neobhodima ploskaya poverhnosty
STR_0008_WAITING :{BLACK}Ozhidanie: {WHITE}{STRING}
STR_0009 :{WHITE}{STRING}
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (marshrut iz
STR_000B :{YELLOW}{STATION})
STR_000C_ACCEPTS :{BLACK}Prinimaetsya: {WHITE}
STR_000D_ACCEPTS :{BLACK}Prinimaetsya: {GOLD}
STR_000E :
STR_000F_PASSENGERS :Passajiri
STR_0010_COAL :Ugoly
STR_0011_MAIL :Pochta
STR_0012_OIL :Nefty
STR_0013_LIVESTOCK :Domashniy skot
STR_0014_GOODS :Tovary
STR_0015_GRAIN :Zerno
STR_0016_WOOD :Derevo
STR_0017_IRON_ORE :Zheleznaya Ruda
STR_0018_STEEL :Staly
STR_0019_VALUABLES :Dragocennosti
STR_001A_COPPER_ORE :Mednaya Ruda
STR_001B_MAIZE :Kukuruza
STR_001C_FRUIT :Frukti
STR_001D_DIAMONDS :Almazi
STR_001E_FOOD :Prodovolstvie
STR_001F_PAPER :Bumaga
STR_0020_GOLD :Zoloto
STR_0021_WATER :Voda
STR_0022_WHEAT :Pshenica
STR_0023_RUBBER :Rezina
STR_0024_SUGAR :Sahar
STR_0025_TOYS :Igrushki
STR_0026_CANDY :Sladosti
STR_0027_COLA :Kola
STR_0028_COTTON_CANDY :Saharnaya vata
STR_0029_BUBBLES :Puzirki
STR_002A_TOFFEE :Iriska
STR_002B_BATTERIES :Batareyki
STR_002C_PLASTIC :Plastik
STR_002D_FIZZY_DRINKS :Shipuchie napitki
STR_002E :
STR_002F_PASSENGER :Passajiri
STR_0030_COAL :Ugoly
STR_0031_MAIL :Pochta
STR_0032_OIL :Nefty
STR_0033_LIVESTOCK :Domashniy skot
STR_0034_GOODS :Tovary
STR_0035_GRAIN :Zerno
STR_0036_WOOD :Derevo
STR_0037_IRON_ORE :Zheleznaya ruda
STR_0038_STEEL :Staly
STR_0039_VALUABLES :Dragocennosti
STR_003A_COPPER_ORE :Mednaya ruda
STR_003B_MAIZE :Kukuruza
STR_003C_FRUIT :Frukti
STR_003D_DIAMOND :Almazi
STR_003E_FOOD :Prodovolstvie
STR_003F_PAPER :Bumaga
STR_0040_GOLD :Zoloto
STR_0041_WATER :Voda
STR_0042_WHEAT :Pshenica
STR_0043_RUBBER :Rezina
STR_0044_SUGAR :Sahar
STR_0045_TOY :Igrushki
STR_0046_CANDY :Sladosti
STR_0047_COLA :Kola
STR_0048_COTTON_CANDY :Saharnaya vata
STR_0049_BUBBLE :Puzirki
STR_004A_TOFFEE :Iriska
STR_004B_BATTERY :Batareyki
STR_004C_PLASTIC :Plastik
STR_004D_FIZZY_DRINK :Shipuchie napitki
STR_004E :
STR_004F_PASSENGER :{COMMA16} passajirov
STR_0050_TON_OF_COAL :{COMMA16} tonna uglya
STR_0051_BAG_OF_MAIL :{COMMA16} sumka s pochtoy
STR_0052_OF_OIL :{VOLUME} nefti
STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} golov domashnego skota
STR_0054_CRATE_OF_GOODS :{COMMA16} korobka s tovarom
STR_0055_TON_OF_GRAIN :{COMMA16} tonna zerna
STR_0056_TON_OF_WOOD :{COMMA16} tonna dereva
STR_0057_TON_OF_IRON_ORE :{COMMA16} tonna zheleznoy rudi
STR_0058_TON_OF_STEEL :{COMMA16} tonna stali
STR_0059_BAG_OF_VALUABLES :{COMMA16} sumka s dragocennostyami
STR_005A_TON_OF_COPPER_ORE :{COMMA16} tonna mednoy rudi
STR_005B_TON_OF_MAIZE :{COMMA16} tonna kukuruzi
STR_005C_TON_OF_FRUIT :{COMMA16} tonna fruktov
STR_005D_BAG_OF_DIAMONDS :{COMMA16} meshok s almazami
STR_005E_TON_OF_FOOD :{COMMA16} tonna prodovolstviya
STR_005F_TON_OF_PAPER :{COMMA16} tonna bumagi
STR_0060_BAG_OF_GOLD :{COMMA16} meshok zolota
STR_0061_OF_WATER :{VOLUME} vodi
STR_0062_TON_OF_WHEAT :{COMMA16} tonna pshenici
STR_0063_OF_RUBBER :{VOLUME} rezini
STR_0064_TON_OF_SUGAR :{COMMA16} tonna sahara
STR_0065_TOY :{COMMA16} igrushka
STR_0066_BAG_OF_CANDY :{COMMA16} meshok sladostey
STR_0067_OF_COLA :{VOLUME} koli
STR_0068_TON_OF_COTTON_CANDY :{COMMA16} tonna saharnoy vati
STR_0069_BUBBLE :{COMMA16} puzirki
STR_006A_TON_OF_TOFFEE :{COMMA16} tonna irisok
STR_006B_BATTERY :{COMMA16} batareyki
STR_006C_OF_PLASTIC :{VOLUME} plastika
STR_006D_FIZZY_DRINK :{COMMA16} shipuchie napitki
STR_006E :
STR_006F_PASSENGERS :{COMMA16} passajiri
STR_0070_TONS_OF_COAL :{COMMA16} tonn uglya
STR_0071_BAGS_OF_MAIL :{COMMA16} meshkov s pochtoy
STR_0072_OF_OIL :{VOLUME} nefti
STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} golov domashnego skota
STR_0074_CRATES_OF_GOODS :{COMMA16} korobok s tovarom
STR_0075_TONS_OF_GRAIN :{COMMA16} tonn zerna
STR_0076_TONS_OF_WOOD :{COMMA16} tonn dereva
STR_0077_TONS_OF_IRON_ORE :{COMMA16} tonn zheleznoy rudi
STR_0078_TONS_OF_STEEL :{COMMA16} tonn stali
STR_0079_BAGS_OF_VALUABLES :{COMMA16} meshkov s dragocennostyami
STR_007A_TONS_OF_COPPER_ORE :{COMMA16} tonn mednoy rudi
STR_007B_TONS_OF_MAIZE :{COMMA16} tonn kukuruzi
STR_007C_TONS_OF_FRUIT :{COMMA16} tonn fruktov
STR_007D_BAGS_OF_DIAMONDS :{COMMA16} meshkov s almazami
STR_007E_TONS_OF_FOOD :{COMMA16} tonn prodovolstviya
STR_007F_TONS_OF_PAPER :{COMMA16} tonn bumagi
STR_0080_BAGS_OF_GOLD :{COMMA16} meshkov zolota
STR_0081_OF_WATER :{VOLUME} vodi
STR_0082_TONS_OF_WHEAT :{COMMA16} tonn pshenici
STR_0083_OF_RUBBER :{VOLUME} rezini
STR_0084_TONS_OF_SUGAR :{COMMA16} tonn sahara
STR_0085_TOYS :{COMMA16} igrushek
STR_0086_BAGS_OF_CANDY :{COMMA16} meshkov so sladostyami
STR_0087_OF_COLA :{VOLUME} koli
STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} tonn saharnoy vati
STR_0089_BUBBLES :{COMMA16} puzirkov
STR_008A_TONS_OF_TOFFEE :{COMMA16} tonn irisok
STR_008B_BATTERIES :{COMMA16} batareek
STR_008C_OF_PLASTIC :{VOLUME} plastika
STR_008D_FIZZY_DRINKS :{COMMA16} shipuchih napitkov
STR_008E :
STR_008F_PS :{TINYFONT}PS
STR_0090_CL :{TINYFONT}CL
STR_0091_ML :{TINYFONT}ML
STR_0092_OL :{TINYFONT}OL
STR_0093_LV :{TINYFONT}LV
STR_0094_GD :{TINYFONT}GD
STR_0095_GR :{TINYFONT}GR
STR_00AF :{WHITE}{DATE_LONG}
STR_00B0_MAP :{WHITE}Karta - {STRING}
STR_00B1_GAME_OPTIONS :{WHITE}Igrovie Opcii
STR_00B2_MESSAGE :{YELLOW}Soobshenie
STR_00B3_MESSAGE_FROM :{YELLOW}Soobshenie ot {STRING}
STR_00B4_CAN_T_DO_THIS :{WHITE}Ne mogu eto sdelaty....
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Ne vozmozno ochistity etu mestnosty....
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Originalnie avtorskie prava {COPYRIGHT} 1995 Chris Sawyer, Vse prava sohraneni
STR_00B7_VERSION :{BLACK}OpenTTD versiya {REV}
STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2005 Komanda OpenTTD
STR_TRANSLATED_BY :{BLACK} Perevodchik(i) -
STR_00C5 :{BLACK}{CROSS}
STR_00C6 :{SILVER}{CROSS}
STR_00C7_QUIT :{WHITE}Vihod
STR_00C8_YES :{BLACK}Da
STR_00C9_NO :{BLACK}Net
STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Vi uvereni, chto hotite pokinuty etu igru i vernutsya k {STRING}?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
STR_00CE_4 :{BLACK}4
STR_00CF_5 :{BLACK}5
STR_00D0_NOTHING :Nichego
STR_00D1_DARK_BLUE :Temno-Siniy
STR_00D2_PALE_GREEN :Bledno-Zeleniy
STR_00D3_PINK :Rozoviy
STR_00D4_YELLOW :Zheltiy
STR_00D5_RED :Krasniy
STR_00D6_LIGHT_BLUE :Svetlo-Siniy
STR_00D7_GREEN :Zeleniy
STR_00D8_DARK_GREEN :Temno-Zeleniy
STR_00D9_BLUE :Siniy
STR_00DA_CREAM :Kremoviy
STR_00DB_MAUVE :Liloviy
STR_00DC_PURPLE :Purpurniy
STR_00DD_ORANGE :Oranjeviy
STR_00DE_BROWN :Korichneviy
STR_00DF_GREY :Seriy
STR_00E0_WHITE :Beliy
STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Slishkom mnogo transporta v igre
STR_00E2 :{BLACK}{COMMA16}
STR_00E3 :{RED}{COMMA16}
STR_00E4_LOCATION :{BLACK}Poziciya
STR_00E5_CONTOURS :Konturi
STR_00E6_VEHICLES :Transportnie sredstva
STR_00E7_INDUSTRIES :Industrii
STR_00E8_ROUTES :Marshruti
STR_00E9_VEGETATION :Rastitelnosty
STR_00EA_OWNERS :Vladelci
STR_00EB_ROADS :{BLACK}{TINYFONT}Dorogi
STR_00C5 :{BLACK}{CROSS}
STR_00C6 :{SILVER}{CROSS}
STR_00C7_QUIT :{WHITE}Vihod
STR_00C8_YES :{BLACK}Da
STR_00C9_NO :{BLACK}Net
STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Vi uvereni, chto hotite pokinuty etu igru i vernutsya k {STRING}?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
STR_00CE_4 :{BLACK}4
STR_00CF_5 :{BLACK}5
STR_00D0_NOTHING :Nichego
STR_00D1_DARK_BLUE :Temno-Siniy
STR_00D2_PALE_GREEN :Bledno-Zeleniy
STR_00D3_PINK :Rozoviy
STR_00D4_YELLOW :Zheltiy
STR_00D5_RED :Krasniy
STR_00D6_LIGHT_BLUE :Svetlo-Siniy
STR_00D7_GREEN :Zeleniy
STR_00D8_DARK_GREEN :Temno-Zeleniy
STR_00D9_BLUE :Siniy
STR_00DA_CREAM :Kremoviy
STR_00DB_MAUVE :Liloviy
STR_00DC_PURPLE :Purpurniy
STR_00DD_ORANGE :Oranjeviy
STR_00DE_BROWN :Korichneviy
STR_00DF_GREY :Seriy
STR_00E0_WHITE :Beliy
STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Slishkom mnogo transporta v igre
STR_00E2 :{BLACK}{COMMA16}
STR_00E3 :{RED}{COMMA16}
STR_00E4_LOCATION :{BLACK}Poziciya
STR_00E5_CONTOURS :Konturi
STR_00E6_VEHICLES :Transportnie sredstva
STR_00E7_INDUSTRIES :Industrii
STR_00E8_ROUTES :Marshruti
STR_00E9_VEGETATION :Rastitelnosty
STR_00EA_OWNERS :Vladelci
STR_00EB_ROADS :{BLACK}{TINYFONT}Dorogi
@@ -344,7 +343,6 @@ STR_00EB_ROADS :{BLACK}{TINYFON
############ end network gui strings
##id 0x0800
##id 0x1000

View File

@@ -1,252 +1,251 @@
##name Turkish
##ownname T<>rk<72>e
##isocode tr
##id 0x0000
STR_NULL :
STR_0001_OFF_EDGE_OF_MAP :{WHITE}Harita Siniri
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Harita sinirina <20>ok yakin
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Yetersiz Nakit- Gereken {CURRENCY}
STR_0004 :{WHITE}{CURRENCY64}
STR_0005 :{RED}{CURRENCY64}
STR_EMPTY :
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Zeminin d<>z olmasi gerekiyor
STR_0008_WAITING :{BLACK}Bekliyor: {WHITE}{STRING}
STR_0009 :{WHITE}{STRING}
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (Tasindigi Istasyon:
STR_000B :{YELLOW}{STATION})
STR_000C_ACCEPTS :{BLACK}Kabul: {WHITE}
STR_000D_ACCEPTS :{BLACK}Kabul: {GOLD}
STR_000E :
STR_000F_PASSENGERS :Yolcu
STR_0010_COAL :K<>m<EFBFBD>r
STR_0011_MAIL :Posta
STR_0012_OIL :Petrol
STR_0013_LIVESTOCK :Hayvansal <20>r<EFBFBD>nler
STR_0014_GOODS :Mam<61>l Madde
STR_0015_GRAIN :Hububat
STR_0016_WOOD :Aga<67>
STR_0017_IRON_ORE :Demir
STR_0018_STEEL :<3A>elik
STR_0019_VALUABLES :M<>cevherat
STR_001A_COPPER_ORE :Bakir
STR_001B_MAIZE :Maize
STR_001C_FRUIT :Meyve
STR_001D_DIAMONDS :Elmas
STR_001E_FOOD :Gida
STR_001F_PAPER :Kagit
STR_0020_GOLD :Altin
STR_0021_WATER :Su
STR_0022_WHEAT :Bugday
STR_0023_RUBBER :Kau<61>uk
STR_0024_SUGAR :Seker
STR_0025_TOYS :Oyuncak
STR_0026_CANDY :Sekerleme
STR_0027_COLA :Kola
STR_0028_COTTON_CANDY :Pamuk Helva
STR_0029_BUBBLES :K<>p<EFBFBD>k<EFBFBD><6B>k
STR_002A_TOFFEE :Tofita
STR_002B_BATTERIES :Pil
STR_002C_PLASTIC :Plastik
STR_002D_FIZZY_DRINKS :Fizzy Gazozu
STR_002E :
STR_002F_PASSENGER :Yolcu
STR_0030_COAL :K<>m<EFBFBD>r
STR_0031_MAIL :Posta
STR_0032_OIL :Petrol
STR_0033_LIVESTOCK :Hayvansal <20>r<EFBFBD>n
STR_0034_GOODS :Mam<61>l Madde
STR_0035_GRAIN :Hububat
STR_0036_WOOD :Aga<67>
STR_0037_IRON_ORE :Demir
STR_0038_STEEL :<3A>elik
STR_0039_VALUABLES :M<>cevherat
STR_003A_COPPER_ORE :Bakir
STR_003B_MAIZE :Maize
STR_003C_FRUIT :Meyve
STR_003D_DIAMOND :Elmas
STR_003E_FOOD :Gida
STR_003F_PAPER :Kagit
STR_0040_GOLD :Altin
STR_0041_WATER :Su
STR_0042_WHEAT :Bugday
STR_0043_RUBBER :Kau<61>uk
STR_0044_SUGAR :Seker
STR_0045_TOY :Oyuncak
STR_0046_CANDY :Tatli
STR_0047_COLA :Kola
STR_0048_COTTON_CANDY :Pamuk Helva
STR_0049_BUBBLE :K<>p<EFBFBD>k<EFBFBD><6B>k
STR_004A_TOFFEE :Tofita
STR_004B_BATTERY :Pil
STR_004C_PLASTIC :Plastik
STR_004D_FIZZY_DRINK :Fizzy Gazozu
STR_004E :
STR_004F_PASSENGER :{COMMA16} yolcu
STR_0050_TON_OF_COAL :{COMMA16} ton k<>m<EFBFBD>r
STR_0051_BAG_OF_MAIL :{COMMA16} <20>anta posta
STR_0052_OF_OIL :{VOLUME} petrol
STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} adet hayvansal <20>r<EFBFBD>n
STR_0054_CRATE_OF_GOODS :{COMMA16} kasa mam<61>l madde
STR_0055_TON_OF_GRAIN :{COMMA16} ton hububat
STR_0056_TON_OF_WOOD :{COMMA16} ton aga<67>
STR_0057_TON_OF_IRON_ORE :{COMMA16} ton demir
STR_0058_TON_OF_STEEL :{COMMA16} ton <20>elik
STR_0059_BAG_OF_VALUABLES :{COMMA16} <20>anta m<>cevherat
STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton bakir
STR_005B_TON_OF_MAIZE :{COMMA16} ton misir
STR_005C_TON_OF_FRUIT :{COMMA16} ton meyve
STR_005D_BAG_OF_DIAMONDS :{COMMA16} <20>anta elmas
STR_005E_TON_OF_FOOD :{COMMA16} ton gida
STR_005F_TON_OF_PAPER :{COMMA16} ton kagit
STR_0060_BAG_OF_GOLD :{COMMA16} <20>anta altin
STR_0061_OF_WATER :{VOLUME} su
STR_0062_TON_OF_WHEAT :{COMMA16} ton bugday
STR_0063_OF_RUBBER :{VOLUME} of rubber
STR_0064_TON_OF_SUGAR :{COMMA16} ton seker
STR_0065_TOY :{COMMA16} oyuncak
STR_0066_BAG_OF_CANDY :{COMMA16} <20>anta sekerleme
STR_0067_OF_COLA :{VOLUME} kola
STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton pamuk helva
STR_0069_BUBBLE :{COMMA16} k<>p<EFBFBD>k<EFBFBD><6B>k
STR_006A_TON_OF_TOFFEE :{COMMA16} ton tofita
STR_006B_BATTERY :{COMMA16} pil
STR_006C_OF_PLASTIC :{VOLUME} plastik
STR_006D_FIZZY_DRINK :{COMMA16} fizzy gazozu
STR_006E :
STR_006F_PASSENGERS :{COMMA16} yolcu
STR_0070_TONS_OF_COAL :{COMMA16} ton k<>m<EFBFBD>r
STR_0071_BAGS_OF_MAIL :{COMMA16} <20>anta posta
STR_0072_OF_OIL :{VOLUME} petrol
STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} adet hayvansal <20>r<EFBFBD>n
STR_0074_CRATES_OF_GOODS :{COMMA16} kasa mam<61>l madde
STR_0075_TONS_OF_GRAIN :{COMMA16} ton hububat
STR_0076_TONS_OF_WOOD :{COMMA16} ton aga<67>
STR_0077_TONS_OF_IRON_ORE :{COMMA16} ton demir
STR_0078_TONS_OF_STEEL :{COMMA16} ton <20>elik
STR_0079_BAGS_OF_VALUABLES :{COMMA16} <20>anta m<>cevherat
STR_007A_TONS_OF_COPPER_ORE :{COMMA16} ton bakir
STR_007B_TONS_OF_MAIZE :{COMMA16} ton misir
STR_007C_TONS_OF_FRUIT :{COMMA16} ton meyve
STR_007D_BAGS_OF_DIAMONDS :{COMMA16} <20>anta elmas
STR_007E_TONS_OF_FOOD :{COMMA16} ton gida
STR_007F_TONS_OF_PAPER :{COMMA16} ton kagit
STR_0080_BAGS_OF_GOLD :{COMMA16} <20>anta altin
STR_0081_OF_WATER :{VOLUME} su
STR_0082_TONS_OF_WHEAT :{COMMA16} ton bugday
STR_0083_OF_RUBBER :{VOLUME} kau<61>uk
STR_0084_TONS_OF_SUGAR :{COMMA16} ton seker
STR_0085_TOYS :{COMMA16} oyuncak
STR_0086_BAGS_OF_CANDY :{COMMA16} <20>anta sekerleme
STR_0087_OF_COLA :{VOLUME} kola
STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} ton pamuk helva
STR_0089_BUBBLES :{COMMA16} k<>p<EFBFBD>k<EFBFBD><6B>k
STR_008A_TONS_OF_TOFFEE :{COMMA16} ton tofita
STR_008B_BATTERIES :{COMMA16} pil
STR_008C_OF_PLASTIC :{VOLUME} plastik
STR_008D_FIZZY_DRINKS :{COMMA16} fizzy gazozu
STR_008E :
STR_008F_PS :{TINYFONT}YL
STR_0090_CL :{TINYFONT}K<>
STR_0091_ML :{TINYFONT}PO
STR_0092_OL :{TINYFONT}PE
STR_0093_LV :{TINYFONT}H<>
STR_0094_GD :{TINYFONT}MM
STR_0095_GR :{TINYFONT}HB
STR_0096_WD :{TINYFONT}AG
STR_0097_OR :{TINYFONT}OR
STR_0098_ST :{TINYFONT}<7D>E
STR_0099_VL :{TINYFONT}M<>
STR_009A_CO :{TINYFONT}KO
STR_009B_MZ :{TINYFONT}MI
STR_009C_FT :{TINYFONT}FT
STR_009D_DM :{TINYFONT}DM
STR_009E_FD :{TINYFONT}GI
STR_009F_PR :{TINYFONT}KA
STR_00A0_GD :{TINYFONT}MM
STR_00A1_WR :{TINYFONT}WR
STR_00A2_WH :{TINYFONT}BU
STR_00A3_RB :{TINYFONT}KU
STR_00A4_SG :{TINYFONT}SG
STR_00A5_TY :{TINYFONT}OY
STR_00A6_SW :{TINYFONT}TA
STR_00A7_CL :{TINYFONT}K<>
STR_00A8_CF :{TINYFONT}PH
STR_00A9_BU :{TINYFONT}KP
STR_00AA_TF :{TINYFONT}TF
STR_00AB_BA :{TINYFONT}PI
STR_00AC_PL :{TINYFONT}PL
STR_00AD_FZ :{TINYFONT}FG
STR_00AE :{WHITE}{DATE_SHORT}
STR_00AF :{WHITE}{DATE_LONG}
STR_00B0_MAP :{WHITE}Map - {STRING}
STR_00B1_GAME_OPTIONS :{WHITE}Oyun Se<53>enekleri
STR_00B2_MESSAGE :{YELLOW}Mesaj
STR_00B3_MESSAGE_FROM :{YELLOW}Mesaj {STRING}
STR_00B4_CAN_T_DO_THIS :{WHITE}Bunu yapamazsiniz..
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Bu b<>lgeyi temizleyemezsiniz...
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Orjinal telif hakki {COPYRIGHT} 1995 Chris Sawyer, T<>m haklari saklidir
STR_00B7_VERSION :{BLACK}OpenTTD versiyon {REV}
STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2004 OpenTTD ekibi
STR_NULL :
STR_0001_OFF_EDGE_OF_MAP :{WHITE}Harita Siniri
STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP :{WHITE}Harita sinirina <20>ok yakin
STR_0003_NOT_ENOUGH_CASH_REQUIRES :{WHITE}Yetersiz Nakit- Gereken {CURRENCY}
STR_0004 :{WHITE}{CURRENCY64}
STR_0005 :{RED}{CURRENCY64}
STR_EMPTY :
STR_0007_FLAT_LAND_REQUIRED :{WHITE}Zeminin d<>z olmasi gerekiyor
STR_0008_WAITING :{BLACK}Bekliyor: {WHITE}{STRING}
STR_0009 :{WHITE}{STRING}
STR_000A_EN_ROUTE_FROM :{WHITE}{STRING}{YELLOW} (Tasindigi Istasyon:
STR_000B :{YELLOW}{STATION})
STR_000C_ACCEPTS :{BLACK}Kabul: {WHITE}
STR_000D_ACCEPTS :{BLACK}Kabul: {GOLD}
STR_000E :
STR_000F_PASSENGERS :Yolcu
STR_0010_COAL :K<>m<EFBFBD>r
STR_0011_MAIL :Posta
STR_0012_OIL :Petrol
STR_0013_LIVESTOCK :Hayvansal <20>r<EFBFBD>nler
STR_0014_GOODS :Mam<61>l Madde
STR_0015_GRAIN :Hububat
STR_0016_WOOD :Aga<67>
STR_0017_IRON_ORE :Demir
STR_0018_STEEL :<3A>elik
STR_0019_VALUABLES :M<>cevherat
STR_001A_COPPER_ORE :Bakir
STR_001B_MAIZE :Maize
STR_001C_FRUIT :Meyve
STR_001D_DIAMONDS :Elmas
STR_001E_FOOD :Gida
STR_001F_PAPER :Kagit
STR_0020_GOLD :Altin
STR_0021_WATER :Su
STR_0022_WHEAT :Bugday
STR_0023_RUBBER :Kau<61>uk
STR_0024_SUGAR :Seker
STR_0025_TOYS :Oyuncak
STR_0026_CANDY :Sekerleme
STR_0027_COLA :Kola
STR_0028_COTTON_CANDY :Pamuk Helva
STR_0029_BUBBLES :K<>p<EFBFBD>k<EFBFBD><6B>k
STR_002A_TOFFEE :Tofita
STR_002B_BATTERIES :Pil
STR_002C_PLASTIC :Plastik
STR_002D_FIZZY_DRINKS :Fizzy Gazozu
STR_002E :
STR_002F_PASSENGER :Yolcu
STR_0030_COAL :K<>m<EFBFBD>r
STR_0031_MAIL :Posta
STR_0032_OIL :Petrol
STR_0033_LIVESTOCK :Hayvansal <20>r<EFBFBD>n
STR_0034_GOODS :Mam<61>l Madde
STR_0035_GRAIN :Hububat
STR_0036_WOOD :Aga<67>
STR_0037_IRON_ORE :Demir
STR_0038_STEEL :<3A>elik
STR_0039_VALUABLES :M<>cevherat
STR_003A_COPPER_ORE :Bakir
STR_003B_MAIZE :Maize
STR_003C_FRUIT :Meyve
STR_003D_DIAMOND :Elmas
STR_003E_FOOD :Gida
STR_003F_PAPER :Kagit
STR_0040_GOLD :Altin
STR_0041_WATER :Su
STR_0042_WHEAT :Bugday
STR_0043_RUBBER :Kau<61>uk
STR_0044_SUGAR :Seker
STR_0045_TOY :Oyuncak
STR_0046_CANDY :Tatli
STR_0047_COLA :Kola
STR_0048_COTTON_CANDY :Pamuk Helva
STR_0049_BUBBLE :K<>p<EFBFBD>k<EFBFBD><6B>k
STR_004A_TOFFEE :Tofita
STR_004B_BATTERY :Pil
STR_004C_PLASTIC :Plastik
STR_004D_FIZZY_DRINK :Fizzy Gazozu
STR_004E :
STR_004F_PASSENGER :{COMMA16} yolcu
STR_0050_TON_OF_COAL :{COMMA16} ton k<>m<EFBFBD>r
STR_0051_BAG_OF_MAIL :{COMMA16} <20>anta posta
STR_0052_OF_OIL :{VOLUME} petrol
STR_0053_ITEM_OF_LIVESTOCK :{COMMA16} adet hayvansal <20>r<EFBFBD>n
STR_0054_CRATE_OF_GOODS :{COMMA16} kasa mam<61>l madde
STR_0055_TON_OF_GRAIN :{COMMA16} ton hububat
STR_0056_TON_OF_WOOD :{COMMA16} ton aga<67>
STR_0057_TON_OF_IRON_ORE :{COMMA16} ton demir
STR_0058_TON_OF_STEEL :{COMMA16} ton <20>elik
STR_0059_BAG_OF_VALUABLES :{COMMA16} <20>anta m<>cevherat
STR_005A_TON_OF_COPPER_ORE :{COMMA16} ton bakir
STR_005B_TON_OF_MAIZE :{COMMA16} ton misir
STR_005C_TON_OF_FRUIT :{COMMA16} ton meyve
STR_005D_BAG_OF_DIAMONDS :{COMMA16} <20>anta elmas
STR_005E_TON_OF_FOOD :{COMMA16} ton gida
STR_005F_TON_OF_PAPER :{COMMA16} ton kagit
STR_0060_BAG_OF_GOLD :{COMMA16} <20>anta altin
STR_0061_OF_WATER :{VOLUME} su
STR_0062_TON_OF_WHEAT :{COMMA16} ton bugday
STR_0063_OF_RUBBER :{VOLUME} of rubber
STR_0064_TON_OF_SUGAR :{COMMA16} ton seker
STR_0065_TOY :{COMMA16} oyuncak
STR_0066_BAG_OF_CANDY :{COMMA16} <20>anta sekerleme
STR_0067_OF_COLA :{VOLUME} kola
STR_0068_TON_OF_COTTON_CANDY :{COMMA16} ton pamuk helva
STR_0069_BUBBLE :{COMMA16} k<>p<EFBFBD>k<EFBFBD><6B>k
STR_006A_TON_OF_TOFFEE :{COMMA16} ton tofita
STR_006B_BATTERY :{COMMA16} pil
STR_006C_OF_PLASTIC :{VOLUME} plastik
STR_006D_FIZZY_DRINK :{COMMA16} fizzy gazozu
STR_006E :
STR_006F_PASSENGERS :{COMMA16} yolcu
STR_0070_TONS_OF_COAL :{COMMA16} ton k<>m<EFBFBD>r
STR_0071_BAGS_OF_MAIL :{COMMA16} <20>anta posta
STR_0072_OF_OIL :{VOLUME} petrol
STR_0073_ITEMS_OF_LIVESTOCK :{COMMA16} adet hayvansal <20>r<EFBFBD>n
STR_0074_CRATES_OF_GOODS :{COMMA16} kasa mam<61>l madde
STR_0075_TONS_OF_GRAIN :{COMMA16} ton hububat
STR_0076_TONS_OF_WOOD :{COMMA16} ton aga<67>
STR_0077_TONS_OF_IRON_ORE :{COMMA16} ton demir
STR_0078_TONS_OF_STEEL :{COMMA16} ton <20>elik
STR_0079_BAGS_OF_VALUABLES :{COMMA16} <20>anta m<>cevherat
STR_007A_TONS_OF_COPPER_ORE :{COMMA16} ton bakir
STR_007B_TONS_OF_MAIZE :{COMMA16} ton misir
STR_007C_TONS_OF_FRUIT :{COMMA16} ton meyve
STR_007D_BAGS_OF_DIAMONDS :{COMMA16} <20>anta elmas
STR_007E_TONS_OF_FOOD :{COMMA16} ton gida
STR_007F_TONS_OF_PAPER :{COMMA16} ton kagit
STR_0080_BAGS_OF_GOLD :{COMMA16} <20>anta altin
STR_0081_OF_WATER :{VOLUME} su
STR_0082_TONS_OF_WHEAT :{COMMA16} ton bugday
STR_0083_OF_RUBBER :{VOLUME} kau<61>uk
STR_0084_TONS_OF_SUGAR :{COMMA16} ton seker
STR_0085_TOYS :{COMMA16} oyuncak
STR_0086_BAGS_OF_CANDY :{COMMA16} <20>anta sekerleme
STR_0087_OF_COLA :{VOLUME} kola
STR_0088_TONS_OF_COTTON_CANDY :{COMMA16} ton pamuk helva
STR_0089_BUBBLES :{COMMA16} k<>p<EFBFBD>k<EFBFBD><6B>k
STR_008A_TONS_OF_TOFFEE :{COMMA16} ton tofita
STR_008B_BATTERIES :{COMMA16} pil
STR_008C_OF_PLASTIC :{VOLUME} plastik
STR_008D_FIZZY_DRINKS :{COMMA16} fizzy gazozu
STR_008E :
STR_008F_PS :{TINYFONT}YL
STR_0090_CL :{TINYFONT}K<>
STR_0091_ML :{TINYFONT}PO
STR_0092_OL :{TINYFONT}PE
STR_0093_LV :{TINYFONT}H<>
STR_0094_GD :{TINYFONT}MM
STR_0095_GR :{TINYFONT}HB
STR_0096_WD :{TINYFONT}AG
STR_0097_OR :{TINYFONT}OR
STR_0098_ST :{TINYFONT}<7D>E
STR_0099_VL :{TINYFONT}M<>
STR_009A_CO :{TINYFONT}KO
STR_009B_MZ :{TINYFONT}MI
STR_009C_FT :{TINYFONT}FT
STR_009D_DM :{TINYFONT}DM
STR_009E_FD :{TINYFONT}GI
STR_009F_PR :{TINYFONT}KA
STR_00A0_GD :{TINYFONT}MM
STR_00A1_WR :{TINYFONT}WR
STR_00A2_WH :{TINYFONT}BU
STR_00A3_RB :{TINYFONT}KU
STR_00A4_SG :{TINYFONT}SG
STR_00A5_TY :{TINYFONT}OY
STR_00A6_SW :{TINYFONT}TA
STR_00A7_CL :{TINYFONT}K<>
STR_00A8_CF :{TINYFONT}PH
STR_00A9_BU :{TINYFONT}KP
STR_00AA_TF :{TINYFONT}TF
STR_00AB_BA :{TINYFONT}PI
STR_00AC_PL :{TINYFONT}PL
STR_00AD_FZ :{TINYFONT}FG
STR_00AE :{WHITE}{DATE_SHORT}
STR_00AF :{WHITE}{DATE_LONG}
STR_00B0_MAP :{WHITE}Map - {STRING}
STR_00B1_GAME_OPTIONS :{WHITE}Oyun Se<53>enekleri
STR_00B2_MESSAGE :{YELLOW}Mesaj
STR_00B3_MESSAGE_FROM :{YELLOW}Mesaj {STRING}
STR_00B4_CAN_T_DO_THIS :{WHITE}Bunu yapamazsiniz..
STR_00B5_CAN_T_CLEAR_THIS_AREA :{WHITE}Bu b<>lgeyi temizleyemezsiniz...
STR_00B6_ORIGINAL_COPYRIGHT :{BLACK}Orjinal telif hakki {COPYRIGHT} 1995 Chris Sawyer, T<>m haklari saklidir
STR_00B7_VERSION :{BLACK}OpenTTD versiyon {REV}
STR_00BA_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-2004 OpenTTD ekibi
STR_00C5 :{BLACK}{CROSS}
STR_00C6 :{SILVER}{CROSS}
STR_00C7_QUIT :{WHITE}<7D>ik
STR_00C8_YES :{BLACK}Evet
STR_00C9_NO :{BLACK}Hayir
STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Oyunu sonlandirip {STRING}'a d<>nmek istediginizden emin misiniz?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
STR_00CE_4 :{BLACK}4
STR_00CF_5 :{BLACK}5
STR_00D0_NOTHING :Hi<48>
STR_00D1_DARK_BLUE :Koyu Mavi
STR_00D2_PALE_GREEN :A<>ik Yesil
STR_00D3_PINK :Pembe
STR_00D4_YELLOW :Sari
STR_00D5_RED :Kirmizi
STR_00D6_LIGHT_BLUE :A<>ik Mavi
STR_00D7_GREEN :Yesil
STR_00D8_DARK_GREEN :Koyu Yesil
STR_00D9_BLUE :Mavi
STR_00DA_CREAM :Krem
STR_00DB_MAUVE :Leylak
STR_00DC_PURPLE :Mor
STR_00DD_ORANGE :Turuncu
STR_00DE_BROWN :Kahverengi
STR_00DF_GREY :Gri
STR_00E0_WHITE :Beyaz
STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Oyunda <20>ok fazla vasita var
STR_00E2 :{BLACK}{COMMA16}
STR_00E3 :{RED}{COMMA16}
STR_00E4_LOCATION :{BLACK}Konum
STR_00E5_CONTOURS :Dis Hatlar
STR_00E6_VEHICLES :Vasitalar
STR_00E7_INDUSTRIES :End<6E>striler
STR_00E8_ROUTES :Yollar
STR_00E9_VEGETATION :Bitkiler
STR_00EA_OWNERS :Sahipler
STR_00EB_ROADS :{BLACK}{TINYFONT}Yollar
STR_00EC_RAILROADS :{BLACK}{TINYFONT}Demiryollari
STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Istasyon/Havaalani/Liman
STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Binalar/End<6E>striler
STR_00EF_VEHICLES :{BLACK}{TINYFONT}Vasitalar
STR_00F0_100M :{BLACK}{TINYFONT}100m
STR_00F1_200M :{BLACK}{TINYFONT}200m
STR_00F2_300M :{BLACK}{TINYFONT}300m
STR_00F3_400M :{BLACK}{TINYFONT}400m
STR_00F4_500M :{BLACK}{TINYFONT}500m
STR_00F5_TRAINS :{BLACK}{TINYFONT}Trenler
STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Yol Tasitlari
STR_00F7_SHIPS :{BLACK}{TINYFONT}Gemiler
STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Hava Tasitlari
STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Nakil Rotalari
STR_00FA_COAL_MINE :{BLACK}{TINYFONT}K<>m<EFBFBD>r Madeni
STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Enerji Santrali
STR_00FC_FOREST :{BLACK}{TINYFONT}Orman
STR_00FD_SAWMILL :{BLACK}{TINYFONT}Bi<42>ki Fabrikasi
STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Petrol Rafinerisi
STR_00C5 :{BLACK}{CROSS}
STR_00C6 :{SILVER}{CROSS}
STR_00C7_QUIT :{WHITE}<7D>ik
STR_00C8_YES :{BLACK}Evet
STR_00C9_NO :{BLACK}Hayir
STR_00CA_ARE_YOU_SURE_YOU_WANT_TO :{YELLOW}Oyunu sonlandirip {STRING}'a d<>nmek istediginizden emin misiniz?
STR_00CB_1 :{BLACK}1
STR_00CC_2 :{BLACK}2
STR_00CD_3 :{BLACK}3
STR_00CE_4 :{BLACK}4
STR_00CF_5 :{BLACK}5
STR_00D0_NOTHING :Hi<48>
STR_00D1_DARK_BLUE :Koyu Mavi
STR_00D2_PALE_GREEN :A<>ik Yesil
STR_00D3_PINK :Pembe
STR_00D4_YELLOW :Sari
STR_00D5_RED :Kirmizi
STR_00D6_LIGHT_BLUE :A<>ik Mavi
STR_00D7_GREEN :Yesil
STR_00D8_DARK_GREEN :Koyu Yesil
STR_00D9_BLUE :Mavi
STR_00DA_CREAM :Krem
STR_00DB_MAUVE :Leylak
STR_00DC_PURPLE :Mor
STR_00DD_ORANGE :Turuncu
STR_00DE_BROWN :Kahverengi
STR_00DF_GREY :Gri
STR_00E0_WHITE :Beyaz
STR_00E1_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Oyunda <20>ok fazla vasita var
STR_00E2 :{BLACK}{COMMA16}
STR_00E3 :{RED}{COMMA16}
STR_00E4_LOCATION :{BLACK}Konum
STR_00E5_CONTOURS :Dis Hatlar
STR_00E6_VEHICLES :Vasitalar
STR_00E7_INDUSTRIES :End<6E>striler
STR_00E8_ROUTES :Yollar
STR_00E9_VEGETATION :Bitkiler
STR_00EA_OWNERS :Sahipler
STR_00EB_ROADS :{BLACK}{TINYFONT}Yollar
STR_00EC_RAILROADS :{BLACK}{TINYFONT}Demiryollari
STR_00ED_STATIONS_AIRPORTS_DOCKS :{BLACK}{TINYFONT}Istasyon/Havaalani/Liman
STR_00EE_BUILDINGS_INDUSTRIES :{BLACK}{TINYFONT}Binalar/End<6E>striler
STR_00EF_VEHICLES :{BLACK}{TINYFONT}Vasitalar
STR_00F0_100M :{BLACK}{TINYFONT}100m
STR_00F1_200M :{BLACK}{TINYFONT}200m
STR_00F2_300M :{BLACK}{TINYFONT}300m
STR_00F3_400M :{BLACK}{TINYFONT}400m
STR_00F4_500M :{BLACK}{TINYFONT}500m
STR_00F5_TRAINS :{BLACK}{TINYFONT}Trenler
STR_00F6_ROAD_VEHICLES :{BLACK}{TINYFONT}Yol Tasitlari
STR_00F7_SHIPS :{BLACK}{TINYFONT}Gemiler
STR_00F8_AIRCRAFT :{BLACK}{TINYFONT}Hava Tasitlari
STR_00F9_TRANSPORT_ROUTES :{BLACK}{TINYFONT}Nakil Rotalari
STR_00FA_COAL_MINE :{BLACK}{TINYFONT}K<>m<EFBFBD>r Madeni
STR_00FB_POWER_STATION :{BLACK}{TINYFONT}Enerji Santrali
STR_00FC_FOREST :{BLACK}{TINYFONT}Orman
STR_00FD_SAWMILL :{BLACK}{TINYFONT}Bi<42>ki Fabrikasi
STR_00FE_OIL_REFINERY :{BLACK}{TINYFONT}Petrol Rafinerisi
@@ -387,7 +386,6 @@ STR_00FE_OIL_REFINERY :{BLACK}{TINYFON
############ end network gui strings
##id 0x0800
##id 0x1000

587
langs.dsp
View File

@@ -1,311 +1,276 @@
# Microsoft Developer Studio Project File - Name="langs" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Generic Project" 0x010a
CFG=langs - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "langs.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "langs.mak" CFG="langs - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "langs - Win32 Debug" (based on "Win32 (x86) Generic Project")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
MTL=midl.exe
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "langs___Win32_Debug"
# PROP BASE Intermediate_Dir "langs___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir ""
# PROP Target_Dir ""
# Begin Target
# Name "langs - Win32 Debug"
# Begin Source File
SOURCE=.\lang\american.txt
# Begin Custom Build
InputPath=.\lang\american.txt
"lang\american.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\american.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\brazilian_portuguese.txt
# Begin Custom Build
InputPath=.\lang\brazilian_portuguese.txt
"lang\brazilian_portuguese.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\brazilian_portuguese.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\catalan.txt
# Begin Custom Build
InputPath=.\lang\catalan.txt
"lang\catalan.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\catalan.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\czech.txt
# Begin Custom Build
InputPath=.\lang\czech.txt
"lang\czech.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\czech.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\danish.txt
# Begin Custom Build
InputPath=.\lang\danish.txt
"lang\danish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\danish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\dutch.txt
# Begin Custom Build
InputPath=.\lang\dutch.txt
"lang\dutch.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\dutch.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\english.txt
# Begin Custom Build
InputPath=.\lang\english.txt
"lang\english.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\finnish.txt
# Begin Custom Build
InputPath=.\lang\finnish.txt
"lang\finnish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\finnish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\french.txt
# Begin Custom Build
InputPath=.\lang\french.txt
"lang\french.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\french.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\galician.txt
# Begin Custom Build
InputPath=.\lang\galician.txt
"lang\galician.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\galician.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\german.txt
# Begin Custom Build
InputPath=.\lang\german.txt
"lang\german.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\german.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\hungarian.txt
# Begin Custom Build
InputPath=.\lang\hungarian.txt
"lang\hungarian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\hungarian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\icelandic.txt
# Begin Custom Build
InputPath=.\lang\icelandic.txt
"lang\icelandic.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\icelandic.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\italian.txt
# Begin Custom Build
InputPath=.\lang\italian.txt
"lang\italian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\italian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\latvian.txt
# Begin Custom Build
InputPath=.\lang\latvian.txt
"lang\latvian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\latvian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\lithuanian.txt
# Begin Custom Build
InputPath=.\lang\lithuanian.txt
"lang\lithuanian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\lithuanian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\norwegian.txt
# Begin Custom Build
InputPath=.\lang\norwegian.txt
"lang\norwegian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\norwegian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\origveh.txt
# Begin Custom Build
InputPath=.\lang\origveh.txt
"lang\origveh.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\origveh.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\polish.txt
# Begin Custom Build
InputPath=.\lang\polish.txt
"lang\polish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\polish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\portuguese.txt
# Begin Custom Build
InputPath=.\lang\portuguese.txt
"lang\portuguese.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\portuguese.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\romanian.txt
# Begin Custom Build
InputPath=.\lang\romanian.txt
"lang\romanian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\romanian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\slovak.txt
# Begin Custom Build
InputPath=.\lang\slovak.txt
"lang\slovak.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\slovak.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\spanish.txt
# Begin Custom Build
InputPath=.\lang\spanish.txt
"lang\spanish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\spanish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\swedish.txt
# Begin Custom Build
InputPath=.\lang\swedish.txt
"lang\swedish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\swedish.txt
# End Custom Build
# End Source File
# End Target
# End Project
# Microsoft Developer Studio Project File - Name="langs" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Generic Project" 0x010a
CFG=langs - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "langs.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "langs.mak" CFG="langs - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "langs - Win32 Debug" (based on "Win32 (x86) Generic Project")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
MTL=midl.exe
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "langs___Win32_Debug"
# PROP BASE Intermediate_Dir "langs___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir ""
# PROP Target_Dir ""
# Begin Target
# Name "langs - Win32 Debug"
# Begin Source File
SOURCE=.\lang\american.txt
# Begin Custom Build
InputPath=.\lang\american.txt
"lang\american.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\american.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\catalan.txt
# Begin Custom Build
InputPath=.\lang\catalan.txt
"lang\catalan.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\catalan.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\czech.txt
# Begin Custom Build
InputPath=.\lang\czech.txt
"lang\czech.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\czech.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\danish.txt
# Begin Custom Build
InputPath=.\lang\danish.txt
"lang\danish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\danish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\dutch.txt
# Begin Custom Build
InputPath=.\lang\dutch.txt
"lang\dutch.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\dutch.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\english.txt
# Begin Custom Build
InputPath=.\lang\english.txt
"lang\english.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\finnish.txt
# Begin Custom Build
InputPath=.\lang\finnish.txt
"lang\finnish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\finnish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\french.txt
# Begin Custom Build
InputPath=.\lang\french.txt
"lang\french.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\french.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\galician.txt
# Begin Custom Build
InputPath=.\lang\galician.txt
"lang\galician.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\galician.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\german.txt
# Begin Custom Build
InputPath=.\lang\german.txt
"lang\german.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\german.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\hungarian.txt
# Begin Custom Build
InputPath=.\lang\hungarian.txt
"lang\hungarian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\hungarian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\icelandic.txt
# Begin Custom Build
InputPath=.\lang\icelandic.txt
"lang\icelandic.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\icelandic.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\italian.txt
# Begin Custom Build
InputPath=.\lang\italian.txt
"lang\italian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\italian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\norwegian.txt
# Begin Custom Build
InputPath=.\lang\norwegian.txt
"lang\norwegian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\norwegian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\origveh.txt
# Begin Custom Build
InputPath=.\lang\origveh.txt
"lang\origveh.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\origveh.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\polish.txt
# Begin Custom Build
InputPath=.\lang\polish.txt
"lang\polish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\polish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\portuguese.txt
# Begin Custom Build
InputPath=.\lang\portuguese.txt
"lang\portuguese.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\portuguese.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\romanian.txt
# Begin Custom Build
InputPath=.\lang\romanian.txt
"lang\romanian.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\romanian.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\slovak.txt
# Begin Custom Build
InputPath=.\lang\slovak.txt
"lang\slovak.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\slovak.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\spanish.txt
# Begin Custom Build
InputPath=.\lang\spanish.txt
"lang\spanish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\spanish.txt
# End Custom Build
# End Source File
# Begin Source File
SOURCE=.\lang\swedish.txt
# Begin Custom Build
InputPath=.\lang\swedish.txt
"lang\swedish.lng" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
strgen\debug\strgen.exe lang\swedish.txt
# End Custom Build
# End Source File
# End Target
# End Project

View File

@@ -1,331 +1,295 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="langs"
ProjectGUID="{0F066B23-18DF-4284-8265-F4A5E7E3B966}"
RootNamespace="langs"
SccProjectName=""
SccLocalPath=""
Keyword="MakeFileProj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="."
IntermediateDirectory="."
ConfigurationType="10"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName="./langs.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"
Description="Generating strings.h"
CommandLine="strgen\debug\strgen.exe"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\lang\american.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating american language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\american.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\brazilian_portuguese.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating brazilian_portuguese language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\brazilian_portuguese.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\catalan.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating catalan language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\catalan.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\czech.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating czech language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\czech.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\danish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating danish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\danish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\dutch.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating dutch language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\dutch.lng"/>
</FileConfiguration>
</File>
<File
RelativePath="lang\english.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating english language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\english.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\finnish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating finnish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\finnish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\french.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating french language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\french.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\galician.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating galician language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\galician.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\german.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating german language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\german.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\hungarian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating hungarian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\hungarian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\icelandic.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating icelandic language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\icelandic.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\italian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating italian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\italian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\latvian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating latvian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\latvian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\lithuanian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating lithuanian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\lithuanian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\norwegian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating norwegian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\norwegian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\origveh.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating Original Vehicle names file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\origveh.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\polish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating polish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\polish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\portuguese.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating portuguese language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\portuguese.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\romanian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating romanian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\romanian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\slovak.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating slovak language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\slovak.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\spanish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating spanish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\spanish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath="lang\swedish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating swedish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\swedish.lng"/>
</FileConfiguration>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="langs"
ProjectGUID="{0F066B23-18DF-4284-8265-F4A5E7E3B966}"
RootNamespace="langs"
SccProjectName=""
SccLocalPath=""
Keyword="MakeFileProj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="."
IntermediateDirectory="."
ConfigurationType="10"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE">
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName="./langs.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"
Description="Generating strings.h"
CommandLine="strgen\debug\strgen.exe"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\lang\american.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating american language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\american.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\catalan.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating catalan language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\catalan.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\czech.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating czech language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\czech.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\danish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating danish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\danish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\dutch.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating dutch language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\dutch.lng"/>
</FileConfiguration>
</File>
<File
RelativePath="lang\english.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating english language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\english.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\finnish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating finnish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\finnish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\french.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating french language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\french.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\galician.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating galician language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\galician.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\german.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating german language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\german.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\hungarian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating hungarian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\hungarian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\icelandic.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating icelandic language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\icelandic.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\italian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating italian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\italian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\norwegian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating norwegian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\norwegian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\origveh.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating Original Vehicle names file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\origveh.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\polish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating polish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\polish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\portuguese.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating portuguese language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\portuguese.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\romanian.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating romanian language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\romanian.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\slovak.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating slovak language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\slovak.lng"/>
</FileConfiguration>
</File>
<File
RelativePath=".\lang\spanish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating spanish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\spanish.lng"/>
</FileConfiguration>
</File>
<File
RelativePath="lang\swedish.txt">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
Description="Generating swedish language file"
CommandLine="strgen\debug\strgen.exe &quot;$(InputPath)&quot;
"
Outputs="lang\swedish.lng"/>
</FileConfiguration>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -3,6 +3,8 @@
#include "map.h"
#define MAX_INT 0x7FFFFFFF
#ifdef min
#undef min
#endif
@@ -19,11 +21,30 @@ static inline uint minu(uint a, uint b) { if (a <= b) return a; return b; }
static inline uint maxu(uint a, uint b) { if (a >= b) return a; return b; }
static inline int clamp(int a, int min, int max)
static inline int clamp(int a, int min, int max) { if (a <= min) return min; if (a >= max) return max; return a; }
static inline int clamp2(int a, int min, int max) { if (a <= min) a=min; if (a >= max) a=max; return a; }
static inline bool int32_add_overflow(int32 a, int32 b) { return (int32)(a^b)>=0 && (int32)(a^(a+b))<0; }
static inline bool int32_sub_overflow(int32 a, int32 b) { return (int32)(a^b)<0 && (int32)(a^(a-b))<0; }
static inline bool str_eq(const byte *a, const byte *b)
{
if (a <= min) return min;
if (a >= max) return max;
return a;
int i=0;
while (a[i] == b[i]) {
if (a[i] == 0)
return true;
i++;
}
return false;
}
// Will crash if strings are equal
static inline bool str_is_below(byte *a, byte *b) {
while (*a <= *b) {
if (*a < *b) return true;
a++;
b++;
}
return false;
}
@@ -47,6 +68,22 @@ static inline int64 BIGMULS(int32 a, int32 b) {
//#define IS_INSIDE_1D(x, base, size) ((x) >= (base) && (x) < (base) + (size))
#define IS_INSIDE_1D(x, base, size) ( (uint)((x) - (base)) < ((uint)(size)) )
#define LANDSCAPE_SIZE_FACTOR 1
enum {
CORRECT_Z_BITS = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7
};
#define CORRECT_Z(tileh) (CORRECT_Z_BITS & (1 << tileh))
#define TILE_ASSERT(x) assert( TILE_MASK(x) == (x) );
//#define REMADP_COORDS(x,y,z) { int t = x; x = (y-t)*2; y+=t-z; }
#define PACK_POINT(x,y) ((x) | ((y) << 16))
#define UNPACK_POINT_X(p) ((uint16)(p))
#define UNPACK_POINT_Y(p) ((uint16)(p>>16))
#define PACK_PPOINT(p) PACK_POINT((p).x, (p).y)
#define HASBIT(x,y) ((x) & (1 << (y)))
#define SETBIT(x,y) ((x) |= (1 << (y)))
@@ -74,32 +111,14 @@ extern const byte _ffb_64[128];
static inline int FindFirstBit2x64(int value)
{
/*
int i = 0;
if ( (byte) value == 0) {
i += 8;
value >>= 8;
}
return i + FIND_FIRST_BIT(value & 0x3F);
Faster ( or at least cleaner ) implementation below?
*/
if ( (byte) value == 0) {
return FIND_FIRST_BIT((value >> 8) & 0x3F) + 8;
} else {
return FIND_FIRST_BIT(value & 0x3F);
}
}
static inline int KillFirstBit2x64(int value)
{
if ( (byte) value == 0) {
return KILL_FIRST_BIT((value >> 8) & 0x3F) << 8;
} else {
return value & (KILL_FIRST_BIT(value & 0x3F)|0x3F00);
}
}
/* [min,max), strictly less than */
#define IS_BYTE_INSIDE(a,min,max) ((byte)((a)-(min)) < (byte)((max)-(min)))
@@ -126,10 +145,13 @@ static inline int KillFirstBit2x64(int value)
for(_i=0; _b!=0; _i++,_b>>=1) \
if (_b&1)
#define assert_array(i,j) assert(i < lengthof(j))
#define abs myabs
static inline int intxchg_(int *a, int b) { int t = *a; *a = b; return t; }
#define intxchg(a,b) intxchg_(&(a), (b))
#define intswap(a,b) ((b) = intxchg_(&(a), (b)))
static inline int myabs(int a) { if (a<0) a = -a; return a; }
@@ -138,17 +160,27 @@ static inline int64 myabs64(int64 a) { if (a<0) a = -a; return a; }
static inline void swap_byte(byte *a, byte *b) { byte t = *a; *a = *b; *b = t; }
static inline void swap_uint16(uint16 *a, uint16 *b) { uint16 t = *a; *a = *b; *b = t; }
static inline void swap_int16(int16 *a, int16 *b) { int16 t = *a; *a = *b; *b = t; }
static inline void swap_int32(int32 *a, int32 *b) { int32 t = *a; *a = *b; *b = t; }
static inline void swap_tile(TileIndex *a, TileIndex *b) { TileIndex t = *a; *a = *b; *b = t; }
#if defined(TTD_LITTLE_ENDIAN)
# define READ_LE_UINT16(b) (*(const uint16*)(b))
# define ADD_WORD(x) (x)&0xFF, ((x) >> 8)&0xFF
# define ADD_DWORD(x) (x)&0xFF, ((x) >> 8)&0xFF, ((x) >> 16)&0xFF, ((x) >> 24)&0xFF
#elif defined(TTD_BIG_ENDIAN)
static inline uint16 READ_LE_UINT16(const void *b) {
return ((const byte*)b)[0] + (((const byte*)b)[1] << 8);
}
# define ADD_WORD(x) ((x) >> 8)&0xFF, (x)&0xFF
# define ADD_DWORD(x) ((x) >> 24)&0xFF, ((x) >> 16)&0xFF, ((x) >> 8)&0xFF, (x)&0xFF
#endif
static inline void WRITE_LE_UINT16(void *b, uint16 x) {
((byte*)b)[0] = (byte)x;
((byte*)b)[1] = (byte)(x >> 8);
}
#define MAX_DETOUR 6
#endif /* MACROS_H */

View File

@@ -1,11 +1,7 @@
#include "stdafx.h"
#include "ttd.h"
#include "spritecache.h"
#include "strings.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "window.h"
#include "gui.h"
#include "viewport.h"
@@ -19,11 +15,12 @@
#include "sound.h"
#include "network.h"
#include "signs.h"
#include "waypoint.h"
#ifdef ENABLE_NETWORK
#include "network_data.h"
#include "network_client.h"
#include "network_server.h"
#endif /* ENABLE_NETWORK */
#include "table/animcursors.h"
@@ -42,11 +39,15 @@ static int _rename_what;
static byte _terraform_size = 1;
static byte _last_built_railtype;
extern void GenerateWorld(int mode, uint log_x, uint log_y);
extern void GenerateWorld(int mode);
extern void GenerateIndustries(void);
extern void GenerateTowns(void);
extern uint GetCurrentCurrencyRate(void);
extern void CcTerraform(bool success, uint tile, uint32 p1, uint32 p2);
void HandleOnEditTextCancel(void)
{
switch(_rename_what) {
@@ -59,42 +60,43 @@ void HandleOnEditTextCancel(void)
}
}
void HandleOnEditText(WindowEvent *e)
{
const char *b = e->edittext.str;
void HandleOnEditText(WindowEvent *e) {
byte *b = e->edittext.str;
int id;
_cmd_text = b;
memcpy(_decode_parameters, b, 32);
id = _rename_id;
switch (_rename_what) {
case 0: /* Rename a s sign, if string is empty, delete sign */
DoCommandP(0, id, 0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME));
switch(_rename_what) {
case 0:
// for empty string send "remove sign" parameter
DoCommandP(0, id, (*b==0)?1:0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME));
break;
case 1: /* Rename a waypoint */
if (*b == 0) return;
case 1:
if(*b == 0)
return;
DoCommandP(0, id, 0, NULL, CMD_RENAME_WAYPOINT | CMD_MSG(STR_CANT_CHANGE_WAYPOINT_NAME));
break;
#ifdef ENABLE_NETWORK
case 2: /* Speak to.. */
case 2:
// Speak to..
if (!_network_server)
SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT + (id & 0xFF), id & 0xFF, (id >> 8) & 0xFF, e->edittext.str);
else
NetworkServer_HandleChat(NETWORK_ACTION_CHAT + (id & 0xFF), id & 0xFF, (id >> 8) & 0xFF, e->edittext.str, NETWORK_SERVER_INDEX);
break;
case 3: { /* Give money, you can only give money in excess of loan */
const Player *p = DEREF_PLAYER(_current_player);
int32 money = min(p->money64 - p->current_loan, atoi(e->edittext.str) / GetCurrentCurrencyRate());
char msg[20];
case 3: {
// Give money
int32 money = atoi(e->edittext.str) / GetCurrentCurrencyRate();
char msg[100];
money = clamp(money, 0, 20000000); // Clamp between 20 million and 0
money = clamp(money, 0, 0xFFFFFF); // Clamp between 16 million and 0
// Give 'id' the money, and substract it from ourself
if (!DoCommandP(0, money, id, NULL, CMD_GIVE_MONEY | CMD_MSG(STR_INSUFFICIENT_FUNDS))) break;
if (!DoCommandP(0, money, id, NULL, CMD_GIVE_MONEY)) break;
// Inform the player of this action
snprintf(msg, sizeof(msg), "%d", money);
snprintf(msg, 100, "%d", money);
if (!_network_server)
SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_PLAYER, id + 1, msg);
@@ -102,9 +104,10 @@ void HandleOnEditText(WindowEvent *e)
NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_PLAYER, id + 1, msg, NETWORK_SERVER_INDEX);
break;
}
case 4: /* Game-Password and Company-Password */
case 4: {// Game-Password and Company-Password
SEND_COMMAND(PACKET_CLIENT_PASSWORD)(id, e->edittext.str);
break;
}
#endif /* ENABLE_NETWORK */
}
}
@@ -227,7 +230,6 @@ static void MenuClickMap(int index)
switch(index) {
case 0: ShowSmallMap(); break;
case 1: ShowExtraViewPortWindow(); break;
case 2: ShowSignList(); break;
}
}
@@ -241,8 +243,7 @@ static void MenuClickScenMap(int index)
switch(index) {
case 0: ShowSmallMap(); break;
case 1: ShowExtraViewPortWindow(); break;
case 2: ShowSignList(); break;
case 3: ShowTownDirectory(); break;
case 2: ShowTownDirectory(); break;
}
}
@@ -387,14 +388,14 @@ void ShowRenameSignWindow(SignStruct *ss)
ShowQueryString(ss->str, STR_280B_EDIT_SIGN_TEXT, 30, 180, 1, 0);
}
void ShowRenameWaypointWindow(Waypoint *wp)
void ShowRenameWaypointWindow(Waypoint *cp)
{
int id = wp->index;
int id = cp - _waypoints;
/* Are we allowed to change the name of the waypoint? */
if (!CheckTileOwnership(wp->xy)) {
if (!CheckTileOwnership(cp->xy)) {
ShowErrorMessage(_error_message, STR_CANT_CHANGE_WAYPOINT_NAME,
TileX(wp->xy) * 16, TileY(wp->xy) * 16);
TileX(cp->xy) * 16, TileY(cp->xy) * 16);
return;
}
@@ -434,6 +435,7 @@ static void MenuClickNewspaper(int index)
case 0: ShowLastNewsMessage(); break;
case 1: ShowMessageOptions(); break;
case 2: ShowMessageHistory(); break;
case 3: ; /* XXX: chat not done */
}
}
@@ -773,7 +775,7 @@ static void ToolbarSaveClick(Window *w)
static void ToolbarMapClick(Window *w)
{
PopupMainToolbMenu(w, 96, 4, STR_02DE_MAP_OF_WORLD, 3);
PopupMainToolbMenu(w, 96, 4, STR_02DE_MAP_OF_WORLD, 2);
}
static void ToolbarTownClick(Window *w)
@@ -973,7 +975,7 @@ static void ToolbarMusicClick(Window *w)
static void ToolbarNewspaperClick(Window *w)
{
PopupMainToolbMenu(w, 0x1E0, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3);
PopupMainToolbMenu(w, 0x1E0, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, _newspaper_flag != 2 ? 3 : 4);
}
static void ToolbarHelpClick(Window *w)
@@ -1032,7 +1034,7 @@ static void ToolbarScenDateForward(Window *w)
static void ToolbarScenMapTownDir(Window *w)
{
PopupMainToolbMenu(w, 0x16A, 8 | (17<<8), STR_02DE_MAP_OF_WORLD, 4);
PopupMainToolbMenu(w, 0x16A, 8 | (17<<8), STR_02DE_MAP_OF_WORLD, 3);
}
static void ToolbarScenZoomIn(Window *w)
@@ -1078,7 +1080,7 @@ static void ResetLandscape(void)
_random_seeds[0][0] = InteractiveRandom();
_random_seeds[0][1] = InteractiveRandom();
GenerateWorld(1, _patches.map_x, _patches.map_y);
GenerateWorld(1);
MarkWholeScreenDirty();
}
@@ -1100,7 +1102,6 @@ static void AskResetLandscapeWndProc(Window *w, WindowEvent *e)
case WE_PAINT:
DrawWindowWidgets(w);
DrawStringMultiCenter(90, 38, mode?STR_022D_ARE_YOU_SURE_YOU_WANT_TO:STR_GENERATE_RANDOM_LANDSCAPE , 168);
break;
case WE_CLICK:
switch(e->click.widget) {
case 3:
@@ -1121,7 +1122,6 @@ static void AskResetLandscapeWndProc(Window *w, WindowEvent *e)
break;
}
break;
}
}
@@ -1138,55 +1138,43 @@ static void AskResetLandscape(uint mode)
AllocateWindowDescFront(&_ask_reset_landscape_desc, mode);
}
// TODO - Incorporate into game itself to allow for ingame raising/lowering of
// larger chunks at the same time OR remove altogether, as we have 'level land' ?
/**
* Raise/Lower a bigger chunk of land at the same time in the editor. When
* raising get the lowest point, when lowering the highest point, and set all
* tiles in the selection to that height.
* @param tile The top-left tile where the terraforming will start
* @param mode 1 for raising, 0 for lowering land
*/
static void CommonRaiseLowerBigLand(uint tile, int mode)
{
int sizex, sizey;
int size;
byte h;
_error_message_2 = mode ? STR_0808_CAN_T_RAISE_LAND_HERE : STR_0809_CAN_T_LOWER_LAND_HERE;
_generating_world = true; // used to create green terraformed land
_generating_world = true;
// tile = TILE_FROM_XY(TileX(tile) * 16 + _tile_fract_coords.x + 8, TileY(tile) * 16 + _tile_fract_coords.y + 8);
if (_terraform_size == 1) {
DoCommandP(tile, 8, (uint32)mode, CcTerraform, CMD_TERRAFORM_LAND | CMD_AUTO | CMD_MSG(_error_message_2));
} else {
SndPlayTileFx(SND_1F_SPLAT, tile);
assert(_terraform_size != 0);
// check out for map overflows
sizex = min(MapSizeX() - TileX(tile) - 1, _terraform_size);
sizey = min(MapSizeY() - TileY(tile) - 1, _terraform_size);
if (sizex == 0 || sizey == 0) return;
size = _terraform_size;
assert(size != 0);
if (mode != 0) {
/* Raise land */
h = 15; // XXX - max height
BEGIN_TILE_LOOP(tile2, sizex, sizey, tile) {
h = 15;
BEGIN_TILE_LOOP(tile2, size, size, tile)
h = min(h, TileHeight(tile2));
} END_TILE_LOOP(tile2, sizex, sizey, tile)
END_TILE_LOOP(tile2, size, size, tile)
} else {
/* Lower land */
h = 0;
BEGIN_TILE_LOOP(tile2, sizex, sizey, tile) {
BEGIN_TILE_LOOP(tile2, size, size, tile)
h = max(h, TileHeight(tile2));
} END_TILE_LOOP(tile2, sizex, sizey, tile)
END_TILE_LOOP(tile2, size, size, tile)
}
BEGIN_TILE_LOOP(tile2, sizex, sizey, tile) {
BEGIN_TILE_LOOP(tile2, size, size, tile)
if (TileHeight(tile2) == h) {
DoCommandP(tile2, 8, (uint32)mode, NULL, CMD_TERRAFORM_LAND | CMD_AUTO);
}
} END_TILE_LOOP(tile2, sizex, sizey, tile)
END_TILE_LOOP(tile2, size, size, tile)
}
_generating_world = false;
@@ -1202,6 +1190,20 @@ static void PlaceProc_LowerBigLand(uint tile)
CommonRaiseLowerBigLand(tile, 0);
}
//void CcDemolish(bool success, uint tile, uint32 p1, uint32 p2)
//{
// if (success) {
//SndPlayTileFx(0x10, tile);
//CreateEffectVehicleAbove(TileX(tile) * 16 + 8, TileY(tile) * 16 + 8, 2, EV_DEMOLISH);
// }
//}
//void PlaceProc_Demolish(uint tile)
//{
// DoCommandP(tile, 0, 0, CcDemolish, CMD_LANDSCAPE_CLEAR | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
//}
static void PlaceProc_RockyArea(uint tile)
{
if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES))
@@ -1235,34 +1237,27 @@ static void PlaceProc_Transmitter(uint tile)
SndPlayTileFx(SND_1F_SPLAT, tile);
}
static void PlaceProc_DesertArea(TileIndex tile)
static void PlaceProc_Desert(uint tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DesertArea);
}
static void PlaceProc_WaterArea(TileIndex tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_WaterArea);
SetMapExtraBits(tile, GetMapExtraBits(tile) == 1 ? 0 : 1);
}
static const Widget _scen_edit_land_gen_widgets[] = {
{ WWT_TEXTBTN, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 169, 0, 13, STR_0223_LAND_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 7, 170, 181, 0, 13, STR_NULL, STR_STICKY_BUTTON},
{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 181, 14, 101, STR_NULL, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 153, 0, 13, STR_0223_LAND_GENERATION,STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 153, 14, 99, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 22, 43, 14, 35, 0x2B6, STR_018F_RAISE_A_CORNER_OF_LAND},
{ WWT_IMGBTN, RESIZE_NONE, 14, 44, 65, 14, 35, 0x2B7, STR_018E_LOWER_A_CORNER_OF_LAND},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 21, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 125, 135, 43, 54, STR_0224, STR_0228_INCREASE_SIZE_OF_LAND_AREA},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 125, 135, 56, 67, STR_0225, STR_0229_DECREASE_SIZE_OF_LAND_AREA},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 20, 135, 75, 86, STR_0226_RANDOM_LAND, STR_022A_GENERATE_RANDOM_LAND},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 20, 135, 88, 99, STR_0227_RESET_LAND, STR_022B_RESET_LANDSCAPE},
{ WWT_IMGBTN, RESIZE_NONE, 14, 2, 23, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC},
{ WWT_IMGBTN, RESIZE_NONE, 14, 24, 45, 14, 35, SPR_IMG_TERRAFORM_DOWN, STR_018F_RAISE_A_CORNER_OF_LAND},
{ WWT_IMGBTN, RESIZE_NONE, 14, 46, 67, 14, 35, SPR_IMG_TERRAFORM_UP, STR_018E_LOWER_A_CORNER_OF_LAND},
{ WWT_IMGBTN, RESIZE_NONE, 14, 68, 89, 14, 35, SPR_IMG_LEVEL_LAND, STR_LEVEL_LAND_TOOLTIP},
{ WWT_IMGBTN, RESIZE_NONE, 14, 90, 111, 14, 35, SPR_IMG_BUILD_CANAL, STR_CREATE_LAKE},
{ WWT_IMGBTN, RESIZE_NONE, 14, 112, 134, 14, 35, SPR_IMG_ROCKS, STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE},
{ WWT_IMGBTN, RESIZE_NONE, 14, 135, 157, 14, 35, SPR_IMG_LIGHTHOUSE_DESERT, STR_NULL}, // XXX - dynamic
{ WWT_IMGBTN, RESIZE_NONE, 14, 158, 179, 14, 35, SPR_IMG_TRANSMITTER, STR_028E_PLACE_TRANSMITTER},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 139, 149, 43, 54, STR_0224, STR_0228_INCREASE_SIZE_OF_LAND_AREA},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 139, 149, 56, 67, STR_0225, STR_0229_DECREASE_SIZE_OF_LAND_AREA},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 34, 149, 75, 86, STR_0226_RANDOM_LAND, STR_022A_GENERATE_RANDOM_LAND},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 34, 149, 88, 99, STR_0227_RESET_LAND, STR_022B_RESET_LANDSCAPE},
{ WWT_IMGBTN, RESIZE_NONE, 14, 88, 109, 14, 35, 0xFF4, STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE},
{ WWT_IMGBTN, RESIZE_NONE, 14, 110, 131, 14, 35, 0xFF5, STR_028D_PLACE_LIGHTHOUSE},
{ WWT_IMGBTN, RESIZE_NONE, 14, 132, 153, 14, 35, 0xFF6, STR_028E_PLACE_TRANSMITTER},
{ WWT_IMGBTN, RESIZE_NONE, 14, 66, 87, 14, 35, SPR_OPENTTD_BASE+68, STR_LEVEL_LAND_TOOLTIP},
{ WIDGETS_END},
};
@@ -1277,80 +1272,12 @@ static const int8 _multi_terraform_coords[][2] = {
{-28, 0},{-24, -2},{-20, -4},{-16, -6},{-12, -8},{ -8,-10},{ -4,-12},{ 0,-14},{ 4,-12},{ 8,-10},{ 12, -8},{ 16, -6},{ 20, -4},{ 24, -2},{ 28, 0},
};
// TODO - Merge with terraform_gui.c (move there) after I have cooled down at its braindeadness
// and changed OnButtonClick to include the widget as well in the function decleration. Post 0.4.0 - Darkvater
static void EditorTerraformClick_Dynamite(Window *w)
{
HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, 1, PlaceProc_DemolishArea);
}
static void EditorTerraformClick_LowerBigLand(Window *w)
{
HandlePlacePushButton(w, 5, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerBigLand);
}
static void EditorTerraformClick_RaiseBigLand(Window *w)
{
HandlePlacePushButton(w, 6, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseBigLand);
}
static void EditorTerraformClick_LevelLand(Window *w)
{
HandlePlacePushButton(w, 7, SPR_CURSOR_LEVEL_LAND, 2, PlaceProc_LevelLand);
}
static void EditorTerraformClick_WaterArea(Window *w)
{
HandlePlacePushButton(w, 8, SPR_CURSOR_CANAL, 1, PlaceProc_WaterArea);
}
static void EditorTerraformClick_RockyArea(Window *w)
{
HandlePlacePushButton(w, 9, SPR_CURSOR_ROCKY_AREA, 1, PlaceProc_RockyArea);
}
static void EditorTerraformClick_DesertLightHouse(Window *w)
{
HandlePlacePushButton(w, 10, SPR_CURSOR_LIGHTHOUSE, 1, (_opt.landscape == LT_DESERT) ? PlaceProc_DesertArea : PlaceProc_LightHouse);
}
static void EditorTerraformClick_Transmitter(Window *w)
{
HandlePlacePushButton(w, 11, SPR_CURSOR_TRANSMITTER, 1, PlaceProc_Transmitter);
}
static const uint16 _editor_terraform_keycodes[] = {
'D',
'Q',
'W',
'E',
'R',
'T',
'Y',
'U'
};
typedef void OnButtonClick(Window *w);
static OnButtonClick * const _editor_terraform_button_proc[] = {
EditorTerraformClick_Dynamite,
EditorTerraformClick_LowerBigLand,
EditorTerraformClick_RaiseBigLand,
EditorTerraformClick_LevelLand,
EditorTerraformClick_WaterArea,
EditorTerraformClick_RockyArea,
EditorTerraformClick_DesertLightHouse,
EditorTerraformClick_Transmitter
};
static void ScenEditLandGenWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE:
// XXX - lighthouse button is widget 10!! Don't forget when changing
w->widget[10].tooltips = (_opt.landscape == LT_DESERT) ? STR_028F_DEFINE_DESERT_AREA : STR_028D_PLACE_LIGHTHOUSE;
break;
switch(e->event) {
case WE_PAINT:
// XXX - lighthouse button is widget 11!! Don't forget when changing
w->widget[11].tooltips = (_opt.landscape == LT_DESERT) ? STR_028F_DEFINE_DESERT_AREA : STR_028D_PLACE_LIGHTHOUSE;
DrawWindowWidgets(w);
{
@@ -1359,71 +1286,93 @@ static void ScenEditLandGenWndProc(Window *w, WindowEvent *e)
assert(n != 0);
do {
DrawSprite(SPR_WHITE_POINT, 77 + coords[0], 55 + coords[1]);
DrawSprite(0xFEF, 77 + coords[0], 55 + coords[1]);
coords += 2;
} while (--n);
}
if (w->click_state & ( 1 << 5 | 1 << 6)) // change area-size if raise/lower corner is selected
if (_thd.window_class == WC_SCEN_LAND_GEN && (w->click_state&(1<<3|1<<4))) {
SetTileSelectSize(_terraform_size, _terraform_size);
break;
case WE_KEYPRESS: {
int i;
for (i = 0; i != lengthof(_editor_terraform_keycodes); i++) {
if (e->keypress.keycode == _editor_terraform_keycodes[i]) {
e->keypress.cont = false;
_editor_terraform_button_proc[i](w);
break;
}
}
} break;
break;
case WE_CLICK:
switch (e->click.widget) {
case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
_editor_terraform_button_proc[e->click.widget - 4](w);
switch(e->click.widget) {
case 3: /* raise corner */
HandlePlacePushButton(w, 3, ANIMCURSOR_RAISELAND, 2, PlaceProc_RaiseBigLand);
break;
case 12: case 13: { /* Increase/Decrease terraform size */
int size = (e->click.widget == 12) ? 1 : -1;
HandleButtonClick(w, e->click.widget);
case 4: /* lower corner */
HandlePlacePushButton(w, 4, ANIMCURSOR_LOWERLAND, 2, PlaceProc_LowerBigLand);
break;
case 5: /* demolish */
HandlePlacePushButton(w, 5, ANIMCURSOR_DEMOLISH, 1, PlaceProc_DemolishArea);
break;
{
int size;
case 6: /* increase terraform size */
HandleButtonClick(w, 6);
size = 1;
goto terraform_size_common;
case 7: /* decrease terraform size */
HandleButtonClick(w, 7);
size = -1;
terraform_size_common:;
size += _terraform_size;
if (!IS_INT_INSIDE(size, 1, 8 + 1)) return;
if (!IS_INT_INSIDE(size, 1, 8+1))
return;
_terraform_size = size;
SndPlayFx(SND_15_BEEP);
SetWindowDirty(w);
} break;
case 14: /* gen random land */
HandleButtonClick(w, 14);
break;
}
case 8: /* gen random land */
HandleButtonClick(w, 8);
AskResetLandscape(0);
break;
case 15: /* reset landscape */
HandleButtonClick(w,15);
case 9: /* reset landscape */
HandleButtonClick(w,9);
AskResetLandscape(1);
break;
case 10: /* place rocky areas */
HandlePlacePushButton(w, 10, 0xFF7, 1, PlaceProc_RockyArea);
break;
case 11: /* place lighthouse */
HandlePlacePushButton(w, 11, 0xFF8, 1, _opt.landscape == LT_DESERT ? PlaceProc_Desert : PlaceProc_LightHouse);
break;
case 12: /* place transmitter */
HandlePlacePushButton(w, 12, 0xFF9, 1, PlaceProc_Transmitter);
break;
case 13: /* level Land */
HandlePlacePushButton(w, 13, SPR_OPENTTD_BASE+69, 2, PlaceProc_LevelLand);
break;
}
break;
case WE_TIMEOUT:
UnclickSomeWindowButtons(w, ~(1<<4 | 1<<5 | 1<<6 | 1<<7 | 1<<8 | 1<<9 | 1<<10 | 1<<11));
UnclickSomeWindowButtons(w, ~(1<<3 | 1<<4 | 1<<5 | 1<<10|1<<11|1<<12));
break;
case WE_PLACE_OBJ:
_place_proc(e->place.tile);
break;
case WE_PLACE_DRAG:
case WE_PLACE_DRAG: {
VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata & 0xF);
break;
return;
}
case WE_PLACE_MOUSEUP:
if (e->click.pt.x != -1) {
if ((e->place.userdata & 0xF) == VPM_X_AND_Y) // dragged actions
GUIPlaceProcDragXY(e);
uint start_tile = e->place.starttile;
uint end_tile = e->place.tile;
if (e->place.userdata == VPM_X_AND_Y) {
DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
} else if (e->place.userdata == (VPM_X_AND_Y | (2<<4))) {
DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_LEVEL_LAND | CMD_AUTO);
}
}
break;
break;
case WE_ABORT_PLACE_OBJ:
w->click_state = 0;
@@ -1433,24 +1382,19 @@ static void ScenEditLandGenWndProc(Window *w, WindowEvent *e)
}
static const WindowDesc _scen_edit_land_gen_desc = {
-1,-1, 182, 102,
-1,-1, 154, 100,
WC_SCEN_LAND_GEN,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_scen_edit_land_gen_widgets,
ScenEditLandGenWndProc,
};
static inline void ShowEditorTerraformToolBar(void)
{
AllocateWindowDescFront(&_scen_edit_land_gen_desc, 0);
}
static void ToolbarScenGenLand(Window *w)
{
HandleButtonClick(w, 11);
SndPlayFx(SND_15_BEEP);
ShowEditorTerraformToolBar();
AllocateWindowDescFront(&_scen_edit_land_gen_desc, 0);
}
void CcBuildTown(bool success, uint tile, uint32 p1, uint32 p2)
@@ -1468,16 +1412,15 @@ static void PlaceProc_Town(uint tile)
static const Widget _scen_edit_town_gen_widgets[] = {
{ WWT_TEXTBTN, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 7, 148, 159, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 159, 14, 81, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 16, 27, STR_0234_NEW_TOWN, STR_0235_CONSTRUCT_NEW_TOWN},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 29, 40, STR_023D_RANDOM_TOWN, STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 42, 53, STR_MANY_RANDOM_TOWNS, STR_RANDOM_TOWNS_TIP},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 53, 68, 79, STR_02A1_SMALL, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 54, 105, 68, 79, STR_02A2_MEDIUM, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 106, 157, 68, 79, STR_02A3_LARGE, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 159, 0, 13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 159, 14, 81, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 16, 27, STR_0234_NEW_TOWN, STR_0235_CONSTRUCT_NEW_TOWN},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 29, 40, STR_023D_RANDOM_TOWN, STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 42, 53, STR_MANY_RANDOM_TOWNS, STR_RANDOM_TOWNS_TIP},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 53, 68, 79, STR_02A1_SMALL, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 54, 105, 68, 79, STR_02A2_MEDIUM, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 106, 157, 68, 79, STR_02A3_LARGE, STR_02A4_SELECT_TOWN_SIZE},
{ WIDGETS_END},
};
@@ -1485,29 +1428,29 @@ static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT:
w->click_state = (w->click_state & ~(1<<7 | 1<<8 | 1<<9) ) | (1 << (_new_town_size + 7));
w->click_state = (w->click_state & ~(1<<6 | 1<<7 | 1<<8) ) | (1 << (_new_town_size + 6));
DrawWindowWidgets(w);
DrawStringCentered(80, 56, STR_02A5_TOWN_SIZE, 0);
break;
case WE_CLICK:
switch (e->click.widget) {
case 4: /* new town */
HandlePlacePushButton(w, 4, SPR_CURSOR_TOWN, 1, PlaceProc_Town);
switch(e->click.widget) {
case 3: /* new town */
HandlePlacePushButton(w, 3, 0xFF0, 1, PlaceProc_Town);
break;
case 5: {/* random town */
case 4: {/* random town */
Town *t;
HandleButtonClick(w, 5);
HandleButtonClick(w, 4);
_generating_world = true;
t = CreateRandomTown(20);
t = CreateRandomTown();
_generating_world = false;
if (t != NULL)
ScrollMainWindowToTile(t->xy);
break;
}
case 6: {/* many random towns */
HandleButtonClick(w, 6);
case 5: {/* many random towns */
HandleButtonClick(w, 5);
_generating_world = true;
_game_mode = GM_NORMAL; // little hack to avoid towns of the same size
GenerateTowns();
@@ -1516,15 +1459,15 @@ static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
break;
}
case 7: case 8: case 9:
_new_town_size = e->click.widget - 7;
case 6: case 7: case 8:
_new_town_size = e->click.widget - 6;
SetWindowDirty(w);
break;
}
break;
case WE_TIMEOUT:
UnclickSomeWindowButtons(w, 1<<5 | 1<<6);
UnclickSomeWindowButtons(w, 1<<4 | 1<<5);
break;
case WE_PLACE_OBJ:
_place_proc(e->place.tile);
@@ -1539,7 +1482,7 @@ static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
static const WindowDesc _scen_edit_town_gen_desc = {
-1,-1, 160, 82,
WC_SCEN_TOWN_GEN,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_scen_edit_town_gen_widgets,
ScenEditTownGenWndProc,
};
@@ -1881,7 +1824,8 @@ static void MainToolbarWndProc(Window *w, WindowEvent *e)
if (local == 0xff) local = 0; // spectator
switch(e->keypress.keycode) {
case WKC_F1: case WKC_PAUSE:
case WKC_F1:
case WKC_PAUSE:
ToolbarPauseClick(w);
break;
case WKC_F2: ShowGameOptions(); break;
@@ -1910,11 +1854,7 @@ static void MainToolbarWndProc(Window *w, WindowEvent *e)
case WKC_CTRL | 'S': _make_screenshot = 1; break;
case WKC_CTRL | 'G': _make_screenshot = 2; break;
case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break;
case 'A': ShowBuildRailToolbar(_last_built_railtype, 4); break; /* Invoke Autorail */
case 'L': ShowTerraformToolbar(); break;
default: return;
}
e->keypress.cont = false;
} break;
case WE_PLACE_OBJ: {
@@ -2010,8 +1950,8 @@ static const Widget _toolb_scen_widgets[] = {
{ WWT_PANEL, RESIZE_NONE, 14, 96, 225, 0, 21, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 14, 233, 362, 0, 21, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 236, 247, 5, 16, SPR_ARROW_DOWN, STR_029E_MOVE_THE_STARTING_DATE},
{ WWT_IMGBTN, RESIZE_NONE, 14, 347, 358, 5, 16, SPR_ARROW_UP, STR_029F_MOVE_THE_STARTING_DATE},
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 236, 246, 5, 16, STR_0225, STR_029E_MOVE_THE_STARTING_DATE},
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 347, 357, 5, 16, STR_0224, STR_029F_MOVE_THE_STARTING_DATE},
{ WWT_PANEL, RESIZE_NONE, 14, 371, 392, 0, 21, 0x2C4, STR_0175_DISPLAY_MAP_TOWN_DIRECTORY},
@@ -2104,7 +2044,7 @@ static void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
} break;
case WE_KEYPRESS: {
switch (e->keypress.keycode) {
switch(e->keypress.keycode) {
case WKC_F1: ToolbarPauseClick(w); break;
case WKC_F2: ShowGameOptions(); break;
case WKC_F3: MenuClickSaveLoad(0); break;
@@ -2118,9 +2058,9 @@ static void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
case WKC_F11: PlaceLandBlockInfo(); break;
case WKC_CTRL | 'S': _make_screenshot = 1; break;
case WKC_CTRL | 'G': _make_screenshot = 2; break;
case 'L': ShowEditorTerraformToolBar(); break;
} break;
} break;
}
break;
}
case WE_PLACE_OBJ: {
_place_proc(e->place.tile);
@@ -2161,13 +2101,11 @@ extern GetNewsStringCallbackProc * const _get_news_string_callback[];
static bool DrawScrollingStatusText(NewsItem *ni, int pos)
{
char buf[512];
StringID str;
const char *s;
char *d;
byte *s, *d;
DrawPixelInfo tmp_dpi, *old_dpi;
int x;
char buffer[256];
byte buffer[256];
if (ni->display_mode == 3) {
str = _get_news_string_callback[ni->callback](ni);
@@ -2176,9 +2114,10 @@ static bool DrawScrollingStatusText(NewsItem *ni, int pos)
str = ni->string_id;
}
GetString(buf, str);
GetString(str_buffr, str);
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
s = buf;
s = str_buffr;
d = buffer;
for(;;s++) {
@@ -2188,7 +2127,7 @@ static bool DrawScrollingStatusText(NewsItem *ni, int pos)
} else if (*s == 0x0D) {
d[0] = d[1] = d[2] = d[3] = ' ';
d+=4;
} else if ((byte)*s >= ' ' && ((byte)*s < 0x88 || (byte)*s >= 0x99)) {
} else if (*s >= ' ' && (*s < 0x88 || *s >= 0x99)) {
*d++ = *s;
}
}
@@ -2240,9 +2179,6 @@ static void StatusBarWndProc(Window *w, WindowEvent *e)
DrawStringCentered(320, 1, STR_02BA, 0);
}
}
if (WP(w, def_d).data_2 > 0)
DrawSprite(SPR_BLOT | PALETTE_TO_RED, 489, 2);
break;
case WE_CLICK:
@@ -2256,25 +2192,27 @@ static void StatusBarWndProc(Window *w, WindowEvent *e)
break;
case WE_TICK: {
if (_pause) return;
if (WP(w, def_d).data_1 > -1280) { /* Scrolling text */
WP(w, def_d).data_1 -= 2;
InvalidateWidget(w, 1);
}
if (WP(w, def_d).data_2 > 0) { /* Red blot to show there are new unread newsmessages */
WP(w, def_d).data_2 -= 2;
} else if (WP(w, def_d).data_2 < 0) {
WP(w, def_d).data_2 = 0;
InvalidateWidget(w, 1);
}
if (_pause || WP(w,def_d).data_1 <= -1280)
return;
WP(w,def_d).data_1 -= 2;
InvalidateWidget(w, 1);
break;
}
}
}
static void ScrollMainViewport(int x, int y)
{
if (_game_mode != GM_MENU) {
Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
assert(w);
WP(w,vp_d).scrollpos_x += x << w->viewport->zoom;
WP(w,vp_d).scrollpos_y += y << w->viewport->zoom;
}
}
static const Widget _main_status_widgets[] = {
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 139, 0, 11, 0x0, STR_NULL},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 140, 499, 0, 11, 0x0, STR_02B7_SHOW_LAST_MESSAGE_OR_NEWS},
@@ -2290,7 +2228,7 @@ static WindowDesc _main_status_desc = {
StatusBarWndProc
};
extern void UpdateAllStationVirtCoord(void);
extern void DebugProc(int i);
static void MainWindowWndProc(Window *w, WindowEvent *e) {
int off_x;
@@ -2331,17 +2269,42 @@ static void MainWindowWndProc(Window *w, WindowEvent *e) {
break;
case WE_KEYPRESS:
if (e->keypress.keycode == WKC_BACKQUOTE) {
IConsoleSwitch();
e->keypress.cont = false;
if (_game_mode == GM_MENU)
break;
// this is a hack, but this needs to be called at a constant interval and i found
// no other window event that was suited for that purpose.
{
static const int8 scrollamt[16][2] = {
{0,0},
{-1,0}, // 1:left
{0,-1}, // 2:up
{-1,-1}, // 3:left + up
{1,0}, // 4:right
{0,0}, // 5:left + right
{1,-1}, // 6:right + up
{0,0}, // 7:impossible
{0,1}, // 8:down
{-1,1}, // 9:down+left
{0,0}, // 10:impossible
{0,0}, // 11:impossible
{1,1}, // 12:down+right
{0,0}, // 13:impossible
{0,0}, // 14:impossible
{0,0}, // 15:impossible
};
if (_dirkeys) {
int factor = _shift_pressed ? 50 : 10;
ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor);
}
}
if (_game_mode == GM_MENU) break;
switch (e->keypress.keycode) {
case 'C': case 'Z': {
Point pt = GetTileBelowCursor();
switch(e->keypress.keycode) {
case 'C':
case 'Z': {
Point pt;
pt = GetTileBelowCursor();
if (pt.x != -1) {
ScrollMainWindowTo(pt.x, pt.y);
if (e->keypress.keycode == 'Z')
@@ -2353,39 +2316,48 @@ static void MainWindowWndProc(Window *w, WindowEvent *e) {
case WKC_ESC: ResetObjectToPlace(); break;
case WKC_DELETE: DeleteNonVitalWindows(); break;
case WKC_DELETE | WKC_SHIFT: DeleteAllNonVitalWindows(); break;
case 'Q' | WKC_CTRL: case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac
case 'Q' | WKC_CTRL: AskExitGame(); break;
case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac
case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break;
#if defined(_DEBUG)
case '0' | WKC_ALT: /* Crash the game */
*(byte*)0 = 0;
break;
case '1' | WKC_ALT: /* Gimme money */
/* Server can not cheat in advertise mode either! */
#ifdef ENABLE_NETWORK
if (!_networking || !_network_server || !_network_advertise)
#endif
DoCommandP(0, -10000000, 0, NULL, CMD_MONEY_CHEAT);
break;
case '2' | WKC_ALT: /* Update the coordinates of all station signs */
UpdateAllStationVirtCoord();
break;
case '0' | WKC_ALT:
case '1' | WKC_ALT:
case '2' | WKC_ALT:
case '3' | WKC_ALT:
case '4' | WKC_ALT:
break;
#if defined(_DEBUG)
DebugProc(e->keypress.keycode - ('0' | WKC_ALT));
#endif
break;
// invoke autorail
case 'A':
ShowBuildRailToolbar(_last_built_railtype, 4);
break;
case 'L':
ShowTerraformToolbar();
break;
case 'X':
_display_opt ^= DO_TRANS_BUILDINGS;
MarkWholeScreenDirty();
break;
#ifdef ENABLE_NETWORK
case WKC_RETURN: case 'T' | WKC_SHIFT:
if (_networking) ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
case WKC_BACKQUOTE:
IConsoleSwitch();
e->keypress.cont=false;
break;
#endif
default: return;
#ifdef ENABLE_NETWORK
case WKC_RETURN:
case 'T' | WKC_SHIFT:
if(_networking)
ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
break;
#endif /* ENABLE_NETWORK */
default:
return;
}
e->keypress.cont = false;
break;
@@ -2400,12 +2372,12 @@ extern void ShowJoinStatusWindowAfterJoin(void);
void SetupColorsAndInitialWindow(void)
{
int i;
byte *b;
Window *w;
int width,height;
for(i=0; i!=16; i++) {
const byte* b = GetNonSprite(0x307 + i);
b = GetSpritePtr(0x307 + i);
assert(b);
_color_list[i] = *(ColorList*)(b + 0xC6);
}
@@ -2416,15 +2388,15 @@ void SetupColorsAndInitialWindow(void)
// XXX: these are not done
switch(_game_mode) {
case GM_MENU:
w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
AssignWindowViewport(w, 0, 0, width, height, TILE_XY(32, 32), 0);
w = AllocateWindow(0, 0, width, height, MainWindowWndProc, 0, NULL);
AssignWindowViewport(w, 0, 0, width, height, 0x8080, 0);
// w = AllocateWindowDesc(&_toolb_intro_desc);
// w->flags4 &= ~WF_WHITE_BORDER_MASK;
ShowSelectGameWindow();
break;
case GM_NORMAL:
w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
AssignWindowViewport(w, 0, 0, width, height, TILE_XY(32, 32), 0);
w = AllocateWindow(0, 0, width, height, MainWindowWndProc, 0, NULL);
AssignWindowViewport(w, 0, 0, width, height, 0x8080, 0);
ShowVitalWindows();
@@ -2434,7 +2406,7 @@ void SetupColorsAndInitialWindow(void)
break;
case GM_EDITOR:
w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
w = AllocateWindow(0, 0, width, height, MainWindowWndProc, 0, NULL);
AssignWindowViewport(w, 0, 0, width, height, 0, 0);
w = AllocateWindowDesc(&_toolb_scen_desc);

View File

@@ -3,14 +3,14 @@
# Magic at work, note that you can't use commas in arguments for this
CONFIG_LINE=@$(SHELL) -c 'echo $(1)' >> $(MAKE_CONFIG) 2> /dev/null
$(MAKE_CONFIG):
$(MAKE_CONFIG):
touch $(MAKE_CONFIG)
$(call CONFIG_LINE,\# OpenTTD config file for makefile)
$(call CONFIG_LINE,\# OpenTTD config file for makefile)
$(call CONFIG_LINE,\# Set your options here - 1 for use and empty for disable)
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# User setup flags)
$(call CONFIG_LINE,\# Translator: adds TODO to any untranslated strings)
$(call CONFIG_LINE,\# Display_Warnings: when off it hides some warnings while compiling)
@@ -30,11 +30,11 @@ $(MAKE_CONFIG):
$(call CONFIG_LINE,WITH_NETWORK:=$(WITH_NETWORK))
$(call CONFIG_LINE,DEDICATED:=$(DEDICATED))
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# Disable asserts. Leave them on for easier bug finding)
$(call CONFIG_LINE,DISABLE_ASSERTS:=$(DISABLE_ASSERTS))
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# See Makefile for details on these paths)
$(call CONFIG_LINE,\# Folders should not end with /)
$(call CONFIG_LINE,INSTALL:=$(INSTALL))
@@ -46,7 +46,7 @@ $(MAKE_CONFIG):
$(call CONFIG_LINE,SECOND_DATA_PATH:=$(SECOND_DATA_PATH))
$(call CONFIG_LINE,CUSTOM_LANG_PATH:=$(CUSTOM_LANG_PATH))
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# Experimental)
$(call CONFIG_LINE,WITH_DIRECTMUSIC:=$(WITH_DIRECTMUSIC))
$(call CONFIG_LINE,)
@@ -58,7 +58,7 @@ $(MAKE_CONFIG):
$(call CONFIG_LINE,\# Inform us if you have success)
$(call CONFIG_LINE,SKIP_STATIC_CHECK:=$(SKIP_STATIC_CHECK))
$(call CONFIG_LINE,)
$(call CONFIG_LINE,)
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# Everything below this line is autogenerated)
$(call CONFIG_LINE,\#)
@@ -66,15 +66,15 @@ $(MAKE_CONFIG):
$(call CONFIG_LINE,\# If that does not fix the problem, you should make a bug report.)
$(call CONFIG_LINE,\# It would really help if you could tell how to autodetect the missing setting)
$(call CONFIG_LINE,\# That info could be where the missing lib is placed)
$(call CONFIG_LINE,)
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# Libs)
$(call CONFIG_LINE,WITH_ZLIB:=$(WITH_ZLIB))
$(call CONFIG_LINE,WITH_SDL:=$(WITH_SDL))
$(call CONFIG_LINE,WITH_PNG:=$(WITH_PNG))
$(call CONFIG_LINE,STATIC_ZLIB_PATH:=$(STATIC_ZLIB_PATH))
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# OS flags)
$(call CONFIG_LINE,WIN32:=$(WIN32))
$(call CONFIG_LINE,UNIX:=$(UNIX))
@@ -85,16 +85,8 @@ $(MAKE_CONFIG):
$(call CONFIG_LINE,SUNOS:=$(SUNOS))
$(call CONFIG_LINE,CYGWIN:=$(CYGWIN))
$(call CONFIG_LINE,MINGW:=$(MINGW))
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# For cross-compiling)
$(call CONFIG_LINE,CC_TARGET:=$(CC_TARGET))
$(call CONFIG_LINE,CC_HOST:=$(CC_HOST))
$(call CONFIG_LINE,CFLAGS_HOST:=$(CFLAGS_HOST))
$(call CONFIG_LINE,WINDRES:=$(WINDRES))
$(call CONFIG_LINE,ENDIAN_FORCE:=$(ENDIAN_FORCE))
$(call CONFIG_LINE,)
$(call CONFIG_LINE,)
$(call CONFIG_LINE,\# misc)
$(call CONFIG_LINE,SDL-CONFIG:=$(SDL-CONFIG))
$(call CONFIG_LINE,BEOS_NET_SERVER:=$(BEOS_NET_SERVER))

157
map.c
View File

@@ -1,56 +1,22 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "functions.h"
#include "map.h"
uint _map_log_x;
uint _map_log_y;
#define TILE_X_BITS 8
#define TILE_Y_BITS 8
byte *_map_type_and_height = NULL;
byte *_map_owner = NULL;
uint16 *_map2 = NULL;
byte *_map3_lo = NULL;
byte *_map3_hi = NULL;
byte *_map5 = NULL;
byte *_map_extra_bits = NULL;
uint _map_log_x = TILE_X_BITS;
uint _map_log_y = TILE_Y_BITS;
#define MAP_SIZE ((1 << TILE_X_BITS) * (1 << TILE_Y_BITS))
void InitMap(uint log_x, uint log_y)
{
uint map_size;
if (log_x < 6 || log_x > 11 || log_y < 6 || log_y > 11)
error("Invalid map size");
DEBUG(map, 1)("Allocating map of size %dx%d", log_x, log_y);
// XXX - MSVC6 volatile workaround
*(volatile uint*)&_map_log_x = log_x;
*(volatile uint*)&_map_log_y = log_y;
map_size = MapSize();
_map_type_and_height =
realloc(_map_type_and_height, map_size * sizeof(_map_type_and_height[0]));
_map_owner = realloc(_map_owner, map_size * sizeof(_map_owner[0]));
_map2 = realloc(_map2, map_size * sizeof(_map2[0]));
_map3_lo = realloc(_map3_lo, map_size * sizeof(_map3_lo[0]));
_map3_hi = realloc(_map3_hi, map_size * sizeof(_map3_hi[0]));
_map5 = realloc(_map5, map_size * sizeof(_map5[0]));
_map_extra_bits =
realloc(_map_extra_bits, map_size * sizeof(_map_extra_bits[0] / 4));
// XXX TODO handle memory shortage more gracefully
if (_map_type_and_height == NULL ||
_map_owner == NULL ||
_map2 == NULL ||
_map3_lo == NULL ||
_map3_hi == NULL ||
_map5 == NULL ||
_map_extra_bits == NULL)
error("Failed to allocate memory for the map");
}
byte _map_type_and_height [MAP_SIZE];
byte _map5 [MAP_SIZE];
byte _map3_lo [MAP_SIZE];
byte _map3_hi [MAP_SIZE];
byte _map_owner [MAP_SIZE];
uint16 _map2 [MAP_SIZE];
byte _map_extra_bits [MAP_SIZE / 4];
#ifdef _DEBUG
@@ -88,108 +54,9 @@ TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
#endif
uint ScaleByMapSize(uint n)
{
int shift = (int)MapLogX() - 8 + (int)MapLogY() - 8;
if (shift < 0)
return (n + (1 << -shift) - 1) >> -shift;
else
return n << shift;
}
uint ScaleByMapSize1D(uint n)
{
int shift = ((int)MapLogX() - 8 + (int)MapLogY() - 8) / 2;
if (shift < 0)
return (n + (1 << -shift) - 1) >> -shift;
else
return n << shift;
}
// This function checks if we add addx/addy to tile, if we
// do wrap around the edges. For example, tile = (10,2) and
// addx = +3 and addy = -4. This function will now return
// INVALID_TILE, because the y is wrapped. This is needed in
// for example, farmland. When the tile is not wrapped,
// the result will be tile + TILE_XY(addx, addy)
uint TileAddWrap(TileIndex tile, int addx, int addy)
{
uint x, y;
x = TileX(tile) + addx;
y = TileY(tile) + addy;
// Are we about to wrap?
if (x < MapMaxX() && y < MapMaxY())
return tile + TILE_XY(addx, addy);
return INVALID_TILE;
}
const TileIndexDiffC _tileoffs_by_dir[] = {
{-1, 0},
{ 0, 1},
{ 1, 0},
{ 0, -1}
};
uint DistanceManhattan(TileIndex t0, TileIndex t1)
{
const uint dx = abs(TileX(t0) - TileX(t1));
const uint dy = abs(TileY(t0) - TileY(t1));
return dx + dy;
}
uint DistanceSquare(TileIndex t0, TileIndex t1)
{
const int dx = TileX(t0) - TileX(t1);
const int dy = TileY(t0) - TileY(t1);
return dx * dx + dy * dy;
}
uint DistanceMax(TileIndex t0, TileIndex t1)
{
const uint dx = abs(TileX(t0) - TileX(t1));
const uint dy = abs(TileY(t0) - TileY(t1));
return dx > dy ? dx : dy;
}
uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1)
{
const uint dx = abs(TileX(t0) - TileX(t1));
const uint dy = abs(TileY(t0) - TileY(t1));
return dx > dy ? 2 * dx + dy : 2 * dy + dx;
}
uint DistanceTrack(TileIndex t0, TileIndex t1)
{
const uint dx = abs(TileX(t0) - TileX(t1));
const uint dy = abs(TileY(t0) - TileY(t1));
const uint straightTracks = 2 * min(dx, dy); /* The number of straight (not full length) tracks */
/* OPTIMISATION:
* Original: diagTracks = max(dx, dy) - min(dx,dy);
* Proof:
* (dx-dy) - straightTracks == (min + max) - straightTracks = min + // max - 2 * min = max - min */
const uint diagTracks = dx + dy - straightTracks; /* The number of diagonal (full tile length) tracks. */
return diagTracks + straightTracks * STRAIGHT_TRACK_LENGTH;
}
uint DistanceFromEdge(TileIndex tile)
{
const uint xl = TileX(tile);
const uint yl = TileY(tile);
const uint xh = MapSizeX() - 1 - xl;
const uint yh = MapSizeY() - 1 - yl;
const uint minl = xl < yl ? xl : yl;
const uint minh = xh < yh ? xh : yh;
return minl < minh ? minl : minh;
}

112
map.h
View File

@@ -1,23 +1,18 @@
#ifndef MAP_H
#define MAP_H
#include "stdafx.h"
#define TILE_FROM_XY(x,y) (TileIndex)((((y) >> 4) << MapLogX()) + ((x) >> 4))
#define TILE_XY(x,y) (((y) << MapLogX()) + (x))
#define TILE_FROM_XY(x,y) (int)((((y) >> 4) << MapLogX()) + ((x) >> 4))
#define TILE_XY(x,y) (int)(((y) << MapLogX()) + (x))
#define TILE_MASK(x) ((x) & ((1 << (MapLogX() + MapLogY())) - 1))
#define TILE_ASSERT(x) assert(TILE_MASK(x) == (x));
extern byte *_map_type_and_height;
extern byte *_map_owner;
extern uint16 *_map2;
extern byte *_map3_lo;
extern byte *_map3_hi;
extern byte *_map5;
extern byte *_map_extra_bits;
void InitMap(uint log_x, uint log_y);
extern byte _map_type_and_height[];
extern byte _map5[];
extern byte _map3_lo[];
extern byte _map3_hi[];
extern byte _map_owner[];
extern uint16 _map2[];
extern byte _map_extra_bits[];
// binary logarithm of the map size, try to avoid using this one
static inline uint MapLogX(void) { extern uint _map_log_x; return _map_log_x; }
@@ -31,22 +26,8 @@ static inline uint MapMaxY(void) { return MapSizeY() - 1; }
/* The number of tiles in the map */
static inline uint MapSize(void) { return MapSizeX() * MapSizeY(); }
// Scale a number relative to the map size
uint ScaleByMapSize(uint); // Scale relative to the number of tiles
uint ScaleByMapSize1D(uint); // Scale relative to the circumference of the map
typedef uint32 TileIndex;
typedef enum {
OWNER_TOWN = 0xf, // a town owns the tile
OWNER_NONE = 0x10, // nobody owns the tile
OWNER_WATER = 0x11, // "water" owns the tile
OWNER_SPECTATOR = 0xff, // spectator in MP or in scenario editor
} Owner;
enum {
INVALID_TILE = (uint32) -1
};
typedef uint16 TileIndex;
static inline uint TileX(TileIndex tile)
{
@@ -59,7 +40,7 @@ static inline uint TileY(TileIndex tile)
}
typedef int32 TileIndexDiff;
typedef int16 TileIndexDiff;
typedef struct TileIndexDiffC {
int16 x;
@@ -82,33 +63,6 @@ static inline TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
#define TILE_ADDXY(tile, x, y) TILE_ADD(tile, TILE_XY(x, y))
uint TileAddWrap(TileIndex tile, int addx, int addy);
static inline TileIndexDiffC TileIndexDiffCByDir(uint dir) {
extern const TileIndexDiffC _tileoffs_by_dir[4];
return _tileoffs_by_dir[dir];
}
/* Returns tile + the diff given in diff. If the result tile would end up
* outside of the map, INVALID_TILE is returned instead.
*/
static inline TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff) {
int x = TileX(tile) + diff.x;
int y = TileY(tile) + diff.y;
if (x < 0 || y < 0 || x > (int)MapMaxX() || y > (int)MapMaxY())
return INVALID_TILE;
else
return TILE_XY(x, y);
}
// Functions to calculate distances
uint DistanceManhattan(TileIndex, TileIndex); // also known as L1-Norm. Is the shortest distance one could go over diagonal tracks (or roads)
uint DistanceSquare(TileIndex, TileIndex); // euclidian- or L2-Norm squared
uint DistanceMax(TileIndex, TileIndex); // also known as L-Infinity-Norm
uint DistanceMaxPlusManhattan(TileIndex, TileIndex); // Max + Manhattan
uint DistanceTrack(TileIndex, TileIndex); // Returns the shortest distance one could go over tracks
uint DistanceFromEdge(TileIndex); // shortest distance from any edge of the map
static inline TileIndexDiff TileOffsByDir(uint dir)
{
@@ -118,12 +72,42 @@ static inline TileIndexDiff TileOffsByDir(uint dir)
return ToTileIndexDiff(_tileoffs_by_dir[dir]);
}
/* Approximation of the length of a straight track, relative to a diagonal
* track (ie the size of a tile side). #defined instead of const so it can
* stay integer. (no runtime float operations) Is this needed?
* Watch out! There are _no_ brackets around here, to prevent intermediate
* rounding! Be careful when using this!
* This value should be sqrt(2)/2 ~ 0.7071 */
#define STRAIGHT_TRACK_LENGTH 7071/10000
static inline uint TileHeight(TileIndex tile)
{
assert(tile < MapSize());
return _map_type_and_height[tile] & 0xf;
}
static inline void SetTileHeight(TileIndex tile, uint height)
{
assert(tile < MapSize());
assert(height < 16);
_map_type_and_height[tile] &= ~0x0F;
_map_type_and_height[tile] |= height;
}
static inline uint TilePixelHeight(TileIndex tile)
{
return TileHeight(tile) * 8;
}
static inline int TileType(TileIndex tile)
{
assert(tile < MapSize());
return _map_type_and_height[tile] >> 4;
}
static inline void SetTileType(TileIndex tile, uint type)
{
assert(tile < MapSize());
_map_type_and_height[tile] &= ~0xF0;
_map_type_and_height[tile] |= type << 4;
}
static inline bool IsTileType(TileIndex tile, int type)
{
return TileType(tile) == type;
}
#endif

View File

@@ -572,7 +572,7 @@ extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift)
* copyright string in the executable of your product.
*/
const lzo_byte __lzo_copyright[] =
static const lzo_byte __lzo_copyright[] =
#if !defined(__LZO_IN_MINLZO)
LZO_VERSION_STRING;
#else

289
misc.c
View File

@@ -1,7 +1,5 @@
#include "stdafx.h"
#include "ttd.h"
#include "string.h"
#include "strings.h" // XXX GetParam*
#include "table/strings.h"
#include "map.h"
#include "vehicle.h"
@@ -12,12 +10,11 @@
#include "network_data.h"
#include "network_server.h"
#include "engine.h"
#include "vehicle_gui.h"
extern void StartupEconomy(void);
extern void InitNewsItemStructs(void);
char _name_array[512][32];
byte _name_array[512][32];
static inline uint32 ROR(uint32 x, int n)
{
@@ -50,20 +47,20 @@ uint32 t;
if (_current_player>=MAX_PLAYERS || !_networking) {
s = _random_seeds[0][0];
t = _random_seeds[0][1];
_random_seeds[0][0] = s + ROR(t ^ 0x1234567F, 7) + 1;
return _random_seeds[0][1] = ROR(s, 3) - 1;
_random_seeds[0][0] = s + ROR(t ^ 0x1234567F, 7);
return _random_seeds[0][1] = ROR(s, 3);
} else {
uint32 s = _player_seeds[_current_player][0];
uint32 t = _player_seeds[_current_player][1];
_player_seeds[_current_player][0] = s + ROR(t ^ 0x1234567F, 7) + 1;
_player_seeds[_current_player][0] = s + ROR(t ^ 0x1234567F, 7);
DEBUG(net, 1)("[NET-Seeds] Player seed called!");
return _player_seeds[_current_player][1] = ROR(s, 3) - 1;
return _player_seeds[_current_player][1] = ROR(s, 3);
}
#else
s = _random_seeds[0][0];
t = _random_seeds[0][1];
_random_seeds[0][0] = s + ROR(t ^ 0x1234567F, 7) + 1;
return _random_seeds[0][1] = ROR(s, 3) - 1;
_random_seeds[0][0] = s + ROR(t ^ 0x1234567F, 7);
return _random_seeds[0][1] = ROR(s, 3);
#endif
}
@@ -83,8 +80,8 @@ uint32 InteractiveRandom(void)
{
uint32 t = _random_seeds[1][1];
uint32 s = _random_seeds[1][0];
_random_seeds[1][0] = s + ROR(t ^ 0x1234567F, 7) + 1;
return _random_seeds[1][1] = ROR(s, 3) - 1;
_random_seeds[1][0] = s + ROR(t ^ 0x1234567F, 7);
return _random_seeds[1][1] = ROR(s, 3);
}
uint InteractiveRandomRange(uint max)
@@ -113,8 +110,6 @@ void SetDate(uint date)
}
#ifdef ENABLE_NETWORK
// multi os compatible sleep function
#ifdef __AMIGA__
@@ -159,11 +154,7 @@ void CSleep(int milliseconds)
#endif
}
#endif /* ENABLE_NETWORK */
void InitializeVehicles(void);
void InitializeWaypoints(void);
void InitializeDepot(void);
void InitializeOrders(void);
void InitializeClearLand(void);
void InitializeRail(void);
@@ -174,7 +165,7 @@ void InitializeAirportGui(void);
void InitializeDock(void);
void InitializeDockGui(void);
void InitializeIndustries(void);
void InitializeLandscape(uint log_x, uint log_y);
void InitializeLandscape(void);
void InitializeTowns(void);
void InitializeTrees(void);
void InitializeSigns(void);
@@ -182,7 +173,6 @@ void InitializeStations(void);
static void InitializeNameMgr(void);
void InitializePlayers(void);
static void InitializeCheats(void);
void InitializeNPF(void);
void GenerateLandscape(void);
void GenerateClearTile(void);
@@ -197,15 +187,13 @@ void GenerateTrees(void);
void ConvertGroundTilesIntoWaterTiles(void);
void InitializeGame(uint log_x, uint log_y)
void InitializeGame(void)
{
// Initialize the autoreplace array. Needs to be cleared between each game
uint i;
for (i = 0; i < lengthof(_autoreplace_array); i++)
_autoreplace_array[i] = i;
_railtype_selected_in_replace_gui = 0;
AddTypeToEngines(); // make sure all engines have a type
SetObjectToPlace(1, 0, 0, 0);
@@ -224,12 +212,10 @@ void InitializeGame(uint log_x, uint log_y)
}
InitializeVehicles();
InitializeWaypoints();
InitializeDepot();
InitializeOrders();
InitNewsItemStructs();
InitializeLandscape(log_x, log_y);
InitializeLandscape();
InitializeClearLand();
InitializeRail();
InitializeRailGui();
@@ -247,7 +233,6 @@ void InitializeGame(uint log_x, uint log_y)
InitializeNameMgr();
InitializeVehiclesGuiList();
InitializeTrains();
InitializeNPF();
InitializePlayers();
InitializeCheats();
@@ -261,7 +246,7 @@ void InitializeGame(uint log_x, uint log_y)
ResetObjectToPlace();
}
void GenerateWorld(int mode, uint log_x, uint log_y)
void GenerateWorld(int mode)
{
int i;
@@ -269,7 +254,7 @@ void GenerateWorld(int mode, uint log_x, uint log_y)
_current_player = OWNER_NONE;
_generating_world = true;
InitializeGame(log_x, log_y);
InitializeGame();
SetObjectToPlace(1, 0, 0, 0);
// Must start economy early because of the costs.
@@ -314,12 +299,27 @@ void DeleteName(StringID id)
}
}
char *GetName(int id, char *buff)
byte *GetName(int id, byte *buff)
{
if (id & 0x400) GetParamInt32();
if (id & 0x200) GetParamUint16();
byte *b;
return strecpy(buff, _name_array[id & ~0x600], NULL);
if (id & 0x600) {
if (id & 0x200) {
if (id & 0x400) {
GetParamInt32();
GetParamUint16();
} else {
GetParamUint16();
}
} else {
GetParamInt32();
}
}
b = _name_array[(id&~0x600)];
while ((*buff++ = *b++) != 0);
return buff - 1;
}
@@ -334,27 +334,38 @@ static void InitializeNameMgr(void)
memset(_name_array, 0, sizeof(_name_array));
}
StringID RealAllocateName(const char *name, byte skip, bool check_double)
StringID RealAllocateName(const byte *name, byte skip, bool check_double)
{
char (*free_item)[lengthof(*_name_array)] = NULL;
char (*i)[lengthof(*_name_array)];
int free_item = -1;
const byte *names;
byte *dst;
int i;
for (i = _name_array; i != endof(_name_array); ++i) {
if ((*i)[0] == '\0') {
if (free_item == NULL) free_item = i;
} else if (check_double && strncmp(*i, name, lengthof(*i) - 1) == 0) {
_error_message = STR_0132_CHOSEN_NAME_IN_USE_ALREADY;
return 0;
names = &_name_array[0][0];
for(i=0; i!=512; i++,names+=sizeof(_name_array[0])) {
if (names[0] == 0) {
if (free_item == -1)
free_item = i;
} else {
if (check_double && str_eq(names, name)) {
_error_message = STR_0132_CHOSEN_NAME_IN_USE_ALREADY;
return 0;
}
}
}
if (free_item != NULL) {
ttd_strlcpy(*free_item, name, lengthof(*free_item));
return (free_item - _name_array) | 0x7800 | (skip << 8);
} else {
if (free_item < 0) {
_error_message = STR_0131_TOO_MANY_NAMES_DEFINED;
return 0;
}
dst=_name_array[free_item];
for(i=0; (dst[i] = name[i]) != 0 && ++i != 32; ) {}
dst[31] = 0;
return free_item | 0x7800 | (skip << 8);
}
@@ -520,6 +531,43 @@ void InitializeLandscapeVariables(bool only_constants)
}
}
// distance in Manhattan metric
uint GetTileDist(TileIndex xy1, TileIndex xy2)
{
return myabs(TileX(xy1) - TileX(xy2)) +
myabs(TileY(xy1) - TileY(xy2));
}
// maximum distance in x _or_ y
uint GetTileDist1D(TileIndex xy1, TileIndex xy2)
{
return max(myabs(TileX(xy1) - TileX(xy2)),
myabs(TileY(xy1) - TileY(xy2)));
}
uint GetTileDist1Db(TileIndex xy1, TileIndex xy2)
{
int a = myabs(TileX(xy1) - TileX(xy2));
int b = myabs(TileY(xy1) - TileY(xy2));
if (a > b)
return a*2+b;
else
return b*2+a;
}
uint GetTileDistAdv(TileIndex xy1, TileIndex xy2)
{
uint a = myabs(TileX(xy1) - TileX(xy2));
uint b = myabs(TileY(xy1) - TileY(xy2));
return a*a+b*b;
}
bool CheckDistanceFromEdge(TileIndex tile, uint distance)
{
return IS_INT_INSIDE(TileX(tile), distance, MapSizeX() - distance) &&
IS_INT_INSIDE(TileY(tile), distance, MapSizeY() - distance);
}
void OnNewDay_Train(Vehicle *v);
void OnNewDay_RoadVeh(Vehicle *v);
@@ -564,41 +612,12 @@ static const uint16 _autosave_months[] = {
0x001, // every 12 months
};
/**
* Runs the day_proc of 'amount' vehicles.
*/
static void RunVehicleDayProc(uint amount)
{
Vehicle *v;
VehicleID ctr;
uint i;
ctr = _vehicle_id_ctr_day;
/* If the CTR is already over the size of the pool, don't even run the for-loop */
if (ctr >= GetVehiclePoolSize()) {
_vehicle_id_ctr_day += amount;
return;
}
for (i = 0; i < amount; i++, ctr++) {
/* Skip non-existing vehicles */
if (ctr >= GetVehiclePoolSize()) {
_vehicle_id_ctr_day += amount;
return;
}
v = GetVehicle(ctr);
if (v->type != 0)
_on_new_vehicle_day_proc[v->type - 0x10](v);
}
_vehicle_id_ctr_day = ctr;
}
void IncreaseDate(void)
{
uint32 total_vehicles = (1 << _vehicle_pool.block_size_bits) * _vehicle_pool.max_blocks;
const int vehicles_per_day = (1 << (sizeof(_date_fract) * 8)) / 885;
uint i;
VehicleID ctr;
int t;
YearMonthDay ymd;
if (_game_mode == GM_MENU) {
@@ -606,24 +625,35 @@ void IncreaseDate(void)
return;
}
RunVehicleDayProc(total_vehicles / DAY_TICKS);
/*if the day changed, call the vehicle event but only update a part of the vehicles
old max was i!= 12. But with that and a bigger number of vehicles (2560), per day only
a part of it could be done, namely: function called max_size date_fract (uint16) / 885 x 12 ==>
65536 / 885 = 74; 74x12 = 888. So max 888. Any vehicles above that were not _on_new_vehicle_day_proc'd
eg. aged.
So new code updates it for max vehicles.
(_vehicles_size / maximum number of times ctr is incremented before reset ) + 1 (to get last vehicles too)
max size of _date_fract / 885 (added each tick) is number of times before ctr is reset.
Calculation might look complicated, but compiler just replaces it with 35, so that's ok
*/
ctr = _vehicle_id_ctr_day;
for (i = 0; i != (_vehicles_size / vehicles_per_day) + 1 && ctr != _vehicles_size; i++) {
Vehicle *v = GetVehicle(ctr++);
if ((t = v->type) != 0)
_on_new_vehicle_day_proc[t - 0x10](v);
}
_vehicle_id_ctr_day = ctr;
/* increase day, and check if a new day is there? */
_tick_counter++;
_date_fract++;
if (_date_fract < DAY_TICKS)
_date_fract += 885;
if (_date_fract >= 885)
return;
_date_fract = 0;
/* yeah, increse day counter and call various daily loops */
_date++;
/* We have a hole because of rounding errors, between the last vehicle checked and the max amount
* of vehicles.. correct for that problem here */
RunVehicleDayProc(total_vehicles - _vehicle_id_ctr_day);
assert(_vehicle_id_ctr_day == total_vehicles);
_vehicle_id_ctr_day = 0;
TextMessageDailyLoop();
@@ -688,10 +718,6 @@ void IncreaseDate(void)
FOR_ALL_VEHICLES(v) {
v->date_of_last_service -= 365; // 1 year is 365 days long
}
/* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
* all of them if the date is set back, else those messages will hang for ever */
InitTextMessage();
}
if (_patches.auto_euro)
@@ -715,44 +741,16 @@ int FindFirstBit(uint32 value)
return i;
}
//!We're writing an own sort algorithm here, as
//!qsort isn't stable
//!Since the number of elements will be low, a
//!simple bubble sort will have to do :)
void bubblesort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
{
uint i,k;
void *buffer = malloc(size);
char *start = base;
nmemb--;
for (i = 0; i < nmemb; i++) {
for (k = 0; k < nmemb; k++) {
void *a, *b;
a = start + size * k;
b = start + size * (k + 1);
if (compar(a, b) > 0) {
memcpy(buffer, a, size);
memcpy(a, b, size);
memcpy(b, buffer, size);
}
}
}
free(buffer);
buffer = NULL;
}
static void Save_NAME(void)
{
int i;
byte *b = _name_array[0];
for (i = 0; i != lengthof(_name_array); ++i) {
if (_name_array[i][0] != '\0') {
for(i=0; i!=lengthof(_name_array); i++,b+=sizeof(_name_array[0])) {
if (*b) {
SlSetArrayIndex(i);
SlArray(_name_array[i], strlen(_name_array[i]), SLE_UINT8);
SlArray(b, strlen(b), SLE_UINT8);
}
}
}
@@ -795,19 +793,16 @@ static const SaveLoadGlobVarList _date_desc[] = {
{&_vehicle_id_ctr_day, SLE_UINT16, 0, 255},
{&_age_cargo_skip_counter, SLE_UINT8, 0, 255},
{&_avail_aircraft, SLE_UINT8, 0, 255},
{&_cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5},
{&_cur_tileloop_tile, SLE_UINT32, 6, 255},
{&_cur_tileloop_tile, SLE_UINT16, 0, 255},
{&_disaster_delay, SLE_UINT16, 0, 255},
{&_station_tick_ctr, SLE_UINT16, 0, 255},
{&_random_seeds[0][0], SLE_UINT32, 0, 255},
{&_random_seeds[0][1], SLE_UINT32, 0, 255},
{&_cur_town_ctr, SLE_FILE_U8 | SLE_VAR_U32, 0, 9},
{&_cur_town_ctr, SLE_UINT32, 10, 255},
{&_cur_town_ctr, SLE_UINT8, 0, 255},
{&_cur_player_tick_index, SLE_FILE_U8 | SLE_VAR_UINT, 0, 255},
{&_next_competitor_start, SLE_FILE_U16 | SLE_VAR_UINT, 0, 255},
{&_trees_tick_ctr, SLE_UINT8, 0, 255},
{&_pause, SLE_UINT8, 4, 255},
{&_cur_town_iter, SLE_UINT32, 11, 255},
{NULL, 0, 0, 0}
};
@@ -820,10 +815,8 @@ static void SaveLoad_DATE(void)
static const SaveLoadGlobVarList _view_desc[] = {
{&_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_INT, 0, 5},
{&_saved_scrollpos_x, SLE_INT32, 6, 255},
{&_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_INT, 0, 5},
{&_saved_scrollpos_y, SLE_INT32, 6, 255},
{&_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_INT, 0, 255},
{&_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_INT, 0, 255},
{&_saved_scrollpos_zoom, SLE_UINT8, 0, 255},
{NULL, 0, 0, 0}
};
@@ -833,35 +826,6 @@ static void SaveLoad_VIEW(void)
SlGlobList(_view_desc);
}
static uint32 _map_dim_x;
static uint32 _map_dim_y;
static const SaveLoadGlobVarList _map_dimensions[] = {
{&_map_dim_x, SLE_UINT32, 6, 255},
{&_map_dim_y, SLE_UINT32, 6, 255},
{NULL, 0, 0, 0}
};
static void Save_MAPSIZE(void)
{
_map_dim_x = MapSizeX();
_map_dim_y = MapSizeY();
SlGlobList(_map_dimensions);
}
static void Load_MAPSIZE(void)
{
uint bits_x = 0;
uint bits_y = 0;
SlGlobList(_map_dimensions);
for (; _map_dim_x > 1; _map_dim_x >>= 1) ++bits_x;
for (; _map_dim_y > 1; _map_dim_y >>= 1) ++bits_y;
InitMap(bits_x, bits_y);
}
static void SaveLoad_MAPT(void)
{
SlArray(_map_type_and_height, MapSize(), SLE_UINT8);
@@ -930,7 +894,6 @@ static void Load_CHTS(void)
const ChunkHandler _misc_chunk_handlers[] = {
{ 'MAPS', Save_MAPSIZE, Load_MAPSIZE, CH_RIFF },
{ 'MAPT', SaveLoad_MAPT, SaveLoad_MAPT, CH_RIFF },
{ 'MAP2', SaveLoad_MAP2, SaveLoad_MAP2, CH_RIFF },
{ 'M3LO', SaveLoad_M3LO, SaveLoad_M3LO, CH_RIFF },

View File

@@ -1,65 +1,64 @@
#include "stdafx.h"
#include "ttd.h"
#include "string.h"
#include "table/strings.h"
#include "command.h"
#include "player.h"
#include "gfx.h"
#include "window.h"
#include "gui.h"
#include "saveload.h"
#include "economy.h"
#include "network.h"
/** Change the player's face.
* @param x,y unused
* @param p1 unused
* @param p2 face bitmasked
/* p1 = player
p2 = face
*/
int32 CmdSetPlayerFace(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
if (flags & DC_EXEC) {
GetPlayer(_current_player)->face = p2;
DEREF_PLAYER(p1)->face = p2;
MarkWholeScreenDirty();
}
return 0;
}
/** Change the player's company-colour
* @param x,y unused
* @param p1 unused
* @param p2 new colour for vehicles, property, etc.
/* p1 = player
* p2 = color
*/
int32 CmdSetPlayerColor(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Player *p, *pp;
Player *p,*pp;
p = GetPlayer(_current_player);
// /* can only set color for itself */
// if ( (byte)p1 != _current_player)
// return CMD_ERROR;
/* Ensure no two companies have the same colour */
p = DEREF_PLAYER(p1);
/* ensure no dups */
FOR_ALL_PLAYERS(pp) {
if (pp->is_active && pp != p && pp->player_color == (byte)p2)
return CMD_ERROR;
}
if (flags & DC_EXEC) {
_player_colors[_current_player] = (byte)p2;
_player_colors[p1] = (byte)p2;
p->player_color = (byte)p2;
MarkWholeScreenDirty();
}
return 0;
}
/** Increase the loan of your company.
* @param x,y unused
* @param p1 unused
* @param p2 when set, loans the maximum amount in one go (press CTRL)
*/
int32 CmdIncreaseLoan(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Player *p;
int32 size;
p = GetPlayer(_current_player);
if ( (byte)p1 != _current_player)
return CMD_ERROR;
p = DEREF_PLAYER(p1);
if (p->current_loan >= _economy.max_loan) {
SetDParam(0, _economy.max_loan);
@@ -67,11 +66,13 @@ int32 CmdIncreaseLoan(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
if (flags & DC_EXEC) {
/* Loan the maximum amount or not? */
int32 loan = (p2) ? _economy.max_loan - p->current_loan : IS_HUMAN_PLAYER(_current_player) ? 10000 : 50000;
if (p2)
size = _economy.max_loan - p->current_loan;
else
size = IS_HUMAN_PLAYER((byte)p1) ? 10000 : 50000;
p->money64 += loan;
p->current_loan += loan;
p->money64 += size;
p->current_loan += size;
UpdatePlayerMoney32(p);
InvalidatePlayerWindows(p);
}
@@ -79,110 +80,98 @@ int32 CmdIncreaseLoan(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
/** Decrease the loan of your company.
* @param x,y unused
* @param p1 unused
* @param p2 when set, pays back the maximum loan permitting money (press CTRL)
*/
int32 CmdDecreaseLoan(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Player *p;
int32 loan;
int32 size;
if ( (byte)p1 != _current_player)
return CMD_ERROR;
p = GetPlayer(_current_player);
p = DEREF_PLAYER(p1);
if (p->current_loan == 0) return_cmd_error(STR_702D_LOAN_ALREADY_REPAYED);
if (p->current_loan == 0)
return_cmd_error(STR_702D_LOAN_ALREADY_REPAYED);
loan = p->current_loan;
size = p->current_loan;
/* p2 is true while CTRL is pressed (repay all possible loan, or max money you have)
* Repay any loan in chunks of 10.000 pounds */
if (p2) {
loan = min(loan, p->player_money);
loan = max(loan, 10000);
loan -= loan % 10000;
} else {
loan = (_patches.ainew_active) ? min(loan, 10000) : min(loan, IS_HUMAN_PLAYER(_current_player) ? 10000 : 50000);
// p2 is true while CTRL is pressed (repay all possible loan, or max money you have)
if (!p2) {
if (_patches.ainew_active)
size = min(size, 10000);
else
size = min(size, IS_HUMAN_PLAYER((byte)p1) ? 10000 : 50000);
} else { // only repay in chunks of 10K
size = min(size, p->player_money);
size = max(size, 10000);
size -= size % 10000;
}
if (p->player_money < loan) {
SetDParam(0, loan);
if (p->player_money < size) {
SetDParam(0, size);
return_cmd_error(STR_702E_REQUIRED);
}
if (flags & DC_EXEC) {
p->money64 -= loan;
p->current_loan -= loan;
p->money64 -= size;
p->current_loan -= size;
UpdatePlayerMoney32(p);
InvalidatePlayerWindows(p);
}
return 0;
}
/** Change the name of the company.
* @param x,y unused
* @param p1 unused
* @param p2 unused
*/
int32 CmdChangeCompanyName(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
StringID str;
StringID str,old_str;
Player *p;
str = AllocateNameUnique(_cmd_text, 4);
if (str == 0) return CMD_ERROR;
str = AllocateNameUnique((byte*)_decode_parameters, 4);
if (str == 0)
return CMD_ERROR;
if (flags & DC_EXEC) {
p = DEREF_PLAYER(_current_player);
DeleteName(p->name_1);
p = DEREF_PLAYER(p1);
old_str = p->name_1;
p->name_1 = str;
DeleteName(old_str);
MarkWholeScreenDirty();
} else
} else {
DeleteName(str);
}
return 0;
}
/** Change the name of the president.
* @param x,y unused
* @param p1 unused
* @param p2 unused
*/
int32 CmdChangePresidentName(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
StringID str;
StringID str,old_str;
Player *p;
str = AllocateNameUnique(_cmd_text, 4);
if (str == 0) return CMD_ERROR;
str = AllocateNameUnique((byte*)_decode_parameters, 4);
if (str == 0)
return CMD_ERROR;
if (flags & DC_EXEC) {
p = DEREF_PLAYER(_current_player);
DeleteName(p->president_name_1);
p = DEREF_PLAYER(p1);
old_str = p->president_name_1;
p->president_name_1 = str;
DeleteName(old_str);
if (p->name_1 == STR_SV_UNNAMED) {
char buf[80];
snprintf(buf, lengthof(buf), "%s Transport", _cmd_text);
_cmd_text = buf;
DoCommandByTile(0, 0, 0, DC_EXEC, CMD_CHANGE_COMPANY_NAME);
ttd_strlcat(
(char*)_decode_parameters, " Transport", sizeof(_decode_parameters));
DoCommandByTile(0, p1, 0, DC_EXEC, CMD_CHANGE_COMPANY_NAME);
}
MarkWholeScreenDirty();
} else
} else {
DeleteName(str);
}
return 0;
}
/** Pause/Unpause the game (server-only).
* Increase or decrease the pause counter. If the counter is zero,
* the game is unpaused. A counter is used instead of a boolean value
* to have more control over the game when saving/loading, etc.
* @param x,y unused
* @param p1 0 = decrease pause counter; 1 = increase pause counter
* @param p2 unused
*/
// p1 = 0 decrease pause counter
// p1 = 1 increase pause counter
int32 CmdPause(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
if (flags & DC_EXEC) {
@@ -194,78 +183,53 @@ int32 CmdPause(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
/** Change the financial flow of your company.
* This is normally only enabled in offline mode, but if there is a debug
* build, you can cheat (to test).
* @param x,y unused
* @param p1 the amount of money to receive (if negative), or spend (if positive)
* @param p2 unused
*/
int32 CmdResume(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
return 0;
}
int32 CmdMoneyCheat(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
#ifndef _DEBUG
if (_networking) return CMD_ERROR;
#endif
SET_EXPENSES_TYPE(EXPENSES_OTHER);
return (int32)p1;
}
/** Transfer funds (money) from one player to another.
* To prevent abuse in multiplayer games you can only send money to other
* players if you have paid off your loan (either explicitely, or implicitely
* given the fact that you have more money than loan).
* @param x,y unused
* @param p1 the amount of money to transfer; max 20.000.000
* @param p2 the player to transfer the money to
*/
int32 CmdGiveMoney(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
const Player *p = DEREF_PLAYER(_current_player);
int32 amount = min((int32)p1, 20000000);
SET_EXPENSES_TYPE(EXPENSES_OTHER);
/* You can only transfer funds that is in excess of your loan */
if (p->money64 - p->current_loan < amount || amount <= 0) return CMD_ERROR;
if (!_networking || p2 >= MAX_PLAYERS) return CMD_ERROR;
p1 = clamp(p1, 0, 0xFFFFFF); // Clamp between 16 million and 0
if (p1 == 0)
return CMD_ERROR;
if (flags & DC_EXEC) {
/* Add money to player */
PlayerID old_cp = _current_player;
// Add money to player
byte old_cp = _current_player;
_current_player = p2;
SubtractMoneyFromPlayer(-amount);
SubtractMoneyFromPlayer(-(int32)p1);
_current_player = old_cp;
}
/* Subtract money from local-player */
return amount;
// Subtract money from local-player
return (int32)p1;
}
/** Change difficulty level/settings (server-only).
* We cannot really check for valid values of p2 (too much work mostly); stored
* in file 'settings_gui.c' _game_setting_info[]; we'll just trust the server it knows
* what to do and does this correctly
* @param x,y unused
* @param p1 the difficulty setting being changed. If it is -1, the difficulty level
* itself is changed. The new value is inside p2
* @param p2 new value for a difficulty setting or difficulty level
*/
int32 CmdChangeDifficultyLevel(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
if (p1 >= GAME_DIFFICULTY_NUM) return CMD_ERROR;
if (flags & DC_EXEC) {
if (p1 != (uint32)-1L) {
((int*)&_opt_ptr->diff)[p1] = p2;
_opt_ptr->diff_level = 3; // custom difficulty level
} else
_opt_ptr->diff_level = p2;
/* If we are a network-client, update the difficult setting (if it is open).
* Use this instead of just dirtying the window because we need to load in
* the new difficulty settings */
((int*)&_opt_mod_ptr->diff)[p1] = p2;
_opt_mod_ptr->diff_level = 3;
} else {
_opt_mod_ptr->diff_level = p2;
}
// If we are a network-client, update the difficult setting (if it is open)
if (_networking && !_network_server && FindWindowById(WC_GAME_OPTIONS, 0) != NULL)
ShowGameDifficulty();
memcpy(&_opt_mod_temp, _opt_mod_ptr, sizeof(GameOptions));
InvalidateWindow(WC_GAME_OPTIONS, 0);
}
return 0;
}

View File

@@ -1,11 +1,6 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "spritecache.h"
#include "strings.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "table/tree_land.h"
#include "map.h"
#include "window.h"
#include "gui.h"
@@ -17,15 +12,14 @@
#include "town.h"
#include "sound.h"
#include "network.h"
#include "string.h"
#include "hal.h" // for file list
static bool _fios_path_changed;
static bool _savegame_sort_dirty;
bool _query_string_active;
/* Now this is what I call dirty.. the edit-box needs to be rewritten! */
static bool _do_edit_on_text_even_when_no_change_to_edit_box;
typedef struct LandInfoData {
Town *town;
int32 costclear;
@@ -176,7 +170,7 @@ static const char *credits[] = {
"Original graphics by Simon Foster",
"",
"The OpenTTD team (in alphabetical order):",
" Bjarni Corfitzen (Bjarni) - MacOSX port, coder",
" Bjarni Corfitzen (Bjarni) - MacOS port",
" Victor Fischer (Celestar) - Programming everywhere you need him to",
" Tamas Farag<61> (Darkvater) - Lead coder",
" Dominik Scherer (dominik81) - Lead coder",
@@ -192,10 +186,9 @@ static const char *credits[] = {
"Special thanks go out to:",
" Josef Drexler - For his great work on TTDPatch",
" Marcin Grzegorczyk - For his documentation of TTD internals",
" Matthijs Kooijman (blathijs) - For his many patches, suggestions and major work on maprewrite",
" Petr Baudis (pasky) - Many patches, newgrf support",
" blathijs - For his many patches, suggestions and major work on maprewrite",
" pasky - Many patches, newgrf support",
" Stefan Mei<65>ner (sign_de) - For his work on the console",
" Simon Sasburg (HackyKid) - For the many bugfixes he has blessed us with (and future PBS)",
" Cian Duffy (MYOB) - BeOS port / manual writing",
" Christian Rosentreter (tokaiz) - MorphOS / AmigaOS port",
"",
@@ -204,6 +197,7 @@ static const char *credits[] = {
" Marcin Grzegorczyk - Foundations for Tracks on Slopes",
" All Translators - Who made OpenTTD a truly international game",
" Bug Reporters - Without whom OpenTTD would still be full of bugs!",
NULL,
"",
"",
"And last but not least:",
@@ -218,6 +212,8 @@ static void AboutWindowProc(Window *w, WindowEvent *e)
WP(w, scroller_d).height = w->height - 40;
break;
case WE_PAINT: {
const char *str;
char buffer[100];
uint i;
int y = WP(w, scroller_d).height;
DrawWindowWidgets(w);
@@ -229,7 +225,16 @@ static void AboutWindowProc(Window *w, WindowEvent *e)
// Show all scrolling credits
for (i = 0; i < lengthof(credits); i++) {
if (y >= 50 && y < (w->height - 40)) {
DoDrawString(credits[i], 10, y, 0x10);
str = credits[i];
/* Hack-Alert: Translated by is a dynamic string as it changes
* with the language chosen. So the special value of NULL is used
* to identify this for the moment */
if (str == NULL) {
GetString(buffer, STR_TRANSLATED_BY);
str = buffer;
}
DoDrawString(str, 10, y, 0x10);
}
y += 10;
}
@@ -273,6 +278,8 @@ void ShowAboutWindow(void)
static int _tree_to_plant;
static const byte _tree_base_by_landscape[4] = {0, 12, 20, 32};
static const byte _tree_count_by_landscape[4] = {12, 8, 12, 9};
static const uint32 _tree_sprites[] = {
0x655,0x663,0x678,0x62B,0x647,0x639,0x64E,0x632,0x67F,0x68D,0x69B,0x6A9,
0x6AF,0x6D2,0x6D9,0x6C4,0x6CB,0x6B6,0x6BD,0x6E0,
@@ -622,7 +629,6 @@ static void TooltipsWndProc(Window *w, WindowEvent *e)
void GuiShowTooltips(StringID string_id)
{
char buffer[512];
Window *w;
int right,bottom;
int x,y;
@@ -637,9 +643,10 @@ void GuiShowTooltips(StringID string_id)
DeleteWindow(w);
}
GetString(buffer, string_id);
GetString(str_buffr, string_id);
assert(strlen(str_buffr) < sizeof(str_buffr) - 1);
right = GetStringWidth(buffer) + 4;
right = GetStringWidth(str_buffr) + 4;
bottom = 14;
if (right > 200) {
@@ -666,27 +673,36 @@ void GuiShowTooltips(StringID string_id)
}
static void DrawStationCoverageText(const AcceptedCargo accepts,
int str_x, int str_y, uint mask)
static void DrawStationCoverageText(const uint *accepts, int str_x, int str_y, uint mask)
{
char *b = _userstring;
int i;
byte *b;
b = InlineString(b, STR_000D_ACCEPTS);
b = _userstring;
b[0] = 0x81;
b[1] = STR_000D_ACCEPTS;
b[2] = STR_000D_ACCEPTS >> 8;
b += 3;
for (i = 0; i != NUM_CARGO; i++, mask >>= 1) {
if (accepts[i] >= 8 && mask & 1) {
b = InlineString(b, _cargoc.names_s[i]);
*b++ = ',';
*b++ = ' ';
for(i=0; i!=NUM_CARGO; i++,mask>>=1) {
if (accepts[i] >= 8 && (mask&1) ) {
StringID id = _cargoc.names_s[i];
b[0] = 0x81;
b[1] = (byte)(id & 255);
b[2] = (byte)(id >> 8);
b[3] = ',';
b[4] = ' ';
b += 5;
}
}
if (b == &_userstring[3]) {
b = InlineString(b, STR_00D0_NOTHING);
*b++ = '\0';
if (b == (byte*)&_userstring[3]) {
b[0] = 0x81;
b[1] = STR_00D0_NOTHING;
b[2] = STR_00D0_NOTHING >> 8;
b[3] = 0;
} else {
b[-2] = '\0';
b[-2] = 0;
}
DrawStringMultiLine(str_x, str_y, STR_SPEC_USERSTRING, 144);
@@ -757,140 +773,77 @@ void SetHScrollCount(Window *w, int num)
if (num < w->hscroll.pos) w->hscroll.pos = num;
}
static void DelChar(Textbuf *tb)
/* Get the count of characters in the string as well as the width in pixels
* [IN]buf: string to be checked
* [OUT]count: gets set to the count of characters
* [OUT]width: gets set to the pixels width */
static void GetCurrentStringSize(const byte *buf, int *count, int *width)
{
tb->width -= GetCharacterWidth((byte)tb->buf[tb->caretpos]);
memmove(tb->buf + tb->caretpos, tb->buf + tb->caretpos + 1, tb->length - tb->caretpos);
tb->length--;
}
*count = 0;
*width = -1;
/**
* Delete a character from a textbuffer, either with 'Delete' or 'Backspace'
* The character is delete from the position the caret is at
* @param tb @Textbuf type to be changed
* @param delmode Type of deletion, either @WKC_BACKSPACE or @WKC_DELETE
* @return Return true on successfull change of Textbuf, or false otherwise
*/
bool DeleteTextBufferChar(Textbuf *tb, int delmode)
{
if (delmode == WKC_BACKSPACE && tb->caretpos != 0) {
tb->caretpos--;
tb->caretxoffs -= GetCharacterWidth((byte)tb->buf[tb->caretpos]);
DelChar(tb);
return true;
} else if (delmode == WKC_DELETE && tb->caretpos < tb->length) {
DelChar(tb);
return true;
}
return false;
}
/**
* Insert a character to a textbuffer. If maxlength is zero, we don't care about
* the screenlength but only about the physical length of the string
* @param tb @Textbuf type to be changed
* @param key Character to be inserted
* @return Return true on successfull change of Textbuf, or false otherwise
*/
bool InsertTextBufferChar(Textbuf *tb, byte key)
{
const byte charwidth = GetCharacterWidth(key);
if (tb->length < tb->maxlength && (tb->maxwidth == 0 || tb->width + charwidth <= tb->maxwidth)) {
memmove(tb->buf + tb->caretpos + 1, tb->buf + tb->caretpos, (tb->length - tb->caretpos) + 1);
tb->buf[tb->caretpos] = key;
tb->length++;
tb->width += charwidth;
tb->caretpos++;
tb->caretxoffs += charwidth;
return true;
}
return false;
}
/**
* Handle text navigation with arrow keys left/right.
* This defines where the caret will blink and the next characer interaction will occur
* @param tb @Textbuf type where navigation occurs
* @param navmode Direction in which navigation occurs @WKC_LEFT, @WKC_RIGHT, @WKC_END, @WKC_HOME
* @return Return true on successfull change of Textbuf, or false otherwise
*/
bool MoveTextBufferPos(Textbuf *tb, int navmode)
{
switch (navmode) {
case WKC_LEFT:
if (tb->caretpos != 0) {
tb->caretpos--;
tb->caretxoffs -= GetCharacterWidth((byte)tb->buf[tb->caretpos]);
return true;
}
break;
case WKC_RIGHT:
if (tb->caretpos < tb->length) {
tb->caretxoffs += GetCharacterWidth((byte)tb->buf[tb->caretpos]);
tb->caretpos++;
return true;
}
break;
case WKC_HOME:
tb->caretpos = 0;
tb->caretxoffs = 0;
return true;
case WKC_END:
tb->caretpos = tb->length;
tb->caretxoffs = tb->width;
return true;
}
return false;
}
/**
* Update @Textbuf type with its actual physical character and screenlength
* Get the count of characters in the string as well as the width in pixels.
* Useful when copying in a larger amount of text at once
* @param tb @Textbuf type which length is calculated
*/
void UpdateTextBufferSize(Textbuf *tb)
{
char *buf;
tb->length = 0;
tb->width = 0;
for (buf = tb->buf; *buf != '\0' && tb->length <= tb->maxlength; buf++) {
tb->length++;
tb->width += GetCharacterWidth((byte)*buf);
}
tb->caretpos = tb->length;
tb->caretxoffs = tb->width;
do {
if (*++buf == 0)
break;
(*count)++;
(*width) += _stringwidth_table[*buf - 32];
} while (1);
}
int HandleEditBoxKey(Window *w, int wid, WindowEvent *we)
{
int width,count;
int key = we->keypress.ascii;
we->keypress.cont = false;
switch (we->keypress.keycode) {
case WKC_ESC: return 2;
case WKC_RETURN: case WKC_NUM_ENTER: return 1;
case (WKC_CTRL | 'V'):
if (InsertTextBufferClipboard(&WP(w, querystr_d).text))
if (we->keypress.keycode == WKC_ESC) {
return 2;
} else if (we->keypress.keycode == WKC_RETURN) {
return 1;
#ifdef WIN32
} else if (we->keypress.keycode == (WKC_CTRL | 'V')) {
if (IsClipboardFormatAvailable(CF_TEXT)) {
const byte* data;
HGLOBAL cbuf;
OpenClipboard(NULL);
cbuf = GetClipboardData(CF_TEXT);
data = GlobalLock(cbuf); // clipboard data
GetCurrentStringSize(WP(w,querystr_d).buf - 1, &count, &width);
/* IS_INT_INSIDE = filter for ascii-function codes like BELL and so on [we need an special filter here later] */
for (; (IS_INT_INSIDE(*data, ' ', 256)) && // valid ASCII char
(count < WP(w,querystr_d).maxlen - 1 && // max charcount; always allow for terminating '\0'
width + _stringwidth_table[(int)(*data) - 32] <= WP(w,querystr_d).maxwidth); ++data) { // max screensize
// append data and update size parameters
WP(w,querystr_d).buf[count] = *data;
count++;
width += _stringwidth_table[*data - 32];
}
WP(w,querystr_d).buf[count + 1] = '\0';
GlobalUnlock(cbuf);
CloseClipboard();
InvalidateWidget(w, wid);
break;
case WKC_BACKSPACE: case WKC_DELETE:
if (DeleteTextBufferChar(&WP(w, querystr_d).text, we->keypress.keycode))
InvalidateWidget(w, wid);
break;
case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
if (MoveTextBufferPos(&WP(w, querystr_d).text, we->keypress.keycode))
InvalidateWidget(w, wid);
break;
default:
if (IsValidAsciiChar(we->keypress.ascii)) {
if (InsertTextBufferChar(&WP(w, querystr_d).text, we->keypress.ascii))
}
#endif
} else {
GetCurrentStringSize(WP(w,querystr_d).buf - 1, &count, &width);
if (we->keypress.keycode == WKC_BACKSPACE) {
if (count != 0) {
WP(w,querystr_d).buf[count-1] = 0;
InvalidateWidget(w, wid);
}
} else if (IS_INT_INSIDE((key = we->keypress.ascii), 32, 256)) {
if (count < WP(w,querystr_d).maxlen && width + _stringwidth_table[key - 32] <= WP(w,querystr_d).maxwidth) {
WP(w,querystr_d).buf[count] = key;
WP(w,querystr_d).buf[count + 1] = '\0';
InvalidateWidget(w, wid);
}
} else // key wasn't caught
we->keypress.cont = true;
}
@@ -898,56 +851,54 @@ int HandleEditBoxKey(Window *w, int wid, WindowEvent *we)
return 0;
}
bool HandleCaret(Textbuf *tb)
{
/* caret changed? */
bool b = !!(_caret_timer & 0x20);
if (b != tb->caret) {
tb->caret = b;
return true;
}
return false;
}
void HandleEditBox(Window *w, int wid)
{
if (HandleCaret(&WP(w, querystr_d).text))
bool b;
/* caret changed? */
b = !!(_caret_timer & 0x20);
if (b != WP(w,querystr_d).caret) {
WP(w,querystr_d).caret = b;
InvalidateWidget(w, wid);
}
}
void DrawEditBox(Window *w, int wid)
{
const Widget *wi = w->widget + wid;
const Textbuf *tb = &WP(w,querystr_d).text;
int x;
GfxFillRect(wi->left+1, wi->top+1, wi->right-1, wi->bottom-1, 215);
DoDrawString(tb->buf, wi->left+2, wi->top+1, 8);
if (tb->caret)
DoDrawString("_", wi->left + 2 + tb->caretxoffs, wi->top + 1, 12);
x = DoDrawString(WP(w,querystr_d).buf, wi->left+2, wi->top+1, 8);
if (WP(w,querystr_d).caret)
DoDrawString("_", x, wi->top+1, 12);
}
#define MAX_QUERYSTR_LEN 64
static void QueryStringWndProc(Window *w, WindowEvent *e)
{
static bool closed = false;
switch(e->event) {
case WE_PAINT:
case WE_PAINT: {
// int x;
SetDParam(0, WP(w,querystr_d).caption);
DrawWindowWidgets(w);
DrawEditBox(w, 5);
break;
} break;
case WE_CLICK:
switch(e->click.widget) {
case 3: DeleteWindow(w); break;
case 4:
press_ok:;
if (WP(w, querystr_d).orig != NULL &&
strcmp(WP(w, querystr_d).text.buf, WP(w, querystr_d).orig) == 0) {
if (str_eq(WP(w,querystr_d).buf, WP(w,querystr_d).buf + MAX_QUERYSTR_LEN) && !_do_edit_on_text_even_when_no_change_to_edit_box) {
DeleteWindow(w);
} else {
char *buf = WP(w,querystr_d).text.buf;
byte *buf = WP(w,querystr_d).buf;
WindowClass wnd_class = WP(w,querystr_d).wnd_class;
WindowNumber wnd_num = WP(w,querystr_d).wnd_num;
Window *parent;
@@ -1002,7 +953,6 @@ press_ok:;
}
}
_query_string_active = false;
CLRBIT(_no_scroll, SCROLL_EDIT);
break;
}
}
@@ -1025,41 +975,43 @@ static const WindowDesc _query_string_desc = {
QueryStringWndProc
};
static char _edit_str_buf[64];
static char _orig_str_buf[lengthof(_edit_str_buf)];
static byte _edit_str_buf[MAX_QUERYSTR_LEN*2];
void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number)
void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number)
{
Window *w;
uint realmaxlen = maxlen & ~0x1000;
assert(realmaxlen < lengthof(_edit_str_buf));
#define _orig_edit_str_buf (_edit_str_buf+MAX_QUERYSTR_LEN)
DeleteWindowById(WC_QUERY_STRING, 0);
DeleteWindowById(WC_SAVELOAD, 0);
w = AllocateWindowDesc(&_query_string_desc);
SETBIT(_no_scroll, SCROLL_EDIT);
GetString(_edit_str_buf, str);
_edit_str_buf[realmaxlen] = '\0';
if (maxlen & 0x1000) {
WP(w, querystr_d).orig = NULL;
if (str == 0xFFFF) {
memcpy(_orig_edit_str_buf, str_buffr, MAX_QUERYSTR_LEN);
} else {
strcpy(_orig_str_buf, _edit_str_buf);
WP(w, querystr_d).orig = _orig_str_buf;
GetString(_orig_edit_str_buf, str);
}
if (maxlen & 0x1000) {
_do_edit_on_text_even_when_no_change_to_edit_box = true;
maxlen &= ~0x1000;
} else
_do_edit_on_text_even_when_no_change_to_edit_box = false;
_orig_edit_str_buf[maxlen] = 0;
memcpy(_edit_str_buf, _orig_edit_str_buf, MAX_QUERYSTR_LEN);
w = AllocateWindowDesc(&_query_string_desc);
w->click_state = 1 << 5;
WP(w, querystr_d).caption = caption;
WP(w, querystr_d).wnd_class = window_class;
WP(w, querystr_d).wnd_num = window_number;
WP(w, querystr_d).text.caret = false;
WP(w, querystr_d).text.maxlength = realmaxlen - 1;
WP(w, querystr_d).text.maxwidth = maxwidth;
WP(w, querystr_d).text.buf = _edit_str_buf;
UpdateTextBufferSize(&WP(w, querystr_d).text);
WP(w,querystr_d).caption = caption;
WP(w,querystr_d).wnd_class = window_class;
WP(w,querystr_d).wnd_num = window_number;
WP(w,querystr_d).caret = 0;
WP(w,querystr_d).maxlen = maxlen;
WP(w,querystr_d).maxwidth = maxwidth;
WP(w,querystr_d).buf = _edit_str_buf;
_query_string_active = true;
}
@@ -1127,30 +1079,31 @@ static const Widget _save_dialog_scen_widgets[] = {
void BuildFileList(void)
{
_fios_path_changed = true;
FiosFreeSavegameList();
if (_saveload_mode == SLD_NEW_GAME || _saveload_mode == SLD_LOAD_SCENARIO || _saveload_mode == SLD_SAVE_SCENARIO) {
if(_saveload_mode==SLD_NEW_GAME || _saveload_mode==SLD_LOAD_SCENARIO || _saveload_mode==SLD_SAVE_SCENARIO)
_fios_list = FiosGetScenarioList(&_fios_num, _saveload_mode);
} else
else
_fios_list = FiosGetSavegameList(&_fios_num, _saveload_mode);
}
static void DrawFiosTexts(void)
{
static const char *path = NULL;
static StringID str = STR_4006_UNABLE_TO_READ_DRIVE;
static uint32 tot = 0;
const char *path;
StringID str;
if (_fios_path_changed) {
str = FiosGetDescText(&path, &tot);
_fios_path_changed = false;
}
if (str != STR_4006_UNABLE_TO_READ_DRIVE) SetDParam(0, tot);
DrawString(2, 37, str, 0);
str = FiosGetDescText(&path);
if (str != 0)
DrawString(2, 37, str, 0);
DoDrawString(path, 2, 27, 16);
}
#if defined(_WIN32)
extern int CDECL compare_FiosItems (const void *a, const void *b);
#else
extern int compare_FiosItems (const void *a, const void *b);
#endif
static void MakeSortedSaveGameList(void)
{
/* Directories are always above the files (FIOS_TYPE_DIR)
@@ -1260,14 +1213,13 @@ static void SaveLoadDlgWndProc(Window *w, WindowEvent *e)
strcpy(_file_to_saveload.name, name);
DeleteWindow(w);
} else if (_saveload_mode == SLD_LOAD_SCENARIO) {
_switch_mode = (_game_mode == GM_MENU) ? SM_LOAD : SM_LOAD_SCENARIO;
_switch_mode = SM_LOAD_SCENARIO;
SetFiosType(file->type);
strcpy(_file_to_saveload.name, name);
DeleteWindow(w);
} else {
// SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox
ttd_strlcpy(WP(w, querystr_d).text.buf, (file->title[0] != '\0') ? file->title : file->name, WP(w, querystr_d).text.maxlength);
UpdateTextBufferSize(&WP(w, querystr_d).text);
strcpy(WP(w,querystr_d).buf, file->title[0] ? file->title : file->name);
InvalidateWidget(w, 9);
}
} else {
@@ -1293,28 +1245,25 @@ static void SaveLoadDlgWndProc(Window *w, WindowEvent *e)
break;
case WE_TIMEOUT:
if (HASBIT(w->click_state, 10)) { /* Delete button clicked */
FiosDelete(WP(w,querystr_d).text.buf);
FiosDelete(WP(w,querystr_d).buf);
SetWindowDirty(w);
BuildFileList();
if (_saveload_mode == SLD_SAVE_GAME) {
if (_saveload_mode == SLD_SAVE_GAME)
GenerateFileName(); /* Reset file name to current date */
UpdateTextBufferSize(&WP(w, querystr_d).text);
}
} else if (HASBIT(w->click_state, 11)) { /* Save button clicked */
_switch_mode = SM_SAVE;
FiosMakeSavegameName(_file_to_saveload.name, WP(w,querystr_d).text.buf);
FiosMakeSavegameName(_file_to_saveload.name, WP(w,querystr_d).buf);
/* In the editor set up the vehicle engines correctly (date might have changed) */
if (_game_mode == GM_EDITOR) StartupEngines();
}
break;
case WE_DESTROY:
// pause is only used in single-player, non-editor mode, non menu mode
if(!_networking && (_game_mode != GM_EDITOR) && (_game_mode != GM_MENU))
// pause is only used in single-player, non-editor mode
if(!_networking && (_game_mode != GM_EDITOR))
DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
_query_string_active = false;
FiosFreeSavegameList();
CLRBIT(_no_scroll, SCROLL_SAVE);
break;
case WE_RESIZE: {
/* Widget 2 and 3 have to go with halve speed, make it so obiwan */
@@ -1383,31 +1332,25 @@ void ShowSaveLoadDialog(int mode)
DeleteWindowById(WC_SAVELOAD, 0);
_saveload_mode = mode;
SETBIT(_no_scroll, SCROLL_SAVE);
switch (mode) {
case SLD_SAVE_GAME:
GenerateFileName();
break;
case SLD_SAVE_SCENARIO:
strcpy(_edit_str_buf, "UNNAMED");
break;
}
w = AllocateWindowDesc(_saveload_dialogs[mode]);
w->vscroll.cap = 24;
w->resize.step_width = 2;
w->resize.step_height = 10;
w->resize.height = w->height - 14 * 10; // Minimum of 10 items
SETBIT(w->click_state, 6);
WP(w,querystr_d).text.caret = false;
WP(w,querystr_d).text.maxlength = lengthof(_edit_str_buf) - 1;
WP(w,querystr_d).text.maxwidth = 240;
WP(w,querystr_d).text.buf = _edit_str_buf;
UpdateTextBufferSize(&WP(w, querystr_d).text);
w->click_state |= (1 << 6);
WP(w,querystr_d).caret = 0;
WP(w,querystr_d).maxlen = MAX_QUERYSTR_LEN;
WP(w,querystr_d).maxwidth = 240;
WP(w,querystr_d).buf = _edit_str_buf;
// pause is only used in single-player, non-editor mode, non-menu mode. It
// will be unpaused in the WE_DESTROY event handler.
if (mode == SLD_SAVE_GAME) {
GenerateFileName();
} else if (mode == SLD_SAVE_SCENARIO) {
strcpy(_edit_str_buf, "UNNAMED");
}
// pause is only used in single-player, non-editor mode
if(_game_mode != GM_MENU && !_networking && _game_mode != GM_EDITOR)
DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
@@ -1481,8 +1424,8 @@ static void SelectScenarioWndProc(Window *w, WindowEvent *e) {
break;
case 6: /* Click the listbox */
if (e->click.pt.y < list_start)
GenRandomNewGame(Random(), InteractiveRandom());
if(e->click.pt.y < list_start)
DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_GEN_RANDOM_NEW_GAME);
else {
char *name;
int y = (e->click.pt.y - list_start) / 10;
@@ -1497,7 +1440,7 @@ static void SelectScenarioWndProc(Window *w, WindowEvent *e) {
SetFiosType(file->type);
strcpy(_file_to_saveload.name, name);
DeleteWindow(w);
StartScenarioEditor(Random(), InteractiveRandom());
DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_START_SCENARIO);
}
}
break;
@@ -1606,18 +1549,8 @@ static int32 ClickChangeDateCheat(int32 p1, int32 p2)
typedef int32 CheckButtonClick(int32, int32);
typedef enum ce_type {
CE_BOOL = 0,
CE_UINT8 = 1,
CE_INT16 = 2,
CE_UINT16 = 3,
CE_INT32 = 4,
CE_BYTE = 5,
CE_CLICK = 6,
} ce_type;
typedef struct CheatEntry {
ce_type type; // type of selector
byte type; // type of selector
byte flags; // selector flags
StringID str; // string with descriptive text
void *variable; // pointer to the variable
@@ -1627,6 +1560,19 @@ typedef struct CheatEntry {
uint16 step; // step for spinbox
} CheatEntry;
enum {
CE_BOOL = 0,
CE_UINT8 = 1,
CE_INT16 = 2,
CE_UINT16 = 3,
CE_INT32 = 4,
CE_BYTE = 5,
CE_CLICK = 6,
CF_0ISDIS = 1,
CF_NOCOMMA = 2,
};
static int32 ReadCE(const CheatEntry*ce)
{
switch(ce->type) {
@@ -1668,7 +1614,6 @@ static const CheatEntry _cheats_ui[] = {
{CE_BOOL, 0, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value,&_cheats.crossing_tunnels.been_used,NULL, 0, 0, 0},
{CE_BOOL, 0, STR_CHEAT_BUILD_IN_PAUSE, &_cheats.build_in_pause.value, &_cheats.build_in_pause.been_used, NULL, 0, 0, 0},
{CE_BOOL, 0, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, NULL, 0, 0, 0},
{CE_BOOL, 0, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, NULL, 0, 0, 0},
{CE_UINT8, 0, STR_CHEAT_SWITCH_CLIMATE, &_opt.landscape, &_cheats.switch_climate.been_used, &ClickChangeClimateCheat,-1, 4, 1},
{CE_UINT8, 0, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat, -1, 1, 1},
};
@@ -1677,8 +1622,8 @@ static const CheatEntry _cheats_ui[] = {
static const Widget _cheat_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 399, 0, 13, STR_CHEATS, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PANEL, RESIZE_NONE, 14, 0, 399, 14, 159, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 399, 14, 159, 0x0, STR_CHEATS_TIP},
{ WWT_PANEL, RESIZE_NONE, 14, 0, 399, 14, 147, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 399, 14, 147, 0x0, STR_CHEATS_TIP},
{ WIDGETS_END},
};
@@ -1813,7 +1758,7 @@ static void CheatsWndProc(Window *w, WindowEvent *e)
}
}
static const WindowDesc _cheats_desc = {
240, 22, 400, 160,
240, 22, 400, 148,
WC_CHEATS,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_cheat_widgets,

154
mixer.c
View File

@@ -1,154 +0,0 @@
#include "stdafx.h"
#include "ttd.h"
#include "mixer.h"
struct MixerChannel {
// Mixer
Mixer *mx;
bool active;
// pointer to allocated buffer memory
int8 *memory;
// current position in memory
uint32 pos;
uint32 frac_pos;
uint32 frac_speed;
uint32 samples_left;
// Mixing volume
uint volume_left;
uint volume_right;
uint flags;
};
struct Mixer {
uint32 play_rate;
MixerChannel channels[8];
};
static void mix_int8_to_int16(MixerChannel *sc, int16 *buffer, uint samples)
{
int8 *b;
uint32 frac_pos;
uint32 frac_speed;
uint volume_left;
uint volume_right;
if (samples > sc->samples_left) samples = sc->samples_left;
sc->samples_left -= samples;
assert(samples > 0);
b = sc->memory + sc->pos;
frac_pos = sc->frac_pos;
frac_speed = sc->frac_speed;
volume_left = sc->volume_left;
volume_right = sc->volume_right;
if (frac_speed == 0x10000) {
// Special case when frac_speed is 0x10000
do {
buffer[0] += *b * volume_left >> 8;
buffer[1] += *b * volume_right >> 8;
b++;
buffer += 2;
} while (--samples > 0);
} else {
do {
buffer[0] += *b * volume_left >> 8;
buffer[1] += *b * volume_right >> 8;
buffer += 2;
frac_pos += frac_speed;
b += frac_pos >> 16;
frac_pos &= 0xffff;
} while (--samples > 0);
}
sc->frac_pos = frac_pos;
sc->pos = b - sc->memory;
}
static void MxCloseChannel(MixerChannel *mc)
{
if (mc->flags & MX_AUTOFREE) free(mc->memory);
mc->active = false;
mc->memory = NULL;
}
void MxMixSamples(Mixer *mx, void *buffer, uint samples)
{
MixerChannel *mc;
// Clear the buffer
memset(buffer, 0, sizeof(int16) * 2 * samples);
// Mix each channel
for (mc = mx->channels; mc != endof(mx->channels); mc++) {
if (mc->active) {
mix_int8_to_int16(mc, buffer, samples);
if (mc->samples_left == 0) MxCloseChannel(mc);
}
}
#if 0
{
static FILE *out = NULL;
if (out == NULL)
out = fopen("d:\\dump.raw", "wb");
fwrite(buffer, samples * 4, 1, out);
}
#endif
}
MixerChannel *MxAllocateChannel(Mixer *mx)
{
MixerChannel *mc;
for (mc = mx->channels; mc != endof(mx->channels); mc++)
if (mc->memory == NULL) {
mc->active = false;
mc->mx = mx;
return mc;
}
return NULL;
}
void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, uint size, uint rate, uint flags)
{
mc->memory = mem;
mc->flags = flags;
mc->frac_pos = 0;
mc->pos = 0;
mc->frac_speed = (rate << 16) / mc->mx->play_rate;
// adjust the magnitude to prevent overflow
while (size & 0xFFFF0000) {
size >>= 1;
rate = (rate >> 1) + 1;
}
mc->samples_left = size * mc->mx->play_rate / rate;
}
void MxSetChannelVolume(MixerChannel *mc, uint left, uint right)
{
mc->volume_left = left;
mc->volume_right = right;
}
void MxActivateChannel(MixerChannel* mc)
{
mc->active = true;
}
bool MxInitialize(uint rate)
{
static Mixer mx;
_mixer = &mx;
mx.play_rate = rate;
return true;
}

24
mixer.h
View File

@@ -1,24 +0,0 @@
#ifndef MIXER_H
#define MIXER_H
typedef struct Mixer Mixer;
typedef struct MixerChannel MixerChannel;
enum {
MX_AUTOFREE = 1,
// MX_8BIT = 2,
// MX_STEREO = 4,
// MX_UNSIGNED = 8,
};
VARDEF Mixer *_mixer;
bool MxInitialize(uint rate);
void MxMixSamples(Mixer *mx, void *buffer, uint samples);
MixerChannel *MxAllocateChannel(Mixer *mx);
void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, uint size, uint rate, uint flags);
void MxSetChannelVolume(MixerChannel *mc, uint left, uint right);
void MxActivateChannel(MixerChannel*);
#endif

View File

@@ -182,12 +182,9 @@ void MusicLoop(void)
return;
if (!_music_driver->is_song_playing()) {
if (_game_mode != GM_MENU) {
StopMusic();
SkipToNextSong();
PlayPlaylistSong();
} else
ResetMusic();
StopMusic();
SkipToNextSong();
PlayPlaylistSong();
}
}

248
namegen.c
View File

@@ -1,7 +1,6 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "namegen.h"
#include "table/namegen.h"
static inline uint32 SeedChance(int shift_by, int max, uint32 seed)
@@ -9,20 +8,6 @@ static inline uint32 SeedChance(int shift_by, int max, uint32 seed)
return ((uint16)(seed >> shift_by) * max) >> 16;
}
static inline uint32 SeedModChance(int shift_by, int max, uint32 seed)
{
/* This actually gives *MUCH* more even distribution of the values
* than SeedChance(), which is absolutely horrible in that. If
* you do not believe me, try with i.e. the Czech town names,
* compare the words (nicely visible on prefixes) generated by
* SeedChance() and SeedModChance(). Do not get dicouraged by the
* never-use-modulo myths, which hold true only for the linear
* congruential generators (and Random() isn't such a generator).
* --pasky */
// TODO: Perhaps we should use it for all the name generators? --pasky
return (seed >> shift_by) % max;
}
static inline int32 SeedChanceBias(int shift_by, int max, uint32 seed, int bias)
{
return SeedChance(shift_by, max + bias, seed) - bias;
@@ -33,7 +18,7 @@ static void ReplaceWords(const char *org, const char *rep, char *buf)
if (strncmp(buf, org, 4) == 0) strncpy(buf, rep, 4);
}
static byte MakeEnglishOriginalTownName(char *buf, uint32 seed)
static byte MakeEnglishOriginalTownName(byte *buf, uint32 seed)
{
int i;
@@ -74,7 +59,7 @@ static byte MakeEnglishOriginalTownName(char *buf, uint32 seed)
}
static byte MakeEnglishAdditionalTownName(char *buf, uint32 seed)
static byte MakeEnglishAdditionalTownName(byte *buf, uint32 seed)
{
int i;
@@ -119,7 +104,7 @@ static byte MakeEnglishAdditionalTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeAustrianTownName(char *buf, uint32 seed)
static byte MakeAustrianTownName(byte *buf, uint32 seed)
{
int i, j = 0;
strcpy(buf, "");
@@ -157,7 +142,7 @@ static byte MakeAustrianTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeGermanTownName(char *buf, uint32 seed)
static byte MakeGermanTownName(byte *buf, uint32 seed)
{
uint i;
uint seed_derivative;
@@ -174,11 +159,11 @@ static byte MakeGermanTownName(char *buf, uint32 seed)
}
// mandatory middle segments including option of hardcoded name
i = SeedChance(3, lengthof(name_german_real) + lengthof(name_german_1), seed);
if (i < lengthof(name_german_real)) {
strcat(buf,name_german_real[i]);
i = SeedChance(3, lengthof(name_german_hardcoded) + lengthof(name_german_1), seed);
if (i < lengthof(name_german_hardcoded)) {
strcat(buf,name_german_hardcoded[i]);
} else {
strcat(buf, name_german_1[i - lengthof(name_german_real)]);
strcat(buf, name_german_1[i - lengthof(name_german_hardcoded)]);
i = SeedChance(5, lengthof(name_german_2), seed);
strcat(buf, name_german_2[i]);
@@ -199,26 +184,26 @@ static byte MakeGermanTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeSpanishTownName(char *buf, uint32 seed)
static byte MakeSpanishTownName(byte *buf, uint32 seed)
{
strcpy(buf, name_spanish_real[SeedChance(0, lengthof(name_spanish_real), seed)]);
strcpy(buf, name_spanish_1[SeedChance(0, lengthof(name_spanish_1), seed)]);
return 0;
}
static byte MakeFrenchTownName(char *buf, uint32 seed)
static byte MakeFrenchTownName(byte *buf, uint32 seed)
{
strcpy(buf, name_french_real[SeedChance(0, lengthof(name_french_real), seed)]);
strcpy(buf, name_french_1[SeedChance(0, lengthof(name_french_1), seed)]);
return 0;
}
static byte MakeSillyTownName(char *buf, uint32 seed)
static byte MakeSillyTownName(byte *buf, uint32 seed)
{
strcpy(buf, name_silly_1[SeedChance( 0, lengthof(name_silly_1), seed)]);
strcat(buf, name_silly_2[SeedChance(16, lengthof(name_silly_2), seed)]);
return 0;
}
static byte MakeSwedishTownName(char *buf, uint32 seed)
static byte MakeSwedishTownName(byte *buf, uint32 seed)
{
int i;
@@ -244,7 +229,7 @@ static byte MakeSwedishTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeDutchTownName(char *buf, uint32 seed)
static byte MakeDutchTownName(byte *buf, uint32 seed)
{
int i;
@@ -268,23 +253,23 @@ static byte MakeDutchTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeFinnishTownName(char *buf, uint32 seed)
static byte MakeFinnishTownName(byte *buf, uint32 seed)
{
//null terminates the string for strcat
strcpy(buf, "");
// Select randomly if town name should consists of one or two parts.
if (SeedChance(0, 15, seed) >= 10) {
strcat(buf, name_finnish_real[SeedChance( 2, lengthof(name_finnish_real), seed)]);
} else {
strcat(buf, name_finnish_1[SeedChance( 2, lengthof(name_finnish_1), seed)]);
strcat(buf, name_finnish_2[SeedChance(10, lengthof(name_finnish_2), seed)]);
} else {
strcat(buf, name_finnish_2a[SeedChance( 2, lengthof(name_finnish_2a), seed)]);
strcat(buf, name_finnish_2b[SeedChance(10, lengthof(name_finnish_2b), seed)]);
}
return 0;
}
static byte MakePolishTownName(char *buf, uint32 seed)
static byte MakePolishTownName(byte *buf, uint32 seed)
{
uint i;
uint j;
@@ -330,194 +315,25 @@ static byte MakePolishTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeCzechTownName(char *buf, uint32 seed)
static byte MakeCzechTownName(byte *buf, uint32 seed)
{
/* Probability of prefixes/suffixes */
/* 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
int prob_tails;
bool do_prefix, do_suffix, dynamic_subst;
/* IDs of the respective parts */
int prefix = 0, ending = 0, suffix = 0;
uint postfix = 0;
uint stem;
/* The select criteria. */
CzechGender gender;
CzechChoose choose;
CzechAllow allow;
// 1:3 chance to use a real name.
if (SeedModChance(0, 4, seed) == 0) {
strcpy(buf, name_czech_real[SeedModChance(4, lengthof(name_czech_real), seed)]);
return 0;
}
// NUL terminates the string for strcat()
strcpy(buf, "");
prob_tails = SeedModChance(2, 32, seed);
do_prefix = prob_tails < 12;
do_suffix = prob_tails > 11 && prob_tails < 17;
if (do_prefix) prefix = SeedModChance(5, lengthof(name_czech_adj) * 12, seed) / 12;
if (do_suffix) suffix = SeedModChance(7, lengthof(name_czech_suffix), seed);
// 3:1 chance 3:1 to use dynamic substantive
stem = SeedModChance(9,
lengthof(name_czech_subst_full) + 3 * lengthof(name_czech_subst_stem),
seed);
if (stem < lengthof(name_czech_subst_full)) {
// That was easy!
dynamic_subst = false;
gender = name_czech_subst_full[stem].gender;
choose = name_czech_subst_full[stem].choose;
allow = name_czech_subst_full[stem].allow;
} else {
unsigned int map[lengthof(name_czech_subst_ending)];
int ending_start = -1, ending_stop = -1;
int i;
// Load the substantive
dynamic_subst = true;
stem -= lengthof(name_czech_subst_full);
stem %= lengthof(name_czech_subst_stem);
gender = name_czech_subst_stem[stem].gender;
choose = name_czech_subst_stem[stem].choose;
allow = name_czech_subst_stem[stem].allow;
// Load the postfix (1:1 chance that a postfix will be inserted)
postfix = SeedModChance(14, lengthof(name_czech_subst_postfix) * 2, seed);
if (choose & CZC_POSTFIX) {
// Always get a real postfix.
postfix %= lengthof(name_czech_subst_postfix);
}
if (choose & CZC_NOPOSTFIX) {
// Always drop a postfix.
postfix += lengthof(name_czech_subst_postfix);
}
if (postfix < lengthof(name_czech_subst_postfix))
choose |= CZC_POSTFIX;
else
choose |= CZC_NOPOSTFIX;
// Localize the array segment containing a good gender
for (ending = 0; ending < (int) lengthof(name_czech_subst_ending); ending++) {
const CzechNameSubst *e = &name_czech_subst_ending[ending];
if (gender == CZG_FREE ||
(gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
gender == e->gender) {
if (ending_start < 0)
ending_start = ending;
} else if (ending_start >= 0) {
ending_stop = ending - 1;
break;
}
}
if (ending_stop < 0) {
// Whoa. All the endings matched.
ending_stop = ending - 1;
}
// Make a sequential map of the items with good mask
i = 0;
for (ending = ending_start; ending <= ending_stop; ending++) {
const CzechNameSubst *e = &name_czech_subst_ending[ending];
if ((e->choose & choose) == choose && (e->allow & allow) != 0)
map[i++] = ending;
}
assert(i > 0);
// Load the ending
ending = map[SeedModChance(16, i, seed)];
// Override possible CZG_*FREE; this must be a real gender,
// otherwise we get overflow when modifying the adjectivum.
gender = name_czech_subst_ending[ending].gender;
assert(gender != CZG_FREE && gender != CZG_NFREE);
}
if (do_prefix && (name_czech_adj[prefix].choose & choose) != choose) {
// Throw away non-matching prefix.
do_prefix = false;
}
// Now finally construct the name
if (do_prefix) {
CzechPattern pattern = name_czech_adj[prefix].pattern;
int endpos;
strcat(buf, name_czech_adj[prefix].name);
endpos = strlen(buf) - 1;
if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
/* -ovX -> -uv */
buf[endpos - 2] = 'u';
assert(buf[endpos - 1] == 'v');
buf[endpos] = '\0';
} else {
buf[endpos] = name_czech_patmod[gender][pattern];
}
strcat(buf, " ");
}
if (dynamic_subst) {
strcat(buf, name_czech_subst_stem[stem].name);
if (postfix < lengthof(name_czech_subst_postfix)) {
const char *poststr = name_czech_subst_postfix[postfix];
const char *endstr = name_czech_subst_ending[ending].name;
int postlen, endlen;
postlen = strlen(poststr);
endlen = strlen(endstr);
assert(postlen > 0 && endlen > 0);
// Kill the "avava" and "Jananna"-like cases
if (postlen < 2 || postlen > endlen || (
(poststr[1] != 'v' || poststr[1] != endstr[1]) &&
poststr[2] != endstr[1])
) {
uint buflen;
strcat(buf, poststr);
buflen = strlen(buf);
// k-i -> c-i, h-i -> z-i
if (endstr[0] == 'i') {
switch (buf[buflen - 1]) {
case 'k': buf[buflen - 1] = 'c'; break;
case 'h': buf[buflen - 1] = 'z'; break;
default: break;
}
}
}
}
strcat(buf, name_czech_subst_ending[ending].name);
} else {
strcat(buf, name_czech_subst_full[stem].name);
}
if (do_suffix) {
strcat(buf, " ");
strcat(buf, name_czech_suffix[suffix]);
}
strcpy(buf, name_czech_1[SeedChance(0, lengthof(name_czech_1), seed)]);
return 0;
}
static byte MakeRomanianTownName(char *buf, uint32 seed)
static byte MakeRomanianTownName(byte *buf, uint32 seed)
{
strcpy(buf, name_romanian_real[SeedChance(0, lengthof(name_romanian_real), seed)]);
strcpy(buf, name_romanian_1[SeedChance(0, lengthof(name_romanian_1), seed)]);
return 0;
}
static byte MakeSlovakTownName(char *buf, uint32 seed)
static byte MakeSlovakTownName(byte *buf, uint32 seed)
{
strcpy(buf, name_slovak_real[SeedChance(0, lengthof(name_slovak_real), seed)]);
strcpy(buf, name_slovakish_1[SeedChance(0, lengthof(name_slovakish_1), seed)]);
return 0;
}
static byte MakeNorwegianTownName(char *buf, uint32 seed)
static byte MakeNorwegianTownName(byte *buf, uint32 seed)
{
strcpy(buf, "");
@@ -536,7 +352,7 @@ static byte MakeNorwegianTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeHungarianTownName(char *buf, uint32 seed)
static byte MakeHungarianTownName(byte *buf, uint32 seed)
{
uint i;
@@ -565,7 +381,7 @@ static byte MakeHungarianTownName(char *buf, uint32 seed)
return 0;
}
static byte MakeSwissTownName(char *buf, uint32 seed)
static byte MakeSwissTownName(byte *buf, uint32 seed)
{
strcpy(buf, name_swiss_real[SeedChance(0, lengthof(name_swiss_real), seed)]);
return 0;
@@ -605,7 +421,7 @@ uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type)
case 1: /* French */
/* For some reason 86 needs to be subtracted from townnameparts
* 0000 0000 0000 0000 0000 0000 1111 1111 */
return FIXNUM(townnameparts - 86, lengthof(name_french_real), 0);
return FIXNUM(townnameparts - 86, lengthof(name_french_1), 0);
case 2: /* German */
DEBUG(misc, 0) ("German Townnames are buggy... (%d)", townnameparts);
@@ -613,7 +429,7 @@ uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type)
case 4: /* Latin-American */
/* 0000 0000 0000 0000 0000 0000 1111 1111 */
return FIXNUM(townnameparts, lengthof(name_spanish_real), 0);
return FIXNUM(townnameparts, lengthof(name_spanish_1), 0);
case 5: /* Silly */
/* NUM_SILLY_1 - lower 16 bits

View File

@@ -1,8 +0,0 @@
#ifndef NAMEGEN_H
#define NAMEGEN_H
typedef byte TownNameGenerator(char *buf, uint32 seed);
extern TownNameGenerator * const _town_name_generators[];
#endif

112
network.c
View File

@@ -1,10 +1,6 @@
#include "stdafx.h"
#include "debug.h"
#include "string.h"
#include "strings.h"
#include "map.h"
#include "network_data.h"
#include "command.h"
#if defined(WITH_REV)
extern const char _openttd_revision[];
@@ -47,6 +43,7 @@ static uint16 _network_client_index = NETWORK_SERVER_INDEX + 1;
/* Some externs / forwards */
extern void ShowJoinStatusWindow(void);
extern void StateGameLoop(void);
extern uint GetCurrentCurrencyRate(void);
// Function that looks up the CI for a given client-index
NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index)
@@ -333,8 +330,9 @@ static void NetworkFindIPs(void)
// If something fails, make sure the list is empty
_network_ip_list[0] = 0;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) return;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
return;
}
#ifdef WIN32
// On windows it is easy
@@ -425,9 +423,9 @@ unsigned long NetworkResolveHost(const char *hostname)
// connection_string will be re-terminated to seperate out the hostname, and player and port will
// be set to the player and port strings given by the user, inside the memory area originally
// occupied by connection_string.
void ParseConnectionString(const char **player, const char **port, char *connection_string)
void ParseConnectionString(const byte **player, const byte **port, byte *connection_string)
{
char *p;
byte *p;
for (p = connection_string; *p != '\0'; p++) {
if (*p == '#') {
*player = p + 1;
@@ -467,9 +465,6 @@ static NetworkClientState *NetworkAllocClient(SOCKET s)
cs->last_frame = 0;
cs->quited = false;
cs->last_frame = _frame_counter;
cs->last_frame_server = _frame_counter;
if (_network_server) {
ci = DEREF_CLIENT_INFO(cs);
memset(ci, 0, sizeof(*ci));
@@ -517,12 +512,6 @@ void NetworkCloseClient(NetworkClientState *cs)
}
}
/* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
if (cs->status == STATUS_PRE_ACTIVE && _network_pause_on_join) {
DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
}
closesocket(cs->socket);
cs->writable = false;
cs->quited = true;
@@ -582,8 +571,14 @@ static bool NetworkConnect(const char *hostname, int port)
return false;
}
if (!SetNoDelay(s))
DEBUG(net, 1)("[NET] Setting TCP_NODELAY failed");
{ // set nodelay /* XXX should this be done at all? */
#if !defined(BEOS_NET_SERVER) // not implemented on BeOS net_server...
int b = 1;
// The (const char*) cast is needed for windows!!
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) != 0)
DEBUG(net, 1)("[NET] Setting TCP_NODELAY failed");
#endif
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = NetworkResolveHost(hostname);
@@ -595,8 +590,16 @@ static bool NetworkConnect(const char *hostname, int port)
return false;
}
if (!SetNonBlocking(s))
DEBUG(net, 0)("[NET] Setting non-blocking failed"); // XXX should this be an error?
{ // set nonblocking mode for socket..
unsigned long blocking = 1;
#if defined(__BEOS__) && defined(BEOS_NET_SERVER)
byte nonblocking = 1;
if (setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(blocking)) != 0)
#else
if (ioctlsocket(s, FIONBIO, &blocking) != 0)
#endif
DEBUG(net, 0)("[NET] Setting non-blocking failed"); /* XXX should this be an error? */
}
// in client mode, only the first client field is used. it's pointing to the server.
NetworkAllocClient(s);
@@ -614,6 +617,11 @@ static void NetworkAcceptClients(void)
struct sockaddr_in sin;
SOCKET s;
NetworkClientState *cs;
#ifndef __MORPHOS__
int sin_len;
#else
LONG sin_len; // for some reason we need a 'LONG' under MorphOS
#endif
uint i;
bool banned;
@@ -621,17 +629,24 @@ static void NetworkAcceptClients(void)
assert(_listensocket != INVALID_SOCKET);
for (;;) {
socklen_t sin_len;
sin_len = sizeof(sin);
s = accept(_listensocket, (struct sockaddr*)&sin, &sin_len);
if (s == INVALID_SOCKET) return;
SetNonBlocking(s); // XXX error handling?
// set nonblocking mode for client socket
#if defined(__BEOS__) && defined(BEOS_NET_SERVER)
{ unsigned long blocking = 1; byte nonblocking = 1; setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(blocking)); }
#else
{ unsigned long blocking = 1; ioctlsocket(s, FIONBIO, &blocking); }
#endif
DEBUG(net, 1) ("[NET] Client connected from %s on frame %d", inet_ntoa(sin.sin_addr), _frame_counter);
SetNoDelay(s); // XXX error handling?
// set nodelay
#if !defined(BEOS_NET_SERVER) // not implemented on BeOS net_server...
// The (const char*) cast is needed for windows!!
{int b = 1; setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b));}
#endif
/* Check if the client is banned */
banned = false;
@@ -717,8 +732,16 @@ static bool NetworkListen(void)
}
}
if (!SetNonBlocking(ls))
DEBUG(net, 0)("[NET] Setting non-blocking failed"); // XXX should this be an error?
{ // set nonblocking mode for socket
unsigned long blocking = 1;
#if defined(__BEOS__) && defined(BEOS_NET_SERVER)
byte nonblocking = 1;
if (setsockopt(ls, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(blocking)) != 0)
#else
if (ioctlsocket(ls, FIONBIO, &blocking) != 0)
#endif
DEBUG(net, 0)("[NET] Setting non-blocking failed"); /* XXX should this be an error? */
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = _network_server_bind_ip;
@@ -794,7 +817,7 @@ static void NetworkInitialize(void)
// Query a server to fetch his game-info
// If game_info is true, only the gameinfo is fetched,
// else only the client_info is fetched
NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info)
NetworkGameList *NetworkQueryServer(const byte* host, unsigned short port, bool game_info)
{
if (!_network_available) return NULL;
@@ -828,13 +851,13 @@ NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool
/* Validates an address entered as a string and adds the server to
* the list. If you use this functions, the games will be marked
* as manually added. */
void NetworkAddServer(const char *b)
void NetworkAddServer(const byte *b)
{
if (*b != '\0') {
NetworkGameList *item;
const char *port = NULL;
const char *player = NULL;
char host[NETWORK_HOSTNAME_LENGTH];
const byte *port = NULL;
const byte *player = NULL;
byte host[NETWORK_HOSTNAME_LENGTH];
uint16 rport;
ttd_strlcpy(host, b, lengthof(host));
@@ -871,7 +894,7 @@ void NetworkRebuildHostList(void)
}
// Used by clients, to connect to a server
bool NetworkClientConnectGame(const char* host, unsigned short port)
bool NetworkClientConnectGame(const byte* host, unsigned short port)
{
if (!_network_available) return false;
@@ -925,7 +948,11 @@ static void NetworkInitGameInfo(void)
_network_game_info.map_height = MapSizeY();
_network_game_info.map_set = _opt.landscape;
_network_game_info.use_password = (_network_server_password[0] == '\0') ? 0 : 1;
if (_network_game_info.server_password[0] == '\0') {
_network_game_info.use_password = 0;
} else {
_network_game_info.use_password = 1;
}
// We use _network_client_info[MAX_CLIENT_INFO - 1] to store the server-data in it
// The index is NETWORK_SERVER_INDEX ( = 1)
@@ -1370,9 +1397,24 @@ void NetworkShutDown(void)
}
#endif
}
void NetworkChangeCompanyPassword(const char *str)
{
if (strncmp(str, "*", sizeof(_network_player_info[_local_player].password)) == 0) {
_network_player_info[_local_player].password[0] = '\0';
IConsolePrint(_iconsole_color_warning, "Company password protection removed.");
} else {
ttd_strlcpy(_network_player_info[_local_player].password, str, sizeof(_network_player_info[_local_player].password));
IConsolePrintF(_iconsole_color_warning, "Company protected with password '%s'.", _network_player_info[_local_player].password);
}
if (!_network_server)
SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
}
#else
void ParseConnectionString(const char **player, const char **port, char *connection_string) {}
void ParseConnectionString(const byte **player, const byte **port, byte *connection_string) {}
void NetworkUpdateClientInfo(uint16 client_index) {}
#endif /* ENABLE_NETWORK */

Some files were not shown because too many files have changed in this diff Show More