src/autoreplace_gui.cpp
branchgamebalance
changeset 9911 0b8b245a2391
parent 9908 0fa543611bbe
child 9912 1ac8aac92385
equal deleted inserted replaced
9910:0b2aebc8283e 9911:0b8b245a2391
    12 #include "gui.h"
    12 #include "gui.h"
    13 #include "command.h"
    13 #include "command.h"
    14 #include "variables.h"
    14 #include "variables.h"
    15 #include "vehicle_gui.h"
    15 #include "vehicle_gui.h"
    16 #include "newgrf_engine.h"
    16 #include "newgrf_engine.h"
       
    17 #include "group.h"
    17 
    18 
    18 
    19 
    19 static RailType _railtype_selected_in_replace_gui;
    20 static RailType _railtype_selected_in_replace_gui;
    20 
    21 
    21 static bool _rebuild_left_list;
    22 static bool _rebuild_left_list;
    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
   159 			if (e == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew)
   163 			if (e == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew)
   200 	WP(w, replaceveh_d).update_right = false;
   204 	WP(w, replaceveh_d).update_right = false;
   201 	WP(w, replaceveh_d).init_lists   = false;
   205 	WP(w, replaceveh_d).init_lists   = false;
   202 }
   206 }
   203 
   207 
   204 
   208 
   205 void DrawEngineList(byte type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count);
   209 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 
   210 
   207 static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
   211 static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
   208 {
   212 {
   209 	/* Strings for the pulldown menu */
   213 	/* Strings for the pulldown menu */
   210 	static const StringID _vehicle_type_names[] = {
   214 	static const StringID _vehicle_type_names[] = {
   229 		case WE_PAINT: {
   233 		case WE_PAINT: {
   230 			if (WP(w, replaceveh_d).update_left || WP(w, replaceveh_d).update_right) GenerateLists(w);
   234 			if (WP(w, replaceveh_d).update_left || WP(w, replaceveh_d).update_right) GenerateLists(w);
   231 
   235 
   232 			Player *p = GetPlayer(_local_player);
   236 			Player *p = GetPlayer(_local_player);
   233 			EngineID selected_id[2];
   237 			EngineID selected_id[2];
       
   238 			const GroupID selected_group = WP(w,replaceveh_d).sel_group;
   234 
   239 
   235 			selected_id[0] = WP(w, replaceveh_d).sel_engine[0];
   240 			selected_id[0] = WP(w, replaceveh_d).sel_engine[0];
   236 			selected_id[1] = WP(w, replaceveh_d).sel_engine[1];
   241 			selected_id[1] = WP(w, replaceveh_d).sel_engine[1];
   237 
   242 
   238 			/* Disable the "Start Replacing" button if:
   243 			/* Disable the "Start Replacing" button if:
   240 			 * or The selected replacement engine has a replacement (to prevent loops)
   245 			 * or The selected replacement engine has a replacement (to prevent loops)
   241 			 * or The right list (new replacement) has the existing replacement vehicle selected */
   246 			 * or The right list (new replacement) has the existing replacement vehicle selected */
   242 			SetWindowWidgetDisabledState(w, 4,
   247 			SetWindowWidgetDisabledState(w, 4,
   243 										 selected_id[0] == INVALID_ENGINE ||
   248 										 selected_id[0] == INVALID_ENGINE ||
   244 										 selected_id[1] == INVALID_ENGINE ||
   249 										 selected_id[1] == INVALID_ENGINE ||
   245 										 EngineReplacementForPlayer(p, selected_id[1]) != INVALID_ENGINE ||
   250 										 EngineReplacementForPlayer(p, selected_id[1], selected_group) != INVALID_ENGINE ||
   246 										 EngineReplacementForPlayer(p, selected_id[0]) == selected_id[1]);
   251 										 EngineReplacementForPlayer(p, selected_id[0], selected_group) == selected_id[1]);
   247 
   252 
   248 			/* Disable the "Stop Replacing" button if:
   253 			/* Disable the "Stop Replacing" button if:
   249 			 *   The left list (existing vehicle) is empty
   254 			 *   The left list (existing vehicle) is empty
   250 			 *   or The selected vehicle has no replacement set up */
   255 			 *   or The selected vehicle has no replacement set up */
   251 			SetWindowWidgetDisabledState(w, 6,
   256 			SetWindowWidgetDisabledState(w, 6,
   252 										 selected_id[0] == INVALID_ENGINE ||
   257 										 selected_id[0] == INVALID_ENGINE ||
   253 										 !EngineHasReplacementForPlayer(p, selected_id[0]));
   258 										 !EngineHasReplacementForPlayer(p, selected_id[0], selected_group));
   254 
   259 
   255 			/* now the actual drawing of the window itself takes place */
   260 			/* now the actual drawing of the window itself takes place */
   256 			SetDParam(0, _vehicle_type_names[w->window_number]);
   261 			SetDParam(0, _vehicle_type_names[w->window_number]);
   257 
   262 
   258 			if (w->window_number == VEH_TRAIN) {
   263 			if (w->window_number == VEH_TRAIN) {
   275 				DrawString(157, w->widget[14].top + 1, _rail_types_list[railtype], 0x10);
   280 				DrawString(157, w->widget[14].top + 1, _rail_types_list[railtype], 0x10);
   276 			}
   281 			}
   277 
   282 
   278 			/* sets up the string for the vehicle that is being replaced to */
   283 			/* sets up the string for the vehicle that is being replaced to */
   279 			if (selected_id[0] != INVALID_ENGINE) {
   284 			if (selected_id[0] != INVALID_ENGINE) {
   280 				if (!EngineHasReplacementForPlayer(p, selected_id[0])) {
   285 				if (!EngineHasReplacementForPlayer(p, selected_id[0], selected_group)) {
   281 					SetDParam(0, STR_NOT_REPLACING);
   286 					SetDParam(0, STR_NOT_REPLACING);
   282 				} else {
   287 				} else {
   283 					SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0])));
   288 					SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0], selected_group)));
   284 				}
   289 				}
   285 			} else {
   290 			} else {
   286 				SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
   291 				SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
   287 			}
   292 			}
   288 
   293 
   294 				EngineList list = WP(w, replaceveh_d).list[i]; // which list to draw
   299 				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)
   300 				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));
   301 				EngineID end    = min((i == 0 ? w->vscroll.cap : w->vscroll2.cap) + start, EngList_Count(&list));
   297 
   302 
   298 				/* Do the actual drawing */
   303 				/* Do the actual drawing */
   299 				DrawEngineList(w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0);
   304 				DrawEngineList((VehicleType)w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0, selected_group);
   300 
   305 
   301 				/* Also draw the details if an engine is selected */
   306 				/* Also draw the details if an engine is selected */
   302 				if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) {
   307 				if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) {
   303 					const Widget *wi = &w->widget[i == 0 ? 3 : 11];
   308 					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]);
   309 					DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, WP(w, replaceveh_d).sel_engine[i]);
   326 					break;
   331 					break;
   327 
   332 
   328 				case 4: { /* Start replacing */
   333 				case 4: { /* Start replacing */
   329 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   334 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   330 					EngineID veh_to = WP(w, replaceveh_d).sel_engine[1];
   335 					EngineID veh_to = WP(w, replaceveh_d).sel_engine[1];
   331 					DoCommandP(0, 3, veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
   336 					DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16) , veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
   332 				} break;
   337 				} break;
   333 
   338 
   334 				case 6: { /* Stop replacing */
   339 				case 6: { /* Stop replacing */
   335 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   340 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   336 					DoCommandP(0, 3, veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
   341 					DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16), veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
   337 				} break;
   342 				} break;
   338 
   343 
   339 				case 7:
   344 				case 7:
   340 				case 9: {
   345 				case 9: {
   341 					uint i = (e->we.click.pt.y - 14) / w->resize.step_height;
   346 					uint i = (e->we.click.pt.y - 14) / w->resize.step_height;
   478 	_replace_ship_aircraft_vehicle_widgets,
   483 	_replace_ship_aircraft_vehicle_widgets,
   479 	ReplaceVehicleWndProc
   484 	ReplaceVehicleWndProc
   480 };
   485 };
   481 
   486 
   482 
   487 
   483 void ShowReplaceVehicleWindow(byte vehicletype)
   488 void ShowReplaceVehicleWindow(VehicleType vehicletype)
   484 {
   489 {
   485 	Window *w;
   490 	Window *w;
   486 
   491 
   487 	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
   492 	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
   488 
   493 
   507 		default: return;
   512 		default: return;
   508 	}
   513 	}
   509 
   514 
   510 	w->caption_color = _local_player;
   515 	w->caption_color = _local_player;
   511 	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
   516 	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
   512 }
   517 	WP(w, replaceveh_d).sel_group = DEFAULT_GROUP;
       
   518  }
       
   519 
       
   520 void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
       
   521 {
       
   522 	Window *w;
       
   523 
       
   524 	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
       
   525 
       
   526 	switch (vehicletype) {
       
   527 		default: NOT_REACHED();
       
   528 		case VEH_TRAIN:
       
   529 			w = AllocateWindowDescFront(&_replace_rail_vehicle_desc, vehicletype);
       
   530 			w->vscroll.cap  = 8;
       
   531 			w->resize.step_height = 14;
       
   532 			WP(w, replaceveh_d).wagon_btnstate = true;
       
   533 			break;
       
   534 		case VEH_ROAD:
       
   535 			w = AllocateWindowDescFront(&_replace_road_vehicle_desc, vehicletype);
       
   536 			w->vscroll.cap  = 8;
       
   537 			w->resize.step_height = 14;
       
   538 			break;
       
   539 		case VEH_SHIP:
       
   540 		case VEH_AIRCRAFT:
       
   541 			w = AllocateWindowDescFront(&_replace_ship_aircraft_vehicle_desc, vehicletype);
       
   542 			w->vscroll.cap  = 4;
       
   543 			w->resize.step_height = 24;
       
   544 			break;
       
   545 	}
       
   546 
       
   547 	w->caption_color = _local_player;
       
   548 	WP(w, replaceveh_d).sel_group = id_g;
       
   549 	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
       
   550 }