Refactor NpcAnimation: get rid of delayed update (no longer required), make sure that the Animation is set up *before* the inventory store is accessed anywhere (which now triggers auto equip and animation update). Allows better tracking of magic VFX for permanent enchantments in InventoryStore.

actorid
scrawl 11 years ago
parent 956d8adb99
commit 992a8e9c36

@ -410,13 +410,16 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mVerboseScripts, *mScriptContext)); mVerboseScripts, *mScriptContext));
// Create game mechanics system // Create game mechanics system
mEnvironment.setMechanicsManager (new MWMechanics::MechanicsManager); MWMechanics::MechanicsManager* mechanics = new MWMechanics::MechanicsManager;
mEnvironment.setMechanicsManager (mechanics);
// Create dialog system // Create dialog system
mEnvironment.setJournal (new MWDialogue::Journal); mEnvironment.setJournal (new MWDialogue::Journal);
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage)); mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage));
mEnvironment.getWorld()->renderPlayer(); mEnvironment.getWorld()->renderPlayer();
mechanics->buildPlayer();
window->updatePlayer();
if (!mNewGame) if (!mNewGame)
{ {

@ -254,7 +254,7 @@ namespace MWClass
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{ {
renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr)); renderingInterface.getActors().insertNPC(ptr);
} }
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const

@ -47,8 +47,6 @@ namespace MWGui
, mIngredients (4) , mIngredients (4)
, mSortModel(NULL) , mSortModel(NULL)
{ {
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
getWidget(mCreateButton, "CreateButton"); getWidget(mCreateButton, "CreateButton");
getWidget(mCancelButton, "CancelButton"); getWidget(mCancelButton, "CancelButton");
getWidget(mIngredients[0], "Ingredient1"); getWidget(mIngredients[0], "Ingredient1");
@ -145,6 +143,8 @@ namespace MWGui
void AlchemyWindow::open() void AlchemyWindow::open()
{ {
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
InventoryItemModel* model = new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); InventoryItemModel* model = new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
mSortModel = new SortFilterItemModel(model); mSortModel = new SortFilterItemModel(model);
mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients); mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients);

@ -63,8 +63,6 @@ namespace MWGui
mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected); mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected);
mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &InventoryWindow::onBackgroundSelected); mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &InventoryWindow::onBackgroundSelected);
updatePlayer();
mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged); mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
@ -75,8 +73,6 @@ namespace MWGui
setCoord(mPositionInventory.left, mPositionInventory.top, mPositionInventory.width, mPositionInventory.height); setCoord(mPositionInventory.left, mPositionInventory.top, mPositionInventory.width, mPositionInventory.height);
onWindowResize(static_cast<MyGUI::Window*>(mMainWidget)); onWindowResize(static_cast<MyGUI::Window*>(mMainWidget));
mPreview.setup();
} }
void InventoryWindow::updatePlayer() void InventoryWindow::updatePlayer()

@ -45,7 +45,6 @@ void ItemView::setModel(ItemModel *model)
{ {
delete mModel; delete mModel;
mModel = model; mModel = model;
update();
} }
void ItemView::initialiseOverride() void ItemView::initialiseOverride()

@ -51,8 +51,6 @@ namespace MWGui
setCoord(498, 300, 302, 300); setCoord(498, 300, 302, 300);
updateSpells();
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize); mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize);
} }

@ -246,9 +246,6 @@ namespace MWGui
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::Stat<float>())); mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::Stat<float>()));
} }
unsetSelectedSpell();
unsetSelectedWeapon();
// Set up visibility // Set up visibility
updateVisible(); updateVisible();
@ -1333,6 +1330,9 @@ namespace MWGui
void WindowManager::updatePlayer() void WindowManager::updatePlayer()
{ {
unsetSelectedSpell();
unsetSelectedWeapon();
mInventoryWindow->updatePlayer(); mInventoryWindow->updatePlayer();
} }

