mirror of https://github.com/OpenTTD/OpenTTD
(svn r16742) [0.7] -Backport from trunk:
- Fix: Only pay for whatever has been actually unloaded and perform the payment when unloading has finished [FS#2995] (r16694)release/0.7
parent
876d064c4d
commit
a97240dede
|
@ -955,6 +955,10 @@
|
||||||
RelativePath=".\..\src\driver.h"
|
RelativePath=".\..\src\driver.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\economy_base.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\economy_func.h"
|
RelativePath=".\..\src\economy_func.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -952,6 +952,10 @@
|
||||||
RelativePath=".\..\src\driver.h"
|
RelativePath=".\..\src\driver.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\economy_base.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\economy_func.h"
|
RelativePath=".\..\src\economy_func.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -167,6 +167,7 @@ direction_func.h
|
||||||
direction_type.h
|
direction_type.h
|
||||||
music/dmusic.h
|
music/dmusic.h
|
||||||
driver.h
|
driver.h
|
||||||
|
economy_base.h
|
||||||
economy_func.h
|
economy_func.h
|
||||||
economy_type.h
|
economy_type.h
|
||||||
effectvehicle_base.h
|
effectvehicle_base.h
|
||||||
|
|
|
@ -111,7 +111,7 @@ static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chai
|
||||||
uint amount = min(src->cargo.Count(), dest->cargo_cap - dest->cargo.Count());
|
uint amount = min(src->cargo.Count(), dest->cargo_cap - dest->cargo.Count());
|
||||||
if (amount <= 0) continue;
|
if (amount <= 0) continue;
|
||||||
|
|
||||||
src->cargo.MoveTo(&dest->cargo, amount);
|
src->cargo.MoveTo(&dest->cargo, amount, CargoList::MTA_UNLOAD, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "station_base.h"
|
#include "station_base.h"
|
||||||
#include "oldpool_func.h"
|
#include "oldpool_func.h"
|
||||||
|
#include "economy_base.h"
|
||||||
|
|
||||||
/* Initialize the cargopacket-pool */
|
/* Initialize the cargopacket-pool */
|
||||||
DEFINE_OLD_POOL_GENERIC(CargoPacket, CargoPacket)
|
DEFINE_OLD_POOL_GENERIC(CargoPacket, CargoPacket)
|
||||||
|
@ -27,7 +28,6 @@ CargoPacket::CargoPacket(StationID source, uint16 count)
|
||||||
this->count = count;
|
this->count = count;
|
||||||
this->days_in_transit = 0;
|
this->days_in_transit = 0;
|
||||||
this->feeder_share = 0;
|
this->feeder_share = 0;
|
||||||
this->paid_for = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CargoPacket::~CargoPacket()
|
CargoPacket::~CargoPacket()
|
||||||
|
@ -37,7 +37,7 @@ CargoPacket::~CargoPacket()
|
||||||
|
|
||||||
bool CargoPacket::SameSource(const CargoPacket *cp) const
|
bool CargoPacket::SameSource(const CargoPacket *cp) const
|
||||||
{
|
{
|
||||||
return this->source_xy == cp->source_xy && this->days_in_transit == cp->days_in_transit && this->paid_for == cp->paid_for;
|
return this->source_xy == cp->source_xy && this->days_in_transit == cp->days_in_transit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -81,11 +81,6 @@ uint CargoList::Count() const
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CargoList::UnpaidCargo() const
|
|
||||||
{
|
|
||||||
return unpaid_cargo;
|
|
||||||
}
|
|
||||||
|
|
||||||
Money CargoList::FeederShare() const
|
Money CargoList::FeederShare() const
|
||||||
{
|
{
|
||||||
return feeder_share;
|
return feeder_share;
|
||||||
|
@ -146,9 +141,10 @@ void CargoList::Truncate(uint count)
|
||||||
InvalidateCache();
|
InvalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, uint data)
|
bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, CargoPayment *payment, uint data)
|
||||||
{
|
{
|
||||||
assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
|
assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
|
||||||
|
assert(mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL);
|
||||||
CargoList tmp;
|
CargoList tmp;
|
||||||
|
|
||||||
while (!packets.empty() && count > 0) {
|
while (!packets.empty() && count > 0) {
|
||||||
|
@ -161,20 +157,25 @@ bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta,
|
||||||
if (cp->source == data) {
|
if (cp->source == data) {
|
||||||
tmp.Append(cp);
|
tmp.Append(cp);
|
||||||
} else {
|
} else {
|
||||||
|
payment->PayFinalDelivery(cp, cp->count);
|
||||||
count -= cp->count;
|
count -= cp->count;
|
||||||
delete cp;
|
delete cp;
|
||||||
}
|
}
|
||||||
break;
|
continue; // of the loop
|
||||||
|
|
||||||
case MTA_CARGO_LOAD:
|
case MTA_CARGO_LOAD:
|
||||||
cp->loaded_at_xy = data;
|
cp->loaded_at_xy = data;
|
||||||
/* When cargo is moved into another vehicle you have *always* paid for it */
|
break;
|
||||||
cp->paid_for = false;
|
|
||||||
/* FALL THROUGH */
|
case MTA_TRANSFER:
|
||||||
case MTA_OTHER:
|
payment->PayTransfer(cp, cp->count);
|
||||||
count -= cp->count;
|
break;
|
||||||
dest->packets.push_back(cp);
|
|
||||||
|
case MTA_UNLOAD:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
count -= cp->count;
|
||||||
|
dest->packets.push_back(cp);
|
||||||
} else {
|
} else {
|
||||||
/* Can move only part of the packet, so split it into two pieces */
|
/* Can move only part of the packet, so split it into two pieces */
|
||||||
if (mta != MTA_FINAL_DELIVERY) {
|
if (mta != MTA_FINAL_DELIVERY) {
|
||||||
|
@ -189,11 +190,13 @@ bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta,
|
||||||
|
|
||||||
cp_new->days_in_transit = cp->days_in_transit;
|
cp_new->days_in_transit = cp->days_in_transit;
|
||||||
cp_new->feeder_share = fs;
|
cp_new->feeder_share = fs;
|
||||||
/* When cargo is moved into another vehicle you have *always* paid for it */
|
|
||||||
cp_new->paid_for = (mta == MTA_CARGO_LOAD) ? false : cp->paid_for;
|
|
||||||
|
|
||||||
cp_new->count = count;
|
cp_new->count = count;
|
||||||
dest->packets.push_back(cp_new);
|
dest->packets.push_back(cp_new);
|
||||||
|
|
||||||
|
if (mta == MTA_TRANSFER) payment->PayTransfer(cp_new, count);
|
||||||
|
} else {
|
||||||
|
payment->PayFinalDelivery(cp, count);
|
||||||
}
|
}
|
||||||
cp->count -= count;
|
cp->count -= count;
|
||||||
|
|
||||||
|
@ -205,7 +208,7 @@ bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta,
|
||||||
|
|
||||||
if (mta == MTA_FINAL_DELIVERY && !tmp.Empty()) {
|
if (mta == MTA_FINAL_DELIVERY && !tmp.Empty()) {
|
||||||
/* There are some packets that could not be delivered at the station, put them back */
|
/* There are some packets that could not be delivered at the station, put them back */
|
||||||
tmp.MoveTo(this, UINT_MAX);
|
tmp.MoveTo(this, UINT_MAX, MTA_UNLOAD, NULL);
|
||||||
tmp.packets.clear();
|
tmp.packets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +222,6 @@ void CargoList::InvalidateCache()
|
||||||
{
|
{
|
||||||
empty = packets.empty();
|
empty = packets.empty();
|
||||||
count = 0;
|
count = 0;
|
||||||
unpaid_cargo = false;
|
|
||||||
feeder_share = 0;
|
feeder_share = 0;
|
||||||
source = INVALID_STATION;
|
source = INVALID_STATION;
|
||||||
days_in_transit = 0;
|
days_in_transit = 0;
|
||||||
|
@ -229,7 +231,6 @@ void CargoList::InvalidateCache()
|
||||||
uint dit = 0;
|
uint dit = 0;
|
||||||
for (List::const_iterator it = packets.begin(); it != packets.end(); it++) {
|
for (List::const_iterator it = packets.begin(); it != packets.end(); it++) {
|
||||||
count += (*it)->count;
|
count += (*it)->count;
|
||||||
unpaid_cargo |= !(*it)->paid_for;
|
|
||||||
dit += (*it)->days_in_transit * (*it)->count;
|
dit += (*it)->days_in_transit * (*it)->count;
|
||||||
feeder_share += (*it)->feeder_share;
|
feeder_share += (*it)->feeder_share;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ struct CargoPacket : PoolItem<CargoPacket, CargoPacketID, &_CargoPacket_pool> {
|
||||||
|
|
||||||
uint16 count; ///< The amount of cargo in this packet
|
uint16 count; ///< The amount of cargo in this packet
|
||||||
byte days_in_transit; ///< Amount of days this packet has been in transit
|
byte days_in_transit; ///< Amount of days this packet has been in transit
|
||||||
bool paid_for; ///< Have we been paid for this cargo packet?
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new cargo packet
|
* Creates a new cargo packet
|
||||||
|
@ -85,7 +84,8 @@ public:
|
||||||
enum MoveToAction {
|
enum MoveToAction {
|
||||||
MTA_FINAL_DELIVERY, ///< "Deliver" the packet to the final destination, i.e. destroy the packet
|
MTA_FINAL_DELIVERY, ///< "Deliver" the packet to the final destination, i.e. destroy the packet
|
||||||
MTA_CARGO_LOAD, ///< Load the packet onto a vehicle, i.e. set the last loaded station ID
|
MTA_CARGO_LOAD, ///< Load the packet onto a vehicle, i.e. set the last loaded station ID
|
||||||
MTA_OTHER ///< "Just" move the packet to another cargo list
|
MTA_TRANSFER, ///< The cargo is moved as part of a transfer
|
||||||
|
MTA_UNLOAD, ///< The cargo is moved as part of a forced unload
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -93,7 +93,6 @@ private:
|
||||||
|
|
||||||
bool empty; ///< Cache for whether this list is empty or not
|
bool empty; ///< Cache for whether this list is empty or not
|
||||||
uint count; ///< Cache for the number of cargo entities
|
uint count; ///< Cache for the number of cargo entities
|
||||||
bool unpaid_cargo; ///< Cache for the unpaid cargo
|
|
||||||
Money feeder_share; ///< Cache for the feeder share
|
Money feeder_share; ///< Cache for the feeder share
|
||||||
StationID source; ///< Cache for the source of the packet
|
StationID source; ///< Cache for the source of the packet
|
||||||
uint days_in_transit; ///< Cache for the number of days in transit
|
uint days_in_transit; ///< Cache for the number of days in transit
|
||||||
|
@ -129,12 +128,6 @@ public:
|
||||||
*/
|
*/
|
||||||
uint Count() const;
|
uint Count() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Is there some cargo that has not been paid for?
|
|
||||||
* @return true if and only if there is such a cargo
|
|
||||||
*/
|
|
||||||
bool UnpaidCargo() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns total sum of the feeder share for all packets
|
* Returns total sum of the feeder share for all packets
|
||||||
* @return the before mentioned number
|
* @return the before mentioned number
|
||||||
|
@ -175,18 +168,23 @@ public:
|
||||||
* Depending on the value of mta the side effects of this function differ:
|
* Depending on the value of mta the side effects of this function differ:
|
||||||
* - MTA_FINAL_DELIVERY: destroys the packets that do not originate from a specific station
|
* - MTA_FINAL_DELIVERY: destroys the packets that do not originate from a specific station
|
||||||
* - MTA_CARGO_LOAD: sets the loaded_at_xy value of the moved packets
|
* - MTA_CARGO_LOAD: sets the loaded_at_xy value of the moved packets
|
||||||
* - MTA_OTHER: just move without side effects
|
* - MTA_TRANSFER: just move without side effects
|
||||||
|
* - MTA_UNLOAD: just move without side effects
|
||||||
* @param dest the destination to move the cargo to
|
* @param dest the destination to move the cargo to
|
||||||
* @param count the amount of cargo entities to move
|
* @param count the amount of cargo entities to move
|
||||||
* @param mta how to handle the moving (side effects)
|
* @param mta how to handle the moving (side effects)
|
||||||
* @param data Depending on mta the data of this variable differs:
|
* @param data Depending on mta the data of this variable differs:
|
||||||
* - MTA_FINAL_DELIVERY - station ID of packet's origin not to remove
|
* - MTA_FINAL_DELIVERY - station ID of packet's origin not to remove
|
||||||
* - MTA_CARGO_LOAD - station's tile index of load
|
* - MTA_CARGO_LOAD - station's tile index of load
|
||||||
* - MTA_OTHER - unused
|
* - MTA_TRANSFER - unused
|
||||||
* @param mta == MTA_FINAL_DELIVERY || dest != NULL
|
* - MTA_UNLOAD - unused
|
||||||
|
* @param payment The payment helper
|
||||||
|
*
|
||||||
|
* @pre mta == MTA_FINAL_DELIVERY || dest != NULL
|
||||||
|
* @pre mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL
|
||||||
* @return true if there are still packets that might be moved from this cargo list
|
* @return true if there are still packets that might be moved from this cargo list
|
||||||
*/
|
*/
|
||||||
bool MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta = MTA_OTHER, uint data = 0);
|
bool MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, CargoPayment *payment, uint data = 0);
|
||||||
|
|
||||||
/** Invalidates the cached data and rebuild it */
|
/** Invalidates the cached data and rebuild it */
|
||||||
void InvalidateCache();
|
void InvalidateCache();
|
||||||
|
|
240
src/economy.cpp
240
src/economy.cpp
|
@ -32,10 +32,16 @@
|
||||||
#include "autoreplace_func.h"
|
#include "autoreplace_func.h"
|
||||||
#include "company_gui.h"
|
#include "company_gui.h"
|
||||||
#include "signs_base.h"
|
#include "signs_base.h"
|
||||||
|
#include "economy_base.h"
|
||||||
|
#include "oldpool_func.h"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
#include "table/sprites.h"
|
#include "table/sprites.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize the cargo payment-pool */
|
||||||
|
DEFINE_OLD_POOL_GENERIC(CargoPayment, CargoPayment)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiply two integer values and shift the results to right.
|
* Multiply two integer values and shift the results to right.
|
||||||
*
|
*
|
||||||
|
@ -1220,15 +1226,17 @@ static bool FindIndustryToDeliver(TileIndex ind_tile, void *user_data)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The industries we've currently brought cargo to. */
|
||||||
|
static SmallIndustryList _cargo_delivery_destinations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfer goods from station to industry.
|
* Transfer goods from station to industry.
|
||||||
* All cargo is delivered to the nearest (Manhattan) industry to the station sign, which is inside the acceptance rectangle and actually accepts the cargo.
|
* All cargo is delivered to the nearest (Manhattan) industry to the station sign, which is inside the acceptance rectangle and actually accepts the cargo.
|
||||||
* @param st The station that accepted the cargo
|
* @param st The station that accepted the cargo
|
||||||
* @param cargo_type Type of cargo delivered
|
* @param cargo_type Type of cargo delivered
|
||||||
* @param nun_pieces Amount of cargo delivered
|
* @param nun_pieces Amount of cargo delivered
|
||||||
* @param industry_set The destination industry will be inserted into this set
|
|
||||||
*/
|
*/
|
||||||
static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int num_pieces, SmallIndustryList *industry_set)
|
static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int num_pieces)
|
||||||
{
|
{
|
||||||
if (st->rect.IsEmpty()) return;
|
if (st->rect.IsEmpty()) return;
|
||||||
|
|
||||||
|
@ -1267,13 +1275,14 @@ static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int nu
|
||||||
assert(best != NULL);
|
assert(best != NULL);
|
||||||
|
|
||||||
/* Insert the industry into industry_set, if not yet contained */
|
/* Insert the industry into industry_set, if not yet contained */
|
||||||
if (industry_set != NULL) industry_set->Include(best);
|
_cargo_delivery_destinations.Include(best);
|
||||||
|
|
||||||
best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
|
best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type)
|
|
||||||
|
static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type, CompanyID company)
|
||||||
{
|
{
|
||||||
Subsidy *s;
|
Subsidy *s;
|
||||||
TileIndex xy;
|
TileIndex xy;
|
||||||
|
@ -1325,7 +1334,7 @@ static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type)
|
||||||
pair = SetupSubsidyDecodeParam(s, 0);
|
pair = SetupSubsidyDecodeParam(s, 0);
|
||||||
InjectDParam(1);
|
InjectDParam(1);
|
||||||
|
|
||||||
SetDParam(0, _current_company);
|
SetDParam(0, company);
|
||||||
AddNewsItem(
|
AddNewsItem(
|
||||||
STR_2031_SERVICE_SUBSIDY_AWARDED + _settings_game.difficulty.subsidy_multiplier,
|
STR_2031_SERVICE_SUBSIDY_AWARDED + _settings_game.difficulty.subsidy_multiplier,
|
||||||
NS_SUBSIDIES,
|
NS_SUBSIDIES,
|
||||||
|
@ -1347,10 +1356,10 @@ static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type)
|
||||||
* @param dest Station the cargo has been unloaded
|
* @param dest Station the cargo has been unloaded
|
||||||
* @param source_tile The origin of the cargo for distance calculation
|
* @param source_tile The origin of the cargo for distance calculation
|
||||||
* @param days_in_transit Travel time
|
* @param days_in_transit Travel time
|
||||||
* @param industry_set The delivered industry will be inserted into this set, if not yet contained
|
* @param company The company delivering the cargo
|
||||||
* The cargo is just added to the stockpile of the industry. It is due to the caller to trigger the industry's production machinery
|
* The cargo is just added to the stockpile of the industry. It is due to the caller to trigger the industry's production machinery
|
||||||
*/
|
*/
|
||||||
static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source, StationID dest, TileIndex source_tile, byte days_in_transit, SmallIndustryList *industry_set)
|
static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company)
|
||||||
{
|
{
|
||||||
bool subsidised;
|
bool subsidised;
|
||||||
Station *s_from, *s_to;
|
Station *s_from, *s_to;
|
||||||
|
@ -1359,18 +1368,15 @@ static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source,
|
||||||
assert(num_pieces > 0);
|
assert(num_pieces > 0);
|
||||||
|
|
||||||
/* Update company statistics */
|
/* Update company statistics */
|
||||||
{
|
company->cur_economy.delivered_cargo += num_pieces;
|
||||||
Company *c = GetCompany(_current_company);
|
SetBit(company->cargo_types, cargo_type);
|
||||||
c->cur_economy.delivered_cargo += num_pieces;
|
|
||||||
SetBit(c->cargo_types, cargo_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get station pointers. */
|
/* Get station pointers. */
|
||||||
s_from = IsValidStationID(source) ? GetStation(source) : NULL;
|
s_from = IsValidStationID(source) ? GetStation(source) : NULL;
|
||||||
s_to = GetStation(dest);
|
s_to = GetStation(dest);
|
||||||
|
|
||||||
/* Check if a subsidy applies. */
|
/* Check if a subsidy applies. */
|
||||||
subsidised = s_from != NULL && CheckSubsidised(s_from, s_to, cargo_type);
|
subsidised = s_from != NULL && CheckSubsidised(s_from, s_to, cargo_type, company->index);
|
||||||
|
|
||||||
/* Increase town's counter for some special goods types */
|
/* Increase town's counter for some special goods types */
|
||||||
const CargoSpec *cs = GetCargo(cargo_type);
|
const CargoSpec *cs = GetCargo(cargo_type);
|
||||||
|
@ -1378,7 +1384,7 @@ static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source,
|
||||||
if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces;
|
if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces;
|
||||||
|
|
||||||
/* Give the goods to the industry. */
|
/* Give the goods to the industry. */
|
||||||
DeliverGoodsToIndustry(s_to, cargo_type, num_pieces, industry_set);
|
DeliverGoodsToIndustry(s_to, cargo_type, num_pieces);
|
||||||
|
|
||||||
/* Determine profit */
|
/* Determine profit */
|
||||||
profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, s_to->xy), days_in_transit, cargo_type);
|
profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, s_to->xy), days_in_transit, cargo_type);
|
||||||
|
@ -1432,109 +1438,107 @@ static void TriggerIndustryProduction(Industry *i)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the vehicle payment _and_ marks the vehicle to be unloaded.
|
* 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),
|
||||||
|
current_station(front->last_station_visited)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CargoPayment::~CargoPayment()
|
||||||
|
{
|
||||||
|
if (this->CleaningPool()) return;
|
||||||
|
|
||||||
|
this->front->cargo_payment = NULL;
|
||||||
|
|
||||||
|
if (this->visual_profit == 0) {
|
||||||
|
this->front = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompanyID old_company = _current_company;
|
||||||
|
_current_company = this->front->owner;
|
||||||
|
|
||||||
|
SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
|
||||||
|
this->front->profit_this_year += this->visual_profit << 8;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
this->front = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = GetCompany(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, GetStation(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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the vehicle to be unloaded.
|
||||||
* @param front_v 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 = GetStation(last_visited);
|
|
||||||
|
|
||||||
/* 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 */
|
/* At this moment loading cannot be finished */
|
||||||
ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
|
ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
|
||||||
|
|
||||||
/* Start unloading in at the first possible moment */
|
/* Start unloading in at the first possible moment */
|
||||||
front_v->load_unload_time_rem = 1;
|
front_v->load_unload_time_rem = 1;
|
||||||
|
|
||||||
/* Collect delivered industries */
|
if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
|
||||||
static SmallIndustryList industry_set;
|
for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
|
||||||
industry_set.Clear();
|
if (v->cargo_cap > 0 && !v->cargo.Empty()) {
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* handle end of route payment */
|
|
||||||
Money profit = DeliverGoods(cp->count, v->cargo_type, cp->source, last_visited, cp->source_xy, cp->days_in_transit, &industry_set);
|
|
||||||
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
|
|
||||||
|
|
||||||
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, GetStation(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
|
|
||||||
}
|
|
||||||
result |= 2;
|
|
||||||
|
|
||||||
SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
|
SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v->cargo.InvalidateCache();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call the production machinery of industries only once for every vehicle chain */
|
assert(front_v->cargo_payment == NULL);
|
||||||
const Industry * const *isend = industry_set.End();
|
front_v->cargo_payment = new CargoPayment(front_v);
|
||||||
for (Industry **iid = industry_set.Begin(); iid != isend; iid++) {
|
|
||||||
TriggerIndustryProduction(*iid);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1583,6 +1587,8 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
||||||
|
|
||||||
v->cur_speed = 0;
|
v->cur_speed = 0;
|
||||||
|
|
||||||
|
CargoPayment *payment = v->cargo_payment;
|
||||||
|
|
||||||
for (; v != NULL; v = v->Next()) {
|
for (; v != NULL; v = v->Next()) {
|
||||||
if (v->cargo_cap == 0) continue;
|
if (v->cargo_cap == 0) continue;
|
||||||
|
|
||||||
|
@ -1604,9 +1610,11 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
||||||
bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
|
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?
|
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)) {
|
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 */
|
/* 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;
|
result |= 1;
|
||||||
accepted = true;
|
accepted = true;
|
||||||
|
@ -1618,14 +1626,20 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
||||||
* station is still accepting the cargo in the vehicle. It doesn't
|
* station is still accepting the cargo in the vehicle. It doesn't
|
||||||
* accept cargo that was loaded at the same station. */
|
* accept cargo that was loaded at the same station. */
|
||||||
if (u->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER) && (!accepted || v->cargo.Count() == cargo_count)) {
|
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);
|
SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP);
|
||||||
|
|
||||||
result |= 2;
|
result |= 2;
|
||||||
} else if (!accepted) {
|
} else if (!accepted) {
|
||||||
/* The order changed while unloading (unset unload/transfer) or the
|
/* The order changed while unloading (unset unload/transfer) or the
|
||||||
* station does not accept goods anymore. */
|
* station does not accept our goods. */
|
||||||
ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
|
ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
|
||||||
|
|
||||||
|
/* Say we loaded something, otherwise we'll think we didn't unload
|
||||||
|
* something and we didn't load something, so we must be finished
|
||||||
|
* at this station. Setting the unloaded means that we will get a
|
||||||
|
* retry for loading in the next cycle. */
|
||||||
|
anything_unloaded = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1695,7 +1709,7 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
||||||
completely_emptied = false;
|
completely_emptied = false;
|
||||||
anything_loaded = true;
|
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->time_since_load = 0;
|
||||||
st->last_vehicle_type = v->type;
|
st->last_vehicle_type = v->type;
|
||||||
|
@ -1731,6 +1745,8 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
||||||
|
|
||||||
v = u;
|
v = u;
|
||||||
|
|
||||||
|
if (!anything_unloaded) delete payment;
|
||||||
|
|
||||||
if (anything_loaded || anything_unloaded) {
|
if (anything_loaded || anything_unloaded) {
|
||||||
if (_settings_game.order.gradual_loading) {
|
if (_settings_game.order.gradual_loading) {
|
||||||
/* The time it takes to load one 'slice' of cargo or passengers depends
|
/* The time it takes to load one 'slice' of cargo or passengers depends
|
||||||
|
@ -1807,6 +1823,9 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
||||||
*/
|
*/
|
||||||
void LoadUnloadStation(Station *st)
|
void LoadUnloadStation(Station *st)
|
||||||
{
|
{
|
||||||
|
/* No vehicle is here... */
|
||||||
|
if (st->loading_vehicles.empty()) return;
|
||||||
|
|
||||||
int cargo_left[NUM_CARGO];
|
int cargo_left[NUM_CARGO];
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count();
|
for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count();
|
||||||
|
@ -1816,6 +1835,13 @@ void LoadUnloadStation(Station *st)
|
||||||
Vehicle *v = *iter;
|
Vehicle *v = *iter;
|
||||||
if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
|
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()
|
void CompaniesMonthlyLoop()
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/** @file economy_base.h Base classes related to the economy. */
|
||||||
|
|
||||||
|
#ifndef ECONOMY_BASE_H
|
||||||
|
#define ECONOMY_BASE_H
|
||||||
|
|
||||||
|
#include "cargopacket.h"
|
||||||
|
|
||||||
|
DECLARE_OLD_POOL(CargoPayment, CargoPayment, 9, 125)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to perform the cargo payment.
|
||||||
|
*/
|
||||||
|
struct CargoPayment : PoolItem<CargoPayment, CargoPaymentID, &_CargoPayment_pool> {
|
||||||
|
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
|
||||||
|
|
||||||
|
/* Unsaved variables */
|
||||||
|
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() {}
|
||||||
|
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; }
|
||||||
|
|
||||||
|
inline bool IsValid() const { return this->front != NULL; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FOR_ALL_CARGO_PAYMENTS_FROM(v, start) for (v = GetCargoPayment(start); v != NULL; v = (v->index + 1U < GetCargoPaymentPoolSize()) ? GetCargoPayment(v->index + 1) : NULL) if (v->IsValid())
|
||||||
|
#define FOR_ALL_CARGO_PAYMENTS(var) FOR_ALL_CARGO_PAYMENTS_FROM(var, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this savegame is a savegame with cargo payment or not.
|
||||||
|
* This is important to know when loading a savegame.
|
||||||
|
*/
|
||||||
|
extern bool _cargo_payment_savegame;
|
||||||
|
|
||||||
|
#endif /* ECONOMY_BASE_H */
|
|
@ -39,7 +39,7 @@ void StartupIndustryDailyChanges(bool init_counter);
|
||||||
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type);
|
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type);
|
||||||
uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount);
|
uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount);
|
||||||
|
|
||||||
void VehiclePayment(Vehicle *front_v);
|
void PrepareUnload(Vehicle *front_v);
|
||||||
void LoadUnloadStation(Station *st);
|
void LoadUnloadStation(Station *st);
|
||||||
|
|
||||||
Money GetPriceByIndex(uint8 index);
|
Money GetPriceByIndex(uint8 index);
|
||||||
|
|
|
@ -136,4 +136,7 @@ enum {
|
||||||
LOAN_INTERVAL_OLD_AI = 50000,
|
LOAN_INTERVAL_OLD_AI = 50000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CargoPayment;
|
||||||
|
typedef uint32 CargoPaymentID;
|
||||||
|
|
||||||
#endif /* ECONOMY_TYPE_H */
|
#endif /* ECONOMY_TYPE_H */
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "../ai/ai.hpp"
|
#include "../ai/ai.hpp"
|
||||||
#include "../animated_tile_func.h"
|
#include "../animated_tile_func.h"
|
||||||
|
|
||||||
|
#include "../economy_base.h"
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
#include "saveload_internal.h"
|
#include "saveload_internal.h"
|
||||||
|
@ -541,6 +542,13 @@ bool AfterLoadGame()
|
||||||
if (!IsValidCompanyID(COMPANY_FIRST) && (!_networking || (_networking && _network_server && !_network_dedicated)))
|
if (!IsValidCompanyID(COMPANY_FIRST) && (!_networking || (_networking && _network_server && !_network_dedicated)))
|
||||||
DoStartupNewCompany(false);
|
DoStartupNewCompany(false);
|
||||||
|
|
||||||
|
/* Fix the cache for cargo payments. */
|
||||||
|
CargoPayment *cp;
|
||||||
|
FOR_ALL_CARGO_PAYMENTS(cp) {
|
||||||
|
cp->front->cargo_payment = cp;
|
||||||
|
cp->current_station = cp->front->last_station_visited;
|
||||||
|
}
|
||||||
|
|
||||||
if (CheckSavegameVersion(72)) {
|
if (CheckSavegameVersion(72)) {
|
||||||
/* Locks/shiplifts in very old savegames had OWNER_WATER as owner */
|
/* Locks/shiplifts in very old savegames had OWNER_WATER as owner */
|
||||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||||
|
@ -1269,13 +1277,8 @@ bool AfterLoadGame()
|
||||||
* stored to stop people cheating and cashing in several times. This
|
* stored to stop people cheating and cashing in several times. This
|
||||||
* wasn't enough though as it was cleared when the vehicle started
|
* wasn't enough though as it was cleared when the vehicle started
|
||||||
* loading again, even if it didn't actually load anything, so now the
|
* loading again, even if it didn't actually load anything, so now the
|
||||||
* amount of cargo that has been paid for is stored. */
|
* amount that has been paid is stored. */
|
||||||
FOR_ALL_VEHICLES(v) {
|
FOR_ALL_VEHICLES(v) {
|
||||||
const CargoList::List *packets = v->cargo.Packets();
|
|
||||||
for (CargoList::List::const_iterator it = packets->begin(); it != packets->end(); it++) {
|
|
||||||
CargoPacket *cp = *it;
|
|
||||||
cp->paid_for = HasBit(v->vehicle_flags, 2);
|
|
||||||
}
|
|
||||||
ClrBit(v->vehicle_flags, 2);
|
ClrBit(v->vehicle_flags, 2);
|
||||||
v->cargo.InvalidateCache();
|
v->cargo.InvalidateCache();
|
||||||
}
|
}
|
||||||
|
@ -1846,6 +1849,22 @@ bool AfterLoadGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_cargo_payment_savegame) {
|
||||||
|
/* We didn't store cargo payment yet, so make them for vehicles that are
|
||||||
|
* currently at a station and loading/unloading. If they don't get any
|
||||||
|
* payment anymore they just removed in the next load/unload cycle.
|
||||||
|
*/
|
||||||
|
Station *st;
|
||||||
|
FOR_ALL_STATIONS(st) {
|
||||||
|
std::list<Vehicle *>::iterator iter;
|
||||||
|
for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
|
||||||
|
Vehicle *v = *iter;
|
||||||
|
assert(v->cargo_payment == NULL);
|
||||||
|
v->cargo_payment = new CargoPayment(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (CheckSavegameVersion(122)) {
|
if (CheckSavegameVersion(122)) {
|
||||||
/* Animated tiles would sometimes not be actually animated or
|
/* Animated tiles would sometimes not be actually animated or
|
||||||
* in case of old savegames duplicate. */
|
* in case of old savegames duplicate. */
|
||||||
|
@ -1926,6 +1945,7 @@ void ReloadNewGRFData()
|
||||||
StartupEngines();
|
StartupEngines();
|
||||||
SetCachedEngineCounts();
|
SetCachedEngineCounts();
|
||||||
/* update station and waypoint graphics */
|
/* update station and waypoint graphics */
|
||||||
|
|
||||||
AfterLoadWaypoints();
|
AfterLoadWaypoints();
|
||||||
AfterLoadStations();
|
AfterLoadStations();
|
||||||
/* Check and update house and town values */
|
/* Check and update house and town values */
|
||||||
|
|
|
@ -8,13 +8,15 @@
|
||||||
#include "saveload.h"
|
#include "saveload.h"
|
||||||
|
|
||||||
static const SaveLoad _cargopacket_desc[] = {
|
static const SaveLoad _cargopacket_desc[] = {
|
||||||
SLE_VAR(CargoPacket, source, SLE_UINT16),
|
SLE_VAR(CargoPacket, source, SLE_UINT16),
|
||||||
SLE_VAR(CargoPacket, source_xy, SLE_UINT32),
|
SLE_VAR(CargoPacket, source_xy, SLE_UINT32),
|
||||||
SLE_VAR(CargoPacket, loaded_at_xy, SLE_UINT32),
|
SLE_VAR(CargoPacket, loaded_at_xy, SLE_UINT32),
|
||||||
SLE_VAR(CargoPacket, count, SLE_UINT16),
|
SLE_VAR(CargoPacket, count, SLE_UINT16),
|
||||||
SLE_VAR(CargoPacket, days_in_transit, SLE_UINT8),
|
SLE_VAR(CargoPacket, days_in_transit, SLE_UINT8),
|
||||||
SLE_VAR(CargoPacket, feeder_share, SLE_INT64),
|
SLE_VAR(CargoPacket, feeder_share, SLE_INT64),
|
||||||
SLE_VAR(CargoPacket, paid_for, SLE_BOOL),
|
|
||||||
|
/* Used to be paid_for, but that got changed. */
|
||||||
|
SLE_CONDNULL(1, 0, 120),
|
||||||
|
|
||||||
SLE_END()
|
SLE_END()
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,9 +4,12 @@
|
||||||
|
|
||||||
#include "../stdafx.h"
|
#include "../stdafx.h"
|
||||||
#include "../economy_func.h"
|
#include "../economy_func.h"
|
||||||
|
#include "../economy_base.h"
|
||||||
|
|
||||||
#include "saveload.h"
|
#include "saveload.h"
|
||||||
|
|
||||||
|
bool _cargo_payment_savegame = false;
|
||||||
|
|
||||||
/** Prices */
|
/** Prices */
|
||||||
static void SaveLoad_PRIC()
|
static void SaveLoad_PRIC()
|
||||||
{
|
{
|
||||||
|
@ -51,7 +54,37 @@ static void Load_ECMY()
|
||||||
StartupIndustryDailyChanges(CheckSavegameVersion(102)); // old savegames will need to be initialized
|
StartupIndustryDailyChanges(CheckSavegameVersion(102)); // old savegames will need to be initialized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const SaveLoad _cargopayment_desc[] = {
|
||||||
|
SLE_REF(CargoPayment, front, REF_VEHICLE),
|
||||||
|
SLE_VAR(CargoPayment, route_profit, SLE_INT64),
|
||||||
|
SLE_VAR(CargoPayment, visual_profit, SLE_INT64),
|
||||||
|
|
||||||
|
SLE_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
static void Save_CAPY()
|
||||||
|
{
|
||||||
|
CargoPayment *cp;
|
||||||
|
FOR_ALL_CARGO_PAYMENTS(cp) {
|
||||||
|
SlSetArrayIndex(cp->index);
|
||||||
|
SlObject(cp, _cargopayment_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Load_CAPY()
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
CargoPayment *cp = new (index) CargoPayment();
|
||||||
|
SlObject(cp, _cargopayment_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
_cargo_payment_savegame = true;
|
||||||
|
}
|
||||||
|
|
||||||
extern const ChunkHandler _economy_chunk_handlers[] = {
|
extern const ChunkHandler _economy_chunk_handlers[] = {
|
||||||
|
{ 'CAPY', Save_CAPY, Load_CAPY, CH_ARRAY},
|
||||||
{ 'PRIC', SaveLoad_PRIC, SaveLoad_PRIC, CH_RIFF | CH_AUTO_LENGTH},
|
{ 'PRIC', SaveLoad_PRIC, SaveLoad_PRIC, CH_RIFF | CH_AUTO_LENGTH},
|
||||||
{ 'CAPR', SaveLoad_CAPR, SaveLoad_CAPR, CH_RIFF | CH_AUTO_LENGTH},
|
{ 'CAPR', SaveLoad_CAPR, SaveLoad_CAPR, CH_RIFF | CH_AUTO_LENGTH},
|
||||||
{ 'ECMY', Save_ECMY, Load_ECMY, CH_RIFF | CH_LAST},
|
{ 'ECMY', Save_ECMY, Load_ECMY, CH_RIFF | CH_LAST},
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "settings_type.h"
|
#include "settings_type.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
|
|
||||||
|
#include "economy_base.h"
|
||||||
#include "table/sprites.h"
|
#include "table/sprites.h"
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
|
@ -481,6 +482,11 @@ void InitializeVehicles()
|
||||||
_Vehicle_pool.CleanPool();
|
_Vehicle_pool.CleanPool();
|
||||||
_Vehicle_pool.AddBlockToPool();
|
_Vehicle_pool.AddBlockToPool();
|
||||||
|
|
||||||
|
_CargoPayment_pool.CleanPool();
|
||||||
|
_CargoPayment_pool.AddBlockToPool();
|
||||||
|
|
||||||
|
_cargo_payment_savegame = false;
|
||||||
|
|
||||||
_vehicles_to_autoreplace.Reset();
|
_vehicles_to_autoreplace.Reset();
|
||||||
ResetVehiclePosHash();
|
ResetVehiclePosHash();
|
||||||
}
|
}
|
||||||
|
@ -1514,7 +1520,7 @@ void Vehicle::BeginLoading()
|
||||||
|
|
||||||
GetStation(this->last_station_visited)->loading_vehicles.push_back(this);
|
GetStation(this->last_station_visited)->loading_vehicles.push_back(this);
|
||||||
|
|
||||||
VehiclePayment(this);
|
PrepareUnload(this);
|
||||||
|
|
||||||
InvalidateWindow(GetWindowClassForVehicleType(this->type), this->owner);
|
InvalidateWindow(GetWindowClassForVehicleType(this->type), this->owner);
|
||||||
InvalidateWindowWidget(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
|
InvalidateWindowWidget(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
|
||||||
|
@ -1530,6 +1536,8 @@ void Vehicle::LeaveStation()
|
||||||
{
|
{
|
||||||
assert(current_order.IsType(OT_LOADING));
|
assert(current_order.IsType(OT_LOADING));
|
||||||
|
|
||||||
|
delete this->cargo_payment;
|
||||||
|
|
||||||
/* Only update the timetable if the vehicle was supposed to stop here. */
|
/* Only update the timetable if the vehicle was supposed to stop here. */
|
||||||
if (current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
|
if (current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,9 @@ public:
|
||||||
|
|
||||||
Money profit_this_year; ///< Profit this year << 8, low 8 bits are fract
|
Money profit_this_year; ///< Profit this year << 8, low 8 bits are fract
|
||||||
Money profit_last_year; ///< Profit last year << 8, low 8 bits are fract
|
Money profit_last_year; ///< Profit last year << 8, low 8 bits are fract
|
||||||
Money value;
|
Money value; ///< Value of the vehicle
|
||||||
|
|
||||||
|
CargoPayment *cargo_payment; ///< The cargo payment we're currently in
|
||||||
|
|
||||||
/* Used for timetabling. */
|
/* Used for timetabling. */
|
||||||
uint32 current_order_time; ///< How many ticks have passed since this order started.
|
uint32 current_order_time; ///< How many ticks have passed since this order started.
|
||||||
|
|
Loading…
Reference in New Issue