|
@@ -36,10 +36,16 @@
|
|
|
#include "subsidy_func.h"
|
|
|
#include "station_base.h"
|
|
|
#include "economy_base.h"
|
|
|
#include "core/pool_func.hpp"
|
|
|
|
|
|
#include "table/strings.h"
|
|
|
#include "table/sprites.h"
|
|
|
|
|
|
|
|
|
/* Initialize the cargo payment-pool */
|
|
|
CargoPaymentPool _cargo_payment_pool("CargoPayment");
|
|
|
INSTANTIATE_POOL_METHODS(CargoPayment)
|
|
|
|
|
|
/**
|
|
|
* Multiply two integer values and shift the results to right.
|
|
|
*
|
|
@@ -1148,15 +1154,16 @@ static void TriggerIndustryProduction(In
|
|
|
*/
|
|
|
CargoPayment::CargoPayment(Vehicle *front) :
|
|
|
front(front),
|
|
|
route_profit(0),
|
|
|
visual_profit(0),
|
|
|
owner(NULL),
|
|
|
current_station(front->last_station_visited)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
CargoPayment::~CargoPayment()
|
|
|
{
|
|
|
if (this->CleaningPool()) return;
|
|
|
|
|
|
this->front->cargo_payment = NULL;
|
|
|
|
|
|
if (this->visual_profit == 0) return;
|
|
|
|
|
|
CompanyID old_company = _current_company;
|
|
@@ -1195,8 +1202,6 @@ void CargoPayment::PayFinalDelivery(Carg
|
|
|
|
|
|
/* The vehicle's profit is whatever route profit there is minus feeder shares. */
|
|
|
this->visual_profit += profit - cp->feeder_share;
|
|
|
|
|
|
cp->paid_for = true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1215,80 +1220,30 @@ void CargoPayment::PayTransfer(CargoPack
|
|
|
|
|
|
this->visual_profit += profit; // accumulate transfer profits for whole vehicle
|
|
|
cp->feeder_share += profit; // account for the (virtual) profit already made for the cargo packet
|
|
|
|
|
|
cp->paid_for = true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Performs the vehicle payment _and_ marks the vehicle to be unloaded.
|
|
|
* Prepare the vehicle to be unloaded.
|
|
|
* @param front_v the vehicle to be unloaded
|
|
|
*/
|
|
|
void VehiclePayment(Vehicle *front_v)
|
|
|
void PrepareUnload(Vehicle *front_v)
|
|
|
{
|
|
|
int result = 0;
|
|
|
|
|
|
Money vehicle_profit = 0; // Money paid to the train
|
|
|
Money route_profit = 0; // The grand total amount for the route. A-D of transfer chain A-B-C-D
|
|
|
Money virtual_profit = 0; // The virtual profit for entire vehicle chain
|
|
|
|
|
|
StationID last_visited = front_v->last_station_visited;
|
|
|
Station *st = Station::Get(last_visited);
|
|
|
|
|
|
/* At this moment loading cannot be finished */
|
|
|
ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
|
|
|
|
|
|
/* Start unloading in at the first possible moment */
|
|
|
front_v->load_unload_time_rem = 1;
|
|
|
|
|
|
CargoPayment payment(front_v);
|
|
|
|
|
|
for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
|
|
|
/* No cargo to unload */
|
|
|
if (v->cargo_cap == 0 || v->cargo.Empty() || (front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD)) continue;
|
|
|
|
|
|
/* All cargo has already been paid for, no need to pay again */
|
|
|
if (!v->cargo.UnpaidCargo()) {
|
|
|
SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
GoodsEntry *ge = &st->goods[v->cargo_type];
|
|
|
const CargoList::List *cargos = v->cargo.Packets();
|
|
|
|
|
|
payment.SetCargo(v->cargo_type);
|
|
|
|
|
|
for (CargoList::List::const_iterator it = cargos->begin(); it != cargos->end(); it++) {
|
|
|
CargoPacket *cp = *it;
|
|
|
if (!cp->paid_for &&
|
|
|
cp->source != last_visited &&
|
|
|
HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) &&
|
|
|
(front_v->current_order.GetUnloadType() & OUFB_TRANSFER) == 0) {
|
|
|
/* Deliver goods to the station */
|
|
|
st->time_since_unload = 0;
|
|
|
|
|
|
payment.PayFinalDelivery(cp, cp->count);
|
|
|
|
|
|
result |= 1;
|
|
|
|
|
|
SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
|
|
|
} else if (front_v->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) {
|
|
|
if (!cp->paid_for && (front_v->current_order.GetUnloadType() & OUFB_TRANSFER) != 0) {
|
|
|
payment.PayTransfer(cp, cp->count);
|
|
|
}
|
|
|
result |= 2;
|
|
|
|
|
|
if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
|
|
|
for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
|
|
|
if (v->cargo_cap > 0 && !v->cargo.Empty()) {
|
|
|
SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
|
|
|
}
|
|
|
}
|
|
|
v->cargo.InvalidateCache();
|
|
|
}
|
|
|
|
|
|
/* Call the production machinery of industries */
|
|
|
const Industry * const *isend = _cargo_delivery_destinations.End();
|
|
|
for (Industry **iid = _cargo_delivery_destinations.Begin(); iid != isend; iid++) {
|
|
|
TriggerIndustryProduction(*iid);
|
|
|
}
|
|
|
_cargo_delivery_destinations.Clear();
|
|
|
assert(front_v->cargo_payment == NULL);
|
|
|
front_v->cargo_payment = new CargoPayment(front_v);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1337,6 +1292,8 @@ static void LoadUnloadVehicle(Vehicle *v
|
|
|
|
|
|
v->cur_speed = 0;
|
|
|
|
|
|
CargoPayment *payment = v->cargo_payment;
|
|
|
|
|
|
for (; v != NULL; v = v->Next()) {
|
|
|
if (v->cargo_cap == 0) continue;
|
|
|
|
|
@@ -1358,9 +1315,11 @@ static void LoadUnloadVehicle(Vehicle *v
|
|
|
bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
|
|
|
bool accepted = false; // Is the cargo accepted by the station?
|
|
|
|
|
|
payment->SetCargo(v->cargo_type);
|
|
|
|
|
|
if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.GetUnloadType() & OUFB_TRANSFER)) {
|
|
|
/* The cargo has reached it's final destination, the packets may now be destroyed */
|
|
|
remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, last_visited);
|
|
|
remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, payment, last_visited);
|
|
|
|
|
|
result |= 1;
|
|
|
accepted = true;
|
|
@@ -1372,7 +1331,7 @@ static void LoadUnloadVehicle(Vehicle *v
|
|
|
* station is still accepting the cargo in the vehicle. It doesn't
|
|
|
* accept cargo that was loaded at the same station. */
|
|
|
if ((u->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) && (!accepted || v->cargo.Count() == cargo_count)) {
|
|
|
remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded);
|
|
|
remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded, u->current_order.GetUnloadType() & OUFB_TRANSFER ? CargoList::MTA_TRANSFER : CargoList::MTA_UNLOAD, payment);
|
|
|
SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP);
|
|
|
|
|
|
result |= 2;
|
|
@@ -1449,7 +1408,7 @@ static void LoadUnloadVehicle(Vehicle *v
|
|
|
completely_emptied = false;
|
|
|
anything_loaded = true;
|
|
|
|
|
|
ge->cargo.MoveTo(&v->cargo, cap, CargoList::MTA_CARGO_LOAD, st->xy);
|
|
|
ge->cargo.MoveTo(&v->cargo, cap, CargoList::MTA_CARGO_LOAD, NULL, st->xy);
|
|
|
|
|
|
st->time_since_load = 0;
|
|
|
st->last_vehicle_type = v->type;
|
|
@@ -1485,6 +1444,8 @@ static void LoadUnloadVehicle(Vehicle *v
|
|
|
|
|
|
v = u;
|
|
|
|
|
|
if (!anything_unloaded) delete payment;
|
|
|
|
|
|
if (anything_loaded || anything_unloaded) {
|
|
|
if (_settings_game.order.gradual_loading) {
|
|
|
/* The time it takes to load one 'slice' of cargo or passengers depends
|
|
@@ -1573,6 +1534,13 @@ void LoadUnloadStation(Station *st)
|
|
|
Vehicle *v = *iter;
|
|
|
if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
|
|
|
}
|
|
|
|
|
|
/* Call the production machinery of industries */
|
|
|
const Industry * const *isend = _cargo_delivery_destinations.End();
|
|
|
for (Industry **iid = _cargo_delivery_destinations.Begin(); iid != isend; iid++) {
|
|
|
TriggerIndustryProduction(*iid);
|
|
|
}
|
|
|
_cargo_delivery_destinations.Clear();
|
|
|
}
|
|
|
|
|
|
void CompaniesMonthlyLoop()
|