Merge branch 'weather_the_sun' into 'master'

Implement sun damage based on the research on the wiki

Closes #6977

See merge request OpenMW/openmw!2422
make_linux_ci_do_zoomies
psi29a 2 years ago
commit fb90d35805

@ -13,6 +13,7 @@
Bug #6949: Sun Damage effect doesn't work in quasi exteriors
Bug #6964: Nerasa Dralor Won't Follow
Bug #6974: Only harmful effects are reflected
Bug #6977: Sun damage implementation does not match research
Bug #6986: Sound magic effect does not make noise
Bug #6987: Set/Mod Blindness should not darken the screen
Bug #6992: Crossbow reloading doesn't look the same as in Morrowind

@ -564,6 +564,9 @@ namespace MWBase
// Allow NPCs to use torches?
virtual bool useTorches() const = 0;
virtual float getSunVisibility() const = 0;
virtual float getSunPercentage() const = 0;
virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)

@ -664,15 +664,9 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
// isInCell shouldn't be needed, but updateActor called during game start
if (!target.isInCell() || !(target.getCell()->isExterior() || target.getCell()->isQuasiExterior()) || godmode)
break;
float time = world->getTimeStamp().getHour();
float timeDiff = std::clamp(std::abs(time - 13.f), 0.f, 7.f);
float damageScale = 1.f - timeDiff / 7.f;
// When cloudy, the sun damage effect is halved
const float sunRisen = world->getSunPercentage();
static float fMagicSunBlockedMult = world->getStore().get<ESM::GameSetting>().find("fMagicSunBlockedMult")->mValue.getFloat();
int weather = world->getCurrentWeather();
if (weather > 1)
damageScale *= fMagicSunBlockedMult;
const float damageScale = std::clamp(std::max(world->getSunVisibility() * sunRisen, fMagicSunBlockedMult * sunRisen), 0.f, 1.f);
float damage = effect.mMagnitude * damageScale;
adjustDynamicStat(target, 0, -damage);
if (damage > 0.f)

@ -176,8 +176,8 @@ namespace
, mParticleEffect(particleEffect)
, mRainEffect(Fallback::Map::getBool("Weather_" + name + "_Using_Precip") ? "meshes\\raindrop.nif" : "")
, mStormDirection(Weather::defaultDirection())
, mTransitionDelta(Fallback::Map::getFloat("Weather_" + name + "_Transition_Delta"))
, mCloudsMaximumPercent(Fallback::Map::getFloat("Weather_" + name + "_Clouds_Maximum_Percent"))
, mTransitionDelta(Fallback::Map::getFloat("Weather_" + name + "_Transition_Delta"))
, mThunderFrequency(Fallback::Map::getFloat("Weather_" + name + "_Thunder_Frequency"))
, mThunderThreshold(Fallback::Map::getFloat("Weather_" + name + "_Thunder_Threshold"))
, mThunderSoundID()
@ -875,6 +875,27 @@ namespace
return isDark && !mPrecipitation;
}
float WeatherManager::getSunPercentage(float hour) const
{
if (hour <= mTimeSettings.mNightEnd || hour >= mTimeSettings.mNightStart)
return 0.f;
else if (hour <= mTimeSettings.mDayStart)
return (hour - mTimeSettings.mNightEnd) / mSunriseDuration;
else if (hour > mTimeSettings.mDayEnd)
return 1.f - ((hour - mTimeSettings.mDayEnd) / mSunsetDuration);
return 1.f;
}
float WeatherManager::getSunVisibility() const
{
if (inTransition() && mTransitionFactor < mWeatherSettings[mNextWeather].mCloudsMaximumPercent)
{
float t = mTransitionFactor / mWeatherSettings[mNextWeather].mCloudsMaximumPercent;
return (1.f - t) * mWeatherSettings[mCurrentWeather].mGlareView + t * mWeatherSettings[mNextWeather].mGlareView;
}
return mWeatherSettings[mCurrentWeather].mGlareView;
}
void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
{
ESM::WeatherState state;
@ -1072,7 +1093,7 @@ namespace
mQueuedWeather = invalidWeatherID;
}
inline bool WeatherManager::inTransition()
inline bool WeatherManager::inTransition() const
{
return mNextWeather != invalidWeatherID;
}

@ -193,6 +193,8 @@ namespace MWWorld
osg::Vec3f mStormDirection;
float mCloudsMaximumPercent;
// Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature
// is broken in the vanilla game and was disabled.
@ -203,7 +205,6 @@ namespace MWWorld
private:
float mTransitionDelta;
float mCloudsMaximumPercent;
// Note: In MW, only thunderstorms support these attributes, but in the interest of making weather more
// flexible, these settings are imported for all weather types. Only thunderstorms will normally have any
@ -315,6 +316,10 @@ namespace MWWorld
bool useTorches(float hour) const;
float getSunPercentage(float hour) const;
float getSunVisibility() const;
void write(ESM::ESMWriter& writer, Loading::Listener& progress);
bool readRecord(ESM::ESMReader& reader, uint32_t type);
@ -379,7 +384,7 @@ namespace MWWorld
void updateWeatherTransitions(const float elapsedRealSeconds);
void forceWeather(const int weatherID);
bool inTransition();
bool inTransition() const;
void addWeatherTransition(const int weatherID);
void calculateWeatherResult(const float gameHour, const float elapsedSeconds, const bool isPaused);

@ -3260,6 +3260,16 @@ namespace MWWorld
}
}
float World::getSunVisibility() const
{
return mWeatherManager->getSunVisibility();
}
float World::getSunPercentage() const
{
return mWeatherManager->getSunPercentage(getTimeStamp().getHour());
}
bool World::findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result)
{
if (cell->isExterior())

@ -668,6 +668,9 @@ namespace MWWorld
// Allow NPCs to use torches?
bool useTorches() const override;
float getSunVisibility() const override;
float getSunPercentage() const override;
bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)

Loading…
Cancel
Save