Merge remote-tracking branch 'scrawl/master'

sceneinput
Marc Zinnschlag 10 years ago
commit 3992125b61

@ -281,9 +281,12 @@ namespace MWClass
ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative
}
bool Container::canLock(const MWWorld::Ptr &ptr) const
{
return true;
}
MWWorld::Ptr
Container::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
MWWorld::Ptr Container::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{
MWWorld::LiveCellRef<ESM::Container> *ref =
ptr.get<ESM::Container>();
@ -291,8 +294,7 @@ namespace MWClass
return MWWorld::Ptr(&cell.get<ESM::Container>().insert(*ref), &cell);
}
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
const
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
{
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
@ -307,8 +309,7 @@ namespace MWClass
readState (state2.mInventory);
}
void Container::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
const
void Container::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const
{
ESM::ContainerState& state2 = dynamic_cast<ESM::ContainerState&> (state);

@ -57,6 +57,8 @@ namespace MWClass
virtual void unlock (const MWWorld::Ptr& ptr) const;
///< Unlock object
virtual bool canLock(const MWWorld::Ptr &ptr) const;
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
const;
///< Read additional state from \a state into \a ptr.

@ -207,6 +207,11 @@ namespace MWClass
ptr.getCellRef().setLockLevel(-abs(ptr.getCellRef().getLockLevel())); //Makes lockLevel negative
}
bool Door::canLock(const MWWorld::Ptr &ptr) const
{
return true;
}
std::string Door::getScript (const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Door> *ref =

@ -47,6 +47,8 @@ namespace MWClass
virtual void unlock (const MWWorld::Ptr& ptr) const;
///< Unlock object
virtual bool canLock(const MWWorld::Ptr &ptr) const;
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr

@ -312,7 +312,7 @@ namespace MWGui
};
}
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
void CharacterCreation::selectPickedClass()
{
if (mPickClassDialog)
{
@ -332,20 +332,18 @@ namespace MWGui
}
updatePlayerHealth();
}
void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
{
selectPickedClass();
handleDialogDone(CSE_ClassChosen, GM_Birth);
}
void CharacterCreation::onPickClassDialogBack()
{
if (mPickClassDialog)
{
const std::string classId = mPickClassDialog->getClassId();
if (!classId.empty())
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(classId);
MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog);
mPickClassDialog = 0;
}
selectPickedClass();
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
@ -390,7 +388,7 @@ namespace MWGui
handleDialogDone(CSE_NameChosen, GM_Race);
}
void CharacterCreation::onRaceDialogBack()
void CharacterCreation::selectRace()
{
if (mRaceDialog)
{
@ -404,40 +402,31 @@ namespace MWGui
data.mHair
);
}
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->rebuildAvatar();
MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
mRaceDialog = 0;
}
updatePlayerHealth();
}
void CharacterCreation::onRaceDialogBack()
{
selectRace();
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Name);
}
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
{
if (mRaceDialog)
{
const ESM::NPC &data = mRaceDialog->getResult();
mPlayerRaceId = data.mRace;
if (!mPlayerRaceId.empty()) {
MWBase::Environment::get().getMechanicsManager()->setPlayerRace(
data.mRace,
data.isMale(),
data.mHead,
data.mHair
);
}
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->rebuildAvatar();
MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
mRaceDialog = 0;
}
updatePlayerHealth();
selectRace();
handleDialogDone(CSE_RaceChosen, GM_Class);
}
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
void CharacterCreation::selectBirthSign()
{
if (mBirthSignDialog)
{
@ -449,24 +438,24 @@ namespace MWGui
}
updatePlayerHealth();
}
void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
{
selectBirthSign();
handleDialogDone(CSE_BirthSignChosen, GM_Review);
}
void CharacterCreation::onBirthSignDialogBack()
{
if (mBirthSignDialog)
{
MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mBirthSignDialog->getBirthId());
MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog);
mBirthSignDialog = 0;
}
selectBirthSign();
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
}
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
void CharacterCreation::selectCreatedClass()
{
if (mCreateClassDialog)
{
@ -495,19 +484,23 @@ namespace MWGui
mPlayerClass = klass;
MWBase::Environment::get().getWindowManager()->setPlayerClass(klass);
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
// Do not delete dialog, so that choices are remembered in case we want to go back and adjust them later
mCreateClassDialog->setVisible(false);
}
updatePlayerHealth();
}
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
{
selectCreatedClass();
handleDialogDone(CSE_ClassChosen, GM_Birth);
}
void CharacterCreation::onCreateClassDialogBack()
{
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
mCreateClassDialog->setVisible(false);
// not done in MW, but we do it for consistency with the other dialogs
selectCreatedClass();
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
@ -631,18 +624,7 @@ namespace MWGui
MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps(mGenerateClassStep).mSound);
}
void CharacterCreation::onGenerateClassBack()
{
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
mGenerateClassResultDialog = 0;
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass);
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
}
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
void CharacterCreation::selectGeneratedClass()
{
MWBase::Environment::get().getWindowManager()->removeDialog(mGenerateClassResultDialog);
mGenerateClassResultDialog = 0;
@ -656,6 +638,19 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass);
updatePlayerHealth();
}
void CharacterCreation::onGenerateClassBack()
{
selectGeneratedClass();
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
}
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
{
selectGeneratedClass();
handleDialogDone(CSE_ClassChosen, GM_Birth);
}

@ -83,6 +83,7 @@ namespace MWGui
//Race dialog
void onRaceDialogDone(WindowBase* parWindow);
void onRaceDialogBack();
void selectRace();
//Class dialogs
void onClassChoice(int _index);
@ -94,10 +95,14 @@ namespace MWGui
void onClassQuestionChosen(int _index);
void onGenerateClassBack();
void onGenerateClassDone(WindowBase* parWindow);
void selectGeneratedClass();
void selectCreatedClass();
void selectPickedClass();
//Birthsign dialog
void onBirthSignDialogDone(WindowBase* parWindow);
void onBirthSignDialogBack();
void selectBirthSign();
//Review dialog
void onReviewDialogDone(WindowBase* parWindow);

@ -119,7 +119,12 @@ namespace MWGui
{
mPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr());
mSortModel = new SortFilterItemModel(mTradeModel);
if (mSortModel) // reuse existing SortModel when possible to keep previous category/filter settings
mSortModel->setSourceModel(mTradeModel);
else
mSortModel = new SortFilterItemModel(mTradeModel);
mItemView->setModel(mSortModel);
mPreview->updatePtr(mPtr);

@ -120,6 +120,11 @@ namespace MWGui
}
ProxyItemModel::ProxyItemModel()
: mSourceModel(NULL)
{
}
ProxyItemModel::~ProxyItemModel()
{
delete mSourceModel;
@ -164,4 +169,18 @@ namespace MWGui
return mSourceModel->getIndex(item);
}
void ProxyItemModel::setSourceModel(ItemModel *sourceModel)
{
if (mSourceModel == sourceModel)
return;
if (mSourceModel)
{
delete mSourceModel;
mSourceModel = NULL;
}
mSourceModel = sourceModel;
}
}

@ -80,11 +80,15 @@ namespace MWGui
class ProxyItemModel : public ItemModel
{
public:
ProxyItemModel();
virtual ~ProxyItemModel();
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
virtual void removeItem (const ItemStack& item, size_t count);
virtual ModelIndex getIndex (ItemStack item);
/// @note Takes ownership of the passed pointer.
void setSourceModel(ItemModel* sourceModel);
ModelIndex mapToSource (ModelIndex index);
ModelIndex mapFromSource (ModelIndex index);
protected:

@ -30,8 +30,12 @@ ItemView::~ItemView()
void ItemView::setModel(ItemModel *model)
{
if (mModel == model)
return;
delete mModel;
mModel = model;
update();
}

@ -61,6 +61,7 @@ namespace
DisplayStateStack mStates;
Book mTopicIndexBook;
bool mQuestMode;
bool mOptionsMode;
bool mAllQuests;
template <typename T>
@ -182,6 +183,7 @@ namespace
mQuestMode = false;
mAllQuests = false;
mOptionsMode = false;
}
void adjustButton (char const * name, bool optional = false)
@ -244,6 +246,7 @@ namespace
void setBookMode ()
{
mOptionsMode = false;
setVisible (OptionsBTN, true);
setVisible (OptionsOverlay, false);
@ -253,6 +256,8 @@ namespace
void setOptionsMode ()
{
mOptionsMode = true;
setVisible (OptionsBTN, false);
setVisible (OptionsOverlay, true);
@ -508,6 +513,8 @@ namespace
void notifyNextPage(MyGUI::Widget* _sender)
{
if (mOptionsMode)
return;
if (!mStates.empty ())
{
unsigned int & page = mStates.top ().mPage;
@ -523,6 +530,8 @@ namespace
void notifyPrevPage(MyGUI::Widget* _sender)
{
if (mOptionsMode)
return;
if (!mStates.empty ())
{
unsigned int & page = mStates.top ().mPage;

@ -783,7 +783,7 @@ namespace MWGui
MyGUI::Widget* markerWidget = mGlobalMap->createWidget<MyGUI::Widget>("MarkerButton",
widgetCoord, MyGUI::Align::Default);
markerWidget->setUserString("Caption_TextOneLine", name);
markerWidget->setUserString("Caption_TextOneLine", "#{sCell=" + name + "}");
setGlobalMapMarkerTooltip(markerWidget, x, y);

@ -190,7 +190,8 @@ namespace MWGui
void renderGlobalMap(Loading::Listener* loadingListener);
// adds the marker to the global map
/// adds the marker to the global map
/// @param name The ESM::Cell::mName
void addVisitedLocation(const std::string& name, int x, int y);
// reveals this cell's map on the global map

@ -347,8 +347,8 @@ namespace MWGui
char buffer[size];
if (std::strftime(buffer, size, "%x %X", timeinfo) > 0)
text << buffer << "\n";
text << "Level " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
text << mCurrentSlot->mProfile.mPlayerCell << "\n";
text << "#{sLevel} " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
text << "#{sCell=" << mCurrentSlot->mProfile.mPlayerCell << "}\n";
// text << "Time played: " << slot->mProfile.mTimePlayed << "\n";
int hour = int(mCurrentSlot->mProfile.mInGameTime.mGameHour);

@ -71,7 +71,6 @@ namespace MWGui
SortFilterItemModel::SortFilterItemModel(ItemModel *sourceModel)
: mCategory(Category_All)
, mFilter(0)
, mShowEquipped(true)
, mSortByType(true)
{
mSourceModel = sourceModel;
@ -91,9 +90,6 @@ namespace MWGui
{
MWWorld::Ptr base = item.mBase;
if (item.mType == ItemStack::Type_Equipped && !mShowEquipped)
return false;
int category = 0;
if (base.getTypeName() == typeid(ESM::Armor).name()
|| base.getTypeName() == typeid(ESM::Clothing).name())

@ -24,7 +24,6 @@ namespace MWGui
void setCategory (int category);
void setFilter (int filter);
void setShowEquipped (bool show) { mShowEquipped = show; }
/// Use ItemStack::Type for sorting?
void setSortByType(bool sort) { mSortByType = sort; }
@ -49,7 +48,6 @@ namespace MWGui
int mCategory;
int mFilter;
bool mShowEquipped;
bool mSortByType;
};

@ -157,7 +157,7 @@ namespace MWGui
// figure out if player will be woken while sleeping
int x = Misc::Rng::rollDice(hoursToWait);
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->getFloat();
if (x < fSleepRandMod * hoursToWait)
if (x < static_cast<int>(fSleepRandMod * hoursToWait))
{
float fSleepRestMod = world->getStore().get<ESM::GameSetting>().find("fSleepRestMod")->getFloat();
mInterruptAt = hoursToWait - int(fSleepRestMod * hoursToWait);

@ -993,7 +993,7 @@ namespace MWGui
if (cell->getCell()->isExterior())
{
if (!cell->getCell()->mName.empty())
mMap->addVisitedLocation ("#{sCell=" + name + "}", cell->getCell()->getGridX (), cell->getCell()->getGridY ());
mMap->addVisitedLocation (name, cell->getCell()->getGridX (), cell->getCell()->getGridY ());
mMap->cellExplored (cell->getCell()->getGridX(), cell->getCell()->getGridY());
}

@ -247,15 +247,16 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
bool block = mPtr.getClass().getCreatureStats(mPtr).getBlock();
if(mHitState == CharState_None)
{
if (mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() < 0
if ((mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() < 0
|| mPtr.getClass().getCreatureStats(mPtr).getFatigue().getBase() == 0)
&& mAnimation->hasAnimation("knockout"))
{
mHitState = CharState_KnockOut;
mCurrentHit = "knockout";
mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::BlendMask_All, false, 1, "start", "stop", 0.0f, ~0ul);
mPtr.getClass().getCreatureStats(mPtr).setKnockedDown(true);
}
else if(knockdown)
else if(knockdown && mAnimation->hasAnimation("knockdown"))
{
mHitState = CharState_KnockDown;
mCurrentHit = "knockdown";
@ -263,11 +264,15 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
}
else if (recovery)
{
mHitState = CharState_Hit;
mCurrentHit = chooseRandomGroup("hit");
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::BlendMask_All, true, 1, "start", "stop", 0.0f, 0);
std::string anim = chooseRandomGroup("hit");
if (mAnimation->hasAnimation(anim))
{
mHitState = CharState_Hit;
mCurrentHit = anim;
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::BlendMask_All, true, 1, "start", "stop", 0.0f, 0);
}
}
else if (block)
else if (block && mAnimation->hasAnimation("shield"))
{
mHitState = CharState_Block;
mCurrentHit = "shield";

@ -31,7 +31,7 @@ namespace MWMechanics
void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick,
std::string& resultMessage, std::string& resultSound)
{
if (!(lock.getCellRef().getLockLevel() > 0)) //If it's unlocked back out immediately
if (!(lock.getCellRef().getLockLevel() > 0) || !lock.getClass().canLock(lock)) //If it's unlocked back out immediately
return;
int lockStrength = lock.getCellRef().getLockLevel();

@ -489,8 +489,8 @@ namespace MWMechanics
if (!wasDead && isDead)
MWBase::Environment::get().getMechanicsManager()->actorKilled(target, caster);
}
else
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
else if (!applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude))
continue;
}
// Re-casting a summon effect will remove the creature from previous castings of that effect.
@ -559,10 +559,10 @@ namespace MWMechanics
target.getClass().onHit(target, 0.f, true, MWWorld::Ptr(), caster, true);
}
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const MWMechanics::EffectKey& effect, float magnitude)
bool CastSpell::applyInstantEffect(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, const MWMechanics::EffectKey& effect, float magnitude)
{
short effectId = effect.mId;
if (!target.getClass().isActor())
if (target.getClass().canLock(target))
{
if (effectId == ESM::MagicEffect::Lock)
{
@ -570,8 +570,9 @@ namespace MWMechanics
{
if (caster == MWBase::Environment::get().getWorld()->getPlayerPtr())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicLockSuccess}");
target.getCellRef().setLockLevel(static_cast<int>(magnitude));
target.getClass().lock(target, static_cast<int>(magnitude));
}
return true;
}
else if (effectId == ESM::MagicEffect::Open)
{
@ -586,47 +587,59 @@ namespace MWMechanics
if (caster == MWBase::Environment::get().getWorld()->getPlayerPtr())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicOpenSuccess}");
}
target.getCellRef().setLockLevel(-abs(target.getCellRef().getLockLevel()));
target.getClass().unlock(target);
}
else
MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock Fail", 1.f, 1.f);
return true;
}
}
else
else if (target.getClass().isActor())
{
if (effectId == ESM::MagicEffect::CurePoison)
switch (effectId)
{
case ESM::MagicEffect::CurePoison:
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
else if (effectId == ESM::MagicEffect::CureParalyzation)
return true;
case ESM::MagicEffect::CureParalyzation:
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze);
else if (effectId == ESM::MagicEffect::CureCommonDisease)
return true;
case ESM::MagicEffect::CureCommonDisease:
target.getClass().getCreatureStats(target).getSpells().purgeCommonDisease();
else if (effectId == ESM::MagicEffect::CureBlightDisease)
return true;
case ESM::MagicEffect::CureBlightDisease:
target.getClass().getCreatureStats(target).getSpells().purgeBlightDisease();
else if (effectId == ESM::MagicEffect::CureCorprusDisease)
return true;
case ESM::MagicEffect::CureCorprusDisease:
target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease();
else if (effectId == ESM::MagicEffect::Dispel)
return true;
case ESM::MagicEffect::Dispel:
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude);
else if (effectId == ESM::MagicEffect::RemoveCurse)
return true;
case ESM::MagicEffect::RemoveCurse:
target.getClass().getCreatureStats(target).getSpells().purgeCurses();
return true;
}
if (target != MWBase::Environment::get().getWorld()->getPlayerPtr())
return;
if (!MWBase::Environment::get().getWorld()->isTeleportingEnabled())
return;
return false;
if (effectId == ESM::MagicEffect::DivineIntervention)
{
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "divinemarker");
return true;
}
else if (effectId == ESM::MagicEffect::AlmsiviIntervention)
{
MWBase::Environment::get().getWorld()->teleportToClosestMarker(target, "templemarker");
return true;
}
else if (effectId == ESM::MagicEffect::Mark)
{
MWBase::Environment::get().getWorld()->getPlayer().markPosition(
target.getCell(), target.getRefData().getPosition());
return true;
}
else if (effectId == ESM::MagicEffect::Recall)
{
@ -640,8 +653,10 @@ namespace MWMechanics
markedPosition, false);
action.execute(target);
}
return true;
}
}
return false;
}
@ -926,7 +941,8 @@ namespace MWMechanics
MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr);
MWWorld::ContainerStoreIterator item =
inv.getSlot(slot);
if (item != inv.end())
if (item != inv.end() && (item.getType() == MWWorld::ContainerStore::Type_Armor || item.getType() == MWWorld::ContainerStore::Type_Weapon))
{
if (!item->getClass().hasItemHealth(*item))
return false;

@ -97,7 +97,8 @@ namespace MWMechanics
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false, bool exploded=false);
/// @note \a caster can be any type of object, or even an empty object.
void applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
/// @return was the target suitable for the effect?
bool applyInstantEffect (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const MWMechanics::EffectKey& effect, float magnitude);
};
}

@ -208,6 +208,38 @@ namespace
std::vector<osg::Node*> mToRemove;
};
class RemoveTriBipVisitor : public osg::NodeVisitor
{
public:
RemoveTriBipVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
{
}
virtual void apply(osg::Geode &node)
{
const std::string toFind = "tri bip";
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
{
// Not safe to remove in apply(), since the visitor is still iterating the child list
mToRemove.push_back(&node);
}
}
void remove()
{
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
{
osg::Node* node = *it;
if (node->getNumParents())
node->getParent(0)->removeChild(node);
}
}
private:
std::vector<osg::Node*> mToRemove;
};
}
namespace MWRender
@ -898,7 +930,7 @@ namespace MWRender
return movement;
}
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly)
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature)
{
if (mObjectRoot)
{
@ -933,6 +965,13 @@ namespace MWRender
removeDrawableVisitor.remove();
}
if (isCreature)
{
RemoveTriBipVisitor removeTriBipVisitor;
mObjectRoot->accept(removeTriBipVisitor);
removeTriBipVisitor.remove();
}
NodeMapVisitor visitor;
mObjectRoot->accept(visitor);
mNodeMap = visitor.getNodeMap();
@ -1308,7 +1347,7 @@ namespace MWRender
{
if (!model.empty())
{
setObjectRoot(model, false, false);
setObjectRoot(model, false, false, false);
if (animated)
addAnimSource(model);

@ -273,7 +273,7 @@ protected:
* @param baseonly If true, then any meshes or particle systems in the model are ignored
* (useful for NPCs, where only the skeleton is needed for the root, and the actual NPC parts are then assembled from separate files).
*/
void setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly);
void setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature);
/* Adds the keyframe controllers in the specified model as a new animation source. Note that
* the filename portion of the provided model name will be prepended with 'x', and the .nif

@ -24,7 +24,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr,
if(!model.empty())
{
setObjectRoot(model, false, false);
setObjectRoot(model, false, false, true);
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
addAnimSource("meshes\\xbase_anim.nif");
@ -42,7 +42,7 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const
if(!model.empty())
{
setObjectRoot(model, true, false);
setObjectRoot(model, true, false, true);
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
addAnimSource("meshes\\xbase_anim.nif");

@ -378,7 +378,7 @@ void NpcAnimation::updateNpcBase()
: "meshes\\wolf\\skin.1st.nif");
smodel = Misc::ResourceHelpers::correctActorModelPath(smodel, mResourceSystem->getVFS());
setObjectRoot(smodel, true, true);
setObjectRoot(smodel, true, true, false);
if(mViewMode != VM_FirstPerson)
{

@ -144,6 +144,11 @@ namespace MWWorld
throw std::runtime_error ("class does not support unlocking");
}
bool Class::canLock(const Ptr &ptr) const
{
return false;
}
void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const
{
throw std::runtime_error ("class does not support time-based uses");

@ -161,6 +161,8 @@ namespace MWWorld
virtual void unlock (const Ptr& ptr) const;
///< Unlock object (default implementation: throw an exception)
virtual bool canLock (const Ptr& ptr) const;
virtual void setRemainingUsageTime (const Ptr& ptr, float duration) const;
///< Sets the remaining duration of the object, such as an equippable light
/// source. (default implementation: throw an exception)

@ -228,6 +228,7 @@ namespace MWWorld
if (findExteriorPosition (mStartCell, pos))
{
changeToExteriorCell (pos);
fixPosition(getPlayerPtr());
}
else
{
@ -2623,12 +2624,10 @@ namespace MWWorld
{
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
// Get the target to use for "on touch" effects
// Get the target to use for "on touch" effects, using the facing direction from Head node
MWWorld::Ptr target;
float distance = 192.f; // ??
osg::Vec3f hitPosition = actor.getRefData().getPosition().asVec3();
// For NPCs use facing direction from Head node
osg::Vec3f origin(actor.getRefData().getPosition().asVec3());
MWRender::Animation* anim = mRendering->getAnimation(actor);
@ -2651,13 +2650,33 @@ namespace MWWorld
osg::Vec3f direction = orient * osg::Vec3f(0,1,0);
osg::Vec3f dest = origin + direction * distance;
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(origin, dest, actor);
target = result.mHitObject;
hitPosition = result.mHitPos;
// For actor targets, we want to use bounding boxes (physics raycast).
// This is to give a slight tolerance for errors, especially with creatures like the Skeleton that would be very hard to aim at otherwise.
// For object targets, we want the detailed shapes (rendering raycast).
// If we used the bounding boxes for static objects, then we would not be able to target e.g. objects lying on a shelf.
MWPhysics::PhysicsSystem::RayResult result1 = mPhysics->castRay(origin, dest, actor, MWPhysics::CollisionType_Actor);
MWRender::RenderingManager::RayResult result2 = mRendering->castRay(origin, dest, true, true);
float dist1 = FLT_MAX;
float dist2 = FLT_MAX;
if (result1.mHit)
dist1 = (origin - result1.mHitPos).length();
if (result2.mHit)
dist2 = (origin - result2.mHitPointWorld).length();
// don't allow casting on non-activatable objects
if (!target.isEmpty() && !target.getClass().isActor() && target.getClass().getName(target).empty())
target = MWWorld::Ptr();
if (dist1 <= dist2 && result1.mHit)
{
target = result1.mHitObject;
hitPosition = result1.mHitPos;
}
else if (result2.mHit)
{
target = result2.mHitObject;
hitPosition = result2.mHitPointWorld;
}
std::string selectedSpell = stats.getSpells().getSelectedSpell();

Loading…
Cancel
Save