forked from mirror/openmw-tes3mp
Merge pull request #59 from OpenMW/master
Add OpenMW commits up to 18 Sep
This commit is contained in:
commit
79c561057c
18 changed files with 114 additions and 38 deletions
|
@ -91,15 +91,17 @@ namespace MWGui
|
||||||
|
|
||||||
if (mSaveList->getItemCount() == 0)
|
if (mSaveList->getItemCount() == 0)
|
||||||
{
|
{
|
||||||
// The character might be deleted now
|
|
||||||
size_t previousIndex = mCharacterSelection->getIndexSelected();
|
size_t previousIndex = mCharacterSelection->getIndexSelected();
|
||||||
open();
|
mCurrentCharacter = NULL;
|
||||||
|
mCharacterSelection->removeItemAt(previousIndex);
|
||||||
if (mCharacterSelection->getItemCount())
|
if (mCharacterSelection->getItemCount())
|
||||||
{
|
{
|
||||||
size_t nextCharacter = std::min(previousIndex, mCharacterSelection->getItemCount()-1);
|
size_t nextCharacter = std::min(previousIndex, mCharacterSelection->getItemCount()-1);
|
||||||
mCharacterSelection->setIndexSelected(nextCharacter);
|
mCharacterSelection->setIndexSelected(nextCharacter);
|
||||||
onCharacterSelected(mCharacterSelection, nextCharacter);
|
onCharacterSelected(mCharacterSelection, nextCharacter);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
fillSaveList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1236,9 +1236,7 @@ bool CharacterController::updateWeaponState()
|
||||||
cast.playSpellCastingEffects(spellid);
|
cast.playSpellCastingEffects(spellid);
|
||||||
|
|
||||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||||
|
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back();
|
||||||
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.at(spell->mEffects.mList.size() - 1);
|
|
||||||
|
|
||||||
const ESM::MagicEffect *effect;
|
const ESM::MagicEffect *effect;
|
||||||
|
|
||||||
effect = store.get<ESM::MagicEffect>().find(lastEffect.mEffectID); // use last effect of list for color of VFX_Hands
|
effect = store.get<ESM::MagicEffect>().find(lastEffect.mEffectID); // use last effect of list for color of VFX_Hands
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
|
||||||
ESM::Skill::SkillEnum spellSchoolToSkill(int school)
|
ESM::Skill::SkillEnum spellSchoolToSkill(int school)
|
||||||
{
|
{
|
||||||
std::map<int, ESM::Skill::SkillEnum> schoolSkillMap; // maps spell school to skill id
|
std::map<int, ESM::Skill::SkillEnum> schoolSkillMap; // maps spell school to skill id
|
||||||
|
@ -544,12 +543,14 @@ namespace MWMechanics
|
||||||
else
|
else
|
||||||
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_DefaultHit");
|
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_DefaultHit");
|
||||||
|
|
||||||
|
std::string texture = magicEffect->mParticle;
|
||||||
|
|
||||||
// TODO: VFX are no longer active after saving/reloading the game
|
// TODO: VFX are no longer active after saving/reloading the game
|
||||||
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
||||||
// Note: in case of non actor, a free effect should be fine as well
|
// Note: in case of non actor, a free effect should be fine as well
|
||||||
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||||
if (anim)
|
if (anim)
|
||||||
anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "");
|
anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "", texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -958,15 +959,18 @@ namespace MWMechanics
|
||||||
|
|
||||||
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
|
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster);
|
||||||
|
|
||||||
if (mCaster.getClass().isActor()) // TODO: Non-actors (except for large statics?) should also create a spell cast vfx
|
if (mCaster.getClass().isActor()) // TODO: Non-actors should also create a spell cast vfx
|
||||||
{
|
{
|
||||||
const ESM::Static* castStatic;
|
const ESM::Static* castStatic;
|
||||||
|
|
||||||
if (!effect->mCasting.empty())
|
if (!effect->mCasting.empty())
|
||||||
castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
castStatic = store.get<ESM::Static>().find (effect->mCasting);
|
||||||
else
|
else
|
||||||
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
|
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
|
||||||
|
|
||||||
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex);
|
std::string texture = effect->mParticle;
|
||||||
|
|
||||||
|
animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mCaster.getClass().isActor())
|
if (!mCaster.getClass().isActor())
|
||||||
|
|
|
@ -1342,7 +1342,7 @@ namespace MWRender
|
||||||
SceneUtil::AssignControllerSourcesVisitor assignVisitor(boost::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
|
SceneUtil::AssignControllerSourcesVisitor assignVisitor(boost::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
|
||||||
node->accept(assignVisitor);
|
node->accept(assignVisitor);
|
||||||
|
|
||||||
overrideTexture(texture, mResourceSystem, node);
|
overrideFirstRootTexture(texture, mResourceSystem, node);
|
||||||
|
|
||||||
// TODO: in vanilla morrowind the effect is scaled based on the host object's bounding box.
|
// TODO: in vanilla morrowind the effect is scaled based on the host object's bounding box.
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ EffectManager::~EffectManager()
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectManager::addEffect(const std::string &model, const std::string& textureOverride, const osg::Vec3f &worldPosition, float scale)
|
void EffectManager::addEffect(const std::string &model, const std::string& textureOverride, const osg::Vec3f &worldPosition, float scale, bool isMagicVFX)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model);
|
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model);
|
||||||
|
|
||||||
|
@ -46,6 +46,9 @@ void EffectManager::addEffect(const std::string &model, const std::string& textu
|
||||||
SceneUtil::AssignControllerSourcesVisitor assignVisitor(effect.mAnimTime);
|
SceneUtil::AssignControllerSourcesVisitor assignVisitor(effect.mAnimTime);
|
||||||
node->accept(assignVisitor);
|
node->accept(assignVisitor);
|
||||||
|
|
||||||
|
if (isMagicVFX)
|
||||||
|
overrideFirstRootTexture(textureOverride, mResourceSystem, node);
|
||||||
|
else
|
||||||
overrideTexture(textureOverride, mResourceSystem, node);
|
overrideTexture(textureOverride, mResourceSystem, node);
|
||||||
|
|
||||||
mParentNode->addChild(trans);
|
mParentNode->addChild(trans);
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace MWRender
|
||||||
~EffectManager();
|
~EffectManager();
|
||||||
|
|
||||||
/// Add an effect. When it's finished playing, it will be removed automatically.
|
/// Add an effect. When it's finished playing, it will be removed automatically.
|
||||||
void addEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPosition, float scale);
|
void addEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPosition, float scale, bool isMagicVFX = true);
|
||||||
|
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
|
|
||||||
|
|
|
@ -970,12 +970,12 @@ Resource::ResourceSystem* NpcAnimation::getResourceSystem()
|
||||||
return mResourceSystem;
|
return mResourceSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound)
|
void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew)
|
||||||
{
|
{
|
||||||
// During first auto equip, we don't play any sounds.
|
// During first auto equip, we don't play any sounds.
|
||||||
// Basically we don't want sounds when the actor is first loaded,
|
// Basically we don't want sounds when the actor is first loaded,
|
||||||
// the items should appear as if they'd always been equipped.
|
// the items should appear as if they'd always been equipped.
|
||||||
if (playSound)
|
if (isNew)
|
||||||
{
|
{
|
||||||
static const std::string schools[] = {
|
static const std::string schools[] = {
|
||||||
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
||||||
|
@ -994,7 +994,7 @@ void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, boo
|
||||||
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
||||||
// Don't play particle VFX unless the effect is new or it should be looping.
|
// Don't play particle VFX unless the effect is new or it should be looping.
|
||||||
if (isNew || loop)
|
if (isNew || loop)
|
||||||
addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "");
|
addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "", magicEffect->mParticle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::I
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void equipmentChanged();
|
virtual void equipmentChanged();
|
||||||
virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound);
|
virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::map<ESM::PartReferenceType,std::string> PartBoneMap;
|
typedef std::map<ESM::PartReferenceType,std::string> PartBoneMap;
|
||||||
|
|
|
@ -742,9 +742,9 @@ namespace MWRender
|
||||||
mObjects->updatePtr(old, updated);
|
mObjects->updatePtr(old, updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale)
|
void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale, bool isMagicVFX)
|
||||||
{
|
{
|
||||||
mEffectManager->addEffect(model, texture, worldPosition, scale);
|
mEffectManager->addEffect(model, texture, worldPosition, scale, isMagicVFX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::notifyWorldSpaceChanged()
|
void RenderingManager::notifyWorldSpaceChanged()
|
||||||
|
|
|
@ -138,7 +138,7 @@ namespace MWRender
|
||||||
|
|
||||||
SkyManager* getSkyManager();
|
SkyManager* getSkyManager();
|
||||||
|
|
||||||
void spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale = 1.f);
|
void spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale = 1.f, bool isMagicVFX = true);
|
||||||
|
|
||||||
/// Clear all savegame-specific data
|
/// Clear all savegame-specific data
|
||||||
void clear();
|
void clear();
|
||||||
|
|
|
@ -1,14 +1,47 @@
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
|
#include <osg/ValueObject>
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
#include <components/sceneutil/visitor.hpp>
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class TextureOverrideVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextureOverrideVisitor(std::string texture, Resource::ResourceSystem* resourcesystem)
|
||||||
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
|
, mTexture(texture)
|
||||||
|
, mResourcesystem(resourcesystem)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Node& node)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
osg::ref_ptr<osg::Node> nodePtr(&node);
|
||||||
|
if (node.getUserValue("overrideFx", index))
|
||||||
|
{
|
||||||
|
if (index == 1)
|
||||||
|
overrideTexture(mTexture, mResourcesystem, nodePtr);
|
||||||
|
}
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
std::string mTexture;
|
||||||
|
Resource::ResourceSystem* mResourcesystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
void overrideFirstRootTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node)
|
||||||
|
{
|
||||||
|
TextureOverrideVisitor overrideVisitor(texture, resourceSystem);
|
||||||
|
node->accept(overrideVisitor);
|
||||||
|
}
|
||||||
|
|
||||||
void overrideTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node)
|
void overrideTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node)
|
||||||
{
|
{
|
||||||
if (texture.empty())
|
if (texture.empty())
|
||||||
|
|
|
@ -17,6 +17,10 @@ namespace Resource
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
// Overrides the texture of nodes in the mesh that had the same NiTexturingProperty as the first NiTexturingProperty of the .NIF file's root node,
|
||||||
|
// if it had a NiTexturingProperty. Used for applying "particle textures" to magic effects.
|
||||||
|
void overrideFirstRootTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node);
|
||||||
|
|
||||||
void overrideTexture(const std::string& texture, Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Node> node);
|
void overrideTexture(const std::string& texture, Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Node> node);
|
||||||
|
|
||||||
// Node callback to entirely skip the traversal.
|
// Node callback to entirely skip the traversal.
|
||||||
|
|
|
@ -414,8 +414,7 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor)
|
||||||
// During first auto equip, we don't play any sounds.
|
// During first auto equip, we don't play any sounds.
|
||||||
// Basically we don't want sounds when the actor is first loaded,
|
// Basically we don't want sounds when the actor is first loaded,
|
||||||
// the items should appear as if they'd always been equipped.
|
// the items should appear as if they'd always been equipped.
|
||||||
mListener->permanentEffectAdded(magicEffect, !mFirstAutoEquip,
|
mListener->permanentEffectAdded(magicEffect, !mFirstAutoEquip);
|
||||||
!mFirstAutoEquip && effectIt == enchantment.mEffects.mList.begin());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (magnitude)
|
if (magnitude)
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace MWWorld
|
||||||
* If it isn't new, non-looping VFX should not be played.
|
* If it isn't new, non-looping VFX should not be played.
|
||||||
* @param playSound Play effect sound?
|
* @param playSound Play effect sound?
|
||||||
*/
|
*/
|
||||||
virtual void permanentEffectAdded (const ESM::MagicEffect *magicEffect, bool isNew, bool playSound) {}
|
virtual void permanentEffectAdded (const ESM::MagicEffect *magicEffect, bool isNew) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
#include "../mwrender/vismask.hpp"
|
#include "../mwrender/vismask.hpp"
|
||||||
#include "../mwrender/renderingmanager.hpp"
|
#include "../mwrender/renderingmanager.hpp"
|
||||||
|
#include "../mwrender/util.hpp"
|
||||||
|
|
||||||
#include "../mwsound/sound.hpp"
|
#include "../mwsound/sound.hpp"
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
ESM::EffectList getMagicBoltData(std::vector<std::string>& projectileIDs, std::vector<std::string>& sounds, float& speed, const ESM::EffectList& effects)
|
ESM::EffectList getMagicBoltData(std::vector<std::string>& projectileIDs, std::vector<std::string>& sounds, float& speed, std::string& texture, const ESM::EffectList& effects)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
speed = 0.0f;
|
speed = 0.0f;
|
||||||
|
@ -74,6 +75,14 @@ namespace
|
||||||
if (count != 0)
|
if (count != 0)
|
||||||
speed /= count;
|
speed /= count;
|
||||||
|
|
||||||
|
// the particle texture is only used if there is only one projectile
|
||||||
|
if (projectileEffects.mList.size() == 1)
|
||||||
|
{
|
||||||
|
const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
||||||
|
effects.mList.begin()->mEffectID);
|
||||||
|
texture = magicEffect->mParticle;
|
||||||
|
}
|
||||||
|
|
||||||
if (projectileEffects.mList.size() > 1) // insert a VFX_Multiple projectile if there are multiple projectile effects
|
if (projectileEffects.mList.size() > 1) // insert a VFX_Multiple projectile if there are multiple projectile effects
|
||||||
{
|
{
|
||||||
std::ostringstream ID;
|
std::ostringstream ID;
|
||||||
|
@ -127,7 +136,7 @@ namespace MWWorld
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void ProjectileManager::createModel(State &state, const std::string &model, const osg::Vec3f& pos, const osg::Quat& orient, bool rotate)
|
void ProjectileManager::createModel(State &state, const std::string &model, const osg::Vec3f& pos, const osg::Quat& orient, bool rotate, std::string texture)
|
||||||
{
|
{
|
||||||
state.mNode = new osg::PositionAttitudeTransform;
|
state.mNode = new osg::PositionAttitudeTransform;
|
||||||
state.mNode->setNodeMask(MWRender::Mask_Effect);
|
state.mNode->setNodeMask(MWRender::Mask_Effect);
|
||||||
|
@ -144,7 +153,7 @@ namespace MWWorld
|
||||||
attachTo = rotateNode;
|
attachTo = rotateNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
mResourceSystem->getSceneManager()->getInstance(model, attachTo);
|
osg::ref_ptr<osg::Node> projectile = mResourceSystem->getSceneManager()->getInstance(model, attachTo);
|
||||||
|
|
||||||
if (state.mIdMagic.size() > 1)
|
if (state.mIdMagic.size() > 1)
|
||||||
for (size_t iter = 1; iter != state.mIdMagic.size(); ++iter)
|
for (size_t iter = 1; iter != state.mIdMagic.size(); ++iter)
|
||||||
|
@ -169,6 +178,8 @@ namespace MWWorld
|
||||||
|
|
||||||
SceneUtil::AssignControllerSourcesVisitor assignVisitor (state.mEffectAnimationTime);
|
SceneUtil::AssignControllerSourcesVisitor assignVisitor (state.mEffectAnimationTime);
|
||||||
state.mNode->accept(assignVisitor);
|
state.mNode->accept(assignVisitor);
|
||||||
|
|
||||||
|
MWRender::overrideFirstRootTexture(texture, mResourceSystem, projectile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectileManager::update(State& state, float duration)
|
void ProjectileManager::update(State& state, float duration)
|
||||||
|
@ -207,7 +218,9 @@ namespace MWWorld
|
||||||
state.mActorId = -1;
|
state.mActorId = -1;
|
||||||
state.mStack = stack;
|
state.mStack = stack;
|
||||||
|
|
||||||
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, effects);
|
std::string texture = "";
|
||||||
|
|
||||||
|
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, texture, effects);
|
||||||
|
|
||||||
// Non-projectile should have been removed by getMagicBoltData
|
// Non-projectile should have been removed by getMagicBoltData
|
||||||
if (state.mEffects.mList.empty())
|
if (state.mEffects.mList.empty())
|
||||||
|
@ -216,7 +229,7 @@ namespace MWWorld
|
||||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), state.mIdMagic.at(0));
|
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), state.mIdMagic.at(0));
|
||||||
MWWorld::Ptr ptr = ref.getPtr();
|
MWWorld::Ptr ptr = ref.getPtr();
|
||||||
|
|
||||||
createModel(state, ptr.getClass().getModel(ptr), pos, orient, true);
|
createModel(state, ptr.getClass().getModel(ptr), pos, orient, true, texture);
|
||||||
|
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
for (size_t it = 0; it != state.mSoundIds.size(); it++)
|
for (size_t it = 0; it != state.mSoundIds.size(); it++)
|
||||||
|
@ -486,7 +499,8 @@ namespace MWWorld
|
||||||
state.mSpellId = esm.mSpellId;
|
state.mSpellId = esm.mSpellId;
|
||||||
state.mActorId = esm.mActorId;
|
state.mActorId = esm.mActorId;
|
||||||
state.mStack = esm.mStack;
|
state.mStack = esm.mStack;
|
||||||
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, esm.mEffects);
|
std::string texture = "";
|
||||||
|
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, texture, esm.mEffects);
|
||||||
state.mSpeed = esm.mSpeed; // speed is derived from non-projectile effects as well as
|
state.mSpeed = esm.mSpeed; // speed is derived from non-projectile effects as well as
|
||||||
// projectile effects, so we can't calculate it from the save
|
// projectile effects, so we can't calculate it from the save
|
||||||
// file's effect list, which is already trimmed of non-projectile
|
// file's effect list, which is already trimmed of non-projectile
|
||||||
|
@ -504,7 +518,7 @@ namespace MWWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true);
|
createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true, texture);
|
||||||
|
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ namespace MWWorld
|
||||||
void moveProjectiles(float dt);
|
void moveProjectiles(float dt);
|
||||||
void moveMagicBolts(float dt);
|
void moveMagicBolts(float dt);
|
||||||
|
|
||||||
void createModel (State& state, const std::string& model, const osg::Vec3f& pos, const osg::Quat& orient, bool rotate);
|
void createModel (State& state, const std::string& model, const osg::Vec3f& pos, const osg::Quat& orient, bool rotate, std::string texture = "");
|
||||||
void update (State& state, float duration);
|
void update (State& state, float duration);
|
||||||
|
|
||||||
void operator=(const ProjectileManager&);
|
void operator=(const ProjectileManager&);
|
||||||
|
|
|
@ -3166,7 +3166,7 @@ namespace MWWorld
|
||||||
modelName << roll;
|
modelName << roll;
|
||||||
std::string model = "meshes\\" + getFallback()->getFallbackString(modelName.str());
|
std::string model = "meshes\\" + getFallback()->getFallbackString(modelName.str());
|
||||||
|
|
||||||
mRendering->spawnEffect(model, texture, worldPosition);
|
mRendering->spawnEffect(model, texture, worldPosition, 1.0f, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::spawnEffect(const std::string &model, const std::string &textureOverride, const osg::Vec3f &worldPos)
|
void World::spawnEffect(const std::string &model, const std::string &textureOverride, const osg::Vec3f &worldPos)
|
||||||
|
@ -3183,7 +3183,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
const ESM::MagicEffect* effect = getStore().get<ESM::MagicEffect>().find(effectIt->mEffectID);
|
const ESM::MagicEffect* effect = getStore().get<ESM::MagicEffect>().find(effectIt->mEffectID);
|
||||||
|
|
||||||
if ((effectIt->mArea <= 0 && !ignore.isEmpty() && ignore.getClass().isActor()) || effectIt->mRange != rangeType)
|
if (effectIt->mRange != rangeType || (effectIt->mArea <= 0 && !ignore.isEmpty() && ignore.getClass().isActor()))
|
||||||
continue; // Not right range type, or not area effect and hit an actor
|
continue; // Not right range type, or not area effect and hit an actor
|
||||||
|
|
||||||
// Spawn the explosion orb effect
|
// Spawn the explosion orb effect
|
||||||
|
@ -3193,13 +3193,15 @@ namespace MWWorld
|
||||||
else
|
else
|
||||||
areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea");
|
areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea");
|
||||||
|
|
||||||
|
std::string texture = effect->mParticle;
|
||||||
|
|
||||||
if (effectIt->mArea <= 0)
|
if (effectIt->mArea <= 0)
|
||||||
{
|
{
|
||||||
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", origin, 1.0f);
|
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, texture, origin, 1.0f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", origin, static_cast<float>(effectIt->mArea * 2));
|
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, texture, origin, static_cast<float>(effectIt->mArea * 2));
|
||||||
|
|
||||||
// Play explosion sound (make sure to use NoTrack, since we will delete the projectile now)
|
// Play explosion sound (make sure to use NoTrack, since we will delete the projectile now)
|
||||||
static const std::string schools[] = {
|
static const std::string schools[] = {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <osg/Array>
|
#include <osg/Array>
|
||||||
#include <osg/LOD>
|
#include <osg/LOD>
|
||||||
#include <osg/TexGen>
|
#include <osg/TexGen>
|
||||||
|
#include <osg/ValueObject>
|
||||||
|
|
||||||
// resource
|
// resource
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
@ -276,11 +277,13 @@ namespace NifOsg
|
||||||
public:
|
public:
|
||||||
/// @param filename used for warning messages.
|
/// @param filename used for warning messages.
|
||||||
LoaderImpl(const std::string& filename)
|
LoaderImpl(const std::string& filename)
|
||||||
: mFilename(filename)
|
: mFilename(filename), mFirstRootTextureIndex(-1), mFoundFirstRootTexturingProperty(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
std::string mFilename;
|
std::string mFilename;
|
||||||
|
size_t mFirstRootTextureIndex;
|
||||||
|
bool mFoundFirstRootTexturingProperty;
|
||||||
|
|
||||||
static void loadKf(Nif::NIFFilePtr nif, KeyframeHolder& target)
|
static void loadKf(Nif::NIFFilePtr nif, KeyframeHolder& target)
|
||||||
{
|
{
|
||||||
|
@ -374,9 +377,23 @@ namespace NifOsg
|
||||||
for (size_t i = 0; i <props.length(); ++i)
|
for (size_t i = 0; i <props.length(); ++i)
|
||||||
{
|
{
|
||||||
if (!props[i].empty())
|
if (!props[i].empty())
|
||||||
|
{
|
||||||
|
// Get the lowest numbered recIndex of the NiTexturingProperty root node.
|
||||||
|
// This is what is overridden when a spell effect "particle texture" is used.
|
||||||
|
if (nifNode->parent == NULL && !mFoundFirstRootTexturingProperty && props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
||||||
|
{
|
||||||
|
mFirstRootTextureIndex = props[i].getPtr()->recIndex;
|
||||||
|
mFoundFirstRootTexturingProperty = true;
|
||||||
|
}
|
||||||
|
else if (props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
||||||
|
{
|
||||||
|
if (props[i].getPtr()->recIndex == mFirstRootTextureIndex)
|
||||||
|
applyTo->setUserValue("overrideFx", 1);
|
||||||
|
}
|
||||||
handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags);
|
handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setupController(const Nif::Controller* ctrl, SceneUtil::Controller* toSetup, int animflags)
|
void setupController(const Nif::Controller* ctrl, SceneUtil::Controller* toSetup, int animflags)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue