(svn r25785) -Feature: [Script] Allow AIs and GS to found towns. Allow GS to rename towns

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
zuu 11 years ago
parent 953aa839b9
commit 67ab3108d6

@ -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

@ -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");

@ -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

@ -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");

@ -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.

@ -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;

@ -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.

@ -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; }

@ -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)) {

Loading…
Cancel
Save