mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Feature #957: Implement area magic
This commit is contained in:
parent
ba5300b071
commit
205e8aa4e9
12 changed files with 108 additions and 29 deletions
|
@ -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())
|
||||
{
|
||||
// Terrain
|
||||
}
|
||||
else
|
||||
{
|
||||
MWMechanics::CastSpell cast(caster, obstacle);
|
||||
cast.mStack = it->second.mStack;
|
||||
cast.mId = it->second.mId;
|
||||
cast.mSourceName = it->second.mSourceName;
|
||||
cast.inflict(obstacle, caster, it->second.mEffects, ESM::RT_Target, false);
|
||||
}
|
||||
|
||||
deleteObject(ptr);
|
||||
mProjectiles.erase(it++);
|
||||
}
|
||||
|
||||
if (explode)
|
||||
{
|
||||
// TODO: 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
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.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++);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue