Index: src/command.cpp =================================================================== --- src/command.cpp (revision 15844) +++ src/command.cpp (working copy) @@ -191,6 +191,8 @@ DEF_COMMAND(CmdChangeTimetable); DEF_COMMAND(CmdSetVehicleOnTime); DEF_COMMAND(CmdAutofillTimetable); + +DEF_COMMAND(CmdResetWaypointStats); #undef DEF_COMMAND /** @@ -335,6 +337,7 @@ {CmdChangeTimetable, 0}, // CMD_CHANGE_TIMETABLE {CmdSetVehicleOnTime, 0}, // CMD_SET_VEHICLE_ON_TIME {CmdAutofillTimetable, 0}, // CMD_AUTOFILL_TIMETABLE + {CmdResetWaypointStats, 0}, /* CMD_RESET_WAYPOINT_STATS */ }; /*! Index: src/command_type.h =================================================================== --- src/command_type.h (revision 15844) +++ src/command_type.h (working copy) @@ -286,6 +286,7 @@ CMD_CHANGE_TIMETABLE, ///< change the timetable for a vehicle CMD_SET_VEHICLE_ON_TIME, ///< set the vehicle on time feature (timetable) CMD_AUTOFILL_TIMETABLE, ///< autofill the timetable + CMD_RESET_WAYPOINT_STATS, ///< reset the "Most in a month" traffic counter of a waypoint }; /** Index: src/date.cpp =================================================================== --- src/date.cpp (revision 15844) +++ src/date.cpp (working copy) @@ -158,6 +158,7 @@ extern void EnginesDailyLoop(); extern void DisasterDailyLoop(); extern void IndustryDailyLoop(); +extern void WaypointsMonthlyLoop(); extern void CompaniesMonthlyLoop(); extern void EnginesMonthlyLoop(); extern void TownsMonthlyLoop(); @@ -251,6 +252,7 @@ } InvalidateWindowClasses(WC_CHEATS); + WaypointsMonthlyLoop(); CompaniesMonthlyLoop(); EnginesMonthlyLoop(); TownsMonthlyLoop(); Index: src/lang/english.txt =================================================================== --- src/lang/english.txt (revision 15844) +++ src/lang/english.txt (working copy) @@ -1189,6 +1189,14 @@ STR_WAYPOINT_RAW :{WAYPOINT} STR_EDIT_WAYPOINT_NAME :{WHITE}Edit waypoint name +STR_WAYPOINT_TRAFFIC :{BLACK}Traffic +STR_WAYPOINT_TRAFFIC_THIS_MONTH :{SKIP}{BLACK}This month: {GOLD}{COMMA} +STR_WAYPOINT_TRAFFIC_LAST_MONTH :{SKIP}{SKIP}{BLACK}Last month: {GOLD}{COMMA} +STR_WAYPOINT_TRAFFIC_MOST :{SKIP}{SKIP}{SKIP}{BLACK}Most in a month: {GOLD}{COMMA} + +STR_RESET_STATS :{BLACK}Reset Stats +STR_RESET_STATS_TIP :{BLACK}Reset the "Most in a month" counter + STR_CANT_CHANGE_WAYPOINT_NAME :{WHITE}Can't change waypoint name... STR_CONVERT_RAIL_TO_WAYPOINT_TIP :{BLACK}Convert rail to waypoint STR_CANT_BUILD_TRAIN_WAYPOINT :{WHITE}Can't build train waypoint here... Index: src/rail_cmd.cpp =================================================================== --- src/rail_cmd.cpp (revision 15844) +++ src/rail_cmd.cpp (working copy) @@ -2452,6 +2452,15 @@ DiagDirection dir; int length; + /* if train passes a waypoint, update the waypoint's statistics */ + if (IsFrontEngine(v) && IsRailWaypoint(tile) && v->tile != tile) { + Waypoint *wp = GetWaypointByTile(tile); + if (wp->AddPassageOnStatistics()) { + /* only update the window when the passage of the vehicle affected the waypoint */ + InvalidateWindow(WC_WAYPOINT_VIEW, wp->index); + } + } + /* this routine applies only to trains in depot tiles */ if (v->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE; Index: src/saveload/saveload.cpp =================================================================== --- src/saveload/saveload.cpp (revision 15844) +++ src/saveload/saveload.cpp (working copy) @@ -40,7 +40,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 115; +extern const uint16 SAVEGAME_VERSION = 116; SavegameType _savegame_type; ///< type of savegame we are loading Index: src/saveload/waypoint_sl.cpp =================================================================== --- src/saveload/waypoint_sl.cpp (revision 15844) +++ src/saveload/waypoint_sl.cpp (working copy) @@ -68,6 +68,10 @@ SLE_CONDVAR(Waypoint, grfid, SLE_UINT32, 17, SL_MAX_VERSION), SLE_CONDVAR(Waypoint, owner, SLE_UINT8, 101, SL_MAX_VERSION), + SLE_CONDVAR(Waypoint, traffic_this_month, SLE_UINT16, 116, SL_MAX_VERSION), + SLE_CONDVAR(Waypoint, traffic_last_month, SLE_UINT16, 116, SL_MAX_VERSION), + SLE_CONDVAR(Waypoint, traffic_highest, SLE_UINT16, 116, SL_MAX_VERSION), + SLE_END() }; Index: src/waypoint.cpp =================================================================== --- src/waypoint.cpp (revision 15844) +++ src/waypoint.cpp (working copy) @@ -42,6 +42,19 @@ } /** + * Monthly loop for waypoints + */ +void WaypointsMonthlyLoop() +{ + Waypoint *wp; + + FOR_ALL_WAYPOINTS(wp) { + wp->MonthlyStatisticsMaintenance(); + } + InvalidateWindowClasses(WC_WAYPOINT_VIEW); +} + +/** * This hacks together some dummy one-shot Station structure for a waypoint. * @param tile on which to work * @return pointer to a Station Index: src/waypoint.h =================================================================== --- src/waypoint.h (revision 15844) +++ src/waypoint.h (working copy) @@ -17,27 +17,57 @@ DECLARE_OLD_POOL(Waypoint, Waypoint, 3, 8000) struct Waypoint : PoolItem { - TileIndex xy; ///< Tile of waypoint + TileIndex xy; ///< Tile of waypoint - TownID town_index; ///< Town associated with the waypoint - uint16 town_cn; ///< The Nth waypoint for this town (consecutive number) - StringID string; ///< C000-C03F have special meaning in old games - char *name; ///< Custom name. If not set, town + town_cn is used for naming + TownID town_index; ///< Town associated with the waypoint + uint16 town_cn; ///< The Nth waypoint for this town (consecutive number) + StringID string; ///< C000-C03F have special meaning in old games + char *name; ///< Custom name. If not set, town + town_cn is used for naming - ViewportSign sign; ///< Dimensions of sign (not saved) - Date build_date; ///< Date of construction - OwnerByte owner; ///< Whom this waypoint belongs to + ViewportSign sign; ///< Dimensions of sign (not saved) + Date build_date; ///< Date of construction + OwnerByte owner; ///< Whom this waypoint belongs to - byte stat_id; ///< ID of waypoint within the waypoint class (not saved) - uint32 grfid; ///< ID of GRF file - byte localidx; ///< Index of station within GRF file + byte stat_id; ///< ID of waypoint within the waypoint class (not saved) + uint32 grfid; ///< ID of GRF file + byte localidx; ///< Index of station within GRF file - byte deleted; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted. + byte deleted; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted. + uint16 traffic_this_month; ///< Number of trains that passed this waypoint this month + uint16 traffic_last_month; ///< Number of trains that passed this waypoint last month + uint16 traffic_highest; ///< Maximum number of trains that have passed the waypoint during one month + Waypoint(TileIndex tile = INVALID_TILE); ~Waypoint(); inline bool IsValid() const { return this->xy != INVALID_TILE; } + + inline bool AddPassageOnStatistics() + { + /* do not overflow - the limit of 65535 should not be reached under normal circumstances, but just in case */ + if (this->traffic_this_month < MAX_UVALUE(uint16)) { + this->traffic_this_month++; + this->traffic_highest = max(this->traffic_highest, this->traffic_this_month); + return true; + } + return false; + } + + inline void ResetStatistics() + { + this->traffic_this_month = 0; + this->traffic_highest = 0; + this->traffic_last_month = 0; + } + + inline void MonthlyStatisticsMaintenance() + { + /* Reset waypoint statistics for the current month, since it's now a new one*/ + this->traffic_last_month = this->traffic_this_month; + this->traffic_this_month = 0; + } + }; static inline bool IsValidWaypointID(WaypointID index) Index: src/waypoint_cmd.cpp =================================================================== --- src/waypoint_cmd.cpp (revision 15844) +++ src/waypoint_cmd.cpp (working copy) @@ -222,6 +222,7 @@ wp->deleted = 0; wp->build_date = _date; + wp->ResetStatistics(); if (wp->town_index == INVALID_TOWN) MakeDefaultWaypointName(wp); @@ -340,3 +341,26 @@ } return CommandCost(); } + +/** + * Reset the "Most in a month" counter of a waypoint. + * @param tile unused + * @param flags type of operation + * @param p1 id of waypoint + * @param p2 unused + * @param text unused + * @return cost of operation or error + */ +CommandCost CmdResetWaypointStats(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (!IsValidWaypointID(p1)) return CMD_ERROR; + + Waypoint *wp = GetWaypoint(p1); + if (!CheckOwnership(wp->owner)) return CMD_ERROR; + + if (flags & DC_EXEC) { + wp->ResetStatistics(); + InvalidateWindow(WC_WAYPOINT_VIEW, p1); + } + return CommandCost(); +} Index: src/waypoint_gui.cpp =================================================================== --- src/waypoint_gui.cpp (revision 15844) +++ src/waypoint_gui.cpp (working copy) @@ -26,7 +26,12 @@ WAYPVW_STICKY, WAYPVW_VIEWPORTPANEL, WAYPVW_SPACER, + WAYPVW_TRAFFIC_HEADER, + WAYPVW_TRAFFIC_THIS_MONTH, + WAYPVW_TRAFFIC_LAST_MONTH, + WAYPVW_TRAFFIC_MOST, WAYPVW_CENTERVIEW, + WAYPVW_RESET_STATS, WAYPVW_RENAME, WAYPVW_SHOW_TRAINS, }; @@ -51,11 +56,15 @@ virtual void OnPaint() { /* You can only change your own waypoints */ + this->SetWidgetDisabledState(WAYPVW_RESET_STATS, this->wp->owner != _local_company); this->SetWidgetDisabledState(WAYPVW_RENAME, this->wp->owner != _local_company); /* Disable the widget for waypoints with no owner (after company bankrupt) */ this->SetWidgetDisabledState(WAYPVW_SHOW_TRAINS, this->wp->owner == OWNER_NONE); SetDParam(0, this->wp->index); + SetDParam(1, this->wp->traffic_this_month); + SetDParam(2, this->wp->traffic_last_month); + SetDParam(3, this->wp->traffic_highest); this->DrawWidgets(); this->DrawViewport(); @@ -72,6 +81,10 @@ } break; + case WAYPVW_RESET_STATS: /* reset stats */ + DoCommandP(0, this->window_number, 0, CMD_RESET_WAYPOINT_STATS); + break; + case WAYPVW_RENAME: // rename SetDParam(0, this->wp->index); ShowQueryString(STR_WAYPOINT_RAW, STR_EDIT_WAYPOINT_NAME, MAX_LENGTH_WAYPOINT_NAME_BYTES, MAX_LENGTH_WAYPOINT_NAME_PIXELS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT); @@ -100,19 +113,24 @@ }; static const Widget _waypoint_view_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, COLOUR_GREY, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // WAYPVW_CLOSEBOX -{ WWT_CAPTION, RESIZE_NONE, COLOUR_GREY, 11, 247, 0, 13, STR_WAYPOINT_VIEWPORT, STR_018C_WINDOW_TITLE_DRAG_THIS}, // WAYPVW_CAPTION -{ WWT_STICKYBOX, RESIZE_NONE, COLOUR_GREY, 248, 259, 0, 13, 0x0, STR_STICKY_BUTTON}, // WAYPVW_STICKY -{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 0, 259, 14, 105, 0x0, STR_NULL}, // WAYPVW_VIEWPORTPANEL -{ WWT_INSET, RESIZE_NONE, COLOUR_GREY, 2, 257, 16, 103, 0x0, STR_NULL}, // WAYPVW_SPACER -{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 0, 121, 106, 117, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, // WAYPVW_CENTERVIEW -{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 122, 244, 106, 117, STR_0130_RENAME, STR_CHANGE_WAYPOINT_NAME}, // WAYPVW_RENAME -{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 245, 259, 106, 117, STR_TRAIN, STR_SCHEDULED_TRAINS_TIP }, // WAYPVW_SHOW_TRAINS +{ WWT_CLOSEBOX, RESIZE_NONE, COLOUR_GREY, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // WAYPVW_CLOSEBOX +{ WWT_CAPTION, RESIZE_NONE, COLOUR_GREY, 11, 247, 0, 13, STR_WAYPOINT_VIEWPORT, STR_018C_WINDOW_TITLE_DRAG_THIS}, // WAYPVW_CAPTION +{ WWT_STICKYBOX, RESIZE_NONE, COLOUR_GREY, 248, 259, 0, 13, 0x0, STR_STICKY_BUTTON}, // WAYPVW_STICKY +{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 0, 259, 14, 145, 0x0, STR_NULL}, // WAYPVW_VIEWPORTPANEL +{ WWT_INSET, RESIZE_NONE, COLOUR_GREY, 2, 257, 16, 103, 0x0, STR_NULL}, // WAYPVW_SPACER +{ WWT_TEXT, RESIZE_NONE, COLOUR_GREY, 2, 257, 105, 116, STR_WAYPOINT_TRAFFIC, STR_NULL}, // WAYPVW_TRAFFIC_HEADER +{ WWT_TEXT, RESIZE_NONE, COLOUR_GREY, 5, 257, 115, 126, STR_WAYPOINT_TRAFFIC_THIS_MONTH, STR_NULL}, // WAYPVW_TRAFFIC_THIS_MONTH +{ WWT_TEXT, RESIZE_NONE, COLOUR_GREY, 5, 257, 125, 136, STR_WAYPOINT_TRAFFIC_LAST_MONTH, STR_NULL}, // WAYPVW_TRAFFIC_LAST_MONTH +{ WWT_TEXT, RESIZE_NONE, COLOUR_GREY, 5, 257, 135, 146, STR_WAYPOINT_TRAFFIC_MOST, STR_NULL}, // WAYPVW_TRAFFIC_MOST +{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 0, 81, 146, 157, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, // WAYPVW_CENTERVIEW +{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 82, 163, 146, 157, STR_RESET_STATS, STR_RESET_STATS_TIP}, // WAYPVW_RESET_STATS +{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 164, 245, 146, 157, STR_0130_RENAME, STR_CHANGE_WAYPOINT_NAME}, // WAYPVW_RENAME +{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_GREY, 246, 259, 146, 157, STR_TRAIN, STR_SCHEDULED_TRAINS_TIP }, // WAYPVW_SHOW_TRAINS { WIDGETS_END}, }; static const WindowDesc _waypoint_view_desc( - WDP_AUTO, WDP_AUTO, 260, 118, 260, 118, + WDP_AUTO, WDP_AUTO, 260, 158, 260, 158, WC_WAYPOINT_VIEW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, _waypoint_view_widgets