diff options
-rw-r--r-- | src/command.cpp | 4 | ||||
-rw-r--r-- | src/script/api/ai/ai_town.hpp.sq | 5 | ||||
-rw-r--r-- | src/script/api/ai_changelog.hpp | 1 | ||||
-rw-r--r-- | src/script/api/game/game_town.hpp.sq | 6 | ||||
-rw-r--r-- | src/script/api/game_changelog.hpp | 2 | ||||
-rw-r--r-- | src/script/api/script_town.cpp | 43 | ||||
-rw-r--r-- | src/script/api/script_town.hpp | 40 | ||||
-rw-r--r-- | src/script/api/template/template_town.hpp.sq | 2 | ||||
-rw-r--r-- | src/town_cmd.cpp | 7 |
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)) { |