Merge branch 'master' into jgrpp

# Conflicts:
#	.github/workflows/commit-checker.yml
#	src/industry_cmd.cpp
#	src/industry_gui.cpp
#	src/landscape.cpp
#	src/linkgraph/linkgraph_gui.cpp
#	src/order_base.h
#	src/order_cmd.cpp
#	src/order_gui.cpp
#	src/saveload/afterload.cpp
#	src/saveload/league_sl.cpp
#	src/saveload/saveload.h
#	src/script/api/script_object.hpp
#	src/script/squirrel_helper.hpp
#	src/settings_table.cpp
#	src/station_cmd.cpp
#	src/table/settings.h.preamble
#	src/tree_cmd.cpp
#	src/tree_map.h
#	src/vehicle.cpp
#	src/waypoint_cmd.cpp
pull/491/head
Jonathan G Rennison 1 year ago
commit 2ea1766677

@ -14,6 +14,10 @@ on:
env:
CTEST_OUTPUT_ON_FAILURE: 1
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
jobs:
emscripten:
name: Emscripten

@ -14,6 +14,10 @@ on:
description: 'Ref to build (for Pull Requests, use refs/pull/NNN/head)'
required: true
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
jobs:
analyze:
name: Analyze

@ -4,6 +4,10 @@ on:
workflow_dispatch:
# pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
jobs:
unused-strings:
name: Unused strings

@ -367,6 +367,8 @@ if(NOT OPTION_DEDICATED)
endif()
endif()
include(CheckAtomic)
if(APPLE)
link_package(Iconv TARGET Iconv::Iconv)

@ -0,0 +1,87 @@
# atomic builtins are required for threading support.
INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckLibraryExists)
# Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++17")
check_cxx_source_compiles("
#include <atomic>
std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
int main() {
++z;
++y;
return ++x;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics)
function(check_working_cxx_atomics64 varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-std=c++17 ${CMAKE_REQUIRED_FLAGS}")
check_cxx_source_compiles("
#include <atomic>
#include <cstdint>
std::atomic<uint64_t> x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
(void)i;
return 0;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics64)
# Check for (non-64-bit) atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS_WITHOUT_LIB True)
else()
# First check if atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
if(HAVE_LIBATOMIC)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
message(FATAL_ERROR "Host compiler must support std::atomic!")
endif()
else()
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
endif()
endif()
endif()
# Check for 64 bit atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
else()
# First check if atomics work without the library.
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
if(HAVE_CXX_LIBATOMICS64)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!")
endif()
else()
message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.")
endif()
endif()
endif()
if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB)
target_link_libraries(openttd atomic)
endif()

@ -28,25 +28,27 @@ endmacro()
macro(dump_class_templates NAME)
string(REGEX REPLACE "^Script" "" REALNAME ${NAME})
string(APPEND SQUIRREL_EXPORT "\n template <> inline ${NAME} *GetParam(ForceType<${NAME} *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return (${NAME} *)instance; }")
string(APPEND SQUIRREL_EXPORT "\n template <> inline ${NAME} &GetParam(ForceType<${NAME} &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return *(${NAME} *)instance; }")
string(APPEND SQUIRREL_EXPORT "\n template <> inline const ${NAME} *GetParam(ForceType<const ${NAME} *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return (${NAME} *)instance; }")
string(APPEND SQUIRREL_EXPORT "\n template <> inline const ${NAME} &GetParam(ForceType<const ${NAME} &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return *(${NAME} *)instance; }")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<${NAME} *> { static inline ${NAME} *Get(HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return (${NAME} *)instance; } };")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<${NAME} &> { static inline ${NAME} &Get(HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return *(${NAME} *)instance; } };")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<const ${NAME} *> { static inline const ${NAME} *Get(HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return (${NAME} *)instance; } };")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<const ${NAME} &> { static inline const ${NAME} &Get(HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return *(${NAME} *)instance; } };")
if("${NAME}" STREQUAL "ScriptEvent")
string(APPEND SQUIRREL_EXPORT "\n template <> inline int Return<${NAME} *>(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; }")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Return<${NAME} *> { static inline int Set(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; } };")
elseif("${NAME}" STREQUAL "ScriptText")
string(APPEND SQUIRREL_EXPORT "\n")
string(APPEND SQUIRREL_EXPORT "\n template <> inline Text *GetParam(ForceType<Text *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) {")
string(APPEND SQUIRREL_EXPORT "\n if (sq_gettype(vm, index) == OT_INSTANCE) {")
string(APPEND SQUIRREL_EXPORT "\n return GetParam(ForceType<ScriptText *>(), vm, index, ptr);")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<Text *> {")
string(APPEND SQUIRREL_EXPORT "\n static inline Text *Get(HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) {")
string(APPEND SQUIRREL_EXPORT "\n if (sq_gettype(vm, index) == OT_INSTANCE) {")
string(APPEND SQUIRREL_EXPORT "\n return Param<ScriptText *>::Get(vm, index, ptr);")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n if (sq_gettype(vm, index) == OT_STRING) {")
string(APPEND SQUIRREL_EXPORT "\n return new RawText(Param<const char *>::Get(vm, index, ptr));")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n return nullptr;")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n if (sq_gettype(vm, index) == OT_STRING) {")
string(APPEND SQUIRREL_EXPORT "\n return new RawText(GetParam(ForceType<const char *>(), vm, index, ptr));")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n return nullptr;")
string(APPEND SQUIRREL_EXPORT "\n }")
string(APPEND SQUIRREL_EXPORT "\n };")
else()
string(APPEND SQUIRREL_EXPORT "\n template <> inline int Return<${NAME} *>(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; }")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Return<${NAME} *> { static inline int Set(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; } };")
endif()
endmacro()
@ -297,8 +299,8 @@ foreach(LINE IN LISTS SOURCE_LINES)
endif()
string(APPEND SQUIRREL_EXPORT "\n /* Allow enums to be used as Squirrel parameters */")
foreach(ENUM IN LISTS ENUMS)
string(APPEND SQUIRREL_EXPORT "\n template <> inline ${ENUM} GetParam(ForceType<${ENUM}>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (${ENUM})tmp; }")
string(APPEND SQUIRREL_EXPORT "\n template <> inline int Return<${ENUM}>(HSQUIRRELVM vm, ${ENUM} res) { sq_pushinteger(vm, res); return 1; }")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Param<${ENUM}> { static inline ${ENUM} Get(HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (${ENUM})tmp; } };")
string(APPEND SQUIRREL_EXPORT "\n template <> struct Return<${ENUM}> { static inline int Set(HSQUIRRELVM vm, ${ENUM} res) { sq_pushinteger(vm, res); return 1; } };")
endforeach()
endif()
@ -625,7 +627,7 @@ foreach(LINE IN LISTS SOURCE_LINES)
string(APPEND TYPES "p")
elseif("${PARAM}" MATCHES "^Array")
string(APPEND TYPES "a")
elseif("${PARAM}" MATCHES "^struct Array")
elseif("${PARAM}" MATCHES "^const Array")
string(APPEND TYPES "a")
elseif("${PARAM}" MATCHES "^Text")
string(APPEND TYPES ".")

@ -588,7 +588,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
SetName(): false
GetLastErrorString(): ERR_NAME_IS_NOT_UNIQUE
GetName(): Regression
GetPresidentName(): E. McAlpine
GetPresidentName(): J. Green
SetPresidentName(): true
GetPresidentName(): Regression AI
GetBankBalance(): 100000

@ -69,7 +69,18 @@ EngineID EngineReplacement(EngineRenewList erl, EngineID engine, GroupID group,
/* We didn't find anything useful in the vehicle's own group so we will try ALL_GROUP */
er = GetEngineReplacement(erl, engine, ALL_GROUP);
}
if (replace_when_old != nullptr) *replace_when_old = er == nullptr ? false : er->replace_when_old;
if (replace_when_old != nullptr) {
if (er == nullptr) {
/* Not replacing */
*replace_when_old = false;
} else if (er->to == engine) {
/* When replacing with same model, only ever do it when old */
*replace_when_old = true;
} else {
/* Use player setting */
*replace_when_old = er->replace_when_old;
}
}
return er == nullptr ? INVALID_ENGINE : er->to;
}

@ -56,9 +56,6 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
{
assert(Engine::IsValidID(from) && Engine::IsValidID(to));
/* we can't replace an engine into itself (that would be autorenew) */
if (from == to) return false;
const Engine *e_from = Engine::Get(from);
const Engine *e_to = Engine::Get(to);
VehicleType type = e_from->type;

@ -2544,6 +2544,70 @@ struct CompanyWindow : Window
}
}
void DrawVehicleCountsWidget(const Rect &r, const Company *c) const
{
static_assert(VEH_COMPANY_END == lengthof(_company_view_vehicle_count_strings));
int y = r.top;
for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
uint amount = c->group_all[type].num_vehicle;
if (amount != 0) {
SetDParam(0, amount);
DrawString(r.left, r.right, y, _company_view_vehicle_count_strings[type]);
y += FONT_HEIGHT_NORMAL;
}
}
if (y == r.top) {
/* No String was emited before, so there must be no vehicles at all. */
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
}
}
void DrawInfrastructureCountsWidget(const Rect &r, const Company *c) const
{
int y = r.top;
uint rail_pieces = c->infrastructure.signal;
for (uint i = 0; i < lengthof(c->infrastructure.rail); i++) rail_pieces += c->infrastructure.rail[i];
if (rail_pieces != 0) {
SetDParam(0, rail_pieces);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL);
y += FONT_HEIGHT_NORMAL;
}
uint road_pieces = 0;
for (uint i = 0; i < lengthof(c->infrastructure.road); i++) road_pieces += c->infrastructure.road[i];
if (road_pieces != 0) {
SetDParam(0, road_pieces);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD);
y += FONT_HEIGHT_NORMAL;
}
if (c->infrastructure.water != 0) {
SetDParam(0, c->infrastructure.water);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_WATER);
y += FONT_HEIGHT_NORMAL;
}
if (c->infrastructure.station != 0) {
SetDParam(0, c->infrastructure.station);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_STATION);
y += FONT_HEIGHT_NORMAL;
}
if (c->infrastructure.airport != 0) {
SetDParam(0, c->infrastructure.airport);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT);
y += FONT_HEIGHT_NORMAL;
}
if (y == r.top) {
/* No String was emited before, so there must be no infrastructure at all. */
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
}
}
void DrawWidget(const Rect &r, int widget) const override
{
const Company *c = Company::Get((CompanyID)this->window_number);
@ -2565,70 +2629,13 @@ struct CompanyWindow : Window
break;
}
case WID_C_DESC_VEHICLE_COUNTS: {
uint amounts[4];
amounts[0] = c->group_all[VEH_TRAIN].num_vehicle;
amounts[1] = c->group_all[VEH_ROAD].num_vehicle;
amounts[2] = c->group_all[VEH_SHIP].num_vehicle;
amounts[3] = c->group_all[VEH_AIRCRAFT].num_vehicle;
int y = r.top;
if (amounts[0] + amounts[1] + amounts[2] + amounts[3] == 0) {
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
} else {
static_assert(lengthof(amounts) == lengthof(_company_view_vehicle_count_strings));
for (uint i = 0; i < lengthof(amounts); i++) {
if (amounts[i] != 0) {
SetDParam(0, amounts[i]);
DrawString(r.left, r.right, y, _company_view_vehicle_count_strings[i]);
y += FONT_HEIGHT_NORMAL;
}
}
}
case WID_C_DESC_VEHICLE_COUNTS:
DrawVehicleCountsWidget(r, c);
break;
}
case WID_C_DESC_INFRASTRUCTURE_COUNTS: {
uint y = r.top;
/* Collect rail and road counts. */
uint rail_pieces = c->infrastructure.signal;
uint road_pieces = 0;
for (uint i = 0; i < lengthof(c->infrastructure.rail); i++) rail_pieces += c->infrastructure.rail[i];
for (uint i = 0; i < lengthof(c->infrastructure.road); i++) road_pieces += c->infrastructure.road[i];
if (rail_pieces == 0 && road_pieces == 0 && c->infrastructure.water == 0 && c->infrastructure.station == 0 && c->infrastructure.airport == 0) {
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
} else {
if (rail_pieces != 0) {
SetDParam(0, rail_pieces);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL);
y += FONT_HEIGHT_NORMAL;
}
if (road_pieces != 0) {
SetDParam(0, road_pieces);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD);
y += FONT_HEIGHT_NORMAL;
}
if (c->infrastructure.water != 0) {
SetDParam(0, c->infrastructure.water);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_WATER);
y += FONT_HEIGHT_NORMAL;
}
if (c->infrastructure.station != 0) {
SetDParam(0, c->infrastructure.station);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_STATION);
y += FONT_HEIGHT_NORMAL;
}
if (c->infrastructure.airport != 0) {
SetDParam(0, c->infrastructure.airport);
DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT);
}
}
case WID_C_DESC_INFRASTRUCTURE_COUNTS:
DrawInfrastructureCountsWidget(r, c);
break;
}
case WID_C_DESC_OWNERS: {
uint y = r.top;

@ -19,6 +19,7 @@
#include "game_info.hpp"
#include "table/strings.h"
#include "table/strgen_tables.h"
#include <stdarg.h>
#include <memory>
@ -273,6 +274,31 @@ GameStrings *LoadTranslations()
}
}
static StringParam::ParamType GetParamType(const CmdStruct *cs)
{
if (cs->value == SCC_RAW_STRING_POINTER) return StringParam::RAW_STRING;
if (cs->value == SCC_STRING || cs != TranslateCmdForCompare(cs)) return StringParam::STRING;
return StringParam::OTHER;
}
static void ExtractStringParams(const StringData &data, StringParamsList &params)
{
for (size_t i = 0; i < data.max_strings; i++) {
const LangString *ls = data.strings[i];
if (ls != nullptr) {
StringParams &param = params.emplace_back();
ParsedCommandStruct pcs;
ExtractCommandString(&pcs, ls->english, false);
for (const CmdStruct *cs : pcs.cmd) {
if (cs == nullptr) break;
param.emplace_back(GetParamType(cs), cs->consumes);
}
}
}
}
/** Compile the language. */
void GameStrings::Compile()
{
@ -283,6 +309,8 @@ void GameStrings::Compile()
this->version = data.Version();
ExtractStringParams(data, this->string_params);
StringNameWriter id_writer(this->string_names);
id_writer.WriteHeader(data);
@ -312,6 +340,20 @@ const char *GetGameStringPtr(uint id)
return _current_data->cur_language->lines[id].c_str();
}
/**
* Get the string parameters of a particular game string.
* @param id The ID of the game string.
* @return The string parameters.
*/
const StringParams &GetGameStringParams(uint id)
{
/* An empty result for STR_UNDEFINED. */
static StringParams empty;
if (id >= _current_data->string_params.size()) return empty;
return _current_data->string_params[id];
}
/**
* Register the current translation to the Squirrel engine.
* @param engine The engine to update/

@ -12,7 +12,23 @@
#include "../core/smallvec_type.hpp"
struct StringParam {
enum ParamType {
RAW_STRING,
STRING,
OTHER
};
ParamType type;
uint8 consumes;
StringParam(ParamType type, uint8 consumes) : type(type), consumes(consumes) {}
};
using StringParams = std::vector<StringParam>;
using StringParamsList = std::vector<StringParams>;
const char *GetGameStringPtr(uint id);
const StringParams &GetGameStringParams(uint id);
void RegisterGameTranslation(class Squirrel *engine);
void ReconsiderGameScriptLanguage();
@ -37,6 +53,7 @@ struct GameStrings {
std::vector<LanguageStrings> raw_strings; ///< The raw strings per language, first must be English/the master language!.
std::vector<LanguageStrings> compiled_strings; ///< The compiled strings per language, first must be English/the master language!.
StringList string_names; ///< The names of the compiled strings.
StringParamsList string_params; ///< The parameters for the strings.
void Compile();

@ -189,11 +189,13 @@ void GamelogPrint(GamelogPrintProc *proc)
switch (lc->ct) {
default: NOT_REACHED();
case GLCT_MODE:
/* Changing landscape, or going from scenario editor to game or back. */
buf += seprintf(buf, lastof(buffer), "New game mode: %u landscape: %u",
(uint)lc->mode.mode, (uint)lc->mode.landscape);
break;
case GLCT_REVISION:
/* The game was loaded in a diffferent version than before. */
buf += seprintf(buf, lastof(buffer), "Revision text changed to %s, savegame version %u, ",
lc->revision.text, lc->revision.slver);
@ -207,6 +209,7 @@ void GamelogPrint(GamelogPrintProc *proc)
break;
case GLCT_OLDVER:
/* The game was loaded from before 0.7.0-beta1. */
buf += seprintf(buf, lastof(buffer), "Conversion from ");
switch (lc->oldver.type) {
default: NOT_REACHED();
@ -237,10 +240,12 @@ void GamelogPrint(GamelogPrintProc *proc)
break;
case GLCT_SETTING:
/* A setting with the SF_NO_NETWORK flag got changed; these settings usually affect NewGRFs, such as road side or wagon speed limits. */
buf += seprintf(buf, lastof(buffer), "Setting changed: %s : %d -> %d", lc->setting.name, lc->setting.oldval, lc->setting.newval);
break;
case GLCT_GRFADD: {
/* A NewGRF got added to the game, either at the start of the game (never an issue), or later on when it could be an issue. */
const GRFConfig *gc = FindGRFConfig(lc->grfadd.grfid, FGCM_EXACT, lc->grfadd.md5sum);
buf += seprintf(buf, lastof(buffer), "Added NewGRF: ");
buf = PrintGrfInfo(buf, lastof(buffer), lc->grfadd.grfid, lc->grfadd.md5sum, gc);
@ -251,6 +256,7 @@ void GamelogPrint(GamelogPrintProc *proc)
}
case GLCT_GRFREM: {
/* A NewGRF got removed from the game, either manually or by it missing when loading the game. */
GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
buf += seprintf(buf, lastof(buffer), la->at == GLAT_LOAD ? "Missing NewGRF: " : "Removed NewGRF: ");
buf = PrintGrfInfo(buf, lastof(buffer), lc->grfrem.grfid, nullptr, gm != grf_names.End() ? gm->second.gc : nullptr);
@ -268,6 +274,7 @@ void GamelogPrint(GamelogPrintProc *proc)
}
case GLCT_GRFCOMPAT: {
/* Another version of the same NewGRF got loaded. */
const GRFConfig *gc = FindGRFConfig(lc->grfadd.grfid, FGCM_EXACT, lc->grfadd.md5sum);
buf += seprintf(buf, lastof(buffer), "Compatible NewGRF loaded: ");
buf = PrintGrfInfo(buf, lastof(buffer), lc->grfcompat.grfid, lc->grfcompat.md5sum, gc);
@ -277,6 +284,7 @@ void GamelogPrint(GamelogPrintProc *proc)
}
case GLCT_GRFPARAM: {
/* A parameter of a NewGRF got changed after the game was started. */
GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
buf += seprintf(buf, lastof(buffer), "GRF parameter changed: ");
buf = PrintGrfInfo(buf, lastof(buffer), lc->grfparam.grfid, nullptr, gm != grf_names.End() ? gm->second.gc : nullptr);
@ -285,6 +293,7 @@ void GamelogPrint(GamelogPrintProc *proc)
}
case GLCT_GRFMOVE: {
/* The order of NewGRFs got changed, which might cause some other NewGRFs to behave differently. */
GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
buf += seprintf(buf, lastof(buffer), "GRF order changed: %08X moved %d places %s",
BSWAP32(lc->grfmove.grfid), abs(lc->grfmove.offset), lc->grfmove.offset >= 0 ? "down" : "up" );
@ -294,6 +303,7 @@ void GamelogPrint(GamelogPrintProc *proc)
}
case GLCT_GRFBUG: {
/* A specific bug in a NewGRF, that could cause wide spread problems, has been noted during the execution of the game. */
GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
switch (lc->grfbug.bug) {
default: NOT_REACHED();
@ -307,6 +317,8 @@ void GamelogPrint(GamelogPrintProc *proc)
}
case GLCT_EMERGENCY:
/* At one point the savegame was made during the handling of a game crash.
* The generic code already mentioned the emergency savegame, and there is no extra information to log. */
break;
}

@ -556,171 +556,194 @@ static bool TransportIndustryGoods(TileIndex tile)
return moved_cargo;
}
static void AnimateSugarSieve(TileIndex tile)
{
byte m = GetAnimationFrame(tile) + 1;
void AnimateTile_Industry(TileIndex tile)
if (_settings_client.sound.ambient) {
switch (m & 7) {
case 2: SndPlayTileFx(SND_2D_SUGAR_MINE_1, tile); break;
case 6: SndPlayTileFx(SND_29_SUGAR_MINE_2, tile); break;
}
}
if (m >= 96) {
m = 0;
DeleteAnimatedTile(tile);
}
SetAnimationFrame(tile, m);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
static void AnimateToffeeQuarry(TileIndex tile)
{
IndustryGfx gfx = GetIndustryGfx(tile);
byte m = GetAnimationFrame(tile);
if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
AnimateNewIndustryTile(tile);
return;
if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
SndPlayTileFx(SND_30_TOFFEE_QUARRY, tile);
}
switch (gfx) {
case GFX_SUGAR_MINE_SIEVE:
if ((_scaled_tick_counter & 1) == 0) {
byte m = GetAnimationFrame(tile) + 1;
if (++m >= 70) {
m = 0;
DeleteAnimatedTile(tile);
}
SetAnimationFrame(tile, m);
if (_settings_client.sound.ambient) {
switch (m & 7) {
case 2: SndPlayTileFx(SND_2D_SUGAR_MINE_1, tile); break;
case 6: SndPlayTileFx(SND_29_SUGAR_MINE_2, tile); break;
}
}
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
if (m >= 96) {
m = 0;
DeleteAnimatedTile(tile);
}
SetAnimationFrame(tile, m);
static void AnimateBubbleCatcher(TileIndex tile)
{
byte m = GetAnimationFrame(tile);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
break;
if (++m >= 40) {
m = 0;
DeleteAnimatedTile(tile);
}
SetAnimationFrame(tile, m);
case GFX_TOFFEE_QUARY:
if ((_scaled_tick_counter & 3) == 0) {
byte m = GetAnimationFrame(tile);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
SndPlayTileFx(SND_30_TOFFEE_QUARRY, tile);
}
static void AnimatePowerPlantSparks(TileIndex tile)
{
byte m = GetAnimationFrame(tile);
if (m == 6) {
SetAnimationFrame(tile, 0);
DeleteAnimatedTile(tile);
} else {
SetAnimationFrame(tile, m + 1);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
}
if (++m >= 70) {
static void AnimateToyFactory(TileIndex tile)
{
byte m = GetAnimationFrame(tile) + 1;
switch (m) {
case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_TOY_FACTORY_1, tile); break;
case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_TOY_FACTORY_2, tile); break;
case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_TOY_FACTORY_3, tile); break;
default:
if (m >= 50) {
int n = GetIndustryAnimationLoop(tile) + 1;
m = 0;
DeleteAnimatedTile(tile);
if (n >= 8) {
n = 0;
DeleteAnimatedTile(tile);
}
SetIndustryAnimationLoop(tile, n);
}
SetAnimationFrame(tile, m);
}
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
break;
SetAnimationFrame(tile, m);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
case GFX_BUBBLE_CATCHER:
if ((_scaled_tick_counter & 1) == 0) {
byte m = GetAnimationFrame(tile);
static void AnimatePlasticFountain(TileIndex tile, IndustryGfx gfx)
{
gfx = (gfx < GFX_PLASTIC_FOUNTAIN_ANIMATED_8) ? gfx + 1 : GFX_PLASTIC_FOUNTAIN_ANIMATED_1;
SetIndustryGfx(tile, gfx);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
if (++m >= 40) {
m = 0;
DeleteAnimatedTile(tile);
}
SetAnimationFrame(tile, m);
static void AnimateOilWell(TileIndex tile, IndustryGfx gfx)
{
bool b = Chance16(1, 7);
byte m = GetAnimationFrame(tile) + 1;
if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
SetIndustryConstructionStage(tile, 3);
DeleteAnimatedTile(tile);
} else {
SetAnimationFrame(tile, m);
SetIndustryGfx(tile, gfx);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
}
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
break;
static void AnimateMineTower(TileIndex tile)
{
int state = _scaled_tick_counter & 0x7FF;
/* Sparks on a coal plant */
case GFX_POWERPLANT_SPARKS:
if ((_scaled_tick_counter & 3) == 0) {
if ((state -= 0x400) < 0) return;
if (state < 0x1A0) {
if (state < 0x20 || state >= 0x180) {
byte m = GetAnimationFrame(tile);
if (m == 6) {
SetAnimationFrame(tile, 0);
DeleteAnimatedTile(tile);
} else {
SetAnimationFrame(tile, m + 1);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
if (!(m & 0x40)) {
SetAnimationFrame(tile, m | 0x40);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINE, tile);
}
if (state & 7) return;
} else {
if (state & 3) return;
}
byte m = (GetAnimationFrame(tile) + 1) | 0x40;
if (m > 0xC2) m = 0xC0;
SetAnimationFrame(tile, m);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
} else if (state >= 0x200 && state < 0x3A0) {
int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
if (state & i) return;
byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
if (m < 0x80) m = 0x82;
SetAnimationFrame(tile, m);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
}
void AnimateTile_Industry(TileIndex tile)
{
IndustryGfx gfx = GetIndustryGfx(tile);
if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
AnimateNewIndustryTile(tile);
return;
}
switch (gfx) {
case GFX_SUGAR_MINE_SIEVE:
if ((_scaled_tick_counter & 1) == 0) AnimateSugarSieve(tile);
break;
case GFX_TOY_FACTORY:
if ((_scaled_tick_counter & 1) == 0) {
byte m = GetAnimationFrame(tile) + 1;
switch (m) {
case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_TOY_FACTORY_1, tile); break;
case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_TOY_FACTORY_2, tile); break;
case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_TOY_FACTORY_3, tile); break;
default:
if (m >= 50) {
int n = GetIndustryAnimationLoop(tile) + 1;
m = 0;
if (n >= 8) {
n = 0;
DeleteAnimatedTile(tile);
}
SetIndustryAnimationLoop(tile, n);
}
}
case GFX_TOFFEE_QUARY:
if ((_scaled_tick_counter & 3) == 0) AnimateToffeeQuarry(tile);
break;
SetAnimationFrame(tile, m);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
case GFX_BUBBLE_CATCHER:
if ((_scaled_tick_counter & 1) == 0) AnimateBubbleCatcher(tile);
break;
case GFX_POWERPLANT_SPARKS:
if ((_scaled_tick_counter & 3) == 0) AnimatePowerPlantSparks(tile);
break;
case GFX_TOY_FACTORY:
if ((_scaled_tick_counter & 1) == 0) AnimateToyFactory(tile);
break;
case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
if ((_scaled_tick_counter & 3) == 0) {
IndustryGfx new_gfx = (gfx < 155) ? gfx + 1 : 148;
SetIndustryGfx(tile, new_gfx);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
if ((_scaled_tick_counter & 3) == 0) AnimatePlasticFountain(tile, gfx);
break;
case GFX_OILWELL_ANIMATED_1:
case GFX_OILWELL_ANIMATED_2:
case GFX_OILWELL_ANIMATED_3:
if ((_scaled_tick_counter & 7) == 0) {
bool b = Chance16(1, 7);
byte m = GetAnimationFrame(tile) + 1;
if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
SetIndustryConstructionStage(tile, 3);
DeleteAnimatedTile(tile);
} else {
SetAnimationFrame(tile, m);
SetIndustryGfx(tile, gfx);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
}
if ((_scaled_tick_counter & 7) == 0) AnimateOilWell(tile, gfx);
break;
case GFX_COAL_MINE_TOWER_ANIMATED:
case GFX_COPPER_MINE_TOWER_ANIMATED:
case GFX_GOLD_MINE_TOWER_ANIMATED: {
int state = _scaled_tick_counter & 0x7FF;
if ((state -= 0x400) < 0) return;
if (state < 0x1A0) {
if (state < 0x20 || state >= 0x180) {
byte m = GetAnimationFrame(tile);
if (!(m & 0x40)) {
SetAnimationFrame(tile, m | 0x40);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINE, tile);
}
if (state & 7) return;
} else {
if (state & 3) return;
}
byte m = (GetAnimationFrame(tile) + 1) | 0x40;
if (m > 0xC2) m = 0xC0;
SetAnimationFrame(tile, m);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
} else if (state >= 0x200 && state < 0x3A0) {
int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
if (state & i) return;
byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
if (m < 0x80) m = 0x82;
SetAnimationFrame(tile, m);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
}
break;
}
case GFX_GOLD_MINE_TOWER_ANIMATED:
AnimateMineTower(tile);
break;
}
}

@ -39,6 +39,8 @@
#include "widgets/industry_widget.h"
#include "clear_map.h"
#include "zoom_func.h"
#include "querystring_gui.h"
#include "stringfilter_type.h"
#include "table/strings.h"
@ -1248,12 +1250,17 @@ static const NWidgetPart _nested_industry_directory_widgets[] = {
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_ID_DROPDOWN_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_ID_DROPDOWN_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_ID_FILTER_BY_ACC_CARGO), SetMinimalSize(225, 12), SetFill(0, 1), SetDataTip(STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER, STR_TOOLTIP_FILTER_CRITERIA),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_ID_FILTER_BY_PROD_CARGO), SetMinimalSize(225, 12), SetFill(0, 1), SetDataTip(STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER, STR_TOOLTIP_FILTER_CRITERIA),
NWidget(WWT_PANEL, COLOUR_BROWN), SetResize(1, 0), EndContainer(),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_ID_DROPDOWN_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_ID_DROPDOWN_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_ID_FILTER), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_ID_FILTER_BY_ACC_CARGO), SetMinimalSize(225, 12), SetFill(0, 1), SetDataTip(STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER, STR_TOOLTIP_FILTER_CRITERIA),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_ID_FILTER_BY_PROD_CARGO), SetMinimalSize(225, 12), SetFill(0, 1), SetDataTip(STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER, STR_TOOLTIP_FILTER_CRITERIA),
NWidget(WWT_PANEL, COLOUR_BROWN), SetResize(1, 0), EndContainer(),
EndContainer(),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_ID_INDUSTRY_LIST), SetDataTip(0x0, STR_INDUSTRY_DIRECTORY_LIST_CAPTION), SetResize(1, 1), SetScrollbar(WID_ID_SCROLLBAR), EndContainer(),
EndContainer(),
@ -1349,6 +1356,10 @@ protected:
byte accepted_cargo_filter_criteria; ///< Selected accepted cargo filter index
static CargoID produced_cargo_filter;
const int MAX_FILTER_LENGTH = 16; ///< The max length of the filter, in chars
StringFilter string_filter; ///< Filter for industries
QueryString industry_editbox; ///< Filter editbox
enum class SorterType : uint8 {
ByName, ///< Sorter type to sort by name
ByType, ///< Sorter type to sort by type
@ -1433,7 +1444,13 @@ protected:
this->industries.clear();
for (const Industry *i : Industry::Iterate()) {
this->industries.push_back(i);
if (this->string_filter.IsEmpty()) {
this->industries.push_back(i);
continue;
}
this->string_filter.ResetState();
this->string_filter.AddLine(i->GetCachedName());
if (this->string_filter.GetState()) this->industries.push_back(i);
}
this->industries.shrink_to_fit();
@ -1633,7 +1650,7 @@ protected:
}
public:
IndustryDirectoryWindow(WindowDesc *desc, WindowNumber number) : Window(desc)
IndustryDirectoryWindow(WindowDesc *desc, WindowNumber number) : Window(desc), industry_editbox(MAX_FILTER_LENGTH * MAX_CHAR_LENGTH, MAX_FILTER_LENGTH)
{
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_ID_SCROLLBAR);
@ -1644,6 +1661,9 @@ public:
this->BuildSortIndustriesList();
this->FinishInitNested(0);
this->querystrings[WID_ID_FILTER] = &this->industry_editbox;
this->industry_editbox.cancel_button = QueryString::ACTION_CLEAR;
}
~IndustryDirectoryWindow()
@ -1809,6 +1829,14 @@ public:
this->vscroll->SetCapacityFromWidget(this, WID_ID_INDUSTRY_LIST);
}
void OnEditboxChanged(int wid) override
{
if (wid == WID_ID_FILTER) {
this->string_filter.SetFilterTerm(this->industry_editbox.text.buf);
this->InvalidateData(IDIWD_FORCE_REBUILD);
}
}
void OnPaint() override
{
if (this->industries.NeedRebuild()) this->BuildSortIndustriesList();

@ -930,12 +930,15 @@ static void GenerateTerrain(int type, uint flag)
{
uint32 r = Random();
const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845, ST_MAPGEN);
/* Choose one of the templates from the graphics file. */
const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + SPR_MAPGEN_BEGIN, ST_MAPGEN);
if (templ == nullptr) usererror("Map generator sprites could not be loaded");
/* Chose a random location to apply the template to. */
uint x = r & MapMaxX();
uint y = (r >> MapLogX()) & MapMaxY();
/* Make sure the template is not too close to the upper edges; bottom edges are checked later. */
uint edge_distance = 1 + (_settings_game.construction.freeform_edges ? 1 : 0);
if (x <= edge_distance || y <= edge_distance) return;
@ -948,6 +951,9 @@ static void GenerateTerrain(int type, uint flag)
const byte *p = templ->data;
if ((flag & 4) != 0) {
/* This is only executed in secondary/tertiary loops to generate the terrain for arctic and tropic.
* It prevents the templates to be applied to certain parts of the map based on the flags, thus
* creating regions with different elevations/topography. */
uint xw = x * MapSizeY();
uint yw = y * MapSizeX();
uint bias = (MapSizeX() + MapSizeY()) * 16;
@ -972,11 +978,15 @@ static void GenerateTerrain(int type, uint flag)
}
}
/* Ensure the template does not overflow at the bottom edges of the map; upper edges were checked before. */
if (x + w >= MapMaxX()) return;
if (y + h >= MapMaxY()) return;
TileIndex tile = TileXY(x, y);
/* Get the template and overlay in a particular direction over the map's height from the given
* origin point (tile), and update the map's height everywhere where the height from the template
* is higher than the height of the map. In other words, this only raises the tile heights. */
switch (direction) {
default: NOT_REACHED();
case DIAGDIR_NE:

@ -2359,7 +2359,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova empresa)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Cria uma nova empresa e se une a ela
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Esse é você
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Esse é o hospedeiro do jogo
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} cliente{P "" s} / {NUM} empresa{P "" s}
# Matches ConnectionType
###length 5

@ -2359,7 +2359,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Companyia nova
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crea una companyia nova i uniu-vos.
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Aquest ets tu.
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Aquest és l'hoste de la partida.
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} / {NUM} companyi{P a es}
# Matches ConnectionType
###length 5

@ -2445,7 +2445,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nová společn
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Vytvořit novou společnost a připojit se do ní
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Tohle jsi ty
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Toto je hostitel hry
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" i i} / {NUM} společnost{P “” i i}
# Matches ConnectionType
###length 5

@ -2320,7 +2320,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nyt selskab)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Etabler et nyt selskab og tilslut dig det
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dette er dig
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dette er værten for dette spil
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" er} / {NUM} selskab{P "" er}
# Matches ConnectionType
###length 5

@ -2358,7 +2358,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nieuw bedrijf)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Een nieuw bedrijf maken en meedoen
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dit ben jij
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dit is de host van het spel
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} speler{P "" s} / {NUM} bedrij{P f ven}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} speler{P "" s} - {NUM}/{NUM} bedrij{P f ven}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}Het aantal momenteel verbonden clients, het aantal bedrijven en het maximale aantal toegestane bedrijven door de serverbeheerder
# Matches ConnectionType
###length 5

@ -2358,7 +2358,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(New company)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Create a new company and join it
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}This is you
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}This is the host of the game
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} / {NUM} compan{P y ies}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} - {NUM}/{NUM} compan{P y ies}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}The number of currently connected clients, number of companies and maximum number of companies allowed by the server administrator
# Matches ConnectionType
###length 5
@ -5084,6 +5085,20 @@ STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Can't co
STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... too far from previous destination
STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... aircraft has not enough range
# Extra messages which go on the third line of errors, explaining why orders failed
STR_ERROR_NO_RAIL_STATION :{WHITE}There is no railway station
STR_ERROR_NO_BUS_STATION :{WHITE}There is no bus station
STR_ERROR_NO_TRUCK_STATION :{WHITE}There is no lorry station
STR_ERROR_NO_DOCK :{WHITE}There is no dock
STR_ERROR_NO_AIRPORT :{WHITE}There is no airport/heliport
STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}There are no stops with a compatible road type
STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE :{WHITE}There are no stops with a compatible tram type
STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}There are no stops which are suitable for articulated road vehicles.{}Articulated road vehicles require a drive-through stop, not a bay stop
STR_ERROR_AIRPORT_NO_PLANES :{WHITE}This plane cannot land at this heliport
STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}This helicopter cannot land at this airport
STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}There is no railway waypoint
STR_ERROR_NO_BUOY :{WHITE}There is no buoy
# Timetable related errors
STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Can't timetable vehicle...
STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS :{WHITE}Vehicles can only wait at stations

@ -2358,7 +2358,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(New company)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Create a new company and join it
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}This is you
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}This is the host of the game
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} / {NUM} compan{P y ies}
# Matches ConnectionType
###length 5

@ -2358,7 +2358,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(New company)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Create a new company and join it
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}This is you
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}This is the host of the game
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} / {NUM} compan{P y ies}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} - {NUM}/{NUM} compan{P y ies}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}The number of currently connected clients, number of companies and maximum number of companies allowed by the server administrator
# Matches ConnectionType
###length 5

@ -2415,7 +2415,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Uus ettevõte)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Loo uus ettevõte ja liitu sellega
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Tema oled sina
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Tema on mängu korraldaja
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" i} / {NUM} ettevõt{P e teid}
# Matches ConnectionType
###length 5

@ -1746,18 +1746,7 @@ STR_ERROR_DEPOT_HAS_WRONG_RAIL_TYPE :{WHITE}Depot ca
STR_ERROR_CANNOT_MODIFY_TRACK_TRAIN_APPROACHING :{WHITE}Moving train approaching...
STR_ERROR_NO_RAIL_STATION :{WHITE}There is no railway station...
STR_ERROR_NO_BUS_STATION :{WHITE}There is no bus station...
STR_ERROR_NO_TRUCK_STATION :{WHITE}There is no lorry station...
STR_ERROR_NO_DOCK :{WHITE}There is no dock...
STR_ERROR_NO_AIRPORT :{WHITE}There is no airport/heliport...
STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}There are no stops with a compatible road/tram type...
STR_ERROR_NO_STOP_ARTIC_VEH :{WHITE}There are no stops which are suitable for articulated road vehicles.{}Articulated road vehicles require a drive-through stop, not a bay stop...
STR_ERROR_AIRPORT_NO_PLANES :{WHITE}This plane cannot land at this heliport...
STR_ERROR_AIRPORT_NO_HELIS :{WHITE}This helicopter cannot land at this airport...
STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}There is no railway waypoint...
STR_ERROR_NO_ROAD_WAYPOINT :{WHITE}There is no road waypoint...
STR_ERROR_NO_BUOY :{WHITE}There is no buoy...
STR_ERROR_NO_ROAD_WAYPOINT :{WHITE}There is no road waypoint
# Plan related errors
STR_ERROR_TOO_MANY_PLANS :{WHITE}... too many plans

@ -1705,9 +1705,9 @@ STR_ERROR_NO_TRUCK_STATION :{WHITE}Non hai
STR_ERROR_NO_DOCK :{WHITE}Non hai porto...
STR_ERROR_NO_AIRPORT :{WHITE}Non hai aeroporto/heliporto...
STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}Non hai paradas con un tipo de estrada/tranvía compatible...
STR_ERROR_NO_STOP_ARTIC_VEH :{WHITE}Non hai paradas axeitadas para vehículos articulados de estrada.{}Os vehículos de estrada articulados requiren unha parada de vía, non unha estación terminal/baía.
STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}Non hai paradas axeitadas para vehículos articulados de estrada.{}Os vehículos de estrada articulados requiren unha parada de vía, non unha estación terminal/baía.
STR_ERROR_AIRPORT_NO_PLANES :{WHITE}Este avión non pode aterrar neste heliporto...
STR_ERROR_AIRPORT_NO_HELIS :{WHITE}Este helicóptero non pode aterrar neste aeroporto...
STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}Este helicóptero non pode aterrar neste aeroporto...
STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}Non hai punto de ruta de ferrocarril...
STR_ERROR_NO_ROAD_WAYPOINT :{WHITE}Non hai punto de ruta de estrada...
STR_ERROR_NO_BUOY :{WHITE}Non hai boia...

@ -1615,9 +1615,9 @@ STR_ERROR_NO_TRUCK_STATION :{WHITE}Da ist k
STR_ERROR_NO_DOCK :{WHITE}Da ist kein dock ...
STR_ERROR_NO_AIRPORT :{WHITE}Da ist kein Flughafen/Heliport ...
STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}Da ist kein Station eines kompatiblen Straßen- oder Straßenbahngleistyps ...
STR_ERROR_NO_STOP_ARTIC_VEH :{WHITE}Da sind keine Stationsfelder, die für Gelenkfahrzeuge geeinget sind.{}Gelenkfahrzeuge benötigen eine Durchfahrtsstation, nicht solche mit einer Haltebucht ...
STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}Da sind keine Stationsfelder, die für Gelenkfahrzeuge geeinget sind.{}Gelenkfahrzeuge benötigen eine Durchfahrtsstation, nicht solche mit einer Haltebucht ...
STR_ERROR_AIRPORT_NO_PLANES :{WHITE}Das Flugzeug kann auf diesem Heliport nicht landen ...
STR_ERROR_AIRPORT_NO_HELIS :{WHITE}Der Hubschrauber kann auf diesem Flugplatz nicht landen ...
STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}Der Hubschrauber kann auf diesem Flugplatz nicht landen ...
STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}Da ist kein Wegpunkt ...
STR_ERROR_NO_ROAD_WAYPOINT :{WHITE}Da ist kein Wegpunkt ...
STR_ERROR_NO_BUOY :{WHITE}Da ist keine Boye ...

@ -1711,9 +1711,9 @@ STR_ERROR_NO_TRUCK_STATION :{WHITE}트럭
STR_ERROR_NO_DOCK :{WHITE}항구가 없습니다...
STR_ERROR_NO_AIRPORT :{WHITE}공항/헬리포트가 없습니다...
STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}도로/전차 종류에 맞는 정거장이 없습니다...
STR_ERROR_NO_STOP_ARTIC_VEH :{WHITE}굴절 차량이 들어갈 수 있는 정거장이 없습니다.{}굴절 차량은 터미널식 정류장이 아니라 통과식 정류장을 써야 합니다...
STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}굴절 차량이 들어갈 수 있는 정거장이 없습니다.{}굴절 차량은 터미널식 정류장이 아니라 통과식 정류장을 써야 합니다...
STR_ERROR_AIRPORT_NO_PLANES :{WHITE}이 항공기는 이 헬리포트에 착륙할 수 없습니다...
STR_ERROR_AIRPORT_NO_HELIS :{WHITE}이 헬리콥터는 이 공항에 착륙할 수 없습니다...
STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}이 헬리콥터는 이 공항에 착륙할 수 없습니다...
STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}철도 경유지가 없습니다...
STR_ERROR_NO_ROAD_WAYPOINT :{WHITE}도로 경유지가 없습니다...
STR_ERROR_NO_BUOY :{WHITE}부표가 없습니다...

@ -1700,9 +1700,9 @@ STR_ERROR_NO_TRUCK_STATION :{WHITE}没有
STR_ERROR_NO_DOCK :{WHITE}没有港口...
STR_ERROR_NO_AIRPORT :{WHITE}没有机场或者直升机场...
STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}没有兼容的道路/电车道类型的站点...
STR_ERROR_NO_STOP_ARTIC_VEH :{WHITE}这里没有适用于铰接式的道路车辆的站点。{}铰接式道路车辆需要一个直通式站点而不是港湾式站点...
STR_ERROR_NO_STOP_ARTICULATED_VEHICLE :{WHITE}这里没有适用于铰接式的道路车辆的站点。{}铰接式道路车辆需要一个直通式站点而不是港湾式站点...
STR_ERROR_AIRPORT_NO_PLANES :{WHITE}这架飞机不能在这个直升机场着陆...
STR_ERROR_AIRPORT_NO_HELIS :{WHITE}这架直升机不能在这个机场着陆...
STR_ERROR_AIRPORT_NO_HELICOPTERS :{WHITE}这架直升机不能在这个机场着陆...
STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}这里没有铁道路点...
STR_ERROR_NO_ROAD_WAYPOINT :{WHITE}这里没有公路路点...
STR_ERROR_NO_BUOY :{WHITE}这里没有浮漂...

@ -2358,7 +2358,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Uusi yhtiö)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Perusta uusi yhtiö ja liity siihen
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Tämä olet sinä
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Tämä on pelin ylläpitäjä
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} pelaaja{P "" a} / {NUM} yhtiö{P "" tä}
# Matches ConnectionType
###length 5

@ -2359,7 +2359,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nouvelle compa
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Créer une nouvelle compagnie et la rejoindre
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}C'est vous
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}C'est l'hôte du jeu
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} / {NUM} compagnie{P "" s}
# Matches ConnectionType
###length 5
@ -3353,6 +3352,8 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING
STR_NEWGRF_ERROR_MSG_WARNING :{RED}Attention{NBSP}: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Erreur{NBSP}: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Erreur fatale{NBSP}: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Le NewGRF "{STRING}" a retourné une erreur fatale{NBSP}:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Le NewGRF "{STRING}" a retourné une erreur{NBSP}:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} ne fonctionnera pas avec la version de TTDPatch rapportée par OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} est conçu pour la version {2:STRING} de TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} est conçu pour être utilisé avec {2:STRING}
@ -4528,7 +4529,7 @@ STR_TIMETABLE_CLEAR_SPEED :{BLACK}Annuler
STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Annuler la vitesse maximale de déplacement de l'ordre sélectionné. Ctrl-clic pour annuler la vitesse de tous les ordres
STR_TIMETABLE_RESET_LATENESS :{BLACK}RAZ compteur de retard
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Remettre à zéro le compteur de retard (le véhicule sera donc à l'heure)
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Remettre à zéro le compteur de retard, le véhicule sera donc à l'heure. Ctrl-clic pour remettre à zéro le groupe entier, le véhicule le plus en retard sera donc à l'heure et les autres en avance
STR_TIMETABLE_AUTOFILL :{BLACK}Autoremplir
STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Remplir l'horaire automatiquement avec les valeurs du prochain trajet. Ctrl-clic pour essayer de préserver les temps d'attente

@ -2103,7 +2103,6 @@ STR_NETWORK_CLIENT_LIST_SERVER_NAME_TOOLTIP :{BLACK}Namme fa
STR_NETWORK_CLIENT_LIST_SERVER_VISIBILITY :{BLACK}Sichtberheid
STR_NETWORK_CLIENT_LIST_PLAYER_NAME_QUERY_CAPTION :Dyn namme
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dit bisto sels
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klïïnt{P "" en} / {NUM} bedriuw{P "" en}
# Matches ConnectionType
###length 5

@ -2359,7 +2359,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova compañí
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crear unha nova compañía e unirte a ela
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este es ti
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este é o anfitrión da partida
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} cliente{P "" s} / {NUM} compañía{P "" "s"}
# Matches ConnectionType
###length 5

@ -2357,7 +2357,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Neue Firma)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Eine neue Firma gründen und beitreten
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Das sind Sie
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dies ist der Host des Spiels
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} Client{P "" s} / {NUM} Firm{P a en}
# Matches ConnectionType
###length 5

@ -2462,7 +2462,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Νέα ετα
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Δημιουργήστε μία νέα εταιρία και συμμετέχετε σε αυτήν
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Αυτός/η είστε εσείς
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Αυτός/η είναι ο/η οικοδεσπότης του παιχνιδιού
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} πελάτης/ες / {NUM} εταιρία/ες
# Matches ConnectionType
###length 5

@ -2420,7 +2420,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Új vállalat)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Hozz létre egy új vállalatot és csatlakozz
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Ez vagy te
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Ez a játék elindítója
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} kliens / {NUM} vállalat
# Matches ConnectionType
###length 5

@ -2356,7 +2356,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Perusahaan bar
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Ciptakan perusahaan baru dan bergabung
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Ini adalah Anda
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Ini adalah hos permainan
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klien / {NUM} Perusahaan
# Matches ConnectionType
###length 5

@ -2313,7 +2313,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Cuideachta nua
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Cruthaigh cuideachta nua agus téigh isteach ann
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Seo tusa
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Is é seo óstach an chluiche
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} {P ch ch ch gc c}liant / {NUM} {P ch ch ch gc c}uideachta
# Matches ConnectionType
###length 5

@ -2393,7 +2393,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nuova compagni
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crea una nuova compagnia e controllala
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Questo sei tu
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Questo è l'host del gioco
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} / {NUM} compan{P y ies}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} - {NUM}/{NUM} compagni{P a e}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}Il numero di client attualmente connessi, il numero di compagnie e il numero massimo di compagnie consentito dall'amministratore del server.
# Matches ConnectionType
###length 5

@ -2342,7 +2342,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(新規会社
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}新しく会社を設立し参画します
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}これはあなたです
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}ゲームのホストです
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} 個のクライアント / {NUM} 個の企業
# Matches ConnectionType
###length 5

@ -2359,7 +2359,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(새 회사)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}새 회사를 만듭니다
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}당신입니다
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}이 게임을 연 사람입니다
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}접속자 {NUM}명 / 회사 {NUM}개
# Matches ConnectionType
###length 5

@ -2362,7 +2362,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Jauna kompāni
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Izveidot jaunu kompāniju un pievienoties tai
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Tas esat jūs
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Šis ir spēles īpašnieks
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P s а u} / {NUM} kompānij{P a u as}
# Matches ConnectionType
###length 5

@ -1591,7 +1591,7 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Mécht eng Fens
STR_CONFIG_SETTING_AUTOSAVE :Autospäicheren: {STRING}
STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Setz den Interval tëschend automateschen Späicherstänn
STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Benotz {STRING} Datumsformat fir Späichernimm
STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Datumsformat fir Späichernimm: {STRING}
STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_HELPTEXT :Format vum Datum am Numm vum Späicherstand
###length 3
STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_LONG :laang (31ten Dez 2008)
@ -1886,7 +1886,7 @@ STR_CONFIG_SETTING_SOFT_LIMIT_VALUE :{COMMA}
###setting-zero-is-special
STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :ausgeschalt
STR_CONFIG_SETTING_ZOOM_MIN :Maximalen Ranzoom Level: {STRING}
STR_CONFIG_SETTING_ZOOM_MIN :Maximale Razoom Level: {STRING}
STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :Maximal Razoomstuf fir Usiichtsfënsteren. Et gëtt méi Späicher gebraucht wann d'Stufen ze grouss ginn
STR_CONFIG_SETTING_ZOOM_MAX :Maximalen Rauszoom Level: {STRING}
STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :Maximal Rauszoom-Stuf fir Usiichtsfënsteren. Méi grouss Rauszoom-Stufen kënnen Ruckeler verursaachen
@ -2046,7 +2046,7 @@ STR_CONFIG_ERROR_INVALID_GRF_SYSTEM :System NewGRF
STR_CONFIG_ERROR_INVALID_GRF_INCOMPATIBLE :net mat dëser Versioun vun OpenTTD kompatibel
STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN :onbekannt
STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL :{WHITE}... Kompressiounslevel '{STRING}' ass net gültëg.
STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM :{WHITE}... Spillstand format '{STRING}' gëtt et net. Revertéiren zu '{STRING}'
STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM :{WHITE}... Späicherstand format '{STRING}' gëtt et net. Revertéiren zu '{STRING}'
STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND :{WHITE}... ignoréiren Basis Grafik Set '{STRING}': net fonnt
STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND :{WHITE}... ignoréiren Basis Sound Set '{STRING}': net fonnt
STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND :{WHITE}... ignoréiren Basis Musik Set '{STRING}': net fonnt
@ -2114,7 +2114,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Bass du
# Cheat window
STR_CHEATS :{WHITE}Cheater
STR_CHEATS_TOOLTIP :{BLACK}Checkboxen weisen un dass du den Cheat schon eng Kéier benotzt hues
STR_CHEATS_NOTE :{BLACK}Notiz: jeglech Benotzung vun dësen Astellungen wäert am Spillstand opgeholl ginn
STR_CHEATS_NOTE :{BLACK}Notiz: jeglech Benotzung vun dësen Astellungen wäert am Späicherstand opgeholl ginn
STR_CHEAT_MONEY :{LTBLUE}Suen ëm {CURRENCY_LONG} erhéijen
STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Als Firma {ORANGE}{COMMA} spillen
STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magësche Bulldozer (Industrien ofrappen, onzerstéierbar Objeten): {ORANGE}{STRING}
@ -2358,7 +2358,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nei Firma)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Eng nei Firma erstellen an hier bäitrieden
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dat bass du
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dest ass den Host vun der Partie
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} Client{P "" en} / {NUM} Firm{P a en}
# Matches ConnectionType
###length 5
@ -3352,6 +3351,8 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING
STR_NEWGRF_ERROR_MSG_WARNING :{RED}Warnung: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Fehler: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Den NewGRF "{STRING}" huet e fatale Fehler gemet:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Den NewGRF "{STRING}" huet e Fehler gemet:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} wärt net mat der TTDPatch Versioun déi vun OpenTTD erkannt gouf funktionéiren
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} ass fir {2:STRING} Versioun vun TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} ass designed fir mat {2:STRING} benotzt ze ginn
@ -4527,7 +4528,7 @@ STR_TIMETABLE_CLEAR_SPEED :{BLACK}Geschwin
STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Maximal Reesgeschwindegkeet vum gewielten Optrag läschen. Ctrl+Klick läscht d'Geschwindegkeet fir all Opträg
STR_TIMETABLE_RESET_LATENESS :{BLACK}Verspeidungszieler zerécksetzen
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Setzt de Verspéidungszieler zréck, sou dass d'Gefier mat Zäit ukënnt
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Setzt de Verspéidungszieler zréck, sou dass d'Gefier mat Zäit ukënnt. Ctrl+klick setzt déi ganz Grupp zeréck, sou das dat lescht Gefiert pünktlech ass an all déi aner méi fréi.
STR_TIMETABLE_AUTOFILL :{BLACK}Autofëllen
STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fëll den Zäitplang automatesch mat de Wäerter vum nächsten Trajet Ctrl+Klick fir Wardzäiten probéiren bäizehalen
@ -4675,7 +4676,7 @@ STR_ERROR_GAME_SAVE_FAILED :{WHITE}Fehler b
STR_ERROR_UNABLE_TO_DELETE_FILE :{WHITE}Kann d'Datei net läschen
STR_ERROR_GAME_LOAD_FAILED :{WHITE}Fehler beim Lueden{}{STRING}
STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR :Interne Fehler: {STRING}
STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME :Futtissen Spillstand - {STRING}
STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME :Futtissen Späicherstand - {STRING}
STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :Spillstand ass mat enger méi neier Versioun gemaach
STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :Datei net liesbar
STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :Datei net beschreiwbar

@ -2330,7 +2330,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nytt firma)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Opprett et nytt firma og bli med i det
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Dette er deg
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Dette er verten for spillet
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" s} / {NUM} firma{P et er}
# Matches ConnectionType
###length 5

@ -2679,7 +2679,7 @@ STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Dopuszcz
STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Ustaw maksymalną liczbę klientów. Nie wszystkie miejsca muszą być zapełnione.
STR_NETWORK_START_SERVER_COMPANIES_SELECT :{BLACK}{NUM} firm{P a y ""}
STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Maksymalna liczba firm:
STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Ogranicz serwer do określonej ilości firm
STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Ogranicz serwer do określonej liczby firm
STR_NETWORK_START_SERVER_NEW_GAME_NAME_OSKTITLE :{BLACK}Wpisz nazwę dla gry sieciowej
@ -2738,7 +2738,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nowa firma)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Utwórz nową firmę i dołącz do niej
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}To jesteś ty
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}To jest gospodarz gry
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" ów ów} / {NUM} firm{P a y ""}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" ów ów} - {NUM}/{NUM} firm{P ę y ""}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}Liczba aktualnie podłączonych klientów, liczba firm oraz maksymalna liczba firm dozwolona przez administratora serwera
# Matches ConnectionType
###length 5

@ -2359,7 +2359,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova empresa)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Criar uma nova empresa e juntar-se a ela
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este é você
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este é o anfitrião do jogo
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} cliente{P "" s} / {NUM} companhi{P a as}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} cliente{P "" s} - {NUM}/{NUM} companhi{P a as}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}O número de clientes ligados atualmente, número de empresas e número máximo de empresas permitido pelo administrador do servidor
# Matches ConnectionType
###length 5

@ -2358,7 +2358,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Companie nouă
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Creează o nouă companie și intră în ea
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Aici ești tu
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Aceasta este gazda jocului
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} {P client clienți "de clienți"} / {NUM}{P companie companii "de companii"}
# Matches ConnectionType
###length 5
@ -4529,7 +4528,7 @@ STR_TIMETABLE_CLEAR_SPEED :{BLACK}Şterge
STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Ștergeți viteza maximă de deplasare a comenzii evidențiate. Ctrl+Click șterge viteza pentru toate comenzile
STR_TIMETABLE_RESET_LATENESS :{BLACK}Reinitializeaza contorul de intarziere
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reiniţializează contorul de întârziere, astfel ca vehiculul să ajungă la timp
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reiniţializează contorul de întârziere, astfel ca vehiculul să ajungă la timp. Ctrl+clic va reseta tot grupul astfel încât cel mai întârziat vehicul va ajunge la timp și toate celelalte vor ajunge mai devreme
STR_TIMETABLE_AUTOFILL :{BLACK}Auto-completare
STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Completați automat orarul cu valorile din următoarea călătorie. Ctrl+Click pentru a încerca să păstrați timpii de așteptare

