Properly clear inventory

pull/203/head^2
Andrei Kortunov 8 years ago
commit f0f1df3a96

@ -1,6 +1,7 @@
#include "weapon.hpp" #include "weapon.hpp"
#include <components/esm/loadweap.hpp> #include <components/esm/loadweap.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -261,8 +262,8 @@ namespace MWClass
std::string text; std::string text;
// weapon type & damage. arrows / bolts don't have his info. // weapon type & damage
if (ref->mBase->mData.mType < 12) if ((ref->mBase->mData.mType < 12 || Settings::Manager::getBool("show projectile damage", "Game")) && ref->mBase->mData.mType < 14)
{ {
text += "\n#{sType} "; text += "\n#{sType} ";
@ -279,6 +280,8 @@ namespace MWClass
mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::MarksmanCrossbow] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::MarksmanCrossbow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::MarksmanThrown] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::MarksmanThrown] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::Arrow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::Bolt] = std::make_pair("sSkillMarksman", "");
std::string type = mapping[ref->mBase->mData.mType].first; std::string type = mapping[ref->mBase->mData.mType].first;
std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second; std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second;
@ -318,6 +321,14 @@ namespace MWClass
+ MWGui::ToolTips::toString(ref->mBase->mData.mHealth); + MWGui::ToolTips::toString(ref->mBase->mData.mHealth);
} }
// add reach and attack speed for melee weapon
if (ref->mBase->mData.mType < 9 && Settings::Manager::getBool("show melee info", "Game"))
{
text += MWGui::ToolTips::getPercentString(ref->mBase->mData.mReach, "#{sRange}");
text += MWGui::ToolTips::getPercentString(ref->mBase->mData.mSpeed, "#{sAttributeSpeed}");
}
text += MWGui::ToolTips::getWeightString(ref->mBase->mData.mWeight, "#{sWeight}"); text += MWGui::ToolTips::getWeightString(ref->mBase->mData.mWeight, "#{sWeight}");
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");

@ -13,6 +13,7 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
#include "textinput.hpp" #include "textinput.hpp"
#include "race.hpp" #include "race.hpp"
@ -230,10 +231,19 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
mReviewDialog = 0; mReviewDialog = 0;
mReviewDialog = new ReviewDialog(); mReviewDialog = new ReviewDialog();
mReviewDialog->setPlayerName(mPlayerName);
mReviewDialog->setRace(mPlayerRaceId); MWBase::World *world = MWBase::Environment::get().getWorld();
mReviewDialog->setClass(mPlayerClass);
mReviewDialog->setBirthSign(mPlayerBirthSignId); const ESM::NPC *playerNpc = world->getPlayerPtr().get<ESM::NPC>()->mBase;
const MWWorld::Player player = world->getPlayer();
const ESM::Class *playerClass = world->getStore().get<ESM::Class>().find(playerNpc->mClass);
mReviewDialog->setPlayerName(playerNpc->mName);
mReviewDialog->setRace(playerNpc->mRace);
mReviewDialog->setClass(*playerClass);
mReviewDialog->setBirthSign(player.getBirthSign());
{ {
MWWorld::Ptr player = MWMechanics::getPlayer(); MWWorld::Ptr player = MWMechanics::getPlayer();

@ -17,19 +17,26 @@ namespace MWGui
} }
void ConfirmationDialog::askForConfirmation(const std::string& message, const std::string& confirmMessage, const std::string& cancelMessage) void ConfirmationDialog::askForConfirmation(const std::string& message, const std::string& confirmMessage, const std::string& cancelMessage)
{
mCancelButton->setCaptionWithReplacing(cancelMessage);
mOkButton->setCaptionWithReplacing(confirmMessage);
askForConfirmation(message);
}
void ConfirmationDialog::askForConfirmation(const std::string& message)
{ {
setVisible(true); setVisible(true);
mMessage->setCaptionWithReplacing(message); mMessage->setCaptionWithReplacing(message);
mCancelButton->setCaptionWithReplacing(cancelMessage); int height = mMessage->getTextSize().height + 60;
mOkButton->setCaptionWithReplacing(confirmMessage);
int height = mMessage->getTextSize().height + 72; int width = mMessage->getTextSize().width + 24;
mMainWidget->setSize(mMainWidget->getWidth(), height); mMainWidget->setSize(width, height);
mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height+24); mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height + 24);
center(); center();
} }

