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 |