72 EngineID vb = *(const EngineID*)b; |
72 EngineID vb = *(const EngineID*)b; |
73 int val_a = ((RailVehInfo(va)->flags & RVI_WAGON) != 0) ? 1 : 0; |
73 int val_a = ((RailVehInfo(va)->flags & RVI_WAGON) != 0) ? 1 : 0; |
74 int val_b = ((RailVehInfo(vb)->flags & RVI_WAGON) != 0) ? 1 : 0; |
74 int val_b = ((RailVehInfo(vb)->flags & RVI_WAGON) != 0) ? 1 : 0; |
75 int r = val_a - val_b; |
75 int r = val_a - val_b; |
76 |
76 |
77 if (r == 0) { |
77 /* Use EngineID to sort instead since we want consistent sorting */ |
78 /* Use EngineID to sort instead since we want consistent sorting */ |
78 if (r == 0) return TrainEngineNumberSorter(a, b); |
79 return TrainEngineNumberSorter(a, b); |
79 |
80 } |
|
81 return _internal_sort_order ? -r : r; |
80 return _internal_sort_order ? -r : r; |
82 } |
81 } |
83 |
82 |
84 static int CDECL TrainEngineCostSorter(const void *a, const void *b) |
83 static int CDECL TrainEngineCostSorter(const void *a, const void *b) |
85 { |
84 { |
86 const int va = RailVehInfo(*(const EngineID*)a)->base_cost; |
85 int va = RailVehInfo(*(const EngineID*)a)->base_cost; |
87 const int vb = RailVehInfo(*(const EngineID*)b)->base_cost; |
86 int vb = RailVehInfo(*(const EngineID*)b)->base_cost; |
88 int r = va - vb; |
87 int r = va - vb; |
89 |
88 |
90 return _internal_sort_order ? -r : r; |
89 return _internal_sort_order ? -r : r; |
91 } |
90 } |
92 |
91 |
93 static int CDECL TrainEngineSpeedSorter(const void *a, const void *b) |
92 static int CDECL TrainEngineSpeedSorter(const void *a, const void *b) |
94 { |
93 { |
95 const int va = RailVehInfo(*(const EngineID*)a)->max_speed; |
94 int va = RailVehInfo(*(const EngineID*)a)->max_speed; |
96 const int vb = RailVehInfo(*(const EngineID*)b)->max_speed; |
95 int vb = RailVehInfo(*(const EngineID*)b)->max_speed; |
97 const int r = va - vb; |
96 int r = va - vb; |
98 |
97 |
99 return _internal_sort_order ? -r : r; |
98 return _internal_sort_order ? -r : r; |
100 } |
99 } |
101 |
100 |
102 static int CDECL TrainEnginePowerSorter(const void *a, const void *b) |
101 static int CDECL TrainEnginePowerSorter(const void *a, const void *b) |
103 { |
102 { |
104 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a); |
103 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a); |
105 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b); |
104 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b); |
106 |
105 |
107 const int va = rvi_a->power << (rvi_a->flags & RVI_MULTIHEAD ? 1 : 0); |
106 int va = rvi_a->power << (rvi_a->flags & RVI_MULTIHEAD ? 1 : 0); |
108 const int vb = rvi_b->power << (rvi_b->flags & RVI_MULTIHEAD ? 1 : 0); |
107 int vb = rvi_b->power << (rvi_b->flags & RVI_MULTIHEAD ? 1 : 0); |
109 const int r = va - vb; |
108 int r = va - vb; |
110 |
109 |
111 return _internal_sort_order ? -r : r; |
110 return _internal_sort_order ? -r : r; |
112 } |
111 } |
113 |
112 |
114 static int CDECL TrainEngineIntroDateSorter(const void *a, const void *b) |
113 static int CDECL TrainEngineIntroDateSorter(const void *a, const void *b) |
115 { |
114 { |
116 const int va = GetEngine(*(const EngineID*)a)->intro_date; |
115 int va = GetEngine(*(const EngineID*)a)->intro_date; |
117 const int vb = GetEngine(*(const EngineID*)b)->intro_date; |
116 int vb = GetEngine(*(const EngineID*)b)->intro_date; |
118 const int r = va - vb; |
117 int r = va - vb; |
119 |
118 |
120 return _internal_sort_order ? -r : r; |
119 return _internal_sort_order ? -r : r; |
121 } |
120 } |
122 |
121 |
123 static EngineID _last_engine; // cached vehicle to hopefully speed up name-sorting |
122 static EngineID _last_engine; // cached vehicle to hopefully speed up name-sorting |
147 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b) |
146 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b) |
148 { |
147 { |
149 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a); |
148 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a); |
150 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b); |
149 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b); |
151 |
150 |
152 const int va = rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class] * (rvi_a->flags & RVI_MULTIHEAD ? 2 : 1); |
151 int va = rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class] * (rvi_a->flags & RVI_MULTIHEAD ? 2 : 1); |
153 const int vb = rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class] * (rvi_b->flags & RVI_MULTIHEAD ? 2 : 1); |
152 int vb = rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class] * (rvi_b->flags & RVI_MULTIHEAD ? 2 : 1); |
154 const int r = va - vb; |
153 int r = va - vb; |
155 |
154 |
156 return _internal_sort_order ? -r : r; |
155 return _internal_sort_order ? -r : r; |
157 } |
156 } |
158 |
157 |
159 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b) |
158 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b) |
165 * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int, |
164 * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int, |
166 * we will actually calculate cunning cost/power (to make it more than 1). |
165 * we will actually calculate cunning cost/power (to make it more than 1). |
167 * Because of this, the return value have to be reversed as well and we return b - a instead of a - b. |
166 * Because of this, the return value have to be reversed as well and we return b - a instead of a - b. |
168 * Another thing is that both power and running costs should be doubled for multiheaded engines. |
167 * Another thing is that both power and running costs should be doubled for multiheaded engines. |
169 * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */ |
168 * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */ |
170 const int va = (rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class]) / max(1, rvi_a->power); |
169 int va = (rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class]) / max(1, rvi_a->power); |
171 const int vb = (rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class]) / max(1, rvi_b->power); |
170 int vb = (rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class]) / max(1, rvi_b->power); |
172 const int r = vb - va; |
171 int r = vb - va; |
173 |
172 |
174 return _internal_sort_order ? -r : r; |
173 return _internal_sort_order ? -r : r; |
175 } |
174 } |
176 |
175 |
177 static int CDECL TrainEngineReliabilitySorter(const void *a, const void *b) |
176 static int CDECL TrainEngineReliabilitySorter(const void *a, const void *b) |
178 { |
177 { |
179 const int va = GetEngine(*(const EngineID*)a)->reliability; |
178 int va = GetEngine(*(const EngineID*)a)->reliability; |
180 const int vb = GetEngine(*(const EngineID*)b)->reliability; |
179 int vb = GetEngine(*(const EngineID*)b)->reliability; |
181 const int r = va - vb; |
180 int r = va - vb; |
182 |
181 |
183 return _internal_sort_order ? -r : r; |
182 return _internal_sort_order ? -r : r; |
184 } |
183 } |
185 |
184 |
186 static EngList_SortTypeFunction * const _engine_sorter[] = { |
185 static EngList_SortTypeFunction * const _engine_sorter[] = { |
374 } |
373 } |
375 } |
374 } |
376 |
375 |
377 static void GenerateBuildList(Window *w) |
376 static void GenerateBuildList(Window *w) |
378 { |
377 { |
379 EngineID id; |
378 EngineID eid; |
380 int num_engines = 0; |
379 int num_engines = 0; |
381 int num_wagons = 0; |
380 int num_wagons = 0; |
382 buildvehicle_d *bv = &WP(w, buildvehicle_d); |
381 buildvehicle_d *bv = &WP(w, buildvehicle_d); |
383 |
382 |
384 bv->filter.railtype = w->window_number == 0 ? RAILTYPE_END : GetRailType(w->window_number); |
383 bv->filter.railtype = (w->window_number == 0) ? RAILTYPE_END : GetRailType(w->window_number); |
385 |
384 |
386 EngList_RemoveAll(&bv->eng_list); |
385 EngList_RemoveAll(&bv->eng_list); |
387 // make list of all available cars |
386 |
388 for (id = 0; id < NUM_TRAIN_ENGINES; id++) { |
387 // make a list of all available cars |
389 const Engine *e = GetEngine(id); |
388 for (eid = 0; eid < NUM_TRAIN_ENGINES; eid++) { |
390 const RailVehicleInfo *rvi = RailVehInfo(id); |
389 const Engine *e = GetEngine(eid); |
|
390 const RailVehicleInfo *rvi = RailVehInfo(eid); |
391 |
391 |
392 if (bv->filter.railtype != RAILTYPE_END && !HasPowerOnRail(e->railtype, bv->filter.railtype)) continue; |
392 if (bv->filter.railtype != RAILTYPE_END && !HasPowerOnRail(e->railtype, bv->filter.railtype)) continue; |
393 if (!IsEngineBuildable(id, VEH_Train)) continue; |
393 if (!IsEngineBuildable(eid, VEH_Train)) continue; |
394 |
394 |
395 EngList_Add(&bv->eng_list, id); |
395 EngList_Add(&bv->eng_list, eid); |
396 if ((rvi->flags & RVI_WAGON) == 0) { |
396 if ((rvi->flags & RVI_WAGON) == 0) { |
397 num_engines++; |
397 num_engines++; |
398 } else { |
398 } else { |
399 num_wagons++; |
399 num_wagons++; |
400 } |
400 } |
403 // make engines first, and then wagons, sorted by ListPositionOfEngine() |
403 // make engines first, and then wagons, sorted by ListPositionOfEngine() |
404 _internal_sort_order = false; |
404 _internal_sort_order = false; |
405 EngList_Sort(&bv->eng_list, TrainEnginesThenWagonsSorter); |
405 EngList_Sort(&bv->eng_list, TrainEnginesThenWagonsSorter); |
406 |
406 |
407 // and then sort engines |
407 // and then sort engines |
408 _internal_sort_order = WP(w,buildvehicle_d).descending_sort_order; |
408 _internal_sort_order = bv->descending_sort_order; |
409 EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], 0, num_engines); |
409 EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], 0, num_engines); |
410 |
410 |
411 // and finally sort wagons |
411 // and finally sort wagons |
412 EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], num_engines, num_wagons); |
412 EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], num_engines, num_wagons); |
413 } |
413 } |
414 |
414 |
415 static void DrawTrainBuildWindow(Window *w) |
415 static void DrawTrainBuildWindow(Window *w) |
416 { |
416 { |
417 buildvehicle_d *bv = &WP(w,buildvehicle_d); |
417 const buildvehicle_d *bv = &WP(w, buildvehicle_d); |
418 int num_engines = EngList_Count(&bv->eng_list); |
418 int num_engines = EngList_Count(&bv->eng_list); |
419 int x = 1; |
419 int x = 1; |
420 int y = 27; |
420 int y = 27; |
421 EngineID selected_id = bv->sel_engine; |
421 EngineID selected_id = bv->sel_engine; |
422 int max = w->vscroll.pos + w->vscroll.cap; |
422 int max = w->vscroll.pos + w->vscroll.cap; |
459 DoDrawString(bv->descending_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10); |
459 DoDrawString(bv->descending_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10); |
460 } |
460 } |
461 |
461 |
462 static void NewRailVehicleWndProc(Window *w, WindowEvent *e) |
462 static void NewRailVehicleWndProc(Window *w, WindowEvent *e) |
463 { |
463 { |
464 buildvehicle_d *bv = &WP(w,buildvehicle_d); |
464 buildvehicle_d *bv = &WP(w, buildvehicle_d); |
465 switch (e->event) { |
465 switch (e->event) { |
466 case WE_CREATE: |
466 case WE_CREATE: |
467 EngList_Create(&bv->eng_list); |
467 EngList_Create(&bv->eng_list); |
468 bv->sel_engine = INVALID_ENGINE; |
468 bv->sel_engine = INVALID_ENGINE; |
469 bv->sort_criteria = _last_sort_criteria; |
469 bv->sort_criteria = _last_sort_criteria; |