@ -52,6 +52,8 @@
# include "safeguards.h"
static const uint SQUARED_TOWN_RADIUS_FUNDED_CENTRE = 26 ; ///< Squared radius (exclusive) for the most inner #HZB_TOWN_CENTRE town zone while "fund buildings" is in progress.
TownID _new_town_id ;
uint32 _town_cargoes_accepted ; ///< Bitmap of all cargoes accepted by houses.
@ -70,6 +72,10 @@ Town::~Town()
* and remove from list of sorted towns */
DeleteWindowById ( WC_TOWN_VIEW , this - > index ) ;
/* It is possible that "select town to join house to" window
* contain this town . Simply close it . */
DeleteWindowById ( WC_SELECT_TOWN , 0 ) ;
/* Check no industry is related to us. */
const Industry * i ;
FOR_ALL_INDUSTRIES ( i ) assert ( i - > town ! = this ) ;
@ -162,6 +168,64 @@ void Town::InitializeLayout(TownLayout layout)
return Town : : Get ( index ) ;
}
static inline uint16 DefaultHouseCostForCargoAccepted ( uint16 callback_mask , byte cargo_acceptance , CargoID accepts_cargo )
{
uint16 cost = HasBit ( callback_mask , CBM_HOUSE_CARGO_ACCEPTANCE ) ? 6 : cargo_acceptance ; // assume 75% (6/8) if cb 1F is available
if ( HasBit ( callback_mask , CBM_HOUSE_ACCEPT_CARGO ) ) {
return cost * 4 ; // assume 50% if cb 2A is available (all three cargoes)
} else if ( accepts_cargo = = CT_PASSENGERS | | accepts_cargo = = CT_MAIL ) {
return cost * 2 ; // 25% for passengers/mail
} else if ( accepts_cargo ! = CT_INVALID ) {
return cost * 8 ; // 100% for other cargo (goods etc.)
} else {
return 0 ;
}
}
/**
* Generate default value of the house build cost multiplier for a
* house of given properties .
*
* @ param callback_mask The bitmask of callbacks defined for the house . Used to determine
* if the house has custom cargo production / acceptance .
* @ param population Population of the house .
* @ param mail_generation Mail generation multiplier of the house .
* @ param cargo_acceptance1 How much cargo is accepted by the house ( first cargo ) .
* @ param cargo_acceptance2 How much cargo is accepted by the house ( second cargo ) .
* @ param cargo_acceptance3 How much cargo is accepted by the house ( third cargo ) .
* @ param accepts_cargo1 Cargo accepted by the house ( first ) .
* @ param accepts_cargo2 Cargo accepted by the house ( second ) .
* @ param accepts_cargo3 Cargo accepted by the house ( third ) .
* @ return Default build cost multiplier .
*
* @ see HouseSpec
*/
uint16 DefaultHouseCostBaseMultiplier ( uint16 callback_mask , byte population , byte mail_generation , byte cargo_acceptance1 , byte cargo_acceptance2 , byte cargo_acceptance3 , CargoID accepts_cargo1 , CargoID accepts_cargo2 , CargoID accepts_cargo3 )
{
uint16 cost = 64 ;
if ( HasBit ( callback_mask , CBM_HOUSE_PRODUCE_CARGO ) ) {
cost + = 128 * 3 / 4 ; // assume 75% if cb 2E is available
} else {
cost + = 128 * ( population * population + mail_generation * mail_generation ) / ( 255 * 255 + 255 * 255 ) ;
}
cost + = DefaultHouseCostForCargoAccepted ( callback_mask , cargo_acceptance1 , accepts_cargo1 ) ;
cost + = DefaultHouseCostForCargoAccepted ( callback_mask , cargo_acceptance2 , accepts_cargo2 ) ;
cost + = DefaultHouseCostForCargoAccepted ( callback_mask , cargo_acceptance3 , accepts_cargo3 ) ;
return cost ;
}
/**
* Get the cost for building this house
* @ return the cost ( inflation corrected etc )
*/
Money HouseSpec : : GetConstructionCost ( ) const
{
return ( _price [ PR_BUILD_HOUSE ] * this - > construction_cost ) > > 8 ;
}
/**
* Updates the town label of the town after changes in rating . The colour scheme is :
* Red : Appalling and Very poor ratings .
@ -293,7 +357,8 @@ static void DrawOldHouseTileInGUI(int x, int y, HouseID house_id, bool ground)
} else {
/* Add a house on top of the ground? */
if ( dcts - > building . sprite ! = 0 ) {
DrawSprite ( dcts - > building . sprite , dcts - > building . pal , x + dcts - > subtile_x , y + dcts - > subtile_y ) ;
Point sub = RemapCoords ( dcts - > subtile_x , dcts - > subtile_y , 0 ) ;
DrawSprite ( dcts - > building . sprite , dcts - > building . pal , x + UnScaleGUI ( sub . x ) , y + UnScaleGUI ( sub . y ) ) ;
}
/* Draw the lift */
if ( dcts - > draw_proc = = 1 ) DrawHouseLiftInGUI ( x , y ) ;
@ -301,15 +366,17 @@ static void DrawOldHouseTileInGUI(int x, int y, HouseID house_id, bool ground)
}
/**
* Draw image of a house . Image will be centered between the \ c left and the \ c right and vertical y aligned to the \ c bottom .
* Draw image of a house . Image will be centered between the \ c left and the \ c right and vertical l y aligned to the \ c bottom .
*
* @ param house_id house type
* @ param left left bound of the drawing area
* @ param top top bound of the drawing area
* @ param right right bound of the drawing area
* @ param bottom bottom bound of the drawing area
* @ param image_type Context in which the house is being drawn
* @ param variant house variant
*/
void DrawHouseImage ( HouseID house_id , int left , int top , int right , int bottom )
void DrawHouseImage ( HouseID house_id , int left , int top , int right , int bottom , HouseImageType image_type , HouseVariant variant )
{
DrawPixelInfo tmp_dpi ;
if ( ! FillDrawPixelInfo ( & tmp_dpi , left , top , right - left + 1 , bottom - top + 1 ) ) return ;
@ -318,13 +385,14 @@ void DrawHouseImage(HouseID house_id, int left, int top, int right, int bottom)
const HouseSpec * hs = HouseSpec : : Get ( house_id ) ;
/* sprites are relative to the topmost pixel of the ground tile */
uint x = ( right - left + 1 ) / 2 ;
uint y = bottom - top + 1 - TILE_PIXELS ;
if ( hs - > building_flags & TILE_SIZE_1x2 ) x - = TILE_PIXELS / 2 ;
if ( hs - > building_flags & TILE_SIZE_2x1 ) x + = TILE_PIXELS / 2 ;
if ( hs - > building_flags & BUILDING_HAS_2_TILES ) y - = TILE_PIXELS / 2 ;
if ( hs - > building_flags & BUILDING_HAS_4_TILES ) y - = TILE_PIXELS / 2 ;
/* sprites are relative to the top corner of the ground tile */
const uint gui_tile_pixels = ScaleGUITrad ( TILE_PIXELS ) ; // TILE_PIXELS rescaled to current GUI zoom
uint x = ( right - left ) / 2 ;
uint y = bottom - top - gui_tile_pixels ;
if ( hs - > building_flags & TILE_SIZE_1x2 ) x - = gui_tile_pixels / 2 ;
if ( hs - > building_flags & TILE_SIZE_2x1 ) x + = gui_tile_pixels / 2 ;
if ( hs - > building_flags & BUILDING_HAS_2_TILES ) y - = gui_tile_pixels / 2 ;
if ( hs - > building_flags & BUILDING_HAS_4_TILES ) y - = gui_tile_pixels / 2 ;
bool new_house = false ;
if ( house_id > = NEW_HOUSE_OFFSET ) {
@ -346,10 +414,10 @@ void DrawHouseImage(HouseID house_id, int left, int top, int right, int bottom)
for ( uint row = 0 ; row < num_row ; row + + ) {
for ( uint col = 0 ; col < num_col ; col + + ) {
Point offset = RemapCoords ( row * TILE_SIZE , col * TILE_SIZE , 0 ) ; // offset for current tile
offset . x = UnScale ByZoom( offset . x , ZOOM_LVL_GUI ) ;
offset . y = UnScale ByZoom( offset . y , ZOOM_LVL_GUI ) ;
offset . x = UnScale GUI( offset . x ) ;
offset . y = UnScale GUI( offset . y ) ;
if ( new_house ) {
DrawNewHouseTileInGUI ( x + offset . x , y + offset . y , hid , ground) ;
DrawNewHouseTileInGUI ( x + offset . x , y + offset . y , hid , variant, image_type , ground) ;
} else {
DrawOldHouseTileInGUI ( x + offset . x , y + offset . y , hid , ground ) ;
}
@ -725,14 +793,15 @@ static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlag flags)
return cost ;
}
void AddProducedHouseCargo ( HouseID house_id , TileIndex tile , CargoArray & produced )
void AddProducedHouseCargo ( HouseID house_id , TileIndex tile , CargoArray & produced , HouseVariant variant )
{
const HouseSpec * hs = HouseSpec : : Get ( house_id ) ;
if ( HasBit ( hs - > callback_mask , CBM_HOUSE_PRODUCE_CARGO ) ) {
Town * t = ( tile = = INVALID_TILE ) ? NULL : Town : : GetByTile ( tile ) ;
HouseImageType image_type = ( tile = = INVALID_TILE ) ? HIT_GUI_HOUSE_PREVIEW : HIT_HOUSE_TILE ;
for ( uint i = 0 ; i < 256 ; i + + ) {
uint16 callback = GetHouseCallback ( CBID_HOUSE_PRODUCE_CARGO , i , 0 , house_id , t , tile );
uint16 callback = GetHouseCallback ( CBID_HOUSE_PRODUCE_CARGO , i , 0 , house_id , t , tile , image_type , variant );
if ( callback = = CALLBACK_FAILED | | callback = = CALLBACK_HOUSEPRODCARGO_END ) break ;
@ -763,10 +832,11 @@ static inline void AddAcceptedCargoSetMask(CargoID cargo, uint amount, CargoArra
SetBit ( * always_accepted , cargo ) ;
}
void AddAcceptedHouseCargo ( HouseID house_id , TileIndex tile , CargoArray & acceptance , uint32 * always_accepted )
void AddAcceptedHouseCargo ( HouseID house_id , TileIndex tile , CargoArray & acceptance , uint32 * always_accepted , HouseVariant variant )
{
const HouseSpec * hs = HouseSpec : : Get ( house_id ) ;
Town * t = ( tile = = INVALID_TILE ) ? NULL : Town : : GetByTile ( tile ) ;
HouseImageType image_type = ( tile = = INVALID_TILE ) ? HIT_GUI_HOUSE_PREVIEW : HIT_HOUSE_TILE ;
CargoID accepts [ 3 ] ;
/* Set the initial accepted cargo types */
@ -776,7 +846,7 @@ void AddAcceptedHouseCargo(HouseID house_id, TileIndex tile, CargoArray &accepta
/* Check for custom accepted cargo types */
if ( HasBit ( hs - > callback_mask , CBM_HOUSE_ACCEPT_CARGO ) ) {
uint16 callback = GetHouseCallback ( CBID_HOUSE_ACCEPT_CARGO , 0 , 0 , house_id , t , tile );
uint16 callback = GetHouseCallback ( CBID_HOUSE_ACCEPT_CARGO , 0 , 0 , house_id , t , tile , image_type , variant );
if ( callback ! = CALLBACK_FAILED ) {
/* Replace accepted cargo types with translated values from callback */
accepts [ 0 ] = GetCargoTranslation ( GB ( callback , 0 , 5 ) , hs - > grf_prop . grffile ) ;
@ -787,7 +857,7 @@ void AddAcceptedHouseCargo(HouseID house_id, TileIndex tile, CargoArray &accepta
/* Check for custom cargo acceptance */
if ( HasBit ( hs - > callback_mask , CBM_HOUSE_CARGO_ACCEPTANCE ) ) {
uint16 callback = GetHouseCallback ( CBID_HOUSE_CARGO_ACCEPTANCE , 0 , 0 , house_id , t , tile );
uint16 callback = GetHouseCallback ( CBID_HOUSE_CARGO_ACCEPTANCE , 0 , 0 , house_id , t , tile , image_type , variant );
if ( callback ! = CALLBACK_FAILED ) {
AddAcceptedCargoSetMask ( accepts [ 0 ] , GB ( callback , 0 , 4 ) , acceptance , always_accepted ) ;
AddAcceptedCargoSetMask ( accepts [ 1 ] , GB ( callback , 4 , 4 ) , acceptance , always_accepted ) ;
@ -2138,32 +2208,52 @@ bool GenerateTowns(TownLayout layout)
/**
* Returns the bit corresponding to the town zone of the specified tile
* or # HZB_END if the tile is ouside of the town .
* Returns the bit corresponding to the town zone of the specified tile .
* Also returns bounds of this zone .
*
* Unlikely to # GetTownRadiusGroup , returns # HZB_END if the tile is outside of the town .
*
* When returning # HZB_END ( outside of the town ) \ c zone_outer will be set to \ c UINT_MAX .
*
* @ param t Town on which town zone is to be found
* @ param tile TileIndex where town zone needs to be found
* @ param [ out ] distance ( may be NULL ) squared euclidean distance ( # DistanceSquare ) between the tile and center of the town
* @ param [ out ] zone_inner ( may be NULL ) squared radius of inner edge of the returned zone ( inclusive )
* @ param [ out ] zone_outer ( may be NULL ) squared radius of outer edge of the returned zone ( exclusive )
* @ return the bit position of the given zone , as defined in HouseZones
*
* @ see GetTownRadiusGroup
*/
HouseZonesBits TryGetTownRadiusGroup ( const Town * t , TileIndex tile )
HouseZonesBits TryGetTownRadiusGroup ( const Town * t , TileIndex tile , uint * distance , uint * zone_inner , uint * zone_outer )
{
uint dist = DistanceSquare ( t ile, t - > xy ) ;
if ( t - > fund_buildings_months & & dist < = 25 ) return HZB_TOWN_CENTRE ;
uint dist = DistanceSquare ( t - > xy , tile ) ;
uint funded_rad = ( t - > fund_buildings_months > 0 ) ? SQUARED_TOWN_RADIUS_FUNDED_CENTRE : 0 ;
const uint32 ( & zones ) [ HZB_END ] = t - > cache . squared_town_zone_radius ;
HouseZonesBits smallest = HZB_END ;
for ( HouseZonesBits i = HZB_BEGIN ; i < HZB_END ; i + + ) {
if ( dist < t - > cache . squared_town_zone_radius [ i ] ) smallest = i ;
/* Check if we are within the town at all. */
uint inner_rad = max ( zones [ HZB_TOWN_EDGE ] , funded_rad ) ;
uint outer_rad = 0 ;
HouseZonesBits ret = HZB_END ;
if ( dist < inner_rad ) {
/* Loop through zones and find the one that contains the tile. */
inner_rad = 0 ;
outer_rad = max ( zones [ HZB_TOWN_CENTRE ] , funded_rad ) ;
for ( ret = HZB_TOWN_CENTRE ; ret > HZB_TOWN_EDGE ; ret - - ) {
if ( dist < outer_rad ) break ;
inner_rad = max ( inner_rad , outer_rad ) ;
outer_rad = zones [ ret - 1 ] ;
}
}
return smallest ;
if ( distance ! = NULL ) * distance = dist ;
if ( zone_inner ! = NULL ) * zone_inner = inner_rad ;
if ( zone_outer ! = NULL ) * zone_outer = outer_rad ;
return ret ;
}
/**
* Returns the bit corresponding to the town zone of the specified tile .
* Returns # HZB_TOWN_EDGE if the tile is either in an edge zone or ouside of the town .
*
* Unlikely to # TryGetTownRadiusGroup , returns # HZB_TOWN_EDGE if the tile outside of the town .
*
* @ param t Town on which town zone is to be found
* @ param tile TileIndex where town zone needs to be found
@ -2228,7 +2318,7 @@ static void MakeTownHouse(TileIndex t, Town *town, byte counter, byte stage, Hou
* @ param tile tile to check
* @ param town town that is checking
* @ param noslope are slopes ( foundations ) allowed ?
* @ return success if house can be built here , error message otherwis e
* @ return cost of building here or error messag e
*/
static inline CommandCost CanBuildHouseHere ( TileIndex tile , TownID town , bool noslope )
{
@ -2249,206 +2339,330 @@ static inline CommandCost CanBuildHouseHere(TileIndex tile, TownID town, bool no
/* do not try to build over house owned by another town */
if ( IsTileType ( tile , MP_HOUSE ) & & GetTownIndex ( tile ) ! = town ) return CMD_ERROR ;
return CommandCost ( ) ;
return ret ;
}
/**
* Checks if a house can be built here . Important is slope , bridge above
* and ability to clear the land .
*
* @ param ta tile area to check
* Checks if a house can be built at this tile , must have the same max z as parameter .
* @ param tile tile to check
* @ param town town that is checking
* @ param maxz z level of the house , check if all tiles have this max z level
* @ param z max z of this tile so more parts of a house are at the same height ( with foundation )
* @ param noslope are slopes ( foundations ) allowed ?
* @ return success if house can be built here , error message otherwise
*
* @ see TownLayoutAllowsHouseHere
* @ return cost of building here or error message
* @ see CanBuildHouseHere ( )
*/
static inline CommandCost CanBuildHouseHere ( const TileArea & ta , TownID town , int max z, bool noslope )
static CommandCost CheckBuildHouseSameZ ( TileIndex tile , TownID town , int z, bool noslope )
{
TILE_AREA_LOOP ( tile , ta ) {
CommandCost ret = CanBuildHouseHere ( tile , town , noslope ) ;
/* if building on slopes is allowed, there will be flattening foundation (to tile max z) */
if ( ret . Succeeded ( ) & & GetTileMaxZ ( tile ) ! = maxz ) ret = CommandCost ( STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION ) ;
if ( ret . Failed ( ) ) return ret ;
CommandCost ret = CanBuildHouseHere ( tile , town , noslope ) ;
/* if building on slopes is allowed, there will be flattening foundation (to tile max z) */
if ( ret . Succeeded ( ) & & GetTileMaxZ ( tile ) ! = z ) ret = CommandCost ( STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION ) ;
return ret ;
}
/**
* Checks if a house of size 2 x2 can be built at this tile
* @ param tile tile , N corner
* @ param town town that is checking
* @ param z maximum tile z so all tile have the same max z
* @ param noslope are slopes ( foundations ) allowed ?
* @ return true iff house can be built
* @ see CheckBuildHouseSameZ ( )
*/
static bool CheckFree2x2Area ( TileIndex tile , TownID town , int z , bool noslope )
{
/* we need to check this tile too because we can be at different tile now */
if ( CheckBuildHouseSameZ ( tile , town , z , noslope ) . Failed ( ) ) return false ;
for ( DiagDirection d = DIAGDIR_SE ; d < DIAGDIR_END ; d + + ) {
tile + = TileOffsByDiagDir ( d ) ;
if ( CheckBuildHouseSameZ ( tile , town , z , noslope ) . Failed ( ) ) return false ;
}
return CommandCost ( ) ;
return true ;
}
/**
* Test whether houses of given type are avaliable in current game .
*
* The function will check whether the house is available at all e . g . is not overriden .
* Also availability for current climate and given house zone will be tested .
* Check whether houses of given type are buildable in current game .
*
* @ param house house type
* @ param above_snowline true to test availability above the snow line , false for below ( arctic climate only )
* @ param zone return error if houses are forbidden in this house zone
* @ return success if house is avaliable , error message otherwise
* @ param availability house must be allowed in any of the given climates ( # HZ_CLIMALL bits )
* and in any of the given town zones ( # HZ_ZONALL bits ) , skip testing
* climate if no climate bits are given , skip testing town zones if no
* town zone bits are given
* @ return success if house is available , error message otherwise
*/
static inline CommandCost IsHouseTypeAllowed ( HouseID house , bool above_snowline , HouseZonesBits zone )
{
CommandCost IsHouseTypeAllowed ( HouseID house , HouseZones availability , bool allow_historical )
{
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
/* Disallow disabled and replaced houses. */
if ( ! hs - > enabled | | hs - > grf_prop . override ! = INVALID_HOUSE_ID ) return CMD_ERROR ;
/* Check if we can build this house in current climate. */
if ( _settings_game . game_creation . landscape ! = LT_ARCTIC ) {
if ( ! ( hs - > building_availability & ( HZ_TEMP < < _settings_game . game_creation . landscape ) ) ) return CMD_ERROR ;
} else if ( above_snowline ) {
if ( ! ( hs - > building_availability & HZ_SUBARTC_ABOVE ) ) return_cmd_error ( STR_ERROR_BUILDING_NOT_ALLOWED_ABOVE_SNOW_LINE ) ;
} else {
if ( ! ( hs - > building_availability & HZ_SUBARTC_BELOW ) ) return_cmd_error ( STR_ERROR_BUILDING_NOT_ALLOWED_BELOW_SNOW_LINE ) ;
}
/* Disallow additional parts of a multi-tile building. */
if ( ! ( hs - > building_flags & BUILDING_HAS_1_TILE ) ) return CMD_ERROR ;
/* Check if the house zone is allowed for this type of hous es. */
if ( ! HasBit ( hs - > building_availability & HZ_ZONALL , zone ) ) {
/* Check if the house is allowed in all of the given house zones. */
if ( ( availability & HZ_ZONALL ) & & ! ( availability & HZ_ZONALL & hs - > building_availability ) ) {
return_cmd_error ( STR_ERROR_BUILDING_NOT_ALLOWED_IN_THIS_TOWN_ZONE ) ;
}
/* Check if we can build this house in any of the given climates. */
if ( ( availability & HZ_CLIMALL ) & & ! ( availability & HZ_CLIMALL & hs - > building_availability ) ) {
if ( ( availability & HZ_SUBARTC_ABOVE ) & & ( hs - > building_availability & HZ_SUBARTC_BELOW ) ) {
return_cmd_error ( STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE ) ;
}
if ( ( availability & HZ_SUBARTC_BELOW ) & & ( hs - > building_availability & HZ_SUBARTC_ABOVE ) ) {
return_cmd_error ( STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE ) ;
}
return CMD_ERROR ;
}
/* Check for historical buildings. */
if ( ! allow_historical & & hs - > extra_flags & BUILDING_IS_HISTORICAL ) return CMD_ERROR ;
/* Check if the house can be placed manually. */
if ( _current_company ! = OWNER_TOWN & & ( hs - > extra_flags & DISALLOW_BUILDING_MANUALLY ) ) return CMD_ERROR ;
if ( _current_company < MAX_COMPANIES & & ( hs - > extra_flags & DISALLOW_BUILDING_BY_COMPANIES ) ) return CMD_ERROR ;
return CommandCost ( ) ;
}
/**
* Check whether a town can hold more house types .
* @ param t the town we wan ' t to check
* @ param house type of the house we wan ' t to add
* @ return success if houses of this type are allowed , error message otherwise
* Check if house is currently buildable .
*
* @ param house house type
* @ param t the town the house is about to be built
* @ param ignore_year allow obsolete and feature houses
* @ return success if house is buildable , error message otherwise
*/
static inline CommandCost IsAnotherHouseTypeAllowedInTown ( Town * t , HouseID house )
static CommandCost CheckCanBuildHouse ( HouseID house , const Town * t , bool ignore_year )
{
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
if ( ! ignore_year & & ( _cur_year > hs - > max_year | | _cur_year < hs - > min_year ) ) return CMD_ERROR ;
/* Don't let these counters overflow. Global counters are 32bit, there will never be that many houses. */
if ( hs - > class_id ! = HOUSE_NO_CLASS ) {
/* id_count is always <= class_count, so it doesn't need to be checked */
if ( t - > cache . building_counts . class_count [ hs - > class_id ] = = UINT16_MAX ) return_cmd_error ( STR_ERROR_TOO_MANY_HOUSE_SETS ) ;
if ( t - > cache . building_counts . class_count [ hs - > class_id ] = = UINT16_MAX ) return CMD_ERROR ;
} else {
/* If the house has no class, check id_count instead */
if ( t - > cache . building_counts . id_count [ house ] = = UINT16_MAX ) return_cmd_error ( STR_ERROR_TOO_MANY_HOUSE_TYPES ) ;
if ( t - > cache . building_counts . id_count [ house ] = = UINT16_MAX ) return CMD_ERROR ;
}
/* Special houses that there can be only one of. */
if ( hs - > building_flags & BUILDING_IS_CHURCH ) {
if ( HasBit ( t - > flags , TOWN_HAS_CHURCH ) ) return_cmd_error ( STR_ERROR_ONLY_ONE_CHURCH_PER_TOWN ) ;
} else if ( hs - > building_flags & BUILDING_IS_STADIUM ) {
if ( HasBit ( t - > flags , TOWN_HAS_STADIUM ) ) return_cmd_error ( STR_ERROR_ONLY_ONE_STADIUM_PER_TOWN ) ;
}
return CommandCost ( ) ;
}
/**
* Check if a house can be built at a given area .
* @ param house house type
* @ param tile northern tile of the area to check
* @ return cost of building here or error message
* @ see CanBuildHouseHere ( )
*/
CommandCost CheckFlatLandHouse ( HouseID house , TileIndex tile )
{
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
uint w = hs - > building_flags & BUILDING_2_TILES_X ? 2 : 1 ;
uint h = hs - > building_flags & BUILDING_2_TILES_Y ? 2 : 1 ;
bool noslope = ( hs - > building_flags & TILE_NOT_SLOPED ) ! = 0 ;
int maxz = GetTileMaxZ ( tile ) ;
CommandCost cost ( EXPENSES_CONSTRUCTION ) ;
TILE_AREA_LOOP ( ti , TileArea ( tile , w , h ) ) {
CommandCost ret = ( ti = = tile ) ?
CanBuildHouseHere ( ti , INVALID_TOWN , noslope ) :
CheckBuildHouseSameZ ( ti , INVALID_TOWN , maxz , noslope ) ;
if ( ret . Failed ( ) ) return ret ;
cost . AddCost ( ret ) ;
}
return cost ;
}
/**
* Checks if current town layout allows building here
* @ param t town
* @ param ta tile area to check
* @ param t ile tile to check
* @ return true iff town layout allows building here
* @ note see layouts
*/
static inline bool TownLayoutAllowsHouseHere ( Town * t , const TileArea & ta )
static inline bool TownLayoutAllowsHouseHere ( Town * t , TileIndex tile )
{
/* Allow towns everywhere when we don't build roads */
if ( ! _settings_game . economy . allow_town_roads & & ! _generating_world ) return true ;
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC ( t - > xy , ta . tile ) ;
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC ( t - > xy , t ile) ;
const uint overflow = 3 * 4 * UINT16_MAX ; // perform "floor division"
switch ( t - > layout ) {
case TL_2X2_GRID : return ( uint ) ( grid_pos . x + overflow ) % 3 > = ta . w & & ( uint ) ( grid_pos . y + overflow ) % 3 > = ta . h ;
case TL_3X3_GRID : return ( uint ) ( grid_pos . x + overflow ) % 4 > = ta . w & & ( uint ) ( grid_pos . y + overflow ) % 4 > = ta . h ;
default : return true ;
case TL_2X2_GRID :
if ( ( grid_pos . x % 3 ) = = 0 | | ( grid_pos . y % 3 ) = = 0 ) return false ;
break ;
case TL_3X3_GRID :
if ( ( grid_pos . x % 4 ) = = 0 | | ( grid_pos . y % 4 ) = = 0 ) return false ;
break ;
default :
break ;
}
return true ;
}
/**
* Find a suitable place ( free of any obstacles ) for a new town house . Search around a given location
* taking into account the layout of the town .
*
* @ param tile tile that must be included by the building
* @ param t the town we are building in
* @ param house house type
* @ return where the building can be placed , INVALID_TILE if no lacation was found
*
* @ pre CanBuildHouseHere ( tile , t - > index , false )
*
* @ see CanBuildHouseHere
* Checks if current town layout allows 2 x2 building here
* @ param t town
* @ param tile tile to check
* @ return true iff town layout allows 2 x2 building here
* @ note see layouts
*/
static TileIndex FindPlaceForTownHouseAroundTile ( TileIndex tile , Town * t , HouseID hous e)
static inline bool TownLayoutAllows2x2HouseHere ( Town * t , TileIndex tile )
{
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
bool noslope = ( hs - > building_flags & TILE_NOT_SLOPED ) ! = 0 ;
/* Allow towns everywhere when we don't build roads */
if ( ! _settings_game . economy . allow_town_roads & & ! _generating_world ) return true ;
/* Compute relative position of tile. (Positive offsets are towards north) */
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC ( t - > xy , tile ) ;
switch ( t - > layout ) {
case TL_2X2_GRID :
grid_pos . x % = 3 ;
grid_pos . y % = 3 ;
if ( ( grid_pos . x ! = 2 & & grid_pos . x ! = - 1 ) | |
( grid_pos . y ! = 2 & & grid_pos . y ! = - 1 ) ) return false ;
break ;
case TL_3X3_GRID :
if ( ( grid_pos . x & 3 ) < 2 | | ( grid_pos . y & 3 ) < 2 ) return false ;
break ;
TileArea ta ( tile , 1 , 1 ) ;
DiagDirection dir ;
uint count ;
if ( hs - > building_flags & TILE_SIZE_2x2 ) {
ta . w = ta . h = 2 ;
dir = DIAGDIR_NW ; // 'd' goes through DIAGDIR_NW, DIAGDIR_NE, DIAGDIR_SE
count = 4 ;
} else if ( hs - > building_flags & TILE_SIZE_2x1 ) {
ta . w = 2 ;
dir = DIAGDIR_NE ;
count = 2 ;
} else if ( hs - > building_flags & TILE_SIZE_1x2 ) {
ta . h = 2 ;
dir = DIAGDIR_NW ;
count = 2 ;
} else { // TILE_SIZE_1x1
/* CanBuildHouseHere(tile, t->index, false) already checked */
if ( noslope & & ! IsTileFlat ( tile ) ) return INVALID_TILE ;
return tile ;
default :
break ;
}
int maxz = GetTileMaxZ ( tile ) ;
/* Drift around the tile and find a place for the house. For 1x2 and 2x1 houses just two
* positions will be checked ( at the exact tile and the other ) . In case of 2 x2 houses
* 4 positions have to be checked ( clockwise ) . */
while ( count - - > 0 ) {
if ( ! TownLayoutAllowsHouseHere ( t , ta ) ) continue ;
if ( CanBuildHouseHere ( ta , t - > index , maxz , noslope ) . Succeeded ( ) ) return ta . tile ;
ta . tile + = TileOffsByDiagDir ( dir ) ;
dir = ChangeDiagDir ( dir , DIAGDIRDIFF_90RIGHT ) ;
return true ;
}
/**
* Checks if 1 x2 or 2 x1 building is allowed here , also takes into account current town layout
* Also , tests both building positions that occupy this tile
* @ param tile tile where the building should be built
* @ param t town
* @ param maxz all tiles should have the same height
* @ param noslope are slopes forbidden ?
* @ param second diagdir from first tile to second tile
*/
static bool CheckTownBuild2House ( TileIndex * tile , Town * t , int maxz , bool noslope , DiagDirection second )
{
/* 'tile' is already checked in BuildTownHouse() - CanBuildHouseHere() and slope test */
TileIndex tile2 = * tile + TileOffsByDiagDir ( second ) ;
if ( TownLayoutAllowsHouseHere ( t , tile2 ) & & CheckBuildHouseSameZ ( tile2 , t - > index , maxz , noslope ) . Succeeded ( ) ) return true ;
tile2 = * tile + TileOffsByDiagDir ( ReverseDiagDir ( second ) ) ;
if ( TownLayoutAllowsHouseHere ( t , tile2 ) & & CheckBuildHouseSameZ ( tile2 , t - > index , maxz , noslope ) . Succeeded ( ) ) {
* tile = tile2 ;
return true ;
}
return INVALID_TILE ;
return false ;
}
/**
* Check if a given house can be built in a given town .
* @ param house house type
* @ param t the town
* @ return success if house can be built , error message otherwise
* Checks if 2 x2 building is allowed here , also takes into account current town layout
* Also , tests all four building positions that occupy this tile
* @ param tile tile where the building should be built
* @ param t town
* @ param maxz all tiles should have the same height
* @ param noslope are slopes forbidden ?
*/
static CommandCost CheckCanBuildHouse ( HouseID house , const Town * t )
static bool CheckTownBuild2x2House ( TileIndex * tile , Town * t , int maxz , bool noslope )
{
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
TileIndex tile2 = * tile ;
if ( _loaded_newgrf_features . has_newhouses & & ! _generating_world & &
_game_mode ! = GM_EDITOR & & ( hs - > extra_flags & BUILDING_IS_HISTORICAL ) ! = 0 ) {
return CMD_ERROR ;
for ( DiagDirection d = DIAGDIR_SE ; ; d + + ) { // 'd' goes through DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_END
if ( TownLayoutAllows2x2HouseHere ( t , tile2 ) & & CheckFree2x2Area ( tile2 , t - > index , maxz , noslope ) ) {
* tile = tile2 ;
return true ;
}
if ( d = = DIAGDIR_END ) break ;
tile2 + = TileOffsByDiagDir ( ReverseDiagDir ( d ) ) ; // go clockwise
}
if ( _cur_year > hs - > max_year ) return_cmd_error ( STR_ERROR_BUILDING_IS_TOO_OLD ) ;
if ( _cur_year < hs - > min_year ) return_cmd_error ( STR_ERROR_BUILDING_IS_TOO_MODERN ) ;
return false ;
}
/* Special houses that there can be only one of. */
if ( hs - > building_flags & BUILDING_IS_CHURCH ) {
if ( HasBit ( t - > flags , TOWN_HAS_CHURCH ) ) return_cmd_error ( STR_ERROR_ONLY_ONE_BUILDING_ALLOWED_PER_TOWN ) ;
} else if ( hs - > building_flags & BUILDING_IS_STADIUM ) {
if ( HasBit ( t - > flags , TOWN_HAS_STADIUM ) ) return_cmd_error ( STR_ERROR_ONLY_ONE_BUILDING_ALLOWED_PER_TOWN ) ;
/**
* Check if a given tile is not too far from town for placing a house .
*
* @ param t the town
* @ param tile the tile
* @ param allow_outside whether to allow some area outside but near to the town .
* @ return success or an error
*/
CommandCost CheckHouseDistanceFromTown ( const Town * t , TileIndex tile , bool allow_outside )
{
uint square_dist = DistanceSquare ( t - > xy , tile ) ;
uint square_rad = t - > cache . squared_town_zone_radius [ HZB_BEGIN ] ;
if ( t - > fund_buildings_months > 0 ) square_rad = max ( square_rad , SQUARED_TOWN_RADIUS_FUNDED_CENTRE ) ;
if ( square_dist < square_rad ) return CommandCost ( ) ;
if ( allow_outside ) {
/* How far from edge of a town a house can be placed (in tiles). */
const uint overdist = 8 ;
if ( SqrtCmp ( square_dist , square_rad , overdist * overdist ) ) return CommandCost ( ) ;
}
return CommandCost ( ) ;
return_cmd_error ( STR_ERROR_TOO_FAR_FROM_TOWN ) ;
}
/**
* Set house variant after placing a house .
*
* @ param tile tile where the house was placed
* @ param variant house variant
*/
static void SetupHouseVariant ( TileIndex tile , byte variant )
{
if ( ! _loaded_newgrf_features . has_newhouses ) return ;
HouseID house = GetHouseType ( tile ) ;
if ( house < NEW_HOUSE_OFFSET ) return ;
BuildingFlags flags = HouseSpec : : Get ( house ) - > building_flags ;
AnimateNewHouseSetupVariant ( tile , variant ) ;
if ( flags & BUILDING_2_TILES_Y ) AnimateNewHouseSetupVariant ( tile + TileDiffXY ( 0 , 1 ) , variant ) ;
if ( flags & BUILDING_2_TILES_X ) AnimateNewHouseSetupVariant ( tile + TileDiffXY ( 1 , 0 ) , variant ) ;
if ( flags & BUILDING_HAS_4_TILES ) AnimateNewHouseSetupVariant ( tile + TileDiffXY ( 1 , 1 ) , variant ) ;
}
/**
* Really build a house .
* @ param t town to build house in
* @ param tile house location
* @ param house house type
* @ param variant house variant
* @ param random_bits random bits for the house
*/
static void DoBuildHouse ( Town * t , TileIndex tile , HouseID house , byte random_bits )
static void DoBuildHouse ( Town * t , TileIndex tile , HouseID house , byte variant, byte random_bits)
{
t - > cache . num_houses + + ;
@ -2478,56 +2692,80 @@ static void DoBuildHouse(Town *t, TileIndex tile, HouseID house, byte random_bit
}
MakeTownHouse ( tile , t , construction_counter , construction_stage , house , random_bits ) ;
SetupHouseVariant ( tile , variant ) ;
UpdateTownRadius ( t ) ;
UpdateTownCargoes ( t , tile ) ;
}
/**
* Convert current climate to corresponding # HouseZones .
*
* @ param altitude Test against given tile height ( above / below snowline ) .
* - 1 to return all bits possible in current climate e . g .
* both HZ_SUBARTC_ABOVE and HZ_SUBARTC_BELOW in arctic .
* @ return Bitmask related to current climate ( subset of # HZ_CLIMALL ) .
*/
HouseZones CurrentClimateHouseZones ( int altitude )
{
if ( _settings_game . game_creation . landscape = = LT_ARCTIC ) {
if ( altitude < 0 ) return HZ_SUBARTC_ABOVE | HZ_SUBARTC_BELOW ;
if ( altitude > HighestSnowLine ( ) ) return HZ_SUBARTC_ABOVE ;
}
return ( HouseZones ) ( HZ_TEMP < < _settings_game . game_creation . landscape ) ;
}
static Money GetHouseConstructionCost ( HouseID house )
{
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
uint flags = hs - > building_flags ;
Money cost = hs - > GetConstructionCost ( ) ;
if ( flags & BUILDING_2_TILES_Y ) cost + = ( + + hs ) - > GetConstructionCost ( ) ;
if ( flags & BUILDING_2_TILES_X ) cost + = ( + + hs ) - > GetConstructionCost ( ) ;
if ( flags & BUILDING_HAS_4_TILES ) cost + = ( + + hs ) - > GetConstructionCost ( ) ;
return cost ;
}
/**
* Place a custom house
* @ param tile tile where the house will be located
* @ param flags flags for the command
* @ param p1 \ n
* bits 0. .15 - the HouseID of the house \ n
* bits 16. .31 - the TownID of the town \ n
* @ param p2 \ n
* bits 0. .7 - random bits \ n
* @ param p1
* - p1 = ( bit 0 - 15 ) - the HouseID of the house
* - p1 = ( bit 16 - 31 ) - the TownID of the town
* @ param p2
* - p2 = ( bit 0 - 7 ) - random bits
* - p2 = ( bit 8 - 15 ) - house variant ( 1. . num_variants ) or 0 for no variant
* @ param text unused
* @ return the cost of this operation or an error
*/
CommandCost CmdBuildHouse ( TileIndex tile , DoCommandFlag flags , uint32 p1 , uint32 p2 , const char * text )
{
if ( _game_mode ! = GM_EDITOR & & // in scenario editor anyone can build a house
_current_company ! = OWNER_TOWN & & // towns naturally can build houses
_current_company ! = OWNER_DEITY ) { // GameScript can place a house too
return CMD_ERROR ;
}
HouseID house = GB ( p1 , 0 , 16 ) ;
Town * t = Town : : Get ( GB ( p1 , 16 , 16 ) ) ;
Town * t = Town : : GetIfValid ( GB ( p1 , 16 , 16 ) ) ;
if ( t = = NULL ) return CMD_ERROR ;
byte random_bits = GB ( p2 , 0 , 8 ) ;
byte variant = GB ( p2 , 8 , 8 ) ;
int max_z = GetTileMaxZ ( tile ) ;
bool above_snowline = ( _settings_game . game_creation . landscape = = LT_ARCTIC ) & & ( max_z > HighestSnowLine ( ) ) ;
bool deity = ( _current_company = = OWNER_DEITY ) | | ( _game_mode = = GM_EDITOR & & _current_company = = OWNER_NONE ) ;
if ( ! deity & & ! _settings_game . economy . allow_placing_houses ) return CMD_ERROR ;
HouseZones zones = CurrentClimateHouseZones ( deity ? - 1 : GetTileMaxZ ( tile ) ) ;
if ( ! deity ) zones | = ( HouseZones ) ( HZ_ZON1 < < GetTownRadiusGroup ( t , tile ) ) ;
CommandCost ret = IsHouseTypeAllowed ( house , above_snowline , TryGetTownRadiusGroup ( t , tile ) ) ;
if ( ret . Succeeded ( ) ) ret = IsAnotherHouseTypeAllowedInTown ( t , house ) ;
if ( ret . Succeeded ( ) ) ret = CheckCanBuildHouse ( house , t ) ;
if ( ret . Succeeded ( ) ) {
/* While placing a house manually, try only at exact position and ignore the layout */
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
uint w = hs - > building_flags & BUILDING_2_TILES_X ? 2 : 1 ;
uint h = hs - > building_flags & BUILDING_2_TILES_Y ? 2 : 1 ;
bool noslope = ( hs - > building_flags & TILE_NOT_SLOPED ) ! = 0 ;
ret = CanBuildHouseHere ( TileArea ( tile , w , h ) , t - > index , max_z , noslope ) ;
}
CommandCost cost ( EXPENSES_CONSTRUCTION ) ;
CommandCost ret = CheckHouseDistanceFromTown ( t , tile , deity ) ;
if ( ret . Succeeded ( ) ) ret = IsHouseTypeAllowed ( house , zones , deity ) ;
if ( ret . Succeeded ( ) ) ret = CheckCanBuildHouse ( house , t , deity ) ;
if ( ret . Succeeded ( ) ) ret = CheckFlatLandHouse ( house , tile ) ;
if ( ret . Succeeded ( ) ) cost . AddCost ( ret ) ;
if ( ret . Succeeded ( ) ) ret = HouseAllowsConstruction ( house , variant , tile , t , random_bits ) ;
if ( ret . Failed ( ) ) return ret ;
/* Check if GRF allows this house */
if ( ! HouseAllowsConstruction ( house , tile , t , random_bits ) ) return_cmd_error ( STR_ERROR_BUILDING_NOT_ALLOWED ) ;
/* Place the house. */
if ( flags & DC_EXEC ) DoBuildHouse ( t , tile , house , variant , random_bits ) ;
if ( flags & DC_EXEC ) DoBuildHouse ( t , tile , house , random_bits ) ;
return CommandCost ( ) ;
cost . AddCost ( GetHouseConstructionCost ( house ) ) ;
return cost ;
}
/**
@ -2539,17 +2777,18 @@ CommandCost CmdBuildHouse(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
static bool BuildTownHouse ( Town * t , TileIndex tile )
{
/* forbidden building here by town layout */
if ( ! TownLayoutAllowsHouseHere ( t , TileArea( tile, 1 , 1 ) ) ) return false ;
if ( ! TownLayoutAllowsHouseHere ( t , tile) ) return false ;
/* no house allowed at all, bail out */
if ( CanBuildHouseHere ( tile , t - > index , false ) . Failed ( ) ) return false ;
bool above_snowline = _settings_game . game_creation . landscape = = LT_ARCTIC & & GetTileMaxZ ( tile ) > HighestSnowLine ( ) ;
HouseZonesBits zone = GetTownRadiusGroup ( t , tile ) ;
Slope slope = GetTileSlope ( tile ) ;
int maxz = GetTileMaxZ ( tile ) ;
/* Get the town zone type of the current tile, as well as the climate.
* This will allow to easily compare with the specs of the new house to build */
HouseZones bitmask = ( HouseZones ) ( HZ_ZON1 < < GetTownRadiusGroup ( t , tile ) ) | CurrentClimateHouseZones ( maxz ) ;
/* bits 0-4 are used
* bits 11 - 15 are used
* bits 5 - 10 are not used . */
HouseID houses [ NUM_HOUSES ] ;
uint num = 0 ;
uint probs [ NUM_HOUSES ] ;
@ -2557,8 +2796,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
/* Generate a list of all possible houses that can be built. */
for ( uint i = 0 ; i < NUM_HOUSES ; i + + ) {
if ( IsHouseTypeAllowed ( ( HouseID ) i , above_snowline , zone ) . Failed ( ) ) continue ;
if ( IsAnotherHouseTypeAllowedInTown ( t , ( HouseID ) i ) . Failed ( ) ) continue ;
if ( IsHouseTypeAllowed ( i , bitmask , _generating_world | | _game_mode = = GM_EDITOR ) . Failed ( ) ) continue ;
/* Without NewHouses, all houses have probability '1' */
uint cur_prob = ( _loaded_newgrf_features . has_newhouses ? HouseSpec : : Get ( i ) - > probability : 1 ) ;
@ -2592,18 +2830,30 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
houses [ i ] = houses [ num ] ;
probs [ i ] = probs [ num ] ;
CommandCost ret = CheckCanBuildHouse ( house , t ) ;
if ( ret . Failed ( ) ) continue ;
if ( CheckCanBuildHouse ( house , t , false ) . Failed ( ) ) continue ;
const HouseSpec * hs = HouseSpec : : Get ( house ) ;
tile = FindPlaceForTownHouseAroundTile ( tile , t , house ) ;
if ( tile = = INVALID_TILE ) continue ;
/* Make sure there is no slope? */
bool noslope = ( hs - > building_flags & TILE_NOT_SLOPED ) ! = 0 ;
if ( noslope & & slope ! = SLOPE_FLAT ) continue ;
if ( hs - > building_flags & TILE_SIZE_2x2 ) {
if ( ! CheckTownBuild2x2House ( & tile , t , maxz , noslope ) ) continue ;
} else if ( hs - > building_flags & TILE_SIZE_2x1 ) {
if ( ! CheckTownBuild2House ( & tile , t , maxz , noslope , DIAGDIR_SW ) ) continue ;
} else if ( hs - > building_flags & TILE_SIZE_1x2 ) {
if ( ! CheckTownBuild2House ( & tile , t , maxz , noslope , DIAGDIR_SE ) ) continue ;
} else {
/* 1x1 house checks are already done */
}
byte random_bits = Random ( ) ;
/* Check if GRF allows this house */
if ( ! HouseAllowsConstruction ( house , tile , t , random_bits ) ) continue ;
if ( HouseAllowsConstruction ( house , HOUSE_NO_VARIANT, tile, t , random_bits ) . Failed ( ) ) continue ;
DoBuildHouse ( t , tile , house , random_bits ) ;
DoBuildHouse ( t , tile , house , HOUSE_NO_VARIANT, random_bits) ;
return true ;
}
@ -2627,30 +2877,27 @@ static void DoClearTownHouseHelper(TileIndex tile, Town *t, HouseID house)
}
/**
* Determines if a given HouseID is part of a multi tile house .
* Determines if a given HouseID is part of a multi - tile house .
* The given ID is set to the ID of the north tile and the TileDiff to the north tile is returned .
*
* @ param house Is changed to the HouseID of the north tile of the same house
* @ return Tile Diff from the tile of the given HouseID to the north tile
* @ return Tile Index DiffC from the tile of the given HouseID to the north tile
*/
TileIndexDiff GetHouseNorthPart ( HouseID & house )
TileIndexDiff C GetHouseNorthPart DiffC ( HouseID & house )
{
TileIndexDiffC ret = { 0 , 0 } ;
if ( house > = 3 ) { // house id 0,1,2 MUST be single tile houses, or this code breaks.
if ( HouseSpec : : Get ( house - 1 ) - > building_flags & TILE_SIZE_2x1 ) {
house - - ;
return TileDiffXY ( - 1 , 0 ) ;
house - - , ret . x = - 1 , ret . y = 0 ;
} else if ( HouseSpec : : Get ( house - 1 ) - > building_flags & BUILDING_2_TILES_Y ) {
house - - ;
return TileDiffXY ( 0 , - 1 ) ;
house - - , ret . x = 0 , ret . y = - 1 ;
} else if ( HouseSpec : : Get ( house - 2 ) - > building_flags & BUILDING_HAS_4_TILES ) {
house - = 2 ;
return TileDiffXY ( - 1 , 0 ) ;
house - = 2 , ret . x = - 1 , ret . y = 0 ;
} else if ( HouseSpec : : Get ( house - 3 ) - > building_flags & BUILDING_HAS_4_TILES ) {
house - = 3 ;
return TileDiffXY ( - 1 , - 1 ) ;
house - = 3 , ret . x = - 1 , ret . y = - 1 ;
}
}
return 0 ;
return ret ;
}
void ClearTownHouse ( Town * t , TileIndex tile )
@ -2718,6 +2965,7 @@ CommandCost CmdRenameTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
t - > UpdateVirtCoord ( ) ;
InvalidateWindowData ( WC_TOWN_DIRECTORY , 0 , 1 ) ;
SetWindowDirty ( WC_SELECT_TOWN , 0 ) ; // only repaint this window even thought it may be too narrow for the new name
UpdateAllStationVirtCoords ( ) ;
}
return CommandCost ( ) ;