Restore projectiles

c++11
scrawl 10 years ago
parent c85764b654
commit de8e5f0db1

@ -23,9 +23,7 @@ add_openmw_dir (mwrender
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
bulletdebugdraw globalmap characterpreview camera localmap bulletdebugdraw globalmap characterpreview camera localmap
# occlusionquery water shadows # occlusionquery water shadows ripplesimulation refraction terrainstorage
# ripplesimulation refraction
# terrainstorage weaponanimation
) )
add_openmw_dir (mwinput add_openmw_dir (mwinput
@ -68,8 +66,7 @@ add_openmw_dir (mwworld
cells localscripts customdata inventorystore ptr actionopen actionread cells localscripts customdata inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader actiontrap cellreflist cellref physicssystem weather contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager
# projectilemanager
) )
add_openmw_dir (mwphysics add_openmw_dir (mwphysics

@ -6,9 +6,9 @@
#include <list> #include <list>
#include <stdint.h> #include <stdint.h>
namespace Ogre namespace osg
{ {
class Vector3; class Vec3f;
} }
namespace ESM namespace ESM
@ -174,8 +174,8 @@ namespace MWBase
virtual bool toggleAI() = 0; virtual bool toggleAI() = 0;
virtual bool isAIActive() = 0; virtual bool isAIActive() = 0;
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0; virtual void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0;
virtual void getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects) = 0; virtual void getActorsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects) = 0;
///return the list of actors which are following the given actor ///return the list of actors which are following the given actor
/**ie AiFollow is active and the target is the actor**/ /**ie AiFollow is active and the target is the actor**/

@ -378,7 +378,7 @@ namespace MWBase
virtual bool isWading(const MWWorld::Ptr &object) const = 0; virtual bool isWading(const MWWorld::Ptr &object) const = 0;
///Is the head of the creature underwater? ///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0; virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const = 0; virtual bool isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const = 0;
virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0; virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0;
virtual void togglePOV() = 0; virtual void togglePOV() = 0;
@ -485,7 +485,7 @@ namespace MWBase
virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId, virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId,
float speed, bool stack, const ESM::EffectList& effects, float speed, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, const std::string& sourceName, const Ogre::Vector3& fallbackDirection) = 0; const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) = 0;
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed) = 0; const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed) = 0;
@ -532,7 +532,7 @@ namespace MWBase
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos) = 0; virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos) = 0;
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects, virtual void explodeSpell (const osg::Vec3f& origin, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0; const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0;
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;

@ -247,7 +247,7 @@ namespace MWClass
if (!victim.getClass().isActor()) if (!victim.getClass().isActor())
return; // Can't hit non-actors return; // Can't hit non-actors
Ogre::Vector3 hitPosition (result.second.x(), result.second.y(), result.second.z()); osg::Vec3f hitPosition (result.second);
float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat); float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);
@ -319,7 +319,7 @@ namespace MWClass
damage = 0; damage = 0;
if (damage > 0) if (damage > 0)
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, osg::Vec3f(hitPosition.x, hitPosition.y, hitPosition.z)); MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
MWMechanics::diseaseContact(victim, ptr); MWMechanics::diseaseContact(victim, ptr);
@ -726,7 +726,7 @@ namespace MWClass
if(name == "left") if(name == "left")
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
return 2; return 2;
if(world->isOnGround(ptr)) if(world->isOnGround(ptr))
@ -736,7 +736,7 @@ namespace MWClass
if(name == "right") if(name == "right")
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
return 3; return 3;
if(world->isOnGround(ptr)) if(world->isOnGround(ptr))

@ -493,7 +493,7 @@ namespace MWClass
// TODO: Use second to work out the hit angle // TODO: Use second to work out the hit angle
std::pair<MWWorld::Ptr, osg::Vec3f> result = world->getHitContact(ptr, dist); std::pair<MWWorld::Ptr, osg::Vec3f> result = world->getHitContact(ptr, dist);
MWWorld::Ptr victim = result.first; MWWorld::Ptr victim = result.first;
Ogre::Vector3 hitPosition (result.second.x(), result.second.y(), result.second.z()); osg::Vec3f hitPosition (result.second);
if(victim.isEmpty()) // Didn't hit anything if(victim.isEmpty()) // Didn't hit anything
return; return;
@ -583,7 +583,7 @@ namespace MWClass
damage = 0; damage = 0;
if (healthdmg && damage > 0) if (healthdmg && damage > 0)
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, osg::Vec3f(hitPosition.x, hitPosition.y, hitPosition.z)); MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
MWMechanics::diseaseContact(victim, ptr); MWMechanics::diseaseContact(victim, ptr);
@ -1138,7 +1138,7 @@ namespace MWClass
if(name == "left" || name == "right") if(name == "left" || name == "right")
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
if(world->isSwimming(ptr)) if(world->isSwimming(ptr))
return (name == "left") ? "Swim Left" : "Swim Right"; return (name == "left") ? "Swim Left" : "Swim Right";
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
@ -1175,7 +1175,7 @@ namespace MWClass
if(name == "land") if(name == "land")
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
return "DefaultLandWater"; return "DefaultLandWater";
if(world->isOnGround(ptr)) if(world->isOnGround(ptr))

@ -1623,6 +1623,9 @@ namespace MWGui
void WindowManager::clear() void WindowManager::clear()
{ {
if (mLocalMapRender)
mLocalMapRender->clear();
mMap->clear(); mMap->clear();
mQuickKeysMenu->clear(); mQuickKeysMenu->clear();
mMessageBoxManager->clear(); mMessageBoxManager->clear();

@ -809,7 +809,7 @@ namespace MWMechanics
NpcStats &stats = ptr.getClass().getNpcStats(ptr); NpcStats &stats = ptr.getClass().getNpcStats(ptr);
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
bool knockedOutUnderwater = (ctrl->isKnockedOut() && world->isUnderwater(ptr.getCell(), Ogre::Vector3(ptr.getRefData().getPosition().pos))); bool knockedOutUnderwater = (ctrl->isKnockedOut() && world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3())));
if((world->isSubmerged(ptr) || knockedOutUnderwater) if((world->isSubmerged(ptr) || knockedOutUnderwater)
&& stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0) && stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0)
{ {
@ -1385,11 +1385,11 @@ namespace MWMechanics
return false; return false;
} }
void Actors::getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out) void Actors::getObjectsInRange(const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out)
{ {
for (PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter) for (PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter)
{ {
if (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(position) <= radius*radius) if ((iter->first.getRefData().getPosition().asVec3() - position).length2() <= radius*radius)
out.push_back(iter->first); out.push_back(iter->first);
} }
} }
@ -1457,7 +1457,7 @@ namespace MWMechanics
std::list<MWWorld::Ptr> Actors::getActorsFighting(const MWWorld::Ptr& actor) { std::list<MWWorld::Ptr> Actors::getActorsFighting(const MWWorld::Ptr& actor) {
std::list<MWWorld::Ptr> list; std::list<MWWorld::Ptr> list;
std::vector<MWWorld::Ptr> neighbors; std::vector<MWWorld::Ptr> neighbors;
Ogre::Vector3 position = Ogre::Vector3(actor.getRefData().getPosition().pos); osg::Vec3f position (actor.getRefData().getPosition().asVec3());
getObjectsInRange(position, getObjectsInRange(position,
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(), MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(),
neighbors); //only care about those within the alarm disance neighbors); //only care about those within the alarm disance

@ -114,7 +114,7 @@ namespace MWMechanics
void skipAnimation(const MWWorld::Ptr& ptr); void skipAnimation(const MWWorld::Ptr& ptr);
bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName); bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName);
void getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out); void getObjectsInRange(const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& out);
///Returns the list of actors which are following the given actor ///Returns the list of actors which are following the given actor
/**ie AiFollow is active and the target is the actor **/ /**ie AiFollow is active and the target is the actor **/

@ -64,7 +64,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, AiState& stat
// Make all nearby actors also avoid the door // Make all nearby actors also avoid the door
std::vector<MWWorld::Ptr> actors; std::vector<MWWorld::Ptr> actors;
MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),100,actors); MWBase::Environment::get().getMechanicsManager()->getActorsInRange(pos.asVec3(),100,actors);
for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); ++it) { for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); ++it) {
if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player
MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence(); MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence();

@ -28,7 +28,7 @@ float signedAngleRadians (const osg::Vec3f& v1, const osg::Vec3f& v2, const osg:
return std::atan2((normal * (v1 ^ v2)), (v1 * v2)); return std::atan2((normal * (v1 ^ v2)), (v1 * v2));
} }
bool applyEnchantment (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& object, const Ogre::Vector3& hitPosition) bool applyEnchantment (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& object, const osg::Vec3f& hitPosition)
{ {
std::string enchantmentName = !object.isEmpty() ? object.getClass().getEnchantment(object) : ""; std::string enchantmentName = !object.isEmpty() ? object.getClass().getEnchantment(object) : "";
if (!enchantmentName.empty()) if (!enchantmentName.empty())
@ -166,7 +166,7 @@ namespace MWMechanics
} }
void projectileHit(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, MWWorld::Ptr weapon, const MWWorld::Ptr &projectile, void projectileHit(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, MWWorld::Ptr weapon, const MWWorld::Ptr &projectile,
const Ogre::Vector3& hitPosition) const osg::Vec3f& hitPosition)
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
@ -221,7 +221,7 @@ namespace MWMechanics
appliedEnchantment = applyEnchantment(attacker, victim, projectile, hitPosition); appliedEnchantment = applyEnchantment(attacker, victim, projectile, hitPosition);
if (damage > 0) if (damage > 0)
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, osg::Vec3f(hitPosition.x, hitPosition.y, hitPosition.z)); MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
// Non-enchanted arrows shot at enemies have a chance to turn up in their inventory // Non-enchanted arrows shot at enemies have a chance to turn up in their inventory
if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr() if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr()

@ -15,7 +15,7 @@ void resistNormalWeapon (const MWWorld::Ptr& actor, const MWWorld::Ptr& attacker
/// @note for a thrown weapon, \a weapon == \a projectile, for bows/crossbows, \a projectile is the arrow/bolt /// @note for a thrown weapon, \a weapon == \a projectile, for bows/crossbows, \a projectile is the arrow/bolt
/// @note \a victim may be empty (e.g. for a hit on terrain), a non-actor (environment objects) or an actor /// @note \a victim may be empty (e.g. for a hit on terrain), a non-actor (environment objects) or an actor
void projectileHit (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, MWWorld::Ptr weapon, const MWWorld::Ptr& projectile, void projectileHit (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, MWWorld::Ptr weapon, const MWWorld::Ptr& projectile,
const Ogre::Vector3& hitPosition); const osg::Vec3f& hitPosition);
/// Get the chance (in percent) for \a attacker to successfully hit \a victim with a given weapon skill value /// Get the chance (in percent) for \a attacker to successfully hit \a victim with a given weapon skill value
float getHitChance (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, int skillValue); float getHitChance (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, int skillValue);

@ -1059,14 +1059,14 @@ namespace MWMechanics
// Find all the actors within the alarm radius // Find all the actors within the alarm radius
std::vector<MWWorld::Ptr> neighbors; std::vector<MWWorld::Ptr> neighbors;
Ogre::Vector3 from = Ogre::Vector3(player.getRefData().getPosition().pos); osg::Vec3f from (player.getRefData().getPosition().asVec3());
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(); float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getFloat();
mActors.getObjectsInRange(from, radius, neighbors); mActors.getObjectsInRange(from, radius, neighbors);
// victim should be considered even beyond alarm radius // victim should be considered even beyond alarm radius
if (!victim.isEmpty() && from.squaredDistance(Ogre::Vector3(victim.getRefData().getPosition().pos)) > radius*radius) if (!victim.isEmpty() && (from - victim.getRefData().getPosition().asVec3()).length2() > radius*radius)
neighbors.push_back(victim); neighbors.push_back(victim);
// Did anyone see it? // Did anyone see it?
@ -1149,13 +1149,13 @@ namespace MWMechanics
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
Ogre::Vector3 from = Ogre::Vector3(player.getRefData().getPosition().pos); osg::Vec3f from (player.getRefData().getPosition().asVec3());
float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(); float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getFloat();
mActors.getObjectsInRange(from, radius, neighbors); mActors.getObjectsInRange(from, radius, neighbors);
// victim should be considered even beyond alarm radius // victim should be considered even beyond alarm radius
if (!victim.isEmpty() && from.squaredDistance(Ogre::Vector3(victim.getRefData().getPosition().pos)) > radius*radius) if (!victim.isEmpty() && (from - victim.getRefData().getPosition().asVec3()).length2() > radius*radius)
neighbors.push_back(victim); neighbors.push_back(victim);
int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId(); int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId();
@ -1430,13 +1430,13 @@ namespace MWMechanics
MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); MWBase::Environment::get().getDialogueManager()->say(ptr, "attack");
} }
void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects) void MechanicsManager::getObjectsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects)
{ {
mActors.getObjectsInRange(position, radius, objects); mActors.getObjectsInRange(position, radius, objects);
mObjects.getObjectsInRange(position, radius, objects); mObjects.getObjectsInRange(position, radius, objects);
} }
void MechanicsManager::getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects) void MechanicsManager::getActorsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects)
{ {
mActors.getObjectsInRange(position, radius, objects); mActors.getObjectsInRange(position, radius, objects);
} }

@ -145,8 +145,8 @@ namespace MWMechanics
/// paused we may want to do it manually (after equipping permanent enchantment) /// paused we may want to do it manually (after equipping permanent enchantment)
virtual void updateMagicEffects (const MWWorld::Ptr& ptr); virtual void updateMagicEffects (const MWWorld::Ptr& ptr);
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects); virtual void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector<MWWorld::Ptr>& objects);
virtual void getActorsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects); virtual void getActorsInRange(const osg::Vec3f &position, float radius, std::vector<MWWorld::Ptr> &objects);
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor); virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
virtual std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor); virtual std::list<int> getActorsFollowingIndices(const MWWorld::Ptr& actor);

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

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

