mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-02 19:15:33 +00:00
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.
This commit is contained in:
parent
956d8adb99
commit
992a8e9c36
19 changed files with 86 additions and 123 deletions
|
@ -410,13 +410,16 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
mVerboseScripts, *mScriptContext));
|
||||
|
||||
// Create game mechanics system
|
||||
mEnvironment.setMechanicsManager (new MWMechanics::MechanicsManager);
|
||||
MWMechanics::MechanicsManager* mechanics = new MWMechanics::MechanicsManager;
|
||||
mEnvironment.setMechanicsManager (mechanics);
|
||||
|
||||
// Create dialog system
|
||||
mEnvironment.setJournal (new MWDialogue::Journal);
|
||||
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage));
|
||||
|
||||
mEnvironment.getWorld()->renderPlayer();
|
||||
mechanics->buildPlayer();
|
||||
window->updatePlayer();
|
||||
|
||||
if (!mNewGame)
|
||||
{
|
||||
|
|
|
@ -254,7 +254,7 @@ namespace MWClass
|
|||
|
||||
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
|
||||
|
|
|
@ -47,8 +47,6 @@ namespace MWGui
|
|||
, mIngredients (4)
|
||||
, mSortModel(NULL)
|
||||
{
|
||||
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
|
||||
getWidget(mCreateButton, "CreateButton");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
getWidget(mIngredients[0], "Ingredient1");
|
||||
|
@ -145,6 +143,8 @@ namespace MWGui
|
|||
|
||||
void AlchemyWindow::open()
|
||||
{
|
||||
mAlchemy.setAlchemist (MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
|
||||
InventoryItemModel* model = new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
mSortModel = new SortFilterItemModel(model);
|
||||
mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients);
|
||||
|
|
|
@ -63,8 +63,6 @@ namespace MWGui
|
|||
mItemView->eventItemClicked += MyGUI::newDelegate(this, &InventoryWindow::onItemSelected);
|
||||
mItemView->eventBackgroundClicked += MyGUI::newDelegate(this, &InventoryWindow::onBackgroundSelected);
|
||||
|
||||
updatePlayer();
|
||||
|
||||
mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
|
||||
mFilterWeapon->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);
|
||||
onWindowResize(static_cast<MyGUI::Window*>(mMainWidget));
|
||||
|
||||
mPreview.setup();
|
||||
}
|
||||
|
||||
void InventoryWindow::updatePlayer()
|
||||
|
|
|
@ -45,7 +45,6 @@ void ItemView::setModel(ItemModel *model)
|
|||
{
|
||||
delete mModel;
|
||||
mModel = model;
|
||||
update();
|
||||
}
|
||||
|
||||
void ItemView::initialiseOverride()
|
||||
|
|
|
@ -51,8 +51,6 @@ namespace MWGui
|
|||
|
||||
setCoord(498, 300, 302, 300);
|
||||
|
||||
updateSpells();
|
||||
|
||||
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>()));
|
||||
}
|
||||
|
||||
unsetSelectedSpell();
|
||||
unsetSelectedWeapon();
|
||||
|
||||
// Set up visibility
|
||||
updateVisible();
|
||||
|
||||
|
@ -1333,6 +1330,9 @@ namespace MWGui
|
|||
|
||||
void WindowManager::updatePlayer()
|
||||
{
|
||||
unsetSelectedSpell();
|
||||
unsetSelectedWeapon();
|
||||
|
||||
mInventoryWindow->updatePlayer();
|
||||
}
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace MWMechanics
|
|||
: mUpdatePlayer (true), mClassSelected (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)
|
||||
|
|
|
@ -33,12 +33,12 @@ namespace MWMechanics
|
|||
Objects mObjects;
|
||||
Actors mActors;
|
||||
|
||||
public:
|
||||
|
||||
void buildPlayer();
|
||||
///< 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.
|
||||
|
||||
public:
|
||||
|
||||
MechanicsManager();
|
||||
|
||||
virtual void add (const MWWorld::Ptr& ptr);
|
||||
|
|
|
@ -68,13 +68,16 @@ void Actors::insertBegin(const MWWorld::Ptr &ptr)
|
|||
ptr.getRefData().setBaseNode(insert);
|
||||
}
|
||||
|
||||
void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv)
|
||||
void Actors::insertNPC(const MWWorld::Ptr& 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];
|
||||
mAllActors[ptr] = anim;
|
||||
mRendering->addWaterRippleEmitter (ptr);
|
||||
|
||||
// Create CustomData, will do autoEquip and trigger animation parts update
|
||||
ptr.getClass().getInventoryStore(ptr);
|
||||
}
|
||||
void Actors::insertCreature (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace MWRender
|
|||
|
||||
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 insertActivator (const MWWorld::Ptr& ptr);
|
||||
bool deleteObject (const MWWorld::Ptr& ptr);
|
||||
|
|
|
@ -70,8 +70,9 @@ namespace MWRender
|
|||
|
||||
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));
|
||||
mAnimation->updateParts();
|
||||
|
||||
Ogre::Vector3 scale = mNode->getScale();
|
||||
mCamera->setPosition(mPosition * scale);
|
||||
|
@ -112,10 +113,9 @@ namespace MWRender
|
|||
{
|
||||
assert(mAnimation);
|
||||
delete mAnimation;
|
||||
mAnimation = 0;
|
||||
|
||||
mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter),
|
||||
mAnimation = new NpcAnimation(mCharacter, mNode,
|
||||
0, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
|
||||
mAnimation->updateParts();
|
||||
|
||||
float scale=1.f;
|
||||
MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale);
|
||||
|
@ -193,7 +193,7 @@ namespace MWRender
|
|||
else if(mAnimation->getInfo("torch"))
|
||||
mAnimation->disable("torch");
|
||||
|
||||
mAnimation->updateParts(true);
|
||||
mAnimation->updateParts();
|
||||
mAnimation->runAnimation(0.0f);
|
||||
|
||||
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),
|
||||
mStateID(-1),
|
||||
mTimeToChange(0),
|
||||
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),
|
||||
mShowWeapons(false),
|
||||
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
|
||||
mPartPriorities[i] = 0;
|
||||
}
|
||||
|
||||
updateNpcBase();
|
||||
}
|
||||
|
||||
void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
||||
|
@ -173,56 +157,50 @@ void NpcAnimation::updateNpcBase()
|
|||
|
||||
for(size_t i = 0;i < ESM::PRT_Count;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 {
|
||||
MWWorld::ContainerStoreIterator NpcAnimation::*mPart;
|
||||
int mSlot;
|
||||
int mBasePriority;
|
||||
} slotlist[] = {
|
||||
// FIXME: Priority is based on the number of reserved slots. There should be a better way.
|
||||
{ &NpcAnimation::mRobe, MWWorld::InventoryStore::Slot_Robe, 12 },
|
||||
{ &NpcAnimation::mSkirtIter, MWWorld::InventoryStore::Slot_Skirt, 3 },
|
||||
{ &NpcAnimation::mHelmet, MWWorld::InventoryStore::Slot_Helmet, 0 },
|
||||
{ &NpcAnimation::mCuirass, MWWorld::InventoryStore::Slot_Cuirass, 0 },
|
||||
{ &NpcAnimation::mGreaves, MWWorld::InventoryStore::Slot_Greaves, 0 },
|
||||
{ &NpcAnimation::mPauldronL, MWWorld::InventoryStore::Slot_LeftPauldron, 0 },
|
||||
{ &NpcAnimation::mPauldronR, MWWorld::InventoryStore::Slot_RightPauldron, 0 },
|
||||
{ &NpcAnimation::mBoots, MWWorld::InventoryStore::Slot_Boots, 0 },
|
||||
{ &NpcAnimation::mGloveL, MWWorld::InventoryStore::Slot_LeftGauntlet, 0 },
|
||||
{ &NpcAnimation::mGloveR, MWWorld::InventoryStore::Slot_RightGauntlet, 0 },
|
||||
{ &NpcAnimation::mShirt, MWWorld::InventoryStore::Slot_Shirt, 0 },
|
||||
{ &NpcAnimation::mPants, MWWorld::InventoryStore::Slot_Pants, 0 },
|
||||
{ &NpcAnimation::mShield, MWWorld::InventoryStore::Slot_CarriedLeft, 0 },
|
||||
{ &NpcAnimation::mWeapon, MWWorld::InventoryStore::Slot_CarriedRight, 0 }
|
||||
{ MWWorld::InventoryStore::Slot_Robe, 12 },
|
||||
{ MWWorld::InventoryStore::Slot_Skirt, 3 },
|
||||
{ MWWorld::InventoryStore::Slot_Helmet, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_Cuirass, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_Greaves, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_LeftPauldron, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_RightPauldron, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_Boots, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_LeftGauntlet, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_RightGauntlet, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_Shirt, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_Pants, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_CarriedLeft, 0 },
|
||||
{ MWWorld::InventoryStore::Slot_CarriedRight, 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++)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot);
|
||||
|
||||
this->*slotlist[i].mPart = store;
|
||||
removePartGroup(slotlist[i].mSlot);
|
||||
|
||||
if(this->*slotlist[i].mPart == inv.end())
|
||||
if(store == inv.end())
|
||||
continue;
|
||||
|
||||
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)
|
||||
{
|
||||
if(mTimeToChange <= 0.0f)
|
||||
{
|
||||
mTimeToChange = 0.2f;
|
||||
updateParts();
|
||||
}
|
||||
mTimeToChange -= timepassed;
|
||||
|
||||
Ogre::Vector3 ret = Animation::runAnimation(timepassed);
|
||||
|
||||
Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
||||
|
@ -599,11 +570,10 @@ void NpcAnimation::showWeapons(bool showWeapon)
|
|||
if(showWeapon)
|
||||
{
|
||||
MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
mWeapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
if(mWeapon != inv.end()) // special case for weapons
|
||||
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,22 +43,6 @@ private:
|
|||
ViewMode mViewMode;
|
||||
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 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);
|
||||
|
||||
public:
|
||||
NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node,
|
||||
MWWorld::InventoryStore& inv, int visibilityFlags,
|
||||
NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags,
|
||||
ViewMode viewMode=VM_Normal);
|
||||
virtual ~NpcAnimation();
|
||||
|
||||
|
@ -89,7 +72,7 @@ public:
|
|||
|
||||
void setViewMode(ViewMode viewMode);
|
||||
|
||||
void updateParts(bool forceupdate = false);
|
||||
void updateParts();
|
||||
|
||||
/// \brief Applies a translation to the arms and hands.
|
||||
/// 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())
|
||||
anim = dynamic_cast<NpcAnimation*>(mActors.getAnimation(ptr));
|
||||
|
||||
assert(anim);
|
||||
if(anim)
|
||||
anim->updateParts();
|
||||
}
|
||||
|
@ -926,18 +927,17 @@ void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr)
|
|||
{
|
||||
if(!mPlayerAnimation)
|
||||
{
|
||||
mPlayerAnimation = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(),
|
||||
MWWorld::Class::get(ptr).getInventoryStore(ptr),
|
||||
RV_Actors);
|
||||
mPlayerAnimation = new NpcAnimation(ptr, ptr.getRefData().getBaseNode(), RV_Actors);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reconstruct the NpcAnimation in-place
|
||||
mPlayerAnimation->~NpcAnimation();
|
||||
new(mPlayerAnimation) NpcAnimation(ptr, ptr.getRefData().getBaseNode(),
|
||||
MWWorld::Class::get(ptr).getInventoryStore(ptr),
|
||||
RV_Actors);
|
||||
new(mPlayerAnimation) NpcAnimation(ptr, ptr.getRefData().getBaseNode(), RV_Actors);
|
||||
}
|
||||
// Ensure CustomData -> autoEquip -> animation update
|
||||
ptr.getClass().getInventoryStore(ptr);
|
||||
|
||||
mCamera->setAnimation(mPlayerAnimation);
|
||||
mWater->removeEmitter(ptr);
|
||||
mWater->addEmitter(ptr);
|
||||
|
|
|
@ -45,6 +45,7 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots_)
|
|||
MWWorld::InventoryStore::InventoryStore()
|
||||
: mSelectedEnchantItem(end())
|
||||
, mUpdatesEnabled (true)
|
||||
, mFirstAutoEquip(true)
|
||||
{
|
||||
initSlots (mSlots);
|
||||
}
|
||||
|
@ -54,6 +55,7 @@ MWWorld::InventoryStore::InventoryStore (const InventoryStore& store)
|
|||
, mSelectedEnchantItem(end())
|
||||
{
|
||||
mMagicEffects = store.mMagicEffects;
|
||||
mFirstAutoEquip = store.mFirstAutoEquip;
|
||||
mSelectedEnchantItem = store.mSelectedEnchantItem;
|
||||
mPermanentMagicEffectMagnitudes = store.mPermanentMagicEffectMagnitudes;
|
||||
copySlots (store);
|
||||
|
@ -62,6 +64,7 @@ MWWorld::InventoryStore::InventoryStore (const InventoryStore& store)
|
|||
MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStore& store)
|
||||
{
|
||||
mMagicEffects = store.mMagicEffects;
|
||||
mFirstAutoEquip = store.mFirstAutoEquip;
|
||||
mPermanentMagicEffectMagnitudes = store.mPermanentMagicEffectMagnitudes;
|
||||
ContainerStore::operator= (store);
|
||||
mSlots.clear();
|
||||
|
@ -256,6 +259,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc)
|
|||
updateMagicEffects(npc);
|
||||
flagAsModified();
|
||||
}
|
||||
mFirstAutoEquip = false;
|
||||
}
|
||||
|
||||
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.
|
||||
mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID] = random;
|
||||
|
||||
// TODO: What do we do if no animation yet?
|
||||
if (MWBase::Environment::get().getWorld()->getAnimation(actor))
|
||||
// During first auto equip, we don't play any sounds.
|
||||
// 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
|
||||
if (effectIt == enchantment.mEffects.mList.begin())
|
||||
|
@ -324,13 +330,15 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor)
|
|||
else
|
||||
sndMgr->playSound3D(actor, schools[magicEffect->mData.mSchool]+" hit", 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (!magicEffect->mHit.empty())
|
||||
{
|
||||
const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
|
||||
bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx;
|
||||
if (!magicEffect->mHit.empty())
|
||||
{
|
||||
const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
|
||||
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, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace MWWorld
|
|||
// This is disabled during autoequip to avoid excessive updates
|
||||
bool mUpdatesEnabled;
|
||||
|
||||
bool mFirstAutoEquip;
|
||||
|
||||
// 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.
|
||||
typedef std::map<std::string, std::vector<float> > TEffectMagnitudes;
|
||||
|
|
|
@ -118,8 +118,6 @@ namespace MWWorld
|
|||
|
||||
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);
|
||||
|
||||
if(result.second)
|
||||
|
@ -157,6 +155,10 @@ namespace MWWorld
|
|||
mRendering.requestMap(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)
|
||||
|
|
|
@ -2239,7 +2239,6 @@ namespace MWWorld
|
|||
|
||||
void World::updateAnimParts(const Ptr& actor)
|
||||
{
|
||||
if (actor.mCell && actor.mCell == mWorldScene->getCurrentCell())
|
||||
mRendering->updateAnimParts(actor);
|
||||
mRendering->updateAnimParts(actor);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue