summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.cpp3
-rw-r--r--src/command_type.h1
-rw-r--r--src/industry.h21
-rw-r--r--src/industry_cmd.cpp51
-rw-r--r--src/newgrf_industries.cpp3
-rw-r--r--src/saveload/industry_sl.cpp1
-rw-r--r--src/saveload/saveload.h2
-rw-r--r--src/script/api/game_changelog.hpp4
-rw-r--r--src/script/api/script_cargo.hpp1
-rw-r--r--src/script/api/script_industry.cpp37
-rw-r--r--src/script/api/script_industry.hpp63
11 files changed, 185 insertions, 2 deletions
diff --git a/src/command.cpp b/src/command.cpp
index 453f305d3..9fbc6cae6 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -97,6 +97,7 @@ CommandProc CmdInsertOrder;
CommandProc CmdChangeServiceInt;
CommandProc CmdBuildIndustry;
+CommandProc CmdIndustryCtrl;
CommandProc CmdSetCompanyManagerFace;
CommandProc CmdSetCompanyColour;
@@ -265,6 +266,8 @@ static const Command _command_proc_table[] = {
DEF_CMD(CmdChangeServiceInt, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_CHANGE_SERVICE_INT
DEF_CMD(CmdBuildIndustry, CMD_DEITY, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_INDUSTRY
+ DEF_CMD(CmdIndustryCtrl, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_INDUSTRY_CTRL
+
DEF_CMD(CmdSetCompanyManagerFace, 0, CMDT_OTHER_MANAGEMENT ), // CMD_SET_COMPANY_MANAGER_FACE
DEF_CMD(CmdSetCompanyColour, 0, CMDT_OTHER_MANAGEMENT ), // CMD_SET_COMPANY_COLOUR
diff --git a/src/command_type.h b/src/command_type.h
index 04dbfe893..0620b96b6 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -230,6 +230,7 @@ enum Commands {
CMD_CHANGE_SERVICE_INT, ///< change the server interval of a vehicle
CMD_BUILD_INDUSTRY, ///< build a new industry
+ CMD_INDUSTRY_CTRL, ///< change industry properties
CMD_SET_COMPANY_MANAGER_FACE, ///< set the manager's face of the company
CMD_SET_COMPANY_COLOUR, ///< set the colour of the company
diff --git a/src/industry.h b/src/industry.h
index e82033dd1..feee6f200 100644
--- a/src/industry.h
+++ b/src/industry.h
@@ -35,6 +35,26 @@ enum ProductionLevels {
};
/**
+ * Flags to control/override the behaviour of an industry.
+ * These flags are controlled by game scripts.
+ */
+enum IndustryControlFlags : byte {
+ /** No flags in effect */
+ INDCTL_NONE = 0,
+ /** When industry production change is evaluated, rolls to decrease are ignored. */
+ INDCTL_NO_PRODUCTION_DECREASE = 1 << 0,
+ /** When industry production change is evaluated, rolls to increase are ignored. */
+ INDCTL_NO_PRODUCTION_INCREASE = 1 << 1,
+ /**
+ * Industry can not close regardless of production level or time since last delivery.
+ * This does not prevent a closure already announced. */
+ INDCTL_NO_CLOSURE = 1 << 2,
+ /** Mask of all flags set */
+ INDCTL_MASK = INDCTL_NO_PRODUCTION_DECREASE | INDCTL_NO_PRODUCTION_INCREASE | INDCTL_NO_CLOSURE,
+};
+DECLARE_ENUM_AS_BIT_SET(IndustryControlFlags);
+
+/**
* Defines the internal data of a functional industry.
*/
struct Industry : IndustryPool::PoolItem<&_industry_pool> {
@@ -59,6 +79,7 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
byte random_colour; ///< randomized colour of the industry, for display purpose
Year last_prod_year; ///< last year of production
byte was_cargo_delivered; ///< flag that indicate this has been the closest industry chosen for cargo delivery by a station. see DeliverGoodsToIndustry
+ IndustryControlFlags ctlflags; ///< flags overriding standard behaviours
PartOfSubsidy part_of_subsidy; ///< NOSAVE: is this industry a source/destination of a subsidy?
StationList stations_near; ///< NOSAVE: List of nearby stations.
diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp
index b8b92e5bf..420244e6d 100644
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -1753,6 +1753,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
i->was_cargo_delivered = false;
i->last_prod_year = _cur_year;
i->founder = founder;
+ i->ctlflags = INDCTL_NONE;
i->construction_date = _date;
i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
@@ -2049,6 +2050,43 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
}
+/**
+ * Change industry properties
+ * @param tile Unused.
+ * @param flags Type of operation.
+ * @param p1 IndustryID
+ * @param p2 various bitstuffed elements
+ * - p2 = (bit 0 - 7) - action to perform:
+ * 0 = set control flags
+ * - p2 = (bit 8 - 15) - IndustryControlFlags
+ * (only used with set control flags)
+ * @param text unused
+ * @return Empty cost or an error.
+ */
+CommandCost CmdIndustryCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+ if (_current_company != OWNER_DEITY) return CMD_ERROR;
+
+ Industry *ind = Industry::GetIfValid(p1);
+ if (ind == nullptr) return CMD_ERROR;
+
+ uint8 action = GB(p2, 0, 8);
+
+ switch (action) {
+ case 0: {
+ IndustryControlFlags ctlflags = (IndustryControlFlags)GB(p2, 8, 8) & INDCTL_MASK;
+
+ if (flags & DC_EXEC) ind->ctlflags = ctlflags;
+
+ break;
+ }
+
+ default:
+ NOT_REACHED();
+ }
+
+ return CommandCost();
+}
/**
* Create a new industry of random layout.
@@ -2659,7 +2697,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
}
}
} else if (_settings_game.economy.type == ET_SMOOTH) {
- closeit = true;
+ closeit = !(i->ctlflags & (INDCTL_NO_CLOSURE | INDCTL_NO_PRODUCTION_DECREASE));
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (i->produced_cargo[j] == CT_INVALID) continue;
uint32 r = Random();
@@ -2692,6 +2730,10 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
new_prod = Clamp(new_prod, 0, 16);
}
+ /* If override flags are set, prevent actually changing production if any was decided on */
+ if ((i->ctlflags & INDCTL_NO_PRODUCTION_DECREASE) && new_prod < old_prod) continue;
+ if ((i->ctlflags & INDCTL_NO_PRODUCTION_INCREASE) && new_prod > old_prod) continue;
+
/* Do not stop closing the industry when it has the lowest possible production rate */
if (new_prod == old_prod && old_prod > 1) {
closeit = false;
@@ -2711,6 +2753,10 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
}
}
+ /* If override flags are set, prevent actually changing production if any was decided on */
+ if ((i->ctlflags & INDCTL_NO_PRODUCTION_DECREASE) && (div > 0 || increment < 0)) return;
+ if ((i->ctlflags & INDCTL_NO_PRODUCTION_INCREASE) && (mul > 0 || increment > 0)) return;
+
if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, original_economy ? 2 : 180)) {
closeit = true;
@@ -2728,6 +2774,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
while (div-- != 0 && !closeit) {
if (i->prod_level == PRODLEVEL_MINIMUM) {
closeit = true;
+ break;
} else {
i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
recalculate_multipliers = true;
@@ -2750,7 +2797,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
if (recalculate_multipliers) i->RecomputeProductionMultipliers();
/* Close if needed and allowed */
- if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
+ if (closeit && !CheckIndustryCloseDownProtection(i->type) && !(i->ctlflags & INDCTL_NO_CLOSURE)) {
i->prod_level = PRODLEVEL_CLOSURE;
SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
str = indspec->closure_text;
diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp
index a8748a495..2dbe907de 100644
--- a/src/newgrf_industries.cpp
+++ b/src/newgrf_industries.cpp
@@ -248,6 +248,9 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
case 0x46: return this->industry->construction_date; // Date when built - long format - (in days)
+ /* Override flags from GS */
+ case 0x47: return this->industry->ctlflags;
+
/* Get industry ID at offset param */
case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, this->industry->location.tile, false), this->industry, this->ro.grffile->grfid);
diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp
index f5b1464c1..8f7301120 100644
--- a/src/saveload/industry_sl.cpp
+++ b/src/saveload/industry_sl.cpp
@@ -56,6 +56,7 @@ static const SaveLoad _industry_desc[] = {
SLE_CONDVAR(Industry, last_prod_year, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
SLE_CONDVAR(Industry, last_prod_year, SLE_INT32, SLV_31, SL_MAX_VERSION),
SLE_VAR(Industry, was_cargo_delivered, SLE_UINT8),
+ SLE_CONDVAR(Industry, ctlflags, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
SLE_CONDVAR(Industry, founder, SLE_UINT8, SLV_70, SL_MAX_VERSION),
SLE_CONDVAR(Industry, construction_date, SLE_INT32, SLV_70, SL_MAX_VERSION),
diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h
index 7fa91a509..0b525570d 100644
--- a/src/saveload/saveload.h
+++ b/src/saveload/saveload.h
@@ -320,6 +320,8 @@ 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.
+
SL_MAX_VERSION, ///< Highest possible saveload version
};
diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp
index fc917a012..abc9e9c35 100644
--- a/src/script/api/game_changelog.hpp
+++ b/src/script/api/game_changelog.hpp
@@ -21,6 +21,10 @@
* \li GSEventStoryPageButtonClick
* \li GSEventStoryPageTileSelect
* \li GSEventStoryPageVehicleSelect
+ * \li GSIndustry::GetCargoLastAcceptedDate
+ * \li GSIndustry::GetControlFlags
+ * \li GSIndustry::GetLastProductionYear
+ * \li GSIndustry::SetControlFlags
* \li GSStoryPage::MakePushButtonReference
* \li GSStoryPage::MakeTileButtonReference
* \li GSStoryPage::MakeVehicleButtonReference
diff --git a/src/script/api/script_cargo.hpp b/src/script/api/script_cargo.hpp
index 4aab97c70..9ecd4cbfb 100644
--- a/src/script/api/script_cargo.hpp
+++ b/src/script/api/script_cargo.hpp
@@ -57,6 +57,7 @@ public:
/* Note: these values represent part of the in-game CargoTypes enum */
CT_AUTO_REFIT = ::CT_AUTO_REFIT, ///< Automatically choose cargo type when doing auto-refitting.
CT_NO_REFIT = ::CT_NO_REFIT, ///< Do not refit cargo of a vehicle.
+ CT_INVALID = ::CT_INVALID, ///< An invalid cargo type.
};
/**
diff --git a/src/script/api/script_industry.cpp b/src/script/api/script_industry.cpp
index 4d1e91a3c..c2b449b0b 100644
--- a/src/script/api/script_industry.cpp
+++ b/src/script/api/script_industry.cpp
@@ -16,6 +16,7 @@
#include "../../station_base.h"
#include "../../newgrf_industries.h"
#include "table/strings.h"
+#include <numeric>
#include "../../safeguards.h"
@@ -204,3 +205,39 @@
return ::Industry::Get(industry_id)->type;
}
+
+int32 ScriptIndustry::GetLastProductionYear(IndustryID industry_id)
+{
+ Industry *i = Industry::GetIfValid(industry_id);
+ if (i == nullptr) return 0;
+ return i->last_prod_year;
+}
+
+ScriptDate::Date ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoID cargo_type)
+{
+ Industry *i = Industry::GetIfValid(industry_id);
+ if (i == nullptr) return ScriptDate::DATE_INVALID;
+
+ if (cargo_type == CT_INVALID) {
+ return (ScriptDate::Date)std::accumulate(std::begin(i->last_cargo_accepted_at), std::end(i->last_cargo_accepted_at), 0, [](Date a, Date b) { return std::max(a, b); });
+ } else {
+ int index = i->GetCargoAcceptedIndex(cargo_type);
+ if (index < 0) return ScriptDate::DATE_INVALID;
+ return (ScriptDate::Date)i->last_cargo_accepted_at[index];
+ }
+}
+
+uint32 ScriptIndustry::GetControlFlags(IndustryID industry_id)
+{
+ Industry *i = Industry::GetIfValid(industry_id);
+ if (i == nullptr) return 0;
+ return i->ctlflags;
+}
+
+bool ScriptIndustry::SetControlFlags(IndustryID industry_id, uint32 control_flags)
+{
+ if (ScriptObject::GetCompany() != OWNER_DEITY) return false;
+ if (!IsValidIndustry(industry_id)) return false;
+
+ return ScriptObject::DoCommand(0, industry_id, 0 | ((control_flags & ::INDCTL_MASK) << 8), CMD_INDUSTRY_CTRL);
+}
diff --git a/src/script/api/script_industry.hpp b/src/script/api/script_industry.hpp
index 98c7d33ac..2fbd861cc 100644
--- a/src/script/api/script_industry.hpp
+++ b/src/script/api/script_industry.hpp
@@ -11,6 +11,8 @@
#define SCRIPT_INDUSTRY_HPP
#include "script_object.hpp"
+#include "script_date.hpp"
+#include "../../industry.h"
/**
* Class that handles all industry related functions.
@@ -26,6 +28,27 @@ public:
};
/**
+ * Control flags for industry
+ * @api -ai
+ */
+ enum IndustryControlFlags {
+ /**
+ * When industry production change is evaluated, rolls to decrease are ignored.
+ * This also prevents industry closure due to production dropping to the lowest level.
+ */
+ INDCTL_NO_PRODUCTION_DECREASE = ::INDCTL_NO_PRODUCTION_DECREASE,
+ /**
+ * When industry production change is evaluated, rolls to increase are ignored.
+ */
+ INDCTL_NO_PRODUCTION_INCREASE = ::INDCTL_NO_PRODUCTION_INCREASE,
+ /**
+ * Industry can not close regardless of production level or time since last delivery.
+ * This does not prevent a closure already announced.
+ */
+ INDCTL_NO_CLOSURE = ::INDCTL_NO_CLOSURE,
+ };
+
+ /**
* Gets the number of industries.
* @return The number of industries.
* @note The maximum valid IndustryID can be higher than the value returned.
@@ -196,6 +219,46 @@ public:
* @return The IndustryType of the industry.
*/
static IndustryType GetIndustryType(IndustryID industry_id);
+
+ /**
+ * Get the last year this industry had any production output.
+ * @param industry_id The index of the industry.
+ * @pre IsValidIndustry(industry_id).
+ * @return Year the industry last had production, 0 if error.
+ * @api -ai
+ */
+ static int32 GetLastProductionYear(IndustryID industry_id);
+
+ /**
+ * Get the last date this industry accepted any cargo delivery.
+ * @param industry_id The index of the industry.
+ * @param cargo_type The cargo to query, or CT_INVALID to query latest of all accepted cargoes.
+ * @pre IsValidIndustry(industry_id).
+ * @pre IsValidCargo(cargo_type) || cargo_type == CT_INVALID.
+ * @return Date the industry last received cargo from a delivery, or ScriptDate::DATE_INVALID on error.
+ * @api -ai
+ */
+ static ScriptDate::Date GetCargoLastAcceptedDate(IndustryID industry_id, CargoID cargo_type);
+
+ /**
+ * Get the current control flags for an industry.
+ * @param industry_id The index of the industry.
+ * @pre IsValidIndustry(industry_id).
+ * @return Bit flags of the IndustryControlFlags enumeration.
+ * @api -ai
+ */
+ static uint32 GetControlFlags(IndustryID industry_id);
+
+ /**
+ * Change the control flags for an industry.
+ * @param industry_id The index of the industry.
+ * @param control_flags New flags as a combination of IndustryControlFlags values.
+ * @pre IsValidIndustry(industry_id).
+ * @pre No ScriptCompanyMode may be in scope.
+ * @return True if the action succeeded.
+ * @api -ai
+ */
+ static bool SetControlFlags(IndustryID industry_id, uint32 control_flags);
};
#endif /* SCRIPT_INDUSTRY_HPP */