forked from teamnwah/openmw-tes3coop
Merge branch 'master' of git://github.com/zinnschlag/openmw into companion
This commit is contained in:
commit
1a2daa3bc1
41 changed files with 490 additions and 160 deletions
|
@ -627,10 +627,10 @@ std::string bodyPartFlags(int flags)
|
|||
std::string properties = "";
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
|
||||
if (flags & ESM::BodyPart::BPF_Playable) properties += "Playable ";
|
||||
if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::BodyPart::BPF_Female|
|
||||
ESM::BodyPart::BPF_Playable));
|
||||
ESM::BodyPart::BPF_NotPlayable));
|
||||
if (flags & unused) properties += "Invalid ";
|
||||
properties += str(boost::format("(0x%08X)") % flags);
|
||||
return properties;
|
||||
|
|
|
@ -207,7 +207,7 @@ void CSMDoc::Document::createBase()
|
|||
{
|
||||
ESM::Skill record;
|
||||
record.mIndex = i;
|
||||
record.mId = ESM::Skill::getIndexToId (record.mIndex);
|
||||
record.mId = ESM::Skill::indexToId (record.mIndex);
|
||||
record.blank();
|
||||
|
||||
getData().getSkills().add (record);
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace CSMWorld
|
|||
Display_GmstVarType,
|
||||
Display_GlobalVarType,
|
||||
Display_Specialisation,
|
||||
Display_Attribute
|
||||
Display_Attribute,
|
||||
Display_Boolean
|
||||
};
|
||||
|
||||
std::string mTitle;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef CSM_WOLRD_COLUMNS_H
|
||||
#define CSM_WOLRD_COLUMNS_H
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "columnbase.hpp"
|
||||
|
@ -285,6 +287,128 @@ namespace CSMWorld
|
|||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct NameColumn : public Column<ESXRecordT>
|
||||
{
|
||||
NameColumn() : Column<ESXRecordT> ("Name", ColumnBase::Display_String) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return QString::fromUtf8 (record.get().mName.c_str());
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
|
||||
record2.mName = data.toString().toUtf8().constData();
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct AttributesColumn : public Column<ESXRecordT>
|
||||
{
|
||||
int mIndex;
|
||||
|
||||
AttributesColumn (int index)
|
||||
: Column<ESXRecordT> ("Attribute #" + boost::lexical_cast<std::string> (index),
|
||||
ColumnBase::Display_Attribute), mIndex (index) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return record.get().mData.mAttribute[mIndex];
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
|
||||
record2.mData.mAttribute[mIndex] = data.toInt();
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct SkillsColumn : public Column<ESXRecordT>
|
||||
{
|
||||
int mIndex;
|
||||
bool mMajor;
|
||||
|
||||
SkillsColumn (int index, bool major)
|
||||
: Column<ESXRecordT> ((major ? "Major Skill #" : "Minor Skill #")+
|
||||
boost::lexical_cast<std::string> (index), ColumnBase::Display_String),
|
||||
mIndex (index), mMajor (major)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
int skill = record.get().mData.mSkills[mIndex][mMajor ? 1 : 0];
|
||||
|
||||
return QString::fromUtf8 (ESM::Skill::indexToId (skill).c_str());
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
std::istringstream stream (data.toString().toUtf8().constData());
|
||||
|
||||
int index = -1;
|
||||
char c;
|
||||
|
||||
stream >> c >> index;
|
||||
|
||||
if (index!=-1)
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
|
||||
record2.mData.mSkills[mIndex][mMajor ? 1 : 0] = index;
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct PlayableColumn : public Column<ESXRecordT>
|
||||
{
|
||||
PlayableColumn() : Column<ESXRecordT> ("Playable", ColumnBase::Display_Boolean) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return record.get().mData.mIsPlayable!=0;
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
|
||||
record2.mData.mIsPlayable = data.toInt();
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -44,9 +44,23 @@ CSMWorld::Data::Data()
|
|||
mSkills.addColumn (new UseValueColumn<ESM::Skill> (i));
|
||||
mSkills.addColumn (new DescriptionColumn<ESM::Skill>);
|
||||
|
||||
mClasses.addColumn (new StringIdColumn<ESM::Class>);
|
||||
mClasses.addColumn (new RecordStateColumn<ESM::Class>);
|
||||
mClasses.addColumn (new NameColumn<ESM::Class>);
|
||||
mClasses.addColumn (new AttributesColumn<ESM::Class> (0));
|
||||
mClasses.addColumn (new AttributesColumn<ESM::Class> (1));
|
||||
mClasses.addColumn (new SpecialisationColumn<ESM::Class>);
|
||||
for (int i=0; i<5; ++i)
|
||||
mClasses.addColumn (new SkillsColumn<ESM::Class> (i, true));
|
||||
for (int i=0; i<5; ++i)
|
||||
mClasses.addColumn (new SkillsColumn<ESM::Class> (i, false));
|
||||
mClasses.addColumn (new PlayableColumn<ESM::Class>);
|
||||
mClasses.addColumn (new DescriptionColumn<ESM::Class>);
|
||||
|
||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
||||
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
|
||||
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
|
||||
}
|
||||
|
||||
CSMWorld::Data::~Data()
|
||||
|
@ -122,6 +136,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
|||
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
|
||||
case ESM::REC_GMST: mGmsts.load (reader, base); break;
|
||||
case ESM::REC_SKIL: mSkills.load (reader, base); break;
|
||||
case ESM::REC_CLAS: mClasses.load (reader, base); break;
|
||||
|
||||
default:
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <components/esm/loadglob.hpp>
|
||||
#include <components/esm/loadgmst.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
#include <components/esm/loadclas.hpp>
|
||||
|
||||
#include "idcollection.hpp"
|
||||
#include "universalid.hpp"
|
||||
|
@ -22,6 +23,7 @@ namespace CSMWorld
|
|||
IdCollection<ESM::Global> mGlobals;
|
||||
IdCollection<ESM::GameSetting> mGmsts;
|
||||
IdCollection<ESM::Skill> mSkills;
|
||||
IdCollection<ESM::Class> mClasses;
|
||||
std::vector<QAbstractItemModel *> mModels;
|
||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace
|
|||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" },
|
||||
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||
};
|
||||
|
@ -29,6 +30,7 @@ namespace
|
|||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" },
|
||||
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||
};
|
||||
|
|
|
@ -39,7 +39,9 @@ namespace CSMWorld
|
|||
Type_Gmsts,
|
||||
Type_Gmst,
|
||||
Type_Skills,
|
||||
Type_Skill
|
||||
Type_Skill,
|
||||
Type_Classes,
|
||||
Type_Class
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -90,6 +90,10 @@ void CSVDoc::View::setupWorldMenu()
|
|||
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
|
||||
world->addAction (skills);
|
||||
|
||||
QAction *classes = new QAction (tr ("Classes"), this);
|
||||
connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView()));
|
||||
world->addAction (classes);
|
||||
|
||||
mVerify = new QAction (tr ("&Verify"), this);
|
||||
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
|
||||
world->addAction (mVerify);
|
||||
|
@ -253,6 +257,11 @@ void CSVDoc::View::addSkillsSubView()
|
|||
addSubView (CSMWorld::UniversalId::Type_Skills);
|
||||
}
|
||||
|
||||
void CSVDoc::View::addClassesSubView()
|
||||
{
|
||||
addSubView (CSMWorld::UniversalId::Type_Classes);
|
||||
}
|
||||
|
||||
void CSVDoc::View::abortOperation (int type)
|
||||
{
|
||||
mDocument->abortOperation (type);
|
||||
|
|
|
@ -117,6 +117,8 @@ namespace CSVDoc
|
|||
void addGmstsSubView();
|
||||
|
||||
void addSkillsSubView();
|
||||
|
||||
void addClassesSubView();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
manager.add (CSMWorld::UniversalId::Type_Skills,
|
||||
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Global,
|
||||
new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
|
||||
manager.add (CSMWorld::UniversalId::Type_Classes,
|
||||
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (true));
|
||||
|
||||
// manager.add (CSMWorld::UniversalId::Type_Global,
|
||||
// new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
|
||||
}
|
|
@ -44,6 +44,11 @@ namespace MWRender
|
|||
class Animation;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class Movement;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Fallback;
|
||||
|
@ -54,7 +59,7 @@ namespace MWWorld
|
|||
class ESMStore;
|
||||
class RefData;
|
||||
|
||||
typedef std::vector<std::pair<MWWorld::Ptr,Ogre::Vector3> > PtrMovementList;
|
||||
typedef std::vector<std::pair<MWWorld::Ptr,MWMechanics::Movement> > PtrMovementList;
|
||||
}
|
||||
|
||||
namespace MWBase
|
||||
|
|
|
@ -24,6 +24,18 @@
|
|||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isGold (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
return Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100");
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
|
@ -110,25 +122,15 @@ namespace MWClass
|
|||
|
||||
std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||
ptr.get<ESM::Miscellaneous>();
|
||||
|
||||
if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGold")->getString())
|
||||
{
|
||||
if (isGold(ptr))
|
||||
return std::string("Item Gold Up");
|
||||
}
|
||||
return std::string("Item Misc Up");
|
||||
}
|
||||
|
||||
std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||
ptr.get<ESM::Miscellaneous>();
|
||||
|
||||
if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGold")->getString())
|
||||
{
|
||||
if (isGold(ptr))
|
||||
return std::string("Item Gold Down");
|
||||
}
|
||||
return std::string("Item Misc Down");
|
||||
}
|
||||
|
||||
|
@ -159,19 +161,15 @@ namespace MWClass
|
|||
|
||||
int count = ptr.getRefData().getCount();
|
||||
|
||||
bool isGold = Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100");
|
||||
bool gold = isGold(ptr);
|
||||
|
||||
if (isGold && ptr.getCellRef().mGoldValue != 1)
|
||||
if (gold && ptr.getCellRef().mGoldValue != 1)
|
||||
count = ptr.getCellRef().mGoldValue;
|
||||
else if (isGold)
|
||||
else if (gold)
|
||||
count *= ref->mBase->mData.mValue;
|
||||
|
||||
std::string countString;
|
||||
if (!isGold)
|
||||
if (!gold)
|
||||
countString = MWGui::ToolTips::getCountString(count);
|
||||
else // gold displays its count also if it's 1.
|
||||
countString = " (" + boost::lexical_cast<std::string>(count) + ")";
|
||||
|
@ -187,7 +185,7 @@ namespace MWClass
|
|||
|
||||
std::string text;
|
||||
|
||||
if (!isGold)
|
||||
if (!gold)
|
||||
{
|
||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
||||
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
|
||||
|
@ -211,7 +209,7 @@ namespace MWClass
|
|||
const MWWorld::ESMStore &store =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
if (MWWorld::Class::get(ptr).getName(ptr) == store.get<ESM::GameSetting>().find("sGold")->getString()) {
|
||||
if (isGold(ptr)) {
|
||||
int goldAmount = ptr.getRefData().getCount();
|
||||
|
||||
std::string base = "Gold_001";
|
||||
|
|
|
@ -368,7 +368,7 @@ namespace MWClass
|
|||
moveSpeed = runSpeed;
|
||||
else
|
||||
moveSpeed = walkSpeed;
|
||||
if(getMovementSettings(ptr).mLeftRight != 0 && getMovementSettings(ptr).mForwardBackward == 0)
|
||||
if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0)
|
||||
moveSpeed *= 0.75f;
|
||||
|
||||
return moveSpeed;
|
||||
|
@ -414,14 +414,24 @@ namespace MWClass
|
|||
|
||||
Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
Ogre::Vector3 vector;
|
||||
vector.x = getMovementSettings(ptr).mLeftRight;
|
||||
vector.y = getMovementSettings(ptr).mForwardBackward;
|
||||
vector.z = getMovementSettings(ptr).mUpDown;
|
||||
|
||||
return vector;
|
||||
MWMechanics::Movement &movement = getMovementSettings(ptr);
|
||||
Ogre::Vector3 vec(movement.mPosition);
|
||||
movement.mPosition[0] = 0.0f;
|
||||
movement.mPosition[1] = 0.0f;
|
||||
movement.mPosition[2] = 0.0f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
Ogre::Vector3 Npc::getRotationVector (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWMechanics::Movement &movement = getMovementSettings(ptr);
|
||||
Ogre::Vector3 vec(movement.mRotation);
|
||||
movement.mRotation[0] = 0.0f;
|
||||
movement.mRotation[1] = 0.0f;
|
||||
movement.mRotation[2] = 0.0f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
bool Npc::isEssential (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref =
|
||||
|
|
|
@ -96,6 +96,9 @@ namespace MWClass
|
|||
///< Return desired movement vector (determined based on movement settings,
|
||||
/// stance and stats).
|
||||
|
||||
virtual Ogre::Vector3 getRotationVector (const MWWorld::Ptr& ptr) const;
|
||||
///< Return desired rotations, as euler angles.
|
||||
|
||||
virtual float getCapacity (const MWWorld::Ptr& ptr) const;
|
||||
///< Return total weight that fits into the object. Throws an exception, if the object can't
|
||||
/// hold other objects.
|
||||
|
|
|
@ -140,13 +140,8 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
|
|||
|
||||
if (isInventory())
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
// the player is trying to sell an item, check if the merchant accepts it
|
||||
// also, don't allow selling gold (let's be better than Morrowind at this, can we?)
|
||||
if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object) ||
|
||||
MWWorld::Class::get(object).getName(object) == gmst.find("sGold")->getString())
|
||||
if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object))
|
||||
{
|
||||
// user notification "i don't buy this item"
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
|
|
|
@ -19,6 +19,49 @@
|
|||
using namespace MWGui;
|
||||
using namespace Widgets;
|
||||
|
||||
namespace
|
||||
{
|
||||
int wrap(int index, int max)
|
||||
{
|
||||
if (index < 0)
|
||||
return max - 1;
|
||||
else if (index >= max)
|
||||
return 0;
|
||||
else
|
||||
return index;
|
||||
}
|
||||
|
||||
int countParts(const std::string &part, const std::string &race, bool male)
|
||||
{
|
||||
/// \todo loop through the whole store for appropriate bodyparts instead of looking for fixed IDs
|
||||
const MWWorld::Store<ESM::BodyPart> &store =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
|
||||
std::string prefix =
|
||||
"b_n_" + race + ((male) ? "_m_" : "_f_") + part;
|
||||
|
||||
std::string suffix;
|
||||
suffix.reserve(prefix.size() + 3);
|
||||
|
||||
int count = -1;
|
||||
do {
|
||||
++count;
|
||||
suffix = "_" + (boost::format("%02d") % (count + 1)).str();
|
||||
}
|
||||
while (store.search(prefix + suffix) != 0);
|
||||
|
||||
if (count == 0 && part == "hair") {
|
||||
count = -1;
|
||||
do {
|
||||
++count;
|
||||
suffix = (boost::format("%02d") % (count + 1)).str();
|
||||
}
|
||||
while (store.search(prefix + suffix) != 0);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager)
|
||||
: WindowModal("openmw_chargen_race.layout", parWindowManager)
|
||||
, mGenderIndex(0)
|
||||
|
@ -144,45 +187,6 @@ void RaceDialog::setRaceId(const std::string &raceId)
|
|||
updateSpellPowers();
|
||||
}
|
||||
|
||||
int wrap(int index, int max)
|
||||
{
|
||||
if (index < 0)
|
||||
return max - 1;
|
||||
else if (index >= max)
|
||||
return 0;
|
||||
else
|
||||
return index;
|
||||
}
|
||||
|
||||
int countParts(const std::string &part, const std::string &race, bool male)
|
||||
{
|
||||
const MWWorld::Store<ESM::BodyPart> &store =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
|
||||
std::string prefix =
|
||||
"b_n_" + race + ((male) ? "_m_" : "_f_") + part;
|
||||
|
||||
std::string suffix;
|
||||
suffix.reserve(prefix.size() + 3);
|
||||
|
||||
int count = -1;
|
||||
do {
|
||||
++count;
|
||||
suffix = "_" + (boost::format("%02d") % (count + 1)).str();
|
||||
}
|
||||
while (store.search(prefix + suffix) != 0);
|
||||
|
||||
if (count == 0 && part == "hair") {
|
||||
count = -1;
|
||||
do {
|
||||
++count;
|
||||
suffix = (boost::format("%02d") % (count + 1)).str();
|
||||
}
|
||||
while (store.search(prefix + suffix) != 0);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void RaceDialog::close()
|
||||
{
|
||||
delete mPreview;
|
||||
|
@ -229,28 +233,67 @@ void RaceDialog::onSelectNextGender(MyGUI::Widget*)
|
|||
|
||||
void RaceDialog::onSelectPreviousFace(MyGUI::Widget*)
|
||||
{
|
||||
mFaceIndex = wrap(mFaceIndex - 1, mFaceCount);
|
||||
do
|
||||
mFaceIndex = wrap(mFaceIndex - 1, mFaceCount);
|
||||
while (!isFacePlayable());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectNextFace(MyGUI::Widget*)
|
||||
{
|
||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
||||
do
|
||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
||||
while (!isFacePlayable());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectPreviousHair(MyGUI::Widget*)
|
||||
{
|
||||
mHairIndex = wrap(mHairIndex - 1, mHairCount);
|
||||
do
|
||||
mHairIndex = wrap(mHairIndex - 1, mHairCount);
|
||||
while (!isHairPlayable());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectNextHair(MyGUI::Widget*)
|
||||
{
|
||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
||||
do
|
||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
||||
while (!isHairPlayable());
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
bool RaceDialog::isFacePlayable()
|
||||
{
|
||||
std::string prefix =
|
||||
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
||||
|
||||
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
|
||||
|
||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
|
||||
if (parts.search(prefix + "head_" + headIndex) == 0)
|
||||
return !(parts.find(prefix + "head" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
else
|
||||
return !(parts.find(prefix + "head_" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
}
|
||||
|
||||
bool RaceDialog::isHairPlayable()
|
||||
{
|
||||
std::string prefix =
|
||||
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
||||
|
||||
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
|
||||
|
||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||
if (parts.search(prefix + "hair_" + hairIndex) == 0)
|
||||
return !(parts.find(prefix + "hair" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
else
|
||||
return !(parts.find(prefix + "hair_" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
||||
}
|
||||
|
||||
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
||||
{
|
||||
if (_index == MyGUI::ITEM_NONE)
|
||||
|
@ -273,11 +316,16 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
|||
|
||||
void RaceDialog::recountParts()
|
||||
{
|
||||
mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0);
|
||||
mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0);
|
||||
|
||||
mFaceIndex = 0;
|
||||
mHairIndex = 0;
|
||||
|
||||
mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0);
|
||||
mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0);
|
||||
while (!isHairPlayable())
|
||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
||||
while (!isFacePlayable())
|
||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
||||
}
|
||||
|
||||
// update widget content
|
||||
|
|
|
@ -81,6 +81,9 @@ namespace MWGui
|
|||
void updatePreview();
|
||||
void recountParts();
|
||||
|
||||
bool isHairPlayable();
|
||||
bool isFacePlayable();
|
||||
|
||||
MyGUI::ImageBox* mPreviewImage;
|
||||
MyGUI::ListBox* mRaceList;
|
||||
MyGUI::ScrollBar* mHeadRotate;
|
||||
|
|
|
@ -129,13 +129,10 @@ namespace MWGui
|
|||
MWWorld::Ptr gold;
|
||||
MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore();
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = playerStore.begin();
|
||||
it != playerStore.end(); ++it)
|
||||
{
|
||||
if (MWWorld::Class::get(*it).getName(*it) == gmst.find("sGold")->getString())
|
||||
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001"))
|
||||
{
|
||||
goldFound = true;
|
||||
gold = *it;
|
||||
|
@ -342,6 +339,9 @@ namespace MWGui
|
|||
|
||||
bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001"))
|
||||
return false;
|
||||
|
||||
int services = 0;
|
||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
|
|
|
@ -287,8 +287,6 @@ namespace MWInput
|
|||
triedToMove = true;
|
||||
mPlayer.setLeftRight (1);
|
||||
}
|
||||
else
|
||||
mPlayer.setLeftRight (0);
|
||||
|
||||
if (actionIsActive(A_MoveForward))
|
||||
{
|
||||
|
@ -302,8 +300,6 @@ namespace MWInput
|
|||
mPlayer.setAutoMove (false);
|
||||
mPlayer.setForwardBackward (-1);
|
||||
}
|
||||
else
|
||||
mPlayer.setForwardBackward (0);
|
||||
|
||||
mPlayer.setSneak(actionIsActive(A_Sneak));
|
||||
|
||||
|
@ -312,8 +308,6 @@ namespace MWInput
|
|||
mPlayer.setUpDown (1);
|
||||
triedToMove = true;
|
||||
}
|
||||
else
|
||||
mPlayer.setUpDown (0);
|
||||
|
||||
if (mAlwaysRunActive)
|
||||
mPlayer.setRunState(!actionIsActive(A_Run));
|
||||
|
@ -542,11 +536,11 @@ namespace MWInput
|
|||
{
|
||||
resetIdleTime();
|
||||
|
||||
float x = arg.state.X.rel * mCameraSensitivity * 0.2;
|
||||
float y = arg.state.Y.rel * mCameraSensitivity * 0.2 * (mInvertY ? -1 : 1) * mUIYMultiplier;
|
||||
float x = arg.state.X.rel * mCameraSensitivity * 0.2f;
|
||||
float y = arg.state.Y.rel * mCameraSensitivity * 0.2f * (mInvertY ? -1 : 1) * mUIYMultiplier;
|
||||
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, x, true);
|
||||
mPlayer.setYaw(x);
|
||||
mPlayer.setPitch(-y);
|
||||
|
||||
if (arg.state.Z.rel)
|
||||
MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.state.Z.rel);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <OgreVector3.h>
|
||||
|
||||
#include "movement.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
|
@ -56,7 +58,10 @@ void Activators::update(float duration, bool paused)
|
|||
if(!paused)
|
||||
{
|
||||
for(PtrControllerMap::iterator iter(mActivators.begin());iter != mActivators.end();++iter)
|
||||
iter->second.update(duration);
|
||||
{
|
||||
Movement movement;
|
||||
iter->second.update(duration, movement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "creaturestats.hpp"
|
||||
#include "movement.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
@ -266,7 +267,8 @@ namespace MWMechanics
|
|||
|
||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
|
||||
{
|
||||
Ogre::Vector3 movement = iter->second.update(duration);
|
||||
Movement movement;
|
||||
iter->second.update(duration, movement);
|
||||
mMovement.push_back(std::make_pair(iter->first, movement));
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->doPhysics(mMovement, duration);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <map>
|
||||
|
||||
#include "character.hpp"
|
||||
#include "movement.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
namespace Ogre
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <OgreStringConverter.h>
|
||||
|
||||
#include "movement.hpp"
|
||||
|
||||
#include "../mwrender/animation.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
@ -73,6 +75,9 @@ static const struct {
|
|||
{ CharState_SneakLeft, "sneakleft" },
|
||||
{ CharState_SneakRight, "sneakright" },
|
||||
|
||||
{ CharState_TurnLeft, "turnleft" },
|
||||
{ CharState_TurnRight, "turnright" },
|
||||
|
||||
{ CharState_Jump, "jump" },
|
||||
|
||||
{ CharState_Death1, "death1" },
|
||||
|
@ -168,21 +173,20 @@ void CharacterController::markerEvent(float time, const std::string &evt)
|
|||
}
|
||||
|
||||
|
||||
Ogre::Vector3 CharacterController::update(float duration)
|
||||
void CharacterController::update(float duration, Movement &movement)
|
||||
{
|
||||
Ogre::Vector3 movement(0.0f);
|
||||
|
||||
float speed = 0.0f;
|
||||
if(!(getState() >= CharState_Death1))
|
||||
{
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||
const Ogre::Vector3 &vec = cls.getMovementVector(mPtr);
|
||||
|
||||
bool onground = world->isOnGround(mPtr);
|
||||
bool inwater = world->isSwimming(mPtr);
|
||||
bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run);
|
||||
bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak);
|
||||
const Ogre::Vector3 &vec = cls.getMovementVector(mPtr);
|
||||
const Ogre::Vector3 &rot = cls.getRotationVector(mPtr);
|
||||
speed = cls.getSpeed(mPtr);
|
||||
|
||||
/* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except
|
||||
|
@ -192,14 +196,14 @@ Ogre::Vector3 CharacterController::update(float duration)
|
|||
float x = cls.getJump(mPtr);
|
||||
|
||||
if(vec.x == 0 && vec.y == 0)
|
||||
movement.z += x*duration;
|
||||
movement.mPosition[2] += x*duration;
|
||||
else
|
||||
{
|
||||
/* FIXME: this would be more correct if we were going into a jumping state,
|
||||
* rather than normal walking/idle states. */
|
||||
//Ogre::Vector3 lat = Ogre::Vector3(vec.x, vec.y, 0.0f).normalisedCopy();
|
||||
//movement += Ogre::Vector3(lat.x, lat.y, 1.0f) * x * 0.707f * duration;
|
||||
movement.z += x * 0.707f * duration;
|
||||
movement.mPosition[2] += x * 0.707f * duration;
|
||||
}
|
||||
|
||||
//decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult;
|
||||
|
@ -216,7 +220,7 @@ Ogre::Vector3 CharacterController::update(float duration)
|
|||
: (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true);
|
||||
|
||||
// Apply any forward/backward movement manually
|
||||
movement.y += vec.y * (speed*duration);
|
||||
movement.mPosition[1] += vec.y * (speed*duration);
|
||||
}
|
||||
else if(vec.y != 0.0f && speed > 0.0f)
|
||||
{
|
||||
|
@ -228,20 +232,32 @@ Ogre::Vector3 CharacterController::update(float duration)
|
|||
setState(inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack)
|
||||
: (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack)), true);
|
||||
// Apply any sideways movement manually
|
||||
movement.x += vec.x * (speed*duration);
|
||||
movement.mPosition[0] += vec.x * (speed*duration);
|
||||
}
|
||||
else if(rot.z != 0.0f && !inwater && !sneak)
|
||||
{
|
||||
if(rot.z > 0.0f)
|
||||
setState(CharState_TurnRight, true);
|
||||
else if(rot.z < 0.0f)
|
||||
setState(CharState_TurnLeft, true);
|
||||
}
|
||||
else if(mAnimQueue.size() == 0)
|
||||
setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true);
|
||||
|
||||
movement.mRotation[0] += rot.x * duration;
|
||||
movement.mRotation[1] += rot.y * duration;
|
||||
movement.mRotation[2] += rot.z * duration;
|
||||
}
|
||||
|
||||
if(mAnimation && !mSkipAnim)
|
||||
{
|
||||
mAnimation->setSpeed(speed);
|
||||
movement += mAnimation->runAnimation(duration);
|
||||
Ogre::Vector3 moved = mAnimation->runAnimation(duration);
|
||||
movement.mPosition[0] += moved.x;
|
||||
movement.mPosition[1] += moved.y;
|
||||
movement.mPosition[2] += moved.z;
|
||||
}
|
||||
mSkipAnim = false;
|
||||
|
||||
return movement;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace MWRender
|
|||
namespace MWMechanics
|
||||
{
|
||||
|
||||
class Movement;
|
||||
|
||||
enum CharacterState {
|
||||
CharState_SpecialIdle,
|
||||
CharState_Idle,
|
||||
|
@ -52,6 +54,9 @@ enum CharacterState {
|
|||
CharState_SneakLeft,
|
||||
CharState_SneakRight,
|
||||
|
||||
CharState_TurnLeft,
|
||||
CharState_TurnRight,
|
||||
|
||||
CharState_Jump,
|
||||
|
||||
/* Death states must be last! */
|
||||
|
@ -87,7 +92,7 @@ public:
|
|||
|
||||
void updatePtr(const MWWorld::Ptr &ptr);
|
||||
|
||||
Ogre::Vector3 update(float duration);
|
||||
void update(float duration, Movement &movement);
|
||||
|
||||
void playGroup(const std::string &groupname, int mode, int count);
|
||||
void skipAnim();
|
||||
|
|
|
@ -6,11 +6,14 @@ namespace MWMechanics
|
|||
/// Desired movement for an actor
|
||||
struct Movement
|
||||
{
|
||||
signed char mLeftRight; // 1: wants to move left, -1: wants to move right
|
||||
signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward
|
||||
signed char mUpDown;
|
||||
float mPosition[3];
|
||||
float mRotation[3];
|
||||
|
||||
Movement() : mLeftRight (0), mForwardBackward (0), mUpDown(0) {}
|
||||
Movement()
|
||||
{
|
||||
mPosition[0] = mPosition[1] = mPosition[2] = 0.0f;
|
||||
mRotation[0] = mRotation[1] = mRotation[2] = 0.0f;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -262,37 +262,29 @@ void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3
|
|||
ptr.getRefData().getBaseNode()->setScale(scale);
|
||||
}
|
||||
|
||||
bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot, bool adjust)
|
||||
bool RenderingManager::rotateObject(const MWWorld::Ptr &ptr, Ogre::Vector3 &rot, bool adjust)
|
||||
{
|
||||
bool isActive = ptr.getRefData().getBaseNode() != 0;
|
||||
bool isPlayer = isActive && ptr.getRefData().getHandle() == "player";
|
||||
bool force = true;
|
||||
|
||||
|
||||
if (isPlayer)
|
||||
force = mPlayer->rotate(rot, adjust);
|
||||
|
||||
MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z);
|
||||
|
||||
MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z);
|
||||
if (!isPlayer && isActive)
|
||||
{
|
||||
Ogre::Quaternion xr(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X);
|
||||
Ogre::Quaternion yr(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y);
|
||||
Ogre::Quaternion zr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z);
|
||||
|
||||
Ogre::Quaternion xref(Ogre::Radian(-ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::UNIT_X);
|
||||
Ogre::Quaternion yref(Ogre::Radian(-ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y);
|
||||
Ogre::Quaternion zref(Ogre::Radian(-ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z);
|
||||
|
||||
Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr;
|
||||
|
||||
Ogre::Matrix3 mat;
|
||||
newo.ToRotationMatrix(mat);
|
||||
Ogre::Radian ax,ay,az;
|
||||
mat.ToEulerAnglesXYZ(ax,ay,az);
|
||||
rot.x = -ax.valueRadians();
|
||||
rot.y = -ay.valueRadians();
|
||||
rot.z = -az.valueRadians();
|
||||
if(adjust)
|
||||
{
|
||||
const float *objRot = ptr.getRefData().getPosition().rot;
|
||||
rot.x += objRot[0];
|
||||
rot.y += objRot[1];
|
||||
rot.z += objRot[2];
|
||||
}
|
||||
|
||||
Ogre::Quaternion newo = Ogre::Quaternion(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X) *
|
||||
Ogre::Quaternion(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y) *
|
||||
Ogre::Quaternion(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z);
|
||||
ptr.getRefData().getBaseNode()->setOrientation(newo);
|
||||
}
|
||||
else if(isPlayer)
|
||||
|
|
|
@ -316,5 +316,7 @@ op 0x20001f9: Drop, explicit reference
|
|||
op 0x20001fa: DropSoulGem
|
||||
op 0x20001fb: DropSoulGem, explicit reference
|
||||
op 0x20001fc: OnDeath
|
||||
op 0x20001fd: IsWerewolf
|
||||
op 0x20001fe: IsWerewolf, explicit reference
|
||||
|
||||
opcodes 0x20001fd-0x3ffffff unused
|
||||
opcodes 0x20001ff-0x3ffffff unused
|
||||
|
|
|
@ -1046,6 +1046,18 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class OpIsWerewolf : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
runtime.push(MWWorld::Class::get(ptr).getNpcStats(ptr).isWerewolf());
|
||||
}
|
||||
};
|
||||
|
||||
const int numberOfAttributes = 8;
|
||||
|
||||
const int opcodeGetAttribute = 0x2000027;
|
||||
|
@ -1137,6 +1149,9 @@ namespace MWScript
|
|||
|
||||
const int opcodeOnDeath = 0x20001fc;
|
||||
|
||||
const int opcodeIsWerewolf = 0x20001fd;
|
||||
const int opcodeIsWerewolfExplicit = 0x20001fe;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
static const char *attributes[numberOfAttributes] =
|
||||
|
@ -1252,6 +1267,8 @@ namespace MWScript
|
|||
extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit);
|
||||
|
||||
extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath);
|
||||
|
||||
extensions.registerFunction ("iswerewolf", 'l', "", opcodeIsWerewolf, opcodeIsWerewolfExplicit);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -1368,6 +1385,9 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank<ExplicitRef>);
|
||||
|
||||
interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath);
|
||||
|
||||
interpreter.installSegment5 (opcodeIsWerewolf, new OpIsWerewolf<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeIsWerewolfExplicit, new OpIsWerewolf<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,6 +142,11 @@ namespace MWWorld
|
|||
return Ogre::Vector3 (0, 0, 0);
|
||||
}
|
||||
|
||||
Ogre::Vector3 Class::getRotationVector (const Ptr& ptr) const
|
||||
{
|
||||
return Ogre::Vector3 (0, 0, 0);
|
||||
}
|
||||
|
||||
std::pair<std::vector<int>, bool> Class::getEquipmentSlots (const Ptr& ptr) const
|
||||
{
|
||||
return std::make_pair (std::vector<int>(), false);
|
||||
|
|
|
@ -150,6 +150,9 @@ namespace MWWorld
|
|||
///< Return desired movement vector (determined based on movement settings,
|
||||
/// stance and stats).
|
||||
|
||||
virtual Ogre::Vector3 getRotationVector (const Ptr& ptr) const;
|
||||
///< Return desired rotations, as euler angles.
|
||||
|
||||
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const Ptr& ptr) const;
|
||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||
/// stay stacked when equipped?
|
||||
|
|
|
@ -42,14 +42,14 @@ namespace MWWorld
|
|||
if (mAutoMove)
|
||||
value = 1;
|
||||
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value;
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value;
|
||||
}
|
||||
|
||||
void Player::setLeftRight (int value)
|
||||
{
|
||||
MWWorld::Ptr ptr = getPlayer();
|
||||
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mLeftRight = value;
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value;
|
||||
}
|
||||
|
||||
void Player::setForwardBackward (int value)
|
||||
|
@ -61,14 +61,14 @@ namespace MWWorld
|
|||
if (mAutoMove)
|
||||
value = 1;
|
||||
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value;
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value;
|
||||
}
|
||||
|
||||
void Player::setUpDown(int value)
|
||||
{
|
||||
MWWorld::Ptr ptr = getPlayer();
|
||||
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mUpDown = value;
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value;
|
||||
}
|
||||
|
||||
void Player::setRunState(bool run)
|
||||
|
@ -84,6 +84,22 @@ namespace MWWorld
|
|||
MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Sneak, sneak);
|
||||
}
|
||||
|
||||
void Player::setYaw(float yaw)
|
||||
{
|
||||
MWWorld::Ptr ptr = getPlayer();
|
||||
MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[2] = yaw;
|
||||
}
|
||||
void Player::setPitch(float pitch)
|
||||
{
|
||||
MWWorld::Ptr ptr = getPlayer();
|
||||
MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[0] = pitch;
|
||||
}
|
||||
void Player::setRoll(float roll)
|
||||
{
|
||||
MWWorld::Ptr ptr = getPlayer();
|
||||
MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[1] = roll;
|
||||
}
|
||||
|
||||
MWMechanics::DrawState_ Player::getDrawState()
|
||||
{
|
||||
MWWorld::Ptr ptr = getPlayer();
|
||||
|
|
|
@ -67,6 +67,10 @@ namespace MWWorld
|
|||
|
||||
void setRunState(bool run);
|
||||
void setSneak(bool sneak);
|
||||
|
||||
void setYaw(float yaw);
|
||||
void setPitch(float pitch);
|
||||
void setRoll(float roll);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "../mwbase/scriptmanager.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/movement.hpp"
|
||||
|
||||
#include "../mwrender/sky.hpp"
|
||||
#include "../mwrender/player.hpp"
|
||||
|
@ -805,18 +806,15 @@ namespace MWWorld
|
|||
mPhysics->scaleObject(ptr);
|
||||
}
|
||||
|
||||
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
|
||||
void World::rotateObjectImp (const Ptr& ptr, Ogre::Vector3 rot, bool adjust)
|
||||
{
|
||||
Ogre::Vector3 rot;
|
||||
rot.x = Ogre::Degree(x).valueRadians();
|
||||
rot.y = Ogre::Degree(y).valueRadians();
|
||||
rot.z = Ogre::Degree(z).valueRadians();
|
||||
|
||||
if (mRendering->rotateObject(ptr, rot, adjust))
|
||||
{
|
||||
// rotate physically iff renderer confirm so
|
||||
float *objRot = ptr.getRefData().getPosition().rot;
|
||||
objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z;
|
||||
objRot[0] = rot.x;
|
||||
objRot[1] = rot.y;
|
||||
objRot[2] = rot.z;
|
||||
|
||||
if (ptr.getRefData().getBaseNode() != 0) {
|
||||
mPhysics->rotateObject(ptr);
|
||||
|
@ -824,6 +822,14 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
|
||||
{
|
||||
rotateObjectImp(ptr, Ogre::Vector3(Ogre::Degree(x).valueRadians(),
|
||||
Ogre::Degree(y).valueRadians(),
|
||||
Ogre::Degree(z).valueRadians()),
|
||||
adjust);
|
||||
}
|
||||
|
||||
void World::safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos)
|
||||
{
|
||||
copyObjectToCell(ptr,Cell,pos);
|
||||
|
@ -873,13 +879,18 @@ namespace MWWorld
|
|||
player = iter;
|
||||
continue;
|
||||
}
|
||||
Ogre::Vector3 vec = mPhysics->move(iter->first, iter->second, duration,
|
||||
|
||||
rotateObjectImp(iter->first, Ogre::Vector3(iter->second.mRotation), true);
|
||||
|
||||
Ogre::Vector3 vec = mPhysics->move(iter->first, Ogre::Vector3(iter->second.mPosition), duration,
|
||||
!isSwimming(iter->first) && !isFlying(iter->first));
|
||||
moveObjectImp(iter->first, vec.x, vec.y, vec.z);
|
||||
}
|
||||
if(player != actors.end())
|
||||
{
|
||||
Ogre::Vector3 vec = mPhysics->move(player->first, player->second, duration,
|
||||
rotateObjectImp(player->first, Ogre::Vector3(player->second.mRotation), true);
|
||||
|
||||
Ogre::Vector3 vec = mPhysics->move(player->first, Ogre::Vector3(player->second.mPosition), duration,
|
||||
!isSwimming(player->first) && !isFlying(player->first));
|
||||
moveObjectImp(player->first, vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ namespace MWWorld
|
|||
|
||||
int getDaysPerMonth (int month) const;
|
||||
|
||||
void rotateObjectImp (const Ptr& ptr, Ogre::Vector3 rot, bool adjust);
|
||||
|
||||
bool moveObjectImp (const Ptr& ptr, float x, float y, float z);
|
||||
///< @return true if the active cell (cell player is in) changed
|
||||
|
||||
|
|
|
@ -106,6 +106,12 @@ namespace Compiler
|
|||
mLoc.mLiteral.clear();
|
||||
return true;
|
||||
}
|
||||
else if (c==':')
|
||||
{
|
||||
// treat : as a whitespace :(
|
||||
mLoc.mLiteral.clear();
|
||||
return true;
|
||||
}
|
||||
else if (std::isdigit (c))
|
||||
{
|
||||
bool cont = false;
|
||||
|
|
|
@ -33,7 +33,7 @@ struct BodyPart
|
|||
enum Flags
|
||||
{
|
||||
BPF_Female = 1,
|
||||
BPF_Playable = 2
|
||||
BPF_NotPlayable = 2
|
||||
};
|
||||
|
||||
enum MeshType
|
||||
|
|
|
@ -35,4 +35,18 @@ void Class::save(ESMWriter &esm)
|
|||
esm.writeHNOString("DESC", mDescription);
|
||||
}
|
||||
|
||||
void Class::blank()
|
||||
{
|
||||
mName.clear();
|
||||
mDescription.clear();
|
||||
|
||||
mData.mAttribute[0] = mData.mAttribute[1] = 0;
|
||||
mData.mSpecialization = 0;
|
||||
mData.mIsPlayable = 0;
|
||||
mData.mCalc = 0;
|
||||
|
||||
for (int i=0; i<5; ++i)
|
||||
for (int i2=0; i2<2; ++i2)
|
||||
mData.mSkills[i][i2] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,10 @@ struct Class
|
|||
|
||||
void load(ESMReader &esm);
|
||||
void save(ESMWriter &esm);
|
||||
|
||||
void blank();
|
||||
///< Set record to default state (does not touch the ID/index).
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "esmreader.hpp"
|
||||
#include "esmwriter.hpp"
|
||||
|
||||
|
@ -103,8 +105,9 @@ void Skill::load(ESMReader &esm)
|
|||
|
||||
// create an ID from the index and the name (only used in the editor and likely to change in the
|
||||
// future)
|
||||
mId = getIndexToId (mIndex);
|
||||
mId = indexToId (mIndex);
|
||||
}
|
||||
|
||||
void Skill::save(ESMWriter &esm)
|
||||
{
|
||||
esm.writeHNT("INDX", mIndex);
|
||||
|
@ -120,7 +123,7 @@ void Skill::save(ESMWriter &esm)
|
|||
mDescription.clear();
|
||||
}
|
||||
|
||||
std::string Skill::getIndexToId (int index)
|
||||
std::string Skill::indexToId (int index)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ struct Skill
|
|||
void blank();
|
||||
///< Set record to default state (does not touch the ID/index).
|
||||
|
||||
static std::string getIndexToId (int index);
|
||||
static std::string indexToId (int index);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue