summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Stupnikov <dp@dpointer.org>2020-12-22 16:29:48 +0300
committerGitHub <noreply@github.com>2020-12-22 14:29:48 +0100
commit9a45a0f535e312cd97db12c3a2ec1068fa381136 (patch)
treeeb4f235933ea178c370c04c9b12cd00b005f4644
parentb7751c483e5545aa683baf0b9f09a0add34cfefd (diff)
downloadopenttd-9a45a0f535e312cd97db12c3a2ec1068fa381136.tar.xz
Feature: Set exclusive access to industry from GS (#8115)
-rw-r--r--src/economy.cpp2
-rw-r--r--src/economy_func.h2
-rw-r--r--src/industry.h2
-rw-r--r--src/industry_cmd.cpp32
-rw-r--r--src/saveload/afterload.cpp8
-rw-r--r--src/saveload/industry_sl.cpp2
-rw-r--r--src/saveload/saveload.h2
-rw-r--r--src/script/api/game_changelog.hpp4
-rw-r--r--src/script/api/script_industry.cpp41
-rw-r--r--src/script/api/script_industry.hpp44
-rw-r--r--src/station_cmd.cpp3
11 files changed, 137 insertions, 5 deletions
diff --git a/src/economy.cpp b/src/economy.cpp
index 7c801e854..5e53334a0 100644
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -1042,6 +1042,8 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint n
/* Check if industry temporarily refuses acceptance */
if (IndustryTemporarilyRefusesCargo(ind, cargo_type)) continue;
+ if (ind->exclusive_supplier != INVALID_OWNER && ind->exclusive_supplier != st->owner) continue;
+
/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
include(_cargo_delivery_destinations, ind);
diff --git a/src/economy_func.h b/src/economy_func.h
index d26b344e9..69980b475 100644
--- a/src/economy_func.h
+++ b/src/economy_func.h
@@ -29,7 +29,7 @@ int UpdateCompanyRatingAndValue(Company *c, bool update);
void StartupIndustryDailyChanges(bool init_counter);
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type);
-uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations);
+uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations, Owner exclusivity = INVALID_OWNER);
void PrepareUnload(Vehicle *front_v);
void LoadUnloadStation(Station *st);
diff --git a/src/industry.h b/src/industry.h
index feee6f200..ea4d704a8 100644
--- a/src/industry.h
+++ b/src/industry.h
@@ -90,6 +90,8 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
uint8 construction_type; ///< Way the industry was constructed (@see IndustryConstructionType)
Date last_cargo_accepted_at[INDUSTRY_NUM_INPUTS]; ///< Last day each cargo type was accepted by this industry
byte selected_layout; ///< Which tile layout was used when creating the industry
+ Owner exclusive_supplier; ///< Which company has exclusive rights to deliver cargo (INVALID_OWNER = anyone)
+ Owner exclusive_consumer; ///< Which company has exclusive rights to take cargo (INVALID_OWNER = anyone)
uint16 random; ///< Random value used for randomisation of all kinds of things
diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp
index 420244e6d..92741e3f6 100644
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -17,6 +17,7 @@
#include "town.h"
#include "news_func.h"
#include "cheat_type.h"
+#include "company_base.h"
#include "genworld.h"
#include "tree_map.h"
#include "newgrf_cargo.h"
@@ -539,7 +540,7 @@ static bool TransportIndustryGoods(TileIndex tile)
i->this_month_production[j] += cw;
- uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, &i->stations_near);
+ uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, &i->stations_near, i->exclusive_consumer);
i->this_month_transported[j] += am;
moved_cargo |= (am != 0);
@@ -946,6 +947,9 @@ static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_
/* If the founder merges, the industry was created by the merged company */
Industry *i = Industry::GetByTile(tile);
if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
+
+ if (i->exclusive_supplier == old_owner) i->exclusive_supplier = new_owner;
+ if (i->exclusive_consumer == old_owner) i->exclusive_consumer = new_owner;
}
/**
@@ -1764,6 +1768,9 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
* else, chosen layout + 1 */
i->selected_layout = (byte)(layout_index + 1);
+ i->exclusive_supplier = INVALID_OWNER;
+ i->exclusive_consumer = INVALID_OWNER;
+
i->prod_level = PRODLEVEL_DEFAULT;
/* Call callbacks after the regular fields got initialised. */
@@ -2058,8 +2065,13 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
* @param p2 various bitstuffed elements
* - p2 = (bit 0 - 7) - action to perform:
* 0 = set control flags
+ * 1 = set exclusive supplier
+ * 2 = set exclusive consumer
* - p2 = (bit 8 - 15) - IndustryControlFlags
* (only used with set control flags)
+ * - p2 = (bit 16 - 23) - CompanyID to set or INVALID_OWNER (available to everyone) or
+ * OWNER_NONE (neutral stations only) or OWNER_DEITY (no one)
+ * (only used with set exclusive supplier / consumer)
* @param text unused
* @return Empty cost or an error.
*/
@@ -2081,6 +2093,24 @@ CommandCost CmdIndustryCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
break;
}
+ case 1:
+ case 2: {
+ Owner company_id = (Owner)GB(p2, 16, 8);
+
+ if (company_id != OWNER_NONE && company_id != INVALID_OWNER && company_id != OWNER_DEITY
+ && !Company::IsValidID(company_id)) return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ if (action == 1) {
+ ind->exclusive_supplier = company_id;
+ } else {
+ ind->exclusive_consumer = company_id;
+ }
+ }
+
+ break;
+ }
+
default:
NOT_REACHED();
}
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
index 7d1e70212..c617348d7 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -3125,6 +3125,14 @@ bool AfterLoadGame()
}
}
+ /* Make sure all industries exclusive supplier/consumer set correctly. */
+ if (IsSavegameVersionBefore(SLV_GS_INDUSTRY_CONTROL)) {
+ for (Industry *i : Industry::Iterate()) {
+ i->exclusive_supplier = INVALID_OWNER;
+ i->exclusive_consumer = INVALID_OWNER;
+ }
+ }
+
/* Compute station catchment areas. This is needed here in case UpdateStationAcceptance is called below. */
Station::RecomputeCatchmentForAll();
diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp
index 8f7301120..99e25856c 100644
--- a/src/saveload/industry_sl.cpp
+++ b/src/saveload/industry_sl.cpp
@@ -64,6 +64,8 @@ static const SaveLoad _industry_desc[] = {
SLE_CONDVAR(Industry, last_cargo_accepted_at[0], SLE_INT32, SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
SLE_CONDARR(Industry, last_cargo_accepted_at, SLE_INT32, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
SLE_CONDVAR(Industry, selected_layout, SLE_UINT8, SLV_73, SL_MAX_VERSION),
+ SLE_CONDVAR(Industry, exclusive_supplier, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
+ SLE_CONDVAR(Industry, exclusive_consumer, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
SLEG_CONDARR(_old_ind_persistent_storage.storage, SLE_UINT32, 16, SLV_76, SLV_161),
SLE_CONDREF(Industry, psa, REF_STORAGE, SLV_161, SL_MAX_VERSION),
diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h
index 0b525570d..58a291932 100644
--- a/src/saveload/saveload.h
+++ b/src/saveload/saveload.h
@@ -320,7 +320,7 @@ enum SaveLoadVersion : uint16 {
SLV_START_PATCHPACKS, ///< 220 First known patchpack to use a version just above ours.
SLV_END_PATCHPACKS = 286, ///< 286 Last known patchpack to use a version just above ours.
- SLV_GS_INDUSTRY_CONTROL, ///< 287 PR#7912 GS industry control.
+ SLV_GS_INDUSTRY_CONTROL, ///< 287 PR#7912 and PR#8115 GS industry control.
SL_MAX_VERSION, ///< Highest possible saveload version
};
diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp
index abc9e9c35..1f43cdea1 100644
--- a/src/script/api/game_changelog.hpp
+++ b/src/script/api/game_changelog.hpp
@@ -23,8 +23,12 @@
* \li GSEventStoryPageVehicleSelect
* \li GSIndustry::GetCargoLastAcceptedDate
* \li GSIndustry::GetControlFlags
+ * \li GSIndustry::GetExclusiveConsumer
+ * \li GSIndustry::GetExclusiveSupplier
* \li GSIndustry::GetLastProductionYear
* \li GSIndustry::SetControlFlags
+ * \li GSIndustry::SetExclusiveConsumer
+ * \li GSIndustry::SetExclusiveSupplier
* \li GSStoryPage::MakePushButtonReference
* \li GSStoryPage::MakeTileButtonReference
* \li GSStoryPage::MakeVehicleButtonReference
diff --git a/src/script/api/script_industry.cpp b/src/script/api/script_industry.cpp
index c2b449b0b..14ba8e402 100644
--- a/src/script/api/script_industry.cpp
+++ b/src/script/api/script_industry.cpp
@@ -10,7 +10,10 @@
#include "../../stdafx.h"
#include "script_industry.hpp"
#include "script_cargo.hpp"
+#include "script_company.hpp"
+#include "script_error.hpp"
#include "script_map.hpp"
+#include "../../company_base.h"
#include "../../industry.h"
#include "../../strings_func.h"
#include "../../station_base.h"
@@ -241,3 +244,41 @@ bool ScriptIndustry::SetControlFlags(IndustryID industry_id, uint32 control_flag
return ScriptObject::DoCommand(0, industry_id, 0 | ((control_flags & ::INDCTL_MASK) << 8), CMD_INDUSTRY_CTRL);
}
+
+/* static */ ScriptCompany::CompanyID ScriptIndustry::GetExclusiveSupplier(IndustryID industry_id)
+{
+ if (!IsValidIndustry(industry_id)) return ScriptCompany::COMPANY_INVALID;
+
+ auto company_id = ::Industry::Get(industry_id)->exclusive_supplier;
+ if (!::Company::IsValidID(company_id)) return ScriptCompany::COMPANY_INVALID;
+
+ return (ScriptCompany::CompanyID)((byte)company_id);
+}
+
+/* static */ bool ScriptIndustry::SetExclusiveSupplier(IndustryID industry_id, ScriptCompany::CompanyID company_id)
+{
+ EnforcePrecondition(false, IsValidIndustry(industry_id));
+
+ auto company = ScriptCompany::ResolveCompanyID(company_id);
+ ::Owner owner = (company == ScriptCompany::COMPANY_INVALID ? ::INVALID_OWNER : (::Owner)company);
+ return ScriptObject::DoCommand(0, industry_id, 1 | (((uint8)owner) << 16), CMD_INDUSTRY_CTRL);
+}
+
+/* static */ ScriptCompany::CompanyID ScriptIndustry::GetExclusiveConsumer(IndustryID industry_id)
+{
+ if (!IsValidIndustry(industry_id)) return ScriptCompany::COMPANY_INVALID;
+
+ auto company_id = ::Industry::Get(industry_id)->exclusive_consumer;
+ if (!::Company::IsValidID(company_id)) return ScriptCompany::COMPANY_INVALID;
+
+ return (ScriptCompany::CompanyID)((byte)company_id);
+}
+
+/* static */ bool ScriptIndustry::SetExclusiveConsumer(IndustryID industry_id, ScriptCompany::CompanyID company_id)
+{
+ EnforcePrecondition(false, IsValidIndustry(industry_id));
+
+ auto company = ScriptCompany::ResolveCompanyID(company_id);
+ ::Owner owner = (company == ScriptCompany::COMPANY_INVALID ? ::INVALID_OWNER : (::Owner)company);
+ return ScriptObject::DoCommand(0, industry_id, 2 | (((uint8)owner) << 16), CMD_INDUSTRY_CTRL);
+}
diff --git a/src/script/api/script_industry.hpp b/src/script/api/script_industry.hpp
index 2fbd861cc..dac3d32fd 100644
--- a/src/script/api/script_industry.hpp
+++ b/src/script/api/script_industry.hpp
@@ -10,8 +10,9 @@
#ifndef SCRIPT_INDUSTRY_HPP
#define SCRIPT_INDUSTRY_HPP
-#include "script_object.hpp"
+#include "script_company.hpp"
#include "script_date.hpp"
+#include "script_object.hpp"
#include "../../industry.h"
/**
@@ -259,6 +260,47 @@ public:
* @api -ai
*/
static bool SetControlFlags(IndustryID industry_id, uint32 control_flags);
+
+ /**
+ * Find out which company currently has the exclusive rights to deliver cargo to the industry.
+ * @param industry_id The index of the industry.
+ * @pre IsValidIndustry(industry_id).
+ * @return The company that has the exclusive rights. The value
+ * ScriptCompany::COMPANY_INVALID means that there are currently no
+ * exclusive rights given out to anyone.
+ */
+ static ScriptCompany::CompanyID GetExclusiveSupplier(IndustryID industry_id);
+
+ /**
+ * Sets or resets the company that has exclusive right to deliver cargo to the industry.
+ * @param industry_id The index of the industry.
+ * @param company_id The company to set (ScriptCompany::COMPANY_INVALID to reset).
+ * @pre IsValidIndustry(industry_id).
+ * @return True if the action succeeded.
+ * @api -ai
+ */
+ static bool SetExclusiveSupplier(IndustryID industry_id, ScriptCompany::CompanyID company_id);
+
+ /**
+ * Find out which company currently has the exclusive rights to take cargo from the industry.
+ * @param industry_id The index of the industry.
+ * @pre IsValidIndustry(industry_id).
+ * @return The company that has the exclusive rights. The value
+ * ScriptCompany::COMPANY_SPECTATOR means that there are currently no
+ * exclusive rights given out to anyone.
+ */
+ static ScriptCompany::CompanyID GetExclusiveConsumer(IndustryID industry_id);
+
+ /**
+ * Sets or resets the company that has exclusive right to take cargo from the industry.
+ * @param industry_id The index of the industry.
+ * @param company_id The company to set (ScriptCompany::COMPANY_INVALID to reset).
+ * @pre IsValidIndustry(industry_id).
+ * @return True if the action succeeded.
+ * @api -ai
+ */
+ static bool SetExclusiveConsumer(IndustryID industry_id, ScriptCompany::CompanyID company_id);
+
};
#endif /* SCRIPT_INDUSTRY_HPP */
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 7bce21353..cd56dcb69 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -4013,7 +4013,7 @@ static bool CanMoveGoodsToStation(const Station *st, CargoID type)
return true;
}
-uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
+uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations, Owner exclusivity)
{
/* Return if nothing to do. Also the rounding below fails for 0. */
if (all_stations->empty()) return 0;
@@ -4024,6 +4024,7 @@ uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, Sourc
std::vector<StationInfo> used_stations;
for (Station *st : *all_stations) {
+ if (exclusivity != INVALID_OWNER && exclusivity != st->owner) continue;
if (!CanMoveGoodsToStation(st, type)) continue;
/* Avoid allocating a vector if there is only one station to significantly