@ -2509,7 +2509,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Новая к
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Основать новую транспортную компанию и присоединиться к ней
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Это вы!
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Это организатор игры
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} клиент{P "" а ов} / {NUM} компани{P я и й}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}Клиентов: {NUM}; компаний: {NUM}/{NUM}
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}Количество подключённых в данный момент клиентов, существующих компаний и максимально допустимое количество компаний
# Matches ConnectionType
###length 5

@ -2551,7 +2551,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(novo preduzeć
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Napravi novo preduzeće i pridruži mu se
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Ovo si ti
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Ovo je domaćin igre
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klijen{P t ata ata} / {NUM} preduzeć{P e a a}
# Matches ConnectionType
###length 5

@ -2358,7 +2358,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(新公司)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}新建并加入公司
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}这是你
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}这里是游戏的主机
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM}个客户端 / {NUM}个公司
# Matches ConnectionType
###length 5

@ -2426,7 +2426,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nová spoločn
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Založiť novú spoločnosť a pripojiť sa k nej
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Toto ste vy
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Toto je hosť hry
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" "i" "ov"} / {NUM} spoločnos{P "ť" "ti" "tí"}
# Matches ConnectionType
###length 5

@ -2359,7 +2359,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nueva empresa)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crea una nueva empresa y te une a ella
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Éste eres tú
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Éste es el servidor de la partida
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} cliente{P "" s} / {NUM} empresa{P "" s}
# Matches ConnectionType
###length 5

@ -2359,7 +2359,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nueva empresa)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Crear nueva empresa y unirse a ella
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este eres tú
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este es el host del juego
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} cliente{P "" s}/{NUM} empresa{P "" s}
# Matches ConnectionType
###length 5
@ -3353,6 +3352,7 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING
STR_NEWGRF_ERROR_MSG_WARNING :{RED}Atención: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Error fatal: {SILVER}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}Ha ocurrido un error en el NewGRF "{STRING}":{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} no funcionará con la con la versión de TTDPatch reportada por OpenTTD
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} es la para la versión {2:STRING} de TTD
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} está diseñado para usarse con {2:STRING}

@ -2358,7 +2358,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nytt företag)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Skapa ett nytt företag och gå med i det
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Det här är du
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Det här är spelets värd
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" er} / {NUM} företag
# Matches ConnectionType
###length 5

@ -2098,7 +2098,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(புதி
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}புதிய நிறுவனத்தினை நிறுவி விளையாடு
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :இது நீன்கள்
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}இது விலையாட்டின் வழங்குபவர்
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} வாடிக்கையாளர்{P "" கள்} / {NUM} நிறுவன{P ம் ங்கள்}
# Matches ConnectionType
###length 5

@ -1206,7 +1206,9 @@ STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT :靠右
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN :最大貸款額:{STRING}
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_HELPTEXT :公司最多可借多少錢(此設定的值排除了通貨膨脹因素)。
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_VALUE :{CURRENCY_LONG}
###setting-zero-is-special
STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_DISABLED :無貸款 {RED} 需要有遊戲腳本以提供初始資金
STR_CONFIG_SETTING_INTEREST_RATE :息率:{STRING}
STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :設定貸款息率。如啟用了通貨膨脹的設定,則此設定同時決定通脹率。
@ -2356,7 +2358,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(新公司)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}創立並加入一個新公司
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}這是你
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}這是遊戲的主持端
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM}個用戶端 / {NUM}所公司
# Matches ConnectionType
###length 5
@ -3350,6 +3351,8 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING
STR_NEWGRF_ERROR_MSG_WARNING :{RED}警告:{SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_ERROR :{RED}錯誤:{SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}嚴重錯誤:{SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}發生嚴重 NewGRF "{STRING}" 錯誤的處理方式:{}{STRING}
STR_NEWGRF_ERROR_POPUP :{WHITE}發生NewGRF "{STRING}" 錯誤:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} 跟由 OpenTTD 回報的 TTDPatch 版本不合
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} 只適合用於 TTD 版本 {2:STRING}。
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} 必須跟 {2:STRING} 一起使用
@ -4620,7 +4623,9 @@ STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}高度
STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}小地圖截圖
# Script Parameters
STR_AI_SETTINGS_CAPTION_AI :{WHITE}AI參數
STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} 參數
STR_AI_SETTINGS_CAPTION_AI :AI 參數
STR_AI_SETTINGS_CAPTION_GAMESCRIPT :遊戲腳本
STR_AI_SETTINGS_CLOSE :{BLACK}關閉
STR_AI_SETTINGS_RESET :{BLACK}重設
STR_AI_SETTINGS_SETTING :{STRING}{ORANGE}{STRING}

@ -2359,7 +2359,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Yeni şirket)
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Yeni bir şirket oluştur ve ona katıl
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Bu sensin
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Bu, oyunun ev sahibi
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} oyuncu / {NUM} şirket
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} oyuncu - {NUM}/{NUM} şirket
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}Şu anda bağlı olan istemci sayısı, şirket sayısı ve sunucu sahibi tarafından izin verilen maksimum şirket sayısı
# Matches ConnectionType
###length 5
@ -4626,7 +4627,7 @@ STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}Küçük
# Script Parameters
STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parametreler
STR_AI_SETTINGS_CAPTION_AI :{WHITE}YZ Parametreleri
STR_AI_SETTINGS_CAPTION_AI :YZ
STR_AI_SETTINGS_CAPTION_GAMESCRIPT :Oyun Betiği
STR_AI_SETTINGS_CLOSE :{BLACK}Kapat
STR_AI_SETTINGS_RESET :{BLACK}Yeniden başlat

@ -2484,7 +2484,6 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Нова ко
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Створити нову компанію і приєднатись до неї
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Це ти
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Організатор гри
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} клієнт{P "" и ів} / {NUM} компан{P ія ії ій}
# Matches ConnectionType
###length 5

@ -2358,7 +2358,8 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Công ty mới
STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Khai sinh một công ty và gia nhập
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Đây là bạn
STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Đây là người tổ chức ván chơi
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} người chơi / {NUM} công ty
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} nguời chơi - {NUM}/{NUM} công ty
STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP :{BLACK}Số lượng máy trạm, số lượng công ty và số lượng công ty tối đa mà quản lý máy chủ cho phép
# Matches ConnectionType
###length 5

@ -30,7 +30,7 @@ extern LeagueTablePool _league_table_pool;
**/
struct LeagueTableElement : LeagueTableElementPool::PoolItem<&_league_table_element_pool> {
LeagueTableID table; ///< Id of the table which this element belongs to
uint64 rating; ///< Value that determines ordering of elements in the table (higher=better)
int64 rating; ///< Value that determines ordering of elements in the table (higher=better)
CompanyID company; ///< Company Id to show the color blob for or INVALID_COMPANY
std::string text; ///< Text of the element
std::string score; ///< String representation of the score associated with the element

@ -1294,6 +1294,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(P
_network_server_max_companies = p->Recv_uint8();
_network_server_name = p->Recv_string(NETWORK_NAME_LENGTH);
SetWindowClassesDirty(WC_CLIENT_LIST);
return NETWORK_RECV_STATUS_OKAY;
}
@ -1553,11 +1554,20 @@ bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio)
return false;
}
/**
* Get the maximum number of companies that are allowed by the server.
* @return The number of companies allowed.
*/
uint NetworkMaxCompaniesAllowed()
{
return _network_server ? _settings_client.network.max_companies : _network_server_max_companies;
}
/**
* Check if max_companies has been reached on the server (local check only).
* @return true if the max value has been reached or exceeded, false otherwise.
*/
bool NetworkMaxCompaniesReached()
{
return Company::GetNumItems() >= (_network_server ? _settings_client.network.max_companies : _network_server_max_companies);
return Company::GetNumItems() >= NetworkMaxCompaniesAllowed();
}

@ -65,6 +65,7 @@ void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const
void NetworkClientSendDesyncMsg(const char *msg);
bool NetworkClientPreferTeamChat(const NetworkClientInfo *cio);
bool NetworkCompanyIsPassworded(CompanyID company_id);
uint NetworkMaxCompaniesAllowed();
bool NetworkMaxCompaniesReached();
void NetworkPrintClients();
void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode);

@ -1366,7 +1366,7 @@ static const NWidgetPart _nested_client_list_widgets[] = {
NWidget(NWID_VERTICAL),
NWidget(WWT_MATRIX, COLOUR_GREY, WID_CL_MATRIX), SetMinimalSize(180, 0), SetResize(1, 1), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_CL_SCROLLBAR),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(WWT_TEXT, COLOUR_GREY, WID_CL_CLIENT_COMPANY_COUNT), SetFill(1, 0), SetMinimalTextLines(1, 0), SetResize(1, 0), SetPadding(2, 1, 2, 1), SetAlignment(SA_CENTER), SetDataTip(STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT, STR_NULL),
NWidget(WWT_TEXT, COLOUR_GREY, WID_CL_CLIENT_COMPANY_COUNT), SetFill(1, 0), SetMinimalTextLines(1, 0), SetResize(1, 0), SetPadding(2, 1, 2, 1), SetAlignment(SA_CENTER), SetDataTip(STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT, STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(NWID_VERTICAL),
@ -1811,6 +1811,7 @@ public:
case WID_CL_CLIENT_COMPANY_COUNT:
SetDParam(0, NetworkClientInfo::GetNumItems());
SetDParam(1, Company::GetNumItems());
SetDParam(2, NetworkMaxCompaniesAllowed());
break;
}
}

