From 20b8cb30590de8c4861360130c5d8dc620d6020f Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 17 Mar 2024 12:31:50 +0000 Subject: [PATCH] Add setting to use object land ground for purchased land Default on --- src/lang/extra/english.txt | 3 ++ src/newgrf_object.cpp | 49 +++++++++++++++------------ src/newgrf_object.h | 1 + src/object_cmd.cpp | 9 +++-- src/settings_gui.cpp | 1 + src/settings_type.h | 1 + src/sl/extended_ver_sl.cpp | 2 +- src/table/object_land.h | 12 +++---- src/table/settings/world_settings.ini | 9 +++++ 9 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index 380f6aabb5..a58e490e6a 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -733,6 +733,9 @@ STR_CONFIG_SETTING_IGNORE_OBJECT_INTRO_DATES_HELPTEXT :Set whether pla STR_CONFIG_SETTING_ALLOW_CONVERT_TOWN_ROAD_NO_HOUSES :Allow converting town roads to non-house types: {STRING2} STR_CONFIG_SETTING_ALLOW_CONVERT_TOWN_ROAD_NO_HOUSES_HELPTEXT :Whether to allow players to convert town-owned roads to a road type which does not allow houses.{}This is off by default because doing so can prevent towns from building houses at all, resulting in them shrinking. +STR_CONFIG_SETTING_PURCHASED_LAND_CLEAR_GROUND :Use clear ground tile for purchased land: {STRING2} +STR_CONFIG_SETTING_PURCHASED_LAND_CLEAR_GROUND_HELPTEXT :If enabled, purchased land is shown using the same ground type as clear ground tiles, i.e. bare ground to grass, coast, snow, desert, etc. + STR_CONFIG_SETTING_SPAWN_PRIMARY_INDUSTRY_ONLY :Only generate primary industries: {STRING2} STR_CONFIG_SETTING_SPAWN_PRIMARY_INDUSTRY_ONLY_HELPTEXT :If enabled, only primary industries are generated during game play and map generation. diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index 7613a81305..0fd5471f60 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -459,6 +459,32 @@ uint16_t GetObjectCallback(CallbackID callback, uint32_t param1, uint32_t param2 return object.ResolveCallback(); } +void DrawObjectLandscapeGround(TileInfo *ti) +{ + if (IsTileOnWater(ti->tile) && GetObjectGroundType(ti->tile) != OBJECT_GROUND_SHORE) { + DrawWaterClassGround(ti); + } else { + switch (GetObjectGroundType(ti->tile)) { + case OBJECT_GROUND_GRASS: + DrawClearLandTile(ti, GetObjectGroundDensity(ti->tile)); + break; + + case OBJECT_GROUND_SNOW_DESERT: + DrawGroundSprite(GetSpriteIDForSnowDesert(ti->tileh, GetObjectGroundDensity(ti->tile)), PAL_NONE); + break; + + case OBJECT_GROUND_SHORE: + DrawShoreTile(ti->tileh); + break; + + default: + /* This should never be reached, just draw a black sprite to make the problem clear without being unnecessarily punitive */ + DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK); + break; + } + } +} + /** * Draw an group of sprites on the map. * @param ti Information about the tile to draw on. @@ -474,28 +500,7 @@ static void DrawTileLayout(TileInfo *ti, const TileLayoutSpriteGroup *group, con PaletteID pal = dts->ground.pal; if (spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) { - if (IsTileOnWater(ti->tile) && GetObjectGroundType(ti->tile) != OBJECT_GROUND_SHORE) { - DrawWaterClassGround(ti); - } else { - switch (GetObjectGroundType(ti->tile)) { - case OBJECT_GROUND_GRASS: - DrawClearLandTile(ti, GetObjectGroundDensity(ti->tile)); - break; - - case OBJECT_GROUND_SNOW_DESERT: - DrawGroundSprite(GetSpriteIDForSnowDesert(ti->tileh, GetObjectGroundDensity(ti->tile)), PAL_NONE); - break; - - case OBJECT_GROUND_SHORE: - DrawShoreTile(ti->tileh); - break; - - default: - /* This should never be reached, just draw a black sprite to make the problem clear without being unnecessarily punitive */ - DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK); - break; - } - } + DrawObjectLandscapeGround(ti); } else if (GB(image, 0, SPRITE_WIDTH) != 0) { /* If the ground sprite is the default flat water sprite, draw also canal/river borders * Do not do this if the tile's WaterClass is 'land'. */ diff --git a/src/newgrf_object.h b/src/newgrf_object.h index 669bdd0596..b7c4276b32 100644 --- a/src/newgrf_object.h +++ b/src/newgrf_object.h @@ -207,6 +207,7 @@ static const size_t OBJECT_SPRITE_GROUP_PURCHASE = 1; uint16_t GetObjectCallback(CallbackID callback, uint32_t param1, uint32_t param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8_t view = 0); +void DrawObjectLandscapeGround(TileInfo *ti); void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec, int building_z_offset); void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8_t view); void AnimateNewObjectTile(TileIndex tile); diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index ccb3f1b802..0af347b374 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -629,7 +629,9 @@ static void DrawTile_Object(TileInfo *ti, DrawTileProcParams params) dts = &_objects[type]; } - if (spec->flags & OBJECT_FLAG_HAS_NO_FOUNDATION) { + if ((spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) && _settings_game.construction.purchased_land_clear_ground) { + DrawObjectLandscapeGround(ti); + } else if (spec->flags & OBJECT_FLAG_HAS_NO_FOUNDATION) { /* If an object has no foundation, but tries to draw a (flat) ground * type... we have to be nice and convert that for them. */ switch (dts->ground.sprite) { @@ -1211,7 +1213,10 @@ static CommandCost TerraformTile_Object(TileIndex tile, DoCommandFlag flags, int if (type == OBJECT_OWNED_LAND) { /* Owned land remains unsold */ CommandCost ret = CheckTileOwnership(tile); - if (ret.Succeeded()) return CommandCost(); + if (ret.Succeeded()) { + if (flags & DC_EXEC) SetObjectGroundTypeDensity(tile, OBJECT_GROUND_GRASS, 0); + return CommandCost(); + } } else if (AutoslopeEnabled() && type != OBJECT_TRANSMITTER && type != OBJECT_LIGHTHOUSE) { const ObjectSpec *spec = ObjectSpec::Get(type); diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 4bc3c3914a..b67ae282cb 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -2693,6 +2693,7 @@ static SettingsContainer &GetSettingsTree() environment->Add(new SettingEntry("construction.map_edge_mode")); environment->Add(new SettingEntry("station.cargo_class_rating_wait_time")); environment->Add(new SettingEntry("station.station_size_rating_cargo_amount")); + environment->Add(new SettingEntry("construction.purchased_land_clear_ground")); } SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI)); diff --git a/src/settings_type.h b/src/settings_type.h index f0d971cde9..d9f6918038 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -539,6 +539,7 @@ struct ConstructionSettings { CalTime::Year no_expire_objects_after; ///< do not expire objects after this year bool ignore_object_intro_dates; ///< allow players to build objects before their introduction dates (does not include during map generation) bool convert_town_road_no_houses; ///< allow converting town roads to a type which does not allow houses + bool purchased_land_clear_ground; ///< purchased land uses clear ground uint32_t terraform_per_64k_frames; ///< how many tile heights may, over a long period, be terraformed per 65536 frames? uint16_t terraform_frame_burst; ///< how many tile heights may, over a short period, be terraformed? diff --git a/src/sl/extended_ver_sl.cpp b/src/sl/extended_ver_sl.cpp index 76800e85ca..1175067f6f 100644 --- a/src/sl/extended_ver_sl.cpp +++ b/src/sl/extended_ver_sl.cpp @@ -168,7 +168,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_DEPOT_ORDER_EXTRA_FLAGS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "depot_order_extra_flags", nullptr, nullptr, nullptr }, { XSLFI_EXTRA_SIGNAL_TYPES, XSCF_NULL, 1, 1, "extra_signal_types", nullptr, nullptr, nullptr }, { XSLFI_BANKRUPTCY_EXTRA, XSCF_NULL, 2, 2, "bankruptcy_extra", nullptr, nullptr, nullptr }, - { XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 3, 3, "object_ground_types", nullptr, nullptr, nullptr }, + { XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 4, 4, "object_ground_types", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_AIRCRAFT, XSCF_NULL, 1, 1, "linkgraph_aircraft", nullptr, nullptr, nullptr }, { XSLFI_COMPANY_PW, XSCF_IGNORABLE_ALL, 2, 2, "company_password", nullptr, nullptr, "PLYP" }, { XSLFI_ST_INDUSTRY_CARGO_MODE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "st_industry_cargo_mode", nullptr, nullptr, nullptr }, diff --git a/src/table/object_land.h b/src/table/object_land.h index cf024f9683..6c70755d05 100644 --- a/src/table/object_land.h +++ b/src/table/object_land.h @@ -121,7 +121,7 @@ static const DrawTileSprites _object_hq[] = { #undef TILE_SPRITE_LINE -#define M(name, size, build_cost_multiplier, clear_cost_multiplier, height, climate, gen_amount, flags) { GRFFilePropsBase<2>(), {0, 0, 0, 0}, INVALID_OBJECT_CLASS, name, climate, size, build_cost_multiplier, clear_cost_multiplier, 0, CalTime::MAX_DATE + 1, flags, OBJECT_CTRL_FLAG_NONE, {0, 0, 0, 0}, 0, height, 1, gen_amount, OVMT_DEFAULT, 0 } +#define M(name, size, build_cost_multiplier, clear_cost_multiplier, height, climate, gen_amount, flags, ctrl_flags) { GRFFilePropsBase<2>(), {0, 0, 0, 0}, INVALID_OBJECT_CLASS, name, climate, size, build_cost_multiplier, clear_cost_multiplier, 0, CalTime::MAX_DATE + 1, flags, ctrl_flags, {0, 0, 0, 0}, 0, height, 1, gen_amount, OVMT_DEFAULT, 0 } /* Climates * T = Temperate @@ -134,11 +134,11 @@ static const DrawTileSprites _object_hq[] = { #define Y 8 /** Specification of the original object structures. */ extern const ObjectSpec _original_objects[] = { - M(STR_LAI_OBJECT_DESCRIPTION_TRANSMITTER, 0x11, 0, 0, 10, T|A|S , 15, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_SCENEDIT), - M(STR_LAI_OBJECT_DESCRIPTION_LIGHTHOUSE, 0x11, 0, 0, 8, T|A , 8, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_SCENEDIT | OBJECT_FLAG_SCALE_BY_WATER), - M(STR_TOWN_BUILDING_NAME_STATUE_1, 0x11, 0, 0, 5, T|S|A|Y, 0, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_GAME | OBJECT_FLAG_ONLY_IN_SCENEDIT), // Yes, we disallow building this everywhere. Happens in "special" case! - M(STR_LAI_OBJECT_DESCRIPTION_COMPANY_OWNED_LAND, 0x11, 10, 10, 0, T|S|A|Y, 0, OBJECT_FLAG_AUTOREMOVE | OBJECT_FLAG_ONLY_IN_GAME | OBJECT_FLAG_CLEAR_INCOME | OBJECT_FLAG_HAS_NO_FOUNDATION ), // Only non-silly use case is to use it when you cannot build a station, so disallow bridges - M(STR_LAI_OBJECT_DESCRIPTION_COMPANY_HEADQUARTERS, 0x22, 0, 0, 7, T|S|A|Y, 0, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_GAME), + M(STR_LAI_OBJECT_DESCRIPTION_TRANSMITTER, 0x11, 0, 0, 10, T|A|S , 15, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_SCENEDIT, OBJECT_CTRL_FLAG_NONE ), + M(STR_LAI_OBJECT_DESCRIPTION_LIGHTHOUSE, 0x11, 0, 0, 8, T|A , 8, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_SCENEDIT | OBJECT_FLAG_SCALE_BY_WATER, OBJECT_CTRL_FLAG_NONE ), + M(STR_TOWN_BUILDING_NAME_STATUE_1, 0x11, 0, 0, 5, T|S|A|Y, 0, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_GAME | OBJECT_FLAG_ONLY_IN_SCENEDIT, OBJECT_CTRL_FLAG_NONE ), // Yes, we disallow building this everywhere. Happens in "special" case! + M(STR_LAI_OBJECT_DESCRIPTION_COMPANY_OWNED_LAND, 0x11, 10, 10, 0, T|S|A|Y, 0, OBJECT_FLAG_AUTOREMOVE | OBJECT_FLAG_ONLY_IN_GAME | OBJECT_FLAG_CLEAR_INCOME | OBJECT_FLAG_HAS_NO_FOUNDATION, OBJECT_CTRL_FLAG_USE_LAND_GROUND ), // Only non-silly use case is to use it when you cannot build a station, so disallow bridges + M(STR_LAI_OBJECT_DESCRIPTION_COMPANY_HEADQUARTERS, 0x22, 0, 0, 7, T|S|A|Y, 0, OBJECT_FLAG_CANNOT_REMOVE | OBJECT_FLAG_ONLY_IN_GAME, OBJECT_CTRL_FLAG_NONE ), }; #undef M diff --git a/src/table/settings/world_settings.ini b/src/table/settings/world_settings.ini index ad1ac06488..ec4d94afd1 100644 --- a/src/table/settings/world_settings.ini +++ b/src/table/settings/world_settings.ini @@ -881,6 +881,15 @@ strhelp = STR_CONFIG_SETTING_ALLOW_CONVERT_TOWN_ROAD_NO_HOUSES_HELPTEXT cat = SC_EXPERT patxname = ""construction.convert_town_road_no_houses"" +[SDT_BOOL] +var = construction.purchased_land_clear_ground +flags = SF_PATCH +def = true +str = STR_CONFIG_SETTING_PURCHASED_LAND_CLEAR_GROUND +strhelp = STR_CONFIG_SETTING_PURCHASED_LAND_CLEAR_GROUND_HELPTEXT +post_cb = [](auto) { MarkWholeNonMapViewportsDirty(); } +cat = SC_BASIC + [SDT_VAR] var = construction.raw_industry_construction type = SLE_UINT8