diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 2eebb8c28..d7b23c096 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -79,8 +79,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) { try { - float frametime = std::min(evt.timeSinceLastFrame, 0.2f); - + float frametime = evt.timeSinceLastFrame; mEnvironment.setFrameDuration (frametime); // update input @@ -478,9 +477,15 @@ void OMW::Engine::go() } // Start the main rendering loop + Ogre::Timer timer; while (!MWBase::Environment::get().getStateManager()->hasQuitRequest()) - Ogre::Root::getSingleton().renderOneFrame(); + { + float dt = timer.getMilliseconds()/1000.f; + dt = std::min(dt, 0.2f); + timer.reset(); + Ogre::Root::getSingleton().renderOneFrame(dt); + } // Save user settings settings.saveUser(settingspath); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 2bfc4f141..444b572b6 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -162,6 +162,9 @@ namespace MWGui void RaceDialog::close() { + mPreviewImage->setImageTexture(""); + const std::string textureName = "CharacterHeadPreview"; + MyGUI::RenderManager::getInstance().destroyTexture(MyGUI::RenderManager::getInstance().getTexture(textureName)); mPreview.reset(NULL); } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 29b166a6a..68682abea 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -190,14 +190,12 @@ namespace MWInput int action = channel->getNumber(); - if (action == A_Use) - { - mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); - } - - if (action == A_Jump) + if (mControlSwitch["playercontrols"]) { - mAttemptJump = (currentValue == 1.0 && previousValue == 0.0); + if (action == A_Use) + mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); + else if (action == A_Jump) + mAttemptJump = (currentValue == 1.0 && previousValue == 0.0); } if (currentValue == 1) @@ -603,7 +601,7 @@ namespace MWInput MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); } - if (mMouseLookEnabled) + if (mMouseLookEnabled && !mControlsDisabled) { resetIdleTime(); @@ -622,7 +620,7 @@ namespace MWInput mPlayer->pitch(y); } - if (arg.zrel && mControlSwitch["playerviewswitch"]) //Check to make sure you are allowed to zoomout and there is a change + if (arg.zrel && mControlSwitch["playerviewswitch"] && mControlSwitch["playercontrols"]) //Check to make sure you are allowed to zoomout and there is a change { MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.zrel); MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true); @@ -680,7 +678,7 @@ namespace MWInput if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; // Not allowed before the magic window is accessible - if (!mControlSwitch["playermagic"]) + if (!mControlSwitch["playermagic"] || !mControlSwitch["playercontrols"]) return; // Not allowed if no spell selected @@ -701,7 +699,7 @@ namespace MWInput if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; // Not allowed before the inventory window is accessible - if (!mControlSwitch["playerfighting"]) + if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"]) return; MWMechanics::DrawState_ state = mPlayer->getDrawState(); @@ -713,6 +711,9 @@ namespace MWInput void InputManager::rest() { + if (!mControlSwitch["playercontrols"]) + return; + if (!MWBase::Environment::get().getWindowManager()->getRestEnabled () || MWBase::Environment::get().getWindowManager()->isGuiMode ()) return; @@ -734,6 +735,9 @@ namespace MWInput void InputManager::toggleInventory() { + if (!mControlSwitch["playercontrols"]) + return; + if (MyGUI::InputManager::getInstance ().isModalAny()) return; @@ -770,6 +774,8 @@ namespace MWInput void InputManager::toggleJournal() { + if (!mControlSwitch["playercontrols"]) + return; if (MyGUI::InputManager::getInstance ().isModalAny()) return; @@ -787,6 +793,8 @@ namespace MWInput void InputManager::quickKey (int index) { + if (!mControlSwitch["playercontrols"]) + return; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if (player.getClass().getNpcStats(player).isWerewolf()) { diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 2e835d57e..a3cfbfd49 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -396,11 +396,7 @@ namespace MWMechanics { CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr); - int strength = creatureStats.getAttribute(ESM::Attribute::Strength).getModified(); int intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getModified(); - int willpower = creatureStats.getAttribute(ESM::Attribute::Willpower).getModified(); - int agility = creatureStats.getAttribute(ESM::Attribute::Agility).getModified(); - int endurance = creatureStats.getAttribute(ESM::Attribute::Endurance).getModified(); float base = 1.f; if (ptr.getCellRef().getRefId() == "player") @@ -415,11 +411,6 @@ namespace MWMechanics float diff = (static_cast(magickaFactor*intelligence)) - magicka.getBase(); magicka.modify(diff); creatureStats.setMagicka(magicka); - - DynamicStat fatigue = creatureStats.getFatigue(); - diff = (strength+willpower+agility+endurance) - fatigue.getBase(); - fatigue.modify(diff); - creatureStats.setFatigue(fatigue); } void Actors::restoreDynamicStats (const MWWorld::Ptr& ptr, bool sleep) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 72a9bbfde..11484ac49 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1645,6 +1645,8 @@ void CharacterController::playGroup(const std::string &groupname, int mode, int } else if(mode == 0) { + if (!mAnimQueue.empty()) + mAnimation->stopLooping(mAnimQueue.front().first); mAnimQueue.resize(1); mAnimQueue.push_back(std::make_pair(groupname, count-1)); } diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index a287a7e11..7bf027732 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -20,7 +20,7 @@ namespace MWMechanics mAttacked (false), mAttackingOrSpell(false), mIsWerewolf(false), - mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), + mFallHeight(0), mRecalcMagicka(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), mLastRestock(0,0), mGoldPool(0), mActorId(-1), @@ -147,10 +147,22 @@ namespace MWMechanics if (value != currentValue) { - if (index != ESM::Attribute::Luck - && index != ESM::Attribute::Personality - && index != ESM::Attribute::Speed) - mRecalcDynamicStats = true; + if (index == ESM::Attribute::Intelligence) + mRecalcMagicka = true; + else if (index == ESM::Attribute::Strength || + index == ESM::Attribute::Willpower || + index == ESM::Attribute::Agility || + index == ESM::Attribute::Endurance) + { + int strength = getAttribute(ESM::Attribute::Strength).getModified(); + int willpower = getAttribute(ESM::Attribute::Willpower).getModified(); + int agility = getAttribute(ESM::Attribute::Agility).getModified(); + int endurance = getAttribute(ESM::Attribute::Endurance).getModified(); + DynamicStat fatigue = getFatigue(); + float diff = (strength+willpower+agility+endurance) - fatigue.getBase(); + fatigue.modify(diff); + setFatigue(fatigue); + } } if(!mIsWerewolf) @@ -200,7 +212,7 @@ namespace MWMechanics { if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier() != mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier()) - mRecalcDynamicStats = true; + mRecalcMagicka = true; mMagicEffects.setModifiers(effects); } @@ -361,9 +373,9 @@ namespace MWMechanics bool CreatureStats::needToRecalcDynamicStats() { - if (mRecalcDynamicStats) + if (mRecalcMagicka) { - mRecalcDynamicStats = false; + mRecalcMagicka = false; return true; } return false; @@ -371,7 +383,7 @@ namespace MWMechanics void CreatureStats::setNeedRecalcDynamicStats(bool val) { - mRecalcDynamicStats = val; + mRecalcMagicka = val; } void CreatureStats::setKnockedDown(bool value) @@ -498,7 +510,7 @@ namespace MWMechanics state.mAttackStrength = mAttackStrength; state.mFallHeight = mFallHeight; // TODO: vertical velocity (move from PhysicActor to CreatureStats?) state.mLastHitObject = mLastHitObject; - state.mRecalcDynamicStats = mRecalcDynamicStats; + state.mRecalcDynamicStats = mRecalcMagicka; state.mDrawState = mDrawState; state.mLevel = mLevel; state.mActorId = mActorId; @@ -546,7 +558,7 @@ namespace MWMechanics mAttackStrength = state.mAttackStrength; mFallHeight = state.mFallHeight; mLastHitObject = state.mLastHitObject; - mRecalcDynamicStats = state.mRecalcDynamicStats; + mRecalcMagicka = state.mRecalcDynamicStats; mDrawState = DrawState_(state.mDrawState); mLevel = state.mLevel; mActorId = state.mActorId; diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 5e169ffb0..f830dd310 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -53,8 +53,7 @@ namespace MWMechanics std::string mLastHitObject; // The last object to hit this actor - // Do we need to recalculate stats derived from attributes or other factors? - bool mRecalcDynamicStats; + bool mRecalcMagicka; // For merchants: the last time items were restocked and gold pool refilled. MWWorld::TimeStamp mLastRestock; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 29db648d0..fc147ce59 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -842,6 +842,17 @@ void Animation::changeGroups(const std::string &groupname, int groups) return; } } + +void Animation::stopLooping(const std::string& groupname) +{ + AnimStateMap::iterator stateiter = mStates.find(groupname); + if(stateiter != mStates.end()) + { + stateiter->second.mLoopCount = 0; + return; + } +} + void Animation::play(const std::string &groupname, int priority, int groups, bool autodisable, float speedmult, const std::string &start, const std::string &stop, float startpoint, size_t loops) { if(!mSkelBase || mAnimSources.empty()) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 8ca3582dc..a8a9ee11e 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -260,6 +260,10 @@ public: float speedmult, const std::string &start, const std::string &stop, float startpoint, size_t loops); + /** If the given animation group is currently playing, set its remaining loop count to '0'. + */ + void stopLooping(const std::string& groupName); + /** Adjust the speed multiplier of an already playing animation. */ void adjustSpeedMult (const std::string& groupname, float speedmult); diff --git a/apps/openmw/mwrender/weaponanimation.cpp b/apps/openmw/mwrender/weaponanimation.cpp index a409e8807..c59a93feb 100644 --- a/apps/openmw/mwrender/weaponanimation.cpp +++ b/apps/openmw/mwrender/weaponanimation.cpp @@ -55,6 +55,7 @@ void WeaponAnimation::attachArrow(MWWorld::Ptr actor) return; std::string model = ammo->getClass().getModel(*ammo); + assert(weapon->mSkelBase && "Need a skeleton to attach the arrow to"); mAmmunition = NifOgre::Loader::createObjects(weapon->mSkelBase, "ArrowBone", weapon->mSkelBase->getParentSceneNode(), model); configureAddedObject(mAmmunition, *ammo, MWWorld::InventoryStore::Slot_Ammunition); } diff --git a/apps/openmw/mwscript/animationextensions.cpp b/apps/openmw/mwscript/animationextensions.cpp index 52de8e042..613cf7d24 100644 --- a/apps/openmw/mwscript/animationextensions.cpp +++ b/apps/openmw/mwscript/animationextensions.cpp @@ -55,7 +55,7 @@ namespace MWScript throw std::runtime_error ("animation mode out of range"); } - MWBase::Environment::get().getMechanicsManager()->playAnimationGroup (ptr, group, mode, 1); + MWBase::Environment::get().getMechanicsManager()->playAnimationGroup (ptr, group, mode, std::numeric_limits::max()); } }; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index c7d221139..e8784f8de 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -964,6 +964,9 @@ namespace MWScript msg << "Grid: " << cell->getCell()->getGridX() << " " << cell->getCell()->getGridY() << std::endl; Ogre::Vector3 pos (ptr.getRefData().getPosition().pos); msg << "Coordinates: " << pos << std::endl; + msg << "Model: " << ptr.getClass().getModel(ptr) << std::endl; + if (!ptr.getClass().getScript(ptr).empty()) + msg << "Script: " << ptr.getClass().getScript(ptr) << std::endl; } std::string notes = runtime.getStringLiteral (runtime[0].mInteger); diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index befb8d82e..d5647db10 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -278,7 +278,9 @@ namespace MWScript MWMechanics::DynamicStat stat (ptr.getClass().getCreatureStats (ptr) .getDynamic (mIndex)); - stat.setCurrent (diff + current, true); + // for fatigue, a negative current value is allowed and means the actor will be knocked down + bool allowDecreaseBelowZero = (mIndex == 2); + stat.setCurrent (diff + current, allowDecreaseBelowZero); ptr.getClass().getCreatureStats (ptr).setDynamic (mIndex, stat); } diff --git a/apps/wizard/componentselectionpage.cpp b/apps/wizard/componentselectionpage.cpp index d372f677d..956f0f237 100644 --- a/apps/wizard/componentselectionpage.cpp +++ b/apps/wizard/componentselectionpage.cpp @@ -62,7 +62,7 @@ void Wizard::ComponentSelectionPage::initializePage() if (field(QLatin1String("installation.new")).toBool() == true) { - morrowindItem->setFlags(morrowindItem->flags() & !Qt::ItemIsEnabled & Qt::ItemIsUserCheckable); + morrowindItem->setFlags(morrowindItem->flags() & ~Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); morrowindItem->setData(Qt::CheckStateRole, Qt::Checked); componentsList->addItem(morrowindItem); @@ -77,7 +77,7 @@ void Wizard::ComponentSelectionPage::initializePage() if (mWizard->mInstallations[path].hasMorrowind) { morrowindItem->setText(tr("Morrowind\t\t(installed)")); - morrowindItem->setFlags(morrowindItem->flags() & !Qt::ItemIsEnabled & Qt::ItemIsUserCheckable); + morrowindItem->setFlags(morrowindItem->flags() & ~Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); morrowindItem->setData(Qt::CheckStateRole, Qt::Unchecked); } else { morrowindItem->setText(tr("Morrowind")); @@ -88,7 +88,7 @@ void Wizard::ComponentSelectionPage::initializePage() if (mWizard->mInstallations[path].hasTribunal) { tribunalItem->setText(tr("Tribunal\t\t(installed)")); - tribunalItem->setFlags(tribunalItem->flags() & !Qt::ItemIsEnabled & Qt::ItemIsUserCheckable); + tribunalItem->setFlags(tribunalItem->flags() & ~Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); tribunalItem->setData(Qt::CheckStateRole, Qt::Unchecked); } else { tribunalItem->setText(tr("Tribunal")); @@ -99,7 +99,7 @@ void Wizard::ComponentSelectionPage::initializePage() if (mWizard->mInstallations[path].hasBloodmoon) { bloodmoonItem->setText(tr("Bloodmoon\t\t(installed)")); - bloodmoonItem->setFlags(bloodmoonItem->flags() & !Qt::ItemIsEnabled & Qt::ItemIsUserCheckable); + bloodmoonItem->setFlags(bloodmoonItem->flags() & ~Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); bloodmoonItem->setData(Qt::CheckStateRole, Qt::Unchecked); } else { bloodmoonItem->setText(tr("Bloodmoon")); diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index b366216de..3abe0c171 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -133,8 +133,6 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) mResourceName = mShape->getName(); mShape->mCollide = false; mBoundingBox = NULL; - mShape->mBoxTranslation = Ogre::Vector3(0,0,0); - mShape->mBoxRotation = Ogre::Quaternion::IDENTITY; mStaticMesh = NULL; mCompoundShape = NULL; diff --git a/components/nifogre/skeleton.cpp b/components/nifogre/skeleton.cpp index 4f6921d89..a3fade5b2 100644 --- a/components/nifogre/skeleton.cpp +++ b/components/nifogre/skeleton.cpp @@ -111,7 +111,7 @@ bool NIFSkeletonLoader::needSkeleton(const Nif::Node *node) /* We need to be a little aggressive here, since some NIFs have a crap-ton * of nodes and Ogre only supports 256 bones. We will skip a skeleton if: * There are no bones used for skinning, there are no keyframe controllers, there - * are no nodes named "AttachLight", and the tree consists of NiNode, + * are no nodes named "AttachLight" or "ArrowBone", and the tree consists of NiNode, * NiTriShape, and RootCollisionNode types only. */ if(node->boneTrafo) @@ -126,7 +126,7 @@ bool NIFSkeletonLoader::needSkeleton(const Nif::Node *node) } while(!(ctrl=ctrl->next).empty()); } - if (node->name == "AttachLight") + if (node->name == "AttachLight" || node->name == "ArrowBone") return true; if(node->recType == Nif::RC_NiNode || node->recType == Nif::RC_RootCollisionNode) diff --git a/extern/shiny/Platforms/Ogre/OgrePlatform.cpp b/extern/shiny/Platforms/Ogre/OgrePlatform.cpp index eab8f93e2..aa01c8ba1 100644 --- a/extern/shiny/Platforms/Ogre/OgrePlatform.cpp +++ b/extern/shiny/Platforms/Ogre/OgrePlatform.cpp @@ -54,6 +54,8 @@ namespace sh OgrePlatform::~OgrePlatform () { + Ogre::MaterialManager::getSingleton().removeListener(this); + delete sSerializer; } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index d7db81595..0b08e28d9 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -514,6 +514,7 @@ namespace Physic assert (mRaycastingObjectMap.find(name) == mRaycastingObjectMap.end()); mRaycastingObjectMap[name] = body; mDynamicsWorld->addRigidBody(body,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_Projectile); + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT); } return body;