diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 02cca66b66..755b51371b 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -959,6 +959,10 @@ RelativePath=".\..\src\driver.h" > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index edf15f0b4d..f0ebbcff15 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -956,6 +956,10 @@ RelativePath=".\..\src\driver.h" > + + diff --git a/source.list b/source.list index 47cf503f9f..f3ee7a5145 100644 --- a/source.list +++ b/source.list @@ -168,6 +168,7 @@ direction_func.h direction_type.h music/dmusic.h driver.h +economy_base.h economy_func.h economy_type.h effectvehicle_base.h diff --git a/src/economy.cpp b/src/economy.cpp index da429a2587..4c10eec628 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -35,6 +35,7 @@ #include "signs_base.h" #include "subsidy_func.h" #include "station_base.h" +#include "economy_base.h" #include "table/strings.h" #include "table/sprites.h" @@ -1140,6 +1141,83 @@ static void TriggerIndustryProduction(Industry *i) StartStopIndustryTileAnimation(i, IAT_INDUSTRY_RECEIVED_CARGO); } +/** + * Makes us a new cargo payment helper. + * @param front The front of the train + * @param destinations List to add the destinations of 'our' cargo to + */ +CargoPayment::CargoPayment(Vehicle *front) : + front(front), + route_profit(0), + visual_profit(0), + owner(NULL), + current_station(front->last_station_visited) +{ +} + +CargoPayment::~CargoPayment() +{ + if (this->visual_profit == 0) return; + + CompanyID old_company = _current_company; + _current_company = this->front->owner; + + SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit)); + + if (this->route_profit != 0) { + if (IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) { + SndPlayVehicleFx(SND_14_CASHTILL, this->front); + } + + ShowCostOrIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, -this->visual_profit); + } else { + ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, this->visual_profit); + } + + _current_company = old_company; +} + +/** + * Handle payment for final delivery of the given cargo packet. + * @param cp The cargo packet to pay for. + * @param count The number of packets to pay for. + */ +void CargoPayment::PayFinalDelivery(CargoPacket *cp, uint count) +{ + if (this->owner == NULL) { + this->owner = Company::Get(this->front->owner); + } + + /* Handle end of route payment */ + Money profit = DeliverGoods(count, this->ct, cp->source, this->current_station, cp->source_xy, cp->days_in_transit, this->owner); + this->route_profit += profit; + + /* The vehicle's profit is whatever route profit there is minus feeder shares. */ + this->visual_profit += profit - cp->feeder_share; + + cp->paid_for = true; +} + +/** + * Handle payment for transfer of the given cargo packet. + * @param cp The cargo packet to pay for. + * @param count The number of packets to pay for. + */ +void CargoPayment::PayTransfer(CargoPacket *cp, uint count) +{ + Money profit = GetTransportedGoodsIncome( + count, + /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */ + DistanceManhattan(cp->loaded_at_xy, Station::Get(this->current_station)->xy), + cp->days_in_transit, + this->ct); + + 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. * @param front_v the vehicle to be unloaded @@ -1154,11 +1232,6 @@ void VehiclePayment(Vehicle *front_v) StationID last_visited = front_v->last_station_visited; Station *st = Station::Get(last_visited); - Company *company = Company::Get(front_v->owner); - - /* The owner of the train wants to be paid */ - CompanyID old_company = _current_company; - _current_company = front_v->owner; /* At this moment loading cannot be finished */ ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED); @@ -1166,6 +1239,8 @@ void VehiclePayment(Vehicle *front_v) /* 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; @@ -1179,6 +1254,8 @@ void VehiclePayment(Vehicle *front_v) 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 && @@ -1188,28 +1265,14 @@ void VehiclePayment(Vehicle *front_v) /* Deliver goods to the station */ st->time_since_unload = 0; - /* handle end of route payment */ - Money profit = DeliverGoods(cp->count, v->cargo_type, cp->source, last_visited, cp->source_xy, cp->days_in_transit, company); - cp->paid_for = true; - route_profit += profit; // display amount paid for final route delivery, A-D of a chain A-B-C-D - vehicle_profit += profit - cp->feeder_share; // whole vehicle is not payed for transfers picked up earlier + 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) { - Money profit = GetTransportedGoodsIncome( - cp->count, - /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */ - DistanceManhattan(cp->loaded_at_xy, Station::Get(last_visited)->xy), - cp->days_in_transit, - v->cargo_type); - - front_v->profit_this_year += profit << 8; - virtual_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; // record that the cargo has been paid for to eliminate double counting + payment.PayTransfer(cp, cp->count); } result |= 2; @@ -1225,23 +1288,6 @@ void VehiclePayment(Vehicle *front_v) TriggerIndustryProduction(*iid); } _cargo_delivery_destinations.Clear(); - - if (virtual_profit > 0) { - ShowFeederIncomeAnimation(front_v->x_pos, front_v->y_pos, front_v->z_pos, virtual_profit); - } - - if (route_profit != 0) { - front_v->profit_this_year += vehicle_profit << 8; - SubtractMoneyFromCompany(CommandCost(front_v->GetExpenseType(true), -route_profit)); - - if (IsLocalCompany() && !PlayVehicleSound(front_v, VSE_LOAD_UNLOAD)) { - SndPlayVehicleFx(SND_14_CASHTILL, front_v); - } - - ShowCostOrIncomeAnimation(front_v->x_pos, front_v->y_pos, front_v->z_pos, -vehicle_profit); - } - - _current_company = old_company; } /** diff --git a/src/economy_base.h b/src/economy_base.h new file mode 100644 index 0000000000..433a4e8210 --- /dev/null +++ b/src/economy_base.h @@ -0,0 +1,36 @@ +/* $Id$ */ + +/** @file economy_base.h Base classes related to the economy. */ + +#ifndef ECONOMY_BASE_H +#define ECONOMY_BASE_H + +#include "cargopacket.h" + +/** + * Helper class to perform the cargo payment. + */ +struct CargoPayment { + Vehicle *front; ///< The front vehicle to do the payment of + Money route_profit; ///< The amount of money to add/remove from the bank account + Money visual_profit; ///< The visual profit to show + + Company *owner; ///< The owner of the vehicle + StationID current_station; ///< The current station + CargoID ct; ///< The currently handled cargo type + + /** Constructor for pool saveload */ + CargoPayment(Vehicle *front); + ~CargoPayment(); + + void PayTransfer(CargoPacket *cp, uint count); + void PayFinalDelivery(CargoPacket *cp, uint count); + + /** + * Sets the currently handled cargo type. + * @param ct the cargo type to handle from now on. + */ + void SetCargo(CargoID ct) { this->ct = ct; } +}; + +#endif /* ECONOMY_BASE_H */