diff --git a/rwengine/src/data/Weather.hpp b/rwengine/src/data/Weather.hpp index 582d10ece..3a3d3edea 100644 --- a/rwengine/src/data/Weather.hpp +++ b/rwengine/src/data/Weather.hpp @@ -40,6 +40,14 @@ class Weather { float a, float tod); std::vector entries; + + // Taken from: https://www.gtamodding.com/wiki/Time_cycle#Weather_lists + // TODO: This weather list applies only for GTA III + const uint16_t WeatherList[64] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 0, + 0, 0, 1, 3, 3, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, + 2, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 2, 1 + }; }; #endif diff --git a/rwengine/src/engine/GameState.hpp b/rwengine/src/engine/GameState.hpp index 99013b324..c8a1caa2c 100644 --- a/rwengine/src/engine/GameState.hpp +++ b/rwengine/src/engine/GameState.hpp @@ -64,7 +64,7 @@ struct BasicState { uint8_t _align3[2]{0}; uint16_t nextWeather{0}; uint8_t _align4[2]{0}; - uint16_t forcedWeather{0}; + uint16_t forcedWeather{0xFFFF}; uint8_t _align5[2]{0}; float weatherInterpolation{1.f}; uint8_t dateTime[24]{0}; // Unused diff --git a/rwengine/src/script/modules/GTA3ModuleImpl.inl b/rwengine/src/script/modules/GTA3ModuleImpl.inl index 06ae9e27c..ae5dd1886 100644 --- a/rwengine/src/script/modules/GTA3ModuleImpl.inl +++ b/rwengine/src/script/modules/GTA3ModuleImpl.inl @@ -4870,8 +4870,7 @@ void opcode_01b6(const ScriptArguments& args, const ScriptWeather weatherID) { opcode 01b7 */ void opcode_01b7(const ScriptArguments& args) { - RW_UNUSED(args); - args.getState()->basic.forcedWeather = -1; + args.getState()->basic.forcedWeather = UINT16_MAX; } /** diff --git a/rwgame/RWGame.cpp b/rwgame/RWGame.cpp index e9aaa87e2..b1a55effd 100644 --- a/rwgame/RWGame.cpp +++ b/rwgame/RWGame.cpp @@ -533,6 +533,7 @@ void RWGame::tick(float dt) { static float clockAccumulator = 0.f; static float scriptTimerAccumulator = 0.f; static ScriptInt beepTime = std::numeric_limits::max(); + static uint8_t prevGameHour = state.basic.gameHour; if (currState->shouldWorldUpdate()) { world->chase.update(dt); @@ -554,6 +555,8 @@ void RWGame::tick(float dt) { clockAccumulator -= 1.f; } + interpolateWeather(prevGameHour); + constexpr float timerClockRate = 1.f / 30.f; if (state.scriptTimerVariable && !state.scriptTimerPaused) { @@ -844,3 +847,23 @@ void RWGame::globalKeyEvent(const SDL_Event& event) { handleCheatInput(symbol); } } + +void RWGame::interpolateWeather(uint8_t prevGameHour) { + if (prevGameHour != state.basic.gameHour) { + state.basic.lastWeather = state.basic.nextWeather; + + // TODO: VC and SA has more than 4 weather conditions + if (state.basic.forcedWeather > 3) { + if (state.basic.weatherType < 63) { + ++state.basic.weatherType; + } else { + state.basic.weatherType = 0; + } + state.basic.nextWeather = + data.weather.WeatherList[state.basic.weatherType]; + } + } + + state.basic.weatherInterpolation = state.basic.gameMinute / 60.f; +} + diff --git a/rwgame/RWGame.hpp b/rwgame/RWGame.hpp index ffd11aba5..570c18132 100644 --- a/rwgame/RWGame.hpp +++ b/rwgame/RWGame.hpp @@ -131,6 +131,9 @@ class RWGame final : public GameBase { void renderDebugView(); void tickObjects(float dt) const; + + void interpolateWeather(uint8_t prevGameHour); }; #endif +