fix: weather particles and cycle durations deterministic due to unseeded rand()

8 rand() calls in weather.cpp used C rand() which defaults to seed 1.
Weather intensity rolls, cycle durations, and particle Y positions were
identical on every launch. Replaced with a file-local mt19937 seeded
from random_device, matching the RNG already present in getRandomPosition.
This commit is contained in:
Kelsi 2026-03-29 20:53:38 -07:00
parent 294c91d84a
commit a55eacfe70

View file

@ -14,6 +14,19 @@
namespace wowee { namespace wowee {
namespace rendering { namespace rendering {
namespace {
// Seeded RNG for weather particle positions and cycle durations.
// Replaces bare rand() which defaults to seed 1 without srand(),
// producing identical weather patterns on every launch.
std::mt19937& weatherRng() {
static std::mt19937 gen(std::random_device{}());
return gen;
}
float weatherRandFloat() {
return std::uniform_real_distribution<float>(0.0f, 1.0f)(weatherRng());
}
} // namespace
Weather::Weather() { Weather::Weather() {
} }
@ -324,7 +337,7 @@ void Weather::resetParticles(const Camera& camera) {
for (int i = 0; i < particleCount; ++i) { for (int i = 0; i < particleCount; ++i) {
Particle p; Particle p;
p.position = getRandomPosition(cameraPos); p.position = getRandomPosition(cameraPos);
p.position.y = cameraPos.y + SPAWN_HEIGHT * (static_cast<float>(rand()) / RAND_MAX); p.position.y = cameraPos.y + SPAWN_HEIGHT * (weatherRandFloat());
p.lifetime = 0.0f; p.lifetime = 0.0f;
if (weatherType == Type::RAIN) { if (weatherType == Type::RAIN) {
@ -456,19 +469,19 @@ void Weather::updateZoneWeather(uint32_t zoneId, float deltaTime) {
targetIntensity_ = 0.0f; targetIntensity_ = 0.0f;
} else { } else {
// Roll whether weather is active based on probability // Roll whether weather is active based on probability
float roll = static_cast<float>(rand()) / static_cast<float>(RAND_MAX); float roll = weatherRandFloat();
zoneWeatherActive_ = (roll < it->second.probability); zoneWeatherActive_ = (roll < it->second.probability);
if (zoneWeatherActive_) { if (zoneWeatherActive_) {
weatherType = it->second.type; weatherType = it->second.type;
// Random intensity within configured range // Random intensity within configured range
float t = static_cast<float>(rand()) / static_cast<float>(RAND_MAX); float t = weatherRandFloat();
targetIntensity_ = glm::mix(it->second.minIntensity, it->second.maxIntensity, t); targetIntensity_ = glm::mix(it->second.minIntensity, it->second.maxIntensity, t);
// Random cycle duration: 3-8 minutes // Random cycle duration: 3-8 minutes
zoneWeatherCycleDuration_ = 180.0f + static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 300.0f; zoneWeatherCycleDuration_ = 180.0f + weatherRandFloat() * 300.0f;
} else { } else {
targetIntensity_ = 0.0f; targetIntensity_ = 0.0f;
zoneWeatherCycleDuration_ = 120.0f + static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 180.0f; zoneWeatherCycleDuration_ = 120.0f + weatherRandFloat() * 180.0f;
} }
} }
} }
@ -496,19 +509,19 @@ void Weather::updateZoneWeather(uint32_t zoneId, float deltaTime) {
auto it = zoneWeatherTable_.find(zoneId); auto it = zoneWeatherTable_.find(zoneId);
if (it != zoneWeatherTable_.end()) { if (it != zoneWeatherTable_.end()) {
float roll = static_cast<float>(rand()) / static_cast<float>(RAND_MAX); float roll = weatherRandFloat();
zoneWeatherActive_ = (roll < it->second.probability); zoneWeatherActive_ = (roll < it->second.probability);
if (zoneWeatherActive_) { if (zoneWeatherActive_) {
weatherType = it->second.type; weatherType = it->second.type;
float t = static_cast<float>(rand()) / static_cast<float>(RAND_MAX); float t = weatherRandFloat();
targetIntensity_ = glm::mix(it->second.minIntensity, it->second.maxIntensity, t); targetIntensity_ = glm::mix(it->second.minIntensity, it->second.maxIntensity, t);
} else { } else {
targetIntensity_ = 0.0f; targetIntensity_ = 0.0f;
} }
// New cycle duration // New cycle duration
zoneWeatherCycleDuration_ = 180.0f + static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 300.0f; zoneWeatherCycleDuration_ = 180.0f + weatherRandFloat() * 300.0f;
} }
} }
} }