diff --git a/AUTHORS.md b/AUTHORS.md index 185b5ee66..190a2f345 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -71,6 +71,7 @@ Programmers John Blomberg (fstp) Jordan Ayers Jordan Milne + Jules Blok (Armada651) Julien Voisin (jvoisin/ap0) Karl-Felix Glatzer (k1ll) Kevin Poitra (PuppyKevin) @@ -80,6 +81,7 @@ Programmers lazydev Leon Krieg (lkrieg) Leon Saunders (emoose) + logzero lohikaarme Lukasz Gromanowski (lgro) Manuel Edelmann (vorenon) diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh index a2ea720e5..49af86a3e 100755 --- a/CI/before_install.osx.sh +++ b/CI/before_install.osx.sh @@ -7,5 +7,5 @@ brew rm pkgconfig || true brew rm qt5 || true brew install cmake pkgconfig $macos_qt_formula -curl http://downloads.openmw.org/osx/dependencies/openmw-deps-263d4a8.zip -o ~/openmw-deps.zip +curl https://downloads.openmw.org/osx/dependencies/openmw-deps-0ecece4.zip -o ~/openmw-deps.zip unzip ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index ff4ae6148..9e5afb66a 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -164,7 +164,7 @@ namespace MWClass getContainerStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId()); if (hasInventory) - getInventoryStore(ptr).autoEquip(ptr); + getInventoryStore(ptr).autoEquipShield(ptr); } } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 3102354a6..830c2bcac 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -448,14 +448,14 @@ namespace MWDialogue { MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue); - // Clamp permanent disposition change so that final disposition doesn't go below 0 (could happen with intimidate) - float curDisp = static_cast(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor, false)); - if (curDisp + mPermanentDispositionChange < 0) - mPermanentDispositionChange = -curDisp; - // Apply disposition change to NPC's base disposition if (mActor.getClass().isNpc()) { + // Clamp permanent disposition change so that final disposition doesn't go below 0 (could happen with intimidate) + float curDisp = static_cast(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor, false)); + if (curDisp + mPermanentDispositionChange < 0) + mPermanentDispositionChange = -curDisp; + MWMechanics::NpcStats& npcStats = mActor.getClass().getNpcStats(mActor); npcStats.setBaseDisposition(static_cast(npcStats.getBaseDisposition() + mPermanentDispositionChange)); } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 78eb03f25..3b4288317 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -34,6 +34,7 @@ #include "movement.hpp" #include "character.hpp" #include "aicombat.hpp" +#include "aicombataction.hpp" #include "aifollow.hpp" #include "aipursue.hpp" #include "actor.hpp" @@ -291,10 +292,12 @@ namespace MWMechanics void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer) { - CreatureStats& creatureStats = actor1.getClass().getCreatureStats(actor1); + const CreatureStats& creatureStats1 = actor1.getClass().getCreatureStats(actor1); + if (creatureStats1.getAiSequence().isInCombat(actor2)) + return; - if (actor2.getClass().getCreatureStats(actor2).isDead() - || actor1.getClass().getCreatureStats(actor1).isDead()) + const CreatureStats& creatureStats2 = actor2.getClass().getCreatureStats(actor2); + if (creatureStats1.isDead() || creatureStats2.isDead()) return; const ESM::Position& actor1Pos = actor1.getRefData().getPosition(); @@ -303,55 +306,26 @@ namespace MWMechanics if (sqrDist > sqrAiProcessingDistance) return; - // pure water creatures won't try to fight with the target on the ground - // except that creature is already hostile - if ((againstPlayer || !creatureStats.getAiSequence().isInCombat()) - && !MWMechanics::isEnvironmentCompatible(actor1, actor2)) // creature can't swim to target - { - return; - } - - // no combat for totally static creatures (they have no movement or attack animations anyway) + // No combat for totally static creatures if (!actor1.getClass().isMobile(actor1)) return; - bool aggressive; - - if (againstPlayer) - { - // followers with high fight should not engage in combat with the player (e.g. bm_bear_black_summon) - const std::list& followers = getActorsSidingWith(actor2); - if (std::find(followers.begin(), followers.end(), actor1) != followers.end()) - return; - - aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2); - } - else - { - aggressive = false; - - // Make guards fight aggressive creatures - if (!actor1.getClass().isNpc() && actor2.getClass().isClass(actor2, "Guard")) - { - if (creatureStats.getAiSequence().isInCombat() && MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2)) - aggressive = true; - } - } - - // start combat if target actor is in combat with one of our followers - const std::list& followers = getActorsSidingWith(actor1); - const CreatureStats& creatureStats2 = actor2.getClass().getCreatureStats(actor2); - for (std::list::const_iterator it = followers.begin(); it != followers.end(); ++it) + // Start combat if target actor is in combat with one of our followers or escorters + const std::list& followersAndEscorters = getActorsSidingWith(actor1); + for (std::list::const_iterator it = followersAndEscorters.begin(); it != followersAndEscorters.end(); ++it) { - // need to check both ways since player doesn't use AI packages + // Need to check both ways since player doesn't use AI packages if ((creatureStats2.getAiSequence().isInCombat(*it) || it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(actor2)) - && !creatureStats.getAiSequence().isInCombat(*it)) - aggressive = true; + && !creatureStats1.getAiSequence().isInCombat(*it)) + { + MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2); + return; + } } - // start combat if target actor is in combat with someone we are following - for (std::list::const_iterator it = creatureStats.getAiSequence().begin(); it != creatureStats.getAiSequence().end(); ++it) + // Start combat if target actor is in combat with someone we are following through a follow package + for (std::list::const_iterator it = creatureStats1.getAiSequence().begin(); it != creatureStats1.getAiSequence().end(); ++it) { if (!(*it)->sideWithTarget()) continue; @@ -361,20 +335,63 @@ namespace MWMechanics if (followTarget.isEmpty()) continue; - if (creatureStats.getAiSequence().isInCombat(followTarget)) + if (creatureStats1.getAiSequence().isInCombat(followTarget)) continue; - // need to check both ways since player doesn't use AI packages + // Need to check both ways since player doesn't use AI packages if (creatureStats2.getAiSequence().isInCombat(followTarget) || followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2)) - aggressive = true; + { + MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2); + return; + } + } + + // Start combat with the player if we are already in combat with a player follower or escorter + const std::list& playerFollowersAndEscorters = getActorsSidingWith(getPlayer()); + if (againstPlayer) + { + for (std::list::const_iterator it = playerFollowersAndEscorters.begin(); it != playerFollowersAndEscorters.end(); ++it) + { + if (creatureStats1.getAiSequence().isInCombat(*it)) + { + MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2); + return; + } + } + } + + // Otherwise, don't initiate combat with an unreachable target + if (!MWMechanics::canFight(actor1,actor2)) + return; + + bool aggressive = false; + + if (againstPlayer || std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), actor2) != playerFollowersAndEscorters.end()) + { + // Player followers and escorters with high fight should not initiate combat here with the player or with + // other player followers or escorters + if (std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), actor1) != playerFollowersAndEscorters.end()) + return; + + aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2); + } + else + { + // Make guards fight aggressive creatures + if (!actor1.getClass().isNpc() && actor2.getClass().isClass(actor2, "Guard")) + { + if (creatureStats1.getAiSequence().isInCombat() && MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2)) + aggressive = true; + } } - if(aggressive) + if (aggressive) { bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor1, actor2); - if (againstPlayer) LOS &= MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor2, actor1); + if (againstPlayer || std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), actor2) != playerFollowersAndEscorters.end()) + LOS &= MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor2, actor1); if (LOS) { diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index d8dae8b79..fbd3819e2 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -19,6 +19,7 @@ #include "aicombataction.hpp" #include "combat.hpp" #include "coordinateconverter.hpp" +#include "actorutil.hpp" namespace { @@ -210,13 +211,14 @@ namespace MWMechanics else { timerReact = 0; - attack(actor, target, storage, characterController); + if (attack(actor, target, storage, characterController)) + return true; } return false; } - void AiCombat::attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController) + bool AiCombat::attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController) { const MWWorld::CellStore*& currentCell = storage.mCell; bool cellChange = currentCell && (actor.getCell() != currentCell); @@ -231,7 +233,10 @@ namespace MWMechanics storage.stopAttack(); characterController.setAttackingOrSpell(false); storage.mActionCooldown = 0.f; - forceFlee = true; + if (target == MWMechanics::getPlayer()) + forceFlee = true; + else + return true; } const MWWorld::Class& actorClass = actor.getClass(); @@ -243,7 +248,7 @@ namespace MWMechanics if (!forceFlee) { if (actionCooldown > 0) - return; + return false; if (characterController.readyToPrepareAttack()) { @@ -258,7 +263,7 @@ namespace MWMechanics } if (!currentAction) - return; + return false; if (storage.isFleeing() != currentAction->isFleeing()) { @@ -266,7 +271,7 @@ namespace MWMechanics { storage.startFleeing(); MWBase::Environment::get().getDialogueManager()->say(actor, "flee"); - return; + return false; } else storage.stopFleeing(); @@ -311,6 +316,7 @@ namespace MWMechanics storage.mMovement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated } } + return false; } void MWMechanics::AiCombat::updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage) diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index a2e995cb3..fbe864ca0 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -59,7 +59,8 @@ namespace MWMechanics int mTargetActorId; - void attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController); + /// Returns true if combat should end + bool attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController); void updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 143b9c779..b4ea29efe 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -617,6 +617,11 @@ namespace MWMechanics return true; } } + else if (target.getClass().isActor() && effectId == ESM::MagicEffect::Dispel) + { + target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude); + return true; + } else if (target.getClass().isActor() && target == getPlayer()) { MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mCaster); @@ -1154,9 +1159,6 @@ namespace MWMechanics case ESM::MagicEffect::CureCorprusDisease: actor.getClass().getCreatureStats(actor).getSpells().purgeCorprusDisease(); break; - case ESM::MagicEffect::Dispel: - actor.getClass().getCreatureStats(actor).getActiveSpells().purgeAll(magnitude); - break; case ESM::MagicEffect::RemoveCurse: actor.getClass().getCreatureStats(actor).getSpells().purgeCurses(); break; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 7cfa38ff2..2d0964f25 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -55,29 +55,46 @@ namespace MWPhysics static const float sMaxSlope = 49.0f; static const float sStepSizeUp = 34.0f; static const float sStepSizeDown = 62.0f; + static const float sMinStep = 10.f; // Arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared. static const int sMaxIterations = 8; - // FIXME: move to a separate file - class MovementSolver + static bool isActor(const btCollisionObject *obj) + { + assert(obj); + return obj->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor; + } + + template + static bool isWalkableSlope(const Vec3 &normal) + { + static const float sMaxSlopeCos = std::cos(osg::DegreesToRadians(sMaxSlope)); + return (normal.z() > sMaxSlopeCos); + } + + static bool canStepDown(const ActorTracer &stepper) + { + return stepper.mHitObject && isWalkableSlope(stepper.mPlaneNormal) && !isActor(stepper.mHitObject); + } + + class Stepper { private: - static float getSlope(osg::Vec3f normal) - { - normal.normalize(); - return osg::RadiansToDegrees(std::acos(normal * osg::Vec3f(0.f, 0.f, 1.f))); - } + const btCollisionWorld *mColWorld; + const btCollisionObject *mColObj; - enum StepMoveResult - { - Result_Blocked, // unable to move over obstacle - Result_MaxSlope, // unable to end movement on this slope - Result_Success - }; + ActorTracer mTracer, mUpStepper, mDownStepper; + bool mHaveMoved; - static StepMoveResult stepMove(const btCollisionObject *colobj, osg::Vec3f &position, - const osg::Vec3f &toMove, float &remainingTime, const btCollisionWorld* collisionWorld) + public: + Stepper(const btCollisionWorld *colWorld, const btCollisionObject *colObj) + : mColWorld(colWorld) + , mColObj(colObj) + , mHaveMoved(true) + {} + + bool step(osg::Vec3f &position, const osg::Vec3f &toMove, float &remainingTime) { /* * Slide up an incline or set of stairs. Should be called only after a @@ -123,12 +140,14 @@ namespace MWPhysics * +--+ +-------- * ============================================== */ - ActorTracer tracer, stepper; - - stepper.doTrace(colobj, position, position+osg::Vec3f(0.0f,0.0f,sStepSizeUp), collisionWorld); - if(stepper.mFraction < std::numeric_limits::epsilon()) - return Result_Blocked; // didn't even move the smallest representable amount - // (TODO: shouldn't this be larger? Why bother with such a small amount?) + if (mHaveMoved) + { + mHaveMoved = false; + mUpStepper.doTrace(mColObj, position, position+osg::Vec3f(0.0f,0.0f,sStepSizeUp), mColWorld); + if(mUpStepper.mFraction < std::numeric_limits::epsilon()) + return false; // didn't even move the smallest representable amount + // (TODO: shouldn't this be larger? Why bother with such a small amount?) + } /* * Try moving from the elevated position using tracer. @@ -143,9 +162,10 @@ namespace MWPhysics * +--+ * ============================================== */ - tracer.doTrace(colobj, stepper.mEndPos, stepper.mEndPos + toMove, collisionWorld); - if(tracer.mFraction < std::numeric_limits::epsilon()) - return Result_Blocked; // didn't even move the smallest representable amount + osg::Vec3f tracerPos = mUpStepper.mEndPos; + mTracer.doTrace(mColObj, tracerPos, tracerPos + toMove, mColWorld); + if(mTracer.mFraction < std::numeric_limits::epsilon()) + return false; // didn't even move the smallest representable amount /* * Try moving back down sStepSizeDown using stepper. @@ -162,26 +182,40 @@ namespace MWPhysics * +--+ +--+ * ============================================== */ - stepper.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), collisionWorld); - if (getSlope(stepper.mPlaneNormal) > sMaxSlope) - return Result_MaxSlope; - if(stepper.mFraction < 1.0f) + mDownStepper.doTrace(mColObj, mTracer.mEndPos, mTracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), mColWorld); + if (!canStepDown(mDownStepper)) + { + // Try again with increased step length + if (mTracer.mFraction < 1.0f || toMove.length2() > sMinStep*sMinStep) + return false; + + osg::Vec3f direction = toMove; + direction.normalize(); + mTracer.doTrace(mColObj, tracerPos, tracerPos + direction*sMinStep, mColWorld); + if (mTracer.mFraction < 0.001f) + return false; + + mDownStepper.doTrace(mColObj, mTracer.mEndPos, mTracer.mEndPos-osg::Vec3f(0.0f,0.0f,sStepSizeDown), mColWorld); + if (!canStepDown(mDownStepper)) + return false; + } + if (mDownStepper.mFraction < 1.0f) { - // don't allow stepping up other actors - if (stepper.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor) - return Result_Blocked; // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall. // TODO: stepper.mPlaneNormal does not appear to be reliable - needs more testing // NOTE: caller's variables 'position' & 'remainingTime' are modified here - position = stepper.mEndPos; - remainingTime *= (1.0f-tracer.mFraction); // remaining time is proportional to remaining distance - return Result_Success; + position = mDownStepper.mEndPos; + remainingTime *= (1.0f-mTracer.mFraction); // remaining time is proportional to remaining distance + mHaveMoved = true; + return true; } - - return Result_Blocked; + return false; } + }; - + class MovementSolver + { + private: ///Project a vector u on another vector v static inline osg::Vec3f project(const osg::Vec3f& u, const osg::Vec3f &v) { @@ -229,14 +263,14 @@ namespace MWPhysics collisionWorld->rayTest(from, to, resultCallback1); if (resultCallback1.hasHit() && - ( (toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos).length() > 35 - || getSlope(tracer.mPlaneNormal) > sMaxSlope)) + ( (toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos).length2() > 35*35 + || !isWalkableSlope(tracer.mPlaneNormal))) { - actor->setOnGround(getSlope(toOsg(resultCallback1.m_hitNormalWorld)) <= sMaxSlope); + actor->setOnGround(isWalkableSlope(resultCallback1.m_hitNormalWorld)); return toOsg(resultCallback1.m_hitPointWorld) + osg::Vec3f(0.f, 0.f, 1.f); } - actor->setOnGround(getSlope(tracer.mPlaneNormal) <= sMaxSlope); + actor->setOnGround(isWalkableSlope(tracer.mPlaneNormal)); return tracer.mEndPos; } @@ -312,8 +346,8 @@ namespace MWPhysics velocity *= 1.f-(fStromWalkMult * (angleDegrees/180.f)); } + Stepper stepper(collisionWorld, colobj); osg::Vec3f origVelocity = velocity; - osg::Vec3f newPosition = position; /* * A loop to find newPosition using tracer, if successful different from the starting position. @@ -332,10 +366,7 @@ namespace MWPhysics newPosition.z() <= swimlevel) { const osg::Vec3f down(0,0,-1); - float movelen = velocity.normalize(); - osg::Vec3f reflectdir = reflect(velocity, down); - reflectdir.normalize(); - velocity = slide(reflectdir, down)*movelen; + velocity = slide(velocity, down); // NOTE: remainingTime is unchanged before the loop continues continue; // velocity updated, calculate nextpos again } @@ -364,19 +395,25 @@ namespace MWPhysics break; } + // We are touching something. + if (tracer.mFraction < 1E-9f) + { + // Try to separate by backing off slighly to unstuck the solver + const osg::Vec3f backOff = (newPosition - tracer.mHitPoint) * 1E-3f; + newPosition += backOff; + } + // We hit something. Check if we can step up. + float hitHeight = tracer.mHitPoint.z() - tracer.mEndPos.z() + halfExtents.z(); osg::Vec3f oldPosition = newPosition; - // We hit something. Try to step up onto it. (NOTE: stepMove does not allow stepping over) - // NOTE: stepMove modifies newPosition if successful - const float minStep = 10.f; - StepMoveResult result = stepMove(colobj, newPosition, velocity*remainingTime, remainingTime, collisionWorld); - if (result == Result_MaxSlope && (velocity*remainingTime).length() < minStep) // to make sure the maximum stepping distance isn't framerate-dependent or movement-speed dependent + bool result = false; + if (hitHeight < sStepSizeUp && !isActor(tracer.mHitObject)) { - osg::Vec3f normalizedVelocity = velocity; - normalizedVelocity.normalize(); - result = stepMove(colobj, newPosition, normalizedVelocity*minStep, remainingTime, collisionWorld); + // Try to step up onto it. + // NOTE: stepMove does not allow stepping over, modifies newPosition if successful + result = stepper.step(newPosition, velocity*remainingTime, remainingTime); } - if(result == Result_Success) + if (result) { // don't let pure water creatures move out of water after stepMove if (ptr.getClass().isPureWaterCreature(ptr) @@ -386,23 +423,19 @@ namespace MWPhysics else { // Can't move this way, try to find another spot along the plane - osg::Vec3f direction = velocity; - float movelen = direction.normalize(); - osg::Vec3f reflectdir = reflect(velocity, tracer.mPlaneNormal); - reflectdir.normalize(); + osg::Vec3f newVelocity = slide(velocity, tracer.mPlaneNormal); + + // Do not allow sliding upward if there is gravity. + // Stepping will have taken care of that. + if(!(newPosition.z() < swimlevel || isFlying)) + newVelocity.z() = std::min(newVelocity.z(), 0.0f); - osg::Vec3f newVelocity = slide(reflectdir, tracer.mPlaneNormal)*movelen; if ((newVelocity-velocity).length2() < 0.01) break; - if ((velocity * origVelocity) <= 0.f) + if ((newVelocity * origVelocity) <= 0.f) break; // ^ dot product velocity = newVelocity; - - // Do not allow sliding upward if there is gravity. Stepping will have taken - // care of that. - if(!(newPosition.z() < swimlevel || isFlying)) - velocity.z() = std::min(velocity.z(), 0.0f); } } @@ -413,7 +446,7 @@ namespace MWPhysics osg::Vec3f to = newPosition - (physicActor->getOnGround() ? osg::Vec3f(0,0,sStepSizeDown+2.f) : osg::Vec3f(0,0,2.f)); tracer.doTrace(colobj, from, to, collisionWorld); - if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope + if(tracer.mFraction < 1.0f && isWalkableSlope(tracer.mPlaneNormal) && tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup != CollisionType_Actor) { const btCollisionObject* standingOn = tracer.mHitObject; diff --git a/apps/openmw/mwphysics/trace.cpp b/apps/openmw/mwphysics/trace.cpp index 420ca1a9e..feda68ca5 100644 --- a/apps/openmw/mwphysics/trace.cpp +++ b/apps/openmw/mwphysics/trace.cpp @@ -78,6 +78,7 @@ void ActorTracer::doTrace(const btCollisionObject *actor, const osg::Vec3f& star mFraction = newTraceCallback.m_closestHitFraction; mPlaneNormal = osg::Vec3f(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); mEndPos = (end-start)*mFraction + start; + mHitPoint = toOsg(newTraceCallback.m_hitPointWorld); mHitObject = newTraceCallback.m_hitCollisionObject; } else @@ -85,6 +86,7 @@ void ActorTracer::doTrace(const btCollisionObject *actor, const osg::Vec3f& star mEndPos = end; mPlaneNormal = osg::Vec3f(0.0f, 0.0f, 1.0f); mFraction = 1.0f; + mHitPoint = end; mHitObject = NULL; } } diff --git a/apps/openmw/mwphysics/trace.h b/apps/openmw/mwphysics/trace.h index 7b7d0391e..0297c9e07 100644 --- a/apps/openmw/mwphysics/trace.h +++ b/apps/openmw/mwphysics/trace.h @@ -15,6 +15,7 @@ namespace MWPhysics { osg::Vec3f mEndPos; osg::Vec3f mPlaneNormal; + osg::Vec3f mHitPoint; const btCollisionObject* mHitObject; float mFraction; diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 6663b8b29..5cf1ecd36 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -144,6 +145,10 @@ namespace MWRender image->allocateImage(mWidth, mHeight, 1, GL_RGB, GL_UNSIGNED_BYTE); unsigned char* data = image->data(); + osg::ref_ptr alphaImage = new osg::Image; + alphaImage->allocateImage(mWidth, mHeight, 1, GL_ALPHA, GL_UNSIGNED_BYTE); + unsigned char* alphaData = alphaImage->data(); + for (int x = mMinX; x <= mMaxX; ++x) { for (int y = mMinY; y <= mMaxY; ++y) @@ -208,6 +213,8 @@ namespace MWRender data[texelY * mWidth * 3 + texelX * 3] = r; data[texelY * mWidth * 3 + texelX * 3+1] = g; data[texelY * mWidth * 3 + texelX * 3+2] = b; + + alphaData[texelY * mWidth+ texelX] = (y2 < 0) ? static_cast(0) : static_cast(255); } } loadingListener->increaseProgress(); @@ -224,6 +231,14 @@ namespace MWRender mBaseTexture->setImage(image); mBaseTexture->setResizeNonPowerOfTwoHint(false); + mAlphaTexture = new osg::Texture2D; + mAlphaTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + mAlphaTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + mAlphaTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + mAlphaTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + mAlphaTexture->setImage(alphaImage); + mAlphaTexture->setResizeNonPowerOfTwoHint(false); + clear(); loadingListener->loadingOff(); @@ -299,6 +314,28 @@ namespace MWRender stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + + if (mAlphaTexture) + { + osg::ref_ptr texcoords = new osg::Vec2Array; + + float x1 = x / static_cast(mWidth); + float x2 = (x + width) / static_cast(mWidth); + float y1 = y / static_cast(mHeight); + float y2 = (y + height) / static_cast(mHeight); + texcoords->push_back(osg::Vec2f(x1, y1)); + texcoords->push_back(osg::Vec2f(x1, y2)); + texcoords->push_back(osg::Vec2f(x2, y2)); + texcoords->push_back(osg::Vec2f(x2, y1)); + geom->setTexCoordArray(1, texcoords, osg::Array::BIND_PER_VERTEX); + + stateset->setTextureAttributeAndModes(1, mAlphaTexture, osg::StateAttribute::ON); + osg::ref_ptr texEnvCombine = new osg::TexEnvCombine; + texEnvCombine->setCombine_RGB(osg::TexEnvCombine::REPLACE); + texEnvCombine->setSource0_RGB(osg::TexEnvCombine::PREVIOUS); + stateset->setTextureAttributeAndModes(1, texEnvCombine); + } + camera->addChild(geom); } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index df8aa9962..1c44439fd 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -107,6 +107,7 @@ namespace MWRender std::vector< std::pair > mExploredCells; osg::ref_ptr mBaseTexture; + osg::ref_ptr mAlphaTexture; // GPU copy of overlay // Note, uploads are pushed through a Camera, instead of through mOverlayImage diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index f94cf9b43..fb259ff5f 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -437,7 +437,9 @@ bool OpenAL_SoundStream::process() alGetSourcei(mSource, AL_SOURCE_STATE, &state); if(state != AL_PLAYING && state != AL_PAUSED) { + // Ensure all processed buffers are removed so we don't replay them. refillQueue(); + alSourcePlay(mSource); } } @@ -906,7 +908,10 @@ void OpenAL_Output::finishSound(MWBase::SoundPtr sound) ALuint source = GET_PTRID(sound->mHandle); sound->mHandle = 0; - alSourceStop(source); + // Rewind the stream instead of stopping it, this puts the source into an AL_INITIAL state, + // which works around a bug in the MacOS OpenAL implementation which would otherwise think + // the initial queue already played when it hasn't. + alSourceRewind(source); alSourcei(source, AL_BUFFER, 0); mFreeSources.push_back(source); @@ -1006,7 +1011,10 @@ void OpenAL_Output::finishStream(MWBase::SoundStreamPtr sound) sound->mHandle = 0; mStreamThread->remove(stream); - alSourceStop(source); + // Rewind the stream instead of stopping it, this puts the source into an AL_INITIAL state, + // which works around a bug in the MacOS OpenAL implementation which would otherwise think + // the initial queue already played when it hasn't. + alSourceRewind(source); alSourcei(source, AL_BUFFER, 0); mFreeSources.push_back(source); diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 3745554ef..a0918b417 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -139,7 +139,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr, // Auto-equip items if an armor/clothing or weapon item is added, but not for the player nor werewolves if (actorPtr != MWMechanics::getPlayer() - && !(actorPtr.getClass().isNpc() && actorPtr.getClass().getNpcStats(actorPtr).isWerewolf())) + && actorPtr.getClass().isNpc() && !actorPtr.getClass().getNpcStats(actorPtr).isWerewolf()) { std::string type = itemPtr.getTypeName(); if (type == typeid(ESM::Armor).name() || type == typeid(ESM::Clothing).name()) @@ -243,10 +243,6 @@ bool MWWorld::InventoryStore::canActorAutoEquip(const MWWorld::Ptr& actor, const void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) { - if (!actor.getClass().isNpc()) - // autoEquip is no-op for creatures - return; - const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::Store &store = world->getStore().get(); MWMechanics::NpcStats& stats = actor.getClass().getNpcStats(actor); @@ -449,6 +445,50 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) } } +void MWWorld::InventoryStore::autoEquipShield(const MWWorld::Ptr& actor) +{ + bool updated = false; + + mUpdatesEnabled = false; + for (ContainerStoreIterator iter(begin(ContainerStore::Type_Armor)); iter != end(); ++iter) + { + if (iter->get()->mBase->mData.mType != ESM::Armor::Shield) + continue; + + if (iter->getClass().canBeEquipped(*iter, actor).first != 1) + continue; + + if (iter->getClass().getItemHealth(*iter) <= 0) + continue; + + std::pair, bool> shieldSlots = + iter->getClass().getEquipmentSlots(*iter); + + if (shieldSlots.first.empty()) + continue; + + int slot = shieldSlots.first[0]; + const ContainerStoreIterator& shield = mSlots[slot]; + + if (shield != end() + && shield.getType() == Type_Armor && shield->get()->mBase->mData.mType == ESM::Armor::Shield) + { + if (shield->getClass().getItemHealth(*shield) >= iter->getClass().getItemHealth(*iter)) + continue; + } + + equip(slot, iter, actor); + updated = true; + } + mUpdatesEnabled = true; + + if (updated) + { + fireEquipmentChangedEvent(actor); + updateMagicEffects(actor); + } +} + const MWMechanics::MagicEffects& MWWorld::InventoryStore::getMagicEffects() const { return mMagicEffects; @@ -628,7 +668,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor // If an armor/clothing item is removed, try to find a replacement, // but not for the player nor werewolves. if (wasEquipped && (actor != MWMechanics::getPlayer()) - && !(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())) + && actor.getClass().isNpc() && !actor.getClass().getNpcStats(actor).isWerewolf()) { std::string type = item.getTypeName(); if (type == typeid(ESM::Armor).name() || type == typeid(ESM::Clothing).name()) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 7e6a259c4..f625e4cd1 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -162,6 +162,9 @@ namespace MWWorld void autoEquip (const MWWorld::Ptr& actor); ///< Auto equip items according to stats and item value. + void autoEquipShield(const MWWorld::Ptr& actor); + ///< Auto-equip the shield with most health. + const MWMechanics::MagicEffects& getMagicEffects() const; ///< Return magic effects from worn items. diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 4d342336d..150d70c93 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -280,7 +280,9 @@ namespace MWWorld MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); for (size_t it = 0; it != state.mSoundIds.size(); it++) { - state.mSounds.push_back(sndMgr->playSound3D(pos, state.mSoundIds.at(it), 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop)); + MWBase::SoundPtr sound = sndMgr->playSound3D(pos, state.mSoundIds.at(it), 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + if (sound) + state.mSounds.push_back(sound); } mMagicBolts.push_back(state); @@ -571,8 +573,10 @@ namespace MWWorld for (size_t soundIter = 0; soundIter != state.mSoundIds.size(); soundIter++) { - state.mSounds.push_back(sndMgr->playSound3D(esm.mPosition, state.mSoundIds.at(soundIter), 1.0f, 1.0f, - MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop)); + MWBase::SoundPtr sound = sndMgr->playSound3D(esm.mPosition, state.mSoundIds.at(soundIter), 1.0f, 1.0f, + MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); + if (sound) + state.mSounds.push_back(sound); } mMagicBolts.push_back(state); diff --git a/docs/source/openmw-mods/differences.rst b/docs/source/openmw-mods/differences.rst index 61f9b2a75..e7cac15d0 100644 --- a/docs/source/openmw-mods/differences.rst +++ b/docs/source/openmw-mods/differences.rst @@ -19,9 +19,9 @@ The largest difference between OpenMW and Morrowind in terms of data structure i To install mods via this new feature: -#. Open ``openmw.cfg`` with your preffered text editor. It is located as described in https://wiki.openmw.org/index.php?title=Paths and *not* in your OpenMW root directory. +#. Open ``openmw.cfg`` with your preffered text editor. It is located as described in :doc:`paths` and *not* in your OpenMW root directory. #. Find or search for ``data=``. This is located very near the bottom of the file. -#. Add a new line below this line and make a new entry of the format ``data=path/to/your/mod`` +#. Add a new line below this line and make a new entry of the format ``data="path/to/your/mod"`` #. Make as many of these entries as you need for each mod folder you want to include. #. Save ``openmw.cfg`` diff --git a/docs/source/openmw-mods/font.rst b/docs/source/openmw-mods/font.rst new file mode 100644 index 000000000..5f01b12d9 --- /dev/null +++ b/docs/source/openmw-mods/font.rst @@ -0,0 +1,77 @@ +Fonts +##### + +Morrowind .fnt fonts +-------------------- + +Morrowind uses a custom ``.fnt`` file format. It is not compatible with the Windows Font File ``.fnt`` format, nor compatible with ``.fnt`` formats from any other Bethesda games. To our knowledge, the format is undocumented and no tools for viewing or editing these fonts exist. + +OpenMW can load this format and convert it on the fly into something usable (see font loader `source code `_). In OpenMW 0.32, an --export-fonts command line option was added to write the converted font (a PNG image and an XML file describing the position of each glyph in the image) to the current directory. + +TrueType fonts +-------------- + +Unlike vanilla Morrowind, OpenMW directly supports TrueType (``.ttf``) fonts. This is the recommended way to create new fonts. + +- To replace the primary "Magic Cards" font: + + #. Download `Pelagiad `_ by Isak Larborn (aka Isaskar). + #. Install the ``openmw_font.xml`` file into ``resources/mygui/openmw_font.xml`` in your OpenMW installation. + #. Copy ``Pelagiad.ttf`` into ``resources/mygui/`` as well. + #. If desired, you can now delete the original ``Magic_Cards.*`` files from your Data Files/Fonts directory. +- You can also replace the Daedric font: + + #. Download `Ayembedt `_ by Georg Duffner. + #. Install ``OMWAyembedt.otf`` into ``/resources/mygui/`` folder in your OpenMW installation. + #. Add the following lines to openmw_font.xml:: + + + + + + + + + + + + + + + + #. This font is missing a few glyphs (mostly punctuation), but is complete in the primary glyphs. If desired, you can now delete the original ``daedric.*`` files from your Data Files/Fonts directory. + +- Another replacement for the Daedric font is `Oblivion `_ by Dongle. + + #. Install the ``Oblivion.ttf`` file resources/mygui/. + #. The openmw_fonts.xml entry is:: + + + + + + + + + + + + + + + + + + + + + + + + + + +Bitmap fonts +------------ + +Morrowind ``.fnt`` files are essentially a bitmap font, but using them is discouraged because of no Unicode support. MyGUI has its own format for bitmap fonts. An example can be seen by using the --export-fonts command line option (see above), which converts Morrowind ``.fnt`` to a MyGUI bitmap font. This is the recommended format to use if you wish to edit Morrowind's bitmap font or create a new bitmap font. \ No newline at end of file diff --git a/docs/source/openmw-mods/index.rst b/docs/source/openmw-mods/index.rst index 34d04abb0..0219c037e 100644 --- a/docs/source/openmw-mods/index.rst +++ b/docs/source/openmw-mods/index.rst @@ -14,4 +14,7 @@ The following document is the complete reference guide to modifying, or modding, foreword differences mod-install + settings/index + fonts convert_bump_mapped_mods + paths \ No newline at end of file diff --git a/docs/source/openmw-mods/mod-install.rst b/docs/source/openmw-mods/mod-install.rst index 317769990..a72678173 100644 --- a/docs/source/openmw-mods/mod-install.rst +++ b/docs/source/openmw-mods/mod-install.rst @@ -8,13 +8,20 @@ Install #. Your mod probably comes in some kind of archive, such as ``.zip``, ``.rar``, ``.7z``, or something along those lines. Unpack this archive into its own folder. #. Ensure the structure of this folder is correct. + #. Locate the plugin files, ``.esp`` or ``.omwaddon``. The folder containing the plugin files we will call your *data folder* #. Check that all resource folders (``Meshes``, ``Textures``, etc.) containing additional resource files (the actual meshes, textures, etc.) are in the *data folder*. -.. note:: - There may be multiple levels of folders, but the location of the plugins must be the same as the resource folders. -#. Open your ``openmw.cfg`` file in your preferred plain text editor. It is located as described in https://wiki.openmw.org/index.php?title=Paths and *not* in your OpenMW root directory. + + .. note:: + There may be multiple levels of folders, but the location of the plugins must be the same as the resource folders. + +#. Open your ``openmw.cfg`` file in your preferred plain text editor. It is located as described in :doc:`paths` and *not* in your OpenMW root directory. #. Find or search for ``data=``. This is located very near the bottom of the file. If you are using Morrowind, this first entry should already point to your Morrowind data directory, ``Data Files``; otherwise it will point to your game file, ``.omwgame``. #. Create a new line underneath and type: ``data="path/to/your/data folder"`` Remember, the *data folder* is where your mod's plugin files are. The double quotes around this path name are *required*. + +.. note:: + Some text editors, such as TextEdit on Mac, will autocorrect your double quotes to typographical "curly" quotes instead of leaving them as the propper neutral vertical quotes ``""``. + #. Save your ``openmw.cfg`` file. You have now installed your mod. Any simple replacer mods that only contain resource files such as meshes or textures will now automatically be loaded in the order of their ``data=*`` entry. This is important to note because replacer mods that replace the same resource will overwrite previous ones as you go down the list. @@ -22,6 +29,15 @@ You have now installed your mod. Any simple replacer mods that only contain reso Enable ------ -Any mods that have plugin files must be enabled to work. +Any mods that have plugin files must be enabled to work. Master game files and plugin files can only be enabled if they have been properly installed within a *data folder* as described above. + +#. Open the OpenMW Launcher. +#. Click on the Data Files tab. +#. In the Content List box, select the content list you wish to modify in the dropdown menu, or make a new one by: -#. \ No newline at end of file + #. Click the New Content List button and enter the name of your content list, then click OK. New lists are useful for keeping track of the mods used for different characters or for different games if you play more than one game using OpenMW. + #. In the Content box, select your game file (``.esm`` or ``.omwgame``) from the dropdown menu. + +#. Now you must activate the plugins you wish to use by checking the box next to their entry in the Content box list. +#. Load order can be changed simply by dragging the entries around within the list. Mods are loaded from the top down, so if one plugin depends on another, it must be lower on the list. +#. Click Play to run OpenMW with your game and enabled mods! diff --git a/docs/source/openmw-mods/paths.rst b/docs/source/openmw-mods/paths.rst new file mode 100644 index 000000000..23e33190d --- /dev/null +++ b/docs/source/openmw-mods/paths.rst @@ -0,0 +1,28 @@ +Paths +##### + +The following describes the locations for the various OpenMW file paths for different types of files on different operating systems. + +.. note:: + Actual location depends on your computer's setup. Username, harddrive, and language may vary. + +Configuration files and log files +--------------------------------- + +:Linux: ``$HOME/.config/openmw`` +:Mac: ``$HOME/Library/Preferences/openmw`` +:Windows: ``C:\Users\Username\Documents\my games\openmw`` + +Savegames +--------- + +:Linux: ``$HOME/.local/share/openmw/saves`` +:Mac: ``$HOME/Library/Application Support/openmw/saves`` +:Windows: ``C:\Users\Username\Documents\my games\openmw\saves`` + +Screenshots +----------- + +:Linux: ``$HOME/.local/share/openmw`` +:Mac: ``$HOME/Library/Application Support/openmw`` +:Windows: ``C:\Users\Username\Documents\my games\openmw`` diff --git a/docs/source/openmw-mods/settings/GUI.rst b/docs/source/openmw-mods/settings/GUI.rst new file mode 100644 index 000000000..945d660c7 --- /dev/null +++ b/docs/source/openmw-mods/settings/GUI.rst @@ -0,0 +1,104 @@ +GUI Settings +############ + +scaling factor +-------------- + +:Type: floating point +:Range: > 0.0 +:Default: 1.0 + +This floating point setting scales the GUI interface windows. The value must be greater than 0.0. A value of 1.0 results in the normal scale. Values much larger than 2.0 may result in user interface components being inaccessible. Until a gamepad interface is created, increasing this setting is helpful for simulating the larger interface used in console games. + +The default value is 1.0. This setting can only be configured by editing the settings configuration file. + +menu transparency +----------------- + +:Type: floating point +:Range: 0.0 (transparent) to 1.0 (opaque) +:Default: 0.84 + +This floating point setting controls the transparency of the GUI windows. The value should be between 0.0 (transparent) and 1.0 (opaque). +The default value is 0.84. This setting can be adjusted in game with the Menu Transparency slider in the Prefs panel of the Options menu. + +tooltip delay +------------- + +:Type: floating point +:Range: > 0.0 +:Default: 0.0 + +This floating point value determines the number of seconds between when you begin hovering over an item and when its tooltip appears. This setting only affects the tooltip delay for objects under the crosshair in GUI mode windows. There does not appear to be a setting to control the tool tip delay in outside of GUI mode. + +The tooltip displays context sensitive information on the selected GUI element, such as weight, value, damage, armor rating, magical effects, and detailed description. + +The default value is 0.0. This setting can be adjusted between 0.0 and 1.0 in game with the Menu Help Delay slider in the Prefs panel of the Options menu. + +stretch menu background +----------------------- + +:Type: boolean +:Range: True/False +:Default: False + +Stretch or shrink the main menu screen, loading splash screens, introductory movie, and cut scenes to fill the specified video resolution, distorting their aspect ratio. The Bethesda provided assets have a 4:3 aspect ratio, but other assets are permitted to have other aspect ratios. If this setting is false, the assets will be centered in their correct aspect ratio, with black bars filling the remainder of the screen. + +The default value is false. This setting can only be configured by editing the settings configuration file. + +subtitles +--------- + +:Type: boolean +:Range: True/False +:Default: False + +Enable or disable subtitles for NPC spoken dialog (and some sound effects). Subtitles will appear in a tool tip box in the lower center of the screen. + +The default value is false. This setting can be toggled in game with the Subtitles button in the Prefs panel of Options menu. + +hit fader +--------- + +:Type: boolean +:Range: True/False +:Default: True + +This boolean setting enables or disables the "red flash" overlay that provides a visual clue when the character has taken damage. + +If this setting is disabled, the player will "bleed" like NPCs do. + +The default value is true. This setting can only be configured by editing the settings configuration file. + +werewolf overlay +---------------- + +:Type: boolean +:Range: True/False +:Default: True + +Enable or disable the werewolf overlay. + +The default value is true. This setting can only be configured by editing the settings configuration file. + +color background owned +---------------------- + +:Type: RGBA floating point +:Range: 0.0 to 1.0 +:Default: 0.15 0.0 0.0 1.0 + +The following two settings determine the background color of the tool tip and the crosshair when hovering over an item owned by an NPC. The color definitions are composed of four floating point values between 0.0 and 1.0 inclusive, representing the red, green, blue and alpha channels. The alpha value is currently ignored. The crosshair color will have no effect if the crosshair setting in the HUD section is disabled. + +The default value is "0.15 0.0 0.0 1.0", which is a dark red color. This setting can only be configured by editing the settings configuration file. This setting has no effect if the show owned setting in the Game Settings Section is false. + +color crosshair owned +--------------------- + +:Type: RGBA floating point +:Range: 0.0 to 1.0 +:Default: 1.0 0.15 0.15 1.0 + +This setting sets the color of the crosshair when hovering over an item owned by an NPC. The value is composed of four floating point values representing the red, green, blue and alpha channels. The alpha value is currently ignored. + +The default value is "1.0 0.15 0.15 1.0" which is a bright red color. This setting can only be configured by editing the settings configuration file. This setting has no effect if the crosshair setting in the HUD Settings Section is false. This setting has no effect if the show owned setting in the Game Settings Section is false. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/HUD.rst b/docs/source/openmw-mods/settings/HUD.rst new file mode 100644 index 000000000..9a15e3aba --- /dev/null +++ b/docs/source/openmw-mods/settings/HUD.rst @@ -0,0 +1,13 @@ +HUD Settings +############ + +crosshair +--------- + +:Type: boolean +:Range: True/False +:Default: True + +This boolean setting determines whether the crosshair or reticle is displayed. Some players perceive that disabling the crosshair provides a more immersive experience. Another common use is to disable the crosshair for screen shots. Enabling the crosshair provides more immediate feedback about which object that is currently the focus of actions. + +The default value is true. This setting can be toggled with the Crosshair button in the Prefs panel of the Options menu. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/camera.rst b/docs/source/openmw-mods/settings/camera.rst new file mode 100644 index 000000000..796e117cb --- /dev/null +++ b/docs/source/openmw-mods/settings/camera.rst @@ -0,0 +1,75 @@ +Camera Settings +############### + +near clip +--------- + +:Type: floating point +:Range: > 0 +:Default: 1.0 + +This floating point setting controls the distance to the near clipping plane. The value must be greater than zero. Values greater than approximately 18.0 will occasionally clip objects in the world in front of the character. Values greater than approximately 8.0 will clip the character's hands in first person view and/or the back of their head in third person view. + +The default value is 1.0. This setting can only be configured by editing the settings configuration file. The value must be greater than 0.0, but it's unclear if the engine enforces this limitation. + +small feature culling +--------------------- + +:Type: boolean +:Range: True/False +:Default: True + +This boolean setting determines whether objects that render to a few pixels or smaller will be culled (not drawn). It generally improves performance to enable this feature, and by definition the culled objects will be very small on screen. It appears that the default definition of "small" in OpenSceneGraph is 2x2 pixels. + +The default value is true. This setting can only be configured by editing the settings configuration file. + +viewing distance +---------------- + +:Type: floating point +:Range: > 0 +:Default: 6666.0 + +This floating point values controls the maximum visible distance (also called the far clipping plane). Larger values significantly improve rendering in exterior spaces, but also increase the amount of rendered geometry and significantly reduce the frame rate. This value interacts with the exterior cell load distance setting in that it's probably undesired for this value to provide visibility into cells that have not yet been loaded. When cells are visible before loading, the geometry will "pop-in" suddenly, creating a jarring visual effect. To prevent this effect, this value must be less than:: + + (8192 * exterior cell load distance - 1024) * 0.93 + +The constant 8192 is the size of a cell, and 1024 is the threshold distance for loading a new cell. Additionally, the field of view setting also interacts with this setting because the view frustrum end is a plane, so you can see further at the edges of the screen than you should be able to. This can be observed in game by looking at distant objects and rotating the camera so the objects are near the edge of the screen. As a result, this setting should further be reduced by a factor that depends on the field of view setting. In the default configuration this reduction is 7%, hence the factor of 0.93 above. Using this factor, approximate values recommended for other exterior cell load distance settings are: + +======= ======== + Cells Viewing + Distance +======= ======== +2 14285 +3 21903 +4 29522 +5 35924 +======= ======== + +Reductions of up to 25% or more can be required to completely eliminate pop-in for wide fields of view and long viewing distances near the edges of the screen, but such situations are unusual and probably not worth the performance penalty introduced by loading geometry obscured by fog in the center of the screen. See RenderingManager::configureFog for the relevant source code. + +Enabling the distant land setting is an alternative to increasing exterior cell load distance. Note that the distant land setting does not include rendering of distant static objects, so the resulting visual effect is not the same. + +The default value is 6666.0. This setting can be adjusted in game from the ridiculously low value of 2000.0 to a maximum of 6666.0, using the View Distance slider in the Detail tab of the Video panel of the Options menu. + +field of view +------------- + +:Type: floating point +:Range: 0-360 +:Default: 55.0 + +Sets the camera field of view in degrees. Recommended values range from 30 degrees to 110 degrees. Small values provide a very narrow field of view that creates a "zoomed in" effect, while large values cause distortion at the edges of the screen. The "field of view" setting interacts with aspect ratio of your video resolution in that more square aspect ratios (e.g. 4:3) need a wider field of view to more resemble the same field of view on a widescreen (e.g. 16:9) monitor. + +The default value is 55.0. This setting can be changed in game using the Field of View slider from the Video tab of the Video panel of the Options menu. + +first person field of view +-------------------------- + +:Type: floating point +:Range: 0-360 +:Default: 55.0 + +The floating point setting controls the field of view for first person meshes such as the player's hands and held objects. It is not recommended to change this value from its default value because the Bethesda provided Morrowind assets do not adapt well to large values, while small values can result in the hands not being visible. + +The default value is 55.0. This setting can only be configured by editing the settings configuration file. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/cells.rst b/docs/source/openmw-mods/settings/cells.rst new file mode 100644 index 000000000..3a5947ff1 --- /dev/null +++ b/docs/source/openmw-mods/settings/cells.rst @@ -0,0 +1,17 @@ +Cells Settings +############## + +exterior cell load distance +--------------------------- + +:Type: integer +:Range: >= 1 +:Default: 1 + +This integer setting determines the number of exterior cells adjacent to the character that will be loaded for rendering. Values greater than one may significantly affect loading times when exiting interior spaces or loading additional exterior cells. Caution is advised when increasing this setting. + +This setting interacts with viewing distance and field of view settings. + +It is generally very wasteful for this value to load geometry than will almost never be visible due to viewing distance and fog. For low frame rate screen shots of scenic vistas, this setting should be set high, and viewing distances adjusted accordingly. + +The default value is 1. This value must be greater than or equal to 1. This setting can only be configured by editing the settings configuration file. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/game.rst b/docs/source/openmw-mods/settings/game.rst new file mode 100644 index 000000000..40fd2e292 --- /dev/null +++ b/docs/source/openmw-mods/settings/game.rst @@ -0,0 +1,46 @@ +Game Settings +############# + +show owned +---------- + +:Type: integer +:Range: 0, 1, 2, 3 +:Default: 0 + +Enable visual clues for items owned by NPCs when the crosshair is on the object. If the setting is 0, no clues are provided which is the default Morrowind behavior. If the setting is 1, the background of the tool tip for the object is highlight in the color specified by the color background owned setting in the GUI Settings Section. If the setting is 2, the crosshair is the color of the color crosshair owned setting in the GUI Settings section. If the setting is 3, both the tool tip background and the crosshair are colored. The crosshair is not visible if crosshair is false. + +The default value is 0 (no clues). This setting can only be configured by editing the settings configuration file. + +best attack +----------- + +:Type: boolean +:Range: True/False +:Default: False + +If this boolean setting is true, the player character will always use the most powerful attack when striking with a weapon (chop, slash or thrust). If this setting is false, the type of attack is determined by the direction that the character is moving at the time the attack begins. + +The default value is false. This setting can be toggled with the Always Use Best Attack button in the Prefs panel of the Options menu. + +difficulty +---------- + +:Type: integer +:Range: -500 to 500 +:Default: 0 + +This integer setting adjusts the difficulty of the game and is intended to be in the range -100 to 100 inclusive. Given the default game setting for fDifficultyMult of 5.0, a value of -100 results in the player taking 80% of the usual damage, doing 6 times the normal damage. A value of 100 results in the player taking 6 times as much damage, but inflicting only 80% of the usual damage. Values less than -500 will result in the player receiving no damage, and values greater than 500 will result in the player inflicting no damage. + +The default value is 0. This setting can be controlled in game with the Difficulty slider in the Prefs panel of the Options menu. + +show effect duration +-------------------- + +:Type: boolean +:Range: True/False +:Default: False + +Show the remaining duration of magic effects and lights if this boolean setting is true. The remaining duration is displayed in the tooltip by hovering over the magical effect. + +The default value is false. This setting can only be configured by editing the settings configuration file. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/general.rst b/docs/source/openmw-mods/settings/general.rst new file mode 100644 index 000000000..e71e82977 --- /dev/null +++ b/docs/source/openmw-mods/settings/general.rst @@ -0,0 +1,35 @@ +General Settings +################ + +anisotropy +---------- + +:Type: integer +:Range: 0 to 16 +:Default: 4 + +Set the maximum anisotropic filtering on textures. Anisotropic filtering is a method of enhancing the image quality of textures on surfaces that are at oblique viewing angles with respect to the camera. Valid values range from 0 to 16. Modern video cards can often perform 8 or 16 anisotropic filtering with a minimal performance impact. This effect of this setting can be seen in the Video panel of the Options menu by finding a location with straight lines (striped rugs and Balmora cobblestones work well) radiating into the distance, and adjusting the anisotropy slider. + +The default value is 4. This setting can be changed in game using the Anisotropy slider in the Detail tab of the Video panel of the Options menu. + +screenshot format +----------------- + +:Type: string +:Range: jpg, png, tga +:Default: png + +Specify the format for screen shots taken by pressing the screen shot key (bound to F12 by default). This setting should be the file extension commonly associated with the desired format. The formats supported will be determined at compilation, but "jpg", "png", and "tga" should be allowed. + +The default value is "png". This setting can only be configured by editing the settings configuration file. + +texture filtering +----------------- + +:Type: string +:Range: bilinear, trilinear +:Default: trilinear + +Set the isotropic texture filtering mode to bilinear or trilinear. Bilinear filtering is a texture filtering method used to smooth textures when displayed larger or smaller than they actually are. Bilinear filtering is reasonably accurate until the scaling of the texture gets below half or above double the original size of the texture. Trilinear filtering is an extension of the bilinear texture filtering method, which also performs linear interpolation between mipmaps. Both methods use mipmaps in OpenMW, and the corresponding OpenGL modes are LINEAR_MIPMAP_NEAREST and LINEAR_MIPMAP_LINEAR. Trilinear filtering produces better texturing at a minimal cost on modern video cards. + +The default value is trilinear. This setting can be changed in game using the Texture filtering pull down in the Detail tab of the Video panel of the Options menu. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/index.rst b/docs/source/openmw-mods/settings/index.rst new file mode 100644 index 000000000..fa79c5efc --- /dev/null +++ b/docs/source/openmw-mods/settings/index.rst @@ -0,0 +1,28 @@ +############################### +Advanced Settings Configuration +############################### + +This part of the guide will cover how to make modifications to the more arcane settings in OpenMW, most of which are not available from in-game menus, to optimize or customize your OpenMW experience. If you are familiar with ``.ini`` tweaks in Morrowind or the other games, this will be quite similar. All settings described in this section are changed in ``settings.cfg``, located in your OpenMW user directory. See :doc:`paths` for this location. + +Although this guide attempts to be comprehensive and up to date. You will always be able to find the full list of settings available and their default values in ``settings-default.cfg`` in your main OpenMW installation directory. The ranges I have included with each setting are the physically possible ranges, not recommendations. + +.. warning:: + As the title suggests, these are advanced settings. If digging around plain text files and manually editing settings sounds scary to you, you may want to stear clear of altering these files. That being said, this guide should be plenty clear enough that you can find the setting you want to change and safely edit it. + +.. toctree:: + :caption: Table of Contents + :maxdepth: 2 + + camera + cells + map + GUI + HUD + game + general + input + saves + sound + video + water + windows \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/input.rst b/docs/source/openmw-mods/settings/input.rst new file mode 100644 index 000000000..8c7b2a42b --- /dev/null +++ b/docs/source/openmw-mods/settings/input.rst @@ -0,0 +1,83 @@ +Input Settings +############## + +grab cursor +----------- + +:Type: boolean +:Range: True/False +:Default: True + +OpenMW will capture control of the cursor if this boolean setting is true. + +In "look mode", OpenMW will center the cursor regardless of the value of this setting (since the cursor/crosshair is always centered in the OpenMW window). However, in GUI mode, this setting determines the behavior when the cursor is moved outside the OpenMW window. If true, the cursor movement stops at the edge of the window preventing access to other applications. If false, the cursor is allowed to move freely on the desktop. + +This setting does not apply to the screen where escape has been pressed, where the cursor is never captured. Regardless of this setting "Alt-Tab" or some other operating system dependent key sequence can be used to allow the operating system to regain control of the mouse cursor. This setting interacts with the minimize on focus loss setting by affecting what counts as a focus loss. Specifically on a two-screen configuration it may be more convenient to access the second screen with setting disabled. + +Note for developers: it's desirable to have this setting disabled when running the game in a debugger, to prevent the mouse cursor from becoming unusable when the game pauses on a breakpoint. + +The default value is true. This setting can only be configured by editing the settings configuration file. + +toggle sneak +------------ + +:Type: boolean +:Range: True/False +:Default: False + +This boolean setting causes the behavior of the sneak key (bound to Ctrl by default) to toggle sneaking on and off rather than requiring the key to be held down while sneaking. Players that spend significant time sneaking may find the character easier to control with this option enabled. + +The default value is false. This setting can only be configured by editing the settings configuration file. + +always run +---------- + +:Type: boolean +:Range: True/False +:Default: False + +If this boolean setting is true, the character is running by default, otherwise the character is walking by default. The shift key will temporarily invert this setting, and the caps lock key will invert this setting while it's "locked". This setting is updated every time you exit the game, based on whether the caps lock key was on or off at the time you exited. + +The default value is false. This settings can be toggled in game by pressing the CapsLock key and exiting. + +allow third person zoom +----------------------- + +:Type: boolean +:Range: True/False +:Default: False + +Allow zooming in and out using the middle mouse wheel in third person view. This feature may not work correctly if the mouse wheel is bound to other actions, and may be triggered accidentally in some cases, so is disabled by default. This setting can only be configured by editing the settings configuration file. + +camera sensitivity +------------------ + +:Type: floating point +:Range: > 0 +:Default: 1.0 + +This floating point setting controls the overall camera/mouse sensitivity when not in GUI mode. The default sensitivity is 1.0, with smaller values requiring more mouse movement, and larger values requiring less. This setting is multiplicative in magnitude. This setting does not affect mouse speed in GUI mode, which is instead controlled by your operating system mouse speed setting. + +The default value is 1.0. This setting can be changed with the Camera Sensitivity slider in the Controls panel of the Options menu. + +camera y multiplier +------------------- + +:Type: floating point +:Range: > 0 +:Default: 1.0 + +This floating point setting controls the vertical camera/mouse sensitivity relative to the horizontal sensitivity (see camera sensitivity above). It is multiplicative with the previous setting, meaning that it should remain set at 1.0 unless the player desires to have different sensitivities in the two axes. + +The default value is 1.0. This setting can only be configured by editing the settings configuration file. + +invert y axis +------------- + +:Type: boolean +:Range: True/False +:Default: False + +Invert the vertical axis while not in GUI mode. If this setting is true, moving the mouse away from the player will look down, while moving it towards the player will look up. This setting does not affect cursor movement in GUI mode. + +The default value is false. This setting can be toggled in game with the Invert Y Axis button in the Controls panel of the Options menu. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/map.rst b/docs/source/openmw-mods/settings/map.rst new file mode 100644 index 000000000..e03bfd615 --- /dev/null +++ b/docs/source/openmw-mods/settings/map.rst @@ -0,0 +1,53 @@ +Map Settings +############ + +global map size +--------------- + +:Type: integer +:Range: >= 1 +:Default: 18 + +This integer setting adjusts the scale of the world map in the GUI mode map window. The value is the width in pixels of each cell in the map, so larger values result in larger more detailed world maps, while smaller values result in smaller less detailed world maps. However, the native resolution of the map source material appears to be 9 pixels per unexplored cell and approximately 18 pixels per explored cell, so values larger than 36 don't produce much additional detail. Similarly, the size of place markers is currently fixed at 12 pixels, so values smaller than this result in overlapping place markers. Values from 12 to 36 are recommended. For reference, Vvardenfell is approximately 41x36 cells. + +Warning: Changing this setting affects saved games. The currently explored area is stored as an image in the save file that's overlayed on the default world map in game. When you increase the resolution of the map, the overlay of earlier saved games will be scaled up on load, and appear blurry. When you visit the cell again, the overlay for that cell is regenerated at the new resolution, so the blurry areas can be corrected by revisiting all the cells you've already visited. + +The default value for this setting is 18. This setting can not be configured except by editing the settings configuration file. + +local map hud widget size +------------------------- + +:Type: integer +:Range: >= 1 +:Default: 256 + +This integer setting controls the zoom level for the HUD map widget (the map in the lower right corner of the window). A value of 64 results in the HUD map widget displaying one entire exterior cell. Since the GUI mode map displays 3x3 cells, a value of approximately 21 displays the same area as the GUI mode map. Larger values increase the level of zoom, while smaller values are wasteful since there's no map data to display beyond the 3x3 cell grid. + +Note that the actual size of the widget is always the same on the screen unless the scaling factor setting in the "GUI" section is changed. Increasing both the scaling factor of the GUI and this setting does result in a higher resolution HUD map, but unfortunately with a scaled direction pointer on top of it. + +The default value for this setting is 256. This setting can not be configured except by editing the settings configuration file. + +local map resolution +-------------------- + +:Type: integer +:Range: >= 1 +:Default: 256 + +This integer setting controls the resolution of the GUI mode local map window. Larger values generally increase the visible detail in map. If this setting is half the local map widget size or smaller, the map will generally be be fairly blurry. Setting both options to the same value results in a map with good detail. Values that exceed the local map widget size setting by more than a factor of two are unlikely to provide much of an improvement in detail since they're subsequently scaled back to the approximately the map widget size before display. The video resolution settings interacts with this setting in that regard. + +.. warning:: + Increasing this setting can increase cell load times, because the map is rendered on demand each time you enter a new cell. Large values may exceed video card limits or exhaust VRAM. + +The default value for this setting is 256. This setting can not be configured except by editing the settings configuration file. + +local map widget size +--------------------- + +:Type: integer +:Range: >= 1 +:Default: 512 + +This integer setting controls the canvas size of the GUI mode local map window. Larger values result in a larger physical map size on screen, and typically require more panning to see all available portions of the map. This larger size also enables an overall greater level of detail if the local map resolution setting is also increased. + +The default value for this setting is 512. This setting can not be configured except by editing the settings configuration file. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/saves.rst b/docs/source/openmw-mods/settings/saves.rst new file mode 100644 index 000000000..39354a4c7 --- /dev/null +++ b/docs/source/openmw-mods/settings/saves.rst @@ -0,0 +1,35 @@ +Saves Settings +############## + +character +--------- + +:Type: string +:Range: +:Default: "" + +This string setting contains the default character name for loading saved games. + +The default value is the empty string, which results in no character being selected by default. This setting is automatically updated from the Load menu when a different character is selected. + +autosave +-------- + +:Type: boolean +:Range: True/False +:Default: True + +This boolean setting determines whether the game will be automatically saved when the character rests. + +The default value is true. This setting can be toggled in game with the Auto-Save when Rest button in the Prefs panel of the Options menu. + +timeplayed +---------- + +:Type: boolean +:Range: True/False +:Default: False + +This boolean setting determines whether the amount of the time the player has spent playing will be displayed for each saved game in the Load menu. + +The default value is false. This setting can only be configured by editing the settings configuration file. This setting was added in OpenMW 0.37. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/sound.rst b/docs/source/openmw-mods/settings/sound.rst new file mode 100644 index 000000000..6537ee950 --- /dev/null +++ b/docs/source/openmw-mods/settings/sound.rst @@ -0,0 +1,113 @@ +Sound Settings +############## + +device +------ + +:Type: string +:Range: +:Default: "" + +This string setting determines which audio device to use. A blank or missing setting means to use the default device, which should usually be sufficient, but if you need to explicitly specify a device use this setting. + +The names of detected devices can be found in the openmw.log file in your configuration directory. + +The default value is the empty string. This setting can only be configured by editing the settings configuration file. + +master volume +------------- + +:Type: floating point +:Range: 0.0 to 1.0 +:Default: 1.0 + +This floating point setting controls the overall volume. The master volume is multiplied with all other volume settings to determine the final volume. + +The default value is 1.0. Valid values range from 0.0 (silent) to 1.0 (maximum volume). This setting can be changed in game using the Master slider from the Audio panel of the Options menu. + +footsteps volume +---------------- + +:Type: floating point +:Range: 0.0 to 1.0 +:Default: 0.2 + +This floating point setting controls the volume of footsteps from the character and other actors. + +The default value is 0.2. Valid values range from 0.0 (silent) to 1.0 (maximum volume). This setting can be changed in game using the Footsteps slider from the Audio panel of the Options menu. + +music volume +------------ + +:Type: floating point +:Range: 0.0 to 1.0 +:Default: 0.5 + +This floating point setting controls the volume for music tracks. + +The default value is 0.5. Valid values range from 0.0 (silent) to 1.0 (maximum volume). This setting can be changed in game using the Music slider from the Audio panel of the Options menu. + +sfx volume +---------- + +:Type: floating point +:Range: 0.0 to 1.0 +:Default: 1.0 + +This floating point setting controls the volume for special sound effects such as combat noises. + +The default value is 1.0. Valid values range from 0.0 (silent) to 1.0 (maximum volume). This setting can be changed in game using the Effects slider from the Audio panel of the Options menu. + +voice volume +------------ + +:Type: floating point +:Range: 0.0 to 1.0 +:Default: 0.8 + +This floating point setting controls the volume for spoken dialog from NPCs. + +The default value is 0.8. Valid values range from 0.0 (silent) to 1.0 (maximum volume). This setting can be changed in game using the Voice slider from the Audio panel of the Options menu. + +buffer cache min +---------------- + +:Type: integer +:Range: > 0 +:Default: 14 + +This integer setting determines the minimum size of the sound buffer cache in megabytes. When the cache reaches the size specified by the buffer cache max setting, old buffers will be unloaded until it's using no more memory than specified by this setting. This setting must be less than or equal to the buffer cache max setting. + +The default value is 14. This setting can only be configured by editing the settings configuration file. This setting was added in OpenMW version 0.38. + +buffer cache max +---------------- + +:Type: integer +:Range: > 0 +:Default: 16 + +This integer setting determines the maximum size of the sound buffer cache in megabytes. When the cache reaches this size, old buffers will be unloaded until it reaches the size specified by the buffer cache min setting. This setting must be greater than or equal to the buffer cache min setting. + +The default value is 16. This setting can only be configured by editing the settings configuration file. This setting was added in OpenMW version 0.38. + +hrtf enable +----------- + +:Type: integer +:Range: -1, 0, 1 +:Default: -1 + +This integer setting determines whether to enable head-related transfer function (HRTF) audio processing. HRTF audio processing creates the perception of sounds occurring in a three dimensional space when wearing headphones. Enabling HRTF may also require an OpenAL Soft version greater than 1.17.0, and possibly some operating system configuration. A value of 0 disables HRTF processing, while a value of 1 explicitly enables HRTF processing. +The default value is -1, which should enable the feature automatically for most users when possible. This setting can only be configured by editing the settings configuration file. This setting was added in OpenMW version 0.38. + +hrtf +---- + +:Type: string +:Range: +:Default: "" + +This string setting specifies which HRTF profile to use when HRTF is enabled. Blank means use the default. This setting has no effect if HRTF is not enabled based on the hrtf enable setting. Allowed values for this field are enumerated in openmw.log file is an HRTF enabled ausio system is installed. + +The default value is the empty string, which uses the default profile. This setting can only be configured by editing the settings configuration file. This setting was added in OpenMW version 0.38. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/video.rst b/docs/source/openmw-mods/settings/video.rst new file mode 100644 index 000000000..a31af5103 --- /dev/null +++ b/docs/source/openmw-mods/settings/video.rst @@ -0,0 +1,135 @@ +Video Settings +############## + +resolution x +------------ + +:Type: integer +:Range: > 0 +:Default: 800 + +This setting determines the horizontal resolution of the OpenMW game window. Larger values produce more detailed images within the constraints of your graphics hardware but also significantly reduce the frame rate. + +The default value is 800. The window resolution can be selected from a menu of common screen sizes in the Video tab of the Video Panel of the Options menu, or in the Graphics tab of the OpenMW Launcher. The horizontal resolution can also be set to a custom value in the Graphics tab of the OpenMW Launcher. + +resolution y +------------ + +:Type: integer +:Range: > 0 +:Default: 600 + +This setting determines the vertical resolution of the OpenMW game window. Larger values produce more detailed images within the constraints of your graphics hardware but also significantly reduce the frame rate. + +The default value is 600. The window resolution can be selected from a menu of common screen sizes in the Video tab of the Video Panel of the Options menu, or in the Graphics tab of the OpenMW Launcher. The vertical resolution can also be set to a custom value in the Graphics tab of the OpenMW Launcher. + +fullscreen +---------- + +:Type: boolean +:Range: True/False +:Default: False + +This boolean setting determines whether the entire screen is used for the specified resolution. + +The default value is false. This setting can be toggled in game using the Fullscreen button in the Video tab of the Video panel in the Options menu. It can also be toggled with the Full Screen check box in the Graphics tab of the OpenMW Launcher. + +screen +------ + +:Type: integer +:Range: >= 0 +:Default: 0 + +This integer setting determines which screen the game will open on in multi-monitor configurations. This setting is particularly important when the fullscreen setting is true, since this is the only way to control which screen is used, but it can also be used to control which screen a normal window or a borderless window opens on as well. The screens are numbered in increasing order, beginning with 0. + +The default value is 0. This setting can be selected from a pull down menu in the Graphics tab of the OpenMW Launcher, but cannot be changed during game play. + +minimize on focus loss +---------------------- + +:Type: boolean +:Range: True/False +:Default: False + +Minimize the OpenMW window if it loses cursor focus. This setting is primarily useful for single screen configurations, so that the OpenMW screen in full screen mode can be minimized when the operating system regains control of the mouse and keyboard. On multiple screen configurations, disabling this option makes it easier to switch between screens while playing OpenMW. + +Note that a minimized game window consumes less system resources and produces less heat, since the game does not need to render in minimized state. It is therefore advisable to minimize the game during pauses (either via use of this setting, or by minimizing the window manually). + +This setting has no effect if the fullscreen setting is false. + +Developer note: corresponds to SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS. + +The default value is true. This setting can only be configured by editing the settings configuration file. + +window border +------------- + +:Type: boolean +:Range: True/False +:Default: True + +This boolean setting determines whether there's an operating system border drawn around the OpenMW window. If this setting is true, the window can be moved and resized with the operating system window controls. If this setting is false, the window has no operating system border. + +This setting has no effect if the fullscreen setting is true. + +The default value is true. This setting can be toggled in game using the Window Border button in the Video tab of the Video panel in the Options menu. It can also be toggled with the Window Border check box in the OpenMW Launcher. + +antialiasing +------------ + +:Type: integer +:Range: 0, 2, 4, 8, 16 +:Default: 0 + +This integer setting controls anti-aliasing. Anti-aliasing is a technique designed to improve the appearance of polygon edges, so they do not appear to be "jagged". Anti-aliasing can smooth these edges at the cost of a minor reduction in the frame rate. A value of 0 disables anti-aliasing. Other powers of two (e.g. 2, 4, 8, 16) are supported according to the capabilities of your graphics hardware. Higher values do a better job of smoothing out the image but have a greater impact on frame rate. + +This setting can be configured from a list of valid choices in the Graphics panel of the OpenMW Launcher, but cannot be changed during game play - due to a technical limitation that may be addressed in a future version of OpenMW. + +vsync +----- + +:Type: boolean +:Range: True/False +:Default: False + +This boolean setting determines whether frame draws are synchronized with the vertical refresh rate of your monitor. Enabling this setting can reduce screen tearing, a visual defect caused by updating the image buffer in the middle of a screen draw. Enabling this option typically implies limiting the framerate to 60 frames per second, but may also introduce additional delays caused by having to wait until the appropriate time (the vertical blanking interval) to draw a frame. + +The default value is false. This setting can be adjusted in game using the VSync button in the Video tab of the Video panel in the Options menu. It can also be changed by toggling the Vertical Sync check box in the Graphics tab of the OpenMW Launcher. + +framerate limit +--------------- + +:Type: floating point +:Range: >= 0.0 +:Default: 0.0 + +This floating point setting determines the maximum frame rate in frames per second. If this setting is 0.0, the frame rate is unlimited. + +There are several reasons to consider capping your frame rate, especially if you're already experiencing a relatively high frame rate (greater than 60 frames per second). Lower frame rates will consume less power and generate less heat and noise. Frame rates above 60 frames per second rarely produce perceptible improvements in visual quality, but may improve input responsiveness. Capping the frame rate may in some situations reduce the perception of choppiness (highly variable frame rates during game play) by lowering the peak frame rates. + +This setting interacts with the vsync setting in the Video section in the sense that enabling vertical sync limits the frame rate to the refresh rate of your monitor (often 60 frames per second). Choosing to limit the frame rate using this setting instead of vsync may reduce input lag due to the game not having to wait for the vertical blanking interval. + +The default value is 0.0. This setting can only be configured by editing the settings configuration file. This setting was added in OpenMW 0.37. + +contrast +-------- + +:Type: floating point +:Range: > 0.0 +:Default: 1.0 + +This floating point setting controls the contrast correction for all video in the game. + +The default value is 1.0. This setting can only be configured by editing the settings configuration file. This setting does not currently work under Linux. + +gamma +----- + +:Type: floating point +:Range: > 0.0 +:Default: 1.0 + +This floating point setting controls the gamma correction for all video in the game. Gamma is an exponent that makes colors brighter if greater than 1.0 and darker if less than 1.0. + +The default value is 1.0. This setting can be changed in the Detail tab of the Video panel of the Options menu. This setting does not currently work under Linux, and the in-game setting in the Options menu has been disabled. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/water.rst b/docs/source/openmw-mods/settings/water.rst new file mode 100644 index 000000000..b2b9a00c2 --- /dev/null +++ b/docs/source/openmw-mods/settings/water.rst @@ -0,0 +1,43 @@ +Water Settings +############ + +.. note:: + The settings for the water shader are difficult to describe, but can be seen immediately in the Water tab of the Video panel in the Options menu. Changes there will be saved to these settings. It is suggested to stand on the shore of a moderately broad body of water with trees or other objects on the far shore to test reflection textures, underwater plants in shallow water near by to test refraction textures, and some deep water visible from your location to test deep water visibility. + +shader +------ + +:Type: boolean +:Range: True/False +:Default: False + +This boolean setting enables or disables the water shader, which results in much more realistic looking water surfaces, including reflected objects and a more detailed wavy surface. + +The default value is false. This setting can be toggled with the Shader button in the Water tab of the Video panel of the Options menu. + +rtt size +-------- + +:Type: integer +:Range: > 0 +:Default: 512 + +The integer setting determines the size of the texture used for reflection and refraction (if enabled). For reflection, the texture size determines the detail of reflected images on the surface of the water. For refraction, the texture size determines the detail of the objects on the other side of the plane of water (which have a wavy appearance caused by the refraction). RTT is an acronym for Render to Texture which allows rendering of the scene to be saved as a texture. +Higher values produces better visuals and result in a marginally lower frame rate depending on your graphics hardware. + +In the Water tab of the Video panel of the Options menu, the choices are Low (512), Medium (1024) and High (2048). This setting has no effect if the shader setting is false. It is recommended to use values that are a power of two because this results in more efficient use of video hardware. + +This setting has no effect if the shader setting is false. + +refraction +---------- + +:Type: boolean +:Range: True/False +:Default: False + +This boolean setting enables the refraction rendering feature of the water shader. Refraction causes deep water to be more opaque and objects seen through the plane of the water to have a wavy appearance. Enabling this feature results in better visuals, and a marginally lower frame rate depending on your graphics hardware. + +This setting has no effect if the shader setting is false. + +The default setting is false. This setting can be toggled with the Refraction button in the Water tab of the Video panel of the Options menu. \ No newline at end of file diff --git a/docs/source/openmw-mods/settings/windows.rst b/docs/source/openmw-mods/settings/windows.rst new file mode 100644 index 000000000..9472b9a81 --- /dev/null +++ b/docs/source/openmw-mods/settings/windows.rst @@ -0,0 +1,149 @@ +Windows Settings +############ + +:Type: floating point +:Range: 0.0 to 1.0 + +This section controls the location and size of each window in GUI mode. Each setting is a floating point number representing a *fraction* of the resolution x or resolution y setting in the Video Settings Section. The X and Y values locate the top left corner of the window, while the W value determines the width of the window and the H value determines the height of the window. + +Unlike the documentation for most sections which lists the exact setting name, this page instead lists the names of the windows. For example, to configure the alchemy window, the actual settings would be:: + + alchemy x = 0.25 + alchemy y = 0.25 + alchemy h = 0.5 + alchemy w = 0.5 + +Each window in the GUI mode remembers it's previous location when exiting the game. By far the easiest way to configure these settings is to simply move the windows around in game. Hand editing the configuration file might result in some fine tuning for alignment, but the settings will be overwritten if a window is moved. + +.. note:: + To scale the windows, making the widgets proportionally larger, see the scaling factor setting instead. + +stats +----- + +:Default: x = 0.0 + y = 0.0 + h = 0.375 + w = 0.4275 + +The stats window, displaying level, race, class, skills and stats. Activated by clicking on any of the three bars in the lower left corner of the HUD. + +spells +------ + +:Default: x = 0.625 + y = 0.5725 + h = 0.375 + w = 0.4275 + +The spells window, displaying powers, spells, and magical items. Activated by clicking on the spells widget (third from left) in the bottom left corner of the HUD. + +map +--- + +:Default: x = 0.625 + y = 0.0 + h = 0.375 + w = 0.5725 + +The local and world map window. Activated by clicking on the map widget in the bottom right corner of the HUD. + +dialogue +-------- + +:Default: x = 0.095 + y = 0.095 + h = 0.810 + w = 0.810 + +The dialog window, for talking with NPCs. Activated by clicking on a NPC. + +alchemy +------- + +:Default: x = 0.25 + y = 0.25 + h = 0.5 + w = 0.5 + +The alchemy window, for crafting potions. Activated by dragging an alchemy tool on to the rag doll. Unlike most other windows, this window hides all other windows when opened. + +console +------- + +:Default: x = 0.0 + y = 0.0 + h = 1.0 + w = 0.5 + +The console command window. Activated by pressing the tilde (~) key. + +inventory +--------- + +:Default: x = 0.0 + y = 0.4275 + h = 0.6225 + w = 0.5725 + +The inventory window, displaying the paper doll and possessions, when activated by clicking on the inventory widget (second from left) in the bottom left corner of the HUD. + +inventory container +------------------- + +:Default: x = 0.0 + y = 0.4275 + h = 0.6225 + w = 0.5725 + +The player's inventory window while searching a container, showing the contents of the character's inventory. Activated by clicking on a container. The same window is used for searching dead bodies, and pickpocketing people. + +inventory barter +---------------- + +:Default: x = 0.0 + y = 0.4275 + h = 0.6225 + w = 0.5725 + +The player's inventory window while bartering. It displays goods owned by the character while bartering. Activated by clicking on the Barter choice in the dialog window for an NPC. + +inventory companion +------------------- + +:Default: x = 0.0 + y = 0.4275 + h = 0.6225 + w = 0.5725 + +The player's inventory window while interacting with a companion. The companion windows were added in the Tribunal expansion, but are available everywhere in the OpenMW engine. + +container +--------- + +:Default: x = 0.25 + y = 0.0 + h = 0.75 + w = 0.375 + +The container window, showing the contents of the container. Activated by clicking on a container. The same window is used for searching dead bodies, and pickpocketing people. + +barter +------ + +:Default: x = 0.25 + y = 0.0 + h = 0.75 + w = 0.375 + +The NPC bartering window, displaying goods owned by the shopkeeper while bartering. Activated by clicking on the Barter choice in the dialog window for an NPC. + +companion +--------- + +:Default: x = 0.25 + y = 0.0 + h = 0.75 + w = 0.375 + +The NPC's inventory window while interacting with a companion. The companion windows were added in the Tribunal expansion, but are available everywhere in the OpenMW engine. \ No newline at end of file