00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "command_func.h"
00014 #include "functions.h"
00015 #include "date_func.h"
00016 #include "window_func.h"
00017 #include "vehicle_base.h"
00018
00019 #include "table/strings.h"
00020
00021 static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time, bool is_journey)
00022 {
00023 Order *order = v->GetOrder(order_number);
00024 int delta;
00025
00026 if (is_journey) {
00027 delta = time - order->travel_time;
00028 order->travel_time = time;
00029 } else {
00030 delta = time - order->wait_time;
00031 order->wait_time = time;
00032 }
00033 v->orders.list->UpdateOrderTimetable(delta);
00034
00035 for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
00036 if (v->cur_order_index == order_number && v->current_order.Equals(*order)) {
00037 if (is_journey) {
00038 v->current_order.travel_time = time;
00039 } else {
00040 v->current_order.wait_time = time;
00041 }
00042 }
00043 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00044 }
00045 }
00046
00064 CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00065 {
00066 if (!_settings_game.order.timetabling) return CMD_ERROR;
00067
00068 VehicleID veh = GB(p1, 0, 16);
00069
00070 Vehicle *v = Vehicle::GetIfValid(veh);
00071 if (v == NULL || !CheckOwnership(v->owner) || !v->IsPrimaryVehicle()) return CMD_ERROR;
00072
00073 VehicleOrderID order_number = GB(p1, 16, 8);
00074 Order *order = v->GetOrder(order_number);
00075 if (order == NULL) return CMD_ERROR;
00076
00077 bool packed_time = HasBit(p1, 25);
00078 bool is_journey = HasBit(p1, 24) || packed_time;
00079
00080 int wait_time = order->wait_time;
00081 int travel_time = order->travel_time;
00082 if (packed_time) {
00083 travel_time = GB(p2, 0, 16);
00084 wait_time = GB(p2, 16, 16);
00085 } else if (is_journey) {
00086 travel_time = GB(p2, 0, 16);
00087 } else {
00088 wait_time = GB(p2, 0, 16);
00089 }
00090
00091 if (wait_time != order->wait_time) {
00092 switch (order->GetType()) {
00093 case OT_GOTO_STATION:
00094 if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
00095 break;
00096
00097 case OT_CONDITIONAL:
00098 break;
00099
00100 default: return_cmd_error(STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
00101 }
00102 }
00103
00104 if (travel_time != order->travel_time && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
00105
00106 if (flags & DC_EXEC) {
00107 if (wait_time != order->wait_time) ChangeTimetable(v, order_number, wait_time, false);
00108 if (travel_time != order->travel_time) ChangeTimetable(v, order_number, travel_time, true);
00109 }
00110
00111 return CommandCost();
00112 }
00113
00124 CommandCost CmdSetVehicleOnTime(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00125 {
00126 if (!_settings_game.order.timetabling) return CMD_ERROR;
00127
00128 VehicleID veh = GB(p1, 0, 16);
00129
00130 Vehicle *v = Vehicle::GetIfValid(veh);
00131 if (v == NULL || !CheckOwnership(v->owner) || !v->IsPrimaryVehicle()) return CMD_ERROR;
00132
00133 if (flags & DC_EXEC) {
00134 v->lateness_counter = 0;
00135 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00136 }
00137
00138 return CommandCost();
00139 }
00140
00148 CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00149 {
00150 if (!_settings_game.order.timetabling) return CMD_ERROR;
00151
00152 Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 16));
00153 if (v == NULL || !CheckOwnership(v->owner) || !v->IsPrimaryVehicle()) return CMD_ERROR;
00154
00155
00156 Date start_date = (Date)p2;
00157 if (start_date < 0 || start_date > MAX_DAY) return CMD_ERROR;
00158 if (start_date - _date > 15 * DAYS_IN_LEAP_YEAR) return CMD_ERROR;
00159 if (_date - start_date > DAYS_IN_LEAP_YEAR) return CMD_ERROR;
00160
00161 if (flags & DC_EXEC) {
00162 v->lateness_counter = 0;
00163 ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00164 v->timetable_start = start_date;
00165
00166 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00167 }
00168
00169 return CommandCost();
00170 }
00171
00172
00186 CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00187 {
00188 if (!_settings_game.order.timetabling) return CMD_ERROR;
00189
00190 VehicleID veh = GB(p1, 0, 16);
00191
00192 Vehicle *v = Vehicle::GetIfValid(veh);
00193 if (v == NULL || !CheckOwnership(v->owner) || !v->IsPrimaryVehicle()) return CMD_ERROR;
00194
00195 if (flags & DC_EXEC) {
00196 if (HasBit(p2, 0)) {
00197
00198
00199
00200 SetBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00201 ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00202
00203
00204 if (HasBit(p2, 1)) SetBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00205
00206 v->timetable_start = 0;
00207 v->lateness_counter = 0;
00208 } else {
00209 ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00210 ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00211 }
00212 }
00213
00214 for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
00215 if (v2 != v) {
00216
00217 ClrBit(v2->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00218 ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00219 }
00220 SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
00221 }
00222
00223 return CommandCost();
00224 }
00225
00226 void UpdateVehicleTimetable(Vehicle *v, bool travelling)
00227 {
00228 uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time;
00229 uint time_taken = v->current_order_time;
00230
00231 v->current_order_time = 0;
00232
00233 if (!_settings_game.order.timetabling) return;
00234
00235 bool just_started = false;
00236
00237
00238 if (v->cur_order_index == 0 && travelling) {
00239
00240
00241
00242
00243 just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00244
00245 if (v->timetable_start != 0) {
00246 v->lateness_counter = (_date - v->timetable_start) * DAY_TICKS + _date_fract;
00247 v->timetable_start = 0;
00248 }
00249
00250 SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00251 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00252 }
00253
00254 if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
00255
00256 if (HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) {
00257 if (travelling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) {
00258
00259 v->current_order.wait_time = 0;
00260 }
00261
00262 if (just_started) return;
00263
00264
00265
00266 if (!v->current_order.IsType(OT_CONDITIONAL) && (travelling || time_taken > v->current_order.wait_time)) {
00267
00268
00269
00270 time_taken = (((time_taken - 1) / DAY_TICKS) + 1) * DAY_TICKS;
00271
00272 ChangeTimetable(v, v->cur_order_index, time_taken, travelling);
00273 }
00274
00275 if (v->cur_order_index == 0 && travelling) {
00276
00277
00278
00279 ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00280 ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00281 }
00282 return;
00283 }
00284
00285 if (just_started) return;
00286
00287
00288
00289
00290 if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
00291
00292 v->lateness_counter -= (timetabled - time_taken);
00293
00294 for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
00295 SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00296 }
00297 }