mirror of https://github.com/OpenTTD/OpenTTD
Add: Command to build an individual house on a specific tile.
parent
f901722066
commit
d99c1337a2
|
@ -283,6 +283,7 @@ enum Commands : uint16_t {
|
||||||
CMD_TOWN_SET_TEXT, ///< set the custom text of a town
|
CMD_TOWN_SET_TEXT, ///< set the custom text of a town
|
||||||
CMD_EXPAND_TOWN, ///< expand a town
|
CMD_EXPAND_TOWN, ///< expand a town
|
||||||
CMD_DELETE_TOWN, ///< delete a town
|
CMD_DELETE_TOWN, ///< delete a town
|
||||||
|
CMD_PLACE_HOUSE, ///< place a house
|
||||||
|
|
||||||
CMD_ORDER_REFIT, ///< change the refit information of an order (for "goto depot" )
|
CMD_ORDER_REFIT, ///< change the refit information of an order (for "goto depot" )
|
||||||
CMD_CLONE_ORDER, ///< clone (and share) an order
|
CMD_CLONE_ORDER, ///< clone (and share) an order
|
||||||
|
|
106
src/town_cmd.cpp
106
src/town_cmd.cpp
|
@ -2665,6 +2665,39 @@ static bool CheckTownBuild2x2House(TileIndex *tile, Town *t, int maxz, bool nosl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a house at this tile.
|
||||||
|
* @param t The town the house will belong to.
|
||||||
|
* @param tile The tile to try building on.
|
||||||
|
* @param hs The @a HouseSpec of the house.
|
||||||
|
* @param house The @a HouseID of the house.
|
||||||
|
* @param random_bits The random data to be associated with the house.
|
||||||
|
*/
|
||||||
|
static void BuildTownHouse(Town *t, TileIndex tile, const HouseSpec *hs, HouseID house, uint8_t random_bits)
|
||||||
|
{
|
||||||
|
/* build the house */
|
||||||
|
t->cache.num_houses++;
|
||||||
|
|
||||||
|
uint8_t construction_counter = 0;
|
||||||
|
uint8_t construction_stage = 0;
|
||||||
|
|
||||||
|
if (_generating_world || _game_mode == GM_EDITOR) {
|
||||||
|
uint32_t construction_random = Random();
|
||||||
|
|
||||||
|
construction_stage = TOWN_HOUSE_COMPLETED;
|
||||||
|
if (Chance16(1, 7)) construction_stage = GB(construction_random, 0, 2);
|
||||||
|
|
||||||
|
if (construction_stage == TOWN_HOUSE_COMPLETED) {
|
||||||
|
ChangePopulation(t, hs->population);
|
||||||
|
} else {
|
||||||
|
construction_counter = GB(construction_random, 2, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
|
||||||
|
UpdateTownRadius(t);
|
||||||
|
UpdateTownGrowthRate(t);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to build a house at this tile.
|
* Tries to build a house at this tile.
|
||||||
|
@ -2784,31 +2817,10 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile)
|
||||||
if (callback_res != CALLBACK_FAILED && !Convert8bitBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_ALLOW_CONSTRUCTION, callback_res)) continue;
|
if (callback_res != CALLBACK_FAILED && !Convert8bitBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_ALLOW_CONSTRUCTION, callback_res)) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build the house */
|
|
||||||
t->cache.num_houses++;
|
|
||||||
|
|
||||||
/* Special houses that there can be only one of. */
|
/* Special houses that there can be only one of. */
|
||||||
t->flags |= oneof;
|
t->flags |= oneof;
|
||||||
|
|
||||||
uint8_t construction_counter = 0;
|
BuildTownHouse(t, tile, hs, house, random_bits);
|
||||||
uint8_t construction_stage = 0;
|
|
||||||
|
|
||||||
if (_generating_world || _game_mode == GM_EDITOR) {
|
|
||||||
uint32_t construction_random = Random();
|
|
||||||
|
|
||||||
construction_stage = TOWN_HOUSE_COMPLETED;
|
|
||||||
if (Chance16(1, 7)) construction_stage = GB(construction_random, 0, 2);
|
|
||||||
|
|
||||||
if (construction_stage == TOWN_HOUSE_COMPLETED) {
|
|
||||||
ChangePopulation(t, hs->population);
|
|
||||||
} else {
|
|
||||||
construction_counter = GB(construction_random, 2, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
|
|
||||||
UpdateTownRadius(t);
|
|
||||||
UpdateTownGrowthRate(t);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2816,6 +2828,56 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandCost CmdPlaceHouse(DoCommandFlag flags, TileIndex tile, HouseID house)
|
||||||
|
{
|
||||||
|
if (_game_mode != GM_EDITOR) return CMD_ERROR;
|
||||||
|
if (Town::GetNumItems() == 0) return_cmd_error(STR_ERROR_MUST_FOUND_TOWN_FIRST);
|
||||||
|
|
||||||
|
if (static_cast<size_t>(house) >= HouseSpec::Specs().size()) return CMD_ERROR;
|
||||||
|
const HouseSpec *hs = HouseSpec::Get(house);
|
||||||
|
if (!hs->enabled) return CMD_ERROR;
|
||||||
|
|
||||||
|
if (TimerGameCalendar::year < hs->min_year || TimerGameCalendar::year > hs->max_year) return CMD_ERROR;
|
||||||
|
|
||||||
|
Town *t = ClosestTownFromTile(tile, UINT_MAX);
|
||||||
|
|
||||||
|
/* cannot build on these slopes... */
|
||||||
|
Slope slope = GetTileSlope(tile);
|
||||||
|
if (IsSteepSlope(slope)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||||
|
|
||||||
|
/* building under a bridge? */
|
||||||
|
if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||||
|
|
||||||
|
/* can we clear the land? */
|
||||||
|
CommandCost cost = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_WATER, tile);
|
||||||
|
if (!cost.Succeeded()) return cost;
|
||||||
|
|
||||||
|
int maxz = GetTileMaxZ(tile);
|
||||||
|
|
||||||
|
/* Make sure there is no slope? */
|
||||||
|
bool noslope = (hs->building_flags & TILE_NOT_SLOPED) != 0;
|
||||||
|
if (noslope && slope != SLOPE_FLAT) return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
|
||||||
|
|
||||||
|
TileArea ta = tile;
|
||||||
|
if (hs->building_flags & TILE_SIZE_2x2) ta.Add(TileAddXY(tile, 1, 1));
|
||||||
|
if (hs->building_flags & TILE_SIZE_2x1) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SW));
|
||||||
|
if (hs->building_flags & TILE_SIZE_1x2) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SE));
|
||||||
|
|
||||||
|
/* Check additonal tiles covered by this house. */
|
||||||
|
for (const TileIndex &subtile : ta) {
|
||||||
|
cost = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_WATER, subtile);
|
||||||
|
if (!cost.Succeeded()) return cost;
|
||||||
|
|
||||||
|
if (!CheckBuildHouseSameZ(subtile, maxz, noslope)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
BuildTownHouse(t, tile, hs, house, Random());
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommandCost();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update data structures when a house is removed
|
* Update data structures when a house is removed
|
||||||
* @param tile Tile of the house
|
* @param tile Tile of the house
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "town_type.h"
|
#include "town_type.h"
|
||||||
|
|
||||||
enum TownAcceptanceEffect : uint8_t;
|
enum TownAcceptanceEffect : uint8_t;
|
||||||
|
using HouseID = uint16_t;
|
||||||
|
|
||||||
std::tuple<CommandCost, Money, TownID> CmdFoundTown(DoCommandFlag flags, TileIndex tile, TownSize size, bool city, TownLayout layout, bool random_location, uint32_t townnameparts, const std::string &text);
|
std::tuple<CommandCost, Money, TownID> CmdFoundTown(DoCommandFlag flags, TileIndex tile, TownSize size, bool city, TownLayout layout, bool random_location, uint32_t townnameparts, const std::string &text);
|
||||||
CommandCost CmdRenameTown(DoCommandFlag flags, TownID town_id, const std::string &text);
|
CommandCost CmdRenameTown(DoCommandFlag flags, TownID town_id, const std::string &text);
|
||||||
|
@ -25,6 +26,7 @@ CommandCost CmdTownCargoGoal(DoCommandFlag flags, TownID town_id, TownAcceptance
|
||||||
CommandCost CmdTownSetText(DoCommandFlag flags, TownID town_id, const std::string &text);
|
CommandCost CmdTownSetText(DoCommandFlag flags, TownID town_id, const std::string &text);
|
||||||
CommandCost CmdExpandTown(DoCommandFlag flags, TownID town_id, uint32_t grow_amount);
|
CommandCost CmdExpandTown(DoCommandFlag flags, TownID town_id, uint32_t grow_amount);
|
||||||
CommandCost CmdDeleteTown(DoCommandFlag flags, TownID town_id);
|
CommandCost CmdDeleteTown(DoCommandFlag flags, TownID town_id);
|
||||||
|
CommandCost CmdPlaceHouse(DoCommandFlag flags, TileIndex tile, HouseID house);
|
||||||
|
|
||||||
DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CMD_DEITY | CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION) // founding random town can fail only in exec run
|
DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CMD_DEITY | CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION) // founding random town can fail only in exec run
|
||||||
DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CMD_DEITY | CMD_SERVER, CMDT_OTHER_MANAGEMENT)
|
DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CMD_DEITY | CMD_SERVER, CMDT_OTHER_MANAGEMENT)
|
||||||
|
@ -35,6 +37,7 @@ DEF_CMD_TRAIT(CMD_TOWN_RATING, CmdTownRating, CMD_DEITY,
|
||||||
DEF_CMD_TRAIT(CMD_TOWN_SET_TEXT, CmdTownSetText, CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
|
DEF_CMD_TRAIT(CMD_TOWN_SET_TEXT, CmdTownSetText, CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
|
||||||
DEF_CMD_TRAIT(CMD_EXPAND_TOWN, CmdExpandTown, CMD_DEITY, CMDT_LANDSCAPE_CONSTRUCTION)
|
DEF_CMD_TRAIT(CMD_EXPAND_TOWN, CmdExpandTown, CMD_DEITY, CMDT_LANDSCAPE_CONSTRUCTION)
|
||||||
DEF_CMD_TRAIT(CMD_DELETE_TOWN, CmdDeleteTown, CMD_OFFLINE, CMDT_LANDSCAPE_CONSTRUCTION)
|
DEF_CMD_TRAIT(CMD_DELETE_TOWN, CmdDeleteTown, CMD_OFFLINE, CMDT_LANDSCAPE_CONSTRUCTION)
|
||||||
|
DEF_CMD_TRAIT(CMD_PLACE_HOUSE, CmdPlaceHouse, CMD_DEITY, CMDT_OTHER_MANAGEMENT)
|
||||||
|
|
||||||
CommandCallback CcFoundTown;
|
CommandCallback CcFoundTown;
|
||||||
void CcFoundRandomTown(Commands cmd, const CommandCost &result, Money, TownID town_id);
|
void CcFoundRandomTown(Commands cmd, const CommandCost &result, Money, TownID town_id);
|
||||||
|
|
Loading…
Reference in New Issue