Merge remote-tracking branch 'remotes/upstream/master' into QtOgre

Conflicts:
	apps/opencs/CMakeLists.txt
loadfix
cc9cii 10 years ago
commit 313aed078e

@ -60,7 +60,7 @@ endif (ANDROID)
# doxygen main page
configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/docs/mainpage.hpp")
configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_DIR}/docs/mainpage.hpp")
option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE)
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
@ -837,3 +837,26 @@ if (APPLE)
include(CPack)
endif (APPLE)
# Doxygen Target -- simply run 'make doc' or 'make doc_pages'
# output directory for 'make doc' is "${OpenMW_BINARY_DIR}/docs/Doxygen"
# output directory for 'make doc_pages' is "${DOXYGEN_PAGES_OUTPUT_DIR}" if defined
# or "${OpenMW_BINARY_DIR}/docs/Pages" otherwise
find_package(Doxygen)
if (DOXYGEN_FOUND)
# determine output directory for doc_pages
if (NOT DEFINED DOXYGEN_PAGES_OUTPUT_DIR)
set(DOXYGEN_PAGES_OUTPUT_DIR "${OpenMW_BINARY_DIR}/docs/Pages")
endif ()
configure_file(${OpenMW_SOURCE_DIR}/docs/Doxyfile.cmake ${OpenMW_BINARY_DIR}/docs/Doxyfile @ONLY)
configure_file(${OpenMW_SOURCE_DIR}/docs/DoxyfilePages.cmake ${OpenMW_BINARY_DIR}/docs/DoxyfilePages @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/Doxyfile
WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
COMMENT "Generating Doxygen documentation at ${OpenMW_BINARY_DIR}/docs/Doxygen"
VERBATIM)
add_custom_target(doc_pages
${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/DoxyfilePages
WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM)
endif ()

@ -77,12 +77,12 @@ opencs_units (view/widget
opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget terrainstorage
previewwidget
)
opencs_units_noqt (view/render
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
lightingbright object cell textoverlay overlaymask
lightingbright object cell terrainstorage textoverlay overlaymask
)
opencs_hdrs_noqt (view/render

@ -2,7 +2,8 @@
#include "view.hpp"
CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id)
CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id)
: mUniversalId (id), mParent (NULL)
{
/// \todo add a button to the title bar that clones this sub view

@ -335,8 +335,11 @@ namespace MWBase
virtual void fadeScreenOut(const float time) = 0;
/// Fade the screen to a specified percentage of black, over \a time seconds
virtual void fadeScreenTo(const int percent, const float time) = 0;
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor) = 0;
/// Darken the screen to a specified percentage
virtual void setBlindness(const int percent) = 0;
virtual void activateHitOverlay(bool interrupt=true) = 0;
virtual void setWerewolfOverlay(bool set) = 0;
virtual void toggleDebugWindow() = 0;
};

@ -297,4 +297,9 @@ namespace MWClass
state2.mTime = dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime;
}
std::string Light::getSound(const MWWorld::Ptr& ptr) const
{
return ptr.get<ESM::Light>()->mBase->mSound;
}
}

@ -82,6 +82,8 @@ namespace MWClass
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
const;
///< Write additional state from \a ptr into \a state.
virtual std::string getSound(const MWWorld::Ptr& ptr) const;
};
}

@ -24,6 +24,7 @@
#include "../mwmechanics/combat.hpp"
#include "../mwmechanics/autocalcspell.hpp"
#include "../mwmechanics/difficultyscaling.hpp"
#include "../mwmechanics/character.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontalk.hpp"
@ -775,7 +776,11 @@ namespace MWClass
damage = scaleDamage(damage, attacker, ptr);
if(damage > 0.0f)
{
sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.0f);
if (ptr.getRefData().getHandle() == "player")
MWBase::Environment::get().getWindowManager()->activateHitOverlay();
}
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage;
setActorHealth(ptr, health, attacker);
}
@ -1216,60 +1221,43 @@ namespace MWClass
std::string Npc::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const
{
if(name == "left")
if(name == "left" || name == "right")
{
MWBase::World *world = MWBase::Environment::get().getWorld();
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos);
if(world->isSwimming(ptr))
return "Swim Left";
return (name == "left") ? "Swim Left" : "Swim Right";
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
return "FootWaterLeft";
return (name == "left") ? "FootWaterLeft" : "FootWaterRight";
if(world->isOnGround(ptr))
{
MWWorld::InventoryStore &inv = Npc::getInventoryStore(ptr);
MWWorld::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots);
if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name())
return "FootBareLeft";
switch(boots->getClass().getEquipmentSkill(*boots))
if (ptr.getClass().getNpcStats(ptr).isWerewolf()
&& ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run))
{
case ESM::Skill::LightArmor:
return "FootLightLeft";
case ESM::Skill::MediumArmor:
return "FootMedLeft";
case ESM::Skill::HeavyArmor:
return "FootHeavyLeft";
MWMechanics::WeaponType weaponType = MWMechanics::WeapType_None;
MWMechanics::getActiveWeapon(ptr.getClass().getCreatureStats(ptr), ptr.getClass().getInventoryStore(ptr), &weaponType);
if (weaponType == MWMechanics::WeapType_None)
return "";
}
}
return "";
}
if(name == "right")
{
MWBase::World *world = MWBase::Environment::get().getWorld();
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos);
if(world->isSwimming(ptr))
return "Swim Right";
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
return "FootWaterRight";
if(world->isOnGround(ptr))
{
MWWorld::InventoryStore &inv = Npc::getInventoryStore(ptr);
MWWorld::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots);
if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name())
return "FootBareRight";
return (name == "left") ? "FootBareLeft" : "FootBareRight";
switch(boots->getClass().getEquipmentSkill(*boots))
{
case ESM::Skill::LightArmor:
return "FootLightRight";
return (name == "left") ? "FootLightLeft" : "FootLightRight";
case ESM::Skill::MediumArmor:
return "FootMedRight";
return (name == "left") ? "FootMedLeft" : "FootMedRight";
case ESM::Skill::HeavyArmor:
return "FootHeavyRight";
return (name == "left") ? "FootHeavyLeft" : "FootHeavyRight";
}
}
return "";
}
if(name == "land")
{
MWBase::World *world = MWBase::Environment::get().getWorld();

@ -507,7 +507,7 @@ namespace MWGui
mScrollBar->setVisible(true);
}
BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits<int>().max());
BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits<int>::max());
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
(*it)->write(typesetter, &mKeywordSearch, mTopicLinks);

@ -3,43 +3,91 @@
namespace MWGui
{
ScreenFader::ScreenFader()
FadeOp::FadeOp(ScreenFader * fader, float time, float targetAlpha)
: mFader(fader),
mRemainingTime(time),
mTargetTime(time),
mTargetAlpha(targetAlpha),
mStartAlpha(0.f),
mRunning(false)
{
}
bool FadeOp::isRunning()
{
return mRunning;
}
void FadeOp::start()
{
if (mRunning)
return;
mRemainingTime = mTargetTime;
mStartAlpha = mFader->getCurrentAlpha();
mRunning = true;
}
void FadeOp::update(float dt)
{
if (!mRunning)
return;
if (mRemainingTime <= 0 || mStartAlpha == mTargetAlpha)
{
finish();
return;
}
float currentAlpha = mFader->getCurrentAlpha();
if (mStartAlpha > mTargetAlpha)
{
currentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha);
if (currentAlpha < mTargetAlpha)
currentAlpha = mTargetAlpha;
}
else
{
currentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha);
if (currentAlpha > mTargetAlpha)
currentAlpha = mTargetAlpha;
}
mFader->notifyAlphaChanged(currentAlpha);
mRemainingTime -= dt;
}
void FadeOp::finish()
{
mRunning = false;
mFader->notifyOperationFinished();
}
ScreenFader::ScreenFader(const std::string & texturePath)
: WindowBase("openmw_screen_fader.layout")
, mMode(FadingMode_In)
, mRemainingTime(0.f)
, mTargetTime(0.f)
, mTargetAlpha(0.f)
, mCurrentAlpha(0.f)
, mStartAlpha(0.f)
, mFactor(1.f)
, mRepeat(false)
{
mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());
setTexture(texturePath);
setVisible(false);
}
void ScreenFader::setTexture(const std::string & texturePath)
{
mMainWidget->setProperty("ImageTexture", texturePath);
}
void ScreenFader::update(float dt)
{
if (mRemainingTime > 0)
if (!mQueue.empty())
{
if (mMode == FadingMode_In)
{
mCurrentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha);
if (mCurrentAlpha < mTargetAlpha) mCurrentAlpha = mTargetAlpha;
}
else if (mMode == FadingMode_Out)
{
mCurrentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha);
if (mCurrentAlpha > mTargetAlpha) mCurrentAlpha = mTargetAlpha;
}
mRemainingTime -= dt;
if (!mQueue.front()->isRunning())
mQueue.front()->start();
mQueue.front()->update(dt);
}
if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f)
mMainWidget->setVisible(false);
else
applyAlpha();
}
void ScreenFader::applyAlpha()
@ -50,62 +98,79 @@ namespace MWGui
void ScreenFader::fadeIn(float time)
{
if (time<0.f) return;
if (time==0.f)
{
mCurrentAlpha = 0.f;
applyAlpha();
return;
}
mStartAlpha = mCurrentAlpha;
mTargetAlpha = 0.f;
mMode = FadingMode_In;
mTargetTime = time;
mRemainingTime = time;
queue(time, 1.f);
}
void ScreenFader::fadeOut(const float time)
{
if (time<0.f) return;
if (time==0.f)
{
mCurrentAlpha = 1.f;
applyAlpha();
return;
}
mStartAlpha = mCurrentAlpha;
mTargetAlpha = 1.f;
mMode = FadingMode_Out;
mTargetTime = time;
mRemainingTime = time;
queue(time, 0.f);
}
void ScreenFader::fadeTo(const int percent, const float time)
{
if (time<0.f) return;
if (time==0.f)
queue(time, percent/100.f);
}
void ScreenFader::setFactor(float factor)
{
mFactor = factor;
applyAlpha();
}
void ScreenFader::setRepeat(bool repeat)
{
mRepeat = repeat;
}
void ScreenFader::queue(float time, float targetAlpha)
{
if (time < 0.f)
return;
if (time == 0.f)
{
mCurrentAlpha = percent/100.f;
mCurrentAlpha = targetAlpha;
applyAlpha();
return;
}
mStartAlpha = mCurrentAlpha;
mTargetAlpha = percent/100.f;
mQueue.push_back(FadeOp::Ptr(new FadeOp(this, time, targetAlpha)));
}
if (mTargetAlpha == mStartAlpha) return;
else if (mTargetAlpha > mStartAlpha) mMode = FadingMode_Out;
else mMode = FadingMode_In;
bool ScreenFader::isEmpty()
{
return mQueue.empty();
}
mTargetTime = time;
mRemainingTime = time;
void ScreenFader::clearQueue()
{
mQueue.clear();
}
void ScreenFader::setFactor(float factor)
void ScreenFader::notifyAlphaChanged(float alpha)
{
mFactor = factor;
if (mCurrentAlpha == alpha)
return;
mCurrentAlpha = alpha;
if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f)
mMainWidget->setVisible(false);
else
applyAlpha();
}
void ScreenFader::notifyOperationFinished()
{
FadeOp::Ptr op = mQueue.front();
mQueue.pop_front();
if (mRepeat)
mQueue.push_back(op);
}
float ScreenFader::getCurrentAlpha()
{
return mCurrentAlpha;
}
}

@ -1,15 +1,44 @@
#ifndef OPENMW_MWGUI_SCREENFADER_H
#define OPENMW_MWGUI_SCREENFADER_H
#include <deque>
#include <boost/shared_ptr.hpp>
#include "windowbase.hpp"
namespace MWGui
{
class ScreenFader;
class FadeOp
{
public:
typedef boost::shared_ptr<FadeOp> Ptr;
FadeOp(ScreenFader * fader, float time, float targetAlpha);
bool isRunning();
void start();
void update(float dt);
void finish();
private:
ScreenFader * mFader;
float mRemainingTime;
float mTargetTime;
float mTargetAlpha;
float mStartAlpha;
bool mRunning;
};
class ScreenFader : public WindowBase
{
public:
ScreenFader();
ScreenFader(const std::string & texturePath);
void setTexture(const std::string & texturePath);
void update(float dt);
@ -18,27 +47,25 @@ namespace MWGui
void fadeTo(const int percent, const float time);
void setFactor (float factor);
void setRepeat(bool repeat);
private:
enum FadingMode
{
FadingMode_In,
FadingMode_Out
};
void queue(float time, float targetAlpha);
bool isEmpty();
void clearQueue();
void applyAlpha();
void notifyAlphaChanged(float alpha);
void notifyOperationFinished();
float getCurrentAlpha();
FadingMode mMode;
private:
void applyAlpha();
float mRemainingTime;
float mTargetTime;
float mTargetAlpha;
float mCurrentAlpha;
float mStartAlpha;
float mFactor;
};
bool mRepeat; // repeat queued operations without removing them
std::deque<FadeOp::Ptr> mQueue;
};
}
#endif

@ -120,6 +120,9 @@ namespace MWGui
, mCompanionWindow(NULL)
, mVideoBackground(NULL)
, mVideoWidget(NULL)
, mWerewolfFader(NULL)
, mBlindnessFader(NULL)
, mHitFader(NULL)
, mScreenFader(NULL)
, mDebugWindow(NULL)
, mTranslationDataStorage (translationDataStorage)
@ -127,6 +130,8 @@ namespace MWGui
, mInputBlocker(NULL)
, mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD"))
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHitFaderEnabled(Settings::Manager::getBool ("hit fader", "GUI"))
, mWerewolfOverlayEnabled(Settings::Manager::getBool ("werewolf overlay", "GUI"))
, mHudEnabled(true)
, mGuiEnabled(true)
, mCursorVisible(true)
@ -267,7 +272,17 @@ namespace MWGui
mSoulgemDialog = new SoulgemDialog(mMessageBoxManager);
mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
trackWindow(mCompanionWindow, "companion");
mScreenFader = new ScreenFader();
mWerewolfFader = new ScreenFader("textures\\werewolfoverlay.dds");
mBlindnessFader = new ScreenFader("black.png");
std::string hitFaderTexture = "textures\\bm_player_hit_01.dds";
// fall back to player_hit_01.dds if bm_player_hit_01.dds is not available
// TODO: check if non-BM versions actually use player_hit_01.dds
if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(hitFaderTexture))
hitFaderTexture = "textures\\player_hit_01.dds";
mHitFader = new ScreenFader(hitFaderTexture);
mScreenFader = new ScreenFader("black.png");
mDebugWindow = new DebugWindow();
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay");
@ -359,6 +374,8 @@ namespace MWGui
delete mCursorManager;
delete mRecharge;
delete mCompanionWindow;
delete mHitFader;
delete mWerewolfFader;
delete mScreenFader;
delete mDebugWindow;
@ -862,6 +879,9 @@ namespace MWGui
mConsole->checkReferenceAvailable();
mCompanionWindow->onFrame();
mWerewolfFader->update(frameDuration);
mBlindnessFader->update(frameDuration);
mHitFader->update(frameDuration);
mScreenFader->update(frameDuration);
mDebugWindow->onFrame(frameDuration);
@ -1450,7 +1470,10 @@ namespace MWGui
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
if (player.getClass().getNpcStats(player).isWerewolf())
{
setWerewolfOverlay(true);
forceHide((GuiWindow)(MWGui::GW_Inventory | MWGui::GW_Magic));
}
}
// Remove this method for MyGUI 3.2.2
@ -1544,6 +1567,8 @@ namespace MWGui
mForceHidden = GW_None;
setWerewolfOverlay(false);
mGuiModes.clear();
MWBase::Environment::get().getInputManager()->changeInputMode(false);
updateVisible();
@ -1718,22 +1743,46 @@ namespace MWGui
void WindowManager::fadeScreenIn(const float time)
{
mScreenFader->fadeIn(time);
mScreenFader->clearQueue();
mScreenFader->fadeOut(time);
}
void WindowManager::fadeScreenOut(const float time)
{
mScreenFader->fadeOut(time);
mScreenFader->clearQueue();
mScreenFader->fadeIn(time);
}
void WindowManager::fadeScreenTo(const int percent, const float time)
{
mScreenFader->clearQueue();
mScreenFader->fadeTo(percent, time);
}
void WindowManager::setScreenFactor(float factor)
void WindowManager::setBlindness(const int percent)
{
mScreenFader->setFactor(factor);
mBlindnessFader->notifyAlphaChanged(percent / 100.f);
}
void WindowManager::activateHitOverlay(bool interrupt)
{
if (!mHitFaderEnabled)
return;
if (!interrupt && !mHitFader->isEmpty())
return;
mHitFader->clearQueue();
mHitFader->fadeTo(100, 0.0f);
mHitFader->fadeTo(0, 0.5f);
}
void WindowManager::setWerewolfOverlay(bool set)
{
if (!mWerewolfOverlayEnabled)
return;
mWerewolfFader->notifyAlphaChanged(set ? 1.0f : 0.0f);
}
void WindowManager::onClipboardChanged(const std::string &_type, const std::string &_data)

@ -330,8 +330,11 @@ namespace MWGui
virtual void fadeScreenOut(const float time);
/// Fade the screen to a specified percentage of black, over \a time seconds
virtual void fadeScreenTo(const int percent, const float time);
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor);
/// Darken the screen to a specified percentage
virtual void setBlindness(const int percent);
virtual void activateHitOverlay(bool interrupt);
virtual void setWerewolfOverlay(bool set);
virtual void toggleDebugWindow();
@ -387,6 +390,9 @@ namespace MWGui
CompanionWindow* mCompanionWindow;
MyGUI::ImageBox* mVideoBackground;
VideoWidget* mVideoWidget;
ScreenFader* mWerewolfFader;
ScreenFader* mBlindnessFader;
ScreenFader* mHitFader;
ScreenFader* mScreenFader;
DebugWindow* mDebugWindow;
@ -398,6 +404,8 @@ namespace MWGui
bool mCrosshairEnabled;
bool mSubtitlesEnabled;
bool mHitFaderEnabled;
bool mWerewolfOverlayEnabled;
bool mHudEnabled;
bool mGuiEnabled;
bool mCursorVisible;

@ -220,7 +220,7 @@ namespace MWMechanics
// Use the smallest soulgem that is large enough to hold the soul
MWWorld::ContainerStore& container = caster.getClass().getContainerStore(caster);
MWWorld::ContainerStoreIterator gem = container.end();
float gemCapacity = std::numeric_limits<float>().max();
float gemCapacity = std::numeric_limits<float>::max();
std::string soulgemFilter = "misc_soulgem"; // no other way to check for soulgems? :/
for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous);
it != container.end(); ++it)
@ -585,6 +585,12 @@ namespace MWMechanics
}
}
bool receivedMagicDamage = false;
if (creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth).getMagnitude() > 0.0f
|| creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth).getMagnitude() > 0.0f)
receivedMagicDamage = true;
// Apply damage ticks
int damageEffects[] = {
ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison,
@ -612,11 +618,22 @@ namespace MWMechanics
if (weather > 1)
damageScale *= fMagicSunBlockedMult;
health.setCurrent(health.getCurrent() - magnitude * duration * damageScale);
if (magnitude * damageScale > 0.0f)
receivedMagicDamage = true;
}
else
{
health.setCurrent(health.getCurrent() - magnitude * duration);
if (magnitude > 0.0f)
receivedMagicDamage = true;
}
}
if (receivedMagicDamage && ptr.getRefData().getHandle() == "player")
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
creatureStats.setHealth(health);
if (!wasDead && creatureStats.isDead())
@ -875,13 +892,13 @@ namespace MWMechanics
static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat();
ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - fSuffocationDamage*duration);
// Play a drowning sound as necessary for the player
// Play a drowning sound
MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager();
if(!sndmgr->getSoundPlaying(ptr, "drown"))
sndmgr->playSound3D(ptr, "drown", 1.0f, 1.0f);
if(ptr == world->getPlayerPtr())
{
MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager();
if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown"))
sndmgr->playSound("drown", 1.0f, 1.0f);
}
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
}
}
else

@ -166,10 +166,18 @@ namespace MWMechanics
{
const CreatureStats& stats = actor.getClass().getCreatureStats(actor);
// Never casting racial spells (ST_Power and F_Always)
if (spell->mData.mType != ESM::Spell::ST_Spell || spell->mData.mFlags & ESM::Spell::F_Always)
if (spell->mData.mType != ESM::Spell::ST_Spell)
return 0.f;
// Don't make use of racial bonus spells, like MW. Can be made optional later
if (actor.getClass().isNpc())
{
std::string raceid = actor.get<ESM::NPC>()->mBase->mRace;
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(raceid);
if (race->mPowers.exists(spell->mId))
return 0.f;
}
if (spell->mData.mCost > stats.getMagicka().getCurrent())
return 0.f;

@ -292,6 +292,7 @@ namespace MWMechanics
, mTarget(target)
, mStack(false)
, mHitPosition(0,0,0)
, mAlwaysSucceed(false)
{
}
@ -761,7 +762,7 @@ namespace MWMechanics
int school = 0;
if (mCaster.getClass().isActor())
if (mCaster.getClass().isActor() && !mAlwaysSucceed)
{
school = getSpellSchool(spell, mCaster);

@ -68,6 +68,7 @@ namespace MWMechanics
std::string mId; // ID of spell, potion, item etc
std::string mSourceName; // Display name for spell, potion, etc
Ogre::Vector3 mHitPosition; // Used for spawning area orb
bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false)
public:
CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target);

@ -85,7 +85,7 @@ namespace MWRender
mNode = renderRoot->createChildSceneNode();
mAnimation = new NpcAnimation(mCharacter, mNode,
0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
Ogre::Vector3 scale = mNode->getScale();
mCamera->setPosition(mPosition * scale);
@ -118,7 +118,7 @@ namespace MWRender
assert(mAnimation);
delete mAnimation;
mAnimation = new NpcAnimation(mCharacter, mNode,
0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
float scale=1.f;
mCharacter.getClass().adjustScale(mCharacter, scale);

@ -177,7 +177,7 @@ NpcAnimation::~NpcAnimation()
}
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener, ViewMode viewMode)
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener, bool disableSounds, ViewMode viewMode)
: Animation(ptr, node),
mVisibilityFlags(visibilityFlags),
mListenerDisabled(disableListener),
@ -186,7 +186,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v
mShowCarriedLeft(true),
mFirstPersonOffset(0.f, 0.f, 0.f),
mAlpha(1.f),
mNpcType(Type_Normal)
mNpcType(Type_Normal),
mSoundsDisabled(disableSounds)
{
mNpc = mPtr.get<ESM::NPC>()->mBase;
@ -297,7 +298,6 @@ void NpcAnimation::updateParts()
{
mAlpha = 1.f;
const MWWorld::Class &cls = mPtr.getClass();
MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr);
NpcType curType = Type_Normal;
if (cls.getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude() > 0)
@ -334,6 +334,7 @@ void NpcAnimation::updateParts()
};
static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]);
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++)
{
MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot);
@ -625,6 +626,11 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type)
mPartslots[type] = -1;
mObjectParts[type].setNull();
if (!mSoundIds[type].empty() && !mSoundsDisabled)
{
MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mSoundIds[type]);
mSoundIds[type].clear();
}
}
void NpcAnimation::reserveIndividualPart(ESM::PartReferenceType type, int group, int priority)
@ -654,8 +660,22 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
removeIndividualPart(type);
mPartslots[type] = group;
mPartPriorities[type] = priority;
mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor);
if (!mSoundsDisabled)
{
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
MWWorld::ContainerStoreIterator csi = inv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group);
if (csi != inv.end())
{
mSoundIds[type] = csi->getClass().getSound(*csi);
if (!mSoundIds[type].empty())
{
MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, mSoundIds[type], 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx,
MWBase::SoundManager::Play_Loop);
}
}
}
if(mObjectParts[type]->mSkelBase)
{
Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton();
@ -760,7 +780,7 @@ void NpcAnimation::showWeapons(bool showWeapon)
mShowWeapons = showWeapon;
if(showWeapon)
{
MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr);
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if(weapon != inv.end())
{
@ -793,9 +813,8 @@ void NpcAnimation::showWeapons(bool showWeapon)
void NpcAnimation::showCarriedLeft(bool show)
{
mShowCarriedLeft = show;
MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr);
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
if(show && iter != inv.end())
{
Ogre::Vector3 glowColor = getEnchantmentColor(*iter);
@ -928,4 +947,9 @@ void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectSce
}
}
void NpcAnimation::equipmentChanged()
{
updateParts();
}
}

@ -51,7 +51,7 @@ public:
class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener
{
public:
virtual void equipmentChanged() { updateParts(); }
virtual void equipmentChanged();
virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound);
public:
@ -70,6 +70,7 @@ private:
// Bounded Parts
NifOgre::ObjectScenePtr mObjectParts[ESM::PRT_Count];
std::string mSoundIds[ESM::PRT_Count];
const ESM::NPC *mNpc;
std::string mHeadModel;
@ -97,6 +98,7 @@ private:
Ogre::SharedPtr<WeaponAnimationTime> mWeaponAnimationTime;
float mAlpha;
bool mSoundsDisabled;
void updateNpcBase();
@ -123,10 +125,11 @@ public:
* one listener at a time, so you shouldn't do this if creating several NpcAnimations
* for the same Ptr, eg preview dolls for the player.
* Those need to be manually rendered anyway.
* @param disableSounds Same as \a disableListener but for playing items sounds
* @param viewMode
*/
NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener = false,
ViewMode viewMode=VM_Normal);
bool disableSounds = false, ViewMode viewMode=VM_Normal);
virtual ~NpcAnimation();
virtual void enableHeadAnimation(bool enable);

@ -36,6 +36,7 @@
#include "../mwbase/statemanager.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwworld/ptr.hpp"
@ -346,9 +347,12 @@ void RenderingManager::update (float duration, bool paused)
MWWorld::Ptr player = world->getPlayerPtr();
int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude();
MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f)));
MWBase::Environment::get().getWindowManager()->setBlindness(std::max(0, std::min(100, blind)));
setAmbientMode();
if (player.getClass().getNpcStats(player).isWerewolf())
MWBase::Environment::get().getWindowManager()->setWerewolfOverlay(mCamera->isFirstPerson());
// player position
MWWorld::RefData &data = player.getRefData();
Ogre::Vector3 playerPos(data.getPosition().pos);
@ -511,7 +515,7 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue
if (density == 0)
{
mFogStart = 0;
mFogEnd = std::numeric_limits<float>().max();
mFogEnd = std::numeric_limits<float>::max();
mRendering.getCamera()->setFarClipDistance (max);
}
else

@ -153,7 +153,7 @@ namespace MWScript
if (cell->getCell()->hasWater())
runtime.push (cell->getWaterLevel());
else
runtime.push (-std::numeric_limits<float>().max());
runtime.push (-std::numeric_limits<float>::max());
}
};

@ -438,7 +438,7 @@ namespace MWScript
// If the objects are in different worldspaces, return a large value (just like vanilla)
if (ref.getCell()->getCell()->getCellId().mWorldspace != ref2.getCell()->getCell()->getCellId().mWorldspace)
return std::numeric_limits<float>().max();
return std::numeric_limits<float>::max();
double diff[3];

@ -854,6 +854,7 @@ namespace MWScript
MWMechanics::CastSpell cast(ptr, target);
cast.mHitPosition = Ogre::Vector3(target.getRefData().getPosition().pos);
cast.mAlwaysSucceed = true;
cast.cast(spell);
}
};
@ -871,6 +872,7 @@ namespace MWScript
MWMechanics::CastSpell cast(ptr, ptr);
cast.mHitPosition = Ogre::Vector3(ptr.getRefData().getPosition().pos);
cast.mAlwaysSucceed = true;
cast.cast(spell);
}
};

@ -29,7 +29,7 @@ namespace MWSound
else if (type == SampleType_Int16)
{
value = *reinterpret_cast<const Ogre::int16*>(&data[sample*advance]);
value /= float(std::numeric_limits<Ogre::int16>().max());
value /= float(std::numeric_limits<Ogre::int16>::max());
}
else if (type == SampleType_Float32)
{

@ -454,6 +454,7 @@ namespace MWSound
while(snditer != mActiveSounds.end())
{
if(snditer->second.first != MWWorld::Ptr() &&
snditer->second.first.getCellRef().getRefId() != "player" &&
snditer->second.first.getCell() == cell)
{
snditer->first->stop();

@ -429,4 +429,9 @@ namespace MWWorld
return getEncumbrance(ptr) / capacity;
}
std::string Class::getSound(const MWWorld::Ptr&) const
{
return std::string();
}
}

@ -339,6 +339,9 @@ namespace MWWorld
virtual void respawn (const MWWorld::Ptr& ptr) const {}
virtual void restock (const MWWorld::Ptr& ptr) const {}
/// Returns sound id
virtual std::string getSound(const MWWorld::Ptr& ptr) const;
};
}

@ -148,16 +148,18 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite
flagAsModified();
fireEquipmentChangedEvent();
updateMagicEffects(actor);
}
void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor)
{
// Only *one* change event should be fired
mUpdatesEnabled = false;
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
unequipSlot(slot, actor);
mUpdatesEnabled = true;
fireEquipmentChangedEvent();
updateMagicEffects(actor);
}
@ -204,8 +206,9 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) &&
(actor.getClass().getScript(actor).empty() ||
!actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion")))
{
continue;
}
int testSkill = test.getClass().getEquipmentSkill (test);
std::pair<std::vector<int>, bool> itemsSlots =
@ -277,11 +280,13 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
bool changed = false;
for (std::size_t i=0; i<slots_.size(); ++i)
if (slots_[i]!=mSlots[i])
{
if (slots_[i] != mSlots[i])
{
changed = true;
break;
}
}
mUpdatesEnabled = true;
if (changed)

@ -829,15 +829,15 @@ namespace MWWorld
const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt)
{
// Collision events are only tracked for a single frame, so reset first
mCollisions.clear();
mStandingCollisions.clear();
mMovementResults.clear();
mTimeAccum += dt;
if(mTimeAccum >= 1.0f/60.0f)
{
// Collision events should be available on every frame
mCollisions.clear();
mStandingCollisions.clear();
const MWBase::World *world = MWBase::Environment::get().getWorld();
PtrVelocityList::iterator iter = mMovementQueue.begin();
for(;iter != mMovementQueue.end();++iter)

@ -124,10 +124,10 @@ namespace MWWorld
void Scene::getGridCenter(int &cellX, int &cellY)
{
int maxX = std::numeric_limits<int>().min();
int maxY = std::numeric_limits<int>().min();
int minX = std::numeric_limits<int>().max();
int minY = std::numeric_limits<int>().max();
int maxX = std::numeric_limits<int>::min();
int maxY = std::numeric_limits<int>::min();
int minX = std::numeric_limits<int>::max();
int minY = std::numeric_limits<int>::max();
CellStoreCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{

@ -2078,6 +2078,9 @@ namespace MWWorld
void World::hurtStandingActors(const Ptr &object, float healthPerSecond)
{
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
return;
std::vector<std::string> actors;
mPhysics->getActorsStandingOn(object, actors);
for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it)
@ -2087,14 +2090,28 @@ namespace MWWorld
continue;
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
if (stats.isDead())
continue;
MWMechanics::DynamicStat<float> health = stats.getHealth();
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
stats.setHealth(health);
if (healthPerSecond > 0.0f)
{
if (actor.getRefData().getHandle() == "player")
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage"))
MWBase::Environment::get().getSoundManager()->playSound3D(actor, "Health Damage", 1.0f, 1.0f);
}
}
}
void World::hurtCollidingActors(const Ptr &object, float healthPerSecond)
{
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
return;
std::vector<std::string> actors;
mPhysics->getActorsCollidingWith(object, actors);
for (std::vector<std::string>::iterator it = actors.begin(); it != actors.end(); ++it)
@ -2104,9 +2121,20 @@ namespace MWWorld
continue;
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
if (stats.isDead())
continue;
MWMechanics::DynamicStat<float> health = stats.getHealth();
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
stats.setHealth(health);
if (healthPerSecond > 0.0f)
{
if (actor.getRefData().getHandle() == "player")
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage"))
MWBase::Environment::get().getSoundManager()->playSound3D(actor, "Health Damage", 1.0f, 1.0f);
}
}
}
@ -2353,6 +2381,8 @@ namespace MWWorld
windowManager->unsetForceHide(MWGui::GW_Magic);
}
windowManager->setWerewolfOverlay(werewolf);
// Witnesses of the player's transformation will make them a globally known werewolf
std::vector<MWWorld::Ptr> closeActors;
MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(actor.getRefData().getPosition().pos),
@ -2934,6 +2964,9 @@ namespace MWWorld
void World::spawnBloodEffect(const Ptr &ptr, const Vector3 &worldPosition)
{
if (ptr.getRefData().getHandle() == "player" && Settings::Manager::getBool("hit fader", "GUI"))
return;
int type = ptr.getClass().getBloodTexture(ptr);
std::string texture;
switch (type)

@ -34,8 +34,8 @@ namespace ESMTerrain
if (!land)
return false;
min = std::numeric_limits<float>().max();
max = -std::numeric_limits<float>().max();
min = std::numeric_limits<float>::max();
max = -std::numeric_limits<float>::max();
for (int row=0; row<ESM::Land::LAND_SIZE; ++row)
{
for (int col=0; col<ESM::Land::LAND_SIZE; ++col)

@ -15,8 +15,8 @@ namespace Gui
public:
NumericEditBox()
: mValue(0), mMinValue(std::numeric_limits<int>().min()),
mMaxValue(std::numeric_limits<int>().max())
: mValue(0), mMinValue(std::numeric_limits<int>::min()),
mMaxValue(std::numeric_limits<int>::max())
{}
void initialiseOverride();

@ -94,6 +94,7 @@ Thomas Luppi (Digmaster)
Tom Mason (wheybags)
Torben Leif Carrington (TorbenC)
Vincent Heuken
vocollapse
Packagers:
Alexander Olofsson (Ace) - Windows

@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = Doxygen
OUTPUT_DIRECTORY = @OpenMW_BINARY_DIR@/docs/Doxygen
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@ -764,10 +764,10 @@ WARN_LOGFILE =
# spaces.
# Note: If this tag is empty the current directory is searched.
INPUT = apps \
components \
libs \
docs
INPUT = @OpenMW_SOURCE_DIR@/apps \
@OpenMW_SOURCE_DIR@/components \
@OpenMW_SOURCE_DIR@/libs \
@OpenMW_BINARY_DIR@/docs/mainpage.hpp
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

@ -38,7 +38,7 @@ PROJECT_NUMBER =
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = ../doxygen
OUTPUT_DIRECTORY = @DOXYGEN_PAGES_OUTPUT_DIR@
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@ -573,10 +573,10 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = apps \
components \
libs \
docs
INPUT = @OpenMW_SOURCE_DIR@/apps \
@OpenMW_SOURCE_DIR@/components \
@OpenMW_SOURCE_DIR@/libs \
@OpenMW_BINARY_DIR@/docs/mainpage.hpp
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

@ -27,7 +27,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h,
throw std::runtime_error("Couldn't get WM Info!");
Ogre::String winHandle;
Ogre::String winHandleSurface;
switch (wmInfo.subsystem)
{
@ -46,8 +45,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h,
#elif ANDROID
case SDL_SYSWM_ANDROID:
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.window);
winHandleSurface = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.surface);
break;
#else
case SDL_SYSWM_X11:
@ -63,7 +60,8 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h,
/// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error.
#ifdef ANDROID
params.insert(std::make_pair("externalSurface", winHandleSurface));
SDL_GLContext context= SDL_GL_CreateContext(window);
params.insert(std::make_pair("currentGLContext","True"));
#endif
params.insert(std::make_pair("externalWindowHandle", winHandle));

@ -41,6 +41,9 @@ tooltip delay = 0
subtitles = false
hit fader = true
werewolf overlay = true
[General]
# Camera field of view
field of view = 55

Loading…
Cancel
Save