Merge PR #351 into jgrpp
This commit is contained in:
157
src/economy.cpp
157
src/economy.cpp
@@ -1075,30 +1075,9 @@ Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, C
|
|||||||
/** The industries we've currently brought cargo to. */
|
/** The industries we've currently brought cargo to. */
|
||||||
static SmallIndustryList _cargo_delivery_destinations;
|
static SmallIndustryList _cargo_delivery_destinations;
|
||||||
|
|
||||||
/**
|
template <class F>
|
||||||
* Transfer goods from station to industry.
|
void ForAcceptingIndustries(const Station *st, CargoID cargo_type, IndustryID source, CompanyID company, F&& f) {
|
||||||
* 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 cargo_type Type of cargo delivered
|
|
||||||
* @param num_pieces Amount of cargo delivered
|
|
||||||
* @param source The source of the cargo
|
|
||||||
* @param company The company delivering the cargo
|
|
||||||
* @return actually accepted pieces of cargo
|
|
||||||
*/
|
|
||||||
static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint num_pieces, IndustryID source, CompanyID company)
|
|
||||||
{
|
|
||||||
/* Find the nearest industrytile to the station sign inside the catchment area, whose industry accepts the cargo.
|
|
||||||
* This fails in three cases:
|
|
||||||
* 1) The station accepts the cargo because there are enough houses around it accepting the cargo.
|
|
||||||
* 2) The industries in the catchment area temporarily reject the cargo, and the daily station loop has not yet updated station acceptance.
|
|
||||||
* 3) The results of callbacks CBID_INDUSTRY_REFUSE_CARGO and CBID_INDTILE_CARGO_ACCEPTANCE are inconsistent. (documented behaviour)
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint accepted = 0;
|
|
||||||
|
|
||||||
for (Industry *ind : st->industries_near) {
|
for (Industry *ind : st->industries_near) {
|
||||||
if (num_pieces == 0) break;
|
|
||||||
|
|
||||||
if (ind->index == source) continue;
|
if (ind->index == source) continue;
|
||||||
|
|
||||||
uint cargo_index;
|
uint cargo_index;
|
||||||
@@ -1113,6 +1092,22 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint n
|
|||||||
|
|
||||||
if (ind->exclusive_supplier != INVALID_OWNER && ind->exclusive_supplier != st->owner) continue;
|
if (ind->exclusive_supplier != INVALID_OWNER && ind->exclusive_supplier != st->owner) continue;
|
||||||
|
|
||||||
|
if (!f(ind, cargo_index)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint DeliverGoodsToIndustryNearestFirst(const Station *st, CargoID cargo_type, uint num_pieces, IndustryID source, CompanyID company)
|
||||||
|
{
|
||||||
|
/* Find the nearest industrytile to the station sign inside the catchment area, whose industry accepts the cargo.
|
||||||
|
* This fails in three cases:
|
||||||
|
* 1) The station accepts the cargo because there are enough houses around it accepting the cargo.
|
||||||
|
* 2) The industries in the catchment area temporarily reject the cargo, and the daily station loop has not yet updated station acceptance.
|
||||||
|
* 3) The results of callbacks CBID_INDUSTRY_REFUSE_CARGO and CBID_INDTILE_CARGO_ACCEPTANCE are inconsistent. (documented behaviour)
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint accepted = 0;
|
||||||
|
|
||||||
|
ForAcceptingIndustries(st, cargo_type, source, company, [&](Industry *ind, uint cargo_index) {
|
||||||
/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
|
/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
|
||||||
include(_cargo_delivery_destinations, ind);
|
include(_cargo_delivery_destinations, ind);
|
||||||
|
|
||||||
@@ -1124,11 +1119,127 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint n
|
|||||||
|
|
||||||
/* Update the cargo monitor. */
|
/* Update the cargo monitor. */
|
||||||
AddCargoDelivery(cargo_type, company, amount, ST_INDUSTRY, source, st, ind->index);
|
AddCargoDelivery(cargo_type, company, amount, ST_INDUSTRY, source, st, ind->index);
|
||||||
|
|
||||||
|
return num_pieces != 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint DeliverGoodsToIndustryEqually(const Station *st, CargoID cargo_type, uint num_pieces, IndustryID source, CompanyID company)
|
||||||
|
{
|
||||||
|
struct AcceptingIndustry {
|
||||||
|
Industry *ind;
|
||||||
|
uint cargo_index;
|
||||||
|
uint capacity;
|
||||||
|
uint delivered;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<AcceptingIndustry> acceptingIndustries;
|
||||||
|
|
||||||
|
ForAcceptingIndustries(st, cargo_type, source, company, [&](Industry *ind, uint cargo_index) {
|
||||||
|
uint capacity = 0xFFFFu - ind->incoming_cargo_waiting[cargo_index];
|
||||||
|
if (capacity > 0) acceptingIndustries.push_back({ ind, cargo_index, capacity, 0 });
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (acceptingIndustries.empty()) return 0;
|
||||||
|
|
||||||
|
uint accepted = 0;
|
||||||
|
|
||||||
|
auto distributeCargo = [&](AcceptingIndustry &e, uint amount) {
|
||||||
|
e.capacity -= amount;
|
||||||
|
e.delivered += amount;
|
||||||
|
num_pieces -= amount;
|
||||||
|
accepted += amount;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto finalizeCargo = [&](AcceptingIndustry &e) {
|
||||||
|
if (e.delivered == 0) return;
|
||||||
|
include(_cargo_delivery_destinations, e.ind);
|
||||||
|
e.ind->incoming_cargo_waiting[e.cargo_index] += e.delivered;
|
||||||
|
e.ind->last_cargo_accepted_at[e.cargo_index] = _date;
|
||||||
|
AddCargoDelivery(cargo_type, company, e.delivered, ST_INDUSTRY, source, st, e.ind->index);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (acceptingIndustries.size() == 1) {
|
||||||
|
distributeCargo(acceptingIndustries[0], std::min<uint>(acceptingIndustries[0].capacity, num_pieces));
|
||||||
|
finalizeCargo(acceptingIndustries[0]);
|
||||||
|
return accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort in order of decreasing capacity */
|
||||||
|
std::sort(acceptingIndustries.begin(), acceptingIndustries.end(), [](AcceptingIndustry &a, AcceptingIndustry &b) {
|
||||||
|
return std::tie(a.capacity, a.ind->index) > std::tie(b.capacity, b.ind->index);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Handle low-capacity industries first */
|
||||||
|
do {
|
||||||
|
uint amount = num_pieces / static_cast<uint>(acceptingIndustries.size());
|
||||||
|
AcceptingIndustry &acc = acceptingIndustries.back();
|
||||||
|
if (amount >= acc.capacity) {
|
||||||
|
distributeCargo(acc, acc.capacity);
|
||||||
|
finalizeCargo(acc);
|
||||||
|
acceptingIndustries.pop_back();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (!acceptingIndustries.empty());
|
||||||
|
|
||||||
|
/* Remaining industries can accept all remaining cargo when distributed evenly */
|
||||||
|
if (!acceptingIndustries.empty()) {
|
||||||
|
uint amount = num_pieces / static_cast<uint>(acceptingIndustries.size());
|
||||||
|
|
||||||
|
if (amount > 0) {
|
||||||
|
for (auto &e : acceptingIndustries) {
|
||||||
|
distributeCargo(e, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If cargo didn't divide evenly into remaining industries, distribute the remainder randomly */
|
||||||
|
if (num_pieces > 0) {
|
||||||
|
assert(num_pieces < acceptingIndustries.size());
|
||||||
|
|
||||||
|
uint idx = RandomRange(acceptingIndustries.size());
|
||||||
|
for (uint i = 0; i < acceptingIndustries.size(); ++i) {
|
||||||
|
if (acceptingIndustries[idx].capacity > 0) {
|
||||||
|
distributeCargo(acceptingIndustries[idx], 1);
|
||||||
|
if (num_pieces == 0) break;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
if (idx == acceptingIndustries.size()) idx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &e : acceptingIndustries) {
|
||||||
|
finalizeCargo(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return accepted;
|
return accepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfer goods from station to industry.
|
||||||
|
* Original distribution mode: All cargo is delivered to the nearest (Manhattan) industry to the station sign, which is inside the acceptance rectangle and actually accepts the cargo.
|
||||||
|
* Balanced distribution: Cargo distributed equally amongst the accepting industries in the acceptance rectangle.
|
||||||
|
* @param st The station that accepted the cargo
|
||||||
|
* @param cargo_type Type of cargo delivered
|
||||||
|
* @param num_pieces Amount of cargo delivered
|
||||||
|
* @param source The source of the cargo
|
||||||
|
* @param company The company delivering the cargo
|
||||||
|
* @return actually accepted pieces of cargo
|
||||||
|
*/
|
||||||
|
static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint num_pieces, IndustryID source, CompanyID company)
|
||||||
|
{
|
||||||
|
switch (_settings_game.station.station_delivery_mode) {
|
||||||
|
case SD_BALANCED:
|
||||||
|
return DeliverGoodsToIndustryEqually(st, cargo_type, num_pieces, source, company);
|
||||||
|
default:
|
||||||
|
return DeliverGoodsToIndustryNearestFirst(st, cargo_type, num_pieces, source, company);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delivers goods to industries/towns and calculates the payment
|
* Delivers goods to industries/towns and calculates the payment
|
||||||
* @param num_pieces amount of cargo delivered
|
* @param num_pieces amount of cargo delivered
|
||||||
|
@@ -1259,6 +1259,8 @@ STR_CONFIG_SETTING_TRAIN_BRAKING_REALISTIC :Realistic {PUSH
|
|||||||
|
|
||||||
STR_CONFIG_SETTING_REALISTIC_BRAKING_SIGNALS_NOT_ALLOWED :{WHITE}Realistic braking can't be enabled. At least one pre-signal or two-way signal is present.
|
STR_CONFIG_SETTING_REALISTIC_BRAKING_SIGNALS_NOT_ALLOWED :{WHITE}Realistic braking can't be enabled. At least one pre-signal or two-way signal is present.
|
||||||
|
|
||||||
|
STR_CONFIG_SETTING_DELIVERY_BALANCED :Balanced
|
||||||
|
|
||||||
###length 3
|
###length 3
|
||||||
STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT :Left
|
STR_CONFIG_SETTING_HORIZONTAL_POS_LEFT :Left
|
||||||
STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER :Centre
|
STR_CONFIG_SETTING_HORIZONTAL_POS_CENTER :Centre
|
||||||
@@ -1340,6 +1342,9 @@ STR_CONFIG_SETTING_STATION_RATING_SIZE_CARGO_AMOUNT_HELPTEXT :When enabled, t
|
|||||||
STR_CONFIG_SETTING_EXTRADYNAMITE :Allow removal of more town-owned roads, bridges and tunnels: {STRING2}
|
STR_CONFIG_SETTING_EXTRADYNAMITE :Allow removal of more town-owned roads, bridges and tunnels: {STRING2}
|
||||||
STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Make it easier to remove town-owned infrastructure and buildings
|
STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Make it easier to remove town-owned infrastructure and buildings
|
||||||
|
|
||||||
|
STR_CONFIG_SETTING_CARGO_DELIVERY_MODE :Cargo delivery distribution mode: {STRING2}
|
||||||
|
STR_CONFIG_SETTING_CARGO_DELIVERY_MODE_HELPTEXT :The method used to deliver cargo to industries surrounding a station.
|
||||||
|
|
||||||
STR_CONFIG_SETTING_TRAIN_LENGTH :Maximum length of trains: {STRING2}
|
STR_CONFIG_SETTING_TRAIN_LENGTH :Maximum length of trains: {STRING2}
|
||||||
STR_CONFIG_SETTING_TRAIN_LENGTH_HELPTEXT :Set the maximum length of trains
|
STR_CONFIG_SETTING_TRAIN_LENGTH_HELPTEXT :Set the maximum length of trains
|
||||||
STR_CONFIG_SETTING_TILE_LENGTH :{COMMA} tile{P 0 "" s}
|
STR_CONFIG_SETTING_TILE_LENGTH :{COMMA} tile{P 0 "" s}
|
||||||
|
@@ -3991,6 +3991,10 @@ bool AfterLoadGame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SlXvIsFeatureMissing(XSLFI_ST_INDUSTRY_CARGO_MODE)) {
|
||||||
|
_settings_game.station.station_delivery_mode = SD_NEAREST_FIRST;
|
||||||
|
}
|
||||||
|
|
||||||
InitializeRoadGUI();
|
InitializeRoadGUI();
|
||||||
|
|
||||||
/* This needs to be done after conversion. */
|
/* This needs to be done after conversion. */
|
||||||
|
@@ -162,6 +162,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
|||||||
{ XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 1, 1, "object_ground_types", nullptr, nullptr, nullptr },
|
{ XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 1, 1, "object_ground_types", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_LINKGRAPH_AIRCRAFT, XSCF_NULL, 1, 1, "linkgraph_aircraft", nullptr, nullptr, nullptr },
|
{ XSLFI_LINKGRAPH_AIRCRAFT, XSCF_NULL, 1, 1, "linkgraph_aircraft", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_COMPANY_PW, XSCF_IGNORABLE_ALL, 1, 1, "company_password", nullptr, nullptr, "PLYP" },
|
{ XSLFI_COMPANY_PW, XSCF_IGNORABLE_ALL, 1, 1, "company_password", nullptr, nullptr, "PLYP" },
|
||||||
|
{ XSLFI_ST_INDUSTRY_CARGO_MODE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "st_industry_cargo_mode", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr },
|
{ XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
||||||
};
|
};
|
||||||
|
@@ -116,6 +116,7 @@ enum SlXvFeatureIndex {
|
|||||||
XSLFI_OBJECT_GROUND_TYPES, ///< Object ground types
|
XSLFI_OBJECT_GROUND_TYPES, ///< Object ground types
|
||||||
XSLFI_LINKGRAPH_AIRCRAFT, ///< Link graph last aircraft update field and aircraft link scaling setting
|
XSLFI_LINKGRAPH_AIRCRAFT, ///< Link graph last aircraft update field and aircraft link scaling setting
|
||||||
XSLFI_COMPANY_PW, ///< Company passwords
|
XSLFI_COMPANY_PW, ///< Company passwords
|
||||||
|
XSLFI_ST_INDUSTRY_CARGO_MODE, ///< Station industry cargo mode setting
|
||||||
|
|
||||||
XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64
|
XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64
|
||||||
|
|
||||||
|
@@ -2181,6 +2181,7 @@ static SettingsContainer &GetSettingsTree()
|
|||||||
industries->Add(new SettingEntry("economy.type"));
|
industries->Add(new SettingEntry("economy.type"));
|
||||||
industries->Add(new SettingEntry("station.serve_neutral_industries"));
|
industries->Add(new SettingEntry("station.serve_neutral_industries"));
|
||||||
industries->Add(new SettingEntry("economy.industry_cargo_scale_factor"));
|
industries->Add(new SettingEntry("economy.industry_cargo_scale_factor"));
|
||||||
|
industries->Add(new SettingEntry("station.station_delivery_mode"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
|
SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include "zoom_type.h"
|
#include "zoom_type.h"
|
||||||
#include "openttd.h"
|
#include "openttd.h"
|
||||||
#include "rail_gui_type.h"
|
#include "rail_gui_type.h"
|
||||||
|
#include "station_type.h"
|
||||||
|
|
||||||
/* Used to validate sizes of "max" value in settings. */
|
/* Used to validate sizes of "max" value in settings. */
|
||||||
const size_t MAX_SLE_UINT8 = UINT8_MAX;
|
const size_t MAX_SLE_UINT8 = UINT8_MAX;
|
||||||
@@ -715,6 +716,7 @@ struct StationSettings {
|
|||||||
byte catchment_increase; ///< amount by which station catchment is increased
|
byte catchment_increase; ///< amount by which station catchment is increased
|
||||||
bool cargo_class_rating_wait_time; ///< station rating tolerance to time since last cargo pickup depends on cargo class
|
bool cargo_class_rating_wait_time; ///< station rating tolerance to time since last cargo pickup depends on cargo class
|
||||||
bool station_size_rating_cargo_amount; ///< station rating tolerance to waiting cargo amount depends on station size
|
bool station_size_rating_cargo_amount; ///< station rating tolerance to waiting cargo amount depends on station size
|
||||||
|
StationDelivery station_delivery_mode; ///< method to use for distributing cargo from stations to accepting industries
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Default settings for vehicles. */
|
/** Default settings for vehicles. */
|
||||||
|
@@ -87,6 +87,11 @@ enum CatchmentArea {
|
|||||||
MAX_CATCHMENT = 10, ///< Maximum catchment for airports with "modified catchment" enabled
|
MAX_CATCHMENT = 10, ///< Maximum catchment for airports with "modified catchment" enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StationDelivery : byte {
|
||||||
|
SD_NEAREST_FIRST = 0, ///< Station delivers cargo only to the nearest accepting industry
|
||||||
|
SD_BALANCED = 1 ///< Station delivers cargo equally among accepting industries
|
||||||
|
};
|
||||||
|
|
||||||
static const uint MAX_LENGTH_STATION_NAME_CHARS = 128; ///< The maximum length of a station name in characters including '\0'
|
static const uint MAX_LENGTH_STATION_NAME_CHARS = 128; ///< The maximum length of a station name in characters including '\0'
|
||||||
|
|
||||||
struct StationCompare {
|
struct StationCompare {
|
||||||
|
@@ -122,6 +122,12 @@ static const SettingDescEnumEntry _train_braking_model[] = {
|
|||||||
{ 0, STR_NULL }
|
{ 0, STR_NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const SettingDescEnumEntry _station_delivery_mode[] = {
|
||||||
|
{ SD_NEAREST_FIRST, STR_CONFIG_SETTING_ORIGINAL},
|
||||||
|
{ SD_BALANCED, STR_CONFIG_SETTING_DELIVERY_BALANCED},
|
||||||
|
{ 0, STR_NULL }
|
||||||
|
};
|
||||||
|
|
||||||
/* Some settings do not need to be synchronised when playing in multiplayer.
|
/* Some settings do not need to be synchronised when playing in multiplayer.
|
||||||
* These include for example the GUI settings and will not be saved with the
|
* These include for example the GUI settings and will not be saved with the
|
||||||
* savegame.
|
* savegame.
|
||||||
@@ -1948,6 +1954,15 @@ str = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES
|
|||||||
strhelp = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT
|
strhelp = STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT
|
||||||
post_cb = StationCatchmentChanged
|
post_cb = StationCatchmentChanged
|
||||||
|
|
||||||
|
[SDT_ENUM]
|
||||||
|
var = station.station_delivery_mode
|
||||||
|
type = SLE_UINT8
|
||||||
|
def = SD_NEAREST_FIRST
|
||||||
|
enumlist = _station_delivery_mode
|
||||||
|
str = STR_CONFIG_SETTING_CARGO_DELIVERY_MODE
|
||||||
|
strhelp = STR_CONFIG_SETTING_CARGO_DELIVERY_MODE_HELPTEXT
|
||||||
|
patxname = ""station.station_delivery_mode""
|
||||||
|
|
||||||
[SDT_BOOL]
|
[SDT_BOOL]
|
||||||
var = order.gradual_loading
|
var = order.gradual_loading
|
||||||
from = SLV_40
|
from = SLV_40
|
||||||
|
Reference in New Issue
Block a user