Merge branch 'template_train_replacement' into jgrpp

This commit is contained in:
Jonathan G Rennison 2018-01-30 18:58:34 +00:00
commit ec661d7ae9
3 changed files with 39 additions and 17 deletions

View File

@ -239,10 +239,11 @@ static CargoID GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type, bool
* @param v The vehicle to find a replacement for
* @param c The vehicle's owner (it's faster to forward the pointer than refinding it)
* @param always_replace Always replace, even if not old.
* @param same_type_only Only replace with same engine type.
* @param [out] e the EngineID of the replacement. INVALID_ENGINE if no replacement is found
* @return Error if the engine to build is not available
*/
static CommandCost GetNewEngineType(const Vehicle *v, const Company *c, bool always_replace, EngineID &e)
static CommandCost GetNewEngineType(const Vehicle *v, const Company *c, bool always_replace, bool same_type_only, EngineID &e)
{
assert(v->type != VEH_TRAIN || !v->IsArticulatedPart());
@ -253,9 +254,11 @@ static CommandCost GetNewEngineType(const Vehicle *v, const Company *c, bool alw
return CommandCost();
}
bool replace_when_old;
e = EngineReplacementForCompany(c, v->engine_type, v->group_id, &replace_when_old);
if (!always_replace && replace_when_old && !v->NeedsAutorenewing(c, false)) e = INVALID_ENGINE;
if (!same_type_only) {
bool replace_when_old;
e = EngineReplacementForCompany(c, v->engine_type, v->group_id, &replace_when_old);
if (!always_replace && replace_when_old && !v->NeedsAutorenewing(c, false)) e = INVALID_ENGINE;
}
/* Autoreplace, if engine is available */
if (e != INVALID_ENGINE && IsEngineBuildable(e, v->type, _current_company)) {
@ -278,16 +281,17 @@ static CommandCost GetNewEngineType(const Vehicle *v, const Company *c, bool alw
* @param old_veh A single (articulated/multiheaded) vehicle that shall be replaced.
* @param new_vehicle Returns the newly build and refitted vehicle
* @param part_of_chain The vehicle is part of a train
* @param same_type_only Only replace with same engine type.
* @return cost or error
*/
static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehicle, bool part_of_chain)
static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehicle, bool part_of_chain, bool same_type_only)
{
*new_vehicle = NULL;
/* Shall the vehicle be replaced? */
const Company *c = Company::Get(_current_company);
EngineID e;
CommandCost cost = GetNewEngineType(old_veh, c, true, e);
CommandCost cost = GetNewEngineType(old_veh, c, true, same_type_only, e);
if (cost.Failed()) return cost;
if (e == INVALID_ENGINE) return CommandCost(); // neither autoreplace is set, nor autorenew is triggered
@ -387,9 +391,10 @@ CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, DoComma
* @param single_unit vehicle to let autoreplace/renew operator on
* @param flags command flags
* @param nothing_to_do is set to 'false' when something was done (only valid when not failed)
* @param same_type_only Only replace with same engine type.
* @return cost or error
*/
static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, bool *nothing_to_do)
static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, bool *nothing_to_do, bool same_type_only)
{
Train *old_v = Train::From(*single_unit);
assert(!old_v->IsArticulatedPart() && !old_v->IsRearDualheaded());
@ -398,7 +403,7 @@ static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, b
/* Build and refit replacement vehicle */
Vehicle *new_v = NULL;
cost.AddCost(BuildReplacementVehicle(old_v, &new_v, false));
cost.AddCost(BuildReplacementVehicle(old_v, &new_v, false, same_type_only));
/* Was a new vehicle constructed? */
if (cost.Succeeded() && new_v != NULL) {
@ -437,9 +442,10 @@ static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, b
* @param flags command flags
* @param wagon_removal remove wagons when the resulting chain occupies more tiles than the old did
* @param nothing_to_do is set to 'false' when something was done (only valid when not failed)
* @param same_type_only Only replace with same engine type.
* @return cost or error
*/
static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon_removal, bool *nothing_to_do)
static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon_removal, bool *nothing_to_do, bool same_type_only)
{
Vehicle *old_head = *chain;
assert(old_head->IsPrimaryVehicle());
@ -465,7 +471,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
assert(i < num_units);
old_vehs[i] = w;
CommandCost ret = BuildReplacementVehicle(old_vehs[i], (Vehicle**)&new_vehs[i], true);
CommandCost ret = BuildReplacementVehicle(old_vehs[i], (Vehicle**)&new_vehs[i], true, same_type_only);
cost.AddCost(ret);
if (cost.Failed()) break;
@ -630,7 +636,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
} else {
/* Build and refit replacement vehicle */
Vehicle *new_head = NULL;
cost.AddCost(BuildReplacementVehicle(old_head, &new_head, true));
cost.AddCost(BuildReplacementVehicle(old_head, &new_head, true, same_type_only));
/* Was a new vehicle constructed? */
if (cost.Succeeded() && new_head != NULL) {
@ -666,7 +672,8 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
* @param tile not used
* @param flags type of operation
* @param p1 Index of vehicle
* @param p2 not used
* @param p2 packed data
* - bit 0 = Autoreplace with same type only
* @param text unused
* @return the cost of this operation or an error
*/
@ -693,13 +700,14 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1
const Company *c = Company::Get(_current_company);
bool wagon_removal = c->settings.renew_keep_length;
bool same_type_only = HasBit(p2, 0);
/* Test whether any replacement is set, before issuing a whole lot of commands that would end in nothing changed */
Vehicle *w = v;
bool any_replacements = false;
while (w != NULL) {
EngineID e;
CommandCost cost = GetNewEngineType(w, c, false, e);
CommandCost cost = GetNewEngineType(w, c, false, same_type_only, e);
if (cost.Failed()) return cost;
any_replacements |= (e != INVALID_ENGINE);
w = (!free_wagon && w->type == VEH_TRAIN ? Train::From(w)->GetNextUnit() : NULL);
@ -723,18 +731,18 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1
SavedRandomSeeds saved_seeds;
SaveRandomSeeds(&saved_seeds);
if (free_wagon) {
cost.AddCost(ReplaceFreeUnit(&v, flags & ~DC_EXEC, &nothing_to_do));
cost.AddCost(ReplaceFreeUnit(&v, flags & ~DC_EXEC, &nothing_to_do, same_type_only));
} else {
cost.AddCost(ReplaceChain(&v, flags & ~DC_EXEC, wagon_removal, &nothing_to_do));
cost.AddCost(ReplaceChain(&v, flags & ~DC_EXEC, wagon_removal, &nothing_to_do, same_type_only));
}
RestoreRandomSeeds(saved_seeds);
if (cost.Succeeded() && (flags & DC_EXEC) != 0) {
CommandCost ret;
if (free_wagon) {
ret = ReplaceFreeUnit(&v, flags, &nothing_to_do);
ret = ReplaceFreeUnit(&v, flags, &nothing_to_do, same_type_only);
} else {
ret = ReplaceChain(&v, flags, wagon_removal, &nothing_to_do);
ret = ReplaceChain(&v, flags, wagon_removal, &nothing_to_do, same_type_only);
}
assert(ret.Succeeded() && ret.GetCost() == cost.GetCost());
}

View File

@ -5035,6 +5035,8 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3
}
EngineID eid = tv->engine_type;
_new_vehicle_id = p1;
CommandCost buy(EXPENSES_NEW_VEHICLES);
CommandCost move_cost(EXPENSES_NEW_VEHICLES);
CommandCost tmp_result(EXPENSES_NEW_VEHICLES);
@ -5209,6 +5211,8 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3
/* Redraw main gui for changed statistics */
SetWindowClassesDirty(WC_TEMPLATEGUI_MAIN);
_new_vehicle_id = new_chain->index;
return buy;
}

View File

@ -1175,6 +1175,16 @@ void CallVehicleTicks()
it->first->vehstatus |= VS_STOPPED;
CommandCost res = DoCommand(t->tile, t->index, stayInDepot ? 1 : 0, DC_EXEC, CMD_TEMPLATE_REPLACE_VEHICLE);
if (res.Succeeded()) {
VehicleID t_new = _new_vehicle_id;
t = Train::From(Vehicle::Get(t_new));
const Company *c = Company::Get(_current_company);
SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, (Money)c->settings.engine_renew_money));
CommandCost res2 = DoCommand(0, t_new, 1, DC_EXEC, CMD_AUTOREPLACE_VEHICLE);
SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -(Money)c->settings.engine_renew_money));
if (res2.Succeeded() || res.GetCost() == 0) res.AddCost(res2);
}
if (!IsLocalCompany()) continue;
if (res.Succeeded()) {