From df1247925209b921b8286ad131329e51bb81d460 Mon Sep 17 00:00:00 2001 From: dP Date: Sun, 19 Jul 2020 02:38:36 +0300 Subject: [PATCH] Add APM counter to the status bar --- cm_changelog.txt | 1 + src/citymania/cm_hotkeys.cpp | 30 ++++++++++++++++++++++++++++++ src/citymania/cm_hotkeys.hpp | 4 ++++ src/citymania/cm_main.cpp | 2 ++ src/command.cpp | 1 + src/lang/english.txt | 2 ++ src/statusbar_gui.cpp | 26 ++++++++++++++++++++++++-- src/widgets/statusbar_widget.h | 1 + 8 files changed, 65 insertions(+), 2 deletions(-) diff --git a/cm_changelog.txt b/cm_changelog.txt index 10db5ed471..fc3cfbc95e 100644 --- a/cm_changelog.txt +++ b/cm_changelog.txt @@ -90,6 +90,7 @@ This is usable for any OpenTTD servers - Allow to toggle removal mode with modifier key on station and signal building tools if it's different from fn modifier (otherwise fn takes priority). - Center text and icons in the status bar vertically. - Shaded trees. +- Add APM counter to the status bar. *** 1.10.2 (5 Jun 2020) *** - Add new minimap mode showing industries, height and farms at the same time. diff --git a/src/citymania/cm_hotkeys.cpp b/src/citymania/cm_hotkeys.cpp index 28bce2045c..2d70bf7dea 100644 --- a/src/citymania/cm_hotkeys.cpp +++ b/src/citymania/cm_hotkeys.cpp @@ -14,6 +14,8 @@ #include "../widgets/rail_widget.h" #include "../widgets/road_widget.h" +#include + #include "../safeguards.h" struct RailStationGUISettings { @@ -25,6 +27,7 @@ struct RailStationGUISettings { byte station_count; ///< Number of custom stations (if newstations is \c true ) }; extern RailStationGUISettings _railstation; ///< Settings of the station builder GUI +extern uint32 _realtime_tick; namespace citymania { @@ -32,6 +35,33 @@ bool _fn_mod = false; bool _remove_mod = false; bool _estimate_mod = false; +uint32 _effective_actions = 0; +uint32 _first_effective_tick = 0; +std::queue _last_actions; + +static void PurgeLastActions() { + while (!_last_actions.empty() && _last_actions.front() <= _realtime_tick) + _last_actions.pop(); +} + +void CountEffectiveAction() { + if (!_first_effective_tick) _first_effective_tick = _realtime_tick; + _effective_actions++; + PurgeLastActions(); + _last_actions.push(_realtime_tick + 60000); +} + +void ResetEffectivveActionCounter() { + _first_effective_tick = 0; + _effective_actions = 0; + std::queue().swap(_last_actions); // clear the queue +} + +std::pair GetEPM() { + if (!_first_effective_tick) return std::make_pair(0, 0); + PurgeLastActions(); + return std::make_pair(_effective_actions * 60000 / (_realtime_tick - _first_effective_tick), _last_actions.size()); +} void UpdateModKeys(bool shift_pressed, bool ctrl_pressed, bool alt_pressed) { ModKey key = ModKey::NONE; diff --git a/src/citymania/cm_hotkeys.hpp b/src/citymania/cm_hotkeys.hpp index ab681d0fbb..f85ec6256f 100644 --- a/src/citymania/cm_hotkeys.hpp +++ b/src/citymania/cm_hotkeys.hpp @@ -25,6 +25,10 @@ ToolRemoveMode RoadToolbar_GetRemoveMode(int widget); void RoadToolbar_UpdateOptionWidgetStatus(Window *w, int widget, bool remove_active, bool is_road); bool RoadToolbar_RemoveModChanged(Window *w, bool remove_active, bool button_clicked, bool is_road); +void CountEffectiveAction(); +void ResetEffectivveActionCounter(); +std::pair GetEPM(); + } // namespace citymania #endif diff --git a/src/citymania/cm_main.cpp b/src/citymania/cm_main.cpp index 4d7ba9e8a8..9953807dfd 100644 --- a/src/citymania/cm_main.cpp +++ b/src/citymania/cm_main.cpp @@ -1,6 +1,7 @@ #include "../stdafx.h" #include "cm_main.hpp" +#include "cm_hotkeys.hpp" #include "../smallmap_gui.h" #include "../window_func.h" @@ -13,6 +14,7 @@ up _game = nullptr; void ResetGame() { _game = make_up(); + ResetEffectivveActionCounter(); } void SwitchToMode(SwitchMode new_mode) { diff --git a/src/command.cpp b/src/command.cpp index 106cd862b0..f0b33d501d 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -588,6 +588,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac /* Only set p2 when the command does not come from the network. */ if (!(cmd & CMD_NETWORK_COMMAND) && GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = CLIENT_ID_SERVER; + if (!(cmd & CMD_NO_ESTIMATE) && my_cmd) citymania::CountEffectiveAction(); CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only); if (res.Failed()) { /* Only show the error when it's for us. */ diff --git a/src/lang/english.txt b/src/lang/english.txt index 1f9d3df831..040c3aad2e 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5542,3 +5542,5 @@ STR_CM_CONFIG_SETTING_SHADED_TREES_HELPTEXT : Change tree brightness depending o STR_CM_CONFIG_SETTING_SHADED_TREES_OFF : Always off STR_CM_CONFIG_SETTING_SHADED_TREES_ON : Always on STR_CM_CONFIG_SETTING_SHADED_TREES_SERVER : As server + +STR_CM_STATUSBAR_EPM : {WHITE}APM: {NUM} AVG: {NUM} diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp index a437f9fa8d..be2ab85862 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -32,6 +32,8 @@ #include "table/strings.h" #include "table/sprites.h" +#include "citymania/cm_hotkeys.hpp" + #include "safeguards.h" static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left, int right, int top, int bottom) @@ -81,6 +83,7 @@ struct StatusBarWindow : Window { int ticker_scroll; GUITimer ticker_timer; GUITimer reminder_timeout; + GUITimer cm_epm_timer; static const int TICKER_STOP = 1640; ///< scrolling is finished when counter reaches this value static const int REMINDER_START = 1350; ///< time in ms for reminder notification (red dot on the right) to stay @@ -92,6 +95,7 @@ struct StatusBarWindow : Window { this->ticker_scroll = TICKER_STOP; this->ticker_timer.SetInterval(15); this->reminder_timeout.SetInterval(REMINDER_STOP); + this->cm_epm_timer.SetInterval(1000); this->InitNested(); CLRBITS(this->flags, WF_WHITE_BORDER); @@ -126,6 +130,12 @@ struct StatusBarWindow : Window { break; } + case CM_WID_S_EPM: + SetDParam(0, 999); + SetDParam(1, 999); + d = GetStringBoundingBox(STR_CM_STATUSBAR_EPM); + break; + default: return; } @@ -187,6 +197,13 @@ struct StatusBarWindow : Window { DrawSprite(SPR_UNREAD_NEWS, PAL_NONE, r.right - WD_FRAMERECT_RIGHT - icon_size.width, r.top + max(0, ((int)(r.bottom - r.top + 1) - (int)icon_size.height) / 2)); } break; + + case CM_WID_S_EPM: + auto epm = citymania::GetEPM(); + SetDParam(0, epm.second); + SetDParam(1, epm.first); + DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, text_top, STR_CM_STATUSBAR_EPM, TC_FROMSTRING, SA_HOR_CENTER); + break; } } @@ -236,14 +253,19 @@ struct StatusBarWindow : Window { if (this->reminder_timeout.Elapsed(delta_ms)) { this->SetWidgetDirty(WID_S_MIDDLE); } + + if (this->cm_epm_timer.CountElapsed(delta_ms)) { + this->SetWidgetDirty(CM_WID_S_EPM); + } } }; static const NWidgetPart _nested_main_status_widgets[] = { NWidget(NWID_HORIZONTAL), - NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(140, 12), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(100, 12), EndContainer(), NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(40, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0), - NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_RIGHT), SetMinimalSize(140, 12), + NWidget(WWT_PANEL, COLOUR_GREY, CM_WID_S_EPM), SetMinimalSize(100, 12), EndContainer(), + NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_RIGHT), SetMinimalSize(100, 12), EndContainer(), }; diff --git a/src/widgets/statusbar_widget.h b/src/widgets/statusbar_widget.h index bb8149e461..b58ca7ed56 100644 --- a/src/widgets/statusbar_widget.h +++ b/src/widgets/statusbar_widget.h @@ -15,6 +15,7 @@ enum StatusbarWidgets { WID_S_LEFT, ///< Left part of the statusbar; date is shown there. WID_S_MIDDLE, ///< Middle part; current news or company name or *** SAVING *** or *** PAUSED ***. WID_S_RIGHT, ///< Right part; bank balance. + CM_WID_S_EPM, ///< CityMania EPM counter. }; #endif /* WIDGETS_STATUSBAR_WIDGET_H */