@ -9,7 +9,8 @@ namespace MWGui
{ {
public: public:
ConfirmationDialog(); ConfirmationDialog();
void askForConfirmation(const std::string& message, const std::string& confirmMessage="#{sOk}", const std::string& cancelMessage="#{sCancel}"); void askForConfirmation(const std::string& message);
void askForConfirmation(const std::string& message, const std::string& confirmMessage, const std::string& cancelMessage);
virtual void exit(); virtual void exit();
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;

@ -136,6 +136,18 @@ namespace MWGui
dirtyPreview(); dirtyPreview();
updatePreviewSize(); updatePreviewSize();
updateEncumbranceBar();
mItemView->update();
notifyContentChanged();
}
void InventoryWindow::clear()
{
mPtr = MWWorld::Ptr();
mTradeModel = NULL;
mSortModel = NULL;
mItemView->setModel(NULL);
} }
void InventoryWindow::setGuiMode(GuiMode mode) void InventoryWindow::setGuiMode(GuiMode mode)
@ -340,13 +352,12 @@ namespace MWGui
void InventoryWindow::open() void InventoryWindow::open()
{ {
mPtr = MWMechanics::getPlayer(); if (!mPtr.isEmpty())
{
updateEncumbranceBar(); updateEncumbranceBar();
mItemView->update();
mItemView->update(); notifyContentChanged();
}
notifyContentChanged();
adjustPanes(); adjustPanes();
} }

@ -60,6 +60,8 @@ namespace MWGui
void updatePlayer(); void updatePlayer();
void clear();
void useItem(const MWWorld::Ptr& ptr); void useItem(const MWWorld::Ptr& ptr);
void setGuiMode(GuiMode mode); void setGuiMode(GuiMode mode);

@ -146,6 +146,7 @@ namespace MWGui
const ESM::NPC& proto = mPreview->getPrototype(); const ESM::NPC& proto = mPreview->getPrototype();
setRaceId(proto.mRace); setRaceId(proto.mRace);
setGender(proto.isMale() ? GM_Male : GM_Female);
recountParts(); recountParts();
for (unsigned int i=0; i<mAvailableHeads.size(); ++i) for (unsigned int i=0; i<mAvailableHeads.size(); ++i)

@ -253,6 +253,21 @@ namespace MWGui
return; return;
} }
} }
else
{
MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState();
// If game is running, ask for confirmation first
if (state == MWBase::StateManager::State_Running && !reallySure)
{
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
dialog->askForConfirmation("#{sMessage1}");
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onConfirmationGiven);
dialog->eventCancelClicked.clear();
return;
}
}
setVisible(false); setVisible(false);
MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu); MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu);

