60 } |
61 } |
61 |
62 |
62 /** When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists |
63 /** When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists |
63 * @param type The type of engine |
64 * @param type The type of engine |
64 */ |
65 */ |
65 void AddRemoveEngineFromAutoreplaceAndBuildWindows(byte type) |
66 void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type) |
66 { |
67 { |
67 _rebuild_left_list = false; // left list is only for the vehicles the player owns and is not related to being buildable |
68 _rebuild_left_list = false; // left list is only for the vehicles the player owns and is not related to being buildable |
68 _rebuild_right_list = true; |
69 _rebuild_right_list = true; |
69 InvalidateWindowData(WC_REPLACE_VEHICLE, type); // Update the autoreplace window |
70 InvalidateWindowData(WC_REPLACE_VEHICLE, type); // Update the autoreplace window |
70 InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well |
71 InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well |
148 |
149 |
149 FOR_ALL_ENGINEIDS_OF_TYPE(e, type) { |
150 FOR_ALL_ENGINEIDS_OF_TYPE(e, type) { |
150 if (type == VEH_TRAIN && !GenerateReplaceRailList(e, draw_left, WP(w, replaceveh_d).wagon_btnstate)) continue; // special rules for trains |
151 if (type == VEH_TRAIN && !GenerateReplaceRailList(e, draw_left, WP(w, replaceveh_d).wagon_btnstate)) continue; // special rules for trains |
151 |
152 |
152 if (draw_left) { |
153 if (draw_left) { |
|
154 const GroupID selected_group = WP(w, replaceveh_d).sel_group; |
|
155 const uint num_engines = IsDefaultGroupID(selected_group) ? p->num_engines[e] : GetGroup(selected_group)->num_engines[e]; |
|
156 |
153 /* Skip drawing the engines we don't have any of and haven't set for replacement */ |
157 /* Skip drawing the engines we don't have any of and haven't set for replacement */ |
154 if (p->num_engines[e] == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), e) == INVALID_ENGINE) continue; |
158 if (num_engines == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), e, selected_group) == INVALID_ENGINE) continue; |
155 } else { |
159 } else { |
156 /* This is for engines we can replace to and they should depend on what we selected to replace from */ |
160 /* This is for engines we can replace to and they should depend on what we selected to replace from */ |
157 if (!IsEngineBuildable(e, type, _local_player)) continue; // we need to be able to build the engine |
161 if (!IsEngineBuildable(e, type, _local_player)) continue; // we need to be able to build the engine |
158 if (!EnginesGotCargoInCommon(e, WP(w, replaceveh_d).sel_engine[0])) continue; // the engines needs to be able to carry the same cargo |
162 if (!EnginesGotCargoInCommon(e, WP(w, replaceveh_d).sel_engine[0])) continue; // the engines needs to be able to carry the same cargo |
|
163 |
|
164 /* Road vehicles can't be replaced by trams and vice-versa */ |
|
165 if (type == VEH_ROAD && HASBIT(EngInfo(WP(w, replaceveh_d).sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HASBIT(EngInfo(e)->misc_flags, EF_ROAD_TRAM)) continue; |
159 if (e == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew) |
166 if (e == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew) |
160 } |
167 } |
161 |
168 |
162 EngList_Add(list, e); |
169 EngList_Add(list, e); |
163 if (e == WP(w, replaceveh_d).sel_engine[i]) selected_engine = e; // The selected engine is still in the list |
170 if (e == WP(w, replaceveh_d).sel_engine[i]) selected_engine = e; // The selected engine is still in the list |
200 WP(w, replaceveh_d).update_right = false; |
207 WP(w, replaceveh_d).update_right = false; |
201 WP(w, replaceveh_d).init_lists = false; |
208 WP(w, replaceveh_d).init_lists = false; |
202 } |
209 } |
203 |
210 |
204 |
211 |
205 void DrawEngineList(byte type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count); |
212 void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group); |
206 |
213 |
207 static void ReplaceVehicleWndProc(Window *w, WindowEvent *e) |
214 static void ReplaceVehicleWndProc(Window *w, WindowEvent *e) |
208 { |
215 { |
209 /* Strings for the pulldown menu */ |
216 /* Strings for the pulldown menu */ |
210 static const StringID _vehicle_type_names[] = { |
217 static const StringID _vehicle_type_names[] = { |
240 * or The selected replacement engine has a replacement (to prevent loops) |
248 * or The selected replacement engine has a replacement (to prevent loops) |
241 * or The right list (new replacement) has the existing replacement vehicle selected */ |
249 * or The right list (new replacement) has the existing replacement vehicle selected */ |
242 SetWindowWidgetDisabledState(w, 4, |
250 SetWindowWidgetDisabledState(w, 4, |
243 selected_id[0] == INVALID_ENGINE || |
251 selected_id[0] == INVALID_ENGINE || |
244 selected_id[1] == INVALID_ENGINE || |
252 selected_id[1] == INVALID_ENGINE || |
245 EngineReplacementForPlayer(p, selected_id[1]) != INVALID_ENGINE || |
253 EngineReplacementForPlayer(p, selected_id[1], selected_group) != INVALID_ENGINE || |
246 EngineReplacementForPlayer(p, selected_id[0]) == selected_id[1]); |
254 EngineReplacementForPlayer(p, selected_id[0], selected_group) == selected_id[1]); |
247 |
255 |
248 /* Disable the "Stop Replacing" button if: |
256 /* Disable the "Stop Replacing" button if: |
249 * The left list (existing vehicle) is empty |
257 * The left list (existing vehicle) is empty |
250 * or The selected vehicle has no replacement set up */ |
258 * or The selected vehicle has no replacement set up */ |
251 SetWindowWidgetDisabledState(w, 6, |
259 SetWindowWidgetDisabledState(w, 6, |
252 selected_id[0] == INVALID_ENGINE || |
260 selected_id[0] == INVALID_ENGINE || |
253 !EngineHasReplacementForPlayer(p, selected_id[0])); |
261 !EngineHasReplacementForPlayer(p, selected_id[0], selected_group)); |
254 |
262 |
255 /* now the actual drawing of the window itself takes place */ |
263 /* now the actual drawing of the window itself takes place */ |
256 SetDParam(0, _vehicle_type_names[w->window_number]); |
264 SetDParam(0, _vehicle_type_names[w->window_number]); |
257 |
265 |
258 if (w->window_number == VEH_TRAIN) { |
266 if (w->window_number == VEH_TRAIN) { |
259 /* set on/off for renew_keep_length */ |
267 /* set on/off for renew_keep_length */ |
260 SetDParam(1, p->renew_keep_length ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF); |
268 SetDParam(1, p->renew_keep_length ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF); |
261 |
269 |
262 /* set wagon/engine button */ |
270 /* set wagon/engine button */ |
263 SetDParam(2, WP(w, replaceveh_d).wagon_btnstate ? STR_ENGINES : STR_WAGONS); |
271 SetDParam(2, WP(w, replaceveh_d).wagon_btnstate ? STR_ENGINES : STR_WAGONS); |
|
272 |
|
273 /* sets the colour of that art thing */ |
|
274 w->widget[13].color = _player_colors[_local_player]; |
|
275 w->widget[16].color = _player_colors[_local_player]; |
264 } |
276 } |
265 |
277 |
266 w->widget[13].color = _player_colors[_local_player]; // sets the colour of that art thing |
|
267 w->widget[16].color = _player_colors[_local_player]; // sets the colour of that art thing |
|
268 |
|
269 DrawWindowWidgets(w); |
278 DrawWindowWidgets(w); |
270 |
|
271 |
279 |
272 if (w->window_number == VEH_TRAIN) { |
280 if (w->window_number == VEH_TRAIN) { |
273 /* Draw the selected railtype in the pulldown menu */ |
281 /* Draw the selected railtype in the pulldown menu */ |
274 RailType railtype = _railtype_selected_in_replace_gui; |
282 RailType railtype = _railtype_selected_in_replace_gui; |
275 DrawString(157, w->widget[14].top + 1, _rail_types_list[railtype], 0x10); |
283 DrawString(157, w->widget[14].top + 1, _rail_types_list[railtype], 0x10); |
276 } |
284 } |
277 |
285 |
278 /* sets up the string for the vehicle that is being replaced to */ |
286 /* sets up the string for the vehicle that is being replaced to */ |
279 if (selected_id[0] != INVALID_ENGINE) { |
287 if (selected_id[0] != INVALID_ENGINE) { |
280 if (!EngineHasReplacementForPlayer(p, selected_id[0])) { |
288 if (!EngineHasReplacementForPlayer(p, selected_id[0], selected_group)) { |
281 SetDParam(0, STR_NOT_REPLACING); |
289 SetDParam(0, STR_NOT_REPLACING); |
282 } else { |
290 } else { |
283 SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0]))); |
291 SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0], selected_group))); |
284 } |
292 } |
285 } else { |
293 } else { |
286 SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED); |
294 SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED); |
287 } |
295 } |
288 |
296 |
294 EngineList list = WP(w, replaceveh_d).list[i]; // which list to draw |
302 EngineList list = WP(w, replaceveh_d).list[i]; // which list to draw |
295 EngineID start = i == 0 ? w->vscroll.pos : w->vscroll2.pos; // what is the offset for the start (scrolling) |
303 EngineID start = i == 0 ? w->vscroll.pos : w->vscroll2.pos; // what is the offset for the start (scrolling) |
296 EngineID end = min((i == 0 ? w->vscroll.cap : w->vscroll2.cap) + start, EngList_Count(&list)); |
304 EngineID end = min((i == 0 ? w->vscroll.cap : w->vscroll2.cap) + start, EngList_Count(&list)); |
297 |
305 |
298 /* Do the actual drawing */ |
306 /* Do the actual drawing */ |
299 DrawEngineList(w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0); |
307 DrawEngineList((VehicleType)w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0, selected_group); |
300 |
308 |
301 /* Also draw the details if an engine is selected */ |
309 /* Also draw the details if an engine is selected */ |
302 if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) { |
310 if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) { |
303 const Widget *wi = &w->widget[i == 0 ? 3 : 11]; |
311 const Widget *wi = &w->widget[i == 0 ? 3 : 11]; |
304 DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, WP(w, replaceveh_d).sel_engine[i]); |
312 DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, WP(w, replaceveh_d).sel_engine[i]); |
326 break; |
334 break; |
327 |
335 |
328 case 4: { /* Start replacing */ |
336 case 4: { /* Start replacing */ |
329 EngineID veh_from = WP(w, replaceveh_d).sel_engine[0]; |
337 EngineID veh_from = WP(w, replaceveh_d).sel_engine[0]; |
330 EngineID veh_to = WP(w, replaceveh_d).sel_engine[1]; |
338 EngineID veh_to = WP(w, replaceveh_d).sel_engine[1]; |
331 DoCommandP(0, 3, veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE); |
339 DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16) , veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE); |
332 } break; |
340 } break; |
333 |
341 |
334 case 6: { /* Stop replacing */ |
342 case 6: { /* Stop replacing */ |
335 EngineID veh_from = WP(w, replaceveh_d).sel_engine[0]; |
343 EngineID veh_from = WP(w, replaceveh_d).sel_engine[0]; |
336 DoCommandP(0, 3, veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE); |
344 DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16), veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE); |
337 } break; |
345 } break; |
338 |
346 |
339 case 7: |
347 case 7: |
340 case 9: { |
348 case 9: { |
341 uint i = (e->we.click.pt.y - 14) / w->resize.step_height; |
349 uint i = (e->we.click.pt.y - 14) / w->resize.step_height; |
507 default: return; |
515 default: return; |
508 } |
516 } |
509 |
517 |
510 w->caption_color = _local_player; |
518 w->caption_color = _local_player; |
511 w->vscroll2.cap = w->vscroll.cap; // these two are always the same |
519 w->vscroll2.cap = w->vscroll.cap; // these two are always the same |
512 } |
520 WP(w, replaceveh_d).sel_group = DEFAULT_GROUP; |
|
521 } |
|
522 |
|
523 void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype) |
|
524 { |
|
525 Window *w; |
|
526 |
|
527 DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype); |
|
528 |
|
529 switch (vehicletype) { |
|
530 default: NOT_REACHED(); |
|
531 case VEH_TRAIN: |
|
532 w = AllocateWindowDescFront(&_replace_rail_vehicle_desc, vehicletype); |
|
533 w->vscroll.cap = 8; |
|
534 w->resize.step_height = 14; |
|
535 WP(w, replaceveh_d).wagon_btnstate = true; |
|
536 break; |
|
537 case VEH_ROAD: |
|
538 w = AllocateWindowDescFront(&_replace_road_vehicle_desc, vehicletype); |
|
539 w->vscroll.cap = 8; |
|
540 w->resize.step_height = 14; |
|
541 break; |
|
542 case VEH_SHIP: |
|
543 case VEH_AIRCRAFT: |
|
544 w = AllocateWindowDescFront(&_replace_ship_aircraft_vehicle_desc, vehicletype); |
|
545 w->vscroll.cap = 4; |
|
546 w->resize.step_height = 24; |
|
547 break; |
|
548 } |
|
549 |
|
550 w->caption_color = _local_player; |
|
551 WP(w, replaceveh_d).sel_group = id_g; |
|
552 w->vscroll2.cap = w->vscroll.cap; // these two are always the same |
|
553 } |