@ -87,12 +87,12 @@ enum GrfSpecFeature : uint8 {
GSF_AIRPORTTILES,
GSF_ROADTYPES,
GSF_TRAMTYPES,
GSF_ROADSTOPS,
GSF_NEWLANDSCAPE,
GSF_END,
GSF_REAL_FEATURE_END = GSF_ROADSTOPS,
GSF_REAL_FEATURE_END = GSF_NEWLANDSCAPE,
GSF_FAKE_TOWNS = GSF_END, ///< Fake town GrfSpecFeature for NewGRF debugging (parent scope)
GSF_FAKE_STATION_STRUCT, ///< Fake station struct GrfSpecFeature for NewGRF debugging

@ -948,6 +948,7 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
switch (scc) {
default: break;
/* These control codes take one string parameter, check there are at least that many available. */
case SCC_NEWGRF_PRINT_DWORD_SIGNED:
case SCC_NEWGRF_PRINT_WORD_SIGNED:
case SCC_NEWGRF_PRINT_BYTE_SIGNED:
@ -977,6 +978,7 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
}
break;
/* These string code take two string parameters, check there are at least that many available. */
case SCC_NEWGRF_PRINT_WORD_CARGO_LONG:
case SCC_NEWGRF_PRINT_WORD_CARGO_SHORT:
case SCC_NEWGRF_PRINT_WORD_CARGO_TINY:
@ -988,6 +990,8 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
}
if (_newgrf_textrefstack.used && modify_argv) {
/* There is data on the NewGRF text stack, and we want to move them to OpenTTD's string stack.
* After this call, a new call is made with `modify_argv` set to false when the string is finally formatted. */
switch (scc) {
default: NOT_REACHED();
case SCC_NEWGRF_PRINT_BYTE_SIGNED: *argv = _newgrf_textrefstack.PopSignedByte(); break;
@ -1015,6 +1019,7 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
case SCC_NEWGRF_PRINT_DWORD_DATE_SHORT:
case SCC_NEWGRF_PRINT_DWORD_HEX: *argv = _newgrf_textrefstack.PopUnsignedDWord(); break;
/* Dates from NewGRFs have 1920-01-01 as their zero point, convert it to OpenTTD's epoch. */
case SCC_NEWGRF_PRINT_WORD_DATE_LONG:
case SCC_NEWGRF_PRINT_WORD_DATE_SHORT: *argv = _newgrf_textrefstack.PopUnsignedWord() + DAYS_TILL_ORIGINAL_BASE_YEAR; break;
@ -1042,7 +1047,7 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
}
}
} else {
/* Consume additional parameter characters */
/* Consume additional parameter characters that follow the NewGRF string code. */
switch (scc) {
default: break;
@ -1053,6 +1058,7 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
}
}
/* Emit OpenTTD's internal string code for the different NewGRF variants. */
switch (scc) {
default: NOT_REACHED();
case SCC_NEWGRF_PRINT_DWORD_SIGNED:
@ -1115,6 +1121,7 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
case SCC_NEWGRF_PRINT_WORD_STATION_NAME:
return SCC_STATION_NAME;
/* These NewGRF string codes modify the NewGRF stack or otherwise do not map to OpenTTD string codes. */
case SCC_NEWGRF_DISCARD_WORD:
case SCC_NEWGRF_ROTATE_TOP_4_WORDS:
case SCC_NEWGRF_PUSH_WORD:

@ -764,7 +764,6 @@ private:
friend upstream_sl::SaveLoadTable upstream_sl::GetOrderListDescription(); ///< Saving and loading of order lists.
friend void Ptrs_ORDL(); ///< Saving and loading of order lists.
StationID GetBestLoadableNext(const Vehicle *v, const Order *o1, const Order *o2) const;
void ReindexOrderList();
Order *GetOrderAtFromList(int index) const;

@ -2420,7 +2420,7 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
* are temporarily invalid due to reconstruction. */
const Station *st = Station::Get(order->GetDestination());
if (CanVehicleUseStation(src, st) && !CanVehicleUseStation(dst, st)) {
return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
return CommandCost::DualErrorMessage(STR_ERROR_CAN_T_COPY_SHARE_ORDER, GetVehicleCannotUseStationReason(dst, st));
}
}
if (OrderGoesToRoadDepot(dst, order)) {
@ -2501,9 +2501,9 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
/* Trucks can't copy all the orders from busses (and visa versa),
* and neither can helicopters and aircraft. */
for (const Order *order : src->Orders()) {
if (OrderGoesToStation(dst, order) &&
!CanVehicleUseStation(dst, Station::Get(order->GetDestination()))) {
return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
Station *st = Station::Get(order->GetDestination());
if (OrderGoesToStation(dst, order) && !CanVehicleUseStation(dst, st)) {
return CommandCost::DualErrorMessage(STR_ERROR_CAN_T_COPY_SHARE_ORDER, GetVehicleCannotUseStationReason(dst, st));
}
if (OrderGoesToRoadDepot(dst, order)) {
const Depot *dp = Depot::GetIfValid(order->GetDestination());

@ -847,9 +847,11 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
SpriteID sprite = rtl ? SPR_ARROW_LEFT : SPR_ARROW_RIGHT;
Dimension sprite_size = GetSpriteSize(sprite);
if (v->cur_real_order_index == order_index) {
/* Draw two arrows before the next real order. */
DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
DrawSprite(sprite, PAL_NONE, rtl ? right - 2 * sprite_size.width : left + sprite_size.width, y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
} else if (v->cur_implicit_order_index == order_index) {
/* Draw one arrow before the next implicit order; the next real order will still get two arrows. */
DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
}
@ -897,6 +899,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
SetDParam(2, order->GetDestination());
if (timetable) {
/* Show only wait time in the timetable window. */
SetDParam(3, STR_EMPTY);
if (order->GetWaitTime() > 0 || order->IsWaitTimetabled()) {
@ -905,6 +908,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
}
timetable_wait_time_valid = true;
} else {
/* Show non-stop, refit and stop location only in the order window. */
SetDParam(3, (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) ? STR_EMPTY : _station_load_types[order->IsRefit()][unload][load]);
if (order->IsRefit()) {
SetDParam(4, order->IsAutoRefit() ? STR_ORDER_AUTO_REFIT_ANY : CargoSpec::Get(order->GetRefitCargo())->name);
@ -921,6 +925,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
case OT_GOTO_DEPOT:
if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
/* Going to the nearest depot. */
SetDParam(0, STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT);
if (v->type == VEH_AIRCRAFT) {
SetDParam(2, STR_ORDER_NEAREST_HANGAR);
@ -930,6 +935,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
SetDParam(3, STR_ORDER_TRAIN_DEPOT + v->type);
}
} else {
/* Going to a specific depot. */
SetDParam(0, STR_ORDER_GO_TO_DEPOT_FORMAT);
SetDParam(2, v->type);
SetDParam(3, order->GetDestination());
@ -944,10 +950,12 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
if (!timetable && (order->GetDepotActionType() & ODATFB_SELL)) {
SetDParam(7, STR_ORDER_SELL_ORDER);
} else {
/* Do not show stopping in the depot in the timetable window. */
if (!timetable && (order->GetDepotActionType() & ODATFB_HALT)) {
SetDParam(7, STR_ORDER_STOP_ORDER);
}
/* Do not show refitting in the depot in the timetable window. */
if (!timetable && order->IsRefit()) {
SetDParam(7, (order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER);
SetDParam(8, CargoSpec::Get(order->GetRefitCargo())->name);

@ -2697,8 +2697,7 @@ bool AfterLoadGame()
if (IsTileType(t, MP_TREES)) {
uint density = GB(_m[t].m2, 6, 2);
uint ground = GB(_m[t].m2, 4, 2);
uint counter = GB(_m[t].m2, 0, 4);
_m[t].m2 = ground << 6 | density << 4 | counter;
_m[t].m2 = ground << 6 | density << 4;
}
}
}

@ -352,6 +352,8 @@ enum SaveLoadVersion : uint16 {
SLV_U64_TICK_COUNTER, ///< 300 PR#10035 Make _tick_counter 64bit to avoid wrapping.
SLV_LAST_LOADING_TICK, ///< 301 PR#9693 Store tick of last loading for vehicles.
SLV_MULTITRACK_LEVEL_CROSSINGS, ///< 302 PR#9931 v13.0 Multi-track level crossings.
SLV_NEWGRF_ROAD_STOPS, ///< 303 PR#10144 NewGRF road stops.
SLV_LINKGRAPH_EDGES, ///< 304 PR#10314 Explicitly store link graph edges destination.
SL_MAX_VERSION, ///< Highest possible saveload version

@ -34,6 +34,12 @@ const SaveLoadCompat _station_spec_list_sl_compat[] = {
SLC_VAR("localidx"),
};
/** Nominal field order for SlRoadStopSpecList. */
const SaveLoadCompat _station_road_stop_spec_list_sl_compat[] = {
SLC_VAR("grfid"),
SLC_VAR("localidx"),
};
/** Original field order for SlStationCargo. */
const SaveLoadCompat _station_cargo_sl_compat[] = {
SLC_VAR("first"),

@ -18,13 +18,14 @@
namespace upstream_sl {
static const SaveLoad _league_table_elements_desc[] = {
SLE_VAR(LeagueTableElement, table, SLE_UINT8),
SLE_VAR(LeagueTableElement, rating, SLE_UINT64),
SLE_VAR(LeagueTableElement, company, SLE_UINT8),
SLE_SSTR(LeagueTableElement, text, SLE_STR | SLF_ALLOW_CONTROL),
SLE_SSTR(LeagueTableElement, score, SLE_STR | SLF_ALLOW_CONTROL),
SLE_VAR(LeagueTableElement, link.type, SLE_UINT8),
SLE_VAR(LeagueTableElement, link.target, SLE_UINT32),
SLE_VAR(LeagueTableElement, table, SLE_UINT8),
SLE_CONDVAR(LeagueTableElement, rating, SLE_FILE_U64 | SLE_VAR_I64, SL_MIN_VERSION, SLV_LINKGRAPH_EDGES),
SLE_CONDVAR(LeagueTableElement, rating, SLE_INT64, SLV_LINKGRAPH_EDGES, SL_MAX_VERSION),
SLE_VAR(LeagueTableElement, company, SLE_UINT8),
SLE_SSTR(LeagueTableElement, text, SLE_STR | SLF_ALLOW_CONTROL),
SLE_SSTR(LeagueTableElement, score, SLE_STR | SLF_ALLOW_CONTROL),
SLE_VAR(LeagueTableElement, link.type, SLE_UINT8),
SLE_VAR(LeagueTableElement, link.target, SLE_UINT32),
};
struct LEAEChunkHandler : ChunkHandler {

@ -27,6 +27,7 @@ typedef LinkGraph::BaseEdge Edge;
static uint16 _num_nodes;
static LinkGraph *_linkgraph; ///< Contains the current linkgraph being saved/loaded.
static NodeID _linkgraph_from; ///< Contains the current "from" node being saved/loaded.
static NodeID _edge_dest_node;
static NodeID _edge_next_edge;
class SlLinkgraphEdge : public DefaultSaveLoadHandler<SlLinkgraphEdge, Node> {
@ -37,7 +38,8 @@ public:
SLE_CONDVAR(Edge, travel_time_sum, SLE_UINT64, SLV_LINKGRAPH_TRAVEL_TIME, SL_MAX_VERSION),
SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION),
SLEG_VAR("next_edge", _edge_next_edge, SLE_UINT16),
SLEG_VAR("dest_node", _edge_dest_node, SLE_UINT16),
SLEG_CONDVAR("next_edge", _edge_next_edge, SLE_UINT16, SL_MIN_VERSION, SLV_LINKGRAPH_EDGES),
};
inline const static SaveLoadCompatTable compat_description = _linkgraph_edge_sl_compat;
@ -54,18 +56,29 @@ public:
NOT_REACHED();
}
size_t used_size = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? max_size : SlGetStructListLength(UINT16_MAX);
if (IsSavegameVersionBefore(SLV_LINKGRAPH_EDGES)) {
size_t used_size = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? max_size : SlGetStructListLength(UINT16_MAX);
/* ... but as that wasted a lot of space we save a sparse matrix now. */
for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _edge_next_edge) {
if (used_size == 0) SlErrorCorrupt("Link graph structure overflow");
used_size--;
/* ... but as that wasted a lot of space we save a sparse matrix now. */
for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _edge_next_edge) {
if (used_size == 0) SlErrorCorrupt("Link graph structure overflow");
used_size--;
if (to >= max_size) SlErrorCorrupt("Link graph structure overflow");
SlObject(&_linkgraph->edges[std::make_pair(_linkgraph_from, to)], this->GetLoadDescription());
}
if (to >= max_size) SlErrorCorrupt("Link graph structure overflow");
SlObject(&_linkgraph->edges[std::make_pair(_linkgraph_from, to)], this->GetLoadDescription());
}
if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph");
if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph");
} else {
/* Edge data is now a simple vector and not any kind of matrix. */
size_t size = SlGetStructListLength(UINT16_MAX);
for (size_t i = 0; i < size; i++) {
Edge edge;
SlObject(&edge, this->GetLoadDescription());
if (_edge_dest_node >= max_size) SlErrorCorrupt("Link graph structure overflow");
_linkgraph->edges[std::make_pair(_linkgraph_from, _edge_dest_node)] = edge;
}
}
}
};

@ -319,6 +319,7 @@ struct SaveLoadCompat {
/**
* Storage of simple variables, references (pointers), and arrays.
* @param cmd Load/save type. @see SaveLoadType
* @param name Field name for table chunks.
* @param base Name of the class or struct containing the variable.
* @param variable Name of the variable in the class or struct referenced by \a base.
* @param type Storage of the data in memory and in the savegame.
@ -327,8 +328,20 @@ struct SaveLoadCompat {
* @param extra Extra data to pass to the address callback function.
* @note In general, it is better to use one of the SLE_* macros below.
*/
#define SLE_GENERAL(cmd, base, variable, type, length, from, to, extra) SaveLoad {#variable, cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { assert(b != nullptr); return const_cast<void *>(static_cast<const void *>(std::addressof(static_cast<base *>(b)->variable))); }, extra, nullptr}
#define SLE_GENERAL2(cmd, base, name, variable, type, length, from, to, extra) SaveLoad {name, cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { assert(b != nullptr); return const_cast<void *>(static_cast<const void *>(std::addressof(static_cast<base *>(b)->variable))); }, extra, nullptr}
#define SLE_GENERAL_NAME(cmd, name, base, variable, type, length, from, to, extra) SaveLoad {name, cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { assert(b != nullptr); return const_cast<void *>(static_cast<const void *>(std::addressof(static_cast<base *>(b)->variable))); }, extra, nullptr}
/**
* Storage of simple variables, references (pointers), and arrays with a custom name.
* @param cmd Load/save type. @see SaveLoadType
* @param base Name of the class or struct containing the variable.
* @param variable Name of the variable in the class or struct referenced by \a base.
* @param type Storage of the data in memory and in the savegame.
* @param from First savegame version that has the field.
* @param to Last savegame version that has the field.
* @param extra Extra data to pass to the address callback function.
* @note In general, it is better to use one of the SLE_* macros below.
*/
#define SLE_GENERAL(cmd, base, variable, type, length, from, to, extra) SLE_GENERAL_NAME(cmd, #variable, base, variable, type, length, from, to, extra)
/**
* Storage of a variable in some savegame versions.
@ -339,7 +352,17 @@ struct SaveLoadCompat {
* @param to Last savegame version that has the field.
*/
#define SLE_CONDVAR(base, variable, type, from, to) SLE_GENERAL(SL_VAR, base, variable, type, 0, from, to, 0)
#define SLE_CONDVAR2(base, name, variable, type, from, to) SLE_GENERAL2(SL_VAR, base, name, variable, type, 0, from, to, 0)
/**
* Storage of a variable in some savegame versions.
* @param base Name of the class or struct containing the variable.
* @param variable Name of the variable in the class or struct referenced by \a base.
* @param name Field name for table chunks.
* @param type Storage of the data in memory and in the savegame.
* @param from First savegame version that has the field.
* @param to Last savegame version that has the field.
*/
#define SLE_CONDVARNAME(base, variable, name, type, from, to) SLE_GENERAL_NAME(SL_VAR, name, base, variable, type, 0, from, to, 0)
/**
* Storage of a reference in some savegame versions.
@ -430,7 +453,7 @@ struct SaveLoadCompat {
* @param type Storage of the data in memory and in the savegame.
*/
#define SLE_VAR(base, variable, type) SLE_CONDVAR(base, variable, type, SL_MIN_VERSION, SL_MAX_VERSION)
#define SLE_VAR2(base, name, variable, type) SLE_CONDVAR2(base, name, variable, type, SL_MIN_VERSION, SL_MAX_VERSION)
#define SLE_VAR2(base, name, variable, type) SLE_CONDVARNAME(base, variable, name, type, SL_MIN_VERSION, SL_MAX_VERSION)
/**
* Storage of a reference in every version of a savegame.

@ -17,6 +17,7 @@
#include "../../roadstop_base.h"
#include "../../vehicle_base.h"
#include "../../newgrf_station.h"
#include "../../newgrf_roadstop.h"
#include "table/strings.h"
@ -102,6 +103,33 @@ public:
}
};
class SlRoadStopSpecList : public DefaultSaveLoadHandler<SlRoadStopSpecList, BaseStation> {
public:
inline static const SaveLoad description[] = {
SLE_VAR(RoadStopSpecList, grfid, SLE_UINT32),
SLE_VAR(RoadStopSpecList, localidx, SLE_FILE_U8 | SLE_VAR_U16),
};
inline const static SaveLoadCompatTable compat_description = _station_road_stop_spec_list_sl_compat;
void Save(BaseStation *bst) const override
{
SlSetStructListLength(bst->roadstop_speclist.size());
for (uint i = 0; i < bst->roadstop_speclist.size(); i++) {
SlObject(&bst->roadstop_speclist[i], this->GetDescription());
}
}
void Load(BaseStation *bst) const override
{
uint8 num_specs = (uint8)SlGetStructListLength(UINT8_MAX);
bst->roadstop_speclist.resize(num_specs);
for (uint i = 0; i < num_specs; i++) {
SlObject(&bst->roadstop_speclist[i], this->GetLoadDescription());
}
}
};
class SlStationCargo : public DefaultSaveLoadHandler<SlStationCargo, GoodsEntry> {
public:
inline static const SaveLoad description[] = {
@ -295,6 +323,35 @@ public:
}
};
class SlRoadStopTileData : public DefaultSaveLoadHandler<SlRoadStopTileData, BaseStation> {
public:
inline static const SaveLoad description[] = {
SLE_VAR(RoadStopTileData, tile, SLE_UINT32),
SLE_VAR(RoadStopTileData, random_bits, SLE_UINT8),
SLE_VAR(RoadStopTileData, animation_frame, SLE_UINT8),
};
inline const static SaveLoadCompatTable compat_description = {};
static uint8 last_num_specs; ///< Number of specs of the last loaded station.
void Save(BaseStation *bst) const override
{
SlSetStructListLength(bst->custom_roadstop_tile_data.size());
for (uint i = 0; i < bst->custom_roadstop_tile_data.size(); i++) {
SlObject(&bst->custom_roadstop_tile_data[i], this->GetDescription());
}
}
void Load(BaseStation *bst) const override
{
uint32 num_tiles = (uint32)SlGetStructListLength(UINT32_MAX);
bst->custom_roadstop_tile_data.resize(num_tiles);
for (uint i = 0; i < num_tiles; i++) {
SlObject(&bst->custom_roadstop_tile_data[i], this->GetLoadDescription());
}
}
};
/**
* SaveLoad handler for the BaseStation, which all other stations / waypoints
* make use of.
@ -371,6 +428,7 @@ public:
SLE_REFVEC(Station, loading_vehicles, REF_VEHICLE),
SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, SLV_127, SLV_EXTEND_CARGOTYPES),
SLE_CONDVAR(Station, always_accepted, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
SLEG_CONDSTRUCTLIST("speclist", SlRoadStopTileData, SLV_NEWGRF_ROAD_STOPS, SL_MAX_VERSION),
SLEG_STRUCTLIST("goods", SlStationGoods),
};
inline const static SaveLoadCompatTable compat_description = _station_normal_sl_compat;
@ -434,6 +492,7 @@ static const SaveLoad _station_desc[] = {
SLEG_STRUCT("normal", SlStationNormal),
SLEG_STRUCT("waypoint", SlStationWaypoint),
SLEG_CONDSTRUCTLIST("speclist", SlStationSpecList, SLV_27, SL_MAX_VERSION),
SLEG_CONDSTRUCTLIST("roadstopspeclist", SlRoadStopSpecList, SLV_NEWGRF_ROAD_STOPS, SL_MAX_VERSION),
};
struct STNNChunkHandler : ChunkHandler {

@ -19,6 +19,8 @@
#include "../script_suspend.hpp"
#include "../squirrel.hpp"
#include <utility>
struct CommandAuxiliaryBase;
/**
@ -342,4 +344,68 @@ private:
static Randomizer random_states[OWNER_END]; ///< Random states for each of the scripts (game script uses OWNER_DEITY)
};
/**
* Internally used class to automate the ScriptObject reference counting.
* @api -all
*/
template <typename T>
class ScriptObjectRef {
private:
T *data; ///< The reference counted object.
public:
/**
* Create the reference counter for the given ScriptObject instance.
* @param data The underlying object.
*/
ScriptObjectRef(T *data) : data(data)
{
this->data->AddRef();
}
/* No copy constructor. */
ScriptObjectRef(const ScriptObjectRef<T> &ref) = delete;
/* Move constructor. */
ScriptObjectRef(ScriptObjectRef<T> &&ref) noexcept : data(std::exchange(ref.data, nullptr))
{
}
/* No copy assignment. */
ScriptObjectRef& operator=(const ScriptObjectRef<T> &other) = delete;
/* Move assignment. */
ScriptObjectRef& operator=(ScriptObjectRef<T> &&other) noexcept
{
std::swap(this->data, other.data);
return *this;
}
/**
* Release the reference counted object.
*/
~ScriptObjectRef()
{
if (this->data != nullptr) this->data->Release();
}
/**
* Dereferencing this reference returns a reference to the reference
* counted object
* @return Reference to the underlying object.
*/
T &operator*()
{
return *this->data;
}
/**
* The arrow operator on this reference returns the reference counted object.
* @return Pointer to the underlying object.
*/
T *operator->()
{
return this->data;
}
};
#endif /* SCRIPT_OBJECT_HPP */

@ -45,7 +45,7 @@ SQInteger ScriptPriorityQueue::Insert(HSQUIRRELVM vm)
this->queue.emplace_back(priority, item);
std::push_heap(this->queue.begin(), this->queue.end(), this->comp);
return SQConvert::Return(vm, true);
return SQConvert::Return<bool>::Set(vm, true);
}
SQInteger ScriptPriorityQueue::Pop(HSQUIRRELVM vm)
@ -61,7 +61,7 @@ SQInteger ScriptPriorityQueue::Pop(HSQUIRRELVM vm)
this->queue.pop_back();
/* Store the object on the Squirrel stack before releasing it to make sure the ref count can't drop to zero. */
auto ret = SQConvert::Return(vm, item);
auto ret = SQConvert::Return<HSQOBJECT>::Set(vm, item);
sq_release(vm, &item);
return ret;
}
@ -74,7 +74,7 @@ SQInteger ScriptPriorityQueue::Peek(HSQUIRRELVM vm)
return 1;
}
return SQConvert::Return(vm, this->queue.front().second);
return SQConvert::Return<HSQOBJECT>::Set(vm, this->queue.front().second);
}
SQInteger ScriptPriorityQueue::Exists(HSQUIRRELVM vm)
@ -83,7 +83,7 @@ SQInteger ScriptPriorityQueue::Exists(HSQUIRRELVM vm)
sq_resetobject(&item);
sq_getstackobj(vm, 2, &item);
return SQConvert::Return(vm, std::find(this->queue.cbegin(), this->queue.cend(), item) != this->queue.cend());
return SQConvert::Return<bool>::Set(vm, std::find(this->queue.cbegin(), this->queue.cend(), item) != this->queue.cend());
}
SQInteger ScriptPriorityQueue::Clear(HSQUIRRELVM vm)

@ -162,9 +162,9 @@
* @param end The part that will be build second.
* @return True if and only if the road bits can be build.
*/
static bool CheckAutoExpandedRoadBits(const Array *existing, int32 start, int32 end)
static bool CheckAutoExpandedRoadBits(const Array<> &existing, int32 start, int32 end)
{
return (start + end == 0) && (existing->size == 0 || existing->array[0] == start || existing->array[0] == end);
return (start + end == 0) && (existing.empty() || existing[0] == start || existing[0] == end);
}
/**
@ -177,7 +177,7 @@ static bool CheckAutoExpandedRoadBits(const Array *existing, int32 start, int32
* they are build or 2 when building the first part automatically
* builds the second part.
*/
static int32 LookupWithoutBuildOnSlopes(::Slope slope, const Array *existing, int32 start, int32 end)
static int32 LookupWithoutBuildOnSlopes(::Slope slope, const Array<> &existing, int32 start, int32 end)
{
switch (slope) {
/* Flat slopes can always be build. */
@ -189,9 +189,9 @@ static int32 LookupWithoutBuildOnSlopes(::Slope slope, const Array *existing, in
* in the game have been changed.
*/
case SLOPE_NE: case SLOPE_SW:
return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing->size == 0 ? 2 : 1) : 0;
return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing.empty() ? 2 : 1) : 0;
case SLOPE_SE: case SLOPE_NW:
return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing->size == 0 ? 2 : 1) : 0;
return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing.empty() ? 2 : 1) : 0;
/* Any other tile cannot be built on. */
default:
@ -241,7 +241,7 @@ static RoadBits NeighbourToRoadBits(int32 neighbour)
* they are build or 2 when building the first part automatically
* builds the second part.
*/
static int32 LookupWithBuildOnSlopes(::Slope slope, Array *existing, int32 start, int32 end)
static int32 LookupWithBuildOnSlopes(::Slope slope, const Array<> &existing, int32 start, int32 end)
{
/* Steep slopes behave the same as slopes with one corner raised. */
if (IsSteepSlope(slope)) {
@ -291,9 +291,6 @@ static int32 LookupWithBuildOnSlopes(::Slope slope, Array *existing, int32 start
/* Now perform the actual rotation. */
for (int j = 0; j < base_rotate; j++) {
for (size_t i = 0; i < existing->size; i++) {
existing->array[i] = RotateNeighbour(existing->array[i]);
}
start = RotateNeighbour(start);
end = RotateNeighbour(end);
}
@ -302,8 +299,11 @@ static int32 LookupWithBuildOnSlopes(::Slope slope, Array *existing, int32 start
RoadBits start_roadbits = NeighbourToRoadBits(start);
RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end);
RoadBits existing_roadbits = ROAD_NONE;
for (size_t i = 0; i < existing->size; i++) {
existing_roadbits |= NeighbourToRoadBits(existing->array[i]);
for (int32 neighbour : existing) {
for (int j = 0; j < base_rotate; j++) {
neighbour = RotateNeighbour(neighbour);
}
existing_roadbits |= NeighbourToRoadBits(neighbour);
}
switch (slope) {
@ -391,7 +391,7 @@ static bool NormaliseTileOffset(int32 *tile)
return false;
}
/* static */ int32 ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::Slope slope_, Array *existing, TileIndex start_, TileIndex end_)
/* static */ int32 ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::Slope slope_, Array<> existing, TileIndex start_, TileIndex end_)
{
::Slope slope = (::Slope)slope_;
int32 start = start_;
@ -400,8 +400,8 @@ static bool NormaliseTileOffset(int32 *tile)
/* The start tile and end tile cannot be the same tile either. */
if (start == end) return -1;
for (size_t i = 0; i < existing->size; i++) {
if (!NormaliseTileOffset(&existing->array[i])) return -1;
for (size_t i = 0; i < existing.size(); i++) {
if (!NormaliseTileOffset(&existing[i])) return -1;
}
if (!NormaliseTileOffset(&start)) return -1;
@ -419,8 +419,6 @@ static bool NormaliseTileOffset(int32 *tile)
/* ROAD_NW ROAD_SW ROAD_SE ROAD_NE */
const TileIndexDiff neighbours[] = {::TileDiffXY(0, -1), ::TileDiffXY(1, 0), ::TileDiffXY(0, 1), ::TileDiffXY(-1, 0)};
Array *existing = (Array*)alloca(sizeof(Array) + lengthof(neighbours) * sizeof(int32));
existing->size = 0;
::RoadBits rb = ::ROAD_NONE;
if (::IsNormalRoadTile(tile)) {
@ -428,8 +426,10 @@ static bool NormaliseTileOffset(int32 *tile)
} else {
rb = ::GetAnyRoadBits(tile, RTT_ROAD) | ::GetAnyRoadBits(tile, RTT_TRAM);
}
Array<> existing;
for (uint i = 0; i < lengthof(neighbours); i++) {
if (HasBit(rb, i)) existing->array[existing->size++] = neighbours[i];
if (HasBit(rb, i)) existing.emplace_back(neighbours[i]);
}
return ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::GetSlope(tile), existing, start - tile, end - tile);

@ -11,6 +11,7 @@
#define SCRIPT_ROAD_HPP
#include "script_tile.hpp"
#include "../squirrel_helper_type.hpp"
#include "../../../road.h"
/**
@ -264,7 +265,7 @@ public:
* they are build or 2 when building the first part automatically
* builds the second part. -1 means the preconditions are not met.
*/
static int32 CanBuildConnectedRoadParts(ScriptTile::Slope slope, struct Array *existing, TileIndex start, TileIndex end);
static int32 CanBuildConnectedRoadParts(ScriptTile::Slope slope, Array<> existing, TileIndex start, TileIndex end);
/**
* Lookup function for building road parts independent of whether the

@ -10,6 +10,7 @@
#include "../../stdafx.h"
#include "../../string_func.h"
#include "../../strings_func.h"
#include "../../game/game_text.hpp"
#include "script_text.hpp"
#include "../script_fatalerror.hpp"
#include "../../table/control_codes.h"
@ -24,7 +25,7 @@ RawText::RawText(const char *text) : text(text)
ScriptText::ScriptText(HSQUIRRELVM vm) :
string(STR_NULL), params(), parami(), paramt(), paramc(0)
string(STR_NULL), param(), paramc(0)
{
int nparam = sq_gettop(vm) - 1;
if (nparam < 1) {
@ -53,32 +54,16 @@ ScriptText::ScriptText(HSQUIRRELVM vm) :
}
}
ScriptText::~ScriptText()
{
for (int i = 0; i < SCRIPT_TEXT_MAX_PARAMETERS; i++) {
free(this->params[i]);
if (this->paramt[i] != nullptr) this->paramt[i]->Release();
}
}
SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm)
{
if (parameter >= SCRIPT_TEXT_MAX_PARAMETERS) return SQ_ERROR;
free(this->params[parameter]);
if (this->paramt[parameter] != nullptr) this->paramt[parameter]->Release();
this->parami[parameter] = 0;
this->params[parameter] = nullptr;
this->paramt[parameter] = nullptr;
switch (sq_gettype(vm, -1)) {
case OT_STRING: {
const SQChar *value;
sq_getstring(vm, -1, &value);
this->params[parameter] = stredup(value);
StrMakeValidInPlace(this->params[parameter]);
this->param[parameter] = StrMakeValid(value);
break;
}
@ -86,7 +71,7 @@ SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm)
SQInteger value;
sq_getinteger(vm, -1, &value);
this->parami[parameter] = value;
this->param[parameter] = value;
break;
}
@ -109,8 +94,7 @@ SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm)
if (real_instance == nullptr) return SQ_ERROR;
ScriptText *value = static_cast<ScriptText *>(real_instance);
value->AddRef();
this->paramt[parameter] = value;
this->param[parameter] = ScriptTextRef(value);
break;
}
@ -185,19 +169,37 @@ char *ScriptText::_GetEncodedText(char *p, char *lastofp, int &param_count)
{
p += Utf8Encode(p, SCC_ENCODED);
p += seprintf(p, lastofp, "%X", this->string);
for (int i = 0; i < this->paramc; i++) {
if (this->params[i] != nullptr) {
p += seprintf(p, lastofp, ":\"%s\"", this->params[i]);
param_count++;
continue;
}
if (this->paramt[i] != nullptr) {
p += seprintf(p, lastofp, ":");
p = this->paramt[i]->_GetEncodedText(p, lastofp, param_count);
continue;
const StringParams &params = GetGameStringParams(this->string);
int cur_idx = 0;
for (const StringParam &cur_param : params) {
if (cur_idx >= this->paramc) throw Script_FatalError("Not enough string parameters");
switch (cur_param.type) {
case StringParam::RAW_STRING:
if (!std::holds_alternative<std::string>(this->param[cur_idx])) throw Script_FatalError("Wrong string parameter type");
p += seprintf(p, lastofp, ":\"%s\"", std::get<std::string>(this->param[cur_idx++]).c_str());
break;
case StringParam::STRING: {
if (!std::holds_alternative<ScriptTextRef>(this->param[cur_idx])) throw Script_FatalError("Wrong string parameter type");
int count = 1; // 1 because the string id is included in consumed parameters
p += seprintf(p, lastofp, ":");
p = std::get<ScriptTextRef>(this->param[cur_idx++])->_GetEncodedText(p, lastofp, count);
if (count != cur_param.consumes) throw Script_FatalError("Substring doesn't consume the expected amount of parameters.");
break;
}
default:
if (cur_idx + cur_param.consumes > this->paramc) throw Script_FatalError("Not enough string parameters");
for (int i = 0; i < cur_param.consumes; i++) {
if (!std::holds_alternative<SQInteger>(this->param[cur_idx])) throw Script_FatalError("Wrong string parameter type");
p += seprintf(p, lastofp,":" OTTD_PRINTFHEX64, std::get<SQInteger>(this->param[cur_idx++]));
}
}
p += seprintf(p, lastofp,":" OTTD_PRINTFHEX64, this->parami[i]);
param_count++;
param_count += cur_param.consumes;
}
return p;

@ -13,6 +13,8 @@
#include "script_object.hpp"
#include "../../core/alloc_type.hpp"
#include <variant>
/**
* Internal parent object of all Text-like objects.
* @api -all
@ -88,7 +90,6 @@ public:
*/
ScriptText(StringID string, ...);
#endif /* DOXYGEN_API */
~ScriptText();
#ifndef DOXYGEN_API
/**
@ -127,10 +128,10 @@ public:
virtual const std::string GetEncodedText();
private:
using ScriptTextRef = ScriptObjectRef<ScriptText>;
StringID string;
char *params[SCRIPT_TEXT_MAX_PARAMETERS];
int64 parami[SCRIPT_TEXT_MAX_PARAMETERS];
ScriptText *paramt[SCRIPT_TEXT_MAX_PARAMETERS];
std::variant<SQInteger, std::string, ScriptTextRef> param[SCRIPT_TEXT_MAX_PARAMETERS];
int paramc;
/**

File diff suppressed because it is too large Load Diff

@ -10,10 +10,10 @@
#ifndef SQUIRREL_HELPER_TYPE_HPP
#define SQUIRREL_HELPER_TYPE_HPP
#include <vector>
/** Definition of a simple array. */
struct Array {
size_t size; ///< The size of the array.
int32 array[]; ///< The data of the array.
};
template <typename Titem = int32>
using Array = std::vector<Titem>;
#endif /* SQUIRREL_HELPER_TYPE_HPP */

@ -1801,7 +1801,10 @@ static void ParseCompanyPasswordStorageSecret(const std::string &value)
static void UpdateClientConfigValues()
{
NetworkServerUpdateGameInfo();
if (_network_server) NetworkServerSendConfigUpdate();
if (_network_server) {
NetworkServerSendConfigUpdate();
SetWindowClassesDirty(WC_CLIENT_LIST);
}
}
/* End - Callback Functions */

@ -120,7 +120,7 @@ static inline SpriteCache *GetSpriteCache(uint index)
static inline bool IsMapgenSpriteID(SpriteID sprite)
{
return IsInsideMM(sprite, 4845, 4882);
return IsInsideMM(sprite, SPR_MAPGEN_BEGIN, SPR_MAPGEN_END);
}
static SpriteCache *AllocateSpriteCache(uint index)

@ -479,6 +479,7 @@ bool Station::CatchmentCoversTown(TownID t) const
/**
* Recompute tiles covered in our catchment area.
* This will additionally recompute nearby towns and industries.
* @param no_clear_nearby_lists If Station::RemoveFromAllNearbyLists does not need to be called.
*/
void Station::RecomputeCatchment(bool no_clear_nearby_lists)
{

@ -3663,83 +3663,89 @@ static Foundation GetFoundation_Station(TileIndex tile, Slope tileh)
return FlatteningFoundation(tileh);
}
static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
{
td->owner[0] = GetTileOwner(tile);
if (IsAnyRoadStopTile(tile)) {
RoadType road_rt = GetRoadTypeRoad(tile);
RoadType tram_rt = GetRoadTypeTram(tile);
Owner road_owner = INVALID_OWNER;
Owner tram_owner = INVALID_OWNER;
if (road_rt != INVALID_ROADTYPE) {
const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
td->roadtype = rti->strings.name;
td->road_speed = rti->max_speed / 2;
road_owner = GetRoadOwner(tile, RTT_ROAD);
}
if (tram_rt != INVALID_ROADTYPE) {
const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
td->tramtype = rti->strings.name;
td->tram_speed = rti->max_speed / 2;
tram_owner = GetRoadOwner(tile, RTT_TRAM);
}
if (IsDriveThroughStopTile(tile)) {
/* Is there a mix of owners? */
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
(road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
uint i = 1;
if (road_owner != INVALID_OWNER) {
td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
td->owner[i] = road_owner;
i++;
}
if (tram_owner != INVALID_OWNER) {
td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
td->owner[i] = tram_owner;
}
static void FillTileDescRoadStop(TileIndex tile, TileDesc *td)
{
RoadType road_rt = GetRoadTypeRoad(tile);
RoadType tram_rt = GetRoadTypeTram(tile);
Owner road_owner = INVALID_OWNER;
Owner tram_owner = INVALID_OWNER;
if (road_rt != INVALID_ROADTYPE) {
const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
td->roadtype = rti->strings.name;
td->road_speed = rti->max_speed / 2;
road_owner = GetRoadOwner(tile, RTT_ROAD);
}
if (tram_rt != INVALID_ROADTYPE) {
const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
td->tramtype = rti->strings.name;
td->tram_speed = rti->max_speed / 2;
tram_owner = GetRoadOwner(tile, RTT_TRAM);
}
if (IsDriveThroughStopTile(tile)) {
/* Is there a mix of owners? */
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
(road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
uint i = 1;
if (road_owner != INVALID_OWNER) {
td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
td->owner[i] = road_owner;
i++;
}
if (tram_owner != INVALID_OWNER) {
td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
td->owner[i] = tram_owner;
}
}
}
}
td->build_date = BaseStation::GetByTile(tile)->build_date;
if (HasStationTileRail(tile)) {
const StationSpec *spec = GetStationSpec(tile);
void FillTileDescRailStation(TileIndex tile, TileDesc *td)
{
const StationSpec *spec = GetStationSpec(tile);
if (spec != nullptr) {
td->station_class = StationClass::Get(spec->cls_id)->name;
td->station_name = spec->name;
if (spec != nullptr) {
td->station_class = StationClass::Get(spec->cls_id)->name;
td->station_name = spec->name;
if (spec->grf_prop.grffile != nullptr) {
const GRFConfig *gc = GetGRFConfig(spec->grf_prop.grffile->grfid);
td->grf = gc->GetName();
}
if (spec->grf_prop.grffile != nullptr) {
const GRFConfig *gc = GetGRFConfig(spec->grf_prop.grffile->grfid);
td->grf = gc->GetName();
}
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
td->rail_speed = rti->max_speed;
td->railtype = rti->strings.name;
}
if (IsAirport(tile)) {
const AirportSpec *as = Station::GetByTile(tile)->airport.GetSpec();
td->airport_class = AirportClass::Get(as->cls_id)->name;
td->airport_name = as->name;
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(tile));
td->rail_speed = rti->max_speed;
td->railtype = rti->strings.name;
}
const AirportTileSpec *ats = AirportTileSpec::GetByTile(tile);
td->airport_tile_name = ats->name;
void FillTileDescAirport(TileIndex tile, TileDesc *td)
{
const AirportSpec *as = Station::GetByTile(tile)->airport.GetSpec();
td->airport_class = AirportClass::Get(as->cls_id)->name;
td->airport_name = as->name;
if (as->grf_prop.grffile != nullptr) {
const GRFConfig *gc = GetGRFConfig(as->grf_prop.grffile->grfid);
td->grf = gc->GetName();
} else if (ats->grf_prop.grffile != nullptr) {
const GRFConfig *gc = GetGRFConfig(ats->grf_prop.grffile->grfid);
td->grf = gc->GetName();
}
const AirportTileSpec *ats = AirportTileSpec::GetByTile(tile);
td->airport_tile_name = ats->name;
if (as->grf_prop.grffile != nullptr) {
const GRFConfig *gc = GetGRFConfig(as->grf_prop.grffile->grfid);
td->grf = gc->GetName();
} else if (ats->grf_prop.grffile != nullptr) {
const GRFConfig *gc = GetGRFConfig(ats->grf_prop.grffile->grfid);
td->grf = gc->GetName();
}
}
static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
{
td->owner[0] = GetTileOwner(tile);
td->build_date = BaseStation::GetByTile(tile)->build_date;
if (IsAnyRoadStopTile(tile)) FillTileDescRoadStop(tile, td);
if (HasStationRail(tile)) FillTileDescRailStation(tile, td);
if (IsAirport(tile)) FillTileDescAirport(tile, td);
StringID str;
switch (GetStationType(tile)) {

@ -152,6 +152,22 @@ struct LanguageWriter {
virtual void WriteLang(const StringData &data);
};
struct CmdStruct;
struct CmdPair {
const CmdStruct *a;
const char *v;
};
struct ParsedCommandStruct {
uint np;
CmdPair pairs[32];
const CmdStruct *cmd[32]; // ordered by param #
};
const CmdStruct *TranslateCmdForCompare(const CmdStruct *a);
void ExtractCommandString(ParsedCommandStruct *p, const char *s, bool warnings);
void CDECL strgen_warning(const char *s, ...) WARN_FORMAT(1, 2);
void CDECL strgen_error(const char *s, ...) WARN_FORMAT(1, 2);
void NORETURN CDECL strgen_fatal(const char *s, ...) WARN_FORMAT(1, 2);

@ -222,17 +222,6 @@ uint StringData::CountInUse(uint tab) const
static const char *_cur_ident;
struct CmdPair {
const CmdStruct *a;
const char *v;
};
struct ParsedCommandStruct {
uint np;
CmdPair pairs[32];
const CmdStruct *cmd[32]; // ordered by param #
};
/* Used when generating some advanced commands. */
static ParsedCommandStruct _cur_pcs;
static int _cur_argidx;
@ -598,7 +587,7 @@ StringReader::~StringReader()
{
}
static void ExtractCommandString(ParsedCommandStruct *p, const char *s, bool warnings)
void ExtractCommandString(ParsedCommandStruct *p, const char *s, bool warnings)
{
char param[MAX_COMMAND_PARAM_SIZE];
int argno;
@ -632,7 +621,7 @@ static void ExtractCommandString(ParsedCommandStruct *p, const char *s, bool war
}
static const CmdStruct *TranslateCmdForCompare(const CmdStruct *a)
const CmdStruct *TranslateCmdForCompare(const CmdStruct *a)
{
if (a == nullptr) return nullptr;

@ -1177,8 +1177,9 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg
sub_args.SetParam(i++, param);
} else {
s++; // skip the leading \"
char *g = stredup(s);
g[p - s] = '\0';
g[p - s - 1] = '\0'; // skip the trailing \"
sub_args_need_free[i] = true;
sub_args.SetParam(i++, (uint64)(size_t)g);
@ -1295,7 +1296,6 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg
break;
case SCC_RAW_STRING_POINTER: { // {RAW_STRING}
if (game_script) break;
const char *raw_string = (const char *)(size_t)args->GetInt64(SCC_RAW_STRING_POINTER);
buff = FormatString(buff, raw_string, args, last);
break;

@ -1179,6 +1179,10 @@ static const SpriteID SPR_OTTD_N = 4839;
static const SpriteID SPR_OTTD_T = 4836;
/* Letters not used: R,A,S,Y,C (4837, 4838, 4840, 4843, 4844) */
/* Range of "special" sprites that are used by the old map generation algorithm. */
static const SpriteID SPR_MAPGEN_BEGIN = 4845;
static const SpriteID SPR_MAPGEN_END = 4882;
static const SpriteID SPR_HIGHSCORE_CHART_BEGIN = 4804;
static const SpriteID SPR_TYCOON_IMG1_BEGIN = 4814;
static const SpriteID SPR_TYCOON_IMG2_BEGIN = 4824;

@ -4397,10 +4397,10 @@ bool CanVehicleUseStation(const Vehicle *v, const Station *st)
}
/**
* Get reason string why this station can't be used by the given vehicle
* @param v the vehicle to test
* @param st the station to test for
* @return true if and only if the vehicle can use this station.
* Get reason string why this station can't be used by the given vehicle.
* @param v The vehicle to test.
* @param st The station to test for.
* @return The string explaining why the vehicle cannot use the station.
*/
StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st)
{
@ -4415,15 +4415,18 @@ StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st)
StringID err = rv->IsBus() ? STR_ERROR_NO_BUS_STATION : STR_ERROR_NO_TRUCK_STATION;
for (; rs != nullptr; rs = rs->next) {
/* The vehicle is articulated and can therefore not go to a standard road stop. */
if (IsStandardRoadStopTile(rs->xy) && rv->HasArticulatedPart()) {
err = STR_ERROR_NO_STOP_ARTIC_VEH;
/* Articulated vehicles cannot use bay road stops, only drive-through. Make sure the vehicle can actually use this bay stop */
if (HasTileAnyRoadType(rs->xy, rv->compatible_roadtypes) && IsStandardRoadStopTile(rs->xy) && rv->HasArticulatedPart()) {
err = STR_ERROR_NO_STOP_ARTICULATED_VEHICLE;
continue;
}
/* The vehicle cannot go to this roadstop (different roadtype) */
if (!HasTileAnyRoadType(rs->xy, rv->compatible_roadtypes)) return STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE;
return INVALID_STRING_ID;
/* Bay stop errors take precedence, but otherwise the vehicle may not be compatible with the roadtype/tramtype of this station tile.
* We give bay stop errors precedence because they are usually a bus sent to a tram station or vice versa. */
if (!HasTileAnyRoadType(rs->xy, rv->compatible_roadtypes) && err != STR_ERROR_NO_STOP_ARTICULATED_VEHICLE) {
err = RoadTypeIsRoad(rv->roadtype) ? STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE : STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE;
continue;
}
}
return err;
@ -4437,7 +4440,7 @@ StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st)
if (v->GetEngine()->u.air.subtype & AIR_CTOL) {
return STR_ERROR_AIRPORT_NO_PLANES;
} else {
return STR_ERROR_AIRPORT_NO_HELIS;
return STR_ERROR_AIRPORT_NO_HELICOPTERS;
}
default:

@ -37,6 +37,7 @@ enum IndustryDirectoryWidgets {
WID_ID_DROPDOWN_CRITERIA, ///< Dropdown for the criteria of the sort.
WID_ID_FILTER_BY_ACC_CARGO, ///< Accepted cargo filter dropdown list.
WID_ID_FILTER_BY_PROD_CARGO, ///< Produced cargo filter dropdown list.
WID_ID_FILTER, ///< Textbox to filter industry name.
WID_ID_INDUSTRY_LIST, ///< Industry list.
WID_ID_SCROLLBAR, ///< Scrollbar of the list.
};

Loading…
Cancel
Save