mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 05:53:50 +00:00
Merge remote-tracking branch 'zini/master' into animations
This commit is contained in:
commit
2822f431c4
9 changed files with 218 additions and 20 deletions
|
@ -230,6 +230,8 @@ namespace MWBase
|
|||
|
||||
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0;
|
||||
|
||||
virtual void localRotateObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
|
||||
|
||||
virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos) = 0;
|
||||
///< place an object in a "safe" location (ie not in the void, etc).
|
||||
|
||||
|
|
|
@ -318,5 +318,12 @@ op 0x20001fb: DropSoulGem, explicit reference
|
|||
op 0x20001fc: OnDeath
|
||||
op 0x20001fd: IsWerewolf
|
||||
op 0x20001fe: IsWerewolf, explicit reference
|
||||
op 0x20001ff: Rotate
|
||||
op 0x2000200: Rotate, explicit reference
|
||||
op 0x2000201: RotateWorld
|
||||
op 0x2000202: RotateWorld, explicit reference
|
||||
op 0x2000203: SetAtStart
|
||||
op 0x2000204: SetAtStart, explicit
|
||||
op 0x2000205: OnDeath, explicit
|
||||
|
||||
opcodes 0x20001ff-0x3ffffff unused
|
||||
opcodes 0x2000206-0x3ffffff unused
|
||||
|
|
|
@ -1025,16 +1025,14 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class OpOnDeath : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
Interpreter::Type_Integer value =
|
||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).hasDied();
|
||||
|
@ -1146,9 +1144,8 @@ namespace MWScript
|
|||
const int opcodeRaiseRankExplicit = 0x20001e9;
|
||||
const int opcodeLowerRank = 0x20001ea;
|
||||
const int opcodeLowerRankExplicit = 0x20001eb;
|
||||
|
||||
const int opcodeOnDeath = 0x20001fc;
|
||||
|
||||
const int opcodeOnDeathExplicit = 0x2000205;
|
||||
const int opcodeIsWerewolf = 0x20001fd;
|
||||
const int opcodeIsWerewolfExplicit = 0x20001fe;
|
||||
|
||||
|
@ -1266,7 +1263,7 @@ namespace MWScript
|
|||
extensions.registerInstruction ("raiserank", "", opcodeRaiseRank, opcodeRaiseRankExplicit);
|
||||
extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit);
|
||||
|
||||
extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath);
|
||||
extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath, opcodeOnDeathExplicit);
|
||||
|
||||
extensions.registerFunction ("iswerewolf", 'l', "", opcodeIsWerewolf, opcodeIsWerewolfExplicit);
|
||||
}
|
||||
|
@ -1384,7 +1381,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeLowerRank, new OpLowerRank<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank<ExplicitRef>);
|
||||
|
||||
interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath);
|
||||
interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeOnDeathExplicit, new OpOnDeath<ExplicitRef>);
|
||||
|
||||
interpreter.installSegment5 (opcodeIsWerewolf, new OpIsWerewolf<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeIsWerewolfExplicit, new OpIsWerewolf<ExplicitRef>);
|
||||
|
|
|
@ -84,21 +84,27 @@ namespace MWScript
|
|||
Interpreter::Type_Float angle = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
|
||||
float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees();
|
||||
float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees();
|
||||
float az = Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees();
|
||||
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
|
||||
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
|
||||
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
|
||||
|
||||
float *objRot = ptr.getRefData().getPosition().rot;
|
||||
|
||||
float lx = Ogre::Radian(objRot[0]).valueDegrees();
|
||||
float ly = Ogre::Radian(objRot[1]).valueDegrees();
|
||||
float lz = Ogre::Radian(objRot[2]).valueDegrees();
|
||||
|
||||
if (axis == "x")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az);
|
||||
MWBase::Environment::get().getWorld()->localRotateObject(ptr,angle-lx,ay,az);
|
||||
}
|
||||
else if (axis == "y")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az);
|
||||
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,angle-ly,az);
|
||||
}
|
||||
else if (axis == "z")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle);
|
||||
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,ay,angle-lz);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error ("invalid ration axis: " + axis);
|
||||
|
@ -148,15 +154,15 @@ namespace MWScript
|
|||
|
||||
if (axis=="x")
|
||||
{
|
||||
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees());
|
||||
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[0]).valueDegrees()+Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees());
|
||||
}
|
||||
else if (axis=="y")
|
||||
{
|
||||
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees());
|
||||
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[1]).valueDegrees()+Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees());
|
||||
}
|
||||
else if (axis=="z")
|
||||
{
|
||||
runtime.push(Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees());
|
||||
runtime.push(Ogre::Radian(ptr.getCellRef().mPos.rot[2]).valueDegrees()+Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees());
|
||||
}
|
||||
else
|
||||
throw std::runtime_error ("invalid ration axis: " + axis);
|
||||
|
@ -542,6 +548,96 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpRotate : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
const MWWorld::Ptr& ptr = R()(runtime);
|
||||
|
||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float rotation = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||
runtime.pop();
|
||||
|
||||
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
|
||||
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
|
||||
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
|
||||
|
||||
if (axis == "x")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax+rotation,ay,az);
|
||||
}
|
||||
else if (axis == "y")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,ay+rotation,az);
|
||||
}
|
||||
else if (axis == "z")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->localRotateObject(ptr,ax,ay,az+rotation);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error ("invalid ration axis: " + axis);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpRotateWorld : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float rotation = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||
runtime.pop();
|
||||
|
||||
float *objRot = ptr.getRefData().getPosition().rot;
|
||||
|
||||
float ax = Ogre::Radian(objRot[0]).valueDegrees();
|
||||
float ay = Ogre::Radian(objRot[1]).valueDegrees();
|
||||
float az = Ogre::Radian(objRot[2]).valueDegrees();
|
||||
|
||||
if (axis == "x")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax+rotation,ay,az);
|
||||
}
|
||||
else if (axis == "y")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay+rotation,az);
|
||||
}
|
||||
else if (axis == "z")
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,az+rotation);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error ("invalid rotation axis: " + axis);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpSetAtStart : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0,0,0,true);
|
||||
MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().mPos.pos[0],
|
||||
ptr.getCellRef().mPos.pos[1], ptr.getCellRef().mPos.pos[2]);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const int opcodeSetScale = 0x2000164;
|
||||
const int opcodeSetScaleExplicit = 0x2000165;
|
||||
const int opcodeSetAngle = 0x2000166;
|
||||
|
@ -568,6 +664,12 @@ namespace MWScript
|
|||
const int opcodePlaceAtMeExplicit = 0x200019e;
|
||||
const int opcodeModScale = 0x20001e3;
|
||||
const int opcodeModScaleExplicit = 0x20001e4;
|
||||
const int opcodeRotate = 0x20001ff;
|
||||
const int opcodeRotateExplicit = 0x2000200;
|
||||
const int opcodeRotateWorld = 0x2000201;
|
||||
const int opcodeRotateWorldExplicit = 0x2000202;
|
||||
const int opcodeSetAtStart = 0x2000203;
|
||||
const int opcodeSetAtStartExplicit = 0x2000204;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
|
@ -585,6 +687,9 @@ namespace MWScript
|
|||
extensions.registerInstruction("placeatpc","clfl",opcodePlaceAtPc);
|
||||
extensions.registerInstruction("placeatme","clfl",opcodePlaceAtMe,opcodePlaceAtMeExplicit);
|
||||
extensions.registerInstruction("modscale","f",opcodeModScale,opcodeModScaleExplicit);
|
||||
extensions.registerInstruction("rotate","cf",opcodeRotate,opcodeRotateExplicit);
|
||||
extensions.registerInstruction("rotateworld","cf",opcodeRotateWorld,opcodeRotateWorldExplicit);
|
||||
extensions.registerInstruction("setatstart","",opcodeSetAtStart,opcodeSetAtStartExplicit);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -614,6 +719,12 @@ namespace MWScript
|
|||
interpreter.installSegment5(opcodePlaceAtMeExplicit,new OpPlaceAtMe<ExplicitRef>);
|
||||
interpreter.installSegment5(opcodeModScale,new OpModScale<ImplicitRef>);
|
||||
interpreter.installSegment5(opcodeModScaleExplicit,new OpModScale<ExplicitRef>);
|
||||
interpreter.installSegment5(opcodeRotate,new OpRotate<ImplicitRef>);
|
||||
interpreter.installSegment5(opcodeRotateExplicit,new OpRotate<ExplicitRef>);
|
||||
interpreter.installSegment5(opcodeRotateWorld,new OpRotateWorld<ImplicitRef>);
|
||||
interpreter.installSegment5(opcodeRotateWorldExplicit,new OpRotateWorld<ExplicitRef>);
|
||||
interpreter.installSegment5(opcodeSetAtStart,new OpSetAtStart<ImplicitRef>);
|
||||
interpreter.installSegment5(opcodeSetAtStartExplicit,new OpSetAtStart<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace MWWorld
|
|||
mEnabled = refData.mEnabled;
|
||||
mCount = refData.mCount;
|
||||
mPosition = refData.mPosition;
|
||||
mLocalRotation = refData.mLocalRotation;
|
||||
|
||||
mCustomData = refData.mCustomData ? refData.mCustomData->clone() : 0;
|
||||
}
|
||||
|
@ -34,7 +35,11 @@ namespace MWWorld
|
|||
RefData::RefData (const ESM::CellRef& cellRef)
|
||||
: mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mPosition (cellRef.mPos),
|
||||
mCustomData (0)
|
||||
{}
|
||||
{
|
||||
mLocalRotation.rot[0]=0;
|
||||
mLocalRotation.rot[1]=0;
|
||||
mLocalRotation.rot[2]=0;
|
||||
}
|
||||
|
||||
RefData::RefData (const RefData& refData)
|
||||
: mBaseNode(0), mCustomData (0)
|
||||
|
@ -141,6 +146,11 @@ namespace MWWorld
|
|||
return mPosition;
|
||||
}
|
||||
|
||||
LocalRotation& RefData::getLocalRotation()
|
||||
{
|
||||
return mLocalRotation;
|
||||
}
|
||||
|
||||
void RefData::setCustomData (CustomData *data)
|
||||
{
|
||||
delete mCustomData;
|
||||
|
|
|
@ -18,6 +18,10 @@ namespace ESM
|
|||
|
||||
namespace MWWorld
|
||||
{
|
||||
struct LocalRotation{
|
||||
float rot[3];
|
||||
};
|
||||
|
||||
class CustomData;
|
||||
|
||||
class RefData
|
||||
|
@ -34,6 +38,8 @@ namespace MWWorld
|
|||
|
||||
ESM::Position mPosition;
|
||||
|
||||
LocalRotation mLocalRotation;
|
||||
|
||||
CustomData *mCustomData;
|
||||
|
||||
void copy (const RefData& refData);
|
||||
|
@ -78,6 +84,8 @@ namespace MWWorld
|
|||
|
||||
ESM::Position& getPosition();
|
||||
|
||||
LocalRotation& getLocalRotation();
|
||||
|
||||
void setCustomData (CustomData *data);
|
||||
///< Set custom data (potentially replacing old custom data). The ownership of \æ data is
|
||||
/// transferred to this.
|
||||
|
|
|
@ -49,7 +49,12 @@ namespace
|
|||
{
|
||||
rendering.addObject(ptr);
|
||||
class_.insertObject(ptr, physics);
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
|
||||
|
||||
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
|
||||
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
|
||||
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
|
||||
MWBase::Environment::get().getWorld()->localRotateObject(ptr, ax, ay, az);
|
||||
|
||||
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().mScale);
|
||||
class_.adjustPosition(ptr);
|
||||
}
|
||||
|
|
|
@ -818,12 +818,67 @@ namespace MWWorld
|
|||
objRot[1] = rot.y;
|
||||
objRot[2] = rot.z;
|
||||
|
||||
float fullRotateRad=Ogre::Degree(360).valueRadians();
|
||||
|
||||
while(objRot[0]>=fullRotateRad)
|
||||
objRot[0] -= fullRotateRad;
|
||||
while(objRot[1]>=fullRotateRad)
|
||||
objRot[1] -= fullRotateRad;
|
||||
while(objRot[2]>=fullRotateRad)
|
||||
objRot[2] -= fullRotateRad;
|
||||
|
||||
while(objRot[0]<=-fullRotateRad)
|
||||
objRot[0] += fullRotateRad;
|
||||
while(objRot[1]<=-fullRotateRad)
|
||||
objRot[1] += fullRotateRad;
|
||||
while(objRot[2]<=-fullRotateRad)
|
||||
objRot[2] += fullRotateRad;
|
||||
|
||||
if (ptr.getRefData().getBaseNode() != 0) {
|
||||
mPhysics->rotateObject(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::localRotateObject (const Ptr& ptr, float x, float y, float z)
|
||||
{
|
||||
if (ptr.getRefData().getBaseNode() != 0) {
|
||||
|
||||
ptr.getRefData().getLocalRotation().rot[0]=Ogre::Degree(x).valueRadians();
|
||||
ptr.getRefData().getLocalRotation().rot[1]=Ogre::Degree(y).valueRadians();
|
||||
ptr.getRefData().getLocalRotation().rot[2]=Ogre::Degree(z).valueRadians();
|
||||
|
||||
float fullRotateRad=Ogre::Degree(360).valueRadians();
|
||||
|
||||
while(ptr.getRefData().getLocalRotation().rot[0]>=fullRotateRad)
|
||||
ptr.getRefData().getLocalRotation().rot[0]-=fullRotateRad;
|
||||
while(ptr.getRefData().getLocalRotation().rot[1]>=fullRotateRad)
|
||||
ptr.getRefData().getLocalRotation().rot[1]-=fullRotateRad;
|
||||
while(ptr.getRefData().getLocalRotation().rot[2]>=fullRotateRad)
|
||||
ptr.getRefData().getLocalRotation().rot[2]-=fullRotateRad;
|
||||
|
||||
while(ptr.getRefData().getLocalRotation().rot[0]<=-fullRotateRad)
|
||||
ptr.getRefData().getLocalRotation().rot[0]+=fullRotateRad;
|
||||
while(ptr.getRefData().getLocalRotation().rot[1]<=-fullRotateRad)
|
||||
ptr.getRefData().getLocalRotation().rot[1]+=fullRotateRad;
|
||||
while(ptr.getRefData().getLocalRotation().rot[2]<=-fullRotateRad)
|
||||
ptr.getRefData().getLocalRotation().rot[2]+=fullRotateRad;
|
||||
|
||||
float *worldRot = ptr.getRefData().getPosition().rot;
|
||||
|
||||
Ogre::Quaternion worldRotQuat(Ogre::Quaternion(Ogre::Radian(-worldRot[0]), Ogre::Vector3::UNIT_X)*
|
||||
Ogre::Quaternion(Ogre::Radian(-worldRot[1]), Ogre::Vector3::UNIT_Y)*
|
||||
Ogre::Quaternion(Ogre::Radian(-worldRot[2]), Ogre::Vector3::UNIT_Z));
|
||||
|
||||
Ogre::Quaternion rot(Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-x).valueRadians()), Ogre::Vector3::UNIT_X)*
|
||||
Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-y).valueRadians()), Ogre::Vector3::UNIT_Y)*
|
||||
Ogre::Quaternion(Ogre::Radian(Ogre::Degree(-z).valueRadians()), Ogre::Vector3::UNIT_Z));
|
||||
|
||||
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot);
|
||||
mPhysics->rotateObject(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void World::adjustPosition(const Ptr &ptr)
|
||||
{
|
||||
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos[0], ptr.getRefData().getPosition().pos[1], ptr.getRefData().getPosition().pos[2]);
|
||||
|
|
|
@ -254,6 +254,8 @@ namespace MWWorld
|
|||
/// \param adjust indicates rotation should be set or adjusted
|
||||
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
|
||||
|
||||
virtual void localRotateObject (const Ptr& ptr, float x, float y, float z);
|
||||
|
||||
virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos);
|
||||
///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr.
|
||||
|
||||
|
|
Loading…
Reference in a new issue