summaryrefslogtreecommitdiff
path: root/src/economy.cpp
diff options
context:
space:
mode:
authorfonsinchen <fonsinchen@openttd.org>2013-06-09 13:03:48 +0000
committerfonsinchen <fonsinchen@openttd.org>2013-06-09 13:03:48 +0000
commit04e3eb6fabc0e4aff04c189368356b8af15e9655 (patch)
treeaa9d6a025fb3e343fc8cdc9358a913182445210b /src/economy.cpp
parenta2ff96d6828bd32f7beb461bfb902880bf46ef75 (diff)
downloadopenttd-04e3eb6fabc0e4aff04c189368356b8af15e9655.tar.xz
(svn r25361) -Feature: distribute cargo according to plan given by linkgraph
Diffstat (limited to 'src/economy.cpp')
-rw-r--r--src/economy.cpp70
1 files changed, 43 insertions, 27 deletions
diff --git a/src/economy.cpp b/src/economy.cpp
index 552839192..d22d35e6f 100644
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -42,6 +42,7 @@
#include "economy_base.h"
#include "core/pool_func.hpp"
#include "core/backup_type.hpp"
+#include "cargo_type.h"
#include "water.h"
#include "game/game.hpp"
#include "cargomonitor.h"
@@ -1210,33 +1211,42 @@ Money CargoPayment::PayTransfer(const CargoPacket *cp, uint count)
/**
* Prepare the vehicle to be unloaded.
+ * @param curr_station the station where the consist is at the moment
* @param front_v the vehicle to be unloaded
*/
void PrepareUnload(Vehicle *front_v)
{
+ Station *curr_station = Station::Get(front_v->last_station_visited);
+ curr_station->loading_vehicles.push_back(front_v);
+
/* At this moment loading cannot be finished */
ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
- /* Start unloading in at the first possible moment */
+ /* Start unloading at the first possible moment */
front_v->load_unload_ticks = 1;
- if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
+ assert(front_v->cargo_payment == NULL);
+ /* One CargoPayment per vehicle and the vehicle limit equals the
+ * limit in number of CargoPayments. Can't go wrong. */
+ assert_compile(CargoPaymentPool::MAX_SIZE == VehiclePool::MAX_SIZE);
+ assert(CargoPayment::CanAllocateItem());
+ front_v->cargo_payment = new CargoPayment(front_v);
+
+ StationID next_station = front_v->GetNextStoppingStation();
+ if (front_v->orders.list == NULL || (front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
+ Station *st = Station::Get(front_v->last_station_visited);
for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
+ const GoodsEntry *ge = &st->goods[v->cargo_type];
if (v->cargo_cap > 0 && v->cargo.TotalCount() > 0) {
v->cargo.Stage(
- HasBit(Station::Get(front_v->last_station_visited)->goods[v->cargo_type].acceptance_pickup, GoodsEntry::GES_ACCEPTANCE),
- front_v->last_station_visited, front_v->current_order.GetUnloadType());
+ HasBit(ge->acceptance_pickup, GoodsEntry::GES_ACCEPTANCE),
+ front_v->last_station_visited, next_station,
+ front_v->current_order.GetUnloadType(), ge,
+ front_v->cargo_payment);
if (v->cargo.UnloadCount() > 0) SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
}
}
}
-
- assert(front_v->cargo_payment == NULL);
- /* One CargoPayment per vehicle and the vehicle limit equals the
- * limit in number of CargoPayments. Can't go wrong. */
- assert_compile(CargoPaymentPool::MAX_SIZE == VehiclePool::MAX_SIZE);
- assert(CargoPayment::CanAllocateItem());
- front_v->cargo_payment = new CargoPayment(front_v);
}
/**
@@ -1280,8 +1290,9 @@ static byte GetLoadAmount(Vehicle *v)
* @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 the vehicle will stop at next.
*/
-static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft)
+static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, StationID next_station)
{
Vehicle *next_cargo = u;
uint32 seen_cargos = 0;
@@ -1310,7 +1321,7 @@ static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft)
/* Nothing to do if the vehicle is full */
if (cap > 0) {
- cap -= st->goods[v->cargo_type].cargo.Reserve(cap, &v->cargo, st->xy);
+ cap -= st->goods[v->cargo_type].cargo.Reserve(cap, &v->cargo, st->xy, next_station);
}
if (consist_capleft != NULL) {
@@ -1347,11 +1358,14 @@ static void LoadUnloadVehicle(Vehicle *front)
StationID last_visited = front->last_station_visited;
Station *st = Station::Get(last_visited);
+ StationID next_station = front->GetNextStoppingStation();
bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CT_AUTO_REFIT;
CargoArray consist_capleft;
if (_settings_game.order.improved_load &&
((front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0 || use_autorefit)) {
- ReserveConsist(st, front, (use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : NULL);
+ ReserveConsist(st, front,
+ (use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : NULL,
+ next_station);
}
/* We have not waited enough time till the next round of loading/unloading */
@@ -1408,7 +1422,7 @@ static void LoadUnloadVehicle(Vehicle *front)
uint new_remaining = v->cargo.RemainingCount() + v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER);
if (v->cargo_cap < new_remaining) {
/* Return some of the reserved cargo to not overload the vehicle. */
- v->cargo.Return(new_remaining - v->cargo_cap, &ge->cargo);
+ v->cargo.Return(new_remaining - v->cargo_cap, &ge->cargo, INVALID_STATION);
}
/* Keep instead of delivering. This may lead to no cargo being unloaded, so ...*/
@@ -1474,18 +1488,19 @@ static void LoadUnloadVehicle(Vehicle *front)
}
if (new_cid == CT_AUTO_REFIT) {
- /* Get refittable cargo type with the most waiting cargo. */
- int amount = 0;
+ /* Get a refittable cargo type with waiting cargo for next_station or INVALID_STATION. */
CargoID cid;
+ new_cid = v_start->cargo_type;
FOR_EACH_SET_CARGO_ID(cid, refit_mask) {
- /* Consider refitting to this cargo, if other vehicles of the consist cannot
- * already take the cargo without refitting */
- if ((int)st->goods[cid].cargo.AvailableCount() > (int)consist_capleft[cid] + amount) {
+ if (st->goods[cid].cargo.HasCargoFor(next_station) ||
+ st->goods[cid].cargo.HasCargoFor(INVALID_STATION)) {
/* Try to find out if auto-refitting would succeed. In case the refit is allowed,
* the returned refit capacity will be greater than zero. */
DoCommand(v_start->tile, v_start->index, cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_QUERY_COST, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
- if (_returned_refit_capacity > 0) {
- amount = st->goods[cid].cargo.AvailableCount() - consist_capleft[cid];
+ /* Try to balance different loadable cargoes between parts of the consist, so that
+ * all of them can be loaded. Avoid a situation where all vehicles suddenly switch
+ * to the first loadable cargo for which there is only one packet. */
+ if (_returned_refit_capacity > 0 && consist_capleft[cid] < consist_capleft[new_cid]) {
new_cid = cid;
}
}
@@ -1493,7 +1508,7 @@ static void LoadUnloadVehicle(Vehicle *front)
}
/* Refit if given a valid cargo. */
- if (new_cid < NUM_CARGO) {
+ if (new_cid < NUM_CARGO && new_cid != v_start->cargo_type) {
CommandCost cost = DoCommand(v_start->tile, v_start->index, new_cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_EXEC, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
if (cost.Succeeded()) front->profit_this_year -= cost.GetCost() << 8;
ge = &st->goods[v->cargo_type];
@@ -1502,7 +1517,7 @@ static void LoadUnloadVehicle(Vehicle *front)
/* Add new capacity to consist capacity and reserve cargo */
w = v_start;
do {
- st->goods[w->cargo_type].cargo.Reserve(w->cargo_cap, &w->cargo, st->xy);
+ st->goods[w->cargo_type].cargo.Reserve(w->cargo_cap, &w->cargo, st->xy, next_station);
consist_capleft[w->cargo_type] += w->cargo_cap - w->cargo.RemainingCount();
w = w->HasArticulatedPart() ? w->GetNextArticulatedPart() : NULL;
} while (w != NULL);
@@ -1534,14 +1549,15 @@ static void LoadUnloadVehicle(Vehicle *front)
ge->last_age = min(_cur_year - front->build_year, 255);
ge->time_since_pickup = 0;
+ assert(v->cargo_cap >= v->cargo.StoredCount());
/* If there's goods waiting at the station, and the vehicle
* has capacity for it, load it on the vehicle. */
- int cap_left = v->cargo_cap - v->cargo.StoredCount();
+ uint cap_left = v->cargo_cap - v->cargo.StoredCount();
if (cap_left > 0 && (v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0 || ge->cargo.AvailableCount() > 0)) {
if (_settings_game.order.gradual_loading) cap_left = min(cap_left, load_amount);
if (v->cargo.StoredCount() == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
- uint loaded = ge->cargo.Load(cap_left, &v->cargo, st->xy);
+ uint loaded = ge->cargo.Load(cap_left, &v->cargo, st->xy, next_station);
if (v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
/* Remember if there are reservations left so that we don't stop
* loading before they're loaded. */
@@ -1549,7 +1565,7 @@ static void LoadUnloadVehicle(Vehicle *front)
}
/* Store whether the maximum possible load amount was loaded or not.*/
- if (loaded == (uint)cap_left) {
+ if (loaded == cap_left) {
SetBit(full_load_amount, v->cargo_type);
} else {
ClrBit(full_load_amount, v->cargo_type);