mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-16 00:12:51 +00:00
(svn r26918) -Fix [FS#6110]: Reserve cargo only after unloading finished or if the vehicle has the desired cargo already
This commit is contained in:
parent
d6fc217136
commit
75cb16a7d7
119
src/economy.cpp
119
src/economy.cpp
@ -1293,53 +1293,6 @@ static uint GetLoadAmount(Vehicle *v)
|
|||||||
return load_amount;
|
return load_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reserves cargo if the full load order and improved_load is set or if the
|
|
||||||
* current order allows autorefit.
|
|
||||||
* @param st Station where the consist is loading at the moment.
|
|
||||||
* @param u Front of the loading vehicle consist.
|
|
||||||
* @param consist_capleft If given, save free capacities after reserving there.
|
|
||||||
* @param next_station Station(s) the vehicle will stop at next.
|
|
||||||
*/
|
|
||||||
static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, StationIDStack next_station)
|
|
||||||
{
|
|
||||||
Vehicle *next_cargo = u;
|
|
||||||
uint32 seen_cargos = 0;
|
|
||||||
|
|
||||||
while (next_cargo != NULL) {
|
|
||||||
if (next_cargo->cargo_cap == 0) {
|
|
||||||
/* No need to reserve for vehicles without capacity. */
|
|
||||||
next_cargo = next_cargo->Next();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CargoID current_cargo = next_cargo->cargo_type;
|
|
||||||
|
|
||||||
Vehicle *v = next_cargo;
|
|
||||||
SetBit(seen_cargos, current_cargo);
|
|
||||||
next_cargo = NULL;
|
|
||||||
for (; v != NULL; v = v->Next()) {
|
|
||||||
if (v->cargo_type != current_cargo) {
|
|
||||||
/* Save start point for next cargo type. */
|
|
||||||
if (next_cargo == NULL && !HasBit(seen_cargos, v->cargo_type)) next_cargo = v;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(v->cargo_cap >= v->cargo.RemainingCount());
|
|
||||||
uint cap = v->cargo_cap - v->cargo.RemainingCount();
|
|
||||||
|
|
||||||
/* Nothing to do if the vehicle is full */
|
|
||||||
if (cap > 0) {
|
|
||||||
cap -= st->goods[v->cargo_type].cargo.Reserve(cap, &v->cargo, st->xy, next_station);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (consist_capleft != NULL) {
|
|
||||||
(*consist_capleft)[current_cargo] += cap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate the articulated parts of a vehicle, also considering the special cases of "normal"
|
* Iterate the articulated parts of a vehicle, also considering the special cases of "normal"
|
||||||
* aircraft and double headed trains. Apply an action to each vehicle and immediately return false
|
* aircraft and double headed trains. Apply an action to each vehicle and immediately return false
|
||||||
@ -1445,15 +1398,17 @@ struct FinalizeRefitAction
|
|||||||
CargoArray &consist_capleft; ///< Capacities left in the consist.
|
CargoArray &consist_capleft; ///< Capacities left in the consist.
|
||||||
Station *st; ///< Station to reserve cargo from.
|
Station *st; ///< Station to reserve cargo from.
|
||||||
StationIDStack &next_station; ///< Next hops to reserve cargo for.
|
StationIDStack &next_station; ///< Next hops to reserve cargo for.
|
||||||
|
bool do_reserve; ///< If the vehicle should reserve.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a finalizing action.
|
* Create a finalizing action.
|
||||||
* @param consist_capleft Capacities left in the consist.
|
* @param consist_capleft Capacities left in the consist.
|
||||||
* @param st Station to reserve cargo from.
|
* @param st Station to reserve cargo from.
|
||||||
* @param next_station Next hops to reserve cargo for.
|
* @param next_station Next hops to reserve cargo for.
|
||||||
|
* @param do_reserve If we should reserve cargo or just add up the capacities.
|
||||||
*/
|
*/
|
||||||
FinalizeRefitAction(CargoArray &consist_capleft, Station *st, StationIDStack &next_station) :
|
FinalizeRefitAction(CargoArray &consist_capleft, Station *st, StationIDStack &next_station, bool do_reserve) :
|
||||||
consist_capleft(consist_capleft), st(st), next_station(next_station) {}
|
consist_capleft(consist_capleft), st(st), next_station(next_station), do_reserve(do_reserve) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserve cargo from the station and update the remaining consist capacities with the
|
* Reserve cargo from the station and update the remaining consist capacities with the
|
||||||
@ -1463,8 +1418,10 @@ struct FinalizeRefitAction
|
|||||||
*/
|
*/
|
||||||
bool operator()(Vehicle *v)
|
bool operator()(Vehicle *v)
|
||||||
{
|
{
|
||||||
|
if (this->do_reserve) {
|
||||||
this->st->goods[v->cargo_type].cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(),
|
this->st->goods[v->cargo_type].cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(),
|
||||||
&v->cargo, st->xy, next_station);
|
&v->cargo, st->xy, this->next_station);
|
||||||
|
}
|
||||||
this->consist_capleft[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
|
this->consist_capleft[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1490,7 +1447,8 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station
|
|||||||
/* Remove old capacity from consist capacity and collect refit mask. */
|
/* Remove old capacity from consist capacity and collect refit mask. */
|
||||||
IterateVehicleParts(v_start, PrepareRefitAction(consist_capleft, refit_mask));
|
IterateVehicleParts(v_start, PrepareRefitAction(consist_capleft, refit_mask));
|
||||||
|
|
||||||
if (new_cid == CT_AUTO_REFIT) {
|
bool is_auto_refit = new_cid == CT_AUTO_REFIT;
|
||||||
|
if (is_auto_refit) {
|
||||||
/* Get a refittable cargo type with waiting cargo for next_station or INVALID_STATION. */
|
/* Get a refittable cargo type with waiting cargo for next_station or INVALID_STATION. */
|
||||||
CargoID cid;
|
CargoID cid;
|
||||||
new_cid = v_start->cargo_type;
|
new_cid = v_start->cargo_type;
|
||||||
@ -1526,11 +1484,62 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add new capacity to consist capacity and reserve cargo */
|
/* Add new capacity to consist capacity and reserve cargo */
|
||||||
IterateVehicleParts(v_start, FinalizeRefitAction(consist_capleft, st, next_station));
|
IterateVehicleParts(v_start, FinalizeRefitAction(consist_capleft, st, next_station,
|
||||||
|
is_auto_refit || (v->First()->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0));
|
||||||
|
|
||||||
cur_company.Restore();
|
cur_company.Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ReserveCargoAction {
|
||||||
|
Station *st;
|
||||||
|
StationIDStack *next_station;
|
||||||
|
|
||||||
|
ReserveCargoAction(Station *st, StationIDStack *next_station) :
|
||||||
|
st(st), next_station(next_station) {}
|
||||||
|
|
||||||
|
bool operator()(Vehicle *v)
|
||||||
|
{
|
||||||
|
if (v->cargo_cap > v->cargo.RemainingCount()) {
|
||||||
|
st->goods[v->cargo_type].cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(),
|
||||||
|
&v->cargo, st->xy, *next_station);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserves cargo if the full load order and improved_load is set or if the
|
||||||
|
* current order allows autorefit.
|
||||||
|
* @param st Station where the consist is loading at the moment.
|
||||||
|
* @param u Front of the loading vehicle consist.
|
||||||
|
* @param consist_capleft If given, save free capacities after reserving there.
|
||||||
|
* @param next_station Station(s) the vehicle will stop at next.
|
||||||
|
*/
|
||||||
|
static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, StationIDStack *next_station)
|
||||||
|
{
|
||||||
|
/* If there is a cargo payment not all vehicles of the consist have tried to do the refit.
|
||||||
|
* In that case, only reserve if it's a fixed refit and the equivalent of "articulated chain"
|
||||||
|
* a vehicle belongs to already has the right cargo. */
|
||||||
|
bool must_reserve = !u->current_order.IsRefit() || u->cargo_payment == NULL;
|
||||||
|
for (Vehicle *v = u; v != NULL; v = v->Next()) {
|
||||||
|
assert(v->cargo_cap >= v->cargo.RemainingCount());
|
||||||
|
|
||||||
|
/* Exclude various ways in which the vehicle might not be the head of an equivalent of
|
||||||
|
* "articulated chain". Also don't do the reservation if the vehicle is going to refit
|
||||||
|
* to a different cargo and hasn't tried to do so, yet. */
|
||||||
|
if (!v->IsArticulatedPart() &&
|
||||||
|
(v->type != VEH_TRAIN || !Train::From(v)->IsRearDualheaded()) &&
|
||||||
|
(v->type != VEH_AIRCRAFT || Aircraft::From(v)->IsNormalAircraft()) &&
|
||||||
|
(must_reserve || u->current_order.GetRefitCargo() == v->cargo_type)) {
|
||||||
|
IterateVehicleParts(v, ReserveCargoAction(st, next_station));
|
||||||
|
}
|
||||||
|
if (consist_capleft == NULL || v->cargo_cap == 0) continue;
|
||||||
|
(*consist_capleft)[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the vehicle's load_unload_ticks, the time it will wait until it tries to load or unload
|
* Update the vehicle's load_unload_ticks, the time it will wait until it tries to load or unload
|
||||||
* again. Adjust for overhang of trains and set it at least to 1.
|
* again. Adjust for overhang of trains and set it at least to 1.
|
||||||
@ -1566,11 +1575,11 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
StationIDStack next_station = front->GetNextStoppingStation();
|
StationIDStack next_station = front->GetNextStoppingStation();
|
||||||
bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CT_AUTO_REFIT;
|
bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CT_AUTO_REFIT;
|
||||||
CargoArray consist_capleft;
|
CargoArray consist_capleft;
|
||||||
if (_settings_game.order.improved_load &&
|
if (_settings_game.order.improved_load && use_autorefit ?
|
||||||
((front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0 || use_autorefit)) {
|
front->cargo_payment == NULL : (front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0) {
|
||||||
ReserveConsist(st, front,
|
ReserveConsist(st, front,
|
||||||
(use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : NULL,
|
(use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : NULL,
|
||||||
next_station);
|
&next_station);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have not waited enough time till the next round of loading/unloading */
|
/* We have not waited enough time till the next round of loading/unloading */
|
||||||
|
Loading…
Reference in New Issue
Block a user