/** * Change/update a particular timetable entry. * @param v The vehicle to change the timetable of. * @param order_number The index of the timetable in the order list. * @param val The new data of the timetable entry. * @param mtf Which part of the timetable entry to change. * @param timetabled If the new value is explicitly timetabled. */ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val, ModifyTimetableFlags mtf, bool timetabled) { Order *order = v->GetOrder(order_number); int total_delta = 0; int timetable_delta = 0; switch (mtf) { case MTF_WAIT_TIME: total_delta = val - order->GetWaitTime(); timetable_delta = (timetabled ? val : 0) - order->GetTimetabledWait(); order->SetWaitTime(val); order->SetWaitTimetabled(timetabled); break; case MTF_TRAVEL_TIME: total_delta = val - order->GetTravelTime(); timetable_delta = (timetabled ? val : 0) - order->GetTimetabledTravel(); order->SetTravelTime(val); order->SetTravelTimetabled(timetabled); break; case MTF_TRAVEL_SPEED: order->SetMaxSpeed(val); break; default: NOT_REACHED(); } v->orders.list->UpdateTotalDuration(total_delta); v->orders.list->UpdateTimetableDuration(timetable_delta); for (v = v->FirstShared(); v != NULL; v = v->NextShared()) { if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) { switch (mtf) { case MTF_WAIT_TIME: v->current_order.SetWaitTime(val); v->current_order.SetWaitTimetabled(timetabled); break; case MTF_TRAVEL_TIME: v->current_order.SetTravelTime(val); v->current_order.SetTravelTimetabled(timetabled); break; case MTF_TRAVEL_SPEED: v->current_order.SetMaxSpeed(val); break; default: NOT_REACHED(); } } SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index); } }
/** * Change timetable data of an order. * @param tile Not used. * @param flags Operation to perform. * @param p1 Various bitstuffed elements * - p1 = (bit 0-19) - Vehicle with the orders to change. * - p1 = (bit 20-27) - Order index to modify. * - p1 = (bit 28-29) - Timetable data to change (@see ModifyTimetableFlags) * @param p2 The amount of time to wait. * - p2 = (bit 0-15) - The data to modify as specified by p1 bits 28-29. * 0 to clear times, UINT16_MAX to clear speed limit. * @param text unused * @return the cost of this operation or an error */ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleID veh = GB(p1, 0, 20); Vehicle *v = Vehicle::GetIfValid(veh); if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR; CommandCost ret = CheckOwnership(v->owner); if (ret.Failed()) return ret; VehicleOrderID order_number = GB(p1, 20, 8); Order *order = v->GetOrder(order_number); if (order == NULL || order->IsType(OT_IMPLICIT)) return CMD_ERROR; ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 2>(p1); if (mtf >= MTF_END) return CMD_ERROR; int wait_time = order->GetWaitTime(); int travel_time = order->GetTravelTime(); int max_speed = order->GetMaxSpeed(); switch (mtf) { case MTF_WAIT_TIME: wait_time = GB(p2, 0, 16); break; case MTF_TRAVEL_TIME: travel_time = GB(p2, 0, 16); break; case MTF_TRAVEL_SPEED: max_speed = GB(p2, 0, 16); if (max_speed == 0) max_speed = UINT16_MAX; // Disable speed limit. break; default: NOT_REACHED(); } if (wait_time != order->GetWaitTime()) { switch (order->GetType()) { case OT_GOTO_STATION: if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE); break; case OT_CONDITIONAL: break; default: return_cmd_error(STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS); } } if (travel_time != order->GetTravelTime() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR; if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR; if (flags & DC_EXEC) { switch (mtf) { case MTF_WAIT_TIME: /* Set time if changing the value or confirming an estimated time as timetabled. */ if (wait_time != order->GetWaitTime() || (wait_time > 0 && !order->IsWaitTimetabled())) { ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME, wait_time > 0); } break; case MTF_TRAVEL_TIME: /* Set time if changing the value or confirming an estimated time as timetabled. */ if (travel_time != order->GetTravelTime() || (travel_time > 0 && !order->IsTravelTimetabled())) { ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME, travel_time > 0); } break; case MTF_TRAVEL_SPEED: if (max_speed != order->GetMaxSpeed()) { ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED, max_speed != UINT16_MAX); } break; default: break; } } return CommandCost(); }