---------------------------------------------------------------------------------MaxCross wrote: ↑23 Jun 2020, 19:36 I forked openmw and created an merge request. Since, as I said, I don't think that this very speciffic feature will ever be merged into master branch of the official repository, target branch is in my fork also.
Just, if someone wants to have realistic sun damage in their version of openmw, maybe with this merge request it will be easier for them...
This is a temporary feature anyway - until the scripting system is added. And I really hope that when it is added, functions such as rendering raycast or getting the coordinates of the actor’s body parts will be available in it, so I don’t have to modify the engine source code only for realistic sun damage.
(note: i hope it isn't very noticeable that i'm not a native english speaker. If it is - i'm sorry)
Since shadows were added, I really wanted to get the opportunity to hide in them from the sun when I play as a vampire.
I understand that this is a very specific feature and it's unlikely to be added to engine officially, so I decided to try adding it myself.
Doesn’t sound very difficult - just raycast from the player’s position in the direction of the sun.
As far as I understand, currently there is no way to raycast scripted-way (at least I did not find one), so I have to modify the source code of the engine for this.
The problem is that I am not at all familiar with this source code at all.
However, after ~15 hours of setting up the build environment and digging in the source code, I got something similar to what I want.
Currently, code looks like this (there are several other changes here, but they are not relevant to this topic):
Code: Select all
//efffectTick() in mwmechanics/tickableeffect.cpp:145
case ESM::MagicEffect::SunDamage:
{
// isInCell shouldn't be needed, but updateActor called during game start
if (!actor.isInCell() || !actor.getCell()->isExterior())
break;
float time = MWBase::Environment::get().getWorld()->getTimeStamp().getHour();
float adjTime = time;
float dayStart = 6.f;
float dayEnd = 20.f;
float dayDuration = dayEnd - dayStart;
float nightDuration = 24.f - dayDuration;
if(adjTime < dayStart) adjTime += 24.f;
double theta;
if(adjTime < dayEnd) theta = osg::PI * (adjTime - dayStart) / dayDuration;
else theta = osg::PI - osg::PI * (adjTime - dayEnd) / nightDuration;
auto actorPos = actor.getRefData().getPosition().asVec3() + osg::Vec3f(0,0,125);
osg::Vec3f sunDirection(
cos(theta),
-0.268f,//~=tan(-15)
sin(theta)
);
sunDirection.normalize();
auto sunPos = actorPos + sunDirection * 500000;
int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door | MWPhysics::CollisionType_Actor | MWPhysics::CollisionType_HeightMap;
if(MWBase::Environment::get().getWorld()->castRay(actorPos, sunPos, mask, actor)) break;
float sunriseDuration = 1.0f;
float sunriseMult = std::min(std::max((adjTime - dayStart) / sunriseDuration, 0.f), 1.f);
float sunsetDuration = 1.0f;
float sunsetMult = std::min(std::max((dayEnd - adjTime) / sunsetDuration, 0.f), 1.f);
float sunMagnitude = std::min(sunriseMult, sunsetMult);
// When cloudy, the sun damage effect is halved
static float fMagicSunBlockedMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fMagicSunBlockedMult")->mValue.getFloat();
int weather = MWBase::Environment::get().getWorld()->getCurrentWeather();
if (weather > 1)
sunMagnitude *= fMagicSunBlockedMult;
if (magnitude * sunMagnitude > 0.f) {
adjustDynamicStat(creatureStats, 0, -magnitude * sunMagnitude);
receivedMagicDamage = true;
}
break;
}
- Is there any better way to get the direction of the sun than to calculate it manually? This method I actually copied from mwworld/weather.cpp:753.
- Is there any way to get the coordinates of a certain body part of the actor (MWWorld::Ptr&)? As a minimum - I would like to raycast from the actor’s head, not from a point which is 125 units higher than the actor’s position. As a maximum, I would like to raycast from each part of the actor’s body, so that the damage depends on how many body parts are actualy under the sun.
- Is there any analogue of a raycast that can hit meshes, not just collisions? The current version will not allow me, for example, to hide under the leaves of trees.
- Do I understand correctly that the coordinates are in centimeters? I mean, I had to raise the actor’s coordinates by 125 units to cast from the head...
- Any other suggestions on how this can be improved?