# timetable_cmd.cpp

Go to the documentation of this file.

    00001 /* $Id: timetable_cmd.cpp 14268 2008-09-07 22:04:39Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "variables.h"
    00008 #include "command_func.h"
    00009 #include "functions.h"
    00010 #include "window_func.h"
    00011 #include "vehicle_func.h"
    00012 #include "vehicle_base.h"
    00013 #include "settings_type.h"
    00014
    00015 #include "table/strings.h"
    00016
    00017 static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time, bool is_journey)
    00018 {
    00019   Order *order = GetVehicleOrder(v, order_number);
    00020
    00021   if (is_journey) {
    00022     order->travel_time = time;
    00023   } else {
    00024     order->wait_time = time;
    00025   }
    00026
    00027   for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) {
    00028     if (v->cur_order_index == order_number && HasBit(v->current_order.flags, OF_PART_OF_ORDERS)) {
    00029       if (is_journey) {
    00030         v->current_order.travel_time = time;
    00031       } else {
    00032         v->current_order.wait_time = time;
    00033       }
    00034     }
    00035     InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
    00036   }
    00037 }
    00038
    00054 CommandCost CmdChangeTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00055 {
    00056   if (!_patches.timetabling) return CMD_ERROR;
    00057
    00058   VehicleID veh = GB(p1, 0, 16);
    00059   if (!IsValidVehicleID(veh)) return CMD_ERROR;
    00060
    00061   Vehicle *v = GetVehicle(veh);
    00062   if (!CheckOwnership(v->owner)) return CMD_ERROR;
    00063
    00064   VehicleOrderID order_number = GB(p1, 16, 8);
    00065   Order *order = GetVehicleOrder(v, order_number);
    00066   if (order == NULL) return CMD_ERROR;
    00067
    00068   bool packed_time = HasBit(p1, 25);
    00069   bool is_journey = HasBit(p1, 24) || packed_time;
    00070   if (!is_journey) {
    00071     if (order->type != OT_GOTO_STATION) return_cmd_error(STR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
    00072     if (_patches.new_nonstop && (order->flags & OFB_NON_STOP)) return_cmd_error(STR_TIMETABLE_NOT_STOPPING_HERE);
    00073   }
    00074
    00075   if (flags & DC_EXEC) {
    00076     ChangeTimetable(v, order_number, GB(p2, 0, 16), is_journey);
    00077     if (packed_time) ChangeTimetable(v, order_number, GB(p2, 16, 16), false);
    00078   }
    00079
    00080   return CommandCost();
    00081 }
    00082
    00090 CommandCost CmdSetVehicleOnTime(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00091 {
    00092   if (!_patches.timetabling) return CMD_ERROR;
    00093
    00094   VehicleID veh = GB(p1, 0, 16);
    00095   if (!IsValidVehicleID(veh)) return CMD_ERROR;
    00096
    00097   Vehicle *v = GetVehicle(veh);
    00098   if (!CheckOwnership(v->owner)) return CMD_ERROR;
    00099
    00100   if (flags & DC_EXEC) {
    00101     v->lateness_counter = 0;
    00102   }
    00103
    00104   return CommandCost();
    00105 }
    00106
    00116 CommandCost CmdAutofillTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00117 {
    00118   if (!_patches.timetabling) return CMD_ERROR;
    00119
    00120   VehicleID veh = GB(p1, 0, 16);
    00121   if (!IsValidVehicleID(veh)) return CMD_ERROR;
    00122
    00123   Vehicle *v = GetVehicle(veh);
    00124   if (!CheckOwnership(v->owner)) return CMD_ERROR;
    00125
    00126   if (flags & DC_EXEC) {
    00127     if (p2 == 1) {
    00128       /* Start autofilling the timetable, which clears all the current
    00129        * timings and clears the "timetable has started" bit. */
    00130       SetBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
    00131       ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
    00132
    00133       for (Order *order = GetVehicleOrder(v, 0); order != NULL; order = order->next) {
    00134         order->wait_time = 0;
    00135         order->travel_time = 0;
    00136       }
    00137
    00138       v->current_order.wait_time = 0;
    00139       v->current_order.travel_time = 0;
    00140     } else {
    00141       ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
    00142     }
    00143   }
    00144
    00145   for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) {
    00146     InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
    00147   }
    00148
    00149   return CommandCost();
    00150 }
    00151
    00152 void UpdateVehicleTimetable(Vehicle *v, bool travelling)
    00153 {
    00154   uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time;
    00155   uint time_taken = v->current_order_time;
    00156
    00157   v->current_order_time = 0;
    00158
    00159   if (!_patches.timetabling) return;
    00160
    00161   /* Make sure the timetable only starts when the vehicle reaches the first
    00162    * order, not when travelling from the depot to the first station. */
    00163   if (v->cur_order_index == 0 && !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) {
    00164     SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
    00165     return;
    00166   }
    00167
    00168   if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
    00169
    00170   if (HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) {
    00171     if (timetabled == 0) {
    00172       /* Round the time taken up to the nearest day, as this will avoid
    00173        * confusion for people who are timetabling in days, and can be
    00174        * adjusted later by people who aren't. */
    00175       time_taken = (((time_taken - 1) / DAY_TICKS) + 1) * DAY_TICKS;
    00176
    00177       ChangeTimetable(v, v->cur_order_index, time_taken, travelling);
    00178       return;
    00179     } else if (v->cur_order_index == 0) {
    00180       /* Otherwise if we're at the beginning and it already has a value,
    00181        * assume that autofill is finished and turn it off again. */
    00182       ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
    00183     }
    00184   }
    00185
    00186   /* Vehicles will wait at stations if they arrive early even if they are not
    00187    * timetabled to wait there, so make sure the lateness counter is updated
    00188    * when this happens. */
    00189   if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
    00190
    00191   v->lateness_counter -= (timetabled - time_taken);
    00192
    00193   for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) {
    00194     InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
    00195   }
    00196 }