@ -167,7 +167,7 @@ namespace MWMechanics
: mUpdatePlayer (true), mClassSelected (false), : mUpdatePlayer (true), mClassSelected (false),
mRaceSelected (false) mRaceSelected (false)
{ {
buildPlayer(); //buildPlayer no longer here, needs to be done explicitely after all subsystems are up and running
} }
void MechanicsManager::add(const MWWorld::Ptr& ptr) void MechanicsManager::add(const MWWorld::Ptr& ptr)

@ -33,12 +33,12 @@ namespace MWMechanics
Objects mObjects; Objects mObjects;
Actors mActors; Actors mActors;
public:
void buildPlayer(); void buildPlayer();
///< build player according to stored class/race/birthsign information. Will ///< build player according to stored class/race/birthsign information. Will
/// default to the values of the ESM::NPC object, if no explicit information is given. /// default to the values of the ESM::NPC object, if no explicit information is given.
public:
MechanicsManager(); MechanicsManager();
virtual void add (const MWWorld::Ptr& ptr); virtual void add (const MWWorld::Ptr& ptr);

@ -68,13 +68,16 @@ void Actors::insertBegin(const MWWorld::Ptr &ptr)
ptr.getRefData().setBaseNode(insert); ptr.getRefData().setBaseNode(insert);
} }
void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv) void Actors::insertNPC(const MWWorld::Ptr& ptr)
{ {
insertBegin(ptr); insertBegin(ptr);
NpcAnimation* anim = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(), inv, RV_Actors); NpcAnimation* anim = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(), RV_Actors);
delete mAllActors[ptr]; delete mAllActors[ptr];
mAllActors[ptr] = anim; mAllActors[ptr] = anim;
mRendering->addWaterRippleEmitter (ptr); mRendering->addWaterRippleEmitter (ptr);
// Create CustomData, will do autoEquip and trigger animation parts update
ptr.getClass().getInventoryStore(ptr);
} }
void Actors::insertCreature (const MWWorld::Ptr& ptr) void Actors::insertCreature (const MWWorld::Ptr& ptr)
{ {

@ -39,7 +39,7 @@ namespace MWRender
void setRootNode(Ogre::SceneNode* root); void setRootNode(Ogre::SceneNode* root);
void insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv); void insertNPC(const MWWorld::Ptr& ptr);
void insertCreature (const MWWorld::Ptr& ptr); void insertCreature (const MWWorld::Ptr& ptr);
void insertActivator (const MWWorld::Ptr& ptr); void insertActivator (const MWWorld::Ptr& ptr);
bool deleteObject (const MWWorld::Ptr& ptr); bool deleteObject (const MWWorld::Ptr& ptr);

@ -70,8 +70,9 @@ namespace MWRender
mNode = renderRoot->createChildSceneNode(); mNode = renderRoot->createChildSceneNode();
mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter), mAnimation = new NpcAnimation(mCharacter, mNode,
0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); 0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
mAnimation->updateParts();
Ogre::Vector3 scale = mNode->getScale(); Ogre::Vector3 scale = mNode->getScale();
mCamera->setPosition(mPosition * scale); mCamera->setPosition(mPosition * scale);
@ -112,10 +113,9 @@ namespace MWRender
{ {
assert(mAnimation); assert(mAnimation);
delete mAnimation; delete mAnimation;
mAnimation = 0; mAnimation = new NpcAnimation(mCharacter, mNode,
mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter),
0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); 0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
mAnimation->updateParts();
float scale=1.f; float scale=1.f;
MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale); MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale);
@ -193,7 +193,7 @@ namespace MWRender
else if(mAnimation->getInfo("torch")) else if(mAnimation->getInfo("torch"))
mAnimation->disable("torch"); mAnimation->disable("torch");
mAnimation->updateParts(true); mAnimation->updateParts();
mAnimation->runAnimation(0.0f); mAnimation->runAnimation(0.0f);
mViewport->setDimensions (0, 0, std::min(1.f, float(sizeX) / float(512)), std::min(1.f, float(sizeY) / float(1024))); mViewport->setDimensions (0, 0, std::min(1.f, float(sizeX) / float(512)), std::min(1.f, float(sizeY) / float(1024)));

