diff --git a/distribution/changelog.txt b/distribution/changelog.txt
index cc17f463f0..f0c2a3da24 100644
--- a/distribution/changelog.txt
+++ b/distribution/changelog.txt
@@ -5,6 +5,7 @@
- Feature: [#14296] Allow using early scenario completion in multiplayer.
- Feature: [#14538] [Plugin] Add property for getting current plugin api version.
- Feature: [#14620] [Plugin] Add properties related to guest generation.
+- Feature: [#14636] [Plugin] Add properties related to climate and weather.
- Change: [#14496] [Plugin] Rename Object to LoadedObject to fix conflicts with Typescript's Object interface.
- Change: [#14536] [Plugin] Rename ListView to ListViewWidget to make it consistent with names of other widgets.
- Fix: [#11829] Visual glitches and crashes when using RCT1 assets from mismatched or corrupt CSG1.DAT and CSG1i.DAT files.
diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts
index 48a252e792..72efec0980 100644
--- a/distribution/openrct2.d.ts
+++ b/distribution/openrct2.d.ts
@@ -37,6 +37,8 @@ declare global {
var park: Park;
/** APIs for the current scenario. */
var scenario: Scenario;
+ /** APIs for the climate and weather. */
+ var climate: Climate;
/**
* APIs for creating and editing title sequences.
* These will only be available to clients that are not running headless mode.
@@ -1819,6 +1821,45 @@ declare global {
companyValueRecord: number;
}
+ type ClimateType =
+ "coolAndWet" |
+ "warm" |
+ "hotAndDry" |
+ "cold";
+
+ type WeatherType =
+ "sunny" |
+ "partiallyCloudy" |
+ "cloudy" |
+ "rain" |
+ "heavyRain" |
+ "thunder" |
+ "snow" |
+ "heavySnow" |
+ "blizzard";
+
+ interface ClimateState {
+ readonly weather: WeatherType;
+ readonly temperature: number;
+ }
+
+ interface Climate {
+ /**
+ * The climate of the park.
+ */
+ readonly type: ClimateType;
+
+ /**
+ * The current weather in the park.
+ */
+ readonly current: ClimateState;
+
+ /**
+ * The next weather the park will experience.
+ */
+ readonly future: ClimateState;
+ }
+
interface Cheats {
allowArbitraryRideTypeChanges: boolean;
allowTrackPlaceInvalidHeights: boolean;
diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj
index 932b7699c4..c1ec236294 100644
--- a/src/openrct2/libopenrct2.vcxproj
+++ b/src/openrct2/libopenrct2.vcxproj
@@ -408,6 +408,7 @@
+
diff --git a/src/openrct2/scripting/ScClimate.hpp b/src/openrct2/scripting/ScClimate.hpp
new file mode 100644
index 0000000000..779d22ada2
--- /dev/null
+++ b/src/openrct2/scripting/ScClimate.hpp
@@ -0,0 +1,129 @@
+/*****************************************************************************
+ * Copyright (c) 2014-2021 OpenRCT2 developers
+ *
+ * For a complete list of all authors, please refer to contributors.md
+ * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
+ *
+ * OpenRCT2 is licensed under the GNU General Public License version 3.
+ *****************************************************************************/
+
+#pragma once
+
+#ifdef ENABLE_SCRIPTING
+
+# include "../Context.h"
+# include "../common.h"
+# include "../core/String.hpp"
+# include "../world/Climate.h"
+# include "Duktape.hpp"
+# include "ScriptEngine.h"
+
+namespace OpenRCT2::Scripting
+{
+ class ScClimateState
+ {
+ private:
+ std::string _weather;
+ int8_t _temperature;
+
+ public:
+ ScClimateState(std::string weather, int8_t temperature)
+ : _weather(weather)
+ , _temperature(temperature)
+ {
+ }
+
+ std::string weather_get() const
+ {
+ return _weather;
+ }
+
+ int8_t temperature_get() const
+ {
+ return _temperature;
+ }
+
+ static void Register(duk_context* ctx)
+ {
+ dukglue_register_property(ctx, &ScClimateState::weather_get, nullptr, "weather");
+ dukglue_register_property(ctx, &ScClimateState::temperature_get, nullptr, "temperature");
+ }
+ };
+
+ class ScClimate
+ {
+ public:
+ static std::string ClimateTypeToString(ClimateType token)
+ {
+ switch (token)
+ {
+ case ClimateType::CoolAndWet:
+ return "coolAndWet";
+ case ClimateType::Warm:
+ return "warm";
+ case ClimateType::HotAndDry:
+ return "hotAndDry";
+ case ClimateType::Cold:
+ return "cold";
+ case ClimateType::Count:
+ return "";
+ }
+ return "";
+ }
+
+ static std::string WeatherTypeToString(WeatherType token)
+ {
+ switch (token)
+ {
+ case WeatherType::Sunny:
+ return "sunny";
+ case WeatherType::PartiallyCloudy:
+ return "partiallyCloudy";
+ case WeatherType::Cloudy:
+ return "cloudy";
+ case WeatherType::Rain:
+ return "rain";
+ case WeatherType::HeavyRain:
+ return "heavyRain";
+ case WeatherType::Thunder:
+ return "thunder";
+ case WeatherType::Snow:
+ return "snow";
+ case WeatherType::HeavySnow:
+ return "heavySnow";
+ case WeatherType::Blizzard:
+ return "blizzard";
+ case WeatherType::Count:
+ return "";
+ }
+ return "";
+ }
+
+ std::string type_get() const
+ {
+ return ClimateTypeToString(gClimate);
+ }
+
+ std::shared_ptr current_get() const
+ {
+ std::string weatherType = WeatherTypeToString(gClimateCurrent.Weather);
+ return std::make_shared(weatherType, gClimateCurrent.Temperature);
+ }
+
+ std::shared_ptr future_get() const
+ {
+ std::string weatherType = WeatherTypeToString(gClimateNext.Weather);
+ return std::make_shared(weatherType, gClimateNext.Temperature);
+ }
+
+ static void Register(duk_context* ctx)
+ {
+ dukglue_register_property(ctx, &ScClimate::type_get, nullptr, "type");
+ dukglue_register_property(ctx, &ScClimate::current_get, nullptr, "current");
+ dukglue_register_property(ctx, &ScClimate::future_get, nullptr, "future");
+ }
+ };
+
+} // namespace OpenRCT2::Scripting
+
+#endif
diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp
index bb93efdc36..d1a1ff3217 100644
--- a/src/openrct2/scripting/ScriptEngine.cpp
+++ b/src/openrct2/scripting/ScriptEngine.cpp
@@ -24,6 +24,7 @@
# include "../platform/Platform2.h"
# include "Duktape.hpp"
# include "ScCheats.hpp"
+# include "ScClimate.hpp"
# include "ScConsole.hpp"
# include "ScContext.hpp"
# include "ScDate.hpp"
@@ -377,6 +378,8 @@ void ScriptEngine::Initialise()
{
auto ctx = static_cast(_context);
ScCheats::Register(ctx);
+ ScClimate::Register(ctx);
+ ScClimateState::Register(ctx);
ScConfiguration::Register(ctx);
ScConsole::Register(ctx);
ScContext::Register(ctx);
@@ -409,6 +412,7 @@ void ScriptEngine::Initialise()
ScStaff::Register(ctx);
dukglue_register_global(ctx, std::make_shared(), "cheats");
+ dukglue_register_global(ctx, std::make_shared(), "climate");
dukglue_register_global(ctx, std::make_shared(_console), "console");
dukglue_register_global(ctx, std::make_shared(_execInfo, _hookEngine), "context");
dukglue_register_global(ctx, std::make_shared(), "date");
diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h
index 7ef439f4be..c4f041aeae 100644
--- a/src/openrct2/scripting/ScriptEngine.h
+++ b/src/openrct2/scripting/ScriptEngine.h
@@ -46,7 +46,7 @@ namespace OpenRCT2
namespace OpenRCT2::Scripting
{
- static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 29;
+ static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 30;
# ifndef DISABLE_NETWORK
class ScSocketBase;