From 4270026b4248bbaa1b1b46b099baadbd24921dd0 Mon Sep 17 00:00:00 2001 From: tron Date: Sat, 4 Mar 2006 11:01:35 +0000 Subject: [PATCH] (svn r3757) -Feature: Delete news items about vehicles, when they get stale This is used to delete - all news about a vehicle, when it gets deleted - "vehicle has stopped in depot" news, when it gets started - "vehicle has invalid orders" news, when the orders get changed --- aircraft_cmd.c | 4 ++++ news.h | 7 +++++++ news_gui.c | 34 ++++++++++++++++++++++++++++++++++ order_cmd.c | 30 +++++++++++++++++++++++++++--- roadveh_cmd.c | 4 ++++ ship_cmd.c | 4 ++++ train_cmd.c | 4 ++++ vehicle.c | 2 ++ 8 files changed, 86 insertions(+), 3 deletions(-) diff --git a/aircraft_cmd.c b/aircraft_cmd.c index 5d2b32c2c2..954667c64a 100644 --- a/aircraft_cmd.c +++ b/aircraft_cmd.c @@ -382,6 +382,10 @@ int32 CmdStartStopAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT); if (flags & DC_EXEC) { + if (v->vehstatus & VS_STOPPED && IsAircraftHangarTile(v->tile)) { + DeleteVehicleNews(p1, STR_A014_AIRCRAFT_IS_WAITING_IN); + } + v->vehstatus ^= VS_STOPPED; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); diff --git a/news.h b/news.h index 736542eaed..d90cb4df2c 100644 --- a/news.h +++ b/news.h @@ -73,4 +73,11 @@ enum { DNC_BANKRUPCY = 4, }; +/** + * Delete a news item type about a vehicle + * if the news item type is INVALID_STRING_ID all news about the vehicle get + * deleted + */ +void DeleteVehicleNews(VehicleID, StringID news); + #endif /* NEWS_H */ diff --git a/news_gui.c b/news_gui.c index 5d484436cd..1354983ec0 100644 --- a/news_gui.c +++ b/news_gui.c @@ -865,3 +865,37 @@ void ShowMessageOptions(void) DeleteWindowById(WC_GAME_OPTIONS, 0); AllocateWindowDesc(&_message_options_desc); } + + +void DeleteVehicleNews(VehicleID vid, StringID news) +{ + byte n; + + for (n = _oldest_news; _latest_news != INVALID_NEWS && n != _latest_news + 1; n = (n + 1) % MAX_NEWS) { + const NewsItem* ni = &_news_items[n]; + + if (ni->flags & NF_VEHICLE && + ni->data_a == vid && + (news == INVALID_STRING_ID || ni->string_id == news)) { + Window* w; + byte i; + + if (_forced_news == n) MoveToNexItem(); + if (_current_news == n) MoveToNexItem(); + + // If this is the last news item, invalidate _latest_news + if (_latest_news == _oldest_news) _latest_news = INVALID_NEWS; + + for (i = n; i != _oldest_news; i = (i + MAX_NEWS - 1) % MAX_NEWS) { + _news_items[i] = _news_items[(i + MAX_NEWS - 1) % MAX_NEWS]; + } + _oldest_news = (_oldest_news + 1) % MAX_NEWS; + _total_news--; + + w = FindWindowById(WC_MESSAGE_HISTORY, 0); + if (w == NULL) return; + SetWindowDirty(w); + w->vscroll.count = _total_news; + } + } +} diff --git a/order_cmd.c b/order_cmd.c index 22770eac4d..c0b950952a 100644 --- a/order_cmd.c +++ b/order_cmd.c @@ -143,6 +143,22 @@ void AssignOrder(Order *order, Order data) order->station = data.station; } + +/** + * Delete all news items regarding defective orders about a vehicle + * This could kill still valid warnings (for example about void order when just + * another order gets added), but assume the player will notice the problems, + * when (s)he's changing the orders. + */ +static void DeleteOrderWarnings(const Vehicle* v) +{ + DeleteVehicleNews(v->index, STR_TRAIN_HAS_TOO_FEW_ORDERS + (v->type - VEH_Train) * 4); + DeleteVehicleNews(v->index, STR_TRAIN_HAS_VOID_ORDER + (v->type - VEH_Train) * 4); + DeleteVehicleNews(v->index, STR_TRAIN_HAS_DUPLICATE_ENTRY + (v->type - VEH_Train) * 4); + DeleteVehicleNews(v->index, STR_TRAIN_HAS_INVALID_ENTRY + (v->type - VEH_Train) * 4); +} + + /** Add an order to the orderlist of a vehicle. * @param x,y unused * @param p1 various bitstuffed elements @@ -366,7 +382,9 @@ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) } } - for (u = GetFirstVehicleFromSharedList(v); u != NULL; u = u->next_shared) { + u = GetFirstVehicleFromSharedList(v); + DeleteOrderWarnings(u); + for (; u != NULL; u = u->next_shared) { /* Increase amount of orders */ u->num_orders++; @@ -451,7 +469,9 @@ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) order->type = OT_NOTHING; order->next = NULL; - for (u = GetFirstVehicleFromSharedList(v); u != NULL; u = u->next_shared) { + u = GetFirstVehicleFromSharedList(v); + DeleteOrderWarnings(u); + for (; u != NULL; u = u->next_shared) { u->num_orders--; if (sel_ord < u->cur_order_index) @@ -575,7 +595,9 @@ int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle* u; - for (u = GetFirstVehicleFromSharedList(v); u != NULL; u = u->next_shared) { + u = GetFirstVehicleFromSharedList(v); + DeleteOrderWarnings(u); + for (; u != NULL; u = u->next_shared) { /* toggle u->current_order "Full load" flag if it changed */ if (sel_ord == u->cur_order_index && HASBIT(u->current_order.flags, OFB_FULL_LOAD) != HASBIT(order->flags, OFB_FULL_LOAD)) { @@ -1006,6 +1028,8 @@ void DeleteVehicleOrders(Vehicle *v) { Order *order, *cur; + DeleteOrderWarnings(v); + /* If we have a shared order-list, don't delete the list, but just remove our pointer */ if (IsOrderListShared(v)) { diff --git a/roadveh_cmd.c b/roadveh_cmd.c index a40801a974..b12debae45 100644 --- a/roadveh_cmd.c +++ b/roadveh_cmd.c @@ -216,6 +216,10 @@ int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR; if (flags & DC_EXEC) { + if (v->vehstatus & VS_STOPPED && v->u.road.state == 254) { + DeleteVehicleNews(p1, STR_9016_ROAD_VEHICLE_IS_WAITING); + } + v->vehstatus ^= VS_STOPPED; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); diff --git a/ship_cmd.c b/ship_cmd.c index 651239286f..82bedb3f8c 100644 --- a/ship_cmd.c +++ b/ship_cmd.c @@ -951,6 +951,10 @@ int32 CmdStartStopShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (v->type != VEH_Ship || !CheckOwnership(v->owner)) return CMD_ERROR; if (flags & DC_EXEC) { + if (v->vehstatus & VS_STOPPED && v->u.ship.state == 0x80) { + DeleteVehicleNews(p1, STR_981C_SHIP_IS_WAITING_IN_DEPOT); + } + v->vehstatus ^= VS_STOPPED; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); diff --git a/train_cmd.c b/train_cmd.c index 4ab3628218..cf2450bc29 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -1176,6 +1176,10 @@ int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR; if (flags & DC_EXEC) { + if (v->vehstatus & VS_STOPPED && v->u.rail.track == 0x80) { + DeleteVehicleNews(p1, STR_8814_TRAIN_IS_WAITING_IN_DEPOT); + } + v->u.rail.days_since_order_progr = 0; v->vehstatus ^= VS_STOPPED; InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); diff --git a/vehicle.c b/vehicle.c index f6543c84a6..a368c5d4b8 100644 --- a/vehicle.c +++ b/vehicle.c @@ -536,6 +536,8 @@ void DeleteVehicle(Vehicle *v) Vehicle *u; bool has_artic_part = false; + DeleteVehicleNews(v->index, INVALID_STRING_ID); + do { u = v->next; has_artic_part = EngineHasArticPart(v);