From 33ef0ca8e80fa65a2bd38e2f418c54f4a75dff58 Mon Sep 17 00:00:00 2001 From: dP Date: Tue, 5 May 2020 22:54:31 +0300 Subject: [PATCH] Feature: Set exclusive access to industry from GS --- src/economy.cpp | 2 ++ src/economy_func.h | 2 +- src/industry.h | 2 ++ src/industry_cmd.cpp | 32 +++++++++++++++++++++- src/saveload/afterload.cpp | 8 ++++++ src/saveload/industry_sl.cpp | 2 ++ src/saveload/saveload.h | 2 +- src/script/api/game_changelog.hpp | 4 +++ src/script/api/script_industry.cpp | 41 ++++++++++++++++++++++++++++ src/script/api/script_industry.hpp | 44 +++++++++++++++++++++++++++++- src/station_cmd.cpp | 3 +- 11 files changed, 137 insertions(+), 5 deletions(-) diff --git a/src/economy.cpp b/src/economy.cpp index 7c801e854d34..5e53334a0e22 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 d26b344e9ad4..69980b4758bb 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 feee6f2008de..ea4d704a8724 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 420244e6dc03..92741e3f698a 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 7d1e70212a21..c617348d7337 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 8f7301120b23..99e25856c81b 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 0b525570d7f3..58a2919326a6 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 abc9e9c35e9c..1f43cdea1cdb 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 c2b449b0ba2b..14ba8e40229f 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 2fbd861cc5c5..dac3d32fd761 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 @@ class ScriptIndustry : public ScriptObject { * @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 7bce21353df1..cd56dcb698df 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 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