From db2a20afac50e3ad8e729196029f7e7f945e65e5 Mon Sep 17 00:00:00 2001 From: dP Date: Fri, 31 Mar 2023 18:31:27 +0400 Subject: [PATCH] Show building preview when funding industries --- src/citymania/cm_highlight.cpp | 98 +++++++++++++++++++++++++++-- src/citymania/cm_highlight_type.hpp | 9 ++- src/command_type.h | 4 ++ src/industry_cmd.cpp | 6 +- src/industry_gui.cpp | 12 ++-- 5 files changed, 118 insertions(+), 11 deletions(-) diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index f4be7ba335..16b6746ae4 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -32,6 +32,7 @@ #include "../table/airporttile_ids.h" #include "../table/track_land.h" #include "../table/autorail.h" +#include "../table/industry_land.h" #include "../debug.h" #include @@ -176,10 +177,21 @@ ObjectTileHighlight ObjectTileHighlight::make_airport_tile(SpriteID palette, Sta return oh; } +ObjectTileHighlight ObjectTileHighlight::make_industry_tile(SpriteID palette, IndustryGfx gfx) { + auto oh = ObjectTileHighlight(Type::INDUSTRY_TILE, palette); + oh.u.industry_tile.gfx = gfx; + return oh; +} + ObjectTileHighlight ObjectTileHighlight::make_point(SpriteID palette) { return ObjectTileHighlight(Type::POINT, palette); } +ObjectTileHighlight ObjectTileHighlight::make_rect(SpriteID palette) { + auto oh = ObjectTileHighlight(Type::RECT, palette); + return oh; +} + ObjectTileHighlight ObjectTileHighlight::make_numbered_rect(SpriteID palette, uint32 number) { auto oh = ObjectTileHighlight(Type::NUMBERED_RECT, palette); oh.u.numbered_rect.number = number; @@ -505,16 +517,35 @@ void ObjectHighlight::UpdateTiles() { add_track(this->tile2, this->end_tile2, this->trackdir2, PALETTE_SEL_TILE_BLUE, INVALID_TILE, INVALID_TILE); break; } - case Type::INDUSTRY: - this->AddTile(this->tile, ObjectTileHighlight::make_numbered_rect(CM_PALETTE_TINT_WHITE, this->ind_layout)); + case Type::INDUSTRY: { + auto cost = cmd::BuildIndustry{this->tile, this->ind_type, this->ind_layout, true, 0}.call(DC_NONE); + if (cost.Succeeded()) { + const IndustrySpec *indspec = GetIndustrySpec(this->ind_type); + Debug(misc, 0, "Layout requested: {}, layout founded: {}", this->ind_layout, cost.cm.industry_layout); + if (indspec == nullptr) break; + if (cost.cm.industry_layout >= indspec->layouts.size()) break; + + const IndustryTileLayout &layout = indspec->layouts[cost.cm.industry_layout]; + for (const IndustryTileLayoutTile &it : layout) { + if (it.gfx == GFX_WATERTILE_SPECIALCHECK) continue; + TileIndex cur_tile = this->tile + ToTileIndexDiff(it.ti); + // WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID); + this->AddTile( + cur_tile, + ObjectTileHighlight::make_industry_tile(CM_PALETTE_TINT_WHITE, it.gfx) + ); + } + } else { + this->AddTile(this->tile, ObjectTileHighlight::make_rect(CM_SPR_PALETTE_ZONING_RED)); + } break; + } default: NOT_REACHED(); } } void ObjectHighlight::MarkDirty() { - this->UpdateTiles(); for (const auto &kv: this->tiles) { MarkTileDirtyByTile(kv.first); } @@ -793,6 +824,57 @@ void DrawAirportTile(SpriteID palette, const TileInfo *ti, StationGfx gfx) { } } +void DrawIndustryTile(SpriteID palette, const TileInfo *ti, IndustryGfx gfx) { + const IndustryTileSpec *indts = GetIndustryTileSpec(gfx); + + if (gfx >= NEW_INDUSTRYTILEOFFSET) return; // TODO + // if (gfx >= NEW_INDUSTRYTILEOFFSET) { + // /* Draw the tile using the specialized method of newgrf industrytile. + // * DrawNewIndustry will return false if ever the resolver could not + // * find any sprite to display. So in this case, we will jump on the + // * substitute gfx instead. */ + // if (indts->grf_prop.spritegroup[0] != nullptr && DrawNewIndustryTile(ti, ind, gfx, indts)) { + // return; + // } else { + // /* No sprite group (or no valid one) found, meaning no graphics associated. + // * Use the substitute one instead */ + // if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) { + // gfx = indts->grf_prop.subst_id; + // /* And point the industrytile spec accordingly */ + // indts = GetIndustryTileSpec(gfx); + // } + // } + // } + + const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | INDUSTRY_COMPLETED]; + + SpriteID image = dits->ground.sprite; + + /* DrawFoundation() modifies ti->z and ti->tileh */ + // if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED); + + /* 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'. */ + // if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) { + // DrawWaterClassGround(ti); + // } else { + DrawGroundSprite(image, GroundSpritePaletteTransform(image, palette, PALETTE_RECOLOUR_START)); + // } + + /* Add industry on top of the ground? */ + image = dits->building.sprite; + if (image != 0) { + AddSortableSpriteToDraw(image, palette, + ti->x + dits->subtile_x, + ti->y + dits->subtile_y, + dits->width, + dits->height, + dits->dz, + ti->z, + false); + } +} + enum SignalOffsets { // from rail_cmd.cpp SIGNAL_TO_SOUTHWEST, SIGNAL_TO_NORTHEAST, @@ -970,9 +1052,15 @@ void ObjectHighlight::Draw(const TileInfo *ti) { case ObjectTileHighlight::Type::AIRPORT_TILE: DrawAirportTile(oth.palette, ti, oth.u.airport_tile.gfx); break; + case ObjectTileHighlight::Type::INDUSTRY_TILE: + DrawIndustryTile(oth.palette, ti, oth.u.industry_tile.gfx); + break; case ObjectTileHighlight::Type::POINT: DrawSelectionPoint(oth.palette, ti); break; + case ObjectTileHighlight::Type::RECT: + DrawTileSelectionRect(ti, oth.palette); + break; case ObjectTileHighlight::Type::NUMBERED_RECT: { DrawTileSelectionRect(ti, oth.palette); ViewportSign sign; @@ -1374,7 +1462,8 @@ bool DrawTileSelection(const TileInfo *ti, const TileHighlightType &tht) { if (_thd.select_proc == DDSP_BUILD_STATION || _thd.select_proc == DDSP_BUILD_BUSSTOP || _thd.select_proc == DDSP_BUILD_TRUCKSTOP || _thd.select_proc == CM_DDSP_BUILD_AIRPORT - || _thd.select_proc == CM_DDSP_BUILD_ROAD_DEPOT || _thd.select_proc == CM_DDSP_BUILD_RAIL_DEPOT) { + || _thd.select_proc == CM_DDSP_BUILD_ROAD_DEPOT || _thd.select_proc == CM_DDSP_BUILD_RAIL_DEPOT + || _thd.select_proc == CM_DDSP_FUND_INDUSTRY) { // handled by DrawTileZoning return true; } @@ -1503,6 +1592,7 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) { if (force_new || _thd.cm != _thd.cm_new) { _thd.cm.MarkDirty(); _thd.cm = _thd.cm_new; + _thd.cm.UpdateTiles(); _thd.cm.MarkDirty(); } return new_drawstyle; diff --git a/src/citymania/cm_highlight_type.hpp b/src/citymania/cm_highlight_type.hpp index 0d605e52fb..6c05e6dfbb 100644 --- a/src/citymania/cm_highlight_type.hpp +++ b/src/citymania/cm_highlight_type.hpp @@ -46,7 +46,9 @@ public: ROAD_DEPOT, AIRPORT_TILE, + INDUSTRY_TILE, POINT, + RECT, NUMBERED_RECT, END, }; @@ -92,6 +94,9 @@ public: struct { StationGfx gfx; } airport_tile; + struct { + IndustryGfx gfx; + } industry_tile; struct { uint32 number; } numbered_rect; @@ -108,7 +113,9 @@ public: static ObjectTileHighlight make_road_stop(SpriteID palette, RoadType roadtype, DiagDirection ddir, bool is_truck); static ObjectTileHighlight make_road_depot(SpriteID palette, RoadType roadtype, DiagDirection ddir); static ObjectTileHighlight make_airport_tile(SpriteID palette, StationGfx gfx); + static ObjectTileHighlight make_industry_tile(SpriteID palette, IndustryGfx gfx); static ObjectTileHighlight make_point(SpriteID palette); + static ObjectTileHighlight make_rect(SpriteID palette); static ObjectTileHighlight make_numbered_rect(SpriteID palette, uint32 number); }; @@ -257,7 +264,6 @@ protected: std::vector sprites = {}; void AddTile(TileIndex tile, ObjectTileHighlight &&oh); // void AddSprite(TileIndex tile, ObjectTileHighlight &&oh); - void UpdateTiles(); void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track); public: @@ -278,6 +284,7 @@ public: void Draw(const TileInfo *ti); void DrawOverlay(DrawPixelInfo *dpi); + void UpdateTiles(); void MarkDirty(); }; diff --git a/src/command_type.h b/src/command_type.h index d2b573b333..1f0194562f 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -15,6 +15,8 @@ #include "tile_type.h" #include +#include "citymania/extensions/cmext_commandcost.hpp" + struct GRFFile; /** @@ -32,6 +34,8 @@ class CommandCost { static uint32 textref_stack[16]; public: + citymania::ext::CommandCost cm; + /** * Creates a command cost return with no cost and no error */ diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index efaa9e6e1a..41a79ee196 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -2102,6 +2102,7 @@ CommandCost CmdBuildIndustry(DoCommandFlag flags, TileIndex tile, IndustryType i for (size_t j = 0; j < num_layouts; j++) { layout = (layout + 1) % num_layouts; ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), calltype, &ind); + ret.cm.industry_layout = layout; if (ret.Succeeded()) break; } if (ret.Succeeded()) break; @@ -2124,6 +2125,7 @@ CommandCost CmdBuildIndustry(DoCommandFlag flags, TileIndex tile, IndustryType i for (size_t i = 0; i < num_layouts; i++) { layout = (layout + 1) % num_layouts; ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind); + ret.cm.industry_layout = layout; if (ret.Succeeded()) break; } @@ -2135,7 +2137,9 @@ CommandCost CmdBuildIndustry(DoCommandFlag flags, TileIndex tile, IndustryType i AdvertiseIndustryOpening(ind); } - return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost()); + auto cm_ret = CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost()); + cm_ret.cm.industry_layout = ret.cm.industry_layout; + return cm_ret; } /** diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index bcb21cdeb4..e99f647760 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -688,10 +688,11 @@ public: if (y < this->count) { // Is it within the boundaries of available data? this->selected_index = y; _cm_funding_type = this->selected_type = this->index[y]; - _cm_funding_layout = 0; - citymania::SetIndustryForbiddenTilesHighlight(this->selected_type); const IndustrySpec *indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? nullptr : GetIndustrySpec(this->selected_type); + _cm_funding_layout = (indsp == nullptr ? 0 : InteractiveRandomRange((uint32)indsp->layouts.size())); + citymania::SetIndustryForbiddenTilesHighlight(this->selected_type); + this->SetDirty(); if (_thd.GetCallbackWnd() == this && @@ -749,8 +750,8 @@ public: /* We do not need to protect ourselves against "Random Many Industries" in this mode */ const IndustrySpec *indsp = GetIndustrySpec(this->selected_type); uint32 seed = InteractiveRandom(); - uint32 layout_index = InteractiveRandomRange((uint32)indsp->layouts.size()); - if (_cm_funding_layout > 0) layout_index = _cm_funding_layout - 1; + // uint32 layout_index = InteractiveRandomRange((uint32)indsp->layouts.size()); + uint32 layout_index = _cm_funding_layout; if (_game_mode == GM_EDITOR) { /* Show error if no town exists at all */ @@ -769,6 +770,7 @@ public: cur_company.Restore(); old_generating_world.Restore(); _ignore_restrictions = false; + _cm_funding_layout = InteractiveRandomRange((uint32)indsp->layouts.size()); } else { success = Command::Post(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY, tile, this->selected_type, layout_index, false, seed); } @@ -830,7 +832,7 @@ public: const IndustrySpec *indspec = GetIndustrySpec(this->selected_type); size_t num_layouts = indspec->layouts.size(); MarkTileDirtyByTile(TileVirtXY(_thd.pos.x, _thd.pos.y)); // redraw tile selection - _cm_funding_layout = (_cm_funding_layout + 1) % (num_layouts + 1); + _cm_funding_layout = (_cm_funding_layout + 1) % num_layouts; return ES_HANDLED; } else return ES_NOT_HANDLED; }