@ -594,6 +594,14 @@ namespace MWGui
return "\n" + prefix + ": " + toString(weight); return "\n" + prefix + ": " + toString(weight);
} }
std::string ToolTips::getPercentString(const float value, const std::string& prefix)
{
if (value == 0)
return "";
else
return "\n" + prefix + ": " + toString(value*100) +"%";
}
std::string ToolTips::getValueString(const int value, const std::string& prefix) std::string ToolTips::getValueString(const int value, const std::string& prefix)
{ {
if (value == 0) if (value == 0)

@ -63,6 +63,7 @@ namespace MWGui
///< set the screen-space position of the tooltip for focused object ///< set the screen-space position of the tooltip for focused object
static std::string getWeightString(const float weight, const std::string& prefix); static std::string getWeightString(const float weight, const std::string& prefix);
static std::string getPercentString(const float value, const std::string& prefix);
static std::string getValueString(const int value, const std::string& prefix); static std::string getValueString(const int value, const std::string& prefix);
///< @return "prefix: value" or "" if value is 0 ///< @return "prefix: value" or "" if value is 0

@ -1711,7 +1711,7 @@ namespace MWGui
mCompanionWindow->resetReference(); mCompanionWindow->resetReference();
mConsole->resetReference(); mConsole->resetReference();
mInventoryWindow->rebuildAvatar(); mInventoryWindow->clear();
mSelectedSpell.clear(); mSelectedSpell.clear();

@ -280,7 +280,7 @@ namespace MWMechanics
} }
} }
void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer) void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer)
{ {
CreatureStats& creatureStats1 = actor1.getClass().getCreatureStats(actor1); CreatureStats& creatureStats1 = actor1.getClass().getCreatureStats(actor1);
if (creatureStats1.getAiSequence().isInCombat(actor2)) if (creatureStats1.getAiSequence().isInCombat(actor2))
@ -306,7 +306,8 @@ namespace MWMechanics
// Get actors allied with actor1. Includes those following or escorting actor1, actors following or escorting those actors, (recursive) // Get actors allied with actor1. Includes those following or escorting actor1, actors following or escorting those actors, (recursive)
// and any actor currently being followed or escorted by actor1 // and any actor currently being followed or escorted by actor1
std::set<MWWorld::Ptr> allies1; std::set<MWWorld::Ptr> allies1;
getActorsSidingWith(actor1, allies1);
getActorsSidingWith(actor1, allies1, cachedAllies);
// If an ally of actor1 has been attacked by actor2 or has attacked actor2, start combat between actor1 and actor2 // If an ally of actor1 has been attacked by actor2 or has attacked actor2, start combat between actor1 and actor2
for (std::set<MWWorld::Ptr>::const_iterator it = allies1.begin(); it != allies1.end(); ++it) for (std::set<MWWorld::Ptr>::const_iterator it = allies1.begin(); it != allies1.end(); ++it)
@ -328,10 +329,10 @@ namespace MWMechanics
aggressive = true; aggressive = true;
} }
std::set<MWWorld::Ptr> playerFollowersAndEscorters; std::set<MWWorld::Ptr> playerAllies;
getActorsSidingWith(MWMechanics::getPlayer(), playerFollowersAndEscorters); getActorsSidingWith(MWMechanics::getPlayer(), playerAllies, cachedAllies);
bool isPlayerFollowerOrEscorter = std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), actor1) != playerFollowersAndEscorters.end(); bool isPlayerFollowerOrEscorter = std::find(playerAllies.begin(), playerAllies.end(), actor1) != playerAllies.end();
// If actor2 and at least one actor2 are in combat with actor1, actor1 and its allies start combat with them // If actor2 and at least one actor2 are in combat with actor1, actor1 and its allies start combat with them
// Doesn't apply for player followers/escorters // Doesn't apply for player followers/escorters
@ -341,7 +342,9 @@ namespace MWMechanics
if (actor2.getClass().getCreatureStats(actor2).getAiSequence().isInCombat(actor1)) if (actor2.getClass().getCreatureStats(actor2).getAiSequence().isInCombat(actor1))
{ {
std::set<MWWorld::Ptr> allies2; std::set<MWWorld::Ptr> allies2;
getActorsSidingWith(actor2, allies2);
getActorsSidingWith(actor2, allies2, cachedAllies);
// Check that an ally of actor2 is also in combat with actor1 // Check that an ally of actor2 is also in combat with actor1
for (std::set<MWWorld::Ptr>::const_iterator it = allies2.begin(); it != allies2.end(); ++it) for (std::set<MWWorld::Ptr>::const_iterator it = allies2.begin(); it != allies2.end(); ++it)
{ {
@ -383,11 +386,11 @@ namespace MWMechanics
// Do aggression check if actor2 is the player or a player follower or escorter // Do aggression check if actor2 is the player or a player follower or escorter
if (!aggressive) if (!aggressive)
{ {
if (againstPlayer || std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), actor2) != playerFollowersAndEscorters.end()) if (againstPlayer || std::find(playerAllies.begin(), playerAllies.end(), actor2) != playerAllies.end())
{ {
// Player followers and escorters with high fight should not initiate combat with the player or with // Player followers and escorters with high fight should not initiate combat with the player or with
// other player followers or escorters // other player followers or escorters
if (std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), actor1) == playerFollowersAndEscorters.end()) if (std::find(playerAllies.begin(), playerAllies.end(), actor1) == playerAllies.end())
aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2); aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2);
} }
} }
@ -800,6 +803,12 @@ namespace MWMechanics
CharacterController* ctrl = it->second->getCharacterController(); CharacterController* ctrl = it->second->getCharacterController();
NpcStats &stats = ptr.getClass().getNpcStats(ptr); NpcStats &stats = ptr.getClass().getNpcStats(ptr);
// When npc stats are just initialized, mTimeToStartDrowning == -1 and we should get value from GMST
static const int fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->getFloat();
if (stats.getTimeToStartDrowning() == -1.f)
stats.setTimeToStartDrowning(fHoldBreathTime);
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
bool knockedOutUnderwater = (ctrl->isKnockedOut() && world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3()))); bool knockedOutUnderwater = (ctrl->isKnockedOut() && world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3())));
if((world->isSubmerged(ptr) || knockedOutUnderwater) if((world->isSubmerged(ptr) || knockedOutUnderwater)
@ -1075,6 +1084,8 @@ namespace MWMechanics
/// \todo move update logic to Actor class where appropriate /// \todo move update logic to Actor class where appropriate
std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> > cachedAllies; // will be filled as engageCombat iterates
// AI and magic effects update // AI and magic effects update
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{ {
@ -1126,7 +1137,7 @@ namespace MWMechanics
{ {
if (it->first == iter->first || iter->first == player) // player is not AI-controlled if (it->first == iter->first || iter->first == player) // player is not AI-controlled
continue; continue;
engageCombat(iter->first, it->first, it->first == player); engageCombat(iter->first, it->first, cachedAllies, it->first == player);
} }
} }
if (timerUpdateHeadTrack == 0) if (timerUpdateHeadTrack == 0)
@ -1591,6 +1602,29 @@ namespace MWMechanics
getActorsSidingWith(*it, out); getActorsSidingWith(*it, out);
} }
void Actors::getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies) {
// If we have already found actor's allies, use the cache
std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >::const_iterator search = cachedAllies.find(actor);
if (search != cachedAllies.end())
out.insert(search->second.begin(), search->second.end());
else
{
std::list<MWWorld::Ptr> followers = getActorsSidingWith(actor);
for (std::list<MWWorld::Ptr>::iterator it = followers.begin(); it != followers.end(); ++it)
if (out.insert(*it).second)
getActorsSidingWith(*it, out, cachedAllies);
// Cache ptrs and their sets of allies
cachedAllies.insert(std::make_pair(actor, out));
for (std::set<MWWorld::Ptr>::const_iterator it = out.begin(); it != out.end(); ++it)
{
search = cachedAllies.find(*it);
if (search == cachedAllies.end())
cachedAllies.insert(std::make_pair(*it, out));
}
}
}
std::list<int> Actors::getActorsFollowingIndices(const MWWorld::Ptr &actor) std::list<int> Actors::getActorsFollowingIndices(const MWWorld::Ptr &actor)
{ {
std::list<int> list; std::list<int> list;

@ -88,7 +88,7 @@ namespace MWMechanics
@Notes: If againstPlayer = true then actor2 should be the Player. @Notes: If againstPlayer = true then actor2 should be the Player.
If one of the combatants is creature it should be actor1. If one of the combatants is creature it should be actor1.
*/ */
void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer); void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer);
void updateHeadTracking(const MWWorld::Ptr& actor, const MWWorld::Ptr& targetActor, void updateHeadTracking(const MWWorld::Ptr& actor, const MWWorld::Ptr& targetActor,
MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance); MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance);
@ -127,6 +127,8 @@ namespace MWMechanics
void getActorsFollowing(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out); void getActorsFollowing(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out);
/// Recursive version of getActorsSidingWith /// Recursive version of getActorsSidingWith
void getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out); void getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out);
/// Recursive version of getActorsSidingWith that takes, adds to and returns a cache of actors mapped to their allies
void getActorsSidingWith(const MWWorld::Ptr &actor, std::set<MWWorld::Ptr>& out, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies);
/// Get the list of AiFollow::mFollowIndex for all actors following this target /// Get the list of AiFollow::mFollowIndex for all actors following this target
std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor); std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor);

@ -1771,8 +1771,6 @@ void CharacterController::update(float duration)
float height = cls.getCreatureStats(mPtr).land(); float height = cls.getCreatureStats(mPtr).land();
float healthLost = getFallDamage(mPtr, height); float healthLost = getFallDamage(mPtr, height);
bool godmode = mPtr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if (healthLost > 0.0f) if (healthLost > 0.0f)
{ {
const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm(); const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm();

@ -73,6 +73,8 @@ namespace MWMechanics
MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr); MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr);
MWMechanics::NpcStats& npcStats = ptr.getClass().getNpcStats (ptr); MWMechanics::NpcStats& npcStats = ptr.getClass().getNpcStats (ptr);
npcStats.setNeedRecalcDynamicStats(true);
const ESM::NPC *player = ptr.get<ESM::NPC>()->mBase; const ESM::NPC *player = ptr.get<ESM::NPC>()->mBase;
// reset // reset
@ -326,12 +328,16 @@ namespace MWMechanics
winMgr->setValue(fbar, stats.getFatigue()); winMgr->setValue(fbar, stats.getFatigue());
} }
if(stats.getTimeToStartDrowning() != mWatchedTimeToStartDrowning) float timeToDrown = stats.getTimeToStartDrowning();
if(timeToDrown != mWatchedTimeToStartDrowning)
{ {
const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>() static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fHoldBreathTime")->getFloat(); .find("fHoldBreathTime")->getFloat();
mWatchedTimeToStartDrowning = stats.getTimeToStartDrowning();
if(stats.getTimeToStartDrowning() >= fHoldBreathTime) mWatchedTimeToStartDrowning = timeToDrown;
if(timeToDrown >= fHoldBreathTime || timeToDrown == -1.0) // -1.0 is a special value during initialization
winMgr->setDrowningBarVisibility(false); winMgr->setDrowningBarVisibility(false);
else else
{ {

@ -30,7 +30,7 @@ MWMechanics::NpcStats::NpcStats()
, mBounty(0) , mBounty(0)
, mWerewolfKills (0) , mWerewolfKills (0)
, mLevelProgress(0) , mLevelProgress(0)
, mTimeToStartDrowning(20.0) , mTimeToStartDrowning(-1.0) // set breath to special value, it will be replaced during actor update
, mIsWerewolf(false) , mIsWerewolf(false)
{ {
mSkillIncreases.resize (ESM::Attribute::Length, 0); mSkillIncreases.resize (ESM::Attribute::Length, 0);

@ -144,7 +144,8 @@ namespace MWScript
if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item)) if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item))
itemName = iter->getClass().getName(*iter); itemName = iter->getClass().getName(*iter);
int numRemoved = store.remove(item, count, ptr); // Actors should not equip a replacement when items are removed with RemoveItem
int numRemoved = store.remove(item, count, ptr, false);
// Spawn a messagebox (only for items removed from player's inventory) // Spawn a messagebox (only for items removed from player's inventory)
if ((numRemoved > 0) if ((numRemoved > 0)
@ -199,7 +200,8 @@ namespace MWScript
else else
{ {
boost::shared_ptr<MWWorld::Action> action = it->getClass().use(*it); boost::shared_ptr<MWWorld::Action> action = it->getClass().use(*it);
action->execute(ptr); // No equip sound for actors other than the player
action->execute(ptr, true);
} }
} }
}; };

@ -22,9 +22,9 @@ MWWorld::Action::Action (bool keepSound, const Ptr& target) : mKeepSound (keepSo
MWWorld::Action::~Action() {} MWWorld::Action::~Action() {}
void MWWorld::Action::execute (const Ptr& actor) void MWWorld::Action::execute (const Ptr& actor, bool noSound)
{ {
if(!mSoundId.empty()) if(!mSoundId.empty() && !noSound)
{ {
if(mKeepSound && actor == MWMechanics::getPlayer()) if(mKeepSound && actor == MWMechanics::getPlayer())
MWBase::Environment::get().getSoundManager()->playSound(mSoundId, 1.0, 1.0, MWBase::Environment::get().getSoundManager()->playSound(mSoundId, 1.0, 1.0,

@ -37,7 +37,7 @@ namespace MWWorld
virtual bool isNullAction() { return false; } virtual bool isNullAction() { return false; }
///< Is running this action a no-op? (default false) ///< Is running this action a no-op? (default false)
void execute (const Ptr& actor); void execute (const Ptr& actor, bool noSound = false);
void setSound (const std::string& id); void setSound (const std::string& id);
void setSoundOffset(float offset); void setSoundOffset(float offset);

@ -398,13 +398,13 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addNewStack (const Cons
return it; return it;
} }
int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor) int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement)
{ {
int toRemove = count; int toRemove = count;
for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter) for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter)
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId)) if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId))
toRemove -= remove(*iter, toRemove, actor); toRemove -= remove(*iter, toRemove, actor, equipReplacement);
flagAsModified(); flagAsModified();
@ -412,7 +412,7 @@ int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const
return count - toRemove; return count - toRemove;
} }
int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor) int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement)
{ {
assert(this == item.getContainerStore()); assert(this == item.getContainerStore());

@ -142,12 +142,12 @@ namespace MWWorld
ContainerStoreIterator add(const std::string& id, int count, const Ptr& actorPtr); ContainerStoreIterator add(const std::string& id, int count, const Ptr& actorPtr);
///< Utility to construct a ManualRef and call add(ptr, count, actorPtr, true) ///< Utility to construct a ManualRef and call add(ptr, count, actorPtr, true)
int remove(const std::string& itemId, int count, const Ptr& actor); int remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement = true);
///< Remove \a count item(s) designated by \a itemId from this container. ///< Remove \a count item(s) designated by \a itemId from this container.
/// ///
/// @return the number of items actually removed /// @return the number of items actually removed
virtual int remove(const Ptr& item, int count, const Ptr& actor); virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement = true);
///< Remove \a count item(s) designated by \a item from this inventory. ///< Remove \a count item(s) designated by \a item from this inventory.
/// ///
/// @return the number of items actually removed /// @return the number of items actually removed

