Merge remote-tracking branch 'kcat/master'

actorid
Marc Zinnschlag 12 years ago
commit ce90c2f3be

@ -39,9 +39,11 @@ namespace MWBase
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */
Play_NoTrack = 1<<2 /* (3D only) Play the sound at the given object's position
Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position
* but do not keep it updated (the sound will not move with
* the object and will not stop when the object is deleted. */
Play_LoopNoEnv = Play_Loop | Play_NoEnv
};
enum PlayType {
Play_TypeSfx = 1<<3, /* Normal SFX sound */

@ -6,19 +6,26 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld//cellstore.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/action.hpp"
#include "../mwworld/failedaction.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwrender/actors.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "../mwgui/tooltips.hpp"
#include "../mwmechanics/npcstats.hpp"
namespace MWClass
{
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
const std::string model = getModel(ptr);
if (!model.empty()) {
@ -94,7 +101,23 @@ namespace MWClass
return info;
}
boost::shared_ptr<MWWorld::Action> Activator::activate(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const
{
if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf())
{
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfActivator");
boost::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
if(sound) action->setSound(sound->mId);
return action;
}
return boost::shared_ptr<MWWorld::Action>(new MWWorld::NullAction);
}
MWWorld::Ptr
Activator::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{

@ -31,6 +31,9 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr
virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const;
///< Generate action for activation
static void registerSelf();
virtual std::string getModel(const MWWorld::Ptr &ptr) const;

@ -11,10 +11,12 @@
#include "../mwworld/class.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "npcstats.hpp"
#include "creaturestats.hpp"
@ -68,22 +70,24 @@ namespace MWMechanics
{
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
int strength = creatureStats.getAttribute(0).getBase();
int intelligence = creatureStats.getAttribute(1).getBase();
int willpower = creatureStats.getAttribute(2).getBase();
int agility = creatureStats.getAttribute(3).getBase();
int endurance = creatureStats.getAttribute(5).getBase();
int strength = creatureStats.getAttribute(ESM::Attribute::Strength).getBase();
int intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getBase();
int willpower = creatureStats.getAttribute(ESM::Attribute::Willpower).getBase();
int agility = creatureStats.getAttribute(ESM::Attribute::Agility).getBase();
int endurance = creatureStats.getAttribute(ESM::Attribute::Endurance).getBase();
double magickaFactor =
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude * 0.1 + 0.5;
DynamicStat<float> magicka = creatureStats.getMagicka();
magicka.setBase (static_cast<int> (intelligence + magickaFactor * intelligence));
creatureStats.setMagicka (magicka);
float diff = (static_cast<int>(intelligence + magickaFactor*intelligence)) - magicka.getBase();
magicka.modify(diff);
creatureStats.setMagicka(magicka);
DynamicStat<float> fatigue = creatureStats.getFatigue();
fatigue.setBase (strength+willpower+agility+endurance);
creatureStats.setFatigue (fatigue);
diff = (strength+willpower+agility+endurance) - fatigue.getBase();
fatigue.modify(diff);
creatureStats.setFatigue(fatigue);
}
void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration)
@ -133,62 +137,63 @@ namespace MWMechanics
void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
{
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
CreatureStats &creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
const MagicEffects &effects = creatureStats.getMagicEffects();
// attributes
for (int i=0; i<8; ++i)
for(int i = 0;i < ESM::Attribute::Length;++i)
{
int modifier =
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyAttribute, i)).mMagnitude;
modifier -= creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::DrainAttribute, i)).mMagnitude;
Stat<int> stat = creatureStats.getAttribute(i);
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude -
effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude);
creatureStats.getAttribute(i).setModifier (modifier);
creatureStats.setAttribute(i, stat);
}
// dynamic stats
MagicEffects effects = creatureStats.getMagicEffects();
for (int i=0; i<3; ++i)
for(int i = 0;i < 3;++i)
{
DynamicStat<float> stat = creatureStats.getDynamic (i);
DynamicStat<float> stat = creatureStats.getDynamic(i);
stat.setModifier(effects.get(EffectKey(80+i)).mMagnitude -
effects.get(EffectKey(18+i)).mMagnitude);
stat.setModifier (
effects.get (EffectKey(80+i)).mMagnitude - effects.get (EffectKey(18+i)).mMagnitude);
creatureStats.setDynamic (i, stat);
creatureStats.setDynamic(i, stat);
}
}
void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration)
{
NpcStats &stats = MWWorld::Class::get(ptr).getNpcStats(ptr);
if(MWBase::Environment::get().getWorld()->isSubmerged(ptr) &&
MWBase::World *world = MWBase::Environment::get().getWorld();
NpcStats &stats = ptr.getClass().getNpcStats(ptr);
if(world->isSubmerged(ptr) &&
stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).mMagnitude == 0)
{
float timeLeft = 0.0f;
if(stats.getFatigue().getCurrent() == 0)
stats.setTimeToStartDrowning(0);
float timeLeft = stats.getTimeToStartDrowning()-duration;
if(timeLeft < 0.0f)
timeLeft = 0.0f;
stats.setTimeToStartDrowning(timeLeft);
else
{
timeLeft = stats.getTimeToStartDrowning() - duration;
if(timeLeft < 0.0f)
timeLeft = 0.0f;
stats.setTimeToStartDrowning(timeLeft);
}
if(timeLeft == 0.0f)
stats.setLastDrowningHitTime(stats.getLastDrowningHitTime()+duration);
{
// If drowning, apply 3 points of damage per second
ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - 3.0f*duration);
// Play a drowning sound as necessary for the player
if(ptr == world->getPlayer().getPlayer())
{
MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager();
if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown"))
sndmgr->playSound("drown", 1.0f, 1.0f);
}
}
}
else
{
stats.setTimeToStartDrowning(20);
stats.setLastDrowningHitTime(0);
}
//if npc is drowning and it's time to hit, then hit
while(stats.getTimeToStartDrowning() == 0.0f && stats.getLastDrowningHitTime() > 0.33f)
{
stats.setLastDrowningHitTime(stats.getLastDrowningHitTime()-0.33f);
//fixme: replace it with something different once screen hit effects are implemented (blood on screen)
MWWorld::Class::get(ptr).setActorHealth(ptr, stats.getHealth().getCurrent()-1.0f);
}
}
Actors::Actors() : mDuration (0) {}

