diff --git a/src/citymania/CMakeLists.txt b/src/citymania/CMakeLists.txt index 80fae71762..54464a98db 100644 --- a/src/citymania/CMakeLists.txt +++ b/src/citymania/CMakeLists.txt @@ -46,6 +46,8 @@ add_files( cm_misc_gui.cpp cm_rail_gui.hpp cm_rail_gui.cpp + cm_overlays.hpp + cm_overlays.cpp cm_station_gui.hpp cm_station_gui.cpp cm_tooltips.hpp diff --git a/src/citymania/cm_client_list_gui.cpp b/src/citymania/cm_client_list_gui.cpp index cbbf2ab27e..56dc1b5854 100644 --- a/src/citymania/cm_client_list_gui.cpp +++ b/src/citymania/cm_client_list_gui.cpp @@ -25,7 +25,7 @@ namespace citymania { -bool Intersects(PointDimension rect, Point pos, Point size) { +static bool Intersects(PointDimension rect, Point pos, Point size) { return ( pos.x + size.x >= rect.x && pos.x <= rect.x + rect.width && @@ -34,7 +34,7 @@ bool Intersects(PointDimension rect, Point pos, Point size) { ); } -bool Intersects(PointDimension rect, int left, int top, int right, int bottom) { +static bool Intersects(PointDimension rect, int left, int top, int right, int bottom) { return ( right >= rect.x && left <= rect.x + rect.width && diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index c247c162c3..c607bdb1a0 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -5,6 +5,7 @@ #include "cm_blueprint.hpp" #include "cm_commands.hpp" #include "cm_main.hpp" +#include "cm_overlays.hpp" #include "cm_station_gui.hpp" #include "cm_zoning.hpp" @@ -35,6 +36,11 @@ #include "../table/autorail.h" #include "../table/industry_land.h" #include "../debug.h" +#include "station_gui.h" +#include "station_type.h" +#include "table/sprites.h" +#include "table/strings.h" +#include "tile_type.h" #include @@ -85,6 +91,7 @@ extern RoadStopGUISettings _roadstop_gui_settings; namespace citymania { +extern CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad); extern void (*DrawTileSelectionRect)(const TileInfo *ti, PaletteID pal); extern void (*DrawAutorailSelection)(const TileInfo *ti, HighLightStyle autorail_type, PaletteID pal); @@ -348,6 +355,33 @@ void ObjectHighlight::AddTile(TileIndex tile, ObjectTileHighlight &&oh) { this->tiles.insert(std::make_pair(tile, std::move(oh))); } +void ObjectHighlight::AddStationOverlayData(TileIndex tile, int w, int h, int rad, StationCoverageType sct) { + if (!_settings_game.station.modified_catchment) rad = CA_UNMODIFIED; + auto production = citymania::GetProductionAroundTiles(this->tile, w, h, rad); + bool has_header = false; + for (CargoID i = 0; i < NUM_CARGO; i++) { + if (production[i] == 0) continue; + + switch (sct) { + case SCT_PASSENGERS_ONLY: if (!IsCargoInClass(i, CC_PASSENGERS)) continue; break; + case SCT_NON_PASSENGERS_ONLY: if (IsCargoInClass(i, CC_PASSENGERS)) continue; break; + case SCT_ALL: break; + default: NOT_REACHED(); + } + + const CargoSpec *cs = CargoSpec::Get(i); + if (cs == nullptr) continue; + + if (!has_header) { + this->overlay_data.emplace_back(PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_STATION_SUPPLIES)); + has_header = true; + } + SetDParam(0, i); + SetDParam(1, production[i] >> 8); + this->overlay_data.emplace_back(cs->GetCargoIcon(), GetString(CM_STR_BUILD_INFO_OVERLAY_STATION_CARGO)); + } +} + void ObjectHighlight::UpdateTiles() { this->tiles.clear(); this->sprites.clear(); @@ -411,6 +445,7 @@ void ObjectHighlight::UpdateTiles() { tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta } while (--numtracks); + this->AddStationOverlayData(this->tile, ta.w, ta.h, CA_TRAIN, SCT_ALL); break; } case Type::ROAD_STOP: { @@ -432,6 +467,9 @@ void ObjectHighlight::UpdateTiles() { for (TileIndex tile : ta) { this->AddTile(tile, ObjectTileHighlight::make_road_stop(palette, this->roadtype, this->ddir, this->is_truck, this->road_stop_spec_class, this->road_stop_spec_index)); } + auto sct = (this->is_truck ? SCT_NON_PASSENGERS_ONLY : SCT_PASSENGERS_ONLY); + auto rad = (this->is_truck ? CA_BUS : CA_TRUCK); + this->AddStationOverlayData(this->tile, ta.w, ta.h, rad, sct); break; } @@ -465,6 +503,7 @@ void ObjectHighlight::UpdateTiles() { for (AirportTileTableIterator iter(as->table[this->airport_layout], this->tile); iter != INVALID_TILE; ++iter) { this->AddTile(iter, ObjectTileHighlight::make_airport_tile(palette, iter.GetStationGfx())); } + this->AddStationOverlayData(this->tile, w, h, as->catchment, SCT_ALL); break; } case Type::BLUEPRINT: @@ -578,10 +617,43 @@ void ObjectHighlight::UpdateTiles() { default: NOT_REACHED(); } +} - if (this->cost.Succeeded()) { - // TODO overlay size +void ObjectHighlight::UpdateOverlay() { + HideBuildInfoOverlay(); + auto w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y); + if (w == nullptr) return; + auto vp = IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y); + if (vp == nullptr) return; + + if (this->tile == INVALID_TILE) { + HideBuildInfoOverlay(); + return; } + auto err = this->cost.GetErrorMessage(); + auto extra_err = this->cost.GetExtraErrorMessage(); + bool no_money = (err == STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY); + SetDParam(0, this->cost.GetCost()); + this->overlay_data.emplace_back(PAL_NONE, GetString(no_money ? CM_STR_BUILD_INFO_OVERLAY_COST_NO_MONEY : CM_STR_BUILD_INFO_OVERLAY_COST_OK)); + // if (this->cost.Failed() && err != STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY) { + // if (err == INVALID_STRING_ID) { + // this->overlay_data.emplace_back(PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_ERROR_UNKNOWN)); + // } else { + // SetDParam(0, err); + // this->overlay_data.emplace_back(PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_ERROR)); + // } + // if (extra_err != INVALID_STRING_ID) { + // SetDParam(0, extra_err); + // this->overlay_data.emplace_back(PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_ERROR)); + // } + // } + + // Point pt = RemapCoords2(TileX(this->tile) * TILE_SIZE + TILE_SIZE / 2, TileY(this->tile) * TILE_SIZE + TILE_SIZE / 2); + Point pt = RemapCoords2(TileX(this->tile) * TILE_SIZE, TileY(this->tile) * TILE_SIZE); + pt.x = UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left; + pt.y = UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top; + // this->overlay_pos = pt; + ShowBuildInfoOverlay(pt.x, pt.y, this->overlay_data); } void ObjectHighlight::MarkDirty() { @@ -1823,6 +1895,7 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) { _thd.cm.MarkDirty(); _thd.cm = _thd.cm_new; _thd.cm.UpdateTiles(); + _thd.cm.UpdateOverlay(); _thd.cm.MarkDirty(); } return new_drawstyle; diff --git a/src/citymania/cm_highlight_type.hpp b/src/citymania/cm_highlight_type.hpp index 33573bf2da..e41cc6df26 100644 --- a/src/citymania/cm_highlight_type.hpp +++ b/src/citymania/cm_highlight_type.hpp @@ -9,6 +9,7 @@ #include "../signal_type.h" #include "../station_map.h" #include "../station_type.h" +#include "../station_gui.h" // StationCoverageType #include "../tile_cmd.h" #include "../tile_type.h" #include "../track_type.h" @@ -318,6 +319,8 @@ protected: bool tiles_updated = false; std::multimap tiles; std::vector sprites = {}; + std::vector> overlay_data = {}; + // Point overlay_pos = {0, 0}; void AddTile(TileIndex tile, ObjectTileHighlight &&oh); // void AddSprite(TileIndex tile, ObjectTileHighlight &&oh); void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track); @@ -342,7 +345,9 @@ public: void Draw(const TileInfo *ti); void DrawSelectionOverlay(DrawPixelInfo *dpi); void DrawOverlay(DrawPixelInfo *dpi); + void AddStationOverlayData(TileIndex tile, int w, int h, int rad, StationCoverageType sct); void UpdateTiles(); + void UpdateOverlay(); void MarkDirty(); }; diff --git a/src/citymania/cm_overlays.cpp b/src/citymania/cm_overlays.cpp new file mode 100644 index 0000000000..53b3cdd028 --- /dev/null +++ b/src/citymania/cm_overlays.cpp @@ -0,0 +1,283 @@ +#include "../stdafx.h" + +#include "cm_overlays.hpp" + +#include "3rdparty/fmt/core.h" +#include "cm_client_list_gui.hpp" + +#include "../blitter/factory.hpp" // Blitter BlitterFactory +#include "../core/geometry_func.hpp" // maxdim +#include "../core/geometry_type.hpp" // PointDimension +#include "../core/alloc_type.hpp" // ReusableBuffer +#include "../gfx_func.h" // _screen +#include "../network/network.h" // _networking +#include "../video/video_driver.hpp" // VideoDriver +#include "../sprite.h" // PALETTE_TO_TRANSPARENT +#include "../window_gui.h" // Window +#include "../window_func.h" // FindWindowByID +#include "../zoom_func.h" + +#include "../safeguards.h" +#include "gfx_type.h" +#include "table/sprites.h" + +namespace citymania { + +static bool Intersects(PointDimension rect, Point pos, Point size) { + return ( + pos.x + size.x >= rect.x && + pos.x <= rect.x + rect.width && + pos.y + size.y >= rect.y && + pos.y <= rect.y + rect.height + ); +} + +static bool Intersects(PointDimension rect, int left, int top, int right, int bottom) { + return ( + right >= rect.x && + left <= rect.x + rect.width && + bottom >= rect.y && + top <= rect.y + rect.height + ); +} + + +class OverlayWindow { +protected: + PointDimension box; + bool drawn = false; + bool dirty = true; + PointDimension backup_box; + ReusableBuffer backup; + int padding; + int x = 0; + int y = 0; + +public: + OverlayWindow() {} + + void SetDirty() { + this->dirty = true; + } + + void UpdateSize() { + this->padding = ScaleGUITrad(3); + auto dim = this->GetContentDimension(); + this->box.width = dim.width + 2 * this->padding; + this->box.height = dim.height + 2 * this->padding; + this->box.x = this->x - this->box.width / 2; + this->box.y = this->y - this->box.height; + + // Window *toolbar = FindWindowById(WC_MAIN_TOOLBAR, 0); + // if (toolbar != nullptr && toolbar->left < this->box.x + this->box.width + this->padding) { + // this->box.y = toolbar->top + toolbar->height + this->padding; + // } + + if (this->box.x < 0) this->box.x = 0; + if (this->box.y < 0) this->box.y = 0; + if (this->box.x >= _screen.width) this->box.x = _screen.width - 1; + if (this->box.y >= _screen.height) this->box.y = _screen.height - 1; + + if (this->box.x + this->box.width > _screen.width) + this->box.width = _screen.width - this->box.x; + if (this->box.y + this->box.height > _screen.height) + this->box.height = _screen.height - this->box.y; + } + + virtual Dimension GetContentDimension()=0; + + void Undraw(int left, int top, int right, int bottom) { + auto &box = this->backup_box; + if (!this->drawn) return; + + if (!Intersects(box, left, top, right, bottom)) return; + + if (box.x + box.width > _screen.width) return; + if (box.y + box.height > _screen.height) return; + + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + /* Put our 'shot' back to the screen */ + blitter->CopyFromBuffer(blitter->MoveTo(_screen.dst_ptr, box.x, box.y), this->backup.GetBuffer(), box.width, box.height); + /* And make sure it is updated next time */ + VideoDriver::GetInstance()->MakeDirty(box.x, box.y, box.width, box.height); + + this->drawn = false; + this->dirty = true; + } + + virtual bool IsVisible()=0; + virtual void DrawContent(Rect rect)=0; + + void Draw() { + if (!this->dirty) return; + this->dirty = false; + + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + bool was_drawn = this->drawn; + + if (this->drawn) { + /* Put our 'shot' back to the screen */ + blitter->CopyFromBuffer(blitter->MoveTo(_screen.dst_ptr, this->backup_box.x, this->backup_box.y), this->backup.GetBuffer(), this->backup_box.width, this->backup_box.height); + /* And make sure it is updated next time */ + VideoDriver::GetInstance()->MakeDirty(this->backup_box.x, this->backup_box.y, this->backup_box.width, this->backup_box.height); + + this->drawn = false; + } + + if (!this->IsVisible()) return; + + this->UpdateSize(); + if (this->box.width <= 0 || this->box.height <= 0) return; + + if (!was_drawn || + this->box.x != this->backup_box.x || + this->box.y != this->backup_box.y || + this->box.width != this->backup_box.width || + this->box.height != this->backup_box.height) { + uint8_t *buffer = this->backup.Allocate(BlitterFactory::GetCurrentBlitter()->BufferSize(this->box.width, this->box.height)); + blitter->CopyToBuffer(blitter->MoveTo(_screen.dst_ptr, this->box.x, this->box.y), buffer, this->box.width, this->box.height); + this->backup_box = this->box; + } + + _cur_dpi = &_screen; // switch to _screen painting + + auto rect = Rect{this->box.x, this->box.y, this->box.x + this->box.width, this->box.y + this->box.height}; + + /* Paint a half-transparent box behind the client list */ + GfxFillRect(rect.left, rect.top, rect.right - 1, rect.bottom - 1, + PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR // black, but with some alpha for background + ); + + this->DrawContent(rect.Shrink(this->padding)); + + /* Make sure the data is updated next flush */ + VideoDriver::GetInstance()->MakeDirty(this->box.x, this->box.y, this->box.width, this->box.height); + + this->drawn = true; + } +}; + +class IconTextAligner { +public: + int line_height; + int max_height; + int padding; + int text_ofs_x; + int text_ofs_y; + + Dimension Init(BuildInfoOverlayData &data, int padding, FontSize font_size) { + // TODO rtl + auto font_height = GetCharacterHeight(font_size); + this->max_height = font_height; + this->line_height = this->max_height + padding; + this->text_ofs_x = 0; + this->text_ofs_y = 0; + this->padding = padding; + + if (data.size() == 0) { return {0, 0}; } + + Dimension text_dim{0, 0}; + Dimension icon_dim{0, 0}; + for (const auto &[icon, s] : data) { + text_dim = maxdim(text_dim, GetStringBoundingBox(s)); + if (icon != PAL_NONE) + icon_dim = maxdim(icon_dim, GetSpriteSize(icon)); + } + this->max_height = std::max(this->max_height, icon_dim.height); + this->text_ofs_y = (this->max_height - font_height) / 2; + this->line_height = max_height + padding; + if (icon_dim.width > 0) + this->text_ofs_x = icon_dim.width + this->padding; + return { + text_dim.width + this->text_ofs_x, + data.size() * this->line_height - padding + }; + } + + std::pair GetPositions(Rect rect, int row, SpriteID icon) { + auto icon_height = this->max_height; + auto ofs_x = 0; + if (icon != PAL_NONE) { + icon_height = GetSpriteSize(icon).height; + ofs_x = this->text_ofs_x; + } + return { + { + rect.left, + rect.top + row * this->line_height + (this->max_height - icon_height) / 2, + }, + { + rect.left + ofs_x, + rect.top + row * this->line_height + this->text_ofs_y, + rect.right, + rect.bottom + }, + }; + } +}; + +class BuildInfoOverlay: public OverlayWindow { + bool visible = false; + int line_height = 0; + int text_ofs_x = 0; + BuildInfoOverlayData data; + IconTextAligner aligner; +public: + void Show(int x, int y, BuildInfoOverlayData data) { + this->x = x; + this->y = y; + this->data = data; + this->visible = true; + this->SetDirty(); + } + + void Hide() { + this->visible = false; + } + + bool IsVisible() override { + return this->visible; + } + + Dimension GetContentDimension() override { + return aligner.Init(this->data, this->padding, FS_NORMAL); + } + + void DrawContent(Rect rect) override { + int row = 0; + for (const auto &[icon, s] : this->data) { + auto [ipos, srect] = this->aligner.GetPositions(rect, row, icon); + + DrawString(srect.left, srect.right, srect.top, s); + if (icon != PAL_NONE) + DrawSprite(icon, PAL_NONE, ipos.x, ipos.y); + + row++; + } + } +}; + +static BuildInfoOverlay _build_info_overlay{}; + +void UndrawOverlays(int left, int top, int right, int bottom) { + _build_info_overlay.Undraw(left, top, right, bottom); + if (_networking) UndrawClientList(left, top, right, bottom); +} + +void DrawOverlays() { + _build_info_overlay.Draw(); + if (_networking) DrawClientList(); +} + +void ShowBuildInfoOverlay(int x, int y, BuildInfoOverlayData data) { + _build_info_overlay.Show(x, y, data); +} + +void HideBuildInfoOverlay() { + _build_info_overlay.Hide(); +} + + +} // namespace citymania diff --git a/src/citymania/cm_overlays.hpp b/src/citymania/cm_overlays.hpp new file mode 100644 index 0000000000..1822d7fc64 --- /dev/null +++ b/src/citymania/cm_overlays.hpp @@ -0,0 +1,18 @@ +#ifndef CM_OVERLAYS_HPP +#define CM_OVERLAYS_HPP + +#include "cm_client_list_gui.hpp" // to reexport SetClientListDirty +#include "../sprite.h" // SpriteID + +namespace citymania { + +typedef std::vector> BuildInfoOverlayData; + +void UndrawOverlays(int left, int top, int right, int bottom); +void DrawOverlays(); +void ShowBuildInfoOverlay(int x, int y, BuildInfoOverlayData data); +void HideBuildInfoOverlay(); + +} // namespace citymania + +#endif diff --git a/src/citymania/cm_station_gui.cpp b/src/citymania/cm_station_gui.cpp index 56d26fae03..2fe4b870cf 100644 --- a/src/citymania/cm_station_gui.cpp +++ b/src/citymania/cm_station_gui.cpp @@ -586,7 +586,7 @@ CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) {36, 48, 64, 96, 196} }; - CargoArray produced; + CargoArray produced{}; std::set industries; TileArea ta = TileArea(tile, w, h).Expand(rad); @@ -617,9 +617,8 @@ CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) /* Skip industry with neutral station */ if (i->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) continue; - for (auto &p : i->produced) { - CargoID cargo = p.cargo; - if (cargo != CT_INVALID) produced[p.cargo] += ((uint)p.history[LAST_MONTH].production) << 8; + for (const auto &p : i->produced) { + if (IsValidCargoID(p.cargo)) produced[p.cargo] += ((uint)p.history[LAST_MONTH].production) << 8; } } @@ -633,18 +632,17 @@ std::string GetStationCoverageProductionText(TileIndex tile, int w, int h, int r s << GetString(CM_STR_STATION_BUILD_SUPPLIES); bool first = true; for (CargoID i = 0; i < NUM_CARGO; i++) { + if (production[i] == 0) continue; switch (sct) { case SCT_PASSENGERS_ONLY: if (!IsCargoInClass(i, CC_PASSENGERS)) continue; break; case SCT_NON_PASSENGERS_ONLY: if (IsCargoInClass(i, CC_PASSENGERS)) continue; break; case SCT_ALL: break; default: NOT_REACHED(); } - if (production[i] == 0) continue; if (!first) s << ", "; first = false; SetDParam(0, i); SetDParam(1, production[i] >> 8); - // GetString(buffer, CM_STR_STATION_BUILD_SUPPLIES_CARGO, lastof(buffer)); s << GetString(STR_JUST_CARGO); } return s.str(); diff --git a/src/gfx.cpp b/src/gfx.cpp index 2e52aa372b..325b195a96 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -33,7 +33,7 @@ #include "table/sprites.h" #include "table/control_codes.h" -#include "citymania/cm_client_list_gui.hpp" +#include "citymania/cm_overlays.hpp" #include "safeguards.h" @@ -101,7 +101,7 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo) if (_cursor.visible) UndrawMouseCursor(); - if (_networking) citymania::UndrawClientList(left, top, left + width, top + height); + citymania::UndrawOverlays(left, top, left + width, top + height); if (_networking) NetworkUndrawChatMessage(); blitter->ScrollBuffer(_screen.dst_ptr, left, top, width, height, xo, yo); @@ -1412,7 +1412,7 @@ void RedrawScreenRect(int left, int top, int right, int bottom) } } - if (_networking) citymania::UndrawClientList(left, top, right, bottom); + citymania::UndrawOverlays(left, top, right, bottom); if (_networking) NetworkUndrawChatMessage(); DrawOverlappedWindowForAll(left, top, right, bottom); @@ -1510,7 +1510,7 @@ void DrawDirtyBlocks() auto clear_overlays = [&]() { if (cleared_overlays) return; if (_cursor.visible) UndrawMouseCursor(); - if (_networking) citymania::UndrawClientList(0, 0, _screen.width, _screen.height); + citymania::UndrawOverlays(0, 0, _screen.width, _screen.height); if (_networking) NetworkUndrawChatMessage(); cleared_overlays = true; }; diff --git a/src/lang/english.txt b/src/lang/english.txt index ab3cb6cf7f..72e04fa7fd 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -6280,3 +6280,10 @@ CM_BUILDING_PREVIEW_COST_ENOUGH :Cost CM_STR_NO_BLUEPRINT_IN_SLOT :{WHITE}No blueprint in slot {NUM} CM_STR_ABOUT_MENU_LOGIN_WINDOW :CityMania-Serverlogin +CM_STR_BUILD_INFO_OVERLAY_COST_OK :{WHITE}Cost: {CURRENCY_LONG} +CM_STR_BUILD_INFO_OVERLAY_COST_NO_MONEY :{RED}Cost: {CURRENCY_LONG} +CM_STR_BUILD_INFO_OVERLAY_STATION_ACCEPTS :{WHITE}Accepts: +CM_STR_BUILD_INFO_OVERLAY_STATION_SUPPLIES :{WHITE}Supplies: +CM_STR_BUILD_INFO_OVERLAY_STATION_CARGO :{WHITE}{CARGO_LONG} +CM_STR_BUILD_INFO_OVERLAY_ERROR :{RED}{STRING} +CM_STR_BUILD_INFO_OVERLAY_ERROR_UNKNOWN :{RED}Unknown Error! diff --git a/src/window.cpp b/src/window.cpp index 26a832c2a3..bec93a5e83 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -42,8 +42,8 @@ /* CityMania code start */ #include #include "window_gui.h" -#include "citymania/cm_client_list_gui.hpp" #include "citymania/cm_hotkeys.hpp" +#include "citymania/cm_overlays.hpp" #include "citymania/cm_tooltips.hpp" /* CityMania code end */ @@ -3095,7 +3095,7 @@ void UpdateWindows() /* Update viewport only if window is not shaded. */ if (w->viewport != nullptr && !w->IsShaded()) UpdateViewportPosition(w, delta_ms.count()); } - citymania::DrawClientList(); + citymania::DrawOverlays(); NetworkDrawChatMessage(); /* Redraw mouse cursor in case it was hidden */ DrawMouseCursor();