Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GS methods to let company have exclusive access to the industry #8115

Merged
merged 1 commit into from Dec 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/economy.cpp
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/economy_func.h
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/industry.h
Expand Up @@ -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

Expand Down
32 changes: 31 additions & 1 deletion src/industry_cmd.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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();
}
Expand Down
8 changes: 8 additions & 0 deletions src/saveload/afterload.cpp
Expand Up @@ -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();

Expand Down
2 changes: 2 additions & 0 deletions src/saveload/industry_sl.cpp
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion src/saveload/saveload.h
Expand Up @@ -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
};
Expand Down
4 changes: 4 additions & 0 deletions src/script/api/game_changelog.hpp
Expand Up @@ -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
Expand Down
41 changes: 41 additions & 0 deletions src/script/api/script_industry.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
44 changes: 43 additions & 1 deletion src/script/api/script_industry.hpp
Expand Up @@ -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"

/**
Expand Down Expand Up @@ -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 */
3 changes: 2 additions & 1 deletion src/station_cmd.cpp
Expand Up @@ -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;
Expand All @@ -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
Expand Down