Merge remote-tracking branch 'scrawl/master'

deque
Marc Zinnschlag 11 years ago
commit 33c36bf0df

@ -102,7 +102,6 @@ set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
set(OENGINE_OGRE set(OENGINE_OGRE
${LIBDIR}/openengine/ogre/renderer.cpp ${LIBDIR}/openengine/ogre/renderer.cpp
${LIBDIR}/openengine/ogre/fader.cpp
${LIBDIR}/openengine/ogre/lights.cpp ${LIBDIR}/openengine/ogre/lights.cpp
${LIBDIR}/openengine/ogre/selectionbuffer.cpp ${LIBDIR}/openengine/ogre/selectionbuffer.cpp
${LIBDIR}/openengine/ogre/imagerotate.cpp ${LIBDIR}/openengine/ogre/imagerotate.cpp

@ -33,7 +33,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog
recharge mode videowidget backgroundimage itemwidget recharge mode videowidget backgroundimage itemwidget screenfader
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

@ -128,6 +128,7 @@ namespace MWBase
OffenseType type, int arg=0) = 0; OffenseType type, int arg=0) = 0;
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0; OffenseType type, int arg=0) = 0;
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
/// Utility to check if taking this item is illegal and calling commitCrime if so /// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0; virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so /// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so

@ -331,6 +331,15 @@ namespace MWBase
virtual void removeCurrentModal(MWGui::WindowModal* input) = 0; virtual void removeCurrentModal(MWGui::WindowModal* input) = 0;
virtual void pinWindow (MWGui::GuiWindow window) = 0; virtual void pinWindow (MWGui::GuiWindow window) = 0;
/// Fade the screen in, over \a time seconds
virtual void fadeScreenIn(const float time) = 0;
/// Fade the screen out to black, over \a time seconds
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;
}; };
} }

@ -17,11 +17,6 @@ namespace Ogre
namespace OEngine namespace OEngine
{ {
namespace Render
{
class Fader;
}
namespace Physic namespace Physic
{ {
class PhysicEngine; class PhysicEngine;
@ -113,9 +108,6 @@ namespace MWBase
virtual void readRecord (ESM::ESMReader& reader, int32_t type, virtual void readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap) = 0; const std::map<int, int>& contentFileMap) = 0;
virtual OEngine::Render::Fader* getFader() = 0;
///< \todo remove this function. Rendering details should not be exposed.
virtual MWWorld::CellStore *getExterior (int x, int y) = 0; virtual MWWorld::CellStore *getExterior (int x, int y) = 0;
virtual MWWorld::CellStore *getInterior (const std::string& name) = 0; virtual MWWorld::CellStore *getInterior (const std::string& name) = 0;
@ -271,8 +263,9 @@ namespace MWBase
/// use the "Head" node, or alternatively the "Bip01 Head" node as a basis. /// use the "Head" node, or alternatively the "Bip01 Head" node as a basis.
virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0; virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0;
virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0; virtual void adjustPosition (const MWWorld::Ptr& ptr, bool force) = 0;
///< Adjust position after load to be on ground. Must be called after model load. ///< Adjust position after load to be on ground. Must be called after model load.
/// @param force do this even if the ptr is flying
virtual void fixPosition (const MWWorld::Ptr& actor) = 0; virtual void fixPosition (const MWWorld::Ptr& actor) = 0;
///< Attempt to fix position so that the Ptr is no longer inside collision geometry. ///< Attempt to fix position so that the Ptr is no longer inside collision geometry.

@ -157,15 +157,19 @@ namespace MWClass
float iWeight = gmst.find (typeGmst)->getInt(); float iWeight = gmst.find (typeGmst)->getInt();
if (iWeight * gmst.find ("fLightMaxMod")->getFloat()>= float epsilon = 5e-4;
ref->mBase->mData.mWeight)
if (ref->mBase->mData.mWeight == 0)
return ESM::Skill::Unarmored;
if (ref->mBase->mData.mWeight <= iWeight * gmst.find ("fLightMaxMod")->getFloat() + epsilon)
return ESM::Skill::LightArmor; return ESM::Skill::LightArmor;
if (iWeight * gmst.find ("fMedMaxMod")->getFloat()>= if (ref->mBase->mData.mWeight <= iWeight * gmst.find ("fMedMaxMod")->getFloat() + epsilon)
ref->mBase->mData.mWeight)
return ESM::Skill::MediumArmor; return ESM::Skill::MediumArmor;
return ESM::Skill::HeavyArmor; else
return ESM::Skill::HeavyArmor;
} }
int Armor::getValue (const MWWorld::Ptr& ptr) const int Armor::getValue (const MWWorld::Ptr& ptr) const

@ -148,9 +148,9 @@ namespace MWClass
return ref->mBase->mId; return ref->mBase->mId;
} }
void Creature::adjustPosition(const MWWorld::Ptr& ptr) const void Creature::adjustPosition(const MWWorld::Ptr& ptr, bool force) const
{ {
MWBase::Environment::get().getWorld()->adjustPosition(ptr); MWBase::Environment::get().getWorld()->adjustPosition(ptr, force);
} }
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -255,23 +255,7 @@ namespace MWClass
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f) if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
{ {
victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, false); victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
// Weapon health is reduced by 1 even if the attack misses
const bool weaphashealth = !weapon.isEmpty() && weapon.getClass().hasItemHealth(weapon);
if(weaphashealth)
{
int weaphealth = weapon.getClass().getItemHealth(weapon);
if (!MWBase::Environment::get().getWorld()->getGodModeState())
{
weaphealth -= std::min(1, weaphealth);
weapon.getCellRef().setCharge(weaphealth);
}
// Weapon broken? unequip it
if (weapon.getCellRef().getCharge() == 0)
weapon = *getInventoryStore(ptr).unequipItem(weapon, ptr);
}
return; return;
} }
@ -298,7 +282,6 @@ namespace MWClass
if (!weapon.isEmpty()) if (!weapon.isEmpty())
{ {
const bool weaphashealth = weapon.getClass().hasItemHealth(weapon);
const unsigned char *attack = NULL; const unsigned char *attack = NULL;
if(type == ESM::Weapon::AT_Chop) if(type == ESM::Weapon::AT_Chop)
attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop; attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop;
@ -309,26 +292,10 @@ namespace MWClass
if(attack) if(attack)
{ {
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength()); damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
damage *= 0.5f + (stats.getAttribute(ESM::Attribute::Luck).getModified() / 100.0f); damage *= gmst.find("fDamageStrengthBase")->getFloat() +
if(weaphashealth) (stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.find("fDamageStrengthMult")->getFloat() * 0.1);
{ MWMechanics::adjustWeaponDamage(damage, weapon);
int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon); MWMechanics::reduceWeaponCondition(damage, true, weapon, ptr);
int weaphealth = weapon.getClass().getItemHealth(weapon);
damage *= float(weaphealth) / weapmaxhealth;
if (!MWBase::Environment::get().getWorld()->getGodModeState())
{
// Reduce weapon charge by at least one, but cap at 0
weaphealth -= std::min(std::max(1,
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weaphealth);
weapon.getCellRef().setCharge(weaphealth);
}
// Weapon broken? unequip it
if (weapon.getCellRef().getCharge() == 0)
weapon = *getInventoryStore(ptr).unequipItem(weapon, ptr);
}
} }
// Apply "On hit" enchanted weapons // Apply "On hit" enchanted weapons
@ -366,16 +333,11 @@ namespace MWClass
getCreatureStats(ptr).setAttacked(true); getCreatureStats(ptr).setAttacked(true);
// Self defense // Self defense
if ( ((!attacker.isEmpty() && attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(ptr)) if ((canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures
|| attacker == MWBase::Environment::get().getWorld()->getPlayerPtr())
&& !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker)
&& (canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures
// (they have no movement or attacks anyway) // (they have no movement or attacks anyway)
) && !attacker.isEmpty())
{ {
// Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back. MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
// Note: accidental or collateral damage attacks are ignored.
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
} }
if(!successful) if(!successful)

@ -49,7 +49,9 @@ namespace MWClass
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const;
virtual void adjustPosition(const MWWorld::Ptr& ptr) const; virtual void adjustPosition(const MWWorld::Ptr& ptr, bool force) const;
///< Adjust position to stand on ground. Must be called post model load
/// @param force do this even if the ptr is flying
virtual std::string getName (const MWWorld::Ptr& ptr) const; virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);

@ -403,9 +403,9 @@ namespace MWClass
return ref->mBase->mId; return ref->mBase->mId;
} }
void Npc::adjustPosition(const MWWorld::Ptr& ptr) const void Npc::adjustPosition(const MWWorld::Ptr& ptr, bool force) const
{ {
MWBase::Environment::get().getWorld()->adjustPosition(ptr); MWBase::Environment::get().getWorld()->adjustPosition(ptr, force);
} }
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -529,24 +529,7 @@ namespace MWClass
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f) if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
{ {
othercls.onHit(victim, 0.0f, false, weapon, ptr, false); othercls.onHit(victim, 0.0f, false, weapon, ptr, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
// Weapon health is reduced by 1 even if the attack misses
const bool weaphashealth = !weapon.isEmpty() && weapon.getClass().hasItemHealth(weapon);
if(weaphashealth)
{
int weaphealth = weapon.getClass().getItemHealth(weapon);
if (!MWBase::Environment::get().getWorld()->getGodModeState())
{
weaphealth -= std::min(1, weaphealth);
weapon.getCellRef().setCharge(weaphealth);
}
// Weapon broken? unequip it
if (weaphealth == 0)
weapon = *inv.unequipItem(weapon, ptr);
}
return; return;
} }
@ -555,7 +538,6 @@ namespace MWClass
MWMechanics::NpcStats &stats = getNpcStats(ptr); MWMechanics::NpcStats &stats = getNpcStats(ptr);
if(!weapon.isEmpty()) if(!weapon.isEmpty())
{ {
const bool weaphashealth = weapon.getClass().hasItemHealth(weapon);
const unsigned char *attack = NULL; const unsigned char *attack = NULL;
if(type == ESM::Weapon::AT_Chop) if(type == ESM::Weapon::AT_Chop)
attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop; attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop;
@ -568,27 +550,9 @@ namespace MWClass
damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength()); damage = attack[0] + ((attack[1]-attack[0])*stats.getAttackStrength());
damage *= gmst.fDamageStrengthBase->getFloat() + damage *= gmst.fDamageStrengthBase->getFloat() +
(stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.fDamageStrengthMult->getFloat() * 0.1); (stats.getAttribute(ESM::Attribute::Strength).getModified() * gmst.fDamageStrengthMult->getFloat() * 0.1);
if(weaphashealth)
{
int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon);
int weaphealth = weapon.getClass().getItemHealth(weapon);
damage *= float(weaphealth) / weapmaxhealth;
if (!MWBase::Environment::get().getWorld()->getGodModeState())
{
// Reduce weapon charge by at least one, but cap at 0
weaphealth -= std::min(std::max(1,
(int)(damage * store.find("fWeaponDamageMult")->getFloat())), weaphealth);
weapon.getCellRef().setCharge(weaphealth);
}
// Weapon broken? unequip it
if (weaphealth == 0)
weapon = *inv.unequipItem(weapon, ptr);
}
} }
MWMechanics::adjustWeaponDamage(damage, weapon);
MWMechanics::reduceWeaponCondition(damage, true, weapon, ptr);
healthdmg = true; healthdmg = true;
} }
else else
@ -675,26 +639,13 @@ namespace MWClass
// NOTE: 'object' and/or 'attacker' may be empty. // NOTE: 'object' and/or 'attacker' may be empty.
if (ptr != MWBase::Environment::get().getWorld()->getPlayerPtr())
{
// Attacking peaceful NPCs is a crime
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker)
&& !MWBase::Environment::get().getMechanicsManager()->isAggressive(ptr, attacker))
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
if (!attacker.isEmpty() && attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(ptr)
&& !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker))
{
// Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back.
// Note: accidental or collateral damage attacks are ignored.
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
}
}
bool wasDead = getCreatureStats(ptr).isDead(); bool wasDead = getCreatureStats(ptr).isDead();
getCreatureStats(ptr).setAttacked(true); getCreatureStats(ptr).setAttacked(true);
if (!attacker.isEmpty())
MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
if(!successful) if(!successful)
{ {
// TODO: Handle HitAttemptOnMe script function // TODO: Handle HitAttemptOnMe script function

@ -55,7 +55,9 @@ namespace MWClass
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const;
virtual void adjustPosition(const MWWorld::Ptr& ptr) const; virtual void adjustPosition(const MWWorld::Ptr& ptr, bool force) const;
///< Adjust position to stand on ground. Must be called post model load
/// @param force do this even if the ptr is flying
virtual std::string getName (const MWWorld::Ptr& ptr) const; virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);

@ -28,6 +28,16 @@
namespace MWGui namespace MWGui
{ {
DragAndDrop::DragAndDrop()
: mDraggedWidget(NULL)
, mDraggedCount(0)
, mSourceModel(NULL)
, mSourceView(NULL)
, mSourceSortModel(NULL)
, mIsOnDragAndDrop(NULL)
{
}
void DragAndDrop::startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count) void DragAndDrop::startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count)
{ {
mItem = sourceModel->getItem(index); mItem = sourceModel->getItem(index);
@ -36,7 +46,6 @@ namespace MWGui
mSourceView = sourceView; mSourceView = sourceView;
mSourceSortModel = sortModel; mSourceSortModel = sortModel;
mIsOnDragAndDrop = true; mIsOnDragAndDrop = true;
mDragAndDropWidget->setVisible(true);
// If picking up an item that isn't from the player's inventory, the item gets added to player inventory backend // If picking up an item that isn't from the player's inventory, the item gets added to player inventory backend
// immediately, even though it's still floating beneath the mouse cursor. A bit counterintuitive, // immediately, even though it's still floating beneath the mouse cursor. A bit counterintuitive,
@ -73,8 +82,13 @@ namespace MWGui
mSourceSortModel->addDragItem(mItem.mBase, count); mSourceSortModel->addDragItem(mItem.mBase, count);
} }
ItemWidget* baseWidget = mDragAndDropWidget->createWidget<ItemWidget> ItemWidget* baseWidget = MyGUI::Gui::getInstance().createWidget<ItemWidget>("MW_ItemIcon", 0, 0, 42, 42, MyGUI::Align::Default, "DragAndDrop");
("MW_ItemIcon", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default);
Controllers::ControllerFollowMouse* controller =
MyGUI::ControllerManager::getInstance().createItem(Controllers::ControllerFollowMouse::getClassTypeName())
->castType<Controllers::ControllerFollowMouse>();
MyGUI::ControllerManager::getInstance().addItem(baseWidget, controller);
mDraggedWidget = baseWidget; mDraggedWidget = baseWidget;
baseWidget->setItem(mItem.mBase); baseWidget->setItem(mItem.mBase);
baseWidget->setNeedMouseFocus(false); baseWidget->setNeedMouseFocus(false);
@ -99,8 +113,6 @@ namespace MWGui
std::string sound = mItem.mBase.getClass().getDownSoundId(mItem.mBase); std::string sound = mItem.mBase.getClass().getDownSoundId(mItem.mBase);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
mDragAndDropWidget->setVisible(false);
// If item is dropped where it was taken from, we don't need to do anything - // If item is dropped where it was taken from, we don't need to do anything -
// otherwise, do the transfer // otherwise, do the transfer
if (targetModel != mSourceModel) if (targetModel != mSourceModel)

@ -33,13 +33,14 @@ namespace MWGui
public: public:
bool mIsOnDragAndDrop; bool mIsOnDragAndDrop;
MyGUI::Widget* mDraggedWidget; MyGUI::Widget* mDraggedWidget;
MyGUI::Widget* mDragAndDropWidget;
ItemModel* mSourceModel; ItemModel* mSourceModel;
ItemView* mSourceView; ItemView* mSourceView;
SortFilterItemModel* mSourceSortModel; SortFilterItemModel* mSourceSortModel;
ItemStack mItem; ItemStack mItem;
int mDraggedCount; int mDraggedCount;
DragAndDrop();
void startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count); void startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count);
void drop (ItemModel* targetModel, ItemView* targetView); void drop (ItemModel* targetModel, ItemView* targetView);

@ -1,5 +1,7 @@
#include "controllers.hpp" #include "controllers.hpp"
#include <MyGUI_InputManager.h>
namespace MWGui namespace MWGui
{ {
namespace Controllers namespace Controllers
@ -50,5 +52,17 @@ namespace MWGui
{ {
} }
// -------------------------------------------------------------
void ControllerFollowMouse::prepareItem(MyGUI::Widget *_widget)
{
}
bool ControllerFollowMouse::addTime(MyGUI::Widget *_widget, float _time)
{
_widget->setPosition(MyGUI::InputManager::getInstance().getMousePosition());
return true;
}
} }
} }

@ -40,6 +40,17 @@ namespace MWGui
bool mEnabled; bool mEnabled;
float mTimeLeft; float mTimeLeft;
}; };
/// Automatically positions a widget below the mouse cursor.
class ControllerFollowMouse :
public MyGUI::ControllerItem
{
MYGUI_RTTI_DERIVED( ControllerFollowMouse )
private:
bool addTime(MyGUI::Widget* _widget, float _time);
void prepareItem(MyGUI::Widget* _widget);
};
} }
} }

@ -262,11 +262,32 @@ namespace MWGui
// in the cp437 encoding of the font. Fall back to similar available characters. // in the cp437 encoding of the font. Fall back to similar available characters.
if (mEncoding == ToUTF8::CP437) if (mEncoding == ToUTF8::CP437)
{ {
std::multimap<int, int> additional; std::multimap<int, int> additional; // <cp437, unicode>
additional.insert(std::make_pair(39, 0x2019)); // apostrophe additional.insert(std::make_pair(39, 0x2019)); // apostrophe
additional.insert(std::make_pair(45, 0x2013)); // dash additional.insert(std::make_pair(45, 0x2013)); // dash
additional.insert(std::make_pair(45, 0x2014)); // dash
additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark
additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark
additional.insert(std::make_pair(44, 0x201A));
additional.insert(std::make_pair(44, 0x201E));
additional.insert(std::make_pair(43, 0x2020));
additional.insert(std::make_pair(94, 0x02C6));
additional.insert(std::make_pair(37, 0x2030));
additional.insert(std::make_pair(83, 0x0160));
additional.insert(std::make_pair(60, 0x2039));
additional.insert(std::make_pair(79, 0x0152));
additional.insert(std::make_pair(90, 0x017D));
additional.insert(std::make_pair(39, 0x2019));
additional.insert(std::make_pair(126, 0x02DC));
additional.insert(std::make_pair(84, 0x2122));
additional.insert(std::make_pair(83, 0x0161));
additional.insert(std::make_pair(62, 0x203A));
additional.insert(std::make_pair(111, 0x0153));
additional.insert(std::make_pair(122, 0x017E));
additional.insert(std::make_pair(89, 0x0178));
additional.insert(std::make_pair(156, 0x00A2));
additional.insert(std::make_pair(46, 0x2026));
for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it) for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it)
{ {
if (it->first != i) if (it->first != i)

@ -406,7 +406,7 @@ namespace MWGui
box->setTextAlign(mTextStyle.mTextAlign); box->setTextAlign(mTextStyle.mTextAlign);
box->setTextColour(mTextStyle.mColour); box->setTextColour(mTextStyle.mColour);
box->setFontName(mTextStyle.mFont); box->setFontName(mTextStyle.mFont);
box->setCaption(realText); box->setCaption(MyGUI::TextIterator::toTagsString(realText));
box->setSize(box->getSize().width, box->getTextSize().height); box->setSize(box->getSize().width, box->getTextSize().height);
mHeight += box->getTextSize().height; mHeight += box->getTextSize().height;

@ -59,7 +59,7 @@ namespace MWGui
}; };
HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop) HUD::HUD(int fpsLevel, DragAndDrop* dragAndDrop)
: Layout("openmw_hud.layout") : Layout("openmw_hud.layout")
, mHealth(NULL) , mHealth(NULL)
, mMagicka(NULL) , mMagicka(NULL)
@ -97,7 +97,7 @@ namespace MWGui
, mWeaponSpellTimer(0.f) , mWeaponSpellTimer(0.f)
, mDrowningFlashTheta(0.f) , mDrowningFlashTheta(0.f)
{ {
setCoord(0,0, width, height); mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());
// Energy bars // Energy bars
getWidget(mHealthFrame, "HealthFrame"); getWidget(mHealthFrame, "HealthFrame");
@ -405,11 +405,6 @@ namespace MWGui
mDrowningFlashTheta += dt * Ogre::Math::TWO_PI; mDrowningFlashTheta += dt * Ogre::Math::TWO_PI;
} }
void HUD::onResChange(int width, int height)
{
setCoord(0, 0, width, height);
}
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
{ {
const ESM::Spell* spell = const ESM::Spell* spell =

@ -15,7 +15,7 @@ namespace MWGui
class HUD : public OEngine::GUI::Layout, public LocalMapBase class HUD : public OEngine::GUI::Layout, public LocalMapBase
{ {
public: public:
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); HUD(int fpsLevel, DragAndDrop* dragAndDrop);
virtual ~HUD(); virtual ~HUD();
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setFPS(float fps); void setFPS(float fps);
@ -47,7 +47,6 @@ namespace MWGui
void setCrosshairVisible(bool visible); void setCrosshairVisible(bool visible);
void onFrame(float dt); void onFrame(float dt);
void onResChange(int width, int height);
void setCellName(const std::string& cellName); void setCellName(const std::string& cellName);

@ -30,6 +30,8 @@ namespace MWGui
, mProgress(0) , mProgress(0)
, mVSyncWasEnabled(false) , mVSyncWasEnabled(false)
{ {
mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());
getWidget(mLoadingText, "LoadingText"); getWidget(mLoadingText, "LoadingText");
getWidget(mProgressBar, "ProgressBar"); getWidget(mProgressBar, "ProgressBar");
@ -56,13 +58,6 @@ namespace MWGui
mBackgroundImage->setVisible(visible); mBackgroundImage->setVisible(visible);
} }
void LoadingScreen::onResChange(int w, int h)
{
setCoord(0,0,w,h);
mBackgroundImage->setCoord(MyGUI::IntCoord(0,0,w,h));
}
void LoadingScreen::loadingOn() void LoadingScreen::loadingOn()
{ {
// Early-out if already on // Early-out if already on

@ -35,8 +35,6 @@ namespace MWGui
void setLoadingProgress (const std::string& stage, int depth, int current, int total); void setLoadingProgress (const std::string& stage, int depth, int current, int total);
void loadingDone(); void loadingDone();
void onResChange(int w, int h);
void updateWindow(Ogre::RenderWindow* rw) { mWindow = rw; } void updateWindow(Ogre::RenderWindow* rw) { mWindow = rw; }
private: private:

@ -0,0 +1,111 @@
#include "screenfader.hpp"
namespace MWGui
{
ScreenFader::ScreenFader()
: 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)
{
mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize());
setVisible(false);
}
void ScreenFader::update(float dt)
{
if (mRemainingTime > 0)
{
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 (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f)
mMainWidget->setVisible(false);
else
applyAlpha();
}
void ScreenFader::applyAlpha()
{
setVisible(true);
mMainWidget->setAlpha(1.f-((1.f-mCurrentAlpha) * mFactor));
}
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;
}
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;
}
void ScreenFader::fadeTo(const int percent, const float time)
{
if (time<0.f) return;
if (time==0.f)
{
mCurrentAlpha = percent/100.f;
applyAlpha();
return;
}
mStartAlpha = mCurrentAlpha;
mTargetAlpha = percent/100.f;
if (mTargetAlpha == mStartAlpha) return;
else if (mTargetAlpha > mStartAlpha) mMode = FadingMode_Out;
else mMode = FadingMode_In;
mTargetTime = time;
mRemainingTime = time;
}
void ScreenFader::setFactor(float factor)
{
mFactor = factor;
}
}

@ -0,0 +1,39 @@
#include "windowbase.hpp"
namespace MWGui
{
class ScreenFader : public WindowBase
{
public:
ScreenFader();
void update(float dt);
void fadeIn(const float time);
void fadeOut(const float time);
void fadeTo(const int percent, const float time);
void setFactor (float factor);
private:
enum FadingMode
{
FadingMode_In,
FadingMode_Out
};
void applyAlpha();
FadingMode mMode;
float mRemainingTime;
float mTargetTime;
float mTargetAlpha;
float mCurrentAlpha;
float mStartAlpha;
float mFactor;
};
}

@ -2,8 +2,6 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <openengine/ogre/fader.hpp>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -171,7 +169,7 @@ namespace MWGui
MWBase::Environment::get().getMechanicsManager()->rest(false); MWBase::Environment::get().getMechanicsManager()->rest(false);
MWBase::Environment::get().getMechanicsManager()->rest(false); MWBase::Environment::get().getMechanicsManager()->rest(false);
MWBase::Environment::get().getWorld ()->getFader()->fadeOut(0.25); MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.25);
mFadeTimeRemaining = 0.5; mFadeTimeRemaining = 0.5;
} }
@ -183,6 +181,6 @@ namespace MWGui
mFadeTimeRemaining -= dt; mFadeTimeRemaining -= dt;
if (mFadeTimeRemaining <= 0) if (mFadeTimeRemaining <= 0)
MWBase::Environment::get().getWorld ()->getFader()->fadeIn(0.25); MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.25);
} }
} }

@ -4,8 +4,6 @@
#include <OgreVector3.h> #include <OgreVector3.h>
#include <libs/openengine/ogre/fader.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -156,7 +154,7 @@ namespace MWGui
MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr); MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr);
npcStats.setGoldPool(npcStats.getGoldPool() + price); npcStats.setGoldPool(npcStats.getGoldPool() + price);
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1); MWBase::Environment::get().getWindowManager()->fadeScreenOut(1);
ESM::Position pos = *_sender->getUserData<ESM::Position>(); ESM::Position pos = *_sender->getUserData<ESM::Position>();
std::string cellname = _sender->getUserString("Destination"); std::string cellname = _sender->getUserString("Destination");
bool interior = _sender->getUserString("interior") == "y"; bool interior = _sender->getUserString("interior") == "y";
@ -179,8 +177,8 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0); MWBase::Environment::get().getWindowManager()->fadeScreenOut(0);
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(1); MWBase::Environment::get().getWindowManager()->fadeScreenIn(1);
} }
void TravelWindow::onCancelButtonClicked(MyGUI::Widget* _sender) void TravelWindow::onCancelButtonClicked(MyGUI::Widget* _sender)

@ -2,8 +2,6 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <libs/openengine/ogre/fader.hpp>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -128,7 +126,7 @@ namespace MWGui
MWBase::Environment::get().getStateManager()->quickSave("Autosave"); MWBase::Environment::get().getStateManager()->quickSave("Autosave");
MWBase::World* world = MWBase::Environment::get().getWorld(); MWBase::World* world = MWBase::Environment::get().getWorld();
world->getFader ()->fadeOut(0.2); MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.2);
setVisible(false); setVisible(false);
mProgressBar.setVisible (true); mProgressBar.setVisible (true);
@ -243,7 +241,7 @@ namespace MWGui
void WaitDialog::stopWaiting () void WaitDialog::stopWaiting ()
{ {
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.2); MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.2);
mProgressBar.setVisible (false); mProgressBar.setVisible (false);
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Rest); MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Rest);
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_RestBed); MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_RestBed);

@ -65,6 +65,7 @@
#include "videowidget.hpp" #include "videowidget.hpp"
#include "backgroundimage.hpp" #include "backgroundimage.hpp"
#include "itemwidget.hpp" #include "itemwidget.hpp"
#include "screenfader.hpp"
namespace MWGui namespace MWGui
{ {
@ -112,6 +113,7 @@ namespace MWGui
, mCompanionWindow(NULL) , mCompanionWindow(NULL)
, mVideoBackground(NULL) , mVideoBackground(NULL)
, mVideoWidget(NULL) , mVideoWidget(NULL)
, mScreenFader(NULL)
, mTranslationDataStorage (translationDataStorage) , mTranslationDataStorage (translationDataStorage)
, mCharGen(NULL) , mCharGen(NULL)
, mInputBlocker(NULL) , mInputBlocker(NULL)
@ -171,18 +173,14 @@ namespace MWGui
ItemWidget::registerComponents(); ItemWidget::registerComponents();
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatClick>("Controller"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatClick>("Controller");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer"); MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
MyGUI::ResourceManager::getInstance().load("core.xml"); MyGUI::ResourceManager::getInstance().load("core.xml");
MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag);
// Get size info from the Gui object
int w = MyGUI::RenderManager::getInstance().getViewSize().width;
int h = MyGUI::RenderManager::getInstance().getViewSize().height;
mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ()); mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ());
mLoadingScreen->onResChange (w,h);
//set up the hardware cursor manager //set up the hardware cursor manager
mCursorManager = new SFO::SDLCursorManager(); mCursorManager = new SFO::SDLCursorManager();
@ -192,7 +190,6 @@ namespace MWGui
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
//SDL_ShowCursor(false);
mCursorManager->setEnabled(true); mCursorManager->setEnabled(true);
@ -217,13 +214,7 @@ namespace MWGui
int w = MyGUI::RenderManager::getInstance().getViewSize().width; int w = MyGUI::RenderManager::getInstance().getViewSize().width;
int h = MyGUI::RenderManager::getInstance().getViewSize().height; int h = MyGUI::RenderManager::getInstance().getViewSize().height;
MyGUI::Widget* dragAndDropWidget = mGui->createWidgetT("Widget","",0,0,w,h,MyGUI::Align::Default,"DragAndDrop","DragAndDropWidget");
dragAndDropWidget->setVisible(false);
mDragAndDrop = new DragAndDrop(); mDragAndDrop = new DragAndDrop();
mDragAndDrop->mIsOnDragAndDrop = false;
mDragAndDrop->mDraggedWidget = 0;
mDragAndDrop->mDragAndDropWidget = dragAndDropWidget;
mRecharge = new Recharge(); mRecharge = new Recharge();
mMenu = new MainMenu(w,h); mMenu = new MainMenu(w,h);
@ -245,7 +236,7 @@ namespace MWGui
trackWindow(mDialogueWindow, "dialogue"); trackWindow(mDialogueWindow, "dialogue");
mContainerWindow = new ContainerWindow(mDragAndDrop); mContainerWindow = new ContainerWindow(mDragAndDrop);
trackWindow(mContainerWindow, "container"); trackWindow(mContainerWindow, "container");
mHud = new HUD(w,h, mShowFPSLevel, mDragAndDrop); mHud = new HUD(mShowFPSLevel, mDragAndDrop);
mToolTips = new ToolTips(); mToolTips = new ToolTips();
mScrollWindow = new ScrollWindow(); mScrollWindow = new ScrollWindow();
mBookWindow = new BookWindow(); mBookWindow = new BookWindow();
@ -267,8 +258,9 @@ namespace MWGui
mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); mSoulgemDialog = new SoulgemDialog(mMessageBoxManager);
mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
trackWindow(mCompanionWindow, "companion"); trackWindow(mCompanionWindow, "companion");
mScreenFader = new ScreenFader();
mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Default,"Overlay"); mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay");
mHud->setVisible(mHudEnabled); mHud->setVisible(mHudEnabled);
@ -357,6 +349,7 @@ namespace MWGui
delete mCursorManager; delete mCursorManager;
delete mRecharge; delete mRecharge;
delete mCompanionWindow; delete mCompanionWindow;
delete mScreenFader;
cleanupGarbage(); cleanupGarbage();
@ -858,6 +851,8 @@ namespace MWGui
mCompanionWindow->checkReferenceAvailable(); mCompanionWindow->checkReferenceAvailable();
mConsole->checkReferenceAvailable(); mConsole->checkReferenceAvailable();
mCompanionWindow->onFrame(); mCompanionWindow->onFrame();
mScreenFader->update(frameDuration);
} }
void WindowManager::changeCell(MWWorld::CellStore* cell) void WindowManager::changeCell(MWWorld::CellStore* cell)
@ -1019,7 +1014,6 @@ namespace MWGui
{ {
sizeVideo(x, y); sizeVideo(x, y);
mGuiManager->windowResized(); mGuiManager->windowResized();
mLoadingScreen->onResChange (x,y);
if (!mHud) if (!mHud)
return; // UI not initialized yet return; // UI not initialized yet
@ -1033,7 +1027,6 @@ namespace MWGui
it->first->setSize(size); it->first->setSize(size);
} }
mHud->onResChange(x, y);
mConsole->onResChange(x, y); mConsole->onResChange(x, y);
mMenu->onResChange(x, y); mMenu->onResChange(x, y);
mSettingsWindow->center(); mSettingsWindow->center();
@ -1042,8 +1035,6 @@ namespace MWGui
mBookWindow->center(); mBookWindow->center();
mQuickKeysMenu->center(); mQuickKeysMenu->center();
mSpellBuyingWindow->center(); mSpellBuyingWindow->center();
mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y));
mInputBlocker->setSize(MyGUI::IntSize(x,y));
} }
void WindowManager::pushGuiMode(GuiMode mode) void WindowManager::pushGuiMode(GuiMode mode)
@ -1688,4 +1679,24 @@ namespace MWGui
updateVisible(); updateVisible();
} }
void WindowManager::fadeScreenIn(const float time)
{
mScreenFader->fadeIn(time);
}
void WindowManager::fadeScreenOut(const float time)
{
mScreenFader->fadeOut(time);
}
void WindowManager::fadeScreenTo(const int percent, const float time)
{
mScreenFader->fadeTo(percent, time);
}
void WindowManager::setScreenFactor(float factor)
{
mScreenFader->setFactor(factor);
}
} }

@ -86,6 +86,7 @@ namespace MWGui
class CompanionWindow; class CompanionWindow;
class VideoWidget; class VideoWidget;
class WindowModal; class WindowModal;
class ScreenFader;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -324,6 +325,15 @@ namespace MWGui
virtual void pinWindow (MWGui::GuiWindow window); virtual void pinWindow (MWGui::GuiWindow window);
/// Fade the screen in, over \a time seconds
virtual void fadeScreenIn(const float time);
/// Fade the screen out to black, over \a time seconds
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);
private: private:
bool mConsoleOnlyScripts; bool mConsoleOnlyScripts;
@ -373,6 +383,7 @@ namespace MWGui
CompanionWindow* mCompanionWindow; CompanionWindow* mCompanionWindow;
MyGUI::ImageBox* mVideoBackground; MyGUI::ImageBox* mVideoBackground;
VideoWidget* mVideoWidget; VideoWidget* mVideoWidget;
ScreenFader* mScreenFader;
Translation::Storage& mTranslationDataStorage; Translation::Storage& mTranslationDataStorage;
Cursor* mSoftwareCursor; Cursor* mSoftwareCursor;

@ -805,16 +805,16 @@ namespace MWInput
if (MyGUI::InputManager::getInstance ().isModalAny()) if (MyGUI::InputManager::getInstance ().isModalAny())
return; return;
if((!MWBase::Environment::get().getWindowManager()->isGuiMode() if(MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Journal
|| MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Dialogue) && MWBase::Environment::get().getWindowManager ()->getJournalAllowed()
&& MWBase::Environment::get().getWindowManager ()->getJournalAllowed()) && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console)
{ {
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Journal); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Journal);
} }
else if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Journal) else if(MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Journal))
{ {
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Journal);
} }
} }

@ -169,12 +169,12 @@ namespace MWMechanics
MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker);
const MWWorld::Class &othercls = victim.getClass(); if(victim.isEmpty() || !victim.getClass().isActor() || victim.getClass().getCreatureStats(victim).isDead())
if(!othercls.isActor()) // Can't hit non-actors // Can't hit non-actors or dead actors
return; {
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim); reduceWeaponCondition(0.f, false, weapon, attacker);
if(otherstats.isDead()) // Can't hit dead actors
return; return;
}
if(attacker.getRefData().getHandle() == "player") if(attacker.getRefData().getHandle() == "player")
MWBase::Environment::get().getWindowManager()->setEnemy(victim); MWBase::Environment::get().getWindowManager()->setEnemy(victim);
@ -189,6 +189,7 @@ namespace MWMechanics
if((::rand()/(RAND_MAX+1.0)) > getHitChance(attacker, victim, skillValue)/100.0f) if((::rand()/(RAND_MAX+1.0)) > getHitChance(attacker, victim, skillValue)/100.0f)
{ {
victim.getClass().onHit(victim, 0.0f, false, projectile, attacker, false); victim.getClass().onHit(victim, 0.0f, false, projectile, attacker, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, attacker);
return; return;
} }
@ -209,6 +210,8 @@ namespace MWMechanics
damage *= fDamageStrengthBase + damage *= fDamageStrengthBase +
(attackerStats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult * 0.1); (attackerStats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult * 0.1);
adjustWeaponDamage(damage, weapon);
reduceWeaponCondition(damage, true, weapon, attacker);
if(attacker.getRefData().getHandle() == "player") if(attacker.getRefData().getHandle() == "player")
attacker.getClass().skillUsageSucceeded(attacker, weapskill, 0); attacker.getClass().skillUsageSucceeded(attacker, weapskill, 0);
@ -295,4 +298,42 @@ namespace MWMechanics
} }
} }
void reduceWeaponCondition(float damage, bool hit, MWWorld::Ptr &weapon, const MWWorld::Ptr &attacker)
{
if (weapon.isEmpty())
return;
if (!hit)
damage = 0.f;
const bool weaphashealth = weapon.getClass().hasItemHealth(weapon);
if(weaphashealth)
{
int weaphealth = weapon.getClass().getItemHealth(weapon);
const float fWeaponDamageMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWeaponDamageMult")->getFloat();
float x = std::max(1.f, fWeaponDamageMult * damage);
weaphealth -= std::min(int(x), weaphealth);
weapon.getCellRef().setCharge(weaphealth);
// Weapon broken? unequip it
if (weaphealth == 0)
weapon = *attacker.getClass().getInventoryStore(attacker).unequipItem(weapon, attacker);
}
}
void adjustWeaponDamage(float &damage, const MWWorld::Ptr &weapon)
{
if (weapon.isEmpty())
return;
const bool weaphashealth = weapon.getClass().hasItemHealth(weapon);
if(weaphashealth)
{
int weaphealth = weapon.getClass().getItemHealth(weapon);
int weapmaxhealth = weapon.getClass().getItemMaxHealth(weapon);
damage *= (float(weaphealth) / weapmaxhealth);
}
}
} }

@ -13,6 +13,7 @@ bool blockMeleeAttack (const MWWorld::Ptr& attacker, const MWWorld::Ptr& blocker
void resistNormalWeapon (const MWWorld::Ptr& actor, const MWWorld::Ptr& attacker, const MWWorld::Ptr& weapon, float& damage); void resistNormalWeapon (const MWWorld::Ptr& actor, const MWWorld::Ptr& attacker, const MWWorld::Ptr& weapon, float& damage);
/// @note for a thrown weapon, \a weapon == \a projectile, for bows/crossbows, \a projectile is the arrow/bolt /// @note for a thrown weapon, \a weapon == \a projectile, for bows/crossbows, \a projectile is the arrow/bolt
/// @note \a victim may be empty (e.g. for a hit on terrain), a non-actor (environment objects) or an actor
void projectileHit (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, MWWorld::Ptr weapon, const MWWorld::Ptr& projectile, void projectileHit (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, MWWorld::Ptr weapon, const MWWorld::Ptr& projectile,
const Ogre::Vector3& hitPosition); const Ogre::Vector3& hitPosition);
@ -22,6 +23,15 @@ float getHitChance (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, in
/// Applies damage to attacker based on the victim's elemental shields. /// Applies damage to attacker based on the victim's elemental shields.
void applyElementalShields(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim); void applyElementalShields(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim);
/// @param damage Unmitigated weapon damage of the attack
/// @param hit Was the attack successful?
/// @param weapon The weapon used.
/// @note if the weapon is unequipped as result of condition damage, a new Ptr will be assigned to \a weapon.
void reduceWeaponCondition (float damage, bool hit, MWWorld::Ptr& weapon, const MWWorld::Ptr& attacker);
/// Adjust weapon damage based on its condition. A used weapon will be less effective.
void adjustWeaponDamage (float& damage, const MWWorld::Ptr& weapon);
} }
#endif #endif

@ -973,6 +973,9 @@ namespace MWMechanics
if (!it->getClass().isNpc()) if (!it->getClass().isNpc())
continue; continue;
if (it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(victim))
continue;
// Will the witness report the crime? // Will the witness report the crime?
if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm) if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm)
{ {
@ -1071,6 +1074,9 @@ namespace MWMechanics
if (*it != victim && type == OT_Assault) if (*it != victim && type == OT_Assault)
aggression = iFightAttacking; aggression = iFightAttacking;
if (it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(victim))
continue;
if (it->getClass().isClass(*it, "guard")) if (it->getClass().isClass(*it, "guard"))
{ {
// Mark as Alarmed for dialogue // Mark as Alarmed for dialogue
@ -1100,6 +1106,35 @@ namespace MWMechanics
} }
} }
void MechanicsManager::actorAttacked(const MWWorld::Ptr &ptr, const MWWorld::Ptr &attacker)
{
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
return;
std::list<MWWorld::Ptr> followers = getActorsFollowing(attacker);
if (std::find(followers.begin(), followers.end(), ptr) != followers.end())
{
ptr.getClass().getCreatureStats(ptr).friendlyHit();
if (ptr.getClass().getCreatureStats(ptr).getFriendlyHits() < 4)
return;
}
// Attacking peaceful NPCs is a crime
if (ptr.getClass().isNpc() && !attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker)
&& !isAggressive(ptr, attacker))
commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(ptr)
|| attacker == MWBase::Environment::get().getWorld()->getPlayerPtr())
&& !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker))
{
// Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back.
// Note: accidental or collateral damage attacks are ignored.
startCombat(ptr, attacker);
}
}
bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer) bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer)
{ {
if (observer.getClass().getCreatureStats(observer).isDead()) if (observer.getClass().getCreatureStats(observer).isDead())

@ -119,6 +119,7 @@ namespace MWMechanics
OffenseType type, int arg=0); OffenseType type, int arg=0);
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0); OffenseType type, int arg=0);
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// Utility to check if taking this item is illegal and calling commitCrime if so /// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count); virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count);
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so /// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so

@ -72,7 +72,7 @@ namespace MWMechanics
return schoolSkillMap[school]; return schoolSkillMap[school];
} }
float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool) float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap)
{ {
CreatureStats& stats = actor.getClass().getCreatureStats(actor); CreatureStats& stats = actor.getClass().getCreatureStats(actor);
@ -123,14 +123,17 @@ namespace MWMechanics
if (MWBase::Environment::get().getWorld()->getGodModeState() && actor.getRefData().getHandle() == "player") if (MWBase::Environment::get().getWorld()->getGodModeState() && actor.getRefData().getHandle() == "player")
castChance = 100; castChance = 100;
return std::max(0.f, std::min(100.f, castChance)); if (!cap)
return std::max(0.f, castChance);
else
return std::max(0.f, std::min(100.f, castChance));
} }
float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor, int* effectiveSchool) float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap)
{ {
const ESM::Spell* spell = const ESM::Spell* spell =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId); MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
return getSpellSuccessChance(spell, actor, effectiveSchool); return getSpellSuccessChance(spell, actor, effectiveSchool, cap);
} }
@ -184,6 +187,10 @@ namespace MWMechanics
float resisted = 0; float resisted = 0;
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful) if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful)
{ {
// Effects with no resistance attribute belonging to them can not be resisted
if (ESM::MagicEffect::getResistanceEffect(effectId) == -1)
return 0.f;
float resistance = getEffectResistanceAttribute(effectId, magicEffects); float resistance = getEffectResistanceAttribute(effectId, magicEffects);
float willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); float willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
@ -191,12 +198,13 @@ namespace MWMechanics
float x = (willpower + 0.1 * luck) * stats.getFatigueTerm(); float x = (willpower + 0.1 * luck) * stats.getFatigueTerm();
// This makes spells that are easy to cast harder to resist and vice versa // This makes spells that are easy to cast harder to resist and vice versa
float castChance = 100.f;
if (spell != NULL && !caster.isEmpty() && caster.getClass().isActor()) if (spell != NULL && !caster.isEmpty() && caster.getClass().isActor())
{ {
float castChance = getSpellSuccessChance(spell, caster); castChance = getSpellSuccessChance(spell, caster, NULL, false); // Uncapped casting chance
if (castChance > 0)
x *= 50 / castChance;
} }
if (castChance > 0)
x *= 50 / castChance;
float roll = static_cast<float>(std::rand()) / RAND_MAX * 100; float roll = static_cast<float>(std::rand()) / RAND_MAX * 100;
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude) if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
@ -230,6 +238,44 @@ namespace MWMechanics
return -(resistance-100) / 100.f; return -(resistance-100) / 100.f;
} }
/// Check if the given affect can be applied to the target. If \a castByPlayer, emits a message box on failure.
bool checkEffectTarget (int effectId, const MWWorld::Ptr& target, bool castByPlayer)
{
switch (effectId)
{
case ESM::MagicEffect::Levitate:
if (!MWBase::Environment::get().getWorld()->isLevitationEnabled())
{
if (castByPlayer)
MWBase::Environment::get().getWindowManager()->messageBox("#{sLevitateDisabled}");
return false;
}
break;
case ESM::MagicEffect::Soultrap:
if ((target.getClass().isActor() && target.getClass().isNpc())
|| (target.getTypeName() == typeid(ESM::Creature).name() && target.get<ESM::Creature>()->mBase->mData.mSoul == 0))
{
if (castByPlayer)
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicInvalidTarget}");
return false;
}
break;
case ESM::MagicEffect::AlmsiviIntervention:
case ESM::MagicEffect::DivineIntervention:
case ESM::MagicEffect::Mark:
case ESM::MagicEffect::Recall:
if (!MWBase::Environment::get().getWorld()->isTeleportingEnabled())
{
if (castByPlayer)
MWBase::Environment::get().getWindowManager()->messageBox("#{sTeleportDisabled}");
return false;
}
break;
}
return true;
}
CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target) CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target)
: mCaster(caster) : mCaster(caster)
, mTarget(target) , mTarget(target)
@ -318,23 +364,8 @@ namespace MWMechanics
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find ( MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
effectIt->mEffectID); effectIt->mEffectID);
if (!MWBase::Environment::get().getWorld()->isLevitationEnabled() && effectIt->mEffectID == ESM::MagicEffect::Levitate) if (!checkEffectTarget(effectIt->mEffectID, target, castByPlayer))
{
if (castByPlayer)
MWBase::Environment::get().getWindowManager()->messageBox("#{sLevitateDisabled}");
continue;
}
if (!MWBase::Environment::get().getWorld()->isTeleportingEnabled() &&
(effectIt->mEffectID == ESM::MagicEffect::AlmsiviIntervention ||
effectIt->mEffectID == ESM::MagicEffect::DivineIntervention ||
effectIt->mEffectID == ESM::MagicEffect::Mark ||
effectIt->mEffectID == ESM::MagicEffect::Recall))
{
if (castByPlayer)
MWBase::Environment::get().getWindowManager()->messageBox("#{sTeleportDisabled}");
continue; continue;
}
// If player is healing someone, show the target's HP bar // If player is healing someone, show the target's HP bar
if (castByPlayer && target != caster if (castByPlayer && target != caster

@ -26,11 +26,12 @@ namespace MWMechanics
* @param spell spell to cast * @param spell spell to cast
* @param actor calculate spell success chance for this actor (depends on actor's skills) * @param actor calculate spell success chance for this actor (depends on actor's skills)
* @param effectiveSchool the spell's effective school (relevant for skill progress) will be written here * @param effectiveSchool the spell's effective school (relevant for skill progress) will be written here
* @attention actor has to be an NPC and not a creature! * @param cap cap the result to 100%?
* @return success chance from 0 to 100 (in percent) * @note actor can be an NPC or a creature
* @return success chance from 0 to 100 (in percent), if cap=false then chance above 100 may be returned.
*/ */
float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool = NULL); float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool = NULL, bool cap=true);
float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor, int* effectiveSchool = NULL); float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor, int* effectiveSchool = NULL, bool cap=true);
int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor); int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor);
int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor); int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor);

@ -98,6 +98,7 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell)
return; return;
Ogre::Image image; Ogre::Image image;
tex->load();
tex->convertToImage(image); tex->convertToImage(image);
Ogre::DataStreamPtr encoded = image.encode("tga"); Ogre::DataStreamPtr encoded = image.encode("tga");
@ -137,6 +138,7 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell)
return; return;
Ogre::Image image; Ogre::Image image;
tex->load();
tex->convertToImage(image); tex->convertToImage(image);
fog->mFogTextures.push_back(ESM::FogTexture()); fog->mFogTextures.push_back(ESM::FogTexture());
@ -581,6 +583,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
} }
} }
tex->load();
// copy to the texture // copy to the texture
// NOTE: Could be optimized later. We actually only need to update the region that changed. // NOTE: Could be optimized later. We actually only need to update the region that changed.
// Not a big deal at the moment, the FoW is only 32x32 anyway. // Not a big deal at the moment, the FoW is only 32x32 anyway.

@ -212,11 +212,6 @@ MWRender::Actors& RenderingManager::getActors(){
return *mActors; return *mActors;
} }
OEngine::Render::Fader* RenderingManager::getFader()
{
return mRendering.getFader();
}
MWRender::Camera* RenderingManager::getCamera() const MWRender::Camera* RenderingManager::getCamera() const
{ {
return mCamera; return mCamera;
@ -345,7 +340,7 @@ void RenderingManager::update (float duration, bool paused)
MWWorld::Ptr player = world->getPlayerPtr(); MWWorld::Ptr player = world->getPlayerPtr();
int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude; int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude;
mRendering.getFader()->setFactor(std::max(0.f, 1.f-(blind / 100.f))); MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f)));
setAmbientMode(); setAmbientMode();
// player position // player position

@ -4,8 +4,6 @@
#include "sky.hpp" #include "sky.hpp"
#include "debugging.hpp" #include "debugging.hpp"
#include <openengine/ogre/fader.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -98,8 +96,6 @@ public:
void toggleLight(); void toggleLight();
bool toggleRenderMode(int mode); bool toggleRenderMode(int mode);
OEngine::Render::Fader* getFader();
void removeCell (MWWorld::CellStore *store); void removeCell (MWWorld::CellStore *store);
/// \todo this function should be removed later. Instead the rendering subsystems should track /// \todo this function should be removed later. Instead the rendering subsystems should track

@ -294,7 +294,12 @@ void SkyManager::create()
// Stars // Stars
mAtmosphereNight = mRootNode->createChildSceneNode(); mAtmosphereNight = mRootNode->createChildSceneNode();
NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_01.nif"); NifOgre::ObjectScenePtr objects;
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("meshes\\sky_night_02.nif"))
objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_02.nif");
else
objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_01.nif");
for(size_t i = 0, matidx = 0;i < objects->mEntities.size();i++) for(size_t i = 0, matidx = 0;i < objects->mEntities.size();i++)
{ {
Entity* night1_ent = objects->mEntities[i]; Entity* night1_ent = objects->mEntities[i];

@ -3,8 +3,6 @@
#include <cstdlib> #include <cstdlib>
#include <libs/openengine/ogre/fader.hpp>
#include <components/compiler/extensions.hpp> #include <components/compiler/extensions.hpp>
#include <components/compiler/opcodes.hpp> #include <components/compiler/opcodes.hpp>
#include <components/compiler/locals.hpp> #include <components/compiler/locals.hpp>
@ -248,7 +246,7 @@ namespace MWScript
Interpreter::Type_Float time = runtime[0].mFloat; Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop(); runtime.pop();
MWBase::Environment::get().getWorld()->getFader()->fadeIn(time); MWBase::Environment::get().getWindowManager()->fadeScreenIn(time);
} }
}; };
@ -261,7 +259,7 @@ namespace MWScript
Interpreter::Type_Float time = runtime[0].mFloat; Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop(); runtime.pop();
MWBase::Environment::get().getWorld()->getFader()->fadeOut(time); MWBase::Environment::get().getWindowManager()->fadeScreenOut(time);
} }
}; };
@ -277,7 +275,7 @@ namespace MWScript
Interpreter::Type_Float time = runtime[0].mFloat; Interpreter::Type_Float time = runtime[0].mFloat;
runtime.pop(); runtime.pop();
MWBase::Environment::get().getWorld()->getFader()->fadeTo(alpha, time); MWBase::Environment::get().getWindowManager()->fadeScreenTo(alpha, time);
} }
}; };

@ -637,8 +637,6 @@ namespace MWScript
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{ {
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = ""; std::string factionID = "";
if(arg0 >0) if(arg0 >0)
{ {
@ -647,6 +645,8 @@ namespace MWScript
} }
else else
{ {
MWWorld::Ptr ptr = R()(runtime);
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
{ {
factionID = ""; factionID = "";
@ -913,8 +913,6 @@ namespace MWScript
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{ {
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = ""; std::string factionID = "";
if(arg0 >0 ) if(arg0 >0 )
{ {
@ -923,6 +921,8 @@ namespace MWScript
} }
else else
{ {
MWWorld::Ptr ptr = R()(runtime);
if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty()) if(ptr.getClass().getNpcStats(ptr).getFactionRanks().empty())
{ {
factionID = ""; factionID = "";

@ -327,7 +327,7 @@ namespace MWScript
} }
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot);
ptr.getClass().adjustPosition(ptr); ptr.getClass().adjustPosition(ptr, false);
} }
else else
{ {
@ -374,7 +374,7 @@ namespace MWScript
zRot = zRot/60.; zRot = zRot/60.;
} }
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot); MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot);
ptr.getClass().adjustPosition(ptr); ptr.getClass().adjustPosition(ptr, false);
} }
}; };

@ -322,7 +322,7 @@ namespace MWWorld
return std::make_pair (1, ""); return std::make_pair (1, "");
} }
void Class::adjustPosition(const MWWorld::Ptr& ptr) const void Class::adjustPosition(const MWWorld::Ptr& ptr, bool force) const
{ {
} }

@ -90,8 +90,9 @@ namespace MWWorld
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.
virtual void adjustPosition(const MWWorld::Ptr& ptr) const; virtual void adjustPosition(const MWWorld::Ptr& ptr, bool force) const;
///< Adjust position to stand on ground. Must be called post model load ///< Adjust position to stand on ground. Must be called post model load
/// @param force do this even if the ptr is flying
virtual MWMechanics::CreatureStats& getCreatureStats (const Ptr& ptr) const; virtual MWMechanics::CreatureStats& getCreatureStats (const Ptr& ptr) const;
///< Return creature stats or throw an exception, if class does not have creature stats ///< Return creature stats or throw an exception, if class does not have creature stats

@ -247,29 +247,23 @@ namespace MWWorld
if (obstacle == caster) if (obstacle == caster)
continue; continue;
if (obstacle.isEmpty()) MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId);
// Try to get a Ptr to the bow that was used. It might no longer exist.
MWWorld::Ptr bow = projectileRef.getPtr();
if (!caster.isEmpty())
{ {
// Terrain MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster);
} MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
else if (obstacle.getClass().isActor()) if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), it->mBowId))
{ bow = *invIt;
MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId);
// Try to get a Ptr to the bow that was used. It might no longer exist.
MWWorld::Ptr bow = projectileRef.getPtr();
if (!caster.isEmpty())
{
MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster);
MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), it->mBowId))
bow = *invIt;
}
if (caster.isEmpty())
caster = obstacle;
MWMechanics::projectileHit(caster, obstacle, bow, projectileRef.getPtr(), pos + (newPos - pos) * cIt->first);
} }
if (caster.isEmpty())
caster = obstacle;
MWMechanics::projectileHit(caster, obstacle, bow, projectileRef.getPtr(), pos + (newPos - pos) * cIt->first);
hit = true; hit = true;
} }
if (hit) if (hit)

@ -4,8 +4,6 @@
#include <components/nif/niffile.hpp> #include <components/nif/niffile.hpp>
#include <libs/openengine/ogre/fader.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" /// FIXME #include "../mwbase/world.hpp" /// FIXME
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
@ -86,7 +84,7 @@ namespace
updateObjectLocalRotation(ptr, mPhysics, mRendering); updateObjectLocalRotation(ptr, mPhysics, mRendering);
MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().getScale()); MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().getScale());
ptr.getClass().adjustPosition (ptr); ptr.getClass().adjustPosition (ptr, false);
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -232,7 +230,7 @@ namespace MWWorld
float z = Ogre::Radian(pos.rot[2]).valueDegrees(); float z = Ogre::Radian(pos.rot[2]).valueDegrees();
world->rotateObject(player, x, y, z); world->rotateObject(player, x, y, z);
player.getClass().adjustPosition(player); player.getClass().adjustPosition(player, true);
} }
MWBase::MechanicsManager *mechMgr = MWBase::MechanicsManager *mechMgr =
@ -406,7 +404,7 @@ namespace MWWorld
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
{ {
Nif::NIFFile::CacheLock lock; Nif::NIFFile::CacheLock lock;
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.5); MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(loadingListener); Loading::ScopedLoad load(loadingListener);
@ -431,8 +429,8 @@ namespace MWWorld
float z = Ogre::Radian(position.rot[2]).valueDegrees(); float z = Ogre::Radian(position.rot[2]).valueDegrees();
world->rotateObject(world->getPlayerPtr(), x, y, z); world->rotateObject(world->getPlayerPtr(), x, y, z);
world->getPlayerPtr().getClass().adjustPosition(world->getPlayerPtr()); world->getPlayerPtr().getClass().adjustPosition(world->getPlayerPtr(), true);
world->getFader()->fadeIn(0.5f); MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
return; return;
} }
@ -480,7 +478,7 @@ namespace MWWorld
MWBase::Environment::get().getWorld()->adjustSky(); MWBase::Environment::get().getWorld()->adjustSky();
mCellChanged = true; mCellChanged = true;
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.5); MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
} }
void Scene::changeToExteriorCell (const ESM::Position& position) void Scene::changeToExteriorCell (const ESM::Position& position)

@ -1151,7 +1151,7 @@ namespace MWWorld
} }
} }
void World::adjustPosition(const Ptr &ptr) void World::adjustPosition(const Ptr &ptr, bool force)
{ {
ESM::Position pos (ptr.getRefData().getPosition()); ESM::Position pos (ptr.getRefData().getPosition());
@ -1170,7 +1170,7 @@ namespace MWWorld
ptr.getRefData().setPosition(pos); ptr.getRefData().setPosition(pos);
if (!isFlying(ptr)) if (force || !isFlying(ptr))
{ {
Ogre::Vector3 traced = mPhysics->traceDown(ptr, 200); Ogre::Vector3 traced = mPhysics->traceDown(ptr, 200);
if (traced.z < pos.pos[2]) if (traced.z < pos.pos[2])
@ -1555,11 +1555,6 @@ namespace MWWorld
mWeatherManager->modRegion(regionid, chances); mWeatherManager->modRegion(regionid, chances);
} }
OEngine::Render::Fader* World::getFader()
{
return mRendering->getFader();
}
Ogre::Vector2 World::getNorthVector (CellStore* cell) Ogre::Vector2 World::getNorthVector (CellStore* cell)
{ {
MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>(); MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>();

@ -169,9 +169,6 @@ namespace MWWorld
virtual void readRecord (ESM::ESMReader& reader, int32_t type, virtual void readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap); const std::map<int, int>& contentFileMap);
virtual OEngine::Render::Fader* getFader();
///< \todo remove this function. Rendering details should not be exposed.
virtual CellStore *getExterior (int x, int y); virtual CellStore *getExterior (int x, int y);
virtual CellStore *getInterior (const std::string& name); virtual CellStore *getInterior (const std::string& name);
@ -260,8 +257,9 @@ namespace MWWorld
virtual Ptr searchPtrViaActorId (int actorId); virtual Ptr searchPtrViaActorId (int actorId);
///< Search is limited to the active cells. ///< Search is limited to the active cells.
virtual void adjustPosition (const Ptr& ptr); virtual void adjustPosition (const Ptr& ptr, bool force);
///< Adjust position after load to be on ground. Must be called after model load. ///< Adjust position after load to be on ground. Must be called after model load.
/// @param force do this even if the ptr is flying
virtual void fixPosition (const Ptr& actor); virtual void fixPosition (const Ptr& actor);
///< Attempt to fix position so that the Ptr is no longer inside collision geometry. ///< Attempt to fix position so that the Ptr is no longer inside collision geometry.

@ -113,7 +113,7 @@ namespace Compiler
{ {
void registerExtensions (Extensions& extensions) void registerExtensions (Extensions& extensions)
{ {
extensions.registerInstruction ("additem", "cl", opcodeAddItem, opcodeAddItemExplicit); extensions.registerInstruction ("additem", "clX", opcodeAddItem, opcodeAddItemExplicit);
extensions.registerFunction ("getitemcount", 'l', "c", opcodeGetItemCount, extensions.registerFunction ("getitemcount", 'l', "c", opcodeGetItemCount,
opcodeGetItemCountExplicit); opcodeGetItemCountExplicit);
extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem, extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem,

@ -80,6 +80,7 @@ set(MYGUI_FILES
openmw_companion_window.layout openmw_companion_window.layout
openmw_savegame_dialog.layout openmw_savegame_dialog.layout
openmw_recharge_dialog.layout openmw_recharge_dialog.layout
openmw_screen_fader.layout
DejaVuLGCSansMono.ttf DejaVuLGCSansMono.ttf
markers.png markers.png
../launcher/images/openmw.png ../launcher/images/openmw.png

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout"> <MyGUI type="Layout">
<Widget type="Widget" layer="HUD" position="0 0 300 200" name="_Main"> <Widget type="Widget" layer="HUD" position="0 0 300 200" name="_Main" align="Stretch">
<!-- Energy bars --> <!-- Energy bars -->
<Widget type="ProgressBar" skin="MW_EnergyBar_Yellow" position="13 131 65 12" align="Left Bottom" name="EnemyHealth"> <Widget type="ProgressBar" skin="MW_EnergyBar_Yellow" position="13 131 65 12" align="Left Bottom" name="EnemyHealth">
<Property key="Visible" value="false"/> <Property key="Visible" value="false"/>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layer"> <MyGUI type="Layer">
<Layer name="Render" overlapped="false" peek="false"/>
<Layer name="HUD" overlapped="false" peek="true"/> <Layer name="HUD" overlapped="false" peek="true"/>
<Layer name="Menu" overlapped="false" peek="false"/> <Layer name="Menu" overlapped="false" peek="false"/>
<Layer name="Windows" overlapped="true" peek="true"/> <Layer name="Windows" overlapped="true" peek="true"/>

@ -2,7 +2,7 @@
<MyGUI type="Layout"> <MyGUI type="Layout">
<!-- The entire screen --> <!-- The entire screen -->
<Widget type="Widget" layer="LoadingScreen" position="0 0 300 300" name="_Main"> <Widget type="Widget" layer="LoadingScreen" position="0 0 300 300" name="_Main" align="Stretch">
<Widget type="Widget" skin="HUD_Box" position="0 245 300 48" align="Bottom HCenter"> <Widget type="Widget" skin="HUD_Box" position="0 245 300 48" align="Bottom HCenter">

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="ImageBox" skin="ImageBox" layer="Render" position="0 0 300 200" name="_Main" align="Stretch">
<Property key="ImageTexture" value="black.png"/>
</Widget>
</MyGUI>

@ -1,136 +0,0 @@
#include "fader.hpp"
#include <OgreMaterial.h>
#include <OgreTechnique.h>
#include <OgreMaterialManager.h>
#include <OgreResourceGroupManager.h>
#include <OgreRectangle2D.h>
#include <OgreSceneManager.h>
#include <OgreSceneNode.h>
using namespace Ogre;
using namespace OEngine::Render;
Fader::Fader(Ogre::SceneManager* sceneMgr)
: mSceneMgr(sceneMgr)
, mMode(FadingMode_In)
, mRemainingTime(0.f)
, mTargetTime(0.f)
, mTargetAlpha(0.f)
, mCurrentAlpha(0.f)
, mStartAlpha(0.f)
, mFactor(1.f)
{
// Create the fading material
MaterialPtr material = MaterialManager::getSingleton().create("FadeInOutMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
Pass* pass = material->getTechnique(0)->getPass(0);
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
pass->setDepthWriteEnabled (false);
mFadeTextureUnit = pass->createTextureUnitState("black.png");
mFadeTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(0.f, 0.f, 0.f)); // always black colour
mRectangle = new Ogre::Rectangle2D(true);
mRectangle->setCorners(-1.0, 1.0, 1.0, -1.0);
mRectangle->setMaterial("FadeInOutMaterial");
mRectangle->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY-1);
// Use infinite AAB to always stay visible
Ogre::AxisAlignedBox aabInf;
aabInf.setInfinite();
mRectangle->setBoundingBox(aabInf);
// Attach background to the scene
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(mRectangle);
mRectangle->setVisible(false);
mRectangle->setVisibilityFlags (2048);
}
Fader::~Fader()
{
delete mRectangle;
}
void Fader::update(float dt)
{
if (mRemainingTime > 0)
{
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 (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f)
mRectangle->setVisible(false);
else
applyAlpha();
}
void Fader::applyAlpha()
{
mRectangle->setVisible(true);
mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 1.f-((1.f-mCurrentAlpha) * mFactor));
}
void Fader::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;
}
void Fader::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;
}
void Fader::fadeTo(const int percent, const float time)
{
if (time<0.f) return;
if (time==0.f)
{
mCurrentAlpha = percent/100.f;
applyAlpha();
return;
}
mStartAlpha = mCurrentAlpha;
mTargetAlpha = percent/100.f;
if (mTargetAlpha == mStartAlpha) return;
else if (mTargetAlpha > mStartAlpha) mMode = FadingMode_Out;
else mMode = FadingMode_In;
mTargetTime = time;
mRemainingTime = time;
}

@ -1,59 +0,0 @@
#ifndef OENGINE_OGRE_FADE_H
#define OENGINE_OGRE_FADE_H
/*
A class that handles fading in the screen from black or fading it out to black.
To achieve this, it uses a full-screen Rectangle2d
*/
namespace Ogre
{
class TextureUnitState;
class Rectangle2D;
class SceneManager;
}
namespace OEngine {
namespace Render
{
class Fader
{
public:
Fader(Ogre::SceneManager* sceneMgr);
~Fader();
void update(float dt);
void fadeIn(const float time);
void fadeOut(const float time);
void fadeTo(const int percent, const float time);
void setFactor (float factor) { mFactor = factor; }
private:
enum FadingMode
{
FadingMode_In,
FadingMode_Out
};
void applyAlpha();
Ogre::TextureUnitState* mFadeTextureUnit;
Ogre::Rectangle2D* mRectangle;
FadingMode mMode;
float mRemainingTime;
float mTargetTime;
float mTargetAlpha;
float mCurrentAlpha;
float mStartAlpha;
float mFactor;
Ogre::SceneManager* mSceneMgr;
};
}}
#endif

@ -1,5 +1,4 @@
#include "renderer.hpp" #include "renderer.hpp"
#include "fader.hpp"
#include <SDL.h> #include <SDL.h>
@ -27,9 +26,6 @@ using namespace OEngine::Render;
void OgreRenderer::cleanup() void OgreRenderer::cleanup()
{ {
delete mFader;
mFader = NULL;
if (mWindow) if (mWindow)
Ogre::Root::getSingleton().destroyRenderTarget(mWindow); Ogre::Root::getSingleton().destroyRenderTarget(mWindow);
mWindow = NULL; mWindow = NULL;
@ -46,7 +42,6 @@ void OgreRenderer::cleanup()
void OgreRenderer::update(float dt) void OgreRenderer::update(float dt)
{ {
mFader->update(dt);
} }
void OgreRenderer::screenshot(const std::string &file) void OgreRenderer::screenshot(const std::string &file)
@ -161,8 +156,6 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings&
mScene = mRoot->createSceneManager(ST_GENERIC); mScene = mRoot->createSceneManager(ST_GENERIC);
mFader = new Fader(mScene);
mCamera = mScene->createCamera("cam"); mCamera = mScene->createCamera("cam");
// Create one viewport, entire window // Create one viewport, entire window

@ -43,8 +43,6 @@ namespace OEngine
std::string icon; std::string icon;
}; };
class Fader;
class WindowSizeListener class WindowSizeListener
{ {
public: public:
@ -62,8 +60,6 @@ namespace OEngine
OgreInit::OgreInit* mOgreInit; OgreInit::OgreInit* mOgreInit;
Fader* mFader;
WindowSizeListener* mWindowListener; WindowSizeListener* mWindowListener;
int mWindowWidth; int mWindowWidth;
@ -79,7 +75,6 @@ namespace OEngine
, mCamera(NULL) , mCamera(NULL)
, mView(NULL) , mView(NULL)
, mOgreInit(NULL) , mOgreInit(NULL)
, mFader(NULL)
, mWindowListener(NULL) , mWindowListener(NULL)
, mWindowWidth(0) , mWindowWidth(0)
, mWindowHeight(0) , mWindowHeight(0)
@ -131,9 +126,6 @@ namespace OEngine
/// Get the scene manager /// Get the scene manager
Ogre::SceneManager *getScene() { return mScene; } Ogre::SceneManager *getScene() { return mScene; }
/// Get the screen colour fader
Fader *getFader() { return mFader; }
/// Camera /// Camera
Ogre::Camera *getCamera() { return mCamera; } Ogre::Camera *getCamera() { return mCamera; }

Loading…
Cancel
Save