src/autoreplace_cmd.cpp
branchNewGRF_ports
changeset 6719 4cc327ad39d5
parent 6590 9bbf8fdc5e91
child 6720 35756db7e577
equal deleted inserted replaced
6718:5a8b295aa345 6719:4cc327ad39d5
    14 #include "vehicle_gui.h"
    14 #include "vehicle_gui.h"
    15 #include "depot.h"
    15 #include "depot.h"
    16 #include "train.h"
    16 #include "train.h"
    17 #include "aircraft.h"
    17 #include "aircraft.h"
    18 #include "cargotype.h"
    18 #include "cargotype.h"
       
    19 #include "group.h"
    19 
    20 
    20 
    21 
    21 /*
    22 /*
    22  * move the cargo from one engine to another if possible
    23  * move the cargo from one engine to another if possible
    23  */
    24  */
    85  *    CT_NO_REFIT is returned if no refit is needed
    86  *    CT_NO_REFIT is returned if no refit is needed
    86  *    CT_INVALID is returned when both old and new vehicle got cargo capacity and refitting the new one to the old one's cargo type isn't possible
    87  *    CT_INVALID is returned when both old and new vehicle got cargo capacity and refitting the new one to the old one's cargo type isn't possible
    87  */
    88  */
    88 static CargoID GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type)
    89 static CargoID GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type)
    89 {
    90 {
    90 	bool new_cargo_capacity = true;
    91 	CargoID new_cargo_type = GetEngineCargoType(engine_type);
    91 	CargoID new_cargo_type = CT_INVALID;
    92 
    92 
    93 	if (new_cargo_type == CT_INVALID) return CT_NO_REFIT; // Don't try to refit an engine with no cargo capacity
    93 	switch (v->type) {
       
    94 		case VEH_TRAIN:
       
    95 			new_cargo_capacity = (RailVehInfo(engine_type)->capacity > 0);
       
    96 			new_cargo_type     = RailVehInfo(engine_type)->cargo_type;
       
    97 			break;
       
    98 
       
    99 		case VEH_ROAD:
       
   100 			new_cargo_capacity = (RoadVehInfo(engine_type)->capacity > 0);
       
   101 			new_cargo_type     = RoadVehInfo(engine_type)->cargo_type;
       
   102 			break;
       
   103 		case VEH_SHIP:
       
   104 			new_cargo_capacity = (ShipVehInfo(engine_type)->capacity > 0);
       
   105 			new_cargo_type     = ShipVehInfo(engine_type)->cargo_type;
       
   106 			break;
       
   107 
       
   108 		case VEH_AIRCRAFT:
       
   109 			/* all aircraft starts as passenger planes with cargo capacity
       
   110 			 * new_cargo_capacity is always true for aircraft, which is the init value. No need to set it here */
       
   111 			new_cargo_type     = CT_PASSENGERS;
       
   112 			break;
       
   113 
       
   114 		default: NOT_REACHED(); break;
       
   115 	}
       
   116 
       
   117 	if (!new_cargo_capacity) return CT_NO_REFIT; // Don't try to refit an engine with no cargo capacity
       
   118 
    94 
   119 	if (v->cargo_type == new_cargo_type || CanRefitTo(engine_type, v->cargo_type)) {
    95 	if (v->cargo_type == new_cargo_type || CanRefitTo(engine_type, v->cargo_type)) {
   120 		if (VerifyAutoreplaceRefitForOrders(v, engine_type)) {
    96 		if (VerifyAutoreplaceRefitForOrders(v, engine_type)) {
   121 			return v->cargo_type == new_cargo_type ? (CargoID)CT_NO_REFIT : v->cargo_type;
    97 			return v->cargo_type == new_cargo_type ? (CargoID)CT_NO_REFIT : v->cargo_type;
   122 		} else {
    98 		} else {
   135 	do {
   111 	do {
   136 		if (v->cargo_cap == 0) continue;
   112 		if (v->cargo_cap == 0) continue;
   137 		/* Now we found a cargo type being carried on the train and we will see if it is possible to carry to this one */
   113 		/* Now we found a cargo type being carried on the train and we will see if it is possible to carry to this one */
   138 		if (v->cargo_type == new_cargo_type) return CT_NO_REFIT;
   114 		if (v->cargo_type == new_cargo_type) return CT_NO_REFIT;
   139 		if (CanRefitTo(engine_type, v->cargo_type)) return v->cargo_type;
   115 		if (CanRefitTo(engine_type, v->cargo_type)) return v->cargo_type;
   140 	} while ((v=v->next) != NULL);
   116 	} while ((v = v->next) != NULL);
   141 	return CT_NO_REFIT; // We failed to find a cargo type on the old vehicle and we will not refit the new one
   117 	return CT_NO_REFIT; // We failed to find a cargo type on the old vehicle and we will not refit the new one
   142 }
   118 }
   143 
   119 
   144 /* Replaces a vehicle (used to be called autorenew)
   120 /* Replaces a vehicle (used to be called autorenew)
   145  * This function is only called from MaybeReplaceVehicle()
   121  * This function is only called from MaybeReplaceVehicle()
   159 	bool new_front = false;
   135 	bool new_front = false;
   160 	Vehicle *new_v = NULL;
   136 	Vehicle *new_v = NULL;
   161 	char vehicle_name[32];
   137 	char vehicle_name[32];
   162 	CargoID replacement_cargo_type;
   138 	CargoID replacement_cargo_type;
   163 
   139 
   164 	new_engine_type = EngineReplacementForPlayer(p, old_v->engine_type);
   140 	/* If the vehicle belongs to a group, check if the group is protected from the global autoreplace.
       
   141 	 *  If not, chek if an global auto replacement is defined */
       
   142 	new_engine_type = (IsValidGroupID(old_v->group_id) && GetGroup(old_v->group_id)->replace_protection) ?
       
   143 			INVALID_ENGINE :
       
   144 			EngineReplacementForPlayer(p, old_v->engine_type, DEFAULT_GROUP);
       
   145 
       
   146 	/* If we don't set new_egnine_type previously, we try to check if an autoreplacement was defined
       
   147 	 *  for the group and the engine_type of the vehicle */
       
   148 	if (new_engine_type == INVALID_ENGINE && !IsDefaultGroupID(old_v->group_id)) {
       
   149 		new_engine_type = EngineReplacementForPlayer(p, old_v->engine_type, old_v->group_id);
       
   150 	}
       
   151 
   165 	if (new_engine_type == INVALID_ENGINE) new_engine_type = old_v->engine_type;
   152 	if (new_engine_type == INVALID_ENGINE) new_engine_type = old_v->engine_type;
   166 
   153 
   167 	replacement_cargo_type = GetNewCargoTypeForReplace(old_v, new_engine_type);
   154 	replacement_cargo_type = GetNewCargoTypeForReplace(old_v, new_engine_type);
   168 
   155 
   169 	/* check if we can't refit to the needed type, so no replace takes place to prevent the vehicle from altering cargo type */
   156 	/* check if we can't refit to the needed type, so no replace takes place to prevent the vehicle from altering cargo type */
   182 		SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   169 		SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   183 		SubtractMoneyFromPlayer(-sell_value); // Take back the money we just gave the player
   170 		SubtractMoneyFromPlayer(-sell_value); // Take back the money we just gave the player
   184 		return cost;
   171 		return cost;
   185 	}
   172 	}
   186 
   173 
   187 	if (replacement_cargo_type != CT_NO_REFIT) cost += GetRefitCost(new_engine_type); // add refit cost
   174 	if (replacement_cargo_type != CT_NO_REFIT) {
       
   175 		/* add refit cost */
       
   176 		int32 refit_cost = GetRefitCost(new_engine_type);
       
   177 		if (old_v->type == VEH_TRAIN && IsMultiheaded(old_v)) refit_cost += refit_cost; // pay for both ends
       
   178 		cost += refit_cost;
       
   179 	}
   188 
   180 
   189 	if (flags & DC_EXEC) {
   181 	if (flags & DC_EXEC) {
   190 		new_v = GetVehicle(_new_vehicle_id);
   182 		new_v = GetVehicle(_new_vehicle_id);
   191 		*w = new_v; //we changed the vehicle, so MaybeReplaceVehicle needs to work on the new one. Now we tell it what the new one is
   183 		*w = new_v; //we changed the vehicle, so MaybeReplaceVehicle needs to work on the new one. Now we tell it what the new one is
   192 
   184 
   206 		if (old_v->type == VEH_TRAIN && !IsFrontEngine(old_v)) {
   198 		if (old_v->type == VEH_TRAIN && !IsFrontEngine(old_v)) {
   207 			/* this is a railcar. We need to move the car into the train
   199 			/* this is a railcar. We need to move the car into the train
   208 			 * We add the new engine after the old one instead of replacing it. It will give the same result anyway when we
   200 			 * We add the new engine after the old one instead of replacing it. It will give the same result anyway when we
   209 			 * sell the old engine in a moment
   201 			 * sell the old engine in a moment
   210 			 */
   202 			 */
   211 			DoCommand(0, (GetPrevVehicleInChain(old_v)->index << 16) | new_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
   203 			/* Get the vehicle in front of the one we move out */
       
   204 			Vehicle *front = GetPrevVehicleInChain(old_v);
       
   205 			/* If the vehicle in front is the rear end of a dualheaded engine, then we need to use the one in front of that one */
       
   206 			if (IsMultiheaded(front) && !IsTrainEngine(front)) front = GetPrevVehicleInChain(front);
   212 			/* Now we move the old one out of the train */
   207 			/* Now we move the old one out of the train */
   213 			DoCommand(0, (INVALID_VEHICLE << 16) | old_v->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
   208 			DoCommand(0, (INVALID_VEHICLE << 16) | old_v->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
       
   209 			/* Add the new vehicle */
       
   210 			DoCommand(0, (front->index << 16) | new_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
   214 		} else {
   211 		} else {
   215 			// copy/clone the orders
   212 			// copy/clone the orders
   216 			DoCommand(0, (old_v->index << 16) | new_v->index, IsOrderListShared(old_v) ? CO_SHARE : CO_COPY, DC_EXEC, CMD_CLONE_ORDER);
   213 			DoCommand(0, (old_v->index << 16) | new_v->index, IsOrderListShared(old_v) ? CO_SHARE : CO_COPY, DC_EXEC, CMD_CLONE_ORDER);
   217 			new_v->cur_order_index = old_v->cur_order_index;
   214 			new_v->cur_order_index = old_v->cur_order_index;
   218 			ChangeVehicleViewWindow(old_v, new_v);
   215 			ChangeVehicleViewWindow(old_v, new_v);
   219 			new_v->profit_this_year = old_v->profit_this_year;
   216 			new_v->profit_this_year = old_v->profit_this_year;
   220 			new_v->profit_last_year = old_v->profit_last_year;
   217 			new_v->profit_last_year = old_v->profit_last_year;
   221 			new_v->service_interval = old_v->service_interval;
   218 			new_v->service_interval = old_v->service_interval;
       
   219 			DoCommand(0, old_v->group_id, new_v->index, flags, CMD_ADD_VEHICLE_GROUP);
   222 			new_front = true;
   220 			new_front = true;
   223 			new_v->unitnumber = old_v->unitnumber; // use the same unit number
   221 			new_v->unitnumber = old_v->unitnumber; // use the same unit number
       
   222 			new_v->dest_tile  = old_v->dest_tile;
   224 
   223 
   225 			new_v->current_order = old_v->current_order;
   224 			new_v->current_order = old_v->current_order;
   226 			if (old_v->type == VEH_TRAIN && GetNextVehicle(old_v) != NULL){
   225 			if (old_v->type == VEH_TRAIN && GetNextVehicle(old_v) != NULL){
   227 				Vehicle *temp_v = GetNextVehicle(old_v);
   226 				Vehicle *temp_v = GetNextVehicle(old_v);
   228 
   227 
   327 
   326 
   328 			// check if the vehicle should be replaced
   327 			// check if the vehicle should be replaced
   329 			if (!p->engine_renew ||
   328 			if (!p->engine_renew ||
   330 					w->age - w->max_age < (p->engine_renew_months * 30) || // replace if engine is too old
   329 					w->age - w->max_age < (p->engine_renew_months * 30) || // replace if engine is too old
   331 					w->max_age == 0) { // rail cars got a max age of 0
   330 					w->max_age == 0) { // rail cars got a max age of 0
   332 				if (!EngineHasReplacementForPlayer(p, w->engine_type)) // updates to a new model
   331 				/* If the vehicle belongs to a group, check if the group is protected from the global autoreplace.
       
   332 				   If not, chek if an global auto remplacement is defined */
       
   333 				if (IsValidGroupID(w->group_id)) {
       
   334 					if (!EngineHasReplacementForPlayer(p, w->engine_type, w->group_id) && (
       
   335 							GetGroup(w->group_id)->replace_protection ||
       
   336 							!EngineHasReplacementForPlayer(p, w->engine_type, DEFAULT_GROUP))) {
       
   337 						continue;
       
   338 					}
       
   339 				} else if (!EngineHasReplacementForPlayer(p, w->engine_type, DEFAULT_GROUP)) {
   333 					continue;
   340 					continue;
       
   341 				}
   334 			}
   342 			}
   335 
   343 
   336 			/* Now replace the vehicle */
   344 			/* Now replace the vehicle */
   337 			temp_cost = ReplaceVehicle(&w, flags, cost);
   345 			temp_cost = ReplaceVehicle(&w, flags, cost);
   338 
   346