00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "command_func.h"
00014 #include "company_func.h"
00015 #include "date_func.h"
00016 #include "window_func.h"
00017 #include "vehicle_base.h"
00018
00019 #include "table/strings.h"
00020
00028 static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time, bool is_journey)
00029 {
00030 Order *order = v->GetOrder(order_number);
00031 int delta;
00032
00033 if (is_journey) {
00034 delta = time - order->travel_time;
00035 order->travel_time = time;
00036 } else {
00037 delta = time - order->wait_time;
00038 order->wait_time = time;
00039 }
00040 v->orders.list->UpdateOrderTimetable(delta);
00041
00042 for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
00043 if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
00044 if (is_journey) {
00045 v->current_order.travel_time = time;
00046 } else {
00047 v->current_order.wait_time = time;
00048 }
00049 }
00050 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00051 }
00052 }
00053
00068 CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00069 {
00070 VehicleID veh = GB(p1, 0, 20);
00071
00072 Vehicle *v = Vehicle::GetIfValid(veh);
00073 if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
00074
00075 CommandCost ret = CheckOwnership(v->owner);
00076 if (ret.Failed()) return ret;
00077
00078 VehicleOrderID order_number = GB(p1, 20, 8);
00079 Order *order = v->GetOrder(order_number);
00080 if (order == NULL || order->IsType(OT_IMPLICIT)) return CMD_ERROR;
00081
00082 bool is_journey = HasBit(p1, 28);
00083
00084 int wait_time = order->wait_time;
00085 int travel_time = order->travel_time;
00086 if (is_journey) {
00087 travel_time = GB(p2, 0, 16);
00088 } else {
00089 wait_time = GB(p2, 0, 16);
00090 }
00091
00092 if (wait_time != order->wait_time) {
00093 switch (order->GetType()) {
00094 case OT_GOTO_STATION:
00095 if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
00096 break;
00097
00098 case OT_CONDITIONAL:
00099 break;
00100
00101 default: return_cmd_error(STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
00102 }
00103 }
00104
00105 if (travel_time != order->travel_time && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
00106
00107 if (flags & DC_EXEC) {
00108 if (wait_time != order->wait_time) ChangeTimetable(v, order_number, wait_time, false);
00109 if (travel_time != order->travel_time) ChangeTimetable(v, order_number, travel_time, true);
00110 }
00111
00112 return CommandCost();
00113 }
00114
00125 CommandCost CmdSetVehicleOnTime(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00126 {
00127 VehicleID veh = GB(p1, 0, 20);
00128
00129 Vehicle *v = Vehicle::GetIfValid(veh);
00130 if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
00131
00132 CommandCost ret = CheckOwnership(v->owner);
00133 if (ret.Failed()) return ret;
00134
00135 if (flags & DC_EXEC) {
00136 v->lateness_counter = 0;
00137 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00138 }
00139
00140 return CommandCost();
00141 }
00142
00152 CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00153 {
00154 Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20));
00155 if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
00156
00157 CommandCost ret = CheckOwnership(v->owner);
00158 if (ret.Failed()) return ret;
00159
00160
00161 Date start_date = (Date)p2;
00162 if (start_date < 0 || start_date > MAX_DAY) return CMD_ERROR;
00163 if (start_date - _date > 15 * DAYS_IN_LEAP_YEAR) return CMD_ERROR;
00164 if (_date - start_date > DAYS_IN_LEAP_YEAR) return CMD_ERROR;
00165
00166 if (flags & DC_EXEC) {
00167 v->lateness_counter = 0;
00168 ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00169 v->timetable_start = start_date;
00170
00171 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00172 }
00173
00174 return CommandCost();
00175 }
00176
00177
00191 CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00192 {
00193 VehicleID veh = GB(p1, 0, 20);
00194
00195 Vehicle *v = Vehicle::GetIfValid(veh);
00196 if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
00197
00198 CommandCost ret = CheckOwnership(v->owner);
00199 if (ret.Failed()) return ret;
00200
00201 if (flags & DC_EXEC) {
00202 if (HasBit(p2, 0)) {
00203
00204
00205
00206 SetBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00207 ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00208
00209
00210 if (HasBit(p2, 1)) SetBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00211
00212 v->timetable_start = 0;
00213 v->lateness_counter = 0;
00214 } else {
00215 ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00216 ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00217 }
00218
00219 for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
00220 if (v2 != v) {
00221
00222 ClrBit(v2->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00223 ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00224 }
00225 SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
00226 }
00227 }
00228
00229 return CommandCost();
00230 }
00231
00237 void UpdateVehicleTimetable(Vehicle *v, bool travelling)
00238 {
00239 uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time;
00240 uint time_taken = v->current_order_time;
00241
00242 v->current_order_time = 0;
00243
00244 if (v->current_order.IsType(OT_IMPLICIT)) return;
00245
00246 VehicleOrderID first_manual_order = 0;
00247 for (Order *o = v->GetFirstOrder(); o != NULL && o->IsType(OT_IMPLICIT); o = o->next) {
00248 ++first_manual_order;
00249 }
00250
00251 bool just_started = false;
00252
00253
00254 if (v->cur_real_order_index == first_manual_order && travelling) {
00255
00256
00257
00258
00259 just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00260
00261 if (v->timetable_start != 0) {
00262 v->lateness_counter = (_date - v->timetable_start) * DAY_TICKS + _date_fract;
00263 v->timetable_start = 0;
00264 }
00265
00266 SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00267 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00268 }
00269
00270 if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
00271
00272 if (HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) {
00273 if (travelling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) {
00274
00275 v->current_order.wait_time = 0;
00276 }
00277
00278 if (just_started) return;
00279
00280
00281
00282 if (!v->current_order.IsType(OT_CONDITIONAL) && (travelling || time_taken > v->current_order.wait_time)) {
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 time_taken = CeilDiv(max(time_taken, 1U), DAY_TICKS) * DAY_TICKS;
00293
00294 ChangeTimetable(v, v->cur_real_order_index, time_taken, travelling);
00295 }
00296
00297 if (v->cur_real_order_index == first_manual_order && travelling) {
00298
00299
00300
00301 ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00302 ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00303 }
00304 return;
00305 }
00306
00307 if (just_started) return;
00308
00309
00310
00311
00312 if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
00313
00314 v->lateness_counter -= (timetabled - time_taken);
00315
00316
00317
00318
00319
00320
00321 if (v->lateness_counter > (int)timetabled) {
00322 Ticks cycle = v->orders.list->GetTimetableTotalDuration();
00323 if (cycle != INVALID_TICKS && v->lateness_counter > cycle) {
00324 v->lateness_counter %= cycle;
00325 }
00326 }
00327
00328 for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
00329 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00330 }
00331 }