Feature #957: Implement area magic

actorid
scrawl 11 years ago
parent ba5300b071
commit 205e8aa4e9

@ -157,6 +157,8 @@ namespace MWBase
virtual void toggleAI() = 0;
virtual bool isAIActive() = 0;
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0;
};
}

@ -919,4 +919,13 @@ namespace MWMechanics
return iter->second->isAnimPlaying(groupName);
return false;
}
void Actors::getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out)
{
for (PtrControllerMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
{
if (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(position) <= radius*radius)
out.push_back(iter->first);
}
}
}

@ -94,6 +94,8 @@ namespace MWMechanics
void skipAnimation(const MWWorld::Ptr& ptr);
bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName);
void getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out);
private:
PtrControllerMap mActors;

@ -950,4 +950,10 @@ namespace MWMechanics
return (roll >= target);
}
void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects)
{
mActors.getObjectsInRange(position, radius, objects);
mObjects.getObjectsInRange(position, radius, objects);
}
}

@ -135,6 +135,8 @@ namespace MWMechanics
virtual void toggleAI();
virtual bool isAIActive();
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects);
};
}

@ -92,4 +92,13 @@ void Objects::skipAnimation(const MWWorld::Ptr& ptr)
iter->second->skipAnim();
}
void Objects::getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out)
{
for (PtrControllerMap::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
{
if (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(position) <= radius*radius)
out.push_back(iter->first);
}
}
}

@ -40,6 +40,8 @@ namespace MWMechanics
void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
void skipAnimation(const MWWorld::Ptr& ptr);
void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out);
};
}

@ -26,9 +26,10 @@ EffectManager::EffectManager(Ogre::SceneManager *sceneMgr)
{
}
void EffectManager::addEffect(const std::string &model, std::string textureOverride, const Ogre::Vector3 &worldPosition)
void EffectManager::addEffect(const std::string &model, std::string textureOverride, const Ogre::Vector3 &worldPosition, float scale)
{
Ogre::SceneNode* sceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(worldPosition);
sceneNode->setScale(scale,scale,scale);
// fix texture extension to .dds
if (textureOverride.size() > 4)
@ -78,7 +79,7 @@ void EffectManager::addEffect(const std::string &model, std::string textureOverr
mEffects.push_back(std::make_pair(sceneNode, scene));
}
void EffectManager::update(float dt)
void EffectManager::update(float dt, Ogre::Camera* camera)
{
for (std::vector<std::pair<Ogre::SceneNode*, NifOgre::ObjectScenePtr> >::iterator it = mEffects.begin(); it != mEffects.end(); )
{
@ -91,6 +92,7 @@ void EffectManager::update(float dt)
objects->mControllers[i].update();
}
objects->rotateBillboardNodes(camera);
// Finished playing?
if (objects->mControllers[0].getSource()->getValue() >= objects->mMaxControllerLength)

@ -14,9 +14,9 @@ namespace MWRender
~EffectManager() { clear(); }
/// Add an effect. When it's finished playing, it will be removed automatically.
void addEffect (const std::string& model, std::string textureOverride, const Ogre::Vector3& worldPosition);
void addEffect (const std::string& model, std::string textureOverride, const Ogre::Vector3& worldPosition, float scale);
void update(float dt);
void update(float dt, Ogre::Camera* camera);
/// Remove all effects
void clear();

@ -378,7 +378,7 @@ void RenderingManager::update (float duration, bool paused)
if(paused)
return;
mEffectManager->update(duration);
mEffectManager->update(duration, mRendering.getCamera());
mActors->update (mRendering.getCamera());
mPlayerAnimation->preRender(mRendering.getCamera());
@ -1024,9 +1024,9 @@ float RenderingManager::getCameraDistance() const
return mCamera->getCameraDistance();
}
void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const Vector3 &worldPosition)
void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const Vector3 &worldPosition, float scale)
{
mEffectManager->addEffect(model, texture, worldPosition);
mEffectManager->addEffect(model, "", worldPosition, scale);
}
} // namespace

@ -207,7 +207,7 @@ public:
void stopVideo();
void frameStarted(float dt, bool paused);
void spawnEffect (const std::string& model, const std::string& texture, const Ogre::Vector3& worldPosition);
void spawnEffect (const std::string& model, const std::string& texture, const Ogre::Vector3& worldPosition, float scale=1.f);
protected:
virtual void windowResized(int x, int y);

@ -2174,9 +2174,16 @@ namespace MWWorld
state.mId = id;
state.mActorHandle = actor.getRefData().getHandle();
state.mSpeed = speed;
state.mEffects = effects;
state.mStack = stack;
// Only interested in "on target" effects
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.mList.begin());
iter!=effects.mList.end(); ++iter)
{
if (iter->mRange == ESM::RT_Target)
state.mEffects.mList.push_back(*iter);
}
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
sndMgr->playSound3D(ptr, sound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
@ -2223,30 +2230,68 @@ namespace MWWorld
continue;
explode = true;
}
MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle);
if (caster.isEmpty())
caster = obstacle;
if (obstacle.isEmpty())
if (explode)
{
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = it->second.mEffects.mList.begin();
effectIt != it->second.mEffects.mList.end(); ++effectIt)
{
// Terrain
const ESM::MagicEffect* effect = getStore().get<ESM::MagicEffect>().find(effectIt->mEffectID);
// Spawn the explosion orb effect
const ESM::Static* areaStatic;
if (!effect->mCasting.empty())
areaStatic = getStore().get<ESM::Static>().find (effect->mArea);
else
areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea");
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", Ogre::Vector3(ptr.getRefData().getPosition().pos), effectIt->mArea);
// Play explosion sound (make sure to use NoTrack, since we will delete the projectile now)
static const std::string schools[] = {
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
};
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(!effect->mAreaSound.empty())
sndMgr->playSound3D(ptr, effect->mAreaSound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack);
else
sndMgr->playSound3D(ptr, schools[effect->mData.mSchool]+" area", 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack);
// Get the actors in range of the effect
std::vector<MWWorld::Ptr> objects;
MWBase::Environment::get().getMechanicsManager()->getObjectsInRange(
Ogre::Vector3(ptr.getRefData().getPosition().pos), feetToGameUnits(effectIt->mArea), objects);
for (std::vector<MWWorld::Ptr>::iterator affected = objects.begin(); affected != objects.end(); ++affected)
toApply[*affected].push_back(*effectIt);
}
else
// Now apply the appropriate effects to each actor in range
for (std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> >::iterator apply = toApply.begin(); apply != toApply.end(); ++apply)
{
MWMechanics::CastSpell cast(caster, obstacle);
cast.mStack = it->second.mStack;
MWWorld::Ptr caster = searchPtrViaHandle(it->second.mActorHandle);
// Vanilla-compatible behaviour of never applying the spell to the caster
// (could be changed by mods later)
if (apply->first == caster)
continue;
if (caster.isEmpty())
caster = apply->first;
MWMechanics::CastSpell cast(caster, apply->first);
cast.mId = it->second.mId;
cast.mSourceName = it->second.mSourceName;
cast.inflict(obstacle, caster, it->second.mEffects, ESM::RT_Target, false);
cast.mStack = it->second.mStack;
ESM::EffectList effects;
effects.mList = apply->second;
cast.inflict(apply->first, caster, effects, ESM::RT_Target);
}
deleteObject(ptr);
mProjectiles.erase(it++);
}
if (explode)
{
// TODO: Explode
continue;
}

Loading…
Cancel
Save