mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-03 21:45:34 +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));
|
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…
Reference in a new issue