summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.cpp4
-rw-r--r--src/script/api/ai/ai_town.hpp.sq5
-rw-r--r--src/script/api/ai_changelog.hpp1
-rw-r--r--src/script/api/game/game_town.hpp.sq6
-rw-r--r--src/script/api/game_changelog.hpp2
-rw-r--r--src/script/api/script_town.cpp43
-rw-r--r--src/script/api/script_town.hpp40
-rw-r--r--src/script/api/template/template_town.hpp.sq2
-rw-r--r--src/town_cmd.cpp7
9 files changed, 106 insertions, 4 deletions
diff --git a/src/command.cpp b/src/command.cpp
index de0dbab60..2522d4af3 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -280,8 +280,8 @@ static const Command _command_proc_table[] = {
DEF_CMD(CmdSellShareInCompany, 0, CMDT_MONEY_MANAGEMENT ), // CMD_SELL_SHARE_IN_COMPANY
DEF_CMD(CmdBuyCompany, 0, CMDT_MONEY_MANAGEMENT ), // CMD_BUY_COMANY
- DEF_CMD(CmdFoundTown, CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_FOUND_TOWN; founding random town can fail only in exec run
- DEF_CMD(CmdRenameTown, CMD_SERVER, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_TOWN
+ DEF_CMD(CmdFoundTown, CMD_DEITY | CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_FOUND_TOWN; founding random town can fail only in exec run
+ DEF_CMD(CmdRenameTown, CMD_DEITY | CMD_SERVER, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_TOWN
DEF_CMD(CmdDoTownAction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_DO_TOWN_ACTION
DEF_CMD(CmdTownCargoGoal, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_CARGO_GOAL
DEF_CMD(CmdTownGrowthRate, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_TOWN_GROWTH_RATE
diff --git a/src/script/api/ai/ai_town.hpp.sq b/src/script/api/ai/ai_town.hpp.sq
index 70e3e994e..d626424ed 100644
--- a/src/script/api/ai/ai_town.hpp.sq
+++ b/src/script/api/ai/ai_town.hpp.sq
@@ -44,6 +44,10 @@ void SQAITown_Register(Squirrel *engine)
SQAITown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_2x2, "ROAD_LAYOUT_2x2");
SQAITown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_3x3, "ROAD_LAYOUT_3x3");
SQAITown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_INVALID, "ROAD_LAYOUT_INVALID");
+ SQAITown.DefSQConst(engine, ScriptTown::TOWN_SIZE_SMALL, "TOWN_SIZE_SMALL");
+ SQAITown.DefSQConst(engine, ScriptTown::TOWN_SIZE_MEDIUM, "TOWN_SIZE_MEDIUM");
+ SQAITown.DefSQConst(engine, ScriptTown::TOWN_SIZE_LARGE, "TOWN_SIZE_LARGE");
+ SQAITown.DefSQConst(engine, ScriptTown::TOWN_SIZE_INVALID, "TOWN_SIZE_INVALID");
SQAITown.DefSQStaticMethod(engine, &ScriptTown::GetTownCount, "GetTownCount", 1, ".");
SQAITown.DefSQStaticMethod(engine, &ScriptTown::IsValidTown, "IsValidTown", 2, ".i");
@@ -67,6 +71,7 @@ void SQAITown_Register(Squirrel *engine)
SQAITown.DefSQStaticMethod(engine, &ScriptTown::GetExclusiveRightsDuration, "GetExclusiveRightsDuration", 2, ".i");
SQAITown.DefSQStaticMethod(engine, &ScriptTown::IsActionAvailable, "IsActionAvailable", 3, ".ii");
SQAITown.DefSQStaticMethod(engine, &ScriptTown::PerformTownAction, "PerformTownAction", 3, ".ii");
+ SQAITown.DefSQStaticMethod(engine, &ScriptTown::FoundTown, "FoundTown", 6, ".iibi.");
SQAITown.DefSQStaticMethod(engine, &ScriptTown::GetRating, "GetRating", 3, ".ii");
SQAITown.DefSQStaticMethod(engine, &ScriptTown::GetAllowedNoise, "GetAllowedNoise", 2, ".i");
SQAITown.DefSQStaticMethod(engine, &ScriptTown::GetRoadLayout, "GetRoadLayout", 2, ".i");
diff --git a/src/script/api/ai_changelog.hpp b/src/script/api/ai_changelog.hpp
index 9519c2607..9b224d590 100644
--- a/src/script/api/ai_changelog.hpp
+++ b/src/script/api/ai_changelog.hpp
@@ -22,6 +22,7 @@
* API additions:
* \li AIStation::HasCargoRating
* \li AITile::GetTerrainType
+ * \li AITown::FoundTown
*
* Other changes:
* \li AIStation::GetCargoRating does return -1 for cargo-station combinations that
diff --git a/src/script/api/game/game_town.hpp.sq b/src/script/api/game/game_town.hpp.sq
index ddd80c59d..af5b15944 100644
--- a/src/script/api/game/game_town.hpp.sq
+++ b/src/script/api/game/game_town.hpp.sq
@@ -44,10 +44,15 @@ void SQGSTown_Register(Squirrel *engine)
SQGSTown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_2x2, "ROAD_LAYOUT_2x2");
SQGSTown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_3x3, "ROAD_LAYOUT_3x3");
SQGSTown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_INVALID, "ROAD_LAYOUT_INVALID");
+ SQGSTown.DefSQConst(engine, ScriptTown::TOWN_SIZE_SMALL, "TOWN_SIZE_SMALL");
+ SQGSTown.DefSQConst(engine, ScriptTown::TOWN_SIZE_MEDIUM, "TOWN_SIZE_MEDIUM");
+ SQGSTown.DefSQConst(engine, ScriptTown::TOWN_SIZE_LARGE, "TOWN_SIZE_LARGE");
+ SQGSTown.DefSQConst(engine, ScriptTown::TOWN_SIZE_INVALID, "TOWN_SIZE_INVALID");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::GetTownCount, "GetTownCount", 1, ".");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::IsValidTown, "IsValidTown", 2, ".i");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::GetName, "GetName", 2, ".i");
+ SQGSTown.DefSQStaticMethod(engine, &ScriptTown::SetName, "SetName", 3, ".i.");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::SetText, "SetText", 3, ".i.");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::GetPopulation, "GetPopulation", 2, ".i");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::GetHouseCount, "GetHouseCount", 2, ".i");
@@ -71,6 +76,7 @@ void SQGSTown_Register(Squirrel *engine)
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::IsActionAvailable, "IsActionAvailable", 3, ".ii");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::PerformTownAction, "PerformTownAction", 3, ".ii");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::ExpandTown, "ExpandTown", 3, ".ii");
+ SQGSTown.DefSQStaticMethod(engine, &ScriptTown::FoundTown, "FoundTown", 6, ".iibi.");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::GetRating, "GetRating", 3, ".ii");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::GetAllowedNoise, "GetAllowedNoise", 2, ".i");
SQGSTown.DefSQStaticMethod(engine, &ScriptTown::GetRoadLayout, "GetRoadLayout", 2, ".i");
diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp
index ee21d0be9..ebab776a4 100644
--- a/src/script/api/game_changelog.hpp
+++ b/src/script/api/game_changelog.hpp
@@ -27,6 +27,8 @@
* \li GSStation::HasCargoRating
* \li GSStoryPage
* \li GSTile::GetTerrainType
+ * \li GSTown::FoundTown
+ * \li GSTown::SetName
*
* Other changes:
* \li GSGoal::New can now create up to 64000 concurrent goals. The old limit was 256 goals.
diff --git a/src/script/api/script_town.cpp b/src/script/api/script_town.cpp
index b64adab1a..3b9a4b7b6 100644
--- a/src/script/api/script_town.cpp
+++ b/src/script/api/script_town.cpp
@@ -14,6 +14,7 @@
#include "script_map.hpp"
#include "script_error.hpp"
#include "../../town.h"
+#include "../../townname_func.h"
#include "../../string_func.h"
#include "../../strings_func.h"
#include "../../station_base.h"
@@ -38,6 +39,21 @@
return GetString(STR_TOWN_NAME);
}
+/* static */ bool ScriptTown::SetName(TownID town_id, Text *name)
+{
+ CCountedPtr<Text> counter(name);
+
+ const char *text = NULL;
+ if (name != NULL) {
+ const char *text = name->GetDecodedText();
+ EnforcePreconditionEncodedText(false, text);
+ EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
+ }
+ EnforcePrecondition(false, IsValidTown(town_id));
+
+ return ScriptObject::DoCommand(0, town_id, 0, CMD_RENAME_TOWN, text);
+}
+
/* static */ bool ScriptTown::SetText(TownID town_id, Text *text)
{
CCountedPtr<Text> counter(text);
@@ -238,6 +254,33 @@
return ScriptObject::DoCommand(::Town::Get(town_id)->xy, town_id, houses, CMD_EXPAND_TOWN);
}
+/* static */ bool ScriptTown::FoundTown(TileIndex tile, TownSize size, bool city, RoadLayout layout, Text *name)
+{
+ CCountedPtr<Text> counter(name);
+
+ EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY || _settings_game.economy.found_town != TF_FORBIDDEN);
+ EnforcePrecondition(false, ::IsValidTile(tile));
+ EnforcePrecondition(false, size == TOWN_SIZE_SMALL || size == TOWN_SIZE_MEDIUM || size == TOWN_SIZE_LARGE)
+ EnforcePrecondition(false, size != TOWN_SIZE_LARGE || ScriptObject::GetCompany() == OWNER_DEITY);
+ if (ScriptObject::GetCompany() == OWNER_DEITY || _settings_game.economy.found_town == TF_CUSTOM_LAYOUT) {
+ EnforcePrecondition(false, layout == ROAD_LAYOUT_ORIGINAL || layout == ROAD_LAYOUT_BETTER_ROADS || layout == ROAD_LAYOUT_2x2 || layout == ROAD_LAYOUT_3x3);
+ } else {
+ /* The layout parameter is ignored for AIs when custom layouts is disabled. */
+ layout = (RoadLayout) (byte)_settings_game.economy.town_layout;
+ }
+
+ const char *text = NULL;
+ if (name != NULL) {
+ text = name->GetDecodedText();
+ EnforcePreconditionEncodedText(false, text);
+ EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
+ }
+ uint32 townnameparts;
+ GenerateTownName(&townnameparts);
+
+ return ScriptObject::DoCommand(tile, size | (city ? 1 << 2 : 0) | layout << 3, townnameparts, CMD_FOUND_TOWN, text);
+}
+
/* static */ ScriptTown::TownRating ScriptTown::GetRating(TownID town_id, ScriptCompany::CompanyID company_id)
{
if (!IsValidTown(town_id)) return TOWN_RATING_INVALID;
diff --git a/src/script/api/script_town.hpp b/src/script/api/script_town.hpp
index 1c544ffbe..b41b7f401 100644
--- a/src/script/api/script_town.hpp
+++ b/src/script/api/script_town.hpp
@@ -106,6 +106,17 @@ public:
};
/**
+ * Possible town construction sizes.
+ */
+ enum TownSize {
+ TOWN_SIZE_SMALL = ::TSZ_SMALL, ///< Small town.
+ TOWN_SIZE_MEDIUM = ::TSZ_MEDIUM, ///< Medium town.
+ TOWN_SIZE_LARGE = ::TSZ_LARGE, ///< Large town.
+
+ TOWN_SIZE_INVALID = -1, ///< Invalid town size.
+ };
+
+ /**
* Gets the number of towns.
* @return The number of towns.
*/
@@ -127,6 +138,16 @@ public:
static char *GetName(TownID town_id);
/**
+ * Rename a town.
+ * @param town_id The town to rename
+ * @param name The new name of the town. If NULL or an empty string is passed, the town name will be reset to the default name.
+ * @pre IsValidTown(town_id).
+ * @return True if the action succeeded.
+ * @api -ai
+ */
+ static bool SetName(TownID town_id, Text *name);
+
+ /**
* Set the custom text of a town, shown in the GUI.
* @param town_id The town to set the custom text of.
* @param text The text to set it to (can be either a raw string, or a ScriptText object).
@@ -356,6 +377,25 @@ public:
static bool ExpandTown(TownID town_id, int houses);
/**
+ * Found a new town.
+ * @param tile The location of the new town.
+ * @param size The town size of the new town.
+ * @param city True if the new town should be a city.
+ * @param layout The town layout of the new town.
+ * @param name The name of the new town. Pass NULL to use a random town name.
+ * @game @pre no company mode in scope || ScriptSettings.GetValue("economy.found_town") != 0.
+ * @ai @pre ScriptSettings.GetValue("economy.found_town") != 0.
+ * @game @pre no company mode in scope || size != TOWN_SIZE_LARGE.
+ * @ai @pre size != TOWN_SIZE_LARGE.
+ * @pre size != TOWN_SIZE_INVALID.
+ * @pre layout != ROAD_LAYOUT_INVALID.
+ * @return True if the action succeeded.
+ * @game @note Companies are restricted by the advanced setting that controls if funding towns is allowed or not. If custom road layout is forbidden and there is a company mode in scope, the layout parameter will be ignored.
+ * @ai @note AIs are restricted by the advanced setting that controls if funding towns is allowed or not. If custom road layout is forbidden, the layout parameter will be ignored.
+ */
+ static bool FoundTown(TileIndex tile, TownSize size, bool city, RoadLayout layout, Text *name);
+
+ /**
* Get the rating of a company within a town.
* @param town_id The town to get the rating for.
* @param company_id The company to get the rating for.
diff --git a/src/script/api/template/template_town.hpp.sq b/src/script/api/template/template_town.hpp.sq
index 8eda7fce3..3c48d9835 100644
--- a/src/script/api/template/template_town.hpp.sq
+++ b/src/script/api/template/template_town.hpp.sq
@@ -19,6 +19,8 @@ namespace SQConvert {
template <> inline int Return<ScriptTown::TownRating>(HSQUIRRELVM vm, ScriptTown::TownRating res) { sq_pushinteger(vm, (int32)res); return 1; }
template <> inline ScriptTown::RoadLayout GetParam(ForceType<ScriptTown::RoadLayout>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptTown::RoadLayout)tmp; }
template <> inline int Return<ScriptTown::RoadLayout>(HSQUIRRELVM vm, ScriptTown::RoadLayout res) { sq_pushinteger(vm, (int32)res); return 1; }
+ template <> inline ScriptTown::TownSize GetParam(ForceType<ScriptTown::TownSize>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptTown::TownSize)tmp; }
+ template <> inline int Return<ScriptTown::TownSize>(HSQUIRRELVM vm, ScriptTown::TownSize res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow ScriptTown to be used as Squirrel parameter */
template <> inline ScriptTown *GetParam(ForceType<ScriptTown *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptTown *)instance; }
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index 729769212..7241f7ed4 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -1621,14 +1621,17 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
if (size >= TSZ_END) return CMD_ERROR;
if (layout >= NUM_TLS) return CMD_ERROR;
- /* Some things are allowed only in the scenario editor */
- if (_game_mode != GM_EDITOR) {
+ /* Some things are allowed only in the scenario editor and for game scripts. */
+ if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY) {
if (_settings_game.economy.found_town == TF_FORBIDDEN) return CMD_ERROR;
if (size == TSZ_LARGE) return CMD_ERROR;
if (random) return CMD_ERROR;
if (_settings_game.economy.found_town != TF_CUSTOM_LAYOUT && layout != _settings_game.economy.town_layout) {
return CMD_ERROR;
}
+ } else if (_current_company == OWNER_DEITY && random) {
+ /* Random parameter is not allowed for Game Scripts. */
+ return CMD_ERROR;
}
if (StrEmpty(text)) {