Merge branch 'cargo_type_order' into jgrpp

# Conflicts:
#	src/order_base.h
#	src/order_gui.cpp
#	src/order_type.h
#	src/saveload/extended_ver_sl.cpp
#	src/saveload/extended_ver_sl.h
#	src/vehicle_base.h
This commit is contained in:
Jonathan G Rennison
2016-09-08 00:12:48 +01:00
19 changed files with 1079 additions and 159 deletions

View File

@@ -1867,6 +1867,7 @@ void VehicleEnterDepot(Vehicle *v)
* before the stop to the station after the stop can't be predicted
* we shouldn't construct it when the vehicle visits the next stop. */
v->last_loading_station = INVALID_STATION;
ClrBit(v->vehicle_flags, VF_LAST_LOAD_ST_SEP);
if (v->owner == _local_company) {
SetDParam(0, v->index);
AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
@@ -2339,6 +2340,33 @@ void Vehicle::DeleteUnreachedImplicitOrders()
}
}
/**
* Increase capacity for all link stats associated with vehicles in the given consist.
* @param st Station to get the link stats from.
* @param front First vehicle in the consist.
* @param next_station_id Station the consist will be travelling to next.
*/
static void VehicleIncreaseStats(const Vehicle *front)
{
for (const Vehicle *v = front; v != NULL; v = v->Next()) {
StationID last_loading_station = HasBit(front->vehicle_flags, VF_LAST_LOAD_ST_SEP) ? v->last_loading_station : front->last_loading_station;
if (v->refit_cap > 0 &&
last_loading_station != INVALID_STATION &&
last_loading_station != front->last_station_visited &&
((front->current_order.GetCargoLoadType(v->cargo_type) & OLFB_NO_LOAD) == 0 ||
(front->current_order.GetCargoUnloadType(v->cargo_type) & OUFB_NO_UNLOAD) == 0)) {
/* The cargo count can indeed be higher than the refit_cap if
* wagons have been auto-replaced and subsequently auto-
* refitted to a higher capacity. The cargo gets redistributed
* among the wagons in that case.
* As usage is not such an important figure anyway we just
* ignore the additional cargo then.*/
IncreaseStats(Station::Get(last_loading_station), v->cargo_type, front->last_station_visited, v->refit_cap,
min(v->refit_cap, v->cargo.StoredCount()), EUM_INCREASE);
}
}
}
/**
* Prepare everything to begin the loading when arriving at a station.
* @pre IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP.
@@ -2449,12 +2477,7 @@ void Vehicle::BeginLoading()
this->current_order.MakeLoading(false);
}
if (this->last_loading_station != INVALID_STATION &&
this->last_loading_station != this->last_station_visited &&
((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
(this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0)) {
IncreaseStats(Station::Get(this->last_loading_station), this, this->last_station_visited);
}
VehicleIncreaseStats(this);
PrepareUnload(this);
@@ -2486,6 +2509,21 @@ void Vehicle::CancelReservation(StationID next, Station *st)
}
}
uint32 Vehicle::GetLastLoadingStationValidCargoMask() const
{
if (!HasBit(this->vehicle_flags, VF_LAST_LOAD_ST_SEP)) {
return (this->last_loading_station != INVALID_STATION) ? ~0 : 0;
} else {
uint32 cargo_mask = 0;
for (const Vehicle *u = this; u != NULL; u = u->Next()) {
if (u->cargo_type < NUM_CARGO && u->last_loading_station != INVALID_STATION) {
SetBit(cargo_mask, u->cargo_type);
}
}
return cargo_mask;
}
}
/**
* Perform all actions when leaving a station.
* @pre this->current_order.IsType(OT_LOADING)
@@ -2500,21 +2538,54 @@ void Vehicle::LeaveStation()
/* Only update the timetable if the vehicle was supposed to stop here. */
if (this->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
if ((this->current_order.GetLoadType() & OLFB_NO_LOAD) == 0 ||
(this->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
if (this->current_order.CanLeaveWithCargo(this->last_loading_station != INVALID_STATION)) {
uint32 cargoes_can_load_unload = this->current_order.FilterLoadUnloadTypeCargoMask([&](const Order *o, CargoID cargo) {
return ((o->GetCargoLoadType(cargo) & OLFB_NO_LOAD) == 0) || ((o->GetCargoUnloadType(cargo) & OUFB_NO_UNLOAD) == 0);
});
uint32 has_cargo_mask = this->GetLastLoadingStationValidCargoMask();
uint32 cargoes_can_leave_with_cargo = FilterCargoMask([&](CargoID cargo) {
return this->current_order.CanLeaveWithCargo(HasBit(has_cargo_mask, cargo), cargo);
}, cargoes_can_load_unload);
if (cargoes_can_load_unload != 0) {
if (cargoes_can_leave_with_cargo != 0) {
/* Refresh next hop stats to make sure we've done that at least once
* during the stop and that refit_cap == cargo_cap for each vehicle in
* the consist. */
this->ResetRefitCaps();
LinkRefresher::Run(this);
LinkRefresher::Run(this, true, false, cargoes_can_leave_with_cargo);
}
if (cargoes_can_leave_with_cargo == (uint32) ~0) {
/* can leave with all cargoes */
/* if the vehicle could load here or could stop with cargo loaded set the last loading station */
this->last_loading_station = this->last_station_visited;
} else {
ClrBit(this->vehicle_flags, VF_LAST_LOAD_ST_SEP);
} else if (cargoes_can_leave_with_cargo == 0) {
/* can leave with no cargoes */
/* if the vehicle couldn't load and had to unload or transfer everything
* set the last loading station to invalid as it will leave empty. */
this->last_loading_station = INVALID_STATION;
ClrBit(this->vehicle_flags, VF_LAST_LOAD_ST_SEP);
} else {
/* mix of cargoes loadable or could not leave with all cargoes */
/* NB: this is saved here as we overwrite it on the first iteration of the loop below */
StationID head_last_loading_station = this->last_loading_station;
for (Vehicle *u = this; u != NULL; u = u->Next()) {
StationID last_loading_station = HasBit(this->vehicle_flags, VF_LAST_LOAD_ST_SEP) ? u->last_loading_station : head_last_loading_station;
if (u->cargo_type < NUM_CARGO && HasBit(cargoes_can_load_unload, u->cargo_type)) {
if (HasBit(cargoes_can_leave_with_cargo, u->cargo_type)) {
u->last_loading_station = this->last_station_visited;
} else {
u->last_loading_station = INVALID_STATION;
}
} else {
u->last_loading_station = last_loading_station;
}
}
SetBit(this->vehicle_flags, VF_LAST_LOAD_ST_SEP);
}
}