@ -8,7 +8,6 @@
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
@ -189,6 +188,9 @@ namespace MWMechanics
void MechanicsManager::updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr)
{
if(old == mWatched)
mWatched = ptr;
if(MWWorld::Class::get(ptr).isActor())
mActors.updateActor(old, ptr);
else
@ -213,98 +215,76 @@ namespace MWMechanics
void MechanicsManager::update(float duration, bool paused)
{
if (!mWatched.isEmpty())
if(!mWatched.isEmpty())
{
MWMechanics::CreatureStats& stats =
MWWorld::Class::get (mWatched).getCreatureStats (mWatched);
MWMechanics::NpcStats& npcStats =
MWWorld::Class::get (mWatched).getNpcStats (mWatched);
static const char *attributeNames[8] =
{
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
"AttribVal6", "AttribVal7", "AttribVal8"
};
static const char *dynamicNames[3] =
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
const MWMechanics::NpcStats &stats = mWatched.getClass().getNpcStats(mWatched);
for(int i = 0;i < ESM::Attribute::Length;++i)
{
"HBar", "MBar", "FBar"
};
for (int i=0; i<8; ++i)
{
if (stats.getAttribute(i)!=mWatchedCreature.getAttribute(i))
if(stats.getAttribute(i) != mWatchedStats.getAttribute(i))
{
mWatchedCreature.setAttribute(i, stats.getAttribute(i));
std::stringstream attrname;
attrname << "AttribVal"<<(i+1);
MWBase::Environment::get().getWindowManager()->setValue (attributeNames[i], stats.getAttribute(i));
mWatchedStats.setAttribute(i, stats.getAttribute(i));
winMgr->setValue(attrname.str(), stats.getAttribute(i));
}
}
if (stats.getHealth() != mWatchedCreature.getHealth()) {
mWatchedCreature.setHealth(stats.getHealth());
MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[0], stats.getHealth());
if(stats.getHealth() != mWatchedStats.getHealth())
{
static const std::string hbar("HBar");
mWatchedStats.setHealth(stats.getHealth());
winMgr->setValue(hbar, stats.getHealth());
}
if (stats.getMagicka() != mWatchedCreature.getMagicka()) {
mWatchedCreature.setMagicka(stats.getMagicka());
MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[1], stats.getMagicka());
if(stats.getMagicka() != mWatchedStats.getMagicka())
{
static const std::string mbar("MBar");
mWatchedStats.setMagicka(stats.getMagicka());
winMgr->setValue(mbar, stats.getMagicka());
}
if (stats.getFatigue() != mWatchedCreature.getFatigue()) {
mWatchedCreature.setFatigue(stats.getFatigue());
MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[2], stats.getFatigue());
if(stats.getFatigue() != mWatchedStats.getFatigue())
{
static const std::string fbar("FBar");
mWatchedStats.setFatigue(stats.getFatigue());
winMgr->setValue(fbar, stats.getFatigue());
}
if(npcStats.getTimeToStartDrowning() != mWatchedNpc.getTimeToStartDrowning())
if(stats.getTimeToStartDrowning() != mWatchedStats.getTimeToStartDrowning())
{
mWatchedNpc.setTimeToStartDrowning(npcStats.getTimeToStartDrowning());
if(npcStats.getTimeToStartDrowning()>=20.0)
{
MWBase::Environment::get().getWindowManager()->setDrowningBarVisibility(false);
}
mWatchedStats.setTimeToStartDrowning(stats.getTimeToStartDrowning());
if(stats.getTimeToStartDrowning() >= 20.0f)
winMgr->setDrowningBarVisibility(false);
else
{
MWBase::Environment::get().getWindowManager()->setDrowningBarVisibility(true);
MWBase::Environment::get().getWindowManager()->setDrowningTimeLeft(npcStats.getTimeToStartDrowning());
winMgr->setDrowningBarVisibility(true);
winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning());
}
}
bool update = false;
//Loop over ESM::Skill::SkillEnum
for(int i = 0; i < 27; ++i)
for(int i = 0; i < ESM::Skill::Length; ++i)
{
if(npcStats.getSkill (i) != mWatchedNpc.getSkill (i))
if(stats.getSkill(i) != mWatchedStats.getSkill(i))
{
update = true;
mWatchedNpc.getSkill (i) = npcStats.getSkill (i);
MWBase::Environment::get().getWindowManager()->setValue((ESM::Skill::SkillEnum)i, npcStats.getSkill (i));
mWatchedStats.getSkill(i) = stats.getSkill(i);
winMgr->setValue((ESM::Skill::SkillEnum)i, stats.getSkill(i));
}
}
if (update)
MWBase::Environment::get().getWindowManager()->updateSkillArea();
MWBase::Environment::get().getWindowManager()->setValue ("level", stats.getLevel());
}
if(update)
winMgr->updateSkillArea();
//update drowning sound
MWBase::World *world = MWBase::Environment::get().getWorld();
MWBase::SoundManager * sndmgr = MWBase::Environment::get().getSoundManager();
MWWorld::Ptr playerPtr = world->getPlayer().getPlayer();
NpcStats& playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown") && playerStats.getTimeToStartDrowning()==0.0)
{
sndmgr->playSound("drown",1.0,1.0,MWBase::SoundManager::Play_TypeSfx,MWBase::SoundManager::Play_Loop);
}
if(playerStats.getTimeToStartDrowning()>0.0)
{
//no need to check if it's playing, stop sound does nothing in that case
sndmgr->stopSound("drown");
winMgr->setValue("level", stats.getLevel());
}
if (mUpdatePlayer)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
// basic player profile; should not change anymore after the creation phase is finished.
MWBase::WindowManager *winMgr =
MWBase::Environment::get().getWindowManager();

@ -25,8 +25,7 @@ namespace MWMechanics
class MechanicsManager : public MWBase::MechanicsManager
{
MWWorld::Ptr mWatched;
CreatureStats mWatchedCreature;
NpcStats mWatchedNpc;
NpcStats mWatchedStats;
bool mUpdatePlayer;
bool mClassSelected;
bool mRaceSelected;

@ -422,7 +422,7 @@ void MWMechanics::NpcStats::modifyProfit(int diff)
mProfit += diff;
}
float MWMechanics::NpcStats::getTimeToStartDrowning()
float MWMechanics::NpcStats::getTimeToStartDrowning() const
{
return mTimeToStartDrowning;
}
@ -431,13 +431,3 @@ void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
assert(time>=0 && time<=20);
mTimeToStartDrowning=time;
}
float MWMechanics::NpcStats::getLastDrowningHitTime()
{
return mLastDrowningHit;
}
void MWMechanics::NpcStats::setLastDrowningHitTime(float time)
{
mLastDrowningHit=time;
}

@ -147,15 +147,10 @@ namespace MWMechanics
int getWerewolfKills() const;
float getTimeToStartDrowning();
float getTimeToStartDrowning() const;
/// Sets time left for the creature to drown if it stays underwater.
/// @param time value from [0,20]
void setTimeToStartDrowning(float time);
float getLastDrowningHitTime();
/// Sets time since last hit caused by drowning.
/// @param time value from [0,0.33]
void setLastDrowningHitTime(float time);
};
}

@ -42,6 +42,18 @@ namespace MWMechanics
mBase = mModified = value;
}
void modify(const T& diff)
{
mBase += diff;
if(mBase >= static_cast<T>(0))
mModified += diff;
else
{
mModified += diff - mBase;
mBase = static_cast<T>(0);
}
}
/// Set base and adjust modified accordingly.
void setBase (const T& value)
{

@ -4,11 +4,10 @@
#include <algorithm>
#include <map>
#include "../mwworld/esmstore.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
#include "sound_output.hpp"
@ -103,6 +102,7 @@ namespace MWSound
SoundManager::~SoundManager()
{
mUnderwaterSound.reset();
mActiveSounds.clear();
mMusic.reset();
mOutput.reset();
@ -474,27 +474,32 @@ namespace MWSound
void SoundManager::updateRegionSound(float duration)
{
MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
static float sTimeToNextEnvSound = 0.0f;
static int total = 0;
static std::string regionName = "";
static float timePassed = 0.0;
static float sTimePassed = 0.0;
MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Ptr player = world->getPlayer().getPlayer();
const ESM::Cell *cell = player.getCell()->mCell;
//If the region has changed
timePassed += duration;
if(!current->mCell->isExterior() || timePassed < 10)
sTimePassed += duration;
if(!cell->isExterior() || sTimePassed < sTimeToNextEnvSound)
return;
timePassed = 0;
if(regionName != current->mCell->mRegion)
float a = std::rand() / (double)RAND_MAX;
// NOTE: We should use the "Minimum Time Between Environmental Sounds" and
// "Maximum Time Between Environmental Sounds" fallback settings here.
sTimeToNextEnvSound = 5.0f*a + 15.0f*(1.0f-a);
sTimePassed = 0;
if(regionName != cell->mRegion)
{
regionName = current->mCell->mRegion;
regionName = cell->mRegion;
total = 0;
}
const ESM::Region *regn =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Region>().search(regionName);
if (regn == NULL)
const ESM::Region *regn = world->getStore().get<ESM::Region>().search(regionName);
if(regn == NULL)
return;
std::vector<ESM::Region::SoundRef>::const_iterator soundIter;
@ -550,15 +555,13 @@ namespace MWSound
{
env = Env_Underwater;
//play underwater sound
//HACK: this sound is always played underwater, so set volume and pitch higher (it's then lowered)
//Currently not possible to play looping sound with no environment
if(!getSoundPlaying(MWWorld::Ptr(), "Underwater"))
playSound("Underwater", 1.11, 1.42 ,Play_TypeSfx, Play_Loop );
if(!(mUnderwaterSound && mUnderwaterSound->isPlaying()))
mUnderwaterSound = playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv);
}
else
else if(mUnderwaterSound)
{
//no need to check if it's playing, stop sound does nothing in that case
stopSound("Underwater");
mUnderwaterSound->stop();
mUnderwaterSound.reset();
}
mOutput->updateListener(

@ -44,6 +44,8 @@ namespace MWSound
typedef std::map<MWBase::SoundPtr,PtrIDPair> SoundMap;
SoundMap mActiveSounds;
MWBase::SoundPtr mUnderwaterSound;
Ogre::Vector3 mListenerPos;
Ogre::Vector3 mListenerDir;
Ogre::Vector3 mListenerUp;

Loading…
Cancel
Save