@ -64,25 +64,11 @@ NpcAnimation::~NpcAnimation()
} }
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& inv, int visibilityFlags, ViewMode viewMode) NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, ViewMode viewMode)
: Animation(ptr, node), : Animation(ptr, node),
mStateID(-1), mStateID(-1),
mTimeToChange(0),
mVisibilityFlags(visibilityFlags), mVisibilityFlags(visibilityFlags),
mRobe(inv.end()),
mHelmet(inv.end()),
mShirt(inv.end()),
mCuirass(inv.end()),
mGreaves(inv.end()),
mPauldronL(inv.end()),
mPauldronR(inv.end()),
mBoots(inv.end()),
mPants(inv.end()),
mGloveL(inv.end()),
mGloveR(inv.end()),
mSkirtIter(inv.end()),
mWeapon(inv.end()),
mShield(inv.end()),
mViewMode(viewMode), mViewMode(viewMode),
mShowWeapons(false), mShowWeapons(false),
mFirstPersonOffset(0.f, 0.f, 0.f) mFirstPersonOffset(0.f, 0.f, 0.f)
@ -94,8 +80,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
mPartslots[i] = -1; //each slot is empty mPartslots[i] = -1; //each slot is empty
mPartPriorities[i] = 0; mPartPriorities[i] = 0;
} }
updateNpcBase();
} }
void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
@ -173,56 +157,50 @@ void NpcAnimation::updateNpcBase()
for(size_t i = 0;i < ESM::PRT_Count;i++) for(size_t i = 0;i < ESM::PRT_Count;i++)
removeIndividualPart((ESM::PartReferenceType)i); removeIndividualPart((ESM::PartReferenceType)i);
updateParts(true); updateParts();
} }
void NpcAnimation::updateParts(bool forceupdate) void NpcAnimation::updateParts()
{ {
if (!mSkelBase)
{
// First update?
updateNpcBase();
return;
}
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr);
static const struct { static const struct {
MWWorld::ContainerStoreIterator NpcAnimation::*mPart;
int mSlot; int mSlot;
int mBasePriority; int mBasePriority;
} slotlist[] = { } slotlist[] = {
// FIXME: Priority is based on the number of reserved slots. There should be a better way. // FIXME: Priority is based on the number of reserved slots. There should be a better way.
{ &NpcAnimation::mRobe, MWWorld::InventoryStore::Slot_Robe, 12 }, { MWWorld::InventoryStore::Slot_Robe, 12 },
{ &NpcAnimation::mSkirtIter, MWWorld::InventoryStore::Slot_Skirt, 3 }, { MWWorld::InventoryStore::Slot_Skirt, 3 },
{ &NpcAnimation::mHelmet, MWWorld::InventoryStore::Slot_Helmet, 0 }, { MWWorld::InventoryStore::Slot_Helmet, 0 },
{ &NpcAnimation::mCuirass, MWWorld::InventoryStore::Slot_Cuirass, 0 }, { MWWorld::InventoryStore::Slot_Cuirass, 0 },
{ &NpcAnimation::mGreaves, MWWorld::InventoryStore::Slot_Greaves, 0 }, { MWWorld::InventoryStore::Slot_Greaves, 0 },
{ &NpcAnimation::mPauldronL, MWWorld::InventoryStore::Slot_LeftPauldron, 0 }, { MWWorld::InventoryStore::Slot_LeftPauldron, 0 },
{ &NpcAnimation::mPauldronR, MWWorld::InventoryStore::Slot_RightPauldron, 0 }, { MWWorld::InventoryStore::Slot_RightPauldron, 0 },
{ &NpcAnimation::mBoots, MWWorld::InventoryStore::Slot_Boots, 0 }, { MWWorld::InventoryStore::Slot_Boots, 0 },
{ &NpcAnimation::mGloveL, MWWorld::InventoryStore::Slot_LeftGauntlet, 0 }, { MWWorld::InventoryStore::Slot_LeftGauntlet, 0 },
{ &NpcAnimation::mGloveR, MWWorld::InventoryStore::Slot_RightGauntlet, 0 }, { MWWorld::InventoryStore::Slot_RightGauntlet, 0 },
{ &NpcAnimation::mShirt, MWWorld::InventoryStore::Slot_Shirt, 0 }, { MWWorld::InventoryStore::Slot_Shirt, 0 },
{ &NpcAnimation::mPants, MWWorld::InventoryStore::Slot_Pants, 0 }, { MWWorld::InventoryStore::Slot_Pants, 0 },
{ &NpcAnimation::mShield, MWWorld::InventoryStore::Slot_CarriedLeft, 0 }, { MWWorld::InventoryStore::Slot_CarriedLeft, 0 },
{ &NpcAnimation::mWeapon, MWWorld::InventoryStore::Slot_CarriedRight, 0 } { MWWorld::InventoryStore::Slot_CarriedRight, 0 }
}; };
static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]); static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]);
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr);
for(size_t i = 0;!forceupdate && i < slotlistsize;i++)
{
MWWorld::ContainerStoreIterator iter = inv.getSlot(slotlist[i].mSlot);
if(this->*slotlist[i].mPart != iter)
{
forceupdate = true;
break;
}
}
if(!forceupdate)
return;
for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++)
{ {
MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot); MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot);
this->*slotlist[i].mPart = store;
removePartGroup(slotlist[i].mSlot); removePartGroup(slotlist[i].mSlot);
if(this->*slotlist[i].mPart == inv.end()) if(store == inv.end())
continue; continue;
if(slotlist[i].mSlot == MWWorld::InventoryStore::Slot_Helmet) if(slotlist[i].mSlot == MWWorld::InventoryStore::Slot_Helmet)
@ -439,13 +417,6 @@ NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, in
Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
{ {
if(mTimeToChange <= 0.0f)
{
mTimeToChange = 0.2f;
updateParts();
}
mTimeToChange -= timepassed;
Ogre::Vector3 ret = Animation::runAnimation(timepassed); Ogre::Vector3 ret = Animation::runAnimation(timepassed);
Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
@ -599,11 +570,10 @@ void NpcAnimation::showWeapons(bool showWeapon)
if(showWeapon) if(showWeapon)
{ {
MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr); MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
mWeapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if(mWeapon != inv.end()) // special case for weapons if(weapon != inv.end()) // special case for weapons
{ {
MWWorld::Ptr weapon = *mWeapon; std::string mesh = MWWorld::Class::get(*weapon).getModel(*weapon);
std::string mesh = MWWorld::Class::get(weapon).getModel(weapon);
addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1, mesh); addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1, mesh);
} }
} }

