37 |
37 |
38 /** |
38 /** |
39 * Checks some basic properties whether autoreplace is allowed |
39 * Checks some basic properties whether autoreplace is allowed |
40 * @param from Origin engine |
40 * @param from Origin engine |
41 * @param to Destination engine |
41 * @param to Destination engine |
42 * @param player Player to check for |
42 * @param company Company to check for |
43 * @return true if autoreplace is allowed |
43 * @return true if autoreplace is allowed |
44 */ |
44 */ |
45 bool CheckAutoreplaceValidity(EngineID from, EngineID to, PlayerID player) |
45 bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company) |
46 { |
46 { |
47 /* First we make sure that it's a valid type the user requested |
47 /* First we make sure that it's a valid type the user requested |
48 * check that it's an engine that is in the engine array */ |
48 * check that it's an engine that is in the engine array */ |
49 if (!IsEngineIndex(from) || !IsEngineIndex(to)) return false; |
49 if (!IsEngineIndex(from) || !IsEngineIndex(to)) return false; |
50 |
50 |
51 /* we can't replace an engine into itself (that would be autorenew) */ |
51 /* we can't replace an engine into itself (that would be autorenew) */ |
52 if (from == to) return false; |
52 if (from == to) return false; |
53 |
53 |
54 VehicleType type = GetEngine(from)->type; |
54 VehicleType type = GetEngine(from)->type; |
55 |
55 |
56 /* check that the new vehicle type is available to the player and its type is the same as the original one */ |
56 /* check that the new vehicle type is available to the company and its type is the same as the original one */ |
57 if (!IsEngineBuildable(to, type, player)) return false; |
57 if (!IsEngineBuildable(to, type, company)) return false; |
58 |
58 |
59 switch (type) { |
59 switch (type) { |
60 case VEH_TRAIN: { |
60 case VEH_TRAIN: { |
61 const RailVehicleInfo *rvi_from = RailVehInfo(from); |
61 const RailVehicleInfo *rvi_from = RailVehInfo(from); |
62 const RailVehicleInfo *rvi_to = RailVehInfo(to); |
62 const RailVehicleInfo *rvi_to = RailVehInfo(to); |
211 } |
211 } |
212 } |
212 } |
213 |
213 |
214 /** Get the EngineID of the replacement for a vehicle |
214 /** Get the EngineID of the replacement for a vehicle |
215 * @param v The vehicle to find a replacement for |
215 * @param v The vehicle to find a replacement for |
216 * @param p The vehicle's owner (it's faster to forward the pointer than refinding it) |
216 * @param c The vehicle's owner (it's faster to forward the pointer than refinding it) |
217 * @return the EngineID of the replacement. INVALID_ENGINE if no buildable replacement is found |
217 * @return the EngineID of the replacement. INVALID_ENGINE if no buildable replacement is found |
218 */ |
218 */ |
219 static EngineID GetNewEngineType(const Vehicle *v, const Player *p) |
219 static EngineID GetNewEngineType(const Vehicle *v, const Company *c) |
220 { |
220 { |
221 assert(v->type != VEH_TRAIN || !IsArticulatedPart(v)); |
221 assert(v->type != VEH_TRAIN || !IsArticulatedPart(v)); |
222 |
222 |
223 if (v->type == VEH_TRAIN && IsRearDualheaded(v)) { |
223 if (v->type == VEH_TRAIN && IsRearDualheaded(v)) { |
224 /* we build the rear ends of multiheaded trains with the front ones */ |
224 /* we build the rear ends of multiheaded trains with the front ones */ |
225 return INVALID_ENGINE; |
225 return INVALID_ENGINE; |
226 } |
226 } |
227 |
227 |
228 EngineID e = EngineReplacementForPlayer(p, v->engine_type, v->group_id); |
228 EngineID e = EngineReplacementForCompany(c, v->engine_type, v->group_id); |
229 |
229 |
230 if (e != INVALID_ENGINE && IsEngineBuildable(e, v->type, _current_player)) { |
230 if (e != INVALID_ENGINE && IsEngineBuildable(e, v->type, _current_company)) { |
231 return e; |
231 return e; |
232 } |
232 } |
233 |
233 |
234 if (v->NeedsAutorenewing(p) && // replace if engine is too old |
234 if (v->NeedsAutorenewing(c) && // replace if engine is too old |
235 IsEngineBuildable(v->engine_type, v->type, _current_player)) { // engine can still be build |
235 IsEngineBuildable(v->engine_type, v->type, _current_company)) { // engine can still be build |
236 return v->engine_type; |
236 return v->engine_type; |
237 } |
237 } |
238 |
238 |
239 return INVALID_ENGINE; |
239 return INVALID_ENGINE; |
240 } |
240 } |
249 static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehicle, bool part_of_chain) |
249 static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehicle, bool part_of_chain) |
250 { |
250 { |
251 *new_vehicle = NULL; |
251 *new_vehicle = NULL; |
252 |
252 |
253 /* Shall the vehicle be replaced? */ |
253 /* Shall the vehicle be replaced? */ |
254 const Player *p = GetPlayer(_current_player); |
254 const Company *c = GetCompany(_current_company); |
255 EngineID e = GetNewEngineType(old_veh, p); |
255 EngineID e = GetNewEngineType(old_veh, c); |
256 if (e == INVALID_ENGINE) return CommandCost(); // neither autoreplace is set, nor autorenew is triggered |
256 if (e == INVALID_ENGINE) return CommandCost(); // neither autoreplace is set, nor autorenew is triggered |
257 |
257 |
258 /* Does it need to be refitted */ |
258 /* Does it need to be refitted */ |
259 CargoID refit_cargo = GetNewCargoTypeForReplace(old_veh, e, part_of_chain); |
259 CargoID refit_cargo = GetNewCargoTypeForReplace(old_veh, e, part_of_chain); |
260 if (refit_cargo == CT_INVALID) return CommandCost(); // incompatible cargos |
260 if (refit_cargo == CT_INVALID) return CommandCost(); // incompatible cargos |
625 if (free_wagon && IsFrontEngine(v->First())) return CMD_ERROR; |
625 if (free_wagon && IsFrontEngine(v->First())) return CMD_ERROR; |
626 } else { |
626 } else { |
627 if (!v->IsPrimaryVehicle()) return CMD_ERROR; |
627 if (!v->IsPrimaryVehicle()) return CMD_ERROR; |
628 } |
628 } |
629 |
629 |
630 const Player *p = GetPlayer(_current_player); |
630 const Company *c = GetCompany(_current_company); |
631 bool wagon_removal = p->renew_keep_length; |
631 bool wagon_removal = c->renew_keep_length; |
632 |
632 |
633 /* Test whether any replacement is set, before issuing a whole lot of commands that would end in nothing changed */ |
633 /* Test whether any replacement is set, before issuing a whole lot of commands that would end in nothing changed */ |
634 Vehicle *w = v; |
634 Vehicle *w = v; |
635 bool any_replacements = false; |
635 bool any_replacements = false; |
636 while (w != NULL && !any_replacements) { |
636 while (w != NULL && !any_replacements) { |
637 any_replacements = (GetNewEngineType(w, p) != INVALID_ENGINE); |
637 any_replacements = (GetNewEngineType(w, c) != INVALID_ENGINE); |
638 w = (!free_wagon && w->type == VEH_TRAIN ? GetNextUnit(w) : NULL); |
638 w = (!free_wagon && w->type == VEH_TRAIN ? GetNextUnit(w) : NULL); |
639 } |
639 } |
640 |
640 |
641 if (any_replacements) { |
641 if (any_replacements) { |
642 bool was_stopped = free_wagon || ((v->vehstatus & VS_STOPPED) != 0); |
642 bool was_stopped = free_wagon || ((v->vehstatus & VS_STOPPED) != 0); |