00001
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 int delta;
00021
00022 if (is_journey) {
00023 delta = time - order->travel_time;
00024 order->travel_time = time;
00025 } else {
00026 delta = time - order->wait_time;
00027 order->wait_time = time;
00028 }
00029 v->orders.list->UpdateOrderTimetable(delta);
00030
00031 for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
00032 if (v->cur_order_index == order_number && v->current_order.Equals(*order)) {
00033 if (is_journey) {
00034 v->current_order.travel_time = time;
00035 } else {
00036 v->current_order.wait_time = time;
00037 }
00038 }
00039 InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
00040 }
00041 }
00042
00058 CommandCost CmdChangeTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
00059 {
00060 if (!_settings_game.order.timetabling) return CMD_ERROR;
00061
00062 VehicleID veh = GB(p1, 0, 16);
00063 if (!IsValidVehicleID(veh)) return CMD_ERROR;
00064
00065 Vehicle *v = GetVehicle(veh);
00066 if (!CheckOwnership(v->owner)) return CMD_ERROR;
00067
00068 VehicleOrderID order_number = GB(p1, 16, 8);
00069 Order *order = GetVehicleOrder(v, order_number);
00070 if (order == NULL) return CMD_ERROR;
00071
00072 bool packed_time = HasBit(p1, 25);
00073 bool is_journey = HasBit(p1, 24) || packed_time;
00074
00075 int wait_time = order->wait_time;
00076 int travel_time = order->travel_time;
00077 if (packed_time) {
00078 travel_time = GB(p2, 0, 16);
00079 wait_time = GB(p2, 16, 16);;
00080 } else if (is_journey) {
00081 travel_time = GB(p2, 0, 16);
00082 } else {
00083 wait_time = GB(p2, 0, 16);
00084 }
00085
00086 if (wait_time != order->wait_time) {
00087 switch (order->GetType()) {
00088 case OT_GOTO_STATION:
00089 if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_TIMETABLE_NOT_STOPPING_HERE);
00090 break;
00091
00092 case OT_CONDITIONAL:
00093 break;
00094
00095 default: return_cmd_error(STR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
00096 }
00097 }
00098
00099 if (travel_time != order->travel_time && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
00100
00101 if (flags & DC_EXEC) {
00102 if (wait_time != order->wait_time) ChangeTimetable(v, order_number, wait_time, false);
00103 if (travel_time != order->travel_time) ChangeTimetable(v, order_number, travel_time, true);
00104 }
00105
00106 return CommandCost();
00107 }
00108
00116 CommandCost CmdSetVehicleOnTime(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
00117 {
00118 if (!_settings_game.order.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 v->lateness_counter = 0;
00128 }
00129
00130 return CommandCost();
00131 }
00132
00144 CommandCost CmdAutofillTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
00145 {
00146 if (!_settings_game.order.timetabling) return CMD_ERROR;
00147
00148 VehicleID veh = GB(p1, 0, 16);
00149 if (!IsValidVehicleID(veh)) return CMD_ERROR;
00150
00151 Vehicle *v = GetVehicle(veh);
00152 if (!CheckOwnership(v->owner)) return CMD_ERROR;
00153
00154 if (flags & DC_EXEC) {
00155 if (HasBit(p2, 0)) {
00156
00157
00158 SetBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00159 ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00160
00161 if (HasBit(p2, 1)) SetBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00162
00163 v->lateness_counter = 0;
00164 } else {
00165 ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00166 ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00167 }
00168 }
00169
00170 for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
00171 InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
00172 }
00173
00174 return CommandCost();
00175 }
00176
00177 void UpdateVehicleTimetable(Vehicle *v, bool travelling)
00178 {
00179 uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time;
00180 uint time_taken = v->current_order_time;
00181
00182 v->current_order_time = 0;
00183
00184 if (!_settings_game.order.timetabling) return;
00185
00186 bool just_started = false;
00187
00188
00189
00190 if (v->cur_order_index == 0 && !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) {
00191 SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
00192 just_started = true;
00193 }
00194
00195 if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
00196
00197 if (HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) {
00198 if (travelling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) {
00199
00200 v->current_order.wait_time = 0;
00201 }
00202
00203 if (just_started) return;
00204
00205
00206
00207 if (!v->current_order.IsType(OT_CONDITIONAL) && (travelling || time_taken > v->current_order.wait_time)) {
00208
00209
00210
00211 time_taken = (((time_taken - 1) / DAY_TICKS) + 1) * DAY_TICKS;
00212
00213 ChangeTimetable(v, v->cur_order_index, time_taken, travelling);
00214 }
00215
00216 if (v->cur_order_index == 0 && travelling) {
00217
00218
00219
00220 ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
00221 ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
00222 }
00223 return;
00224 }
00225
00226 if (just_started) return;
00227
00228
00229
00230
00231 if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
00232
00233 v->lateness_counter -= (timetabled - time_taken);
00234
00235 for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
00236 InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
00237 }
00238 }