@ -43,22 +43,6 @@ private:
ViewMode mViewMode; ViewMode mViewMode;
bool mShowWeapons; bool mShowWeapons;
float mTimeToChange;
MWWorld::ContainerStoreIterator mRobe;
MWWorld::ContainerStoreIterator mHelmet;
MWWorld::ContainerStoreIterator mShirt;
MWWorld::ContainerStoreIterator mCuirass;
MWWorld::ContainerStoreIterator mGreaves;
MWWorld::ContainerStoreIterator mPauldronL;
MWWorld::ContainerStoreIterator mPauldronR;
MWWorld::ContainerStoreIterator mBoots;
MWWorld::ContainerStoreIterator mPants;
MWWorld::ContainerStoreIterator mGloveL;
MWWorld::ContainerStoreIterator mGloveR;
MWWorld::ContainerStoreIterator mSkirtIter;
MWWorld::ContainerStoreIterator mWeapon;
MWWorld::ContainerStoreIterator mShield;
int mVisibilityFlags; int mVisibilityFlags;
int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty
@ -78,8 +62,7 @@ private:
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts); void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts);
public: public:
NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags,
MWWorld::InventoryStore& inv, int visibilityFlags,
ViewMode viewMode=VM_Normal); ViewMode viewMode=VM_Normal);
virtual ~NpcAnimation(); virtual ~NpcAnimation();
@ -89,7 +72,7 @@ public:
void setViewMode(ViewMode viewMode); void setViewMode(ViewMode viewMode);
void updateParts(bool forceupdate = false); void updateParts();
/// \brief Applies a translation to the arms and hands. /// \brief Applies a translation to the arms and hands.
/// This may be called multiple times before the animation /// This may be called multiple times before the animation

