6 #include "openttd.h" |
6 #include "openttd.h" |
7 #include "functions.h" |
7 #include "functions.h" |
8 #include "variables.h" |
8 #include "variables.h" |
9 #include "table/strings.h" |
9 #include "table/strings.h" |
10 #include "command.h" |
10 #include "command.h" |
|
11 #include "date.h" |
|
12 #include "player.h" |
11 #include "vehicle.h" |
13 #include "vehicle.h" |
12 |
14 |
|
15 |
|
16 static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time, bool is_journey) |
|
17 { |
|
18 Order *order = GetVehicleOrder(v, order_number); |
|
19 |
|
20 if (is_journey) { |
|
21 order->travel_time = time; |
|
22 } else { |
|
23 order->wait_time = time; |
|
24 } |
|
25 |
|
26 if (v->cur_order_index == order_number && HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) { |
|
27 if (is_journey) { |
|
28 v->current_order.travel_time = time; |
|
29 } else { |
|
30 v->current_order.wait_time = time; |
|
31 } |
|
32 } |
|
33 |
|
34 InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index); |
|
35 } |
13 |
36 |
14 /** |
37 /** |
15 * Add or remove waiting times from an order. |
38 * Add or remove waiting times from an order. |
16 * @param tile Not used. |
39 * @param tile Not used. |
17 * @param flags Operation to perform. |
40 * @param flags Operation to perform. |
41 if (order->type != OT_GOTO_STATION) return_cmd_error(STR_TIMETABLE_ONLY_WAIT_AT_STATIONS); |
64 if (order->type != OT_GOTO_STATION) return_cmd_error(STR_TIMETABLE_ONLY_WAIT_AT_STATIONS); |
42 if (_patches.new_nonstop && (order->flags & OF_NON_STOP)) return_cmd_error(STR_TIMETABLE_NOT_STOPPING_HERE); |
65 if (_patches.new_nonstop && (order->flags & OF_NON_STOP)) return_cmd_error(STR_TIMETABLE_NOT_STOPPING_HERE); |
43 } |
66 } |
44 |
67 |
45 if (flags & DC_EXEC) { |
68 if (flags & DC_EXEC) { |
46 if (is_journey) { |
69 ChangeTimetable(v, order_number, p2, is_journey); |
47 order->travel_time = p2; |
|
48 } else { |
|
49 order->wait_time = p2; |
|
50 } |
|
51 |
|
52 if (v->cur_order_index == order_number && HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) { |
|
53 if (is_journey) { |
|
54 v->current_order.travel_time = p2; |
|
55 } else { |
|
56 v->current_order.wait_time = p2; |
|
57 } |
|
58 } |
|
59 |
|
60 InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index); |
|
61 } |
70 } |
62 |
71 |
63 return CommandCost(); |
72 return CommandCost(); |
64 } |
73 } |
65 |
74 |
85 } |
94 } |
86 |
95 |
87 return CommandCost(); |
96 return CommandCost(); |
88 } |
97 } |
89 |
98 |
|
99 /** |
|
100 * Start or stop filling the timetable automatically from the time the vehicle |
|
101 * actually takes to complete it. When starting to autofill the current times |
|
102 * are cleared and the timetable will start again from scratch. |
|
103 * @param tile Not used. |
|
104 * @param flags Operation to perform. |
|
105 * @param p1 Vehicle index. |
|
106 * @param p2 Set to 1 to enable, 0 to disable. |
|
107 */ |
|
108 CommandCost CmdAutofillTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
|
109 { |
|
110 if (!_patches.timetabling) return CMD_ERROR; |
|
111 |
|
112 VehicleID veh = GB(p1, 0, 16); |
|
113 if (!IsValidVehicleID(veh)) return CMD_ERROR; |
|
114 |
|
115 Vehicle *v = GetVehicle(veh); |
|
116 if (!CheckOwnership(v->owner)) return CMD_ERROR; |
|
117 |
|
118 if (flags & DC_EXEC) { |
|
119 if (p2 == 1) { |
|
120 /* Start autofilling the timetable, which clears all the current |
|
121 * timings and clears the "timetable has started" bit. */ |
|
122 SETBIT(v->vehicle_flags, VF_AUTOFILL_TIMETABLE); |
|
123 CLRBIT(v->vehicle_flags, VF_TIMETABLE_STARTED); |
|
124 |
|
125 for (Order *order = GetVehicleOrder(v, 0); order != NULL; order = order->next) { |
|
126 order->wait_time = 0; |
|
127 order->travel_time = 0; |
|
128 } |
|
129 |
|
130 v->current_order.wait_time = 0; |
|
131 v->current_order.travel_time = 0; |
|
132 } else { |
|
133 CLRBIT(v->vehicle_flags, VF_AUTOFILL_TIMETABLE); |
|
134 } |
|
135 } |
|
136 |
|
137 return CommandCost(); |
|
138 } |
90 |
139 |
91 void UpdateVehicleTimetable(Vehicle *v, bool travelling) |
140 void UpdateVehicleTimetable(Vehicle *v, bool travelling) |
92 { |
141 { |
93 uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time; |
142 uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time; |
94 uint time_taken = v->current_order_time; |
143 uint time_taken = v->current_order_time; |
95 |
144 |
96 v->current_order_time = 0; |
145 v->current_order_time = 0; |
97 |
146 |
|
147 if (!_patches.timetabling) return; |
|
148 |
|
149 /* Make sure the timetable only starts when the vehicle reaches the first |
|
150 * order, not when travelling from the depot to the first station. */ |
|
151 if (v->cur_order_index == 0 && !HASBIT(v->vehicle_flags, VF_TIMETABLE_STARTED)) { |
|
152 SETBIT(v->vehicle_flags, VF_TIMETABLE_STARTED); |
|
153 return; |
|
154 } |
|
155 |
|
156 if (!HASBIT(v->vehicle_flags, VF_TIMETABLE_STARTED)) return; |
|
157 |
|
158 if (HASBIT(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) { |
|
159 if (timetabled == 0) { |
|
160 /* Round the time taken up to the nearest day, as this will avoid |
|
161 * confusion for people who are timetabling in days, and can be |
|
162 * adjusted later by people who aren't. */ |
|
163 time_taken = (((time_taken - 1) / DAY_TICKS) + 1) * DAY_TICKS; |
|
164 |
|
165 ChangeTimetable(v, v->cur_order_index, time_taken, travelling); |
|
166 return; |
|
167 } else if (v->cur_order_index == 0) { |
|
168 /* Otherwise if we're at the beginning and it already has a value, |
|
169 * assume that autofill is finished and turn it off again. */ |
|
170 CLRBIT(v->vehicle_flags, VF_AUTOFILL_TIMETABLE); |
|
171 } |
|
172 } |
|
173 |
98 /* Vehicles will wait at stations if they arrive early even if they are not |
174 /* Vehicles will wait at stations if they arrive early even if they are not |
99 * timetabled to wait there, so make sure the lateness counter is updated |
175 * timetabled to wait there, so make sure the lateness counter is updated |
100 * when this happens. */ |
176 * when this happens. */ |
101 if (!_patches.timetabling || (timetabled == 0 && (travelling || v->lateness_counter >= 0))) return; |
177 if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return; |
102 |
178 |
103 v->lateness_counter -= (timetabled - time_taken); |
179 v->lateness_counter -= (timetabled - time_taken); |
104 |
180 |
105 InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index); |
181 InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index); |
106 } |
182 } |