mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-06 18:45:32 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
4894699eba
21 changed files with 240 additions and 128 deletions
|
@ -536,6 +536,9 @@ namespace MWBase
|
||||||
|
|
||||||
/// @see MWWorld::WeatherManager::getStormDirection
|
/// @see MWWorld::WeatherManager::getStormDirection
|
||||||
virtual Ogre::Vector3 getStormDirection() const = 0;
|
virtual Ogre::Vector3 getStormDirection() const = 0;
|
||||||
|
|
||||||
|
/// Resets all actors in the current active cells to their original location within that cell.
|
||||||
|
virtual void resetActors() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,7 +380,8 @@ namespace MWClass
|
||||||
|
|
||||||
bool Armor::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Armor::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
{
|
{
|
||||||
return npcServices & ESM::NPC::Armor;
|
return (npcServices & ESM::NPC::Armor)
|
||||||
|
|| ((npcServices & ESM::NPC::MagicItems) && !getEnchantment(item).empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
float Armor::getWeight(const MWWorld::Ptr &ptr) const
|
float Armor::getWeight(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -202,7 +202,8 @@ namespace MWClass
|
||||||
|
|
||||||
bool Book::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Book::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
{
|
{
|
||||||
return npcServices & ESM::NPC::Books;
|
return (npcServices & ESM::NPC::Books)
|
||||||
|
|| ((npcServices & ESM::NPC::MagicItems) && !getEnchantment(item).empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
float Book::getWeight(const MWWorld::Ptr &ptr) const
|
float Book::getWeight(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -292,7 +292,8 @@ namespace MWClass
|
||||||
|
|
||||||
bool Clothing::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Clothing::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
{
|
{
|
||||||
return npcServices & ESM::NPC::Clothing;
|
return (npcServices & ESM::NPC::Clothing)
|
||||||
|
|| ((npcServices & ESM::NPC::MagicItems) && !getEnchantment(item).empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
float Clothing::getWeight(const MWWorld::Ptr &ptr) const
|
float Clothing::getWeight(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -434,7 +434,8 @@ namespace MWClass
|
||||||
|
|
||||||
bool Weapon::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Weapon::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
{
|
{
|
||||||
return npcServices & ESM::NPC::Weapon;
|
return (npcServices & ESM::NPC::Weapon)
|
||||||
|
|| ((npcServices & ESM::NPC::MagicItems) && !getEnchantment(item).empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
float Weapon::getWeight(const MWWorld::Ptr &ptr) const
|
float Weapon::getWeight(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -280,7 +280,7 @@ namespace MWMechanics
|
||||||
|| actor1.getClass().getCreatureStats(actor1).isDead())
|
|| actor1.getClass().getCreatureStats(actor1).isDead())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ESM::Position& actor1Pos = actor2.getRefData().getPosition();
|
const ESM::Position& actor1Pos = actor1.getRefData().getPosition();
|
||||||
const ESM::Position& actor2Pos = actor2.getRefData().getPosition();
|
const ESM::Position& actor2Pos = actor2.getRefData().getPosition();
|
||||||
float sqrDist = Ogre::Vector3(actor1Pos.pos).squaredDistance(Ogre::Vector3(actor2Pos.pos));
|
float sqrDist = Ogre::Vector3(actor1Pos.pos).squaredDistance(Ogre::Vector3(actor2Pos.pos));
|
||||||
if (sqrDist > 7168*7168)
|
if (sqrDist > 7168*7168)
|
||||||
|
@ -763,7 +763,7 @@ namespace MWMechanics
|
||||||
MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr());
|
MWMechanics::CreatureStats& summonedCreatureStats = ref.getPtr().getClass().getCreatureStats(ref.getPtr());
|
||||||
|
|
||||||
// Make the summoned creature follow its master and help in fights
|
// Make the summoned creature follow its master and help in fights
|
||||||
AiFollow package(ptr.getRefData().getHandle());
|
AiFollow package(ptr.getCellRef().getRefId());
|
||||||
summonedCreatureStats.getAiSequence().stack(package, ref.getPtr());
|
summonedCreatureStats.getAiSequence().stack(package, ref.getPtr());
|
||||||
int creatureActorId = summonedCreatureStats.getActorId();
|
int creatureActorId = summonedCreatureStats.getActorId();
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,29 @@ void suggestCombatRange(int rangeTypes, float& rangeAttack, float& rangeFollow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int numEffectsToCure (const MWWorld::Ptr& actor, int effectFilter=-1)
|
||||||
|
{
|
||||||
|
int toCure=0;
|
||||||
|
const MWMechanics::ActiveSpells& activeSpells = actor.getClass().getCreatureStats(actor).getActiveSpells();
|
||||||
|
for (MWMechanics::ActiveSpells::TIterator it = activeSpells.begin(); it != activeSpells.end(); ++it)
|
||||||
|
{
|
||||||
|
const MWMechanics::ActiveSpells::ActiveSpellParams& params = it->second;
|
||||||
|
for (std::vector<MWMechanics::ActiveSpells::ActiveEffect>::const_iterator effectIt = params.mEffects.begin();
|
||||||
|
effectIt != params.mEffects.end(); ++effectIt)
|
||||||
|
{
|
||||||
|
int effectId = effectIt->mEffectId;
|
||||||
|
if (effectFilter != -1 && effectId != effectFilter)
|
||||||
|
continue;
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effectId);
|
||||||
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful
|
||||||
|
&& effectIt->mDuration > 3 // Don't attempt to cure if effect runs out shortly anyway
|
||||||
|
)
|
||||||
|
++toCure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toCure;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
|
@ -178,20 +201,24 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
// NOTE: target may be empty
|
// NOTE: target may be empty
|
||||||
|
|
||||||
float baseRating = 1;
|
float rating = 1;
|
||||||
switch (effect.mEffectID)
|
switch (effect.mEffectID)
|
||||||
{
|
{
|
||||||
case ESM::MagicEffect::Soultrap:
|
case ESM::MagicEffect::Soultrap:
|
||||||
case ESM::MagicEffect::AlmsiviIntervention:
|
case ESM::MagicEffect::AlmsiviIntervention:
|
||||||
case ESM::MagicEffect::DivineIntervention:
|
case ESM::MagicEffect::DivineIntervention:
|
||||||
case ESM::MagicEffect::CalmCreature:
|
|
||||||
case ESM::MagicEffect::CalmHumanoid:
|
case ESM::MagicEffect::CalmHumanoid:
|
||||||
|
case ESM::MagicEffect::CalmCreature:
|
||||||
|
case ESM::MagicEffect::FrenzyHumanoid:
|
||||||
|
case ESM::MagicEffect::FrenzyCreature:
|
||||||
|
case ESM::MagicEffect::DemoralizeHumanoid:
|
||||||
|
case ESM::MagicEffect::DemoralizeCreature:
|
||||||
|
case ESM::MagicEffect::RallyHumanoid:
|
||||||
|
case ESM::MagicEffect::RallyCreature:
|
||||||
case ESM::MagicEffect::Charm:
|
case ESM::MagicEffect::Charm:
|
||||||
case ESM::MagicEffect::DetectAnimal:
|
case ESM::MagicEffect::DetectAnimal:
|
||||||
case ESM::MagicEffect::DetectEnchantment:
|
case ESM::MagicEffect::DetectEnchantment:
|
||||||
case ESM::MagicEffect::DetectKey:
|
case ESM::MagicEffect::DetectKey:
|
||||||
case ESM::MagicEffect::FrenzyCreature:
|
|
||||||
case ESM::MagicEffect::FrenzyHumanoid:
|
|
||||||
case ESM::MagicEffect::Telekinesis:
|
case ESM::MagicEffect::Telekinesis:
|
||||||
case ESM::MagicEffect::Mark:
|
case ESM::MagicEffect::Mark:
|
||||||
case ESM::MagicEffect::Recall:
|
case ESM::MagicEffect::Recall:
|
||||||
|
@ -204,16 +231,39 @@ namespace MWMechanics
|
||||||
case ESM::MagicEffect::Lock:
|
case ESM::MagicEffect::Lock:
|
||||||
case ESM::MagicEffect::Open:
|
case ESM::MagicEffect::Open:
|
||||||
case ESM::MagicEffect::TurnUndead:
|
case ESM::MagicEffect::TurnUndead:
|
||||||
|
case ESM::MagicEffect::WeaknessToCommonDisease:
|
||||||
|
case ESM::MagicEffect::WeaknessToBlightDisease:
|
||||||
|
case ESM::MagicEffect::WeaknessToCorprusDisease:
|
||||||
|
case ESM::MagicEffect::CureCommonDisease:
|
||||||
|
case ESM::MagicEffect::CureBlightDisease:
|
||||||
|
case ESM::MagicEffect::CureCorprusDisease:
|
||||||
|
case ESM::MagicEffect::Invisibility:
|
||||||
return 0.f;
|
return 0.f;
|
||||||
case ESM::MagicEffect::Feather:
|
case ESM::MagicEffect::Feather:
|
||||||
return 0.f; // TODO: check if target is overencumbered
|
if (actor.getClass().getEncumbrance(actor) - actor.getClass().getCapacity(actor) >= 0)
|
||||||
|
return 100.f;
|
||||||
|
else
|
||||||
|
return 0.f;
|
||||||
case ESM::MagicEffect::Levitate:
|
case ESM::MagicEffect::Levitate:
|
||||||
return 0.f; // AI isn't designed to take advantage of this, and could be perceived as unfair anyway
|
return 0.f; // AI isn't designed to take advantage of this, and could be perceived as unfair anyway
|
||||||
// TODO: check if Beast race (can't wear boots or helm)
|
|
||||||
/*
|
|
||||||
case ESM::MagicEffect::BoundBoots:
|
case ESM::MagicEffect::BoundBoots:
|
||||||
case ESM::MagicEffect::BoundHelm:
|
case ESM::MagicEffect::BoundHelm:
|
||||||
*/
|
if (actor.getClass().isNpc())
|
||||||
|
{
|
||||||
|
// Beast races can't wear helmets or boots
|
||||||
|
std::string raceid = actor.get<ESM::NPC>()->mBase->mRace;
|
||||||
|
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(raceid);
|
||||||
|
if (race->mData.mFlags & ESM::Race::Beast)
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
// Intended fall-through
|
||||||
|
// Creatures can not wear armor
|
||||||
|
case ESM::MagicEffect::BoundCuirass:
|
||||||
|
case ESM::MagicEffect::BoundGloves:
|
||||||
|
if (!actor.getClass().isNpc())
|
||||||
|
return 0.f;
|
||||||
|
break;
|
||||||
|
|
||||||
case ESM::MagicEffect::RestoreHealth:
|
case ESM::MagicEffect::RestoreHealth:
|
||||||
case ESM::MagicEffect::RestoreMagicka:
|
case ESM::MagicEffect::RestoreMagicka:
|
||||||
case ESM::MagicEffect::RestoreFatigue:
|
case ESM::MagicEffect::RestoreFatigue:
|
||||||
|
@ -231,25 +281,13 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Give a small boost to all direct damage effects. This is combat, after all!
|
// Prefer Cure effects over Dispel, because Dispel also removes positive effects
|
||||||
case ESM::MagicEffect::FireDamage:
|
|
||||||
case ESM::MagicEffect::ShockDamage:
|
|
||||||
case ESM::MagicEffect::FrostDamage:
|
|
||||||
case ESM::MagicEffect::Poison:
|
|
||||||
case ESM::MagicEffect::AbsorbHealth:
|
|
||||||
case ESM::MagicEffect::DamageHealth:
|
|
||||||
baseRating *= 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESM::MagicEffect::Paralyze: // *Evil laughter*
|
|
||||||
baseRating *= 5;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO: rate these effects very high if we are currently suffering from negative effects that could be cured
|
|
||||||
case ESM::MagicEffect::Dispel:
|
case ESM::MagicEffect::Dispel:
|
||||||
|
return 1000.f * numEffectsToCure(actor);
|
||||||
case ESM::MagicEffect::CureParalyzation:
|
case ESM::MagicEffect::CureParalyzation:
|
||||||
|
return 1001.f * numEffectsToCure(actor, ESM::MagicEffect::Paralyze);
|
||||||
case ESM::MagicEffect::CurePoison:
|
case ESM::MagicEffect::CurePoison:
|
||||||
break;
|
return 1001.f * numEffectsToCure(actor, ESM::MagicEffect::Poison);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -261,12 +299,10 @@ namespace MWMechanics
|
||||||
|
|
||||||
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
||||||
|
|
||||||
baseRating *= magicEffect->mData.mBaseCost;
|
rating *= magicEffect->mData.mBaseCost;
|
||||||
|
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
|
||||||
return 0.f; // No clue how useful this would be; will need special cases for each effect
|
rating *= (effect.mMagnMin + effect.mMagnMax)/2.f;
|
||||||
|
|
||||||
float rating = baseRating * (effect.mMagnMin + effect.mMagnMax)/2.f;
|
|
||||||
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
||||||
rating *= effect.mDuration;
|
rating *= effect.mDuration;
|
||||||
|
|
||||||
|
|
|
@ -406,7 +406,11 @@ namespace MWMechanics
|
||||||
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
|
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
|
||||||
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
|
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
|
||||||
|
|
||||||
if (roll < fVoiceIdleOdds && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos)) < 1500*1500)
|
// Only say Idle voices when player is in LOS
|
||||||
|
// A bit counterintuitive, likely vanilla did this to reduce the appearance of
|
||||||
|
// voices going through walls?
|
||||||
|
if (roll < fVoiceIdleOdds && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos)) < 1500*1500
|
||||||
|
&& MWBase::Environment::get().getWorld()->getLOS(player, actor))
|
||||||
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
|
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -684,9 +684,23 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (item.getCellRef().getEnchantmentCharge() < castCost)
|
if (item.getCellRef().getEnchantmentCharge() < castCost)
|
||||||
{
|
{
|
||||||
// TODO: Should there be a sound here?
|
|
||||||
if (mCaster.getRefData().getHandle() == "player")
|
if (mCaster.getRefData().getHandle() == "player")
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicInsufficientCharge}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicInsufficientCharge}");
|
||||||
|
|
||||||
|
// Failure sound
|
||||||
|
int school = 0;
|
||||||
|
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt (enchantment->mEffects.mList.begin());
|
||||||
|
effectIt!=enchantment->mEffects.mList.end(); ++effectIt)
|
||||||
|
{
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effectIt->mEffectID);
|
||||||
|
school = magicEffect->mData.mSchool;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
static const std::string schools[] = {
|
||||||
|
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
||||||
|
};
|
||||||
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
|
sndMgr->playSound3D(mCaster, "Spell Failure " + schools[school], 1.0f, 1.0f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Reduce charge
|
// Reduce charge
|
||||||
|
|
|
@ -384,10 +384,11 @@ void Water::update(float dt, Ogre::Vector3 player)
|
||||||
|
|
||||||
void Water::frameStarted(float dt)
|
void Water::frameStarted(float dt)
|
||||||
{
|
{
|
||||||
mSimulation->update(dt, mPlayer);
|
|
||||||
|
|
||||||
if (mReflection)
|
if (mReflection)
|
||||||
|
{
|
||||||
|
mSimulation->update(dt, mPlayer);
|
||||||
mReflection->update();
|
mReflection->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::applyRTT()
|
void Water::applyRTT()
|
||||||
|
|
|
@ -431,5 +431,6 @@ op 0x2000294-0x20002ab: SetMagicEffect
|
||||||
op 0x20002ac-0x20002c3: SetMagicEffect, explicit
|
op 0x20002ac-0x20002c3: SetMagicEffect, explicit
|
||||||
op 0x20002c4-0x20002db: ModMagicEffect
|
op 0x20002c4-0x20002db: ModMagicEffect
|
||||||
op 0x20002dc-0x20002f3: ModMagicEffect, explicit
|
op 0x20002dc-0x20002f3: ModMagicEffect, explicit
|
||||||
|
op 0x20002f4: ResetActors
|
||||||
|
|
||||||
opcodes 0x20002f4-0x3ffffff unused
|
opcodes 0x20002f5-0x3ffffff unused
|
||||||
|
|
|
@ -719,6 +719,15 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OpResetActors : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->resetActors();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
|
@ -759,6 +768,7 @@ namespace MWScript
|
||||||
interpreter.installSegment5(Compiler::Transformation::opcodeMoveWorldExplicit,new OpMoveWorld<ExplicitRef>);
|
interpreter.installSegment5(Compiler::Transformation::opcodeMoveWorldExplicit,new OpMoveWorld<ExplicitRef>);
|
||||||
interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngle, new OpGetStartingAngle<ImplicitRef>);
|
interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngle, new OpGetStartingAngle<ImplicitRef>);
|
||||||
interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngleExplicit, new OpGetStartingAngle<ExplicitRef>);
|
interpreter.installSegment5(Compiler::Transformation::opcodeGetStartingAngleExplicit, new OpGetStartingAngle<ExplicitRef>);
|
||||||
|
interpreter.installSegment5(Compiler::Transformation::opcodeResetActors, new OpResetActors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,7 +358,7 @@ namespace MWWorld
|
||||||
Class::copyToCell(const Ptr &ptr, CellStore &cell) const
|
Class::copyToCell(const Ptr &ptr, CellStore &cell) const
|
||||||
{
|
{
|
||||||
Ptr newPtr = copyToCellImpl(ptr, cell);
|
Ptr newPtr = copyToCellImpl(ptr, cell);
|
||||||
|
newPtr.getCellRef().unsetRefNum(); // This RefNum is only valid within the original cell of the reference
|
||||||
return newPtr;
|
return newPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2989,4 +2989,31 @@ namespace MWWorld
|
||||||
if (!interpreterContext.hasActivationBeenHandled())
|
if (!interpreterContext.hasActivationBeenHandled())
|
||||||
interpreterContext.executeActivation(object, actor);
|
interpreterContext.executeActivation(object, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ResetActorsFunctor
|
||||||
|
{
|
||||||
|
bool operator() (Ptr ptr)
|
||||||
|
{
|
||||||
|
// Can't reset actors that were moved to a different cell, because we don't know what cell they came from.
|
||||||
|
// This could be fixed once we properly track actor cell changes, but may not be desirable behaviour anyhow.
|
||||||
|
if (ptr.getClass().isActor() && ptr.getCellRef().getRefNum().mContentFile != -1)
|
||||||
|
{
|
||||||
|
const ESM::Position& origPos = ptr.getCellRef().getPosition();
|
||||||
|
MWBase::Environment::get().getWorld()->moveObject(ptr, origPos.pos[0], origPos.pos[1], origPos.pos[2]);
|
||||||
|
MWBase::Environment::get().getWorld()->rotateObject(ptr, origPos.rot[0], origPos.rot[1], origPos.rot[2]);
|
||||||
|
ptr.getClass().adjustPosition(ptr, false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void World::resetActors()
|
||||||
|
{
|
||||||
|
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
|
||||||
|
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
||||||
|
{
|
||||||
|
CellStore* cellstore = *iter;
|
||||||
|
ResetActorsFunctor functor;
|
||||||
|
cellstore->forEach(functor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -611,6 +611,9 @@ namespace MWWorld
|
||||||
|
|
||||||
/// @see MWWorld::WeatherManager::getStormDirection
|
/// @see MWWorld::WeatherManager::getStormDirection
|
||||||
virtual Ogre::Vector3 getStormDirection() const;
|
virtual Ogre::Vector3 getStormDirection() const;
|
||||||
|
|
||||||
|
/// Resets all actors in the current active cells to their original location within that cell.
|
||||||
|
virtual void resetActors();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -527,6 +527,8 @@ namespace Compiler
|
||||||
extensions.registerInstruction("move","cf",opcodeMove,opcodeMoveExplicit);
|
extensions.registerInstruction("move","cf",opcodeMove,opcodeMoveExplicit);
|
||||||
extensions.registerInstruction("moveworld","cf",opcodeMoveWorld,opcodeMoveWorldExplicit);
|
extensions.registerInstruction("moveworld","cf",opcodeMoveWorld,opcodeMoveWorldExplicit);
|
||||||
extensions.registerFunction("getstartingangle",'f',"c",opcodeGetStartingAngle,opcodeGetStartingAngleExplicit);
|
extensions.registerFunction("getstartingangle",'f',"c",opcodeGetStartingAngle,opcodeGetStartingAngleExplicit);
|
||||||
|
extensions.registerInstruction("resetactors","",opcodeResetActors);
|
||||||
|
extensions.registerInstruction("ra","",opcodeResetActors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -484,6 +484,7 @@ namespace Compiler
|
||||||
const int opcodeMoveExplicit = 0x2000207;
|
const int opcodeMoveExplicit = 0x2000207;
|
||||||
const int opcodeMoveWorld = 0x2000208;
|
const int opcodeMoveWorld = 0x2000208;
|
||||||
const int opcodeMoveWorldExplicit = 0x2000209;
|
const int opcodeMoveWorldExplicit = 0x2000209;
|
||||||
|
const int opcodeResetActors = 0x20002f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace User
|
namespace User
|
||||||
|
|
|
@ -210,7 +210,7 @@ public:
|
||||||
class NiPosData : public Record
|
class NiPosData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Vector3KeyList mKeyList;
|
Vector3KeyMap mKeyList;
|
||||||
|
|
||||||
void read(NIFStream *nif)
|
void read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
|
@ -221,7 +221,7 @@ public:
|
||||||
class NiUVData : public Record
|
class NiUVData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FloatKeyList mKeyList[4];
|
FloatKeyMap mKeyList[4];
|
||||||
|
|
||||||
void read(NIFStream *nif)
|
void read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
|
@ -233,7 +233,7 @@ public:
|
||||||
class NiFloatData : public Record
|
class NiFloatData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FloatKeyList mKeyList;
|
FloatKeyMap mKeyList;
|
||||||
|
|
||||||
void read(NIFStream *nif)
|
void read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
|
@ -283,11 +283,11 @@ public:
|
||||||
class NiColorData : public Record
|
class NiColorData : public Record
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Vector4KeyList mKeyList;
|
Vector4KeyMap mKeyMap;
|
||||||
|
|
||||||
void read(NIFStream *nif)
|
void read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
mKeyList.read(nif);
|
mKeyMap.read(nif);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ public:
|
||||||
struct NiMorphData : public Record
|
struct NiMorphData : public Record
|
||||||
{
|
{
|
||||||
struct MorphData {
|
struct MorphData {
|
||||||
FloatKeyList mData;
|
FloatKeyMap mData;
|
||||||
std::vector<Ogre::Vector3> mVertices;
|
std::vector<Ogre::Vector3> mVertices;
|
||||||
};
|
};
|
||||||
std::vector<MorphData> mMorphs;
|
std::vector<MorphData> mMorphs;
|
||||||
|
@ -411,11 +411,11 @@ struct NiMorphData : public Record
|
||||||
|
|
||||||
struct NiKeyframeData : public Record
|
struct NiKeyframeData : public Record
|
||||||
{
|
{
|
||||||
QuaternionKeyList mRotations;
|
QuaternionKeyMap mRotations;
|
||||||
//\FIXME mXYZ_Keys are read, but not used.
|
//\FIXME mXYZ_Keys are read, but not used.
|
||||||
FloatKeyList mXYZ_Keys;
|
FloatKeyMap mXYZ_Keys;
|
||||||
Vector3KeyList mTranslations;
|
Vector3KeyMap mTranslations;
|
||||||
FloatKeyList mScales;
|
FloatKeyMap mScales;
|
||||||
|
|
||||||
void read(NIFStream *nif)
|
void read(NIFStream *nif)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,6 @@ namespace Nif
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct KeyT {
|
struct KeyT {
|
||||||
float mTime;
|
|
||||||
T mValue;
|
T mValue;
|
||||||
T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
||||||
T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList
|
||||||
|
@ -26,8 +25,8 @@ typedef KeyT<Ogre::Vector4> Vector4Key;
|
||||||
typedef KeyT<Ogre::Quaternion> QuaternionKey;
|
typedef KeyT<Ogre::Quaternion> QuaternionKey;
|
||||||
|
|
||||||
template<typename T, T (NIFStream::*getValue)()>
|
template<typename T, T (NIFStream::*getValue)()>
|
||||||
struct KeyListT {
|
struct KeyMapT {
|
||||||
typedef std::vector< KeyT<T> > VecType;
|
typedef std::map< float, KeyT<T> > MapType;
|
||||||
|
|
||||||
static const unsigned int sLinearInterpolation = 1;
|
static const unsigned int sLinearInterpolation = 1;
|
||||||
static const unsigned int sQuadraticInterpolation = 2;
|
static const unsigned int sQuadraticInterpolation = 2;
|
||||||
|
@ -35,9 +34,9 @@ struct KeyListT {
|
||||||
static const unsigned int sXYZInterpolation = 4;
|
static const unsigned int sXYZInterpolation = 4;
|
||||||
|
|
||||||
unsigned int mInterpolationType;
|
unsigned int mInterpolationType;
|
||||||
VecType mKeys;
|
MapType mKeys;
|
||||||
|
|
||||||
KeyListT() : mInterpolationType(sLinearInterpolation) {}
|
KeyMapT() : mInterpolationType(sLinearInterpolation) {}
|
||||||
|
|
||||||
//Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html)
|
//Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html)
|
||||||
void read(NIFStream *nif, bool force=false)
|
void read(NIFStream *nif, bool force=false)
|
||||||
|
@ -63,24 +62,27 @@ struct KeyListT {
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < count;i++)
|
for(size_t i = 0;i < count;i++)
|
||||||
{
|
{
|
||||||
readTimeAndValue(nifReference, key);
|
float time = nif->getFloat();
|
||||||
mKeys.push_back(key);
|
readValue(nifReference, key);
|
||||||
|
mKeys[time] = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(mInterpolationType == sQuadraticInterpolation)
|
else if(mInterpolationType == sQuadraticInterpolation)
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < count;i++)
|
for(size_t i = 0;i < count;i++)
|
||||||
{
|
{
|
||||||
|
float time = nif->getFloat();
|
||||||
readQuadratic(nifReference, key);
|
readQuadratic(nifReference, key);
|
||||||
mKeys.push_back(key);
|
mKeys[time] = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(mInterpolationType == sTBCInterpolation)
|
else if(mInterpolationType == sTBCInterpolation)
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < count;i++)
|
for(size_t i = 0;i < count;i++)
|
||||||
{
|
{
|
||||||
|
float time = nif->getFloat();
|
||||||
readTBC(nifReference, key);
|
readTBC(nifReference, key);
|
||||||
mKeys.push_back(key);
|
mKeys[time] = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//XYZ keys aren't actually read here.
|
//XYZ keys aren't actually read here.
|
||||||
|
@ -104,37 +106,36 @@ struct KeyListT {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void readTimeAndValue(NIFStream &nif, KeyT<T> &key)
|
static void readValue(NIFStream &nif, KeyT<T> &key)
|
||||||
{
|
{
|
||||||
key.mTime = nif.getFloat();
|
|
||||||
key.mValue = (nif.*getValue)();
|
key.mValue = (nif.*getValue)();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key)
|
static void readQuadratic(NIFStream &nif, KeyT<Ogre::Quaternion> &key)
|
||||||
{
|
{
|
||||||
readTimeAndValue(nif, key);
|
readValue(nif, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
|
static void readQuadratic(NIFStream &nif, KeyT<U> &key)
|
||||||
{
|
{
|
||||||
readTimeAndValue(nif, key);
|
readValue(nif, key);
|
||||||
key.mForwardValue = (nif.*getValue)();
|
key.mForwardValue = (nif.*getValue)();
|
||||||
key.mBackwardValue = (nif.*getValue)();
|
key.mBackwardValue = (nif.*getValue)();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readTBC(NIFStream &nif, KeyT<T> &key)
|
static void readTBC(NIFStream &nif, KeyT<T> &key)
|
||||||
{
|
{
|
||||||
readTimeAndValue(nif, key);
|
readValue(nif, key);
|
||||||
key.mTension = nif.getFloat();
|
key.mTension = nif.getFloat();
|
||||||
key.mBias = nif.getFloat();
|
key.mBias = nif.getFloat();
|
||||||
key.mContinuity = nif.getFloat();
|
key.mContinuity = nif.getFloat();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
typedef KeyListT<float,&NIFStream::getFloat> FloatKeyList;
|
typedef KeyMapT<float,&NIFStream::getFloat> FloatKeyMap;
|
||||||
typedef KeyListT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyList;
|
typedef KeyMapT<Ogre::Vector3,&NIFStream::getVector3> Vector3KeyMap;
|
||||||
typedef KeyListT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyList;
|
typedef KeyMapT<Ogre::Vector4,&NIFStream::getVector4> Vector4KeyMap;
|
||||||
typedef KeyListT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyList;
|
typedef KeyMapT<Ogre::Quaternion,&NIFStream::getQuaternion> QuaternionKeyMap;
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
|
@ -2,6 +2,7 @@
|
||||||
#define COMPONENTS_NIFOGRE_CONTROLLER_H
|
#define COMPONENTS_NIFOGRE_CONTROLLER_H
|
||||||
|
|
||||||
#include <components/nif/niffile.hpp>
|
#include <components/nif/niffile.hpp>
|
||||||
|
#include <components/nif/nifkey.hpp>
|
||||||
#include <OgreController.h>
|
#include <OgreController.h>
|
||||||
|
|
||||||
namespace NifOgre
|
namespace NifOgre
|
||||||
|
@ -10,53 +11,55 @@ namespace NifOgre
|
||||||
class ValueInterpolator
|
class ValueInterpolator
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
float interpKey(const Nif::FloatKeyList::VecType &keys, float time, float def=0.f) const
|
float interpKey(const Nif::FloatKeyMap::MapType &keys, float time, float def=0.f) const
|
||||||
{
|
{
|
||||||
if (keys.size() == 0)
|
if (keys.size() == 0)
|
||||||
return def;
|
return def;
|
||||||
|
|
||||||
if(time <= keys.front().mTime)
|
if(time <= keys.begin()->first)
|
||||||
return keys.front().mValue;
|
return keys.begin()->second.mValue;
|
||||||
|
|
||||||
const Nif::FloatKey* keyArray = keys.data();
|
Nif::FloatKeyMap::MapType::const_iterator it = keys.lower_bound(time);
|
||||||
size_t size = keys.size();
|
if (it != keys.end())
|
||||||
|
|
||||||
for (size_t i = 1; i < size; ++i)
|
|
||||||
{
|
{
|
||||||
const Nif::FloatKey* aKey = &keyArray[i];
|
float aTime = it->first;
|
||||||
|
const Nif::FloatKey* aKey = &it->second;
|
||||||
|
|
||||||
if(aKey->mTime < time)
|
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
|
||||||
continue;
|
|
||||||
|
|
||||||
const Nif::FloatKey* aLastKey = &keyArray[i-1];
|
Nif::FloatKeyMap::MapType::const_iterator last = --it;
|
||||||
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
|
float aLastTime = last->first;
|
||||||
|
const Nif::FloatKey* aLastKey = &last->second;
|
||||||
|
|
||||||
|
float a = (time - aLastTime) / (aTime - aLastTime);
|
||||||
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
|
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return keys.back().mValue;
|
return keys.rbegin()->second.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Vector3 interpKey(const Nif::Vector3KeyList::VecType &keys, float time) const
|
Ogre::Vector3 interpKey(const Nif::Vector3KeyMap::MapType &keys, float time) const
|
||||||
{
|
{
|
||||||
if(time <= keys.front().mTime)
|
if(time <= keys.begin()->first)
|
||||||
return keys.front().mValue;
|
return keys.begin()->second.mValue;
|
||||||
|
|
||||||
const Nif::Vector3Key* keyArray = keys.data();
|
Nif::Vector3KeyMap::MapType::const_iterator it = keys.lower_bound(time);
|
||||||
size_t size = keys.size();
|
if (it != keys.end())
|
||||||
|
|
||||||
for (size_t i = 1; i < size; ++i)
|
|
||||||
{
|
{
|
||||||
const Nif::Vector3Key* aKey = &keyArray[i];
|
float aTime = it->first;
|
||||||
|
const Nif::Vector3Key* aKey = &it->second;
|
||||||
|
|
||||||
if(aKey->mTime < time)
|
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
|
||||||
continue;
|
|
||||||
|
|
||||||
const Nif::Vector3Key* aLastKey = &keyArray[i-1];
|
Nif::Vector3KeyMap::MapType::const_iterator last = --it;
|
||||||
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
|
float aLastTime = last->first;
|
||||||
|
const Nif::Vector3Key* aLastKey = &last->second;
|
||||||
|
|
||||||
|
float a = (time - aLastTime) / (aTime - aLastTime);
|
||||||
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
|
return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return keys.back().mValue;
|
return keys.rbegin()->second.mValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,7 @@ public:
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Ogre::MovableObject* mMovable;
|
Ogre::MovableObject* mMovable;
|
||||||
Nif::FloatKeyList mData;
|
Nif::FloatKeyMap mData;
|
||||||
MaterialControllerManager* mMaterialControllerMgr;
|
MaterialControllerManager* mMaterialControllerMgr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -284,7 +284,7 @@ public:
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Ogre::MovableObject* mMovable;
|
Ogre::MovableObject* mMovable;
|
||||||
Nif::Vector3KeyList mData;
|
Nif::Vector3KeyMap mData;
|
||||||
MaterialControllerManager* mMaterialControllerMgr;
|
MaterialControllerManager* mMaterialControllerMgr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -409,34 +409,35 @@ public:
|
||||||
class Value : public NodeTargetValue<Ogre::Real>, public ValueInterpolator
|
class Value : public NodeTargetValue<Ogre::Real>, public ValueInterpolator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
const Nif::QuaternionKeyList* mRotations;
|
const Nif::QuaternionKeyMap* mRotations;
|
||||||
const Nif::Vector3KeyList* mTranslations;
|
const Nif::Vector3KeyMap* mTranslations;
|
||||||
const Nif::FloatKeyList* mScales;
|
const Nif::FloatKeyMap* mScales;
|
||||||
Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid
|
Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid
|
||||||
|
|
||||||
using ValueInterpolator::interpKey;
|
using ValueInterpolator::interpKey;
|
||||||
|
|
||||||
static Ogre::Quaternion interpKey(const Nif::QuaternionKeyList::VecType &keys, float time)
|
static Ogre::Quaternion interpKey(const Nif::QuaternionKeyMap::MapType &keys, float time)
|
||||||
{
|
{
|
||||||
if(time <= keys.front().mTime)
|
if(time <= keys.begin()->first)
|
||||||
return keys.front().mValue;
|
return keys.begin()->second.mValue;
|
||||||
|
|
||||||
const Nif::QuaternionKey* keyArray = keys.data();
|
Nif::QuaternionKeyMap::MapType::const_iterator it = keys.lower_bound(time);
|
||||||
size_t size = keys.size();
|
if (it != keys.end())
|
||||||
|
|
||||||
for (size_t i = 1; i < size; ++i)
|
|
||||||
{
|
{
|
||||||
const Nif::QuaternionKey* aKey = &keyArray[i];
|
float aTime = it->first;
|
||||||
|
const Nif::QuaternionKey* aKey = &it->second;
|
||||||
|
|
||||||
if(aKey->mTime < time)
|
assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function
|
||||||
continue;
|
|
||||||
|
|
||||||
const Nif::QuaternionKey* aLastKey = &keyArray[i-1];
|
Nif::QuaternionKeyMap::MapType::const_iterator last = --it;
|
||||||
float a = (time - aLastKey->mTime) / (aKey->mTime - aLastKey->mTime);
|
float aLastTime = last->first;
|
||||||
|
const Nif::QuaternionKey* aLastKey = &last->second;
|
||||||
|
|
||||||
|
float a = (time - aLastTime) / (aTime - aLastTime);
|
||||||
return Ogre::Quaternion::nlerp(a, aLastKey->mValue, aKey->mValue);
|
return Ogre::Quaternion::nlerp(a, aLastKey->mValue, aKey->mValue);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return keys.back().mValue;
|
return keys.rbegin()->second.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -497,10 +498,10 @@ public:
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Ogre::MovableObject* mMovable;
|
Ogre::MovableObject* mMovable;
|
||||||
Nif::FloatKeyList mUTrans;
|
Nif::FloatKeyMap mUTrans;
|
||||||
Nif::FloatKeyList mVTrans;
|
Nif::FloatKeyMap mVTrans;
|
||||||
Nif::FloatKeyList mUScale;
|
Nif::FloatKeyMap mUScale;
|
||||||
Nif::FloatKeyList mVScale;
|
Nif::FloatKeyMap mVScale;
|
||||||
MaterialControllerManager* mMaterialControllerMgr;
|
MaterialControllerManager* mMaterialControllerMgr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -839,18 +840,19 @@ class NIFObjectLoader
|
||||||
const Nif::NiColorData *clrdata = cl->data.getPtr();
|
const Nif::NiColorData *clrdata = cl->data.getPtr();
|
||||||
|
|
||||||
Ogre::ParticleAffector *affector = partsys->addAffector("ColourInterpolator");
|
Ogre::ParticleAffector *affector = partsys->addAffector("ColourInterpolator");
|
||||||
size_t num_colors = std::min<size_t>(6, clrdata->mKeyList.mKeys.size());
|
size_t num_colors = std::min<size_t>(6, clrdata->mKeyMap.mKeys.size());
|
||||||
for(size_t i = 0;i < num_colors;i++)
|
unsigned int i=0;
|
||||||
|
for (Nif::Vector4KeyMap::MapType::const_iterator it = clrdata->mKeyMap.mKeys.begin(); it != clrdata->mKeyMap.mKeys.end() && i < num_colors; ++it,++i)
|
||||||
{
|
{
|
||||||
Ogre::ColourValue color;
|
Ogre::ColourValue color;
|
||||||
color.r = clrdata->mKeyList.mKeys[i].mValue[0];
|
color.r = it->second.mValue[0];
|
||||||
color.g = clrdata->mKeyList.mKeys[i].mValue[1];
|
color.g = it->second.mValue[1];
|
||||||
color.b = clrdata->mKeyList.mKeys[i].mValue[2];
|
color.b = it->second.mValue[2];
|
||||||
color.a = clrdata->mKeyList.mKeys[i].mValue[3];
|
color.a = it->second.mValue[3];
|
||||||
affector->setParameter("colour"+Ogre::StringConverter::toString(i),
|
affector->setParameter("colour"+Ogre::StringConverter::toString(i),
|
||||||
Ogre::StringConverter::toString(color));
|
Ogre::StringConverter::toString(color));
|
||||||
affector->setParameter("time"+Ogre::StringConverter::toString(i),
|
affector->setParameter("time"+Ogre::StringConverter::toString(i),
|
||||||
Ogre::StringConverter::toString(clrdata->mKeyList.mKeys[i].mTime));
|
Ogre::StringConverter::toString(it->first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(e->recType == Nif::RC_NiParticleRotation)
|
else if(e->recType == Nif::RC_NiParticleRotation)
|
||||||
|
|
Loading…
Reference in a new issue