@ -336,6 +336,7 @@ void RenderingManager::updateAnimParts(const MWWorld::Ptr& ptr)
else if(MWWorld::Class::get(ptr).isActor()) else if(MWWorld::Class::get(ptr).isActor())
anim = dynamic_cast<NpcAnimation*>(mActors.getAnimation(ptr)); anim = dynamic_cast<NpcAnimation*>(mActors.getAnimation(ptr));
assert(anim);
if(anim) if(anim)
anim->updateParts(); anim->updateParts();
} }
@ -926,18 +927,17 @@ void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr)
{ {
if(!mPlayerAnimation) if(!mPlayerAnimation)
{ {
mPlayerAnimation = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(), mPlayerAnimation = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(), RV_Actors);
MWWorld::Class::get(ptr).getInventoryStore(ptr),
RV_Actors);
} }
else else
{ {
// Reconstruct the NpcAnimation in-place // Reconstruct the NpcAnimation in-place
mPlayerAnimation->~NpcAnimation(); mPlayerAnimation->~NpcAnimation();
new(mPlayerAnimation) NpcAnimation(ptr, ptr.getRefData().getBaseNode(), new(mPlayerAnimation) NpcAnimation(ptr, ptr.getRefData().getBaseNode(), RV_Actors);
MWWorld::Class::get(ptr).getInventoryStore(ptr),
RV_Actors);
} }
// Ensure CustomData -> autoEquip -> animation update
ptr.getClass().getInventoryStore(ptr);
mCamera->setAnimation(mPlayerAnimation); mCamera->setAnimation(mPlayerAnimation);
mWater->removeEmitter(ptr); mWater->removeEmitter(ptr);
mWater->addEmitter(ptr); mWater->addEmitter(ptr);

