From 67ab3108d6b4ca9676871cabdae3ed187d51393d Mon Sep 17 00:00:00 2001 From: zuu Date: Thu, 19 Sep 2013 18:48:05 +0000 Subject: (svn r25785) -Feature: [Script] Allow AIs and GS to found towns. Allow GS to rename towns --- src/script/api/ai/ai_town.hpp.sq | 5 ++++ src/script/api/ai_changelog.hpp | 1 + src/script/api/game/game_town.hpp.sq | 6 ++++ src/script/api/game_changelog.hpp | 2 ++ src/script/api/script_town.cpp | 43 ++++++++++++++++++++++++++++ src/script/api/script_town.hpp | 40 ++++++++++++++++++++++++++ src/script/api/template/template_town.hpp.sq | 2 ++ 7 files changed, 99 insertions(+) (limited to 'src/script') 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 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 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 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 @@ -105,6 +105,17 @@ public: ROAD_LAYOUT_INVALID = -1, ///< The layout for invalid towns. }; + /** + * 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. @@ -126,6 +137,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. @@ -355,6 +376,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. 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(HSQUIRRELVM vm, ScriptTown::TownRating res) { sq_pushinteger(vm, (int32)res); return 1; } template <> inline ScriptTown::RoadLayout GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptTown::RoadLayout)tmp; } template <> inline int Return(HSQUIRRELVM vm, ScriptTown::RoadLayout res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline ScriptTown::TownSize GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptTown::TownSize)tmp; } + template <> inline int Return(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, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptTown *)instance; } -- cgit v1.2.3-54-g00ecf