138 const EngineID vb = *(const EngineID*)b; |
138 const EngineID vb = *(const EngineID*)b; |
139 int r; |
139 int r; |
140 |
140 |
141 if (va != last_engine[0]) { |
141 if (va != last_engine[0]) { |
142 last_engine[0] = va; |
142 last_engine[0] = va; |
143 GetString(last_name[0], GetCustomEngineName(va), lastof(last_name[0])); |
143 SetDParam(0, va); |
|
144 GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0])); |
144 } |
145 } |
145 |
146 |
146 if (vb != last_engine[1]) { |
147 if (vb != last_engine[1]) { |
147 last_engine[1] = vb; |
148 last_engine[1] = vb; |
148 GetString(last_name[1], GetCustomEngineName(vb), lastof(last_name[1])); |
149 SetDParam(0, vb); |
|
150 GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1])); |
149 } |
151 } |
150 |
152 |
151 r = strcmp(last_name[0], last_name[1]); // sort by name |
153 r = strcmp(last_name[0], last_name[1]); // sort by name |
152 |
154 |
153 if (r == 0) { |
155 if (r == 0) { |
204 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b) |
206 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b) |
205 { |
207 { |
206 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a); |
208 const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a); |
207 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b); |
209 const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b); |
208 |
210 |
209 int va = rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class] * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); |
211 Money va = rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class] * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); |
210 int vb = rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class] * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); |
212 Money vb = rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class] * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); |
211 int r = va - vb; |
213 int r = ClampToI32(va - vb); |
212 |
214 |
213 return _internal_sort_order ? -r : r; |
215 return _internal_sort_order ? -r : r; |
214 } |
216 } |
215 |
217 |
216 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b) |
218 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b) |
222 * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int, |
224 * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int, |
223 * we will actually calculate cunning cost/power (to make it more than 1). |
225 * we will actually calculate cunning cost/power (to make it more than 1). |
224 * Because of this, the return value have to be reversed as well and we return b - a instead of a - b. |
226 * Because of this, the return value have to be reversed as well and we return b - a instead of a - b. |
225 * Another thing is that both power and running costs should be doubled for multiheaded engines. |
227 * Another thing is that both power and running costs should be doubled for multiheaded engines. |
226 * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */ |
228 * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */ |
227 int va = (rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class]) / max((uint16)1, rvi_a->power); |
229 Money va = (rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class]) / max((uint16)1, rvi_a->power); |
228 int vb = (rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class]) / max((uint16)1, rvi_b->power); |
230 Money vb = (rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class]) / max((uint16)1, rvi_b->power); |
229 int r = vb - va; |
231 int r = ClampToI32(vb - va); |
230 |
232 |
231 return _internal_sort_order ? -r : r; |
233 return _internal_sort_order ? -r : r; |
232 } |
234 } |
233 |
235 |
234 static int CDECL TrainEngineNumberSorter(const void *a, const void *b) |
236 static int CDECL TrainEngineNumberSorter(const void *a, const void *b) |
668 EngineID eid, sel_id; |
670 EngineID eid, sel_id; |
669 int num_engines = 0; |
671 int num_engines = 0; |
670 int num_wagons = 0; |
672 int num_wagons = 0; |
671 buildvehicle_d *bv = &WP(w, buildvehicle_d); |
673 buildvehicle_d *bv = &WP(w, buildvehicle_d); |
672 |
674 |
673 bv->filter.railtype = (w->window_number == 0) ? RAILTYPE_END : GetRailType(w->window_number); |
675 bv->filter.railtype = (w->window_number <= VEH_END) ? RAILTYPE_END : GetRailType(w->window_number); |
674 |
676 |
675 EngList_RemoveAll(&bv->eng_list); |
677 EngList_RemoveAll(&bv->eng_list); |
676 |
678 |
677 /* Make list of all available train engines and wagons. |
679 /* Make list of all available train engines and wagons. |
678 * Also check to see if the previously selected engine is still available, |
680 * Also check to see if the previously selected engine is still available, |
760 * and if not, reset selection to INVALID_ENGINE. This could be the case |
762 * and if not, reset selection to INVALID_ENGINE. This could be the case |
761 * when planes become obsolete and are removed */ |
763 * when planes become obsolete and are removed */ |
762 sel_id = INVALID_ENGINE; |
764 sel_id = INVALID_ENGINE; |
763 for (eid = AIRCRAFT_ENGINES_INDEX; eid < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; eid++) { |
765 for (eid = AIRCRAFT_ENGINES_INDEX; eid < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; eid++) { |
764 if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue; |
766 if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue; |
765 if (w->window_number != 0 && !IsAircraftBuildableAtStation(eid, w->window_number)) continue; |
767 /* First VEH_END window_numbers are fake to allow a window open for all different types at once */ |
|
768 if (w->window_number > VEH_END && !IsAircraftBuildableAtStation(eid, w->window_number)) continue; |
766 |
769 |
767 EngList_Add(&bv->eng_list, eid); |
770 EngList_Add(&bv->eng_list, eid); |
768 if (eid == bv->sel_engine) sel_id = eid; |
771 if (eid == bv->sel_engine) sel_id = eid; |
769 } |
772 } |
770 |
773 |
851 |
854 |
852 for (; min < max; min++, y += step_size) { |
855 for (; min < max; min++, y += step_size) { |
853 const EngineID engine = eng_list[min]; |
856 const EngineID engine = eng_list[min]; |
854 const uint num_engines = IsDefaultGroupID(selected_group) ? p->num_engines[engine] : GetGroup(selected_group)->num_engines[engine]; |
857 const uint num_engines = IsDefaultGroupID(selected_group) ? p->num_engines[engine] : GetGroup(selected_group)->num_engines[engine]; |
855 |
858 |
856 DrawString(x + x_offset, y, GetCustomEngineName(engine), engine == selected_id ? 0xC : 0x10); |
859 SetDParam(0, engine); |
|
860 DrawString(x + x_offset, y, STR_ENGINE_NAME, engine == selected_id ? 0xC : 0x10); |
857 DrawVehicleEngine(type, x, y + y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_player)); |
861 DrawVehicleEngine(type, x, y + y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_player)); |
858 if (show_count) { |
862 if (show_count) { |
859 SetDParam(0, num_engines); |
863 SetDParam(0, num_engines); |
860 DrawStringRightAligned(213, y + (GetVehicleListHeight(type) == 14 ? 3 : 8), STR_TINY_BLACK, 0); |
864 DrawStringRightAligned(213, y + (GetVehicleListHeight(type) == 14 ? 3 : 8), STR_TINY_BLACK, 0); |
861 } |
865 } |
882 static void DrawBuildVehicleWindow(Window *w) |
886 static void DrawBuildVehicleWindow(Window *w) |
883 { |
887 { |
884 const buildvehicle_d *bv = &WP(w, buildvehicle_d); |
888 const buildvehicle_d *bv = &WP(w, buildvehicle_d); |
885 uint max = min(w->vscroll.pos + w->vscroll.cap, EngList_Count(&bv->eng_list)); |
889 uint max = min(w->vscroll.pos + w->vscroll.cap, EngList_Count(&bv->eng_list)); |
886 |
890 |
887 SetWindowWidgetDisabledState(w, BUILD_VEHICLE_WIDGET_BUILD, w->window_number == 0); |
891 SetWindowWidgetDisabledState(w, BUILD_VEHICLE_WIDGET_BUILD, w->window_number <= VEH_END); |
888 |
892 |
889 SetVScrollCount(w, EngList_Count(&bv->eng_list)); |
893 SetVScrollCount(w, EngList_Count(&bv->eng_list)); |
890 SetDParam(0, bv->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles |
894 SetDParam(0, bv->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles |
891 DrawWindowWidgets(w); |
895 DrawWindowWidgets(w); |
892 |
896 |
961 case VEH_TRAIN: str = STR_886A_RENAME_TRAIN_VEHICLE_TYPE; break; |
965 case VEH_TRAIN: str = STR_886A_RENAME_TRAIN_VEHICLE_TYPE; break; |
962 case VEH_ROAD: str = STR_9036_RENAME_ROAD_VEHICLE_TYPE; break; |
966 case VEH_ROAD: str = STR_9036_RENAME_ROAD_VEHICLE_TYPE; break; |
963 case VEH_SHIP: str = STR_9838_RENAME_SHIP_TYPE; break; |
967 case VEH_SHIP: str = STR_9838_RENAME_SHIP_TYPE; break; |
964 case VEH_AIRCRAFT: str = STR_A039_RENAME_AIRCRAFT_TYPE; break; |
968 case VEH_AIRCRAFT: str = STR_A039_RENAME_AIRCRAFT_TYPE; break; |
965 } |
969 } |
966 ShowQueryString(GetCustomEngineName(sel_eng), str, 31, 160, w, CS_ALPHANUMERAL); |
970 SetDParam(0, sel_eng); |
|
971 ShowQueryString(STR_ENGINE_NAME, str, 31, 160, w, CS_ALPHANUMERAL); |
967 } |
972 } |
968 break; |
973 break; |
969 } |
974 } |
970 } |
975 } |
971 } |
976 } |
992 DrawBuildVehicleWindow(w); |
997 DrawBuildVehicleWindow(w); |
993 break; |
998 break; |
994 |
999 |
995 case WE_CLICK: |
1000 case WE_CLICK: |
996 BuildVehicleClickEvent(w, e); |
1001 BuildVehicleClickEvent(w, e); |
|
1002 break; |
|
1003 |
|
1004 case WE_DOUBLE_CLICK: |
|
1005 if (e->we.click.widget == BUILD_VEHICLE_WIDGET_LIST) { |
|
1006 /* When double clicking, we want to buy a vehicle */ |
|
1007 e->we.click.widget = BUILD_VEHICLE_WIDGET_BUILD; |
|
1008 BuildVehicleClickEvent(w, e); |
|
1009 } |
997 break; |
1010 break; |
998 |
1011 |
999 case WE_ON_EDIT_TEXT: { |
1012 case WE_ON_EDIT_TEXT: { |
1000 if (e->we.edittext.str[0] != '\0') { |
1013 if (e->we.edittext.str[0] != '\0') { |
1001 StringID str = STR_NULL; |
1014 StringID str = STR_NULL; |
1041 |
1054 |
1042 void ShowBuildVehicleWindow(TileIndex tile, VehicleType type) |
1055 void ShowBuildVehicleWindow(TileIndex tile, VehicleType type) |
1043 { |
1056 { |
1044 buildvehicle_d *bv; |
1057 buildvehicle_d *bv; |
1045 Window *w; |
1058 Window *w; |
|
1059 /* We want to be able to open both Available Train as Available Ships, |
|
1060 * so if tile == 0 (Available XXX Window), use 'type' as unique number. |
|
1061 * As it always is a low value, it won't collide with any real tile |
|
1062 * number. */ |
|
1063 uint num = (tile == 0) ? (int)type : tile; |
1046 |
1064 |
1047 assert(IsPlayerBuildableVehicleType(type)); |
1065 assert(IsPlayerBuildableVehicleType(type)); |
1048 |
1066 |
1049 DeleteWindowById(WC_BUILD_VEHICLE, tile); |
1067 DeleteWindowById(WC_BUILD_VEHICLE, num); |
1050 |
1068 |
1051 w = AllocateWindowDescFront(&_build_vehicle_desc, tile); |
1069 w = AllocateWindowDescFront(&_build_vehicle_desc, num); |
1052 |
1070 |
1053 if (w == NULL) return; |
1071 if (w == NULL) return; |
1054 |
1072 |
1055 w->caption_color = (tile != 0) ? GetTileOwner(tile) : _local_player; |
1073 w->caption_color = (tile != 0) ? GetTileOwner(tile) : _local_player; |
1056 w->resize.step_height = GetVehicleListHeight(type); |
1074 w->resize.step_height = GetVehicleListHeight(type); |