@ -45,6 +45,7 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots_)
MWWorld::InventoryStore::InventoryStore() MWWorld::InventoryStore::InventoryStore()
: mSelectedEnchantItem(end()) : mSelectedEnchantItem(end())
, mUpdatesEnabled (true) , mUpdatesEnabled (true)
, mFirstAutoEquip(true)
{ {
initSlots (mSlots); initSlots (mSlots);
} }
@ -54,6 +55,7 @@ MWWorld::InventoryStore::InventoryStore (const InventoryStore& store)
, mSelectedEnchantItem(end()) , mSelectedEnchantItem(end())
{ {
mMagicEffects = store.mMagicEffects; mMagicEffects = store.mMagicEffects;
mFirstAutoEquip = store.mFirstAutoEquip;
mSelectedEnchantItem = store.mSelectedEnchantItem; mSelectedEnchantItem = store.mSelectedEnchantItem;
mPermanentMagicEffectMagnitudes = store.mPermanentMagicEffectMagnitudes; mPermanentMagicEffectMagnitudes = store.mPermanentMagicEffectMagnitudes;
copySlots (store); copySlots (store);
@ -62,6 +64,7 @@ MWWorld::InventoryStore::InventoryStore (const InventoryStore& store)
MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStore& store) MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStore& store)
{ {
mMagicEffects = store.mMagicEffects; mMagicEffects = store.mMagicEffects;
mFirstAutoEquip = store.mFirstAutoEquip;
mPermanentMagicEffectMagnitudes = store.mPermanentMagicEffectMagnitudes; mPermanentMagicEffectMagnitudes = store.mPermanentMagicEffectMagnitudes;
ContainerStore::operator= (store); ContainerStore::operator= (store);
mSlots.clear(); mSlots.clear();
@ -256,6 +259,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc)
updateMagicEffects(npc); updateMagicEffects(npc);
flagAsModified(); flagAsModified();
} }
mFirstAutoEquip = false;
} }
const MWMechanics::MagicEffects& MWWorld::InventoryStore::getMagicEffects() const const MWMechanics::MagicEffects& MWWorld::InventoryStore::getMagicEffects() const
@ -308,8 +312,10 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor)
// so it doesn't really matter if both items will get the same magnitude. *Extreme* edge case. // so it doesn't really matter if both items will get the same magnitude. *Extreme* edge case.
mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID] = random; mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID] = random;
// TODO: What do we do if no animation yet? // During first auto equip, we don't play any sounds.
if (MWBase::Environment::get().getWorld()->getAnimation(actor)) // Basically we don't want sounds when the actor is first loaded,
// the items should appear as if they'd always been equipped.
if (!mFirstAutoEquip)
{ {
// Only the sound of the first effect plays // Only the sound of the first effect plays
if (effectIt == enchantment.mEffects.mList.begin()) if (effectIt == enchantment.mEffects.mList.begin())
@ -324,13 +330,15 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor)
else else
sndMgr->playSound3D(actor, schools[magicEffect->mData.mSchool]+" hit", 1.0f, 1.0f); sndMgr->playSound3D(actor, schools[magicEffect->mData.mSchool]+" hit", 1.0f, 1.0f);
} }
}
if (!magicEffect->mHit.empty()) if (!magicEffect->mHit.empty())
{ {
const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit); const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx; bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx;
// Similar as above, we don't want particles during first autoequip either, unless they're continuous.
if (!mFirstAutoEquip || loop)
MWBase::Environment::get().getWorld()->getAnimation(actor)->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, ""); MWBase::Environment::get().getWorld()->getAnimation(actor)->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "");
}
} }
} }

@ -49,6 +49,8 @@ namespace MWWorld
// This is disabled during autoequip to avoid excessive updates // This is disabled during autoequip to avoid excessive updates
bool mUpdatesEnabled; bool mUpdatesEnabled;
bool mFirstAutoEquip;
// Vanilla allows permanent effects with a random magnitude, so it needs to be stored here. // Vanilla allows permanent effects with a random magnitude, so it needs to be stored here.
// We also need this to only play sounds and particle effects when the item is equipped, rather than on every update. // We also need this to only play sounds and particle effects when the item is equipped, rather than on every update.
typedef std::map<std::string, std::vector<float> > TEffectMagnitudes; typedef std::map<std::string, std::vector<float> > TEffectMagnitudes;

@ -118,8 +118,6 @@ namespace MWWorld
void Scene::loadCell (Ptr::CellStore *cell, Loading::Listener* loadingListener) void Scene::loadCell (Ptr::CellStore *cell, Loading::Listener* loadingListener)
{ {
// register local scripts
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
std::pair<CellStoreCollection::iterator, bool> result = mActiveCells.insert(cell); std::pair<CellStoreCollection::iterator, bool> result = mActiveCells.insert(cell);
if(result.second) if(result.second)
@ -157,6 +155,10 @@ namespace MWWorld
mRendering.requestMap(cell); mRendering.requestMap(cell);
mRendering.configureAmbient(*cell); mRendering.configureAmbient(*cell);
} }
// register local scripts
// ??? Should this go into the above if block ???
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
} }
void Scene::playerCellChange(MWWorld::CellStore *cell, const ESM::Position& pos, bool adjustPlayerPos) void Scene::playerCellChange(MWWorld::CellStore *cell, const ESM::Position& pos, bool adjustPlayerPos)

@ -2239,7 +2239,6 @@ namespace MWWorld
void World::updateAnimParts(const Ptr& actor) void World::updateAnimParts(const Ptr& actor)
{ {
if (actor.mCell && actor.mCell == mWorldScene->getCurrentCell()) mRendering->updateAnimParts(actor);
mRendering->updateAnimParts(actor);
} }
} }

Loading…
Cancel
Save