@ -779,7 +779,7 @@ namespace MWMechanics
MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed, MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed,
false, enchantment->mEffects, mCaster, mSourceName, false, enchantment->mEffects, mCaster, mSourceName,
// Not needed, enchantments can only be cast by actors // Not needed, enchantments can only be cast by actors
Ogre::Vector3(1,0,0)); osg::Vec3f(1,0,0));
return true; return true;
} }
@ -861,13 +861,13 @@ namespace MWMechanics
getProjectileInfo(spell->mEffects, projectileModel, sound, speed); getProjectileInfo(spell->mEffects, projectileModel, sound, speed);
if (!projectileModel.empty()) if (!projectileModel.empty())
{ {
Ogre::Vector3 fallbackDirection (0,1,0); osg::Vec3f fallbackDirection (0,1,0);
// Fall back to a "caster to target" direction if we have no other means of determining it // Fall back to a "caster to target" direction if we have no other means of determining it
// (e.g. when cast by a non-actor) // (e.g. when cast by a non-actor)
if (!mTarget.isEmpty()) if (!mTarget.isEmpty())
fallbackDirection = fallbackDirection =
Ogre::Vector3(mTarget.getRefData().getPosition().pos)- osg::Vec3f(mTarget.getRefData().getPosition().asVec3())-
Ogre::Vector3(mCaster.getRefData().getPosition().pos); osg::Vec3f(mCaster.getRefData().getPosition().asVec3());
MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed, MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed,
false, spell->mEffects, mCaster, mSourceName, fallbackDirection); false, spell->mEffects, mCaster, mSourceName, fallbackDirection);

@ -71,7 +71,7 @@ namespace MWMechanics
bool mStack; bool mStack;
std::string mId; // ID of spell, potion, item etc std::string mId; // ID of spell, potion, item etc
std::string mSourceName; // Display name for spell, potion, etc std::string mSourceName; // Display name for spell, potion, etc
Ogre::Vector3 mHitPosition; // Used for spawning area orb osg::Vec3f mHitPosition; // Used for spawning area orb
bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false) bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false)
public: public:

@ -748,7 +748,7 @@ namespace MWPhysics
const btCollisionObject* mMe; const btCollisionObject* mMe;
}; };
PhysicsSystem::RayResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, MWWorld::Ptr ignore, int mask) PhysicsSystem::RayResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, MWWorld::Ptr ignore, int mask, int group)
{ {
btVector3 btFrom = toBullet(from); btVector3 btFrom = toBullet(from);
btVector3 btTo = toBullet(to); btVector3 btTo = toBullet(to);
@ -762,7 +762,7 @@ namespace MWPhysics
} }
ClosestNotMeRayResultCallback resultCallback(me, btFrom, btTo); ClosestNotMeRayResultCallback resultCallback(me, btFrom, btTo);
resultCallback.m_collisionFilterGroup = 0xff; resultCallback.m_collisionFilterGroup = group;
resultCallback.m_collisionFilterMask = mask; resultCallback.m_collisionFilterMask = mask;
mCollisionWorld->rayTest(btFrom, btTo, resultCallback); mCollisionWorld->rayTest(btFrom, btTo, resultCallback);
@ -860,6 +860,15 @@ namespace MWPhysics
} }
} }
osg::Vec3f PhysicsSystem::getHalfExtents(const MWWorld::Ptr &actor)
{
Actor* physactor = getActor(actor);
if (physactor)
return physactor->getHalfExtents();
else
return osg::Vec3f();
}
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{ {
public: public:
@ -1128,7 +1137,7 @@ namespace MWPhysics
if (effects.get(ESM::MagicEffect::WaterWalking).getMagnitude() if (effects.get(ESM::MagicEffect::WaterWalking).getMagnitude()
&& cell->getCell()->hasWater() && cell->getCell()->hasWater()
&& !world->isUnderwater(iter->first.getCell(), && !world->isUnderwater(iter->first.getCell(),
Ogre::Vector3(iter->first.getRefData().getPosition().pos))) osg::Vec3f(iter->first.getRefData().getPosition().asVec3())))
waterCollision = true; waterCollision = true;
ActorMap::iterator foundActor = mActors.find(iter->first); ActorMap::iterator foundActor = mActors.find(iter->first);

@ -99,7 +99,7 @@ namespace MWPhysics
/// @param me Optional, a Ptr to ignore in the list of results /// @param me Optional, a Ptr to ignore in the list of results
RayResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, MWWorld::Ptr ignore = MWWorld::Ptr(), int mask = RayResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, MWWorld::Ptr ignore = MWWorld::Ptr(), int mask =
CollisionType_World|CollisionType_HeightMap|CollisionType_Actor); CollisionType_World|CollisionType_HeightMap|CollisionType_Actor, int group=0xff);
RayResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius); RayResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius);
@ -108,6 +108,8 @@ namespace MWPhysics
bool isOnGround (const MWWorld::Ptr& actor); bool isOnGround (const MWWorld::Ptr& actor);
osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor);
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will /// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
/// be overwritten. Valid until the next call to applyQueuedMovement. /// be overwritten. Valid until the next call to applyQueuedMovement.
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity); void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);

@ -937,7 +937,7 @@ namespace MWScript
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false); MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false);
MWMechanics::CastSpell cast(ptr, target); MWMechanics::CastSpell cast(ptr, target);
cast.mHitPosition = Ogre::Vector3(target.getRefData().getPosition().pos); cast.mHitPosition = target.getRefData().getPosition().asVec3();
cast.mAlwaysSucceed = true; cast.mAlwaysSucceed = true;
cast.cast(spell); cast.cast(spell);
} }
@ -955,7 +955,7 @@ namespace MWScript
runtime.pop(); runtime.pop();
MWMechanics::CastSpell cast(ptr, ptr); MWMechanics::CastSpell cast(ptr, ptr);
cast.mHitPosition = Ogre::Vector3(ptr.getRefData().getPosition().pos); cast.mHitPosition = ptr.getRefData().getPosition().asVec3();
cast.mAlwaysSucceed = true; cast.mAlwaysSucceed = true;
cast.cast(spell); cast.cast(spell);
} }

@ -9,8 +9,8 @@ namespace MWWorld
void ActionTrap::executeImp(const Ptr &actor) void ActionTrap::executeImp(const Ptr &actor)
{ {
Ogre::Vector3 actorPosition(actor.getRefData().getPosition().pos); osg::Vec3f actorPosition(actor.getRefData().getPosition().asVec3());
Ogre::Vector3 trapPosition(mTrapSource.getRefData().getPosition().pos); osg::Vec3f trapPosition(mTrapSource.getRefData().getPosition().asVec3());
float activationDistance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); float activationDistance = MWBase::Environment::get().getWorld()->getMaxActivationDistance();
// GUI calcs if object in activation distance include object and player geometry // GUI calcs if object in activation distance include object and player geometry
@ -20,7 +20,7 @@ namespace MWWorld
// to open door/container. // to open door/container.
// Note, can't just detonate the trap at the trapped object's location and use the blast // Note, can't just detonate the trap at the trapped object's location and use the blast
// radius, because for most trap spells this is 1 foot, much less than the activation distance. // radius, because for most trap spells this is 1 foot, much less than the activation distance.
if (trapPosition.distance(actorPosition) < (activationDistance * fudgeFactor)) if ((trapPosition - actorPosition).length() < (activationDistance * fudgeFactor))
{ {
// assume actor touched trap // assume actor touched trap
MWMechanics::CastSpell cast(mTrapSource, actor); MWMechanics::CastSpell cast(mTrapSource, actor);

@ -1,11 +1,11 @@
#include "projectilemanager.hpp" #include "projectilemanager.hpp"
#include <OgreSceneManager.h> #include <osg/PositionAttitudeTransform>
#include <OgreSceneNode.h>
#include <libs/openengine/bullet/physic.hpp>
#include <components/esm/projectilestate.hpp> #include <components/esm/projectilestate.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/controller.hpp>
#include "../mwworld/manualref.hpp" #include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
@ -22,72 +22,70 @@
#include "../mwrender/effectmanager.hpp" #include "../mwrender/effectmanager.hpp"
#include "../mwrender/animation.hpp" #include "../mwrender/animation.hpp"
#include "../mwrender/renderconst.hpp" #include "../mwrender/vismask.hpp"
#include "../mwsound/sound.hpp" #include "../mwsound/sound.hpp"
#include "../mwphysics/physicssystem.hpp"
namespace MWWorld namespace MWWorld
{ {
ProjectileManager::ProjectileManager(Ogre::SceneManager* sceneMgr, OEngine::Physic::PhysicEngine &engine) ProjectileManager::ProjectileManager(osg::Group* parent, Resource::ResourceSystem* resourceSystem, MWPhysics::PhysicsSystem* physics)
: mPhysEngine(engine) : mParent(parent)
, mSceneMgr(sceneMgr) , mResourceSystem(resourceSystem)
, mPhysics(physics)
{ {
} }
void ProjectileManager::createModel(State &state, const std::string &model) void ProjectileManager::createModel(State &state, const std::string &model)
{ {
state.mObject = NifOgre::Loader::createObjects(state.mNode, model); state.mNode = new osg::PositionAttitudeTransform;
for(size_t i = 0;i < state.mObject->mControllers.size();i++) state.mNode->setNodeMask(MWRender::Mask_Effect);
{ mParent->addChild(state.mNode);
if(state.mObject->mControllers[i].getSource().isNull())
state.mObject->mControllers[i].setSource(Ogre::SharedPtr<MWRender::EffectAnimationTime> (new MWRender::EffectAnimationTime()));
}
MWRender::Animation::setRenderProperties(state.mObject, MWRender::RV_Effects, mResourceSystem->getSceneManager()->createInstance(model, state.mNode);
MWRender::RQG_Main, MWRender::RQG_Alpha, 0.f, false, NULL);
state.mEffectAnimationTime.reset(new MWRender::EffectAnimationTime);
SceneUtil::AssignControllerSourcesVisitor assignVisitor (state.mEffectAnimationTime);
state.mNode->accept(assignVisitor);
} }
void ProjectileManager::update(NifOgre::ObjectScenePtr object, float duration) void ProjectileManager::update(State& state, float duration)
{ {
for(size_t i = 0; i < object->mControllers.size() ;i++) state.mEffectAnimationTime->addTime(duration);
{
MWRender::EffectAnimationTime* value = dynamic_cast<MWRender::EffectAnimationTime*>(object->mControllers[i].getSource().get());
if (value)
value->addTime(duration);
object->mControllers[i].update();
}
} }
void ProjectileManager::launchMagicBolt(const std::string &model, const std::string &sound, void ProjectileManager::launchMagicBolt(const std::string &model, const std::string &sound,
const std::string &spellId, float speed, bool stack, const std::string &spellId, float speed, bool stack,
const ESM::EffectList &effects, const Ptr &caster, const std::string &sourceName, const ESM::EffectList &effects, const Ptr &caster, const std::string &sourceName,
const Ogre::Vector3& fallbackDirection) const osg::Vec3f& fallbackDirection)
{ {
float height = 0; float height = 0;
if (OEngine::Physic::PhysicActor* actor = mPhysEngine.getCharacter(caster.getRefData().getHandle()))
height = actor->getHalfExtents().z * 2 * 0.75f; // Spawn at 0.75 * ActorHeight
Ogre::Vector3 pos(caster.getRefData().getPosition().pos); height += mPhysics->getHalfExtents(caster).z() * 2.f * 0.75f; // Spawn at 0.75 * ActorHeight
pos.z += height;
osg::Vec3f pos(caster.getRefData().getPosition().asVec3());
pos.z() += height;
if (MWBase::Environment::get().getWorld()->isUnderwater(caster.getCell(), pos)) // Underwater casting not possible if (MWBase::Environment::get().getWorld()->isUnderwater(caster.getCell(), pos)) // Underwater casting not possible
return; return;
Ogre::Quaternion orient; osg::Quat orient;
if (caster.getClass().isActor()) if (caster.getClass().isActor())
orient = Ogre::Quaternion(Ogre::Radian(caster.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * orient = osg::Quat(caster.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0))
Ogre::Quaternion(Ogre::Radian(caster.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X); * osg::Quat(caster.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1));
else else
orient = Ogre::Vector3::UNIT_Y.getRotationTo(fallbackDirection); orient.makeRotate(osg::Vec3f(0,1,0), osg::Vec3f(fallbackDirection));
MagicBoltState state; MagicBoltState state;
state.mSourceName = sourceName; state.mSourceName = sourceName;
state.mId = model; state.mId = model;
state.mSpellId = spellId; state.mSpellId = spellId;
state.mCasterHandle = caster.getRefData().getHandle(); state.mCasterHandle = caster;
if (caster.getClass().isActor()) if (caster.getClass().isActor())
state.mActorId = caster.getClass().getCreatureStats(caster).getActorId(); state.mActorId = caster.getClass().getCreatureStats(caster).getActorId();
else else
@ -107,8 +105,9 @@ namespace MWWorld
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), model); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), model);
MWWorld::Ptr ptr = ref.getPtr(); MWWorld::Ptr ptr = ref.getPtr();
state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(pos, orient);
createModel(state, ptr.getClass().getModel(ptr)); createModel(state, ptr.getClass().getModel(ptr));
state.mNode->setPosition(pos);
state.mNode->setAttitude(orient);
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
state.mSound = sndMgr->playManualSound3D(pos, sound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); state.mSound = sndMgr->playManualSound3D(pos, sound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
@ -116,20 +115,21 @@ namespace MWWorld
mMagicBolts.push_back(state); mMagicBolts.push_back(state);
} }
void ProjectileManager::launchProjectile(Ptr actor, Ptr projectile, const Ogre::Vector3 &pos, void ProjectileManager::launchProjectile(Ptr actor, Ptr projectile, const osg::Vec3f &pos, const osg::Quat &orient, Ptr bow, float speed)
const Ogre::Quaternion &orient, Ptr bow, float speed)
{ {
ProjectileState state; ProjectileState state;
state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); state.mActorId = actor.getClass().getCreatureStats(actor).getActorId();
state.mBowId = bow.getCellRef().getRefId(); state.mBowId = bow.getCellRef().getRefId();
state.mVelocity = orient.yAxis() * speed; state.mVelocity = orient * osg::Vec3f(0,1,0) * speed;
state.mId = projectile.getCellRef().getRefId(); state.mId = projectile.getCellRef().getRefId();
state.mCasterHandle = actor;
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().getRefId()); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().getRefId());
MWWorld::Ptr ptr = ref.getPtr(); MWWorld::Ptr ptr = ref.getPtr();
state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(pos, orient);
createModel(state, ptr.getClass().getModel(ptr)); createModel(state, ptr.getClass().getModel(ptr));
state.mNode->setPosition(pos);
state.mNode->setAttitude(orient);
mProjectiles.push_back(state); mProjectiles.push_back(state);
} }
@ -144,60 +144,46 @@ namespace MWWorld
{ {
for (std::vector<MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end();) for (std::vector<MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end();)
{ {
Ogre::Quaternion orient = it->mNode->getOrientation(); osg::Quat orient = it->mNode->getAttitude();
static float fTargetSpellMaxSpeed = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>() static float fTargetSpellMaxSpeed = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fTargetSpellMaxSpeed")->getFloat(); .find("fTargetSpellMaxSpeed")->getFloat();
float speed = fTargetSpellMaxSpeed * it->mSpeed; float speed = fTargetSpellMaxSpeed * it->mSpeed;
Ogre::Vector3 direction = orient.yAxis(); osg::Vec3f direction = orient * osg::Vec3f(0,1,0);
direction.normalise(); direction.normalize();
Ogre::Vector3 pos(it->mNode->getPosition()); osg::Vec3f pos(it->mNode->getPosition());
Ogre::Vector3 newPos = pos + direction * duration * speed; osg::Vec3f newPos = pos + direction * duration * speed;
if (it->mSound.get()) if (it->mSound.get())
it->mSound->setPosition(newPos); it->mSound->setPosition(newPos);
it->mNode->setPosition(newPos); it->mNode->setPosition(newPos);
update(it->mObject, duration); update(*it, duration);
MWWorld::Ptr caster = it->getCaster();
// Check for impact // Check for impact
// TODO: use a proper btRigidBody / btGhostObject? // TODO: use a proper btRigidBody / btGhostObject?
btVector3 from(pos.x, pos.y, pos.z); MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, 0xff, MWPhysics::CollisionType_Projectile);
btVector3 to(newPos.x, newPos.y, newPos.z);
std::vector<std::pair<float, std::string> > collisions = mPhysEngine.rayTest2(from, to, OEngine::Physic::CollisionType_Projectile);
bool hit=false;
for (std::vector<std::pair<float, std::string> >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) bool hit = false;
if (result.mHit)
{ {
MWWorld::Ptr obstacle = MWBase::Environment::get().getWorld()->searchPtrViaHandle(cIt->second); hit = true;
if (result.mHitObject.isEmpty())
MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaHandle(it->mCasterHandle);
if (caster.isEmpty())
caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId);
if (!obstacle.isEmpty() && obstacle == caster)
continue;
if (caster.isEmpty())
caster = obstacle;
if (obstacle.isEmpty())
{ {
// Terrain // terrain
} }
else else
{ {
MWMechanics::CastSpell cast(caster, obstacle); MWMechanics::CastSpell cast(caster, result.mHitObject);
cast.mHitPosition = pos; cast.mHitPosition = pos;
cast.mId = it->mSpellId; cast.mId = it->mSpellId;
cast.mSourceName = it->mSourceName; cast.mSourceName = it->mSourceName;
cast.mStack = it->mStack; cast.mStack = it->mStack;
cast.inflict(obstacle, caster, it->mEffects, ESM::RT_Target, false, true); cast.inflict(result.mHitObject, caster, it->mEffects, ESM::RT_Target, false, true);
} }
hit = true;
} }
// Explodes when hitting water // Explodes when hitting water
@ -206,12 +192,11 @@ namespace MWWorld
if (hit) if (hit)
{ {
MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId);
MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, ESM::RT_Target, it->mSpellId, it->mSourceName); MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, ESM::RT_Target, it->mSpellId, it->mSourceName);
MWBase::Environment::get().getSoundManager()->stopSound(it->mSound); MWBase::Environment::get().getSoundManager()->stopSound(it->mSound);
mSceneMgr->destroySceneNode(it->mNode); mParent->removeChild(it->mNode);
it = mMagicBolts.erase(it); it = mMagicBolts.erase(it);
continue; continue;
@ -227,34 +212,26 @@ namespace MWWorld
{ {
// gravity constant - must be way lower than the gravity affecting actors, since we're not // gravity constant - must be way lower than the gravity affecting actors, since we're not
// simulating aerodynamics at all // simulating aerodynamics at all
it->mVelocity -= Ogre::Vector3(0, 0, 627.2f * 0.1f) * duration; it->mVelocity -= osg::Vec3f(0, 0, 627.2f * 0.1f) * duration;
Ogre::Vector3 pos(it->mNode->getPosition()); osg::Vec3f pos(it->mNode->getPosition());
Ogre::Vector3 newPos = pos + it->mVelocity * duration; osg::Vec3f newPos = pos + it->mVelocity * duration;
Ogre::Quaternion orient = Ogre::Vector3::UNIT_Y.getRotationTo(it->mVelocity); osg::Quat orient;
it->mNode->setOrientation(orient); orient.makeRotate(osg::Vec3f(0,1,0), it->mVelocity);
it->mNode->setAttitude(orient);
it->mNode->setPosition(newPos); it->mNode->setPosition(newPos);
update(it->mObject, duration); update(*it, duration);
MWWorld::Ptr caster = it->getCaster();
// Check for impact // Check for impact
// TODO: use a proper btRigidBody / btGhostObject? // TODO: use a proper btRigidBody / btGhostObject?
btVector3 from(pos.x, pos.y, pos.z); MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, 0xff, MWPhysics::CollisionType_Projectile);
btVector3 to(newPos.x, newPos.y, newPos.z);
std::vector<std::pair<float, std::string> > collisions = mPhysEngine.rayTest2(from, to, OEngine::Physic::CollisionType_Projectile);
bool hit=false;
for (std::vector<std::pair<float, std::string> >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) if (result.mHit)
{ {
MWWorld::Ptr obstacle = MWBase::Environment::get().getWorld()->searchPtrViaHandle(cIt->second);
MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId);
// Arrow intersects with player immediately after shooting :/
if (obstacle == caster)
continue;
MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId); MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId);
// Try to get a Ptr to the bow that was used. It might no longer exist. // Try to get a Ptr to the bow that was used. It might no longer exist.
@ -268,15 +245,11 @@ namespace MWWorld
} }
if (caster.isEmpty()) if (caster.isEmpty())
caster = obstacle; caster = result.mHitObject;
MWMechanics::projectileHit(caster, obstacle, bow, projectileRef.getPtr(), pos + (newPos - pos) * cIt->first); MWMechanics::projectileHit(caster, result.mHitObject, bow, projectileRef.getPtr(), result.mHitPos);
hit = true; mParent->removeChild(it->mNode);
}
if (hit)
{
mSceneMgr->destroySceneNode(it->mNode);
it = mProjectiles.erase(it); it = mProjectiles.erase(it);
continue; continue;
@ -290,13 +263,13 @@ namespace MWWorld
{ {
for (std::vector<ProjectileState>::iterator it = mProjectiles.begin(); it != mProjectiles.end(); ++it) for (std::vector<ProjectileState>::iterator it = mProjectiles.begin(); it != mProjectiles.end(); ++it)
{ {
mSceneMgr->destroySceneNode(it->mNode); mParent->removeChild(it->mNode);
} }
mProjectiles.clear(); mProjectiles.clear();
for (std::vector<MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it) for (std::vector<MagicBoltState>::iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it)
{ {
mParent->removeChild(it->mNode);
MWBase::Environment::get().getSoundManager()->stopSound(it->mSound); MWBase::Environment::get().getSoundManager()->stopSound(it->mSound);
mSceneMgr->destroySceneNode(it->mNode);
} }
mMagicBolts.clear(); mMagicBolts.clear();
} }
@ -309,8 +282,8 @@ namespace MWWorld
ESM::ProjectileState state; ESM::ProjectileState state;
state.mId = it->mId; state.mId = it->mId;
state.mPosition = it->mNode->getPosition(); state.mPosition = ESM::Vector3(osg::Vec3f(it->mNode->getPosition()));
state.mOrientation = it->mNode->getOrientation(); state.mOrientation = ESM::Quaternion(osg::Quat(it->mNode->getAttitude()));
state.mActorId = it->mActorId; state.mActorId = it->mActorId;
state.mBowId = it->mBowId; state.mBowId = it->mBowId;
@ -327,8 +300,8 @@ namespace MWWorld
ESM::MagicBoltState state; ESM::MagicBoltState state;
state.mId = it->mId; state.mId = it->mId;
state.mPosition = it->mNode->getPosition(); state.mPosition = ESM::Vector3(osg::Vec3f(it->mNode->getPosition()));
state.mOrientation = it->mNode->getOrientation(); state.mOrientation = ESM::Quaternion(osg::Quat(it->mNode->getAttitude()));
state.mActorId = it->mActorId; state.mActorId = it->mActorId;
state.mSpellId = it->mSpellId; state.mSpellId = it->mSpellId;
@ -369,8 +342,9 @@ namespace MWWorld
return true; return true;
} }
state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(esm.mPosition, esm.mOrientation);
createModel(state, model); createModel(state, model);
state.mNode->setPosition(osg::Vec3f(esm.mPosition));
state.mNode->setAttitude(osg::Quat(esm.mOrientation));
mProjectiles.push_back(state); mProjectiles.push_back(state);
return true; return true;
@ -401,8 +375,9 @@ namespace MWWorld
return true; return true;
} }
state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(esm.mPosition, esm.mOrientation);
createModel(state, model); createModel(state, model);
state.mNode->setPosition(osg::Vec3f(esm.mPosition));
state.mNode->setAttitude(osg::Quat(esm.mOrientation));
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
state.mSound = sndMgr->playManualSound3D(esm.mPosition, esm.mSound, 1.0f, 1.0f, state.mSound = sndMgr->playManualSound3D(esm.mPosition, esm.mSound, 1.0f, 1.0f,
@ -421,4 +396,12 @@ namespace MWWorld
return mMagicBolts.size() + mProjectiles.size(); return mMagicBolts.size() + mProjectiles.size();
} }
MWWorld::Ptr ProjectileManager::State::getCaster()
{
if (!mCasterHandle.isEmpty())
return mCasterHandle;
return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId);
}
} }

@ -3,7 +3,7 @@
#include <string> #include <string>
#include <OgreVector3.h> #include <osg/ref_ptr>
#include <components/esm/effectlist.hpp> #include <components/esm/effectlist.hpp>
@ -21,9 +21,20 @@ namespace Loading
class Listener; class Listener;
} }
namespace Ogre namespace osg
{ {
class SceneManager; class Group;
class Quat;
}
namespace Resource
{
class ResourceSystem;
}
namespace MWRender
{
class EffectAnimationTime;
} }
namespace MWWorld namespace MWWorld
@ -32,16 +43,16 @@ namespace MWWorld
class ProjectileManager class ProjectileManager
{ {
public: public:
ProjectileManager (Ogre::SceneManager* sceneMgr, ProjectileManager (osg::Group* parent, Resource::ResourceSystem* resourceSystem,
OEngine::Physic::PhysicEngine& engine); MWPhysics::PhysicsSystem* physics);
/// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used. /// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used.
void launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId, void launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId,
float speed, bool stack, const ESM::EffectList& effects, float speed, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, const std::string& sourceName, const Ogre::Vector3& fallbackDirection); const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection);
void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
const Ogre::Vector3& pos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed); const osg::Vec3f& pos, const osg::Quat& orient, MWWorld::Ptr bow, float speed);
void update(float dt); void update(float dt);
@ -53,22 +64,22 @@ namespace MWWorld
int countSavedGameRecords() const; int countSavedGameRecords() const;
private: private:
OEngine::Physic::PhysicEngine& mPhysEngine; osg::ref_ptr<osg::Group> mParent;
Ogre::SceneManager* mSceneMgr; Resource::ResourceSystem* mResourceSystem;
MWPhysics::PhysicsSystem* mPhysics;
struct State struct State
{ {
NifOgre::ObjectScenePtr mObject; osg::ref_ptr<osg::PositionAttitudeTransform> mNode;
Ogre::SceneNode* mNode; boost::shared_ptr<MWRender::EffectAnimationTime> mEffectAnimationTime;
int mActorId; int mActorId;
// actorId doesn't work for non-actors, so we also keep track of the Ogre-handle.
// For non-actors, the caster ptr is mainly needed to prevent the projectile
// from colliding with its caster.
// TODO: this will break when the game is saved and reloaded, since there is currently // TODO: this will break when the game is saved and reloaded, since there is currently
// no way to write identifiers for non-actors to a savegame. // no way to write identifiers for non-actors to a savegame.
std::string mCasterHandle; MWWorld::Ptr mCasterHandle;
MWWorld::Ptr getCaster();
// MW-id of this projectile // MW-id of this projectile
std::string mId; std::string mId;
@ -96,7 +107,7 @@ namespace MWWorld
// RefID of the bow or crossbow the actor was using when this projectile was fired (may be empty) // RefID of the bow or crossbow the actor was using when this projectile was fired (may be empty)
std::string mBowId; std::string mBowId;
Ogre::Vector3 mVelocity; osg::Vec3f mVelocity;
}; };
std::vector<MagicBoltState> mMagicBolts; std::vector<MagicBoltState> mMagicBolts;
@ -106,7 +117,7 @@ namespace MWWorld
void moveMagicBolts(float dt); void moveMagicBolts(float dt);
void createModel (State& state, const std::string& model); void createModel (State& state, const std::string& model);
void update (NifOgre::ObjectScenePtr object, float duration); void update (State& state, float duration);
}; };
} }

@ -54,7 +54,7 @@
#include "containerstore.hpp" #include "containerstore.hpp"
#include "inventorystore.hpp" #include "inventorystore.hpp"
#include "actionteleport.hpp" #include "actionteleport.hpp"
//#include "projectilemanager.hpp" #include "projectilemanager.hpp"
#include "weather.hpp" #include "weather.hpp"
#include "contentloader.hpp" #include "contentloader.hpp"
@ -159,9 +159,7 @@ namespace MWWorld
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0) mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
{ {
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode); mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
#if 0 mProjectileManager.reset(new ProjectileManager(rootNode, resourceSystem, mPhysics));
mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine));
#endif
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem); mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem);
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback); mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
@ -276,9 +274,7 @@ namespace MWWorld
{ {
mWeatherManager->clear(); mWeatherManager->clear();
mRendering->clear(); mRendering->clear();
#if 0
mProjectileManager->clear(); mProjectileManager->clear();
#endif
mLocalScripts.clear(); mLocalScripts.clear();
mWorldScene->changeToVoid(); mWorldScene->changeToVoid();
@ -313,9 +309,7 @@ namespace MWWorld
mCells.countSavedGameRecords() mCells.countSavedGameRecords()
+mStore.countSavedGameRecords() +mStore.countSavedGameRecords()
+mGlobalVariables.countSavedGameRecords() +mGlobalVariables.countSavedGameRecords()
#if 0
+mProjectileManager->countSavedGameRecords() +mProjectileManager->countSavedGameRecords()
#endif
+1 // player record +1 // player record
+1 // weather record +1 // weather record
+1 // actorId counter +1 // actorId counter
@ -346,9 +340,8 @@ namespace MWWorld
mGlobalVariables.write (writer, progress); mGlobalVariables.write (writer, progress);
mPlayer->write (writer, progress); mPlayer->write (writer, progress);
mWeatherManager->write (writer, progress); mWeatherManager->write (writer, progress);
#if 0
mProjectileManager->write (writer, progress); mProjectileManager->write (writer, progress);
#endif
writer.startRecord(ESM::REC_ENAB); writer.startRecord(ESM::REC_ENAB);
writer.writeHNT("TELE", mTeleportEnabled); writer.writeHNT("TELE", mTeleportEnabled);
writer.writeHNT("LEVT", mLevitationEnabled); writer.writeHNT("LEVT", mLevitationEnabled);
@ -377,9 +370,7 @@ namespace MWWorld
!mPlayer->readRecord (reader, type) && !mPlayer->readRecord (reader, type) &&
!mWeatherManager->readRecord (reader, type) && !mWeatherManager->readRecord (reader, type) &&
!mCells.readRecord (reader, type, contentFileMap) !mCells.readRecord (reader, type, contentFileMap)
#if 0
&& !mProjectileManager->readRecord (reader, type) && !mProjectileManager->readRecord (reader, type)
#endif
) )
{ {
throw std::runtime_error ("unknown record in saved game"); throw std::runtime_error ("unknown record in saved game");
@ -472,10 +463,8 @@ namespace MWWorld
World::~World() World::~World()
{ {
#if 0
// Must be cleared before mRendering is destroyed // Must be cleared before mRendering is destroyed
mProjectileManager->clear(); mProjectileManager->clear();
#endif
delete mWeatherManager; delete mWeatherManager;
delete mWorldScene; delete mWorldScene;
delete mRendering; delete mRendering;
@ -970,9 +959,7 @@ namespace MWWorld
if (mCurrentWorldSpace != cellName) if (mCurrentWorldSpace != cellName)
{ {
// changed worldspace // changed worldspace
#if 0
mProjectileManager->clear(); mProjectileManager->clear();
#endif
mRendering->notifyWorldSpaceChanged(); mRendering->notifyWorldSpaceChanged();
mCurrentWorldSpace = cellName; mCurrentWorldSpace = cellName;
@ -990,9 +977,7 @@ namespace MWWorld
if (mCurrentWorldSpace != "sys::default") // FIXME if (mCurrentWorldSpace != "sys::default") // FIXME
{ {
// changed worldspace // changed worldspace
#if 0
mProjectileManager->clear(); mProjectileManager->clear();
#endif
mRendering->notifyWorldSpaceChanged(); mRendering->notifyWorldSpaceChanged();
} }
removeContainerScripts(getPlayerPtr()); removeContainerScripts(getPlayerPtr());
@ -1388,7 +1373,7 @@ namespace MWWorld
mPhysics->stepSimulation(duration); mPhysics->stepSimulation(duration);
processDoors(duration); processDoors(duration);
//mProjectileManager->update(duration); mProjectileManager->update(duration);
const MWPhysics::PtrVelocityList &results = mPhysics->applyQueuedMovement(duration); const MWPhysics::PtrVelocityList &results = mPhysics->applyQueuedMovement(duration);
MWPhysics::PtrVelocityList::const_iterator player(results.end()); MWPhysics::PtrVelocityList::const_iterator player(results.end());
@ -1637,9 +1622,7 @@ namespace MWWorld
const ESM::Position& refpos = getPlayerPtr().getRefData().getPosition(); const ESM::Position& refpos = getPlayerPtr().getRefData().getPosition();
osg::Vec3f playerPos = refpos.asVec3(); osg::Vec3f playerPos = refpos.asVec3();
const MWPhysics::Actor* actor = mPhysics->getActor(getPlayerPtr()); playerPos.z() += 1.85f * mPhysics->getHalfExtents(getPlayerPtr()).z();
if (actor)
playerPos.z() += 1.85f * actor->getHalfExtents().z();
osg::Quat playerOrient = osg::Quat(refpos.rot[1], osg::Vec3f(0,-1,0)) * osg::Quat playerOrient = osg::Quat(refpos.rot[1], osg::Vec3f(0,-1,0)) *
osg::Quat(refpos.rot[0], osg::Vec3f(-1,0,0)) * osg::Quat(refpos.rot[0], osg::Vec3f(-1,0,0)) *
@ -2015,24 +1998,19 @@ namespace MWWorld
bool World::isUnderwater(const MWWorld::Ptr &object, const float heightRatio) const bool World::isUnderwater(const MWWorld::Ptr &object, const float heightRatio) const
{ {
const float *fpos = object.getRefData().getPosition().pos; osg::Vec3f pos (object.getRefData().getPosition().asVec3());
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
const MWPhysics::Actor* actor = mPhysics->getActor(object); pos.z() += heightRatio*2*mPhysics->getHalfExtents(object).z();
if (actor)
{
pos.z += heightRatio*2*actor->getHalfExtents().z();
}
return isUnderwater(object.getCell(), pos); return isUnderwater(object.getCell(), pos);
} }
bool World::isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const bool World::isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const
{ {
if (!(cell->getCell()->mData.mFlags & ESM::Cell::HasWater)) { if (!(cell->getCell()->mData.mFlags & ESM::Cell::HasWater)) {
return false; return false;
} }
return pos.z < cell->getWaterLevel(); return pos.z() < cell->getWaterLevel();
} }
bool World::isOnGround(const MWWorld::Ptr &ptr) const bool World::isOnGround(const MWWorld::Ptr &ptr) const
@ -2125,7 +2103,7 @@ namespace MWWorld
Ptr player = mPlayer->getPlayer(); Ptr player = mPlayer->getPlayer();
RefData &refdata = player.getRefData(); RefData &refdata = player.getRefData();
Ogre::Vector3 playerPos(refdata.getPosition().pos); osg::Vec3f playerPos(refdata.getPosition().asVec3());
const MWPhysics::Actor* actor = mPhysics->getActor(player); const MWPhysics::Actor* actor = mPhysics->getActor(player);
if (!actor) if (!actor)
@ -2519,7 +2497,7 @@ namespace MWWorld
// Witnesses of the player's transformation will make them a globally known werewolf // Witnesses of the player's transformation will make them a globally known werewolf
std::vector<MWWorld::Ptr> closeActors; std::vector<MWWorld::Ptr> closeActors;
MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(actor.getRefData().getPosition().pos), MWBase::Environment::get().getMechanicsManager()->getActorsInRange(actor.getRefData().getPosition().asVec3(),
getStore().get<ESM::GameSetting>().search("fAlarmRadius")->getFloat(), getStore().get<ESM::GameSetting>().search("fAlarmRadius")->getFloat(),
closeActors); closeActors);
@ -2695,7 +2673,7 @@ namespace MWWorld
MWMechanics::CastSpell cast(actor, target); MWMechanics::CastSpell cast(actor, target);
if (!target.isEmpty()) if (!target.isEmpty())
cast.mHitPosition = Ogre::Vector3(target.getRefData().getPosition().pos); cast.mHitPosition = target.getRefData().getPosition().asVec3();
if (!selectedSpell.empty()) if (!selectedSpell.empty())
{ {
@ -2718,18 +2696,14 @@ namespace MWWorld
void World::launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, void World::launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed) const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed)
{ {
#if 0
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed); mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed);
#endif
} }
void World::launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId, void World::launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId,
float speed, bool stack, const ESM::EffectList& effects, float speed, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, const std::string& sourceName, const Ogre::Vector3& fallbackDirection) const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection)
{ {
#if 0
mProjectileManager->launchMagicBolt(model, sound, spellId, speed, stack, effects, caster, sourceName, fallbackDirection); mProjectileManager->launchMagicBolt(model, sound, spellId, speed, stack, effects, caster, sourceName, fallbackDirection);
#endif
} }
const std::vector<std::string>& World::getContentFiles() const const std::vector<std::string>& World::getContentFiles() const
@ -3181,7 +3155,7 @@ namespace MWWorld
mRendering->spawnEffect(model, textureOverride, worldPos); mRendering->spawnEffect(model, textureOverride, worldPos);
} }
void World::explodeSpell(const Ogre::Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, ESM::RangeType rangeType, void World::explodeSpell(const osg::Vec3f &origin, const ESM::EffectList &effects, const Ptr &caster, ESM::RangeType rangeType,
const std::string& id, const std::string& sourceName) const std::string& id, const std::string& sourceName)
{ {
std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply; std::map<MWWorld::Ptr, std::vector<ESM::ENAMstruct> > toApply;
@ -3200,7 +3174,7 @@ namespace MWWorld
else else
areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea"); areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea");
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", osg::Vec3f(origin.x, origin.y, origin.z), static_cast<float>(effectIt->mArea)); mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", origin, static_cast<float>(effectIt->mArea));
// 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[] = {
@ -3209,9 +3183,9 @@ namespace MWWorld
{ {
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(!effect->mAreaSound.empty()) if(!effect->mAreaSound.empty())
sndMgr->playManualSound3D(osg::Vec3f(origin.x, origin.y, origin.z), effect->mAreaSound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack); sndMgr->playManualSound3D(origin, effect->mAreaSound, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack);
else else
sndMgr->playManualSound3D(osg::Vec3f(origin.x, origin.y, origin.z), schools[effect->mData.mSchool]+" area", 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoTrack); sndMgr->playManualSound3D(origin, 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 // Get the actors in range of the effect
std::vector<MWWorld::Ptr> objects; std::vector<MWWorld::Ptr> objects;

@ -455,7 +455,7 @@ namespace MWWorld
///Is the head of the creature underwater? ///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const; virtual bool isSubmerged(const MWWorld::Ptr &object) const;
virtual bool isSwimming(const MWWorld::Ptr &object) const; virtual bool isSwimming(const MWWorld::Ptr &object) const;
virtual bool isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const; virtual bool isUnderwater(const MWWorld::CellStore* cell, const osg::Vec3f &pos) const;
virtual bool isWading(const MWWorld::Ptr &object) const; virtual bool isWading(const MWWorld::Ptr &object) const;
virtual bool isOnGround(const MWWorld::Ptr &ptr) const; virtual bool isOnGround(const MWWorld::Ptr &ptr) const;
@ -572,7 +572,7 @@ namespace MWWorld
virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId, virtual void launchMagicBolt (const std::string& model, const std::string& sound, const std::string& spellId,
float speed, bool stack, const ESM::EffectList& effects, float speed, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, const std::string& sourceName, const Ogre::Vector3& fallbackDirection); const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection);
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile, virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed); const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed);
@ -613,7 +613,7 @@ namespace MWWorld
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos); virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos);
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects, virtual void explodeSpell (const osg::Vec3f& origin, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName); const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName);
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor); virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor);

@ -3,8 +3,8 @@
#include <string> #include <string>
#include <OgreVector3.h> #include <osg/Quat>
#include <OgreQuaternion.h> #include <osg/Vec3f>
#include "effectlist.hpp" #include "effectlist.hpp"

@ -4,6 +4,9 @@
#include <OgreVector3.h> #include <OgreVector3.h>
#include <OgreQuaternion.h> #include <OgreQuaternion.h>
#include <osg/Vec3f>
#include <osg/Quat>
namespace ESM namespace ESM
{ {
@ -21,11 +24,23 @@ struct Quaternion
mValues[2] = q.y; mValues[2] = q.y;
mValues[3] = q.z; mValues[3] = q.z;
} }
Quaternion(const osg::Quat& q)
{
mValues[0] = q.w();
mValues[1] = q.x();
mValues[2] = q.y();
mValues[3] = q.z();
}
operator Ogre::Quaternion () const operator Ogre::Quaternion () const
{ {
return Ogre::Quaternion(mValues[0], mValues[1], mValues[2], mValues[3]); return Ogre::Quaternion(mValues[0], mValues[1], mValues[2], mValues[3]);
} }
operator osg::Quat () const
{
return osg::Quat(mValues[1], mValues[2], mValues[3], mValues[0]);
}
}; };
struct Vector3 struct Vector3
@ -39,11 +54,22 @@ struct Vector3
mValues[1] = v.y; mValues[1] = v.y;
mValues[2] = v.z; mValues[2] = v.z;
} }
Vector3(const osg::Vec3f& v)
{
mValues[0] = v.x();
mValues[1] = v.y();
mValues[2] = v.z();
}
operator Ogre::Vector3 () const operator Ogre::Vector3 () const
{ {
return Ogre::Vector3(&mValues[0]); return Ogre::Vector3(&mValues[0]);
} }
operator osg::Vec3f () const
{
return osg::Vec3f(mValues[0], mValues[1], mValues[2]);
}
}; };
} }

Loading…
Cancel
Save