@ -654,7 +654,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem(
return mSelectedEnchantItem; return mSelectedEnchantItem;
} }
int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor) int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement)
{ {
int retCount = ContainerStore::remove(item, count, actor); int retCount = ContainerStore::remove(item, count, actor);
@ -676,8 +676,9 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
} }
// If an armor/clothing item is removed, try to find a replacement, // If an armor/clothing item is removed, try to find a replacement,
// but not for the player nor werewolves. // but not for the player nor werewolves, and not if the RemoveItem script command
if (wasEquipped && (actor != MWMechanics::getPlayer()) // was used (equipReplacement is false)
if (equipReplacement && wasEquipped && (actor != MWMechanics::getPlayer())
&& actor.getClass().isNpc() && !actor.getClass().getNpcStats(actor).isWerewolf()) && actor.getClass().isNpc() && !actor.getClass().getNpcStats(actor).isWerewolf())
{ {
std::string type = item.getTypeName(); std::string type = item.getTypeName();

@ -177,7 +177,7 @@ namespace MWWorld
virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const; virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const;
///< @return true if the two specified objects can stack with each other ///< @return true if the two specified objects can stack with each other
virtual int remove(const Ptr& item, int count, const Ptr& actor); virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement = true);
///< Remove \a count item(s) designated by \a item from this inventory. ///< Remove \a count item(s) designated by \a item from this inventory.
/// ///
/// @return the number of items actually removed /// @return the number of items actually removed

@ -87,6 +87,8 @@ namespace SceneUtil
{ {
osg::ref_ptr<osg::Group> handle = new osg::Group; osg::ref_ptr<osg::Group> handle = new osg::Group;
osg::UserDataContainer* udc = toAttach->getUserDataContainer();
CopyRigVisitor copyVisitor(handle, filter); CopyRigVisitor copyVisitor(handle, filter);
toAttach->accept(copyVisitor); toAttach->accept(copyVisitor);
copyVisitor.doCopy(); copyVisitor.doCopy();
@ -96,11 +98,13 @@ namespace SceneUtil
osg::ref_ptr<osg::Node> newHandle = handle->getChild(0); osg::ref_ptr<osg::Node> newHandle = handle->getChild(0);
handle->removeChild(newHandle); handle->removeChild(newHandle);
master->asGroup()->addChild(newHandle); master->asGroup()->addChild(newHandle);
newHandle->setUserDataContainer(udc);
return newHandle; return newHandle;
} }
else else
{ {
master->asGroup()->addChild(handle); master->asGroup()->addChild(handle);
handle->setUserDataContainer(udc);
return handle; return handle;
} }
} }

@ -12,6 +12,28 @@ Enable visual clues for items owned by NPCs when the crosshair is on the object.
The default value is 0 (no clues). This setting can only be configured by editing the settings configuration file. The default value is 0 (no clues). This setting can only be configured by editing the settings configuration file.
show projectile damage
----------------------
:Type: boolean
:Range: True/False
:Default: False
If this setting is true, damage bonus of arrows and bolts will be showed on item tooltip.
The default value is false. This setting can only be configured by editing the settings configuration file.
show melee info
---------------
:Type: boolean
:Range: True/False
:Default: False
If this setting is true, melee weapons reach and speed will be showed on item tooltip.
The default value is false. This setting can only be configured by editing the settings configuration file.
best attack best attack
----------- -----------

@ -111,7 +111,7 @@
<Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="Bottom Right"/> <Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="Bottom Right"/>
<Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="Bottom Right"/> <Child type="Widget" skin="BTN_BottomRight" offset="132 20 4 4" align="Bottom Right"/>
<BasisSkin type="SimpleText" offset="4 4 128 16" align="Stretch"> <BasisSkin type="SimpleText" offset="4 3 128 16" align="Stretch">
<State name="disabled" colour="#{fontcolour=disabled}" shift="0"/> <State name="disabled" colour="#{fontcolour=disabled}" shift="0"/>
<State name="normal" colour="#{fontcolour=normal}" shift="0"/> <State name="normal" colour="#{fontcolour=normal}" shift="0"/>
<State name="highlighted" colour="#{fontcolour=normal_over}" shift="0"/> <State name="highlighted" colour="#{fontcolour=normal_over}" shift="0"/>

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout"> <MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 300 130" align="Center" name="_Main"> <Widget type="Window" skin="MW_DialogNoTransp" layer="Windows" position="0 0 360 130" align="Center" name="_Main">
<Property key="Visible" value="false"/> <Property key="Visible" value="false"/>
<Widget type="EditBox" skin="MW_TextEditClient" position="16 8 268 130" name="Message" align="Center Top"> <Widget type="EditBox" skin="MW_TextEditClient" position="16 8 338 130" name="Message" align="Center Top">
<Property key="FontName" value="Default"/> <Property key="FontName" value="Default"/>
<Property key="TextAlign" value="Top HCenter"/> <Property key="TextAlign" value="Top HCenter"/>
<Property key="Static" value="true"/> <Property key="Static" value="true"/>
@ -12,14 +12,14 @@
<Property key="MultiLine" value="true"/> <Property key="MultiLine" value="true"/>
</Widget> </Widget>
<Widget type="VBox" position="0 89 292 24" align="Right Bottom"> <Widget type="VBox" position="0 89 352 24" align="Center Bottom">
<Widget type="HBox"> <Widget type="HBox">
<Property key="Spacing" value="8"/> <Property key="Spacing" value="8"/>
<Widget type="AutoSizedButton" skin="MW_Button" name="OkButton" align="Right Bottom"> <Widget type="AutoSizedButton" skin="MW_Button" name="OkButton" align="Center Bottom">
<Property key="Caption" value="#{sYes}"/> <Property key="Caption" value="#{sYes}"/>
</Widget> </Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="CancelButton" align="Right Bottom"> <Widget type="AutoSizedButton" skin="MW_Button" name="CancelButton" align="Center Bottom">
<Property key="Caption" value="#{sNo}"/> <Property key="Caption" value="#{sNo}"/>
</Widget> </Widget>
</Widget> </Widget>

@ -1,29 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout" version="3.2.0"> <MyGUI type="Layout" version="3.2.0">
<Widget type="Window" skin="MW_Dialog" position="0 0 600 128" align="Center" layer="Windows" name="_Main"> <Widget type="Window" skin="MW_DialogNoTransp" position="0 0 600 128" align="Center" layer="Windows" name="_Main">
<Property key="Visible" value="false"/> <Property key="Visible" value="false"/>
<Widget type="TextBox" skin="SandText" position="4 4 592 24" align="Left Top HStretch" name="LabelText"> <Widget type="TextBox" skin="SandText" position="0 4 592 24" align="Left Top HStretch" name="LabelText">
<Property key="TextAlign" value="Center"/> <Property key="TextAlign" value="Center"/>
</Widget> </Widget>
<Widget type="TextBox" skin="SandText" position="4 30 521 24" align="Left Top HStretch" name="ItemText"> <Widget type="TextBox" skin="SandText" position="12 36 521 24" align="Left Top HStretch" name="ItemText">
<Property key="TextAlign" value="Right"/> <Property key="TextAlign" value="Left"/>
</Widget> </Widget>
<Widget type="NumericEditBox" skin="MW_TextEdit" position="535 30 50 24" align="Right Top" name="ItemEdit"> <Widget type="NumericEditBox" skin="MW_TextEdit" position="535 36 50 24" align="Right Top" name="ItemEdit">
<Property key="TextAlign" value="Center"/> <Property key="TextAlign" value="Center"/>
</Widget> </Widget>
<Widget type="MWScrollBar" skin="MW_HScroll" position="7 61 578 18" align="Left Top HStretch" name="CountSlider"> <Widget type="MWScrollBar" skin="MW_HScroll" position="7 67 578 18" align="Left Top HStretch" name="CountSlider">
<Property key="MoveToClick" value="true"/> <Property key="MoveToClick" value="true"/>
<Property key="Page" value="1"/> <Property key="Page" value="1"/>
<Property key="WheelPage" value="1"/> <Property key="WheelPage" value="1"/>
</Widget> </Widget>
<Widget type="HBox" skin="" position="0 88 585 24" align="Right Bottom"> <Widget type="HBox" skin="" position="0 91 140 24" align="Center Bottom">
<Widget type="Widget" skin="" position="0 12 0 0"> <Widget type="AutoSizedButton" skin="MW_Button" position="0 0 53 24" align="Center Top" name="OkButton">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="4 0 53 24" align="Right Top" name="OkButton">
<Property key="Caption" value="#{sOk}"/> <Property key="Caption" value="#{sOk}"/>
</Widget> </Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="61 0 78 24" align="Right Top" name="CancelButton"> <Widget type="AutoSizedButton" skin="MW_Button" position="0 0 86 24" align="Center Top" name="CancelButton">
<Property key="Caption" value="#{sCancel}"/> <Property key="Caption" value="#{sCancel}"/>
</Widget> </Widget>
</Widget> </Widget>

@ -131,9 +131,9 @@
<Child type="Widget" skin="MW_Box" offset="0 0 516 516" align="Stretch"/> <Child type="Widget" skin="MW_Box" offset="0 0 516 516" align="Stretch"/>
<Child type="MWScrollBar" skin="MW_VScroll" offset="498 3 14 509" align="Right VStretch" name="VScroll"/> <Child type="MWScrollBar" skin="MW_VScroll" offset="498 4 14 508" align="Right VStretch" name="VScroll"/>
<Child type="Widget" skin="" offset="3 3 493 509" align="Stretch" name="Client"/> <Child type="Widget" skin="" offset="3 4 493 508" align="Stretch" name="Client"/>
</Resource> </Resource>

@ -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="VBox" skin="MW_Dialog" layer="Windows" position="0 0 600 400" align="Center" name="_Main"> <Widget type="VBox" skin="MW_DialogNoTransp" layer="Windows" position="0 0 600 400" align="Center" name="_Main">
<Property key="Padding" value="12"/> <Property key="Padding" value="12"/>
<Property key="Spacing" value="8"/> <Property key="Spacing" value="8"/>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Resource" version="1.1"> <MyGUI type="Resource" version="1.1">
<!-- Defines a transparent background --> <!-- Defines a partially transparent background -->
<Resource type="ResourceSkin" name="BlackBG" size="8 8" texture="transparent"> <Resource type="ResourceSkin" name="BlackBG" size="8 8" texture="transparent">
<Property key="Colour" value="#{fontcolour=background}"/> <Property key="Colour" value="#{fontcolour=background}"/>
<BasisSkin type="MainSkin" offset="0 0 8 8"> <BasisSkin type="MainSkin" offset="0 0 8 8">
@ -9,6 +9,14 @@
</BasisSkin> </BasisSkin>
</Resource> </Resource>
<!-- Defines a non-transparent background -->
<Resource type="ResourceSkin" name="FullBlackBG" size="8 8" texture="black">
<BasisSkin type="MainSkin" offset="0 0 8 8">
<State name="normal" offset="0 0 8 8"/>
</BasisSkin>
</Resource>
<!-- Defines a non-transparent background -->
<Resource type="ResourceSkin" name="TransparentBG" size="8 8" texture="transparent"> <Resource type="ResourceSkin" name="TransparentBG" size="8 8" texture="transparent">
<Property key="Colour" value="#{fontcolour=background}"/> <Property key="Colour" value="#{fontcolour=background}"/>
</Resource> </Resource>
@ -883,4 +891,35 @@
<Property key="Scale" value="1 1 -1 -1"/> <Property key="Scale" value="1 1 -1 -1"/>
</Child> </Child>
</Resource> </Resource>
<Resource type="ResourceSkin" name="MW_DialogNoTransp" size="256 54">
<Child type="Widget" skin="FullBlackBG" offset="4 4 248 46" align="Stretch" name="Client"/>
<!-- Outer borders -->
<Child type="Widget" skin="DB_T" offset="4 0 248 4" align="Top HStretch" name="Border">
<Property key="Scale" value="0 1 0 -1"/>
</Child>
<Child type="Widget" skin="DB_L" offset="0 4 4 46" align="Left VStretch" name="Border">
<Property key="Scale" value="1 0 -1 0"/>
</Child>
<Child type="Widget" skin="DB_B" offset="4 50 248 4" align="Bottom HStretch" name="Border">
<Property key="Scale" value="0 0 0 1"/>
</Child>
<Child type="Widget" skin="DB_R" offset="252 4 4 46" align="Right VStretch" name="Border">
<Property key="Scale" value="0 0 1 0"/>
</Child>
<Child type="Widget" skin="DB_BR" offset="252 50 4 4" align="Right Bottom" name="Border">
<Property key="Scale" value="0 0 1 1"/>
</Child>
<Child type="Widget" skin="DB_BL" offset="0 50 4 4" align="Left Bottom" name="Border">
<Property key="Scale" value="1 0 -1 1"/>
</Child>
<Child type="Widget" skin="DB_TR" offset="252 0 4 4" align="Right Top" name="Border">
<Property key="Scale" value="0 1 1 -1"/>
</Child>
<Child type="Widget" skin="DB_TL" offset="0 0 4 4" align="Left Top" name="Border">
<Property key="Scale" value="1 1 -1 -1"/>
</Child>
</Resource>
</MyGUI> </MyGUI>

@ -149,6 +149,12 @@ crosshair = true
# no color, 1 is tool tip only, 2 is crosshair only, and 3 is both). # no color, 1 is tool tip only, 2 is crosshair only, and 3 is both).
show owned = 0 show owned = 0
# Show damage bonus of arrow and bolts.
show projectile damage = false
# Show additional melee weapon info: reach and attack speed
show melee info = false
# Always use the best mode of attack: e.g. chop, slash or thrust. # Always use the best mode of attack: e.g. chop, slash or thrust.
best attack = false best attack = false

Loading…
Cancel
Save