Merge branch 'dialogue' into saving

Conflicts:
	apps/opencs/model/world/columnimp.hpp
	apps/opencs/model/world/columns.cpp
	apps/opencs/model/world/columns.hpp
	apps/opencs/model/world/data.cpp
	components/esm/loaddial.hpp
actorid
Marc Zinnschlag 11 years ago
commit c995533e07

51
.gitignore vendored

@ -1,24 +1,53 @@
build
*~
Doxygen
prebuilt
apps/openmw/config.hpp
Docs/mainpage.hpp
## make
CMakeFiles
*/CMakeFiles
CMakeCache.txt
moc_*.cxx
cmake_install.cmake
*.[ao]
CMakeLists.txt.user
Makefile
makefile
data
build
prebuilt
## doxygen
Doxygen
## ides/editors
*~
*.kdev4
CMakeLists.txt.user
*.swp
*.swo
*.kate-swp
.cproject
.project
.settings/
.settings
.directory
## resources
data
resources
/*.cfg
/*.desktop
/*.install
## binaries
/esmtool
/mwiniimport
/omwlauncher
/openmw
/opencs
## generated objects
apps/openmw/config.hpp
Docs/mainpage.hpp
moc_*.cxx
*.cxx_parameters
*qrc_launcher.cxx
*qrc_resources.cxx
*__*
*ui_datafilespage.h
*ui_graphicspage.h
*ui_mainwindow.h
*ui_playpage.h
*.[ao]
*.so

@ -77,6 +77,8 @@ namespace
ini.insert(loc, setting + "=" + val + "\r\n");
}
#define FIX(setting) add_setting(category, setting, get_setting(category, setting, inx), ini)
void bloodmoon_fix_ini(std::string& ini, const bfs::path inxPath)
{
std::string inx = read_to_string(inxPath);
@ -88,95 +90,94 @@ namespace
ini.erase(start, end-start);
std::string category;
std::string setting;
category = "General";
{
setting = "Werewolf FOV"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Werewolf FOV");
}
category = "Moons";
{
setting = "Script Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Script Color");
}
category = "Weather";
{
setting = "Snow Ripples"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripple Radius"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripples Per Flake"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripple Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripple Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Gravity Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow High Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Low Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Snow Ripples");
FIX("Snow Ripple Radius");
FIX("Snow Ripples Per Flake");
FIX("Snow Ripple Scale");
FIX("Snow Ripple Speed");
FIX("Snow Gravity Scale");
FIX("Snow High Kill");
FIX("Snow Low Kill");
}
category = "Weather Blight";
{
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Ambient Loop Sound ID");
}
category = "Weather Snow";
{
setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Diameter"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Height Min"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Height Max"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Entrance Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Max Snowflakes"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Sky Sunrise Color");
FIX("Sky Day Color");
FIX("Sky Sunset Color");
FIX("Sky Night Color");
FIX("Fog Sunrise Color");
FIX("Fog Day Color");
FIX("Fog Sunset Color");
FIX("Fog Night Color");
FIX("Ambient Sunrise Color");
FIX("Ambient Day Color");
FIX("Ambient Sunset Color");
FIX("Ambient Night Color");
FIX("Sun Sunrise Color");
FIX("Sun Day Color");
FIX("Sun Sunset Color");
FIX("Sun Night Color");
FIX("Sun Disc Sunset Color");
FIX("Transition Delta");
FIX("Land Fog Day Depth");
FIX("Land Fog Night Depth");
FIX("Clouds Maximum Percent");
FIX("Wind Speed");
FIX("Cloud Speed");
FIX("Glare View");
FIX("Cloud Texture");
FIX("Ambient Loop Sound ID");
FIX("Snow Threshold");
FIX("Snow Diameter");
FIX("Snow Height Min");
FIX("Snow Height Max");
FIX("Snow Entrance Speed");
FIX("Max Snowflakes");
}
category = "Weather Blizzard";
{
setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Storm Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Sky Sunrise Color");
FIX("Sky Day Color");
FIX("Sky Sunset Color");
FIX("Sky Night Color");
FIX("Fog Sunrise Color");
FIX("Fog Day Color");
FIX("Fog Sunset Color");
FIX("Fog Night Color");
FIX("Ambient Sunrise Color");
FIX("Ambient Day Color");
FIX("Ambient Sunset Color");
FIX("Ambient Night Color");
FIX("Sun Sunrise Color");
FIX("Sun Day Color");
FIX("Sun Sunset Color");
FIX("Sun Night Color");
FIX("Sun Disc Sunset Color");
FIX("Transition Delta");
FIX("Land Fog Day Depth");
FIX("Land Fog Night Depth");
FIX("Clouds Maximum Percent");
FIX("Wind Speed");
FIX("Cloud Speed");
FIX("Glare View");
FIX("Cloud Texture");
FIX("Ambient Loop Sound ID");
FIX("Storm Threshold");
}
}
@ -268,6 +269,27 @@ namespace
strptime(time, "%d %B %Y", &tms);
return mktime(&tms);
}
// Some cds have cab files which have the Data Files subfolders outside the Data Files folder
void install_dfiles_outside(const bfs::path& from, const bfs::path& dFiles)
{
bfs::path fonts = findFile(from, "fonts", false);
if(fonts.string() != "")
installToPath(fonts, dFiles / "Fonts");
bfs::path music = findFile(from, "music", false);
if(music.string() != "")
installToPath(music, dFiles / "Music");
bfs::path sound = findFile(from, "sound", false);
if(sound.string() != "")
installToPath(sound, dFiles / "Sound");
bfs::path splash = findFile(from, "splash", false);
if(splash.string() != "")
installToPath(splash, dFiles / "Splash");
}
}
bool UnshieldThread::SetMorrowindPath(const std::string& path)
@ -365,6 +387,8 @@ bool UnshieldThread::extract()
installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(mwExtractPath, outputDataFilesDir);
// Videos are often kept uncompressed on the cd
bfs::path videosPath = findFile(mMorrowindPath.parent_path(), "video", false);
if(videosPath.string() != "")
@ -399,6 +423,8 @@ bool UnshieldThread::extract()
installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(tbExtractPath, outputDataFilesDir);
// Mt GOTY CD has Sounds in a seperate folder from the rest of the data files
bfs::path soundsPath = findFile(tbExtractPath, "sounds", false);
if(soundsPath.string() != "")
@ -426,6 +452,8 @@ bool UnshieldThread::extract()
bfs::path dFilesDir = findFile(bmExtractPath, "bloodmoon.esm").parent_path();
installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(bmExtractPath, outputDataFilesDir);
// My GOTY CD contains a folder within cab files called Tribunal patch,
// which contains Tribunal.esm

@ -59,13 +59,14 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode
)
opencs_units_noqt (view/world
dialoguesubview subviews
enumdelegate vartypedelegate recordstatusdelegate refidtypedelegate datadisplaydelegate
scripthighlighter idvalidator
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator
)

@ -2144,6 +2144,79 @@ void CSMDoc::Document::createBase()
getData().getSkills().add (record);
}
static const char *sVoice[] =
{
"Intruder",
"Attack",
"Hello",
"Thief",
"Alarm",
"Idle",
"Flee",
"Hit",
0
};
for (int i=0; sVoice[i]; ++i)
{
ESM::Dialogue record;
record.mId = sVoice[i];
record.mType = ESM::Dialogue::Voice;
record.blank();
getData().getTopics().add (record);
}
static const char *sGreetings[] =
{
"Greeting 0",
"Greeting 1",
"Greeting 2",
"Greeting 3",
"Greeting 4",
"Greeting 5",
"Greeting 6",
"Greeting 7",
"Greeting 8",
"Greeting 9",
0
};
for (int i=0; sGreetings[i]; ++i)
{
ESM::Dialogue record;
record.mId = sGreetings[i];
record.mType = ESM::Dialogue::Greeting;
record.blank();
getData().getTopics().add (record);
}
static const char *sPersuasion[] =
{
"Intimidate Success",
"Intimidate Fail",
"Service Refusal",
"Admire Success",
"Taunt Success",
"Bribe Success",
"Info Refusal",
"Admire Fail",
"Taunt Fail",
"Bribe Fail",
0
};
for (int i=0; sPersuasion[i]; ++i)
{
ESM::Dialogue record;
record.mId = sPersuasion[i];
record.mType = ESM::Dialogue::Persuasion;
record.blank();
getData().getTopics().add (record);
}
}
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,

@ -34,7 +34,7 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
{
string = data.toString();
}
else if (data.type()==QVariant::Int || data.type()==QVariant::UInt ||
else if ((data.type()==QVariant::Int || data.type()==QVariant::UInt) &&
CSMWorld::Columns::hasEnums (static_cast<CSMWorld::Columns::ColumnId> (mColumnId)))
{
int value = data.toInt();
@ -47,8 +47,10 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
}
else if (data.type()==QVariant::Bool)
{
string = data.toBool() ? "true" : " false";
string = data.toBool() ? "true" : "false";
}
else if (mText.empty() && !data.isValid())
return true;
else
return false;

@ -17,7 +17,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);
if (iter==columns.end())
throw std::logic_error ("invalid column in test value test");
throw std::logic_error ("invalid column in value node test");
if (iter->second==-1)
return true;
@ -27,7 +27,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
QVariant data = table.data (index);
if (data.type()!=QVariant::Double && data.type()!=QVariant::Bool && data.type()!=QVariant::Int &&
data.type()!=QVariant::UInt)
data.type()!=QVariant::UInt && data.type()!=static_cast<QVariant::Type> (QMetaType::Float))
return false;
double value = data.toDouble();
@ -68,7 +68,7 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const
<< CSMWorld::Columns::getName (static_cast<CSMWorld::Columns::ColumnId> (mColumnId))
<< "\"";
stream << ", \"";
stream << ", ";
if (mLower==mUpper && mLowerType!=Type_Infinite && mUpperType!=Type_Infinite)
stream << mLower;

@ -19,7 +19,12 @@ int CSMTools::BirthsignCheckStage::setup()
void CSMTools::BirthsignCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::BirthSign& birthsign = mBirthsigns.getRecord (stage).get();
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
if (record.isDeleted())
return;
const ESM::BirthSign& birthsign = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Birthsign, birthsign.mId);

@ -20,7 +20,12 @@ int CSMTools::ClassCheckStage::setup()
void CSMTools::ClassCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Class& class_= mClasses.getRecord (stage).get();
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Class& class_ = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Class, class_.mId);

@ -20,7 +20,12 @@ int CSMTools::FactionCheckStage::setup()
void CSMTools::FactionCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Faction& faction = mFactions.getRecord (stage).get();
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Faction& faction = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Faction, faction.mId);

@ -9,7 +9,12 @@
void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector<std::string>& messages)
{
const ESM::Race& race = mRaces.getRecord (stage).get();
const CSMWorld::Record<ESM::Race>& record = mRaces.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Race& race = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId);

@ -19,7 +19,12 @@ int CSMTools::RegionCheckStage::setup()
void CSMTools::RegionCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Region& region = mRegions.getRecord (stage).get();
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Region& region = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Region, region.mId);

@ -18,7 +18,12 @@ int CSMTools::SkillCheckStage::setup()
void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Skill& skill = mSkills.getRecord (stage).get();
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Skill& skill = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId);

@ -18,7 +18,12 @@ int CSMTools::SoundCheckStage::setup()
void CSMTools::SoundCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Sound& sound = mSounds.getRecord (stage).get();
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Sound& sound = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId);

@ -19,7 +19,12 @@ int CSMTools::SpellCheckStage::setup()
void CSMTools::SpellCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Spell& spell = mSpells.getRecord (stage).get();
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Spell& spell = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Spell, spell.mId);

@ -43,7 +43,8 @@ namespace CSMWorld
Display_CreatureType,
Display_WeaponType,
Display_RecordState,
Display_RefRecordType
Display_RefRecordType,
Display_DialogueType
};
int mColumnId;

@ -1246,6 +1246,108 @@ namespace CSMWorld
return false;
}
};
template<typename ESXRecordT>
struct PosColumn : public Column<ESXRecordT>
{
ESM::Position ESXRecordT::* mPosition;
int mIndex;
PosColumn (ESM::Position ESXRecordT::* position, int index, bool door)
: Column<ESXRecordT> (
(door ? Columns::ColumnId_DoorPositionXPos : Columns::ColumnId_PositionXPos)+index,
ColumnBase::Display_Float), mPosition (position), mIndex (index) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
const ESM::Position& position = record.get().*mPosition;
return position.pos[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
ESM::Position& position = record.get().*mPosition;
position.pos[mIndex] = data.toFloat();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct RotColumn : public Column<ESXRecordT>
{
ESM::Position ESXRecordT::* mPosition;
int mIndex;
RotColumn (ESM::Position ESXRecordT::* position, int index, bool door)
: Column<ESXRecordT> (
(door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index,
ColumnBase::Display_Float), mPosition (position), mIndex (index) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
const ESM::Position& position = record.get().*mPosition;
return position.rot[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
ESM::Position& position = record.get().*mPosition;
position.rot[mIndex] = data.toFloat();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct DialogueTypeColumn : public Column<ESXRecordT>
{
DialogueTypeColumn (bool hidden = false)
: Column<ESXRecordT> (Columns::ColumnId_DialogueType, ColumnBase::Display_DialogueType,
hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mType);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mType = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
}
#endif

@ -51,7 +51,7 @@ namespace CSMWorld
{ ColumnId_FactionIndex, "Faction Index" },
{ ColumnId_Charges, "Charges" },
{ ColumnId_Enchantment, "Enchantment" },
{ ColumnId_Value, "Coin Value" },
{ ColumnId_CoinValue, "Coin Value" },
{ ColumnId_Teleport, "Teleport" },
{ ColumnId_TeleportCell, "Teleport Cell" },
{ ColumnId_LockLevel, "Lock Level" },
@ -147,6 +147,19 @@ namespace CSMWorld
{ ColumnId_Magical, "Magical" },
{ ColumnId_Silver, "Silver" },
{ ColumnId_Filter, "Filter" },
{ ColumnId_PositionXPos, "Pos X" },
{ ColumnId_PositionYPos, "Pos Y" },
{ ColumnId_PositionZPos, "Pos Z" },
{ ColumnId_PositionXRot, "Rot X" },
{ ColumnId_PositionYRot, "Rot Y" },
{ ColumnId_PositionZRot, "Rot Z" },
{ ColumnId_DoorPositionXPos, "Teleport Pos X" },
{ ColumnId_DoorPositionYPos, "Teleport Pos Y" },
{ ColumnId_DoorPositionZPos, "Teleport Pos Z" },
{ ColumnId_DoorPositionXRot, "Teleport Rot X" },
{ ColumnId_DoorPositionYRot, "Teleport Rot Y" },
{ ColumnId_DoorPositionZRot, "Teleport Rot Z" },
{ ColumnId_DialogueType, "Dialogue Type" },
{ ColumnId_Scope, "Scope", },
{ ColumnId_UseValue1, "Use value 1" },
@ -258,6 +271,11 @@ namespace
"unknown", "none", "short", "integer", "long", "float", "string", 0
};
static const char *sDialogueTypeEnums[] =
{
"Topic", "Voice", "Greeting", "Persuasion", 0
};
const char **getEnumNames (CSMWorld::Columns::ColumnId column)
{
switch (column)
@ -272,6 +290,7 @@ namespace
case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes;
case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums;
case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums;
case CSMWorld::Columns::ColumnId_DialogueType: return sDialogueTypeEnums;
default: return 0;
}

@ -45,102 +45,115 @@ namespace CSMWorld
ColumnId_Charges = 32,
ColumnId_Enchantment = 33,
ColumnId_CoinValue = 34,
ColumnId_Teleport = 25,
ColumnId_TeleportCell = 26,
ColumnId_LockLevel = 27,
ColumnId_Key = 28,
ColumnId_Trap = 29,
ColumnId_BeastRace = 30,
ColumnId_AutoCalc = 31,
ColumnId_StarterSpell = 32,
ColumnId_AlwaysSucceeds = 33,
ColumnId_SleepForbidden = 34,
ColumnId_InteriorWater = 35,
ColumnId_InteriorSky = 36,
ColumnId_Model = 37,
ColumnId_Script = 38,
ColumnId_Icon = 39,
ColumnId_Weight = 40,
ColumnId_EnchantmentPoints = 31,
ColumnId_Quality = 32,
ColumnId_Ai = 33,
ColumnId_AiHello = 34,
ColumnId_AiFlee = 35,
ColumnId_AiFight = 36,
ColumnId_AiAlarm = 37,
ColumnId_BuysWeapons = 38,
ColumnId_BuysArmor = 39,
ColumnId_BuysClothing = 40,
ColumnId_BuysBooks = 41,
ColumnId_BuysIngredients = 42,
ColumnId_BuysLockpicks = 43,
ColumnId_BuysProbes = 44,
ColumnId_BuysLights = 45,
ColumnId_BuysApparati = 46,
ColumnId_BuysRepairItems = 47,
ColumnId_BuysMiscItems = 48,
ColumnId_BuysPotions = 49,
ColumnId_BuysMagicItems = 50,
ColumnId_SellsSpells = 51,
ColumnId_Trainer = 52,
ColumnId_Spellmaking = 53,
ColumnId_EnchantingService = 54,
ColumnId_RepairService = 55,
ColumnId_ApparatusType = 56,
ColumnId_ArmorType = 57,
ColumnId_Health = 58,
ColumnId_ArmorValue = 59,
ColumnId_Scroll = 60,
ColumnId_ClothingType = 61,
ColumnId_WeightCapacity = 62,
ColumnId_OrganicContainer = 63,
ColumnId_Respawn = 64,
ColumnId_CreatureType = 65,
ColumnId_SoulPoints = 66,
ColumnId_OriginalCreature = 67,
ColumnId_Biped = 68,
ColumnId_HasWeapon = 69,
ColumnId_NoMovement = 70,
ColumnId_Swims = 71,
ColumnId_Flies = 72,
ColumnId_Walks = 73,
ColumnId_Essential = 74,
ColumnId_SkeletonBlood = 75,
ColumnId_MetalBlood = 76,
ColumnId_OpenSound = 77,
ColumnId_CloseSound = 78,
ColumnId_Duration = 79,
ColumnId_Radius = 80,
ColumnId_Colour = 81,
ColumnId_Sound = 82,
ColumnId_Dynamic = 83,
ColumnId_Portable = 84,
ColumnId_NegativeLight = 85,
ColumnId_Flickering = 86,
ColumnId_SlowFlickering = 87,
ColumnId_Pulsing = 88,
ColumnId_SlowPulsing = 89,
ColumnId_Fire = 90,
ColumnId_OffByDefault = 91,
ColumnId_IsKey = 92,
ColumnId_Race = 93,
ColumnId_Class = 94,
Columnid_Hair = 95,
ColumnId_Head = 96,
ColumnId_Female = 97,
ColumnId_WeaponType = 98,
ColumnId_WeaponSpeed = 99,
ColumnId_WeaponReach = 100,
ColumnId_MinChop = 101,
ColumnId_MaxChip = 102,
Columnid_MinSlash = 103,
ColumnId_MaxSlash = 104,
ColumnId_MinThrust = 105,
ColumnId_MaxThrust = 106,
ColumnId_Magical = 107,
ColumnId_Silver = 108,
ColumnId_Filter = 109,
ColumnId_Scope = 110,
ColumnId_Teleport = 35,
ColumnId_TeleportCell = 36,
ColumnId_LockLevel = 37,
ColumnId_Key = 38,
ColumnId_Trap = 39,
ColumnId_BeastRace = 40,
ColumnId_AutoCalc = 41,
ColumnId_StarterSpell = 42,
ColumnId_AlwaysSucceeds = 43,
ColumnId_SleepForbidden = 44,
ColumnId_InteriorWater = 45,
ColumnId_InteriorSky = 46,
ColumnId_Model = 47,
ColumnId_Script = 48,
ColumnId_Icon = 49,
ColumnId_Weight = 50,
ColumnId_EnchantmentPoints = 51,
ColumnId_Quality = 52,
ColumnId_Ai = 53,
ColumnId_AiHello = 54,
ColumnId_AiFlee = 55,
ColumnId_AiFight = 56,
ColumnId_AiAlarm = 57,
ColumnId_BuysWeapons = 58,
ColumnId_BuysArmor = 59,
ColumnId_BuysClothing = 60,
ColumnId_BuysBooks = 61,
ColumnId_BuysIngredients = 62,
ColumnId_BuysLockpicks = 63,
ColumnId_BuysProbes = 64,
ColumnId_BuysLights = 65,
ColumnId_BuysApparati = 66,
ColumnId_BuysRepairItems = 67,
ColumnId_BuysMiscItems = 68,
ColumnId_BuysPotions = 69,
ColumnId_BuysMagicItems = 70,
ColumnId_SellsSpells = 71,
ColumnId_Trainer = 72,
ColumnId_Spellmaking = 73,
ColumnId_EnchantingService = 74,
ColumnId_RepairService = 75,
ColumnId_ApparatusType = 76,
ColumnId_ArmorType = 77,
ColumnId_Health = 78,
ColumnId_ArmorValue = 79,
ColumnId_Scroll = 80,
ColumnId_ClothingType = 81,
ColumnId_WeightCapacity = 82,
ColumnId_OrganicContainer = 83,
ColumnId_Respawn = 84,
ColumnId_CreatureType = 85,
ColumnId_SoulPoints = 86,
ColumnId_OriginalCreature = 87,
ColumnId_Biped = 88,
ColumnId_HasWeapon = 89,
ColumnId_NoMovement = 90,
ColumnId_Swims = 91,
ColumnId_Flies = 92,
ColumnId_Walks = 93,
ColumnId_Essential = 94,
ColumnId_SkeletonBlood = 95,
ColumnId_MetalBlood = 96,
ColumnId_OpenSound = 97,
ColumnId_CloseSound = 98,
ColumnId_Duration = 99,
ColumnId_Radius = 100,
ColumnId_Colour = 101,
ColumnId_Sound = 102,
ColumnId_Dynamic = 103,
ColumnId_Portable = 104,
ColumnId_NegativeLight = 105,
ColumnId_Flickering = 106,
ColumnId_SlowFlickering = 107,
ColumnId_Pulsing = 108,
ColumnId_SlowPulsing = 109,
ColumnId_Fire = 110,
ColumnId_OffByDefault = 111,
ColumnId_IsKey = 112,
ColumnId_Race = 113,
ColumnId_Class = 114,
Columnid_Hair = 115,
ColumnId_Head = 116,
ColumnId_Female = 117,
ColumnId_WeaponType = 118,
ColumnId_WeaponSpeed = 119,
ColumnId_WeaponReach = 120,
ColumnId_MinChop = 121,
ColumnId_MaxChip = 122,
Columnid_MinSlash = 123,
ColumnId_MaxSlash = 124,
ColumnId_MinThrust = 125,
ColumnId_MaxThrust = 126,
ColumnId_Magical = 127,
ColumnId_Silver = 128,
ColumnId_Filter = 129,
ColumnId_PositionXPos = 130,
ColumnId_PositionYPos = 131,
ColumnId_PositionZPos = 132,
ColumnId_PositionXRot = 133,
ColumnId_PositionYRot = 134,
ColumnId_PositionZRot = 135,
ColumnId_DoorPositionXPos = 136,
ColumnId_DoorPositionYPos = 137,
ColumnId_DoorPositionZPos = 138,
ColumnId_DoorPositionXRot = 139,
ColumnId_DoorPositionYRot = 140,
ColumnId_DoorPositionZRot = 141,
ColumnId_DialogueType = 142,
ColumnId_Scope = 143,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.

@ -9,6 +9,7 @@
#include <components/esm/esmreader.hpp>
#include <components/esm/defs.hpp>
#include <components/esm/loadglob.hpp>
#include <components/esm/cellref.hpp>
#include "idtable.hpp"
#include "columnimp.hpp"
@ -151,6 +152,14 @@ CSMWorld::Data::Data() : mRefs (mCells)
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AlwaysSucceeds, 0x4));
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
mTopics.addColumn (new DialogueTypeColumn<ESM::Dialogue>);
mJournals.addColumn (new StringIdColumn<ESM::Dialogue>);
mJournals.addColumn (new RecordStateColumn<ESM::Dialogue>);
mJournals.addColumn (new DialogueTypeColumn<ESM::Dialogue> (true));
mCells.addColumn (new StringIdColumn<Cell>);
mCells.addColumn (new RecordStateColumn<Cell>);
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
@ -164,6 +173,12 @@ CSMWorld::Data::Data() : mRefs (mCells)
mRefs.addColumn (new RecordStateColumn<CellRef>);
mRefs.addColumn (new CellColumn<CellRef>);
mRefs.addColumn (new IdColumn<CellRef>);
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 0, false));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 1, false));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 2, false));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mPos, 0, false));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mPos, 1, false));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mPos, 2, false));
mRefs.addColumn (new ScaleColumn<CellRef>);
mRefs.addColumn (new OwnerColumn<CellRef>);
mRefs.addColumn (new SoulColumn<CellRef>);
@ -174,6 +189,12 @@ CSMWorld::Data::Data() : mRefs (mCells)
mRefs.addColumn (new GoldValueColumn<CellRef>);
mRefs.addColumn (new TeleportColumn<CellRef>);
mRefs.addColumn (new TeleportCellColumn<CellRef>);
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mDoorDest, 0, true));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mDoorDest, 1, true));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mDoorDest, 2, true));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mDoorDest, 0, true));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mDoorDest, 1, true));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mDoorDest, 2, true));
mRefs.addColumn (new LockLevelColumn<CellRef>);
mRefs.addColumn (new KeyColumn<CellRef>);
mRefs.addColumn (new TrapColumn<CellRef>);
@ -195,6 +216,8 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic);
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal);
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable);
@ -318,6 +341,28 @@ CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells()
return mSpells;
}
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics() const
{
return mTopics;
}
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics()
{
return mTopics;
}
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals() const
{
return mJournals;
}
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals()
{
return mJournals;
}
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
{
return mCells;
@ -449,6 +494,41 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base, b
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
case ESM::REC_DIAL:
{
std::string id = reader.getHNOString ("NAME");
ESM::Dialogue record;
record.mId = id;
record.load (reader);
if (record.mType==ESM::Dialogue::Journal)
{
mJournals.load (record, base);
}
else if (record.mType==ESM::Dialogue::Deleted)
{
if (mJournals.tryDelete (id))
{
/// \todo handle info records
}
else if (mTopics.tryDelete (id))
{
/// \todo handle info records
}
else
{
/// \todo report deletion of non-existing record
}
}
else
{
mTopics.load (record, base);
}
break;
}
case ESM::REC_FILT:
if (project)
@ -484,6 +564,8 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getRegions().searchId (id)!=-1 ||
getBirthsigns().searchId (id)!=-1 ||
getSpells().searchId (id)!=-1 ||
getTopics().searchId (id)!=-1 ||
getJournals().searchId (id)!=-1 ||
getCells().searchId (id)!=-1 ||
getReferenceables().searchId (id)!=-1;
}
@ -540,6 +622,8 @@ std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
appendIds (ids, mRegions, listDeleted);
appendIds (ids, mBirthsigns, listDeleted);
appendIds (ids, mSpells, listDeleted);
appendIds (ids, mTopics, listDeleted);
appendIds (ids, mJournals, listDeleted);
appendIds (ids, mCells, listDeleted);
appendIds (ids, mReferenceables, listDeleted);

@ -20,6 +20,7 @@
#include <components/esm/loadregn.hpp>
#include <components/esm/loadbsgn.hpp>
#include <components/esm/loadspel.hpp>
#include <components/esm/loaddial.hpp>
#include "../filter/filter.hpp"
@ -48,6 +49,8 @@ namespace CSMWorld
IdCollection<ESM::Region> mRegions;
IdCollection<ESM::BirthSign> mBirthsigns;
IdCollection<ESM::Spell> mSpells;
IdCollection<ESM::Dialogue> mTopics;
IdCollection<ESM::Dialogue> mJournals;
IdCollection<Cell> mCells;
RefIdCollection mReferenceables;
RefCollection mRefs;
@ -120,6 +123,14 @@ namespace CSMWorld
IdCollection<ESM::Spell>& getSpells();
const IdCollection<ESM::Dialogue>& getTopics() const;
IdCollection<ESM::Dialogue>& getTopics();
const IdCollection<ESM::Dialogue>& getJournals() const;
IdCollection<ESM::Dialogue>& getJournals();
const IdCollection<Cell>& getCells() const;
IdCollection<Cell>& getCells();

@ -7,21 +7,24 @@
namespace CSMWorld
{
/// \brief Single type collection of top level records
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
class IdCollection : public Collection<ESXRecordT, IdAccessorT>
{
public:
void load (ESM::ESMReader& reader, bool base,
UniversalId::Type type = UniversalId::Type_None);
///< \param type Will be ignored, unless the collection supports multiple record types
void load (ESM::ESMReader& reader, bool base);
void load (const ESXRecordT& record, bool base);
bool tryDelete (const std::string& id);
///< Try deleting \a id. If the id does not exist or can't be deleted the call is ignored.
///
/// \return Has the ID been deleted?
};
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base,
UniversalId::Type type)
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
{
std::string id = reader.getHNOString ("NAME");
@ -56,30 +59,62 @@ namespace CSMWorld
IdAccessorT().getId (record) = id;
record.load (reader);
int index = this->searchId (IdAccessorT().getId (record));
load (record, base);
}
}
if (index==-1)
{
// new record
Record<ESXRecordT> record2;
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
(base ? record2.mBase : record2.mModified) = record;
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::load (const ESXRecordT& record, bool base)
{
int index = this->searchId (IdAccessorT().getId (record));
this->appendRecord (record2);
}
if (index==-1)
{
// new record
Record<ESXRecordT> record2;
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
(base ? record2.mBase : record2.mModified) = record;
this->appendRecord (record2);
}
else
{
// old record
Record<ESXRecordT> record2 = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
if (base)
record2.mBase = record;
else
{
// old record
Record<ESXRecordT> record2 = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
record2.setModified (record);
if (base)
record2.mBase = record;
else
record2.setModified (record);
this->setRecord (index, record2);
}
}
this->setRecord (index, record2);
}
template<typename ESXRecordT, typename IdAccessorT>
bool IdCollection<ESXRecordT, IdAccessorT>::tryDelete (const std::string& id)
{
int index = this->searchId (id);
if (index==-1)
return false;
Record<ESXRecordT> record = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
if (record.isDeleted())
return false;
if (record.mState==RecordBase::State_ModifiedOnly)
{
Collection<ESXRecordT, IdAccessorT>::removeRows (index, 1);
}
else
{
record.mState = RecordBase::State_Deleted;
setRecord (index, record);
}
return true;
}
}

@ -29,6 +29,8 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
"Referenceables", 0 },
@ -43,18 +45,20 @@ namespace
static const TypeData sIdArg[] =
{
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", ":./globvar.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":./GMST.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":./skill.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":./class.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":./faction.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":./race.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":./sound.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":./script.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
@ -80,13 +84,14 @@ namespace
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", 0 },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
static const TypeData sIndexArg[] =
{
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};

@ -86,10 +86,15 @@ namespace CSMWorld
Type_Reference,
Type_RegionMap,
Type_Filter,
Type_Filters
Type_Filters,
Type_Topics,
Type_Topic,
Type_Journals,
Type_Journal,
Type_Scene
};
enum { NumberOfTypes = Type_Filters+1 };
enum { NumberOfTypes = Type_Scene+1 };
private:

@ -1,6 +0,0 @@
#include "ocspropertywidget.hpp"
OcsPropertyWidget::OcsPropertyWidget(QObject *parent) :
QObject(parent)
{
}

@ -1,18 +0,0 @@
#ifndef OCSPROPERTYWIDGET_HPP
#define OCSPROPERTYWIDGET_HPP
#include <QObject>
class OcsPropertyWidget : public QObject
{
Q_OBJECT
public:
explicit OcsPropertyWidget(QObject *parent = 0);
signals:
public slots:
};
#endif // OCSPROPERTYWIDGET_HPP

@ -65,7 +65,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
if (path.parent_path().string()==mLocalData.string())
{
// path already points to the local data directory
message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str());
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
mResultPath = path;
mValid = true;
}
@ -74,7 +74,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
// path points somewhere else or is a leaf name.
path = mLocalData / path.filename();
message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str());
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
mResultPath = path;
mValid = true;

@ -115,6 +115,10 @@ void CSVDoc::View::setupWorldMenu()
world->addSeparator(); // items that don't represent single record lists follow here
QAction *scene = new QAction (tr ("Scene"), this);
connect (scene, SIGNAL (triggered()), this, SLOT (addSceneSubView()));
world->addAction (scene);
QAction *regionMap = new QAction (tr ("Region Map"), this);
connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView()));
world->addAction (regionMap);
@ -159,6 +163,14 @@ void CSVDoc::View::setupMechanicsMenu()
QAction *spells = new QAction (tr ("Spells"), this);
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
mechanics->addAction (spells);
QAction *topics = new QAction (tr ("Topics"), this);
connect (topics, SIGNAL (triggered()), this, SLOT (addTopicsSubView()));
mechanics->addAction (topics);
QAction *journals = new QAction (tr ("Journals"), this);
connect (journals, SIGNAL (triggered()), this, SLOT (addJournalsSubView()));
mechanics->addAction (journals);
}
void CSVDoc::View::setupAssetsMenu()
@ -403,6 +415,21 @@ void CSVDoc::View::addFiltersSubView()
addSubView (CSMWorld::UniversalId::Type_Filters);
}
void CSVDoc::View::addSceneSubView()
{
addSubView (CSMWorld::UniversalId::Type_Scene);
}
void CSVDoc::View::addTopicsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Topics);
}
void CSVDoc::View::addJournalsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Journals);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -164,6 +164,12 @@ namespace CSVDoc
void addFiltersSubView();
void addSceneSubView();
void addTopicsSubView();
void addJournalsSubView();
void toggleShowStatusBar (bool show);
};
}

@ -14,7 +14,7 @@
#include "../world/enumdelegate.hpp"
#include "../world/vartypedelegate.hpp"
#include "../world/recordstatusdelegate.hpp"
#include "../world/refidtypedelegate.hpp"
#include "../world/idtypedelegate.hpp"
#include "../settings/usersettingsdialog.hpp"
#include "view.hpp"
@ -56,7 +56,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
new CSVWorld::RecordStatusDelegateFactory());
mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType,
new CSVWorld::RefIdTypeDelegateFactory());
new CSVWorld::IdTypeDelegateFactory());
struct Mapping
{
@ -74,7 +74,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
{ CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false },
{ CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false },
{ CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false },
{ CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false }
{ CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false },
{ CSMWorld::ColumnBase::Display_DialogueType, CSMWorld::Columns::ColumnId_DialogueType, false }
};
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)

@ -6,6 +6,8 @@
#include "../../model/tools/reportmodel.hpp"
#include "../../view/world/idtypedelegate.hpp"
CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: CSVDoc::SubView (id), mModel (document.getReport (id))
{
@ -18,6 +20,11 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc:
mTable->setSelectionBehavior (QAbstractItemView::SelectRows);
mTable->setSelectionMode (QAbstractItemView::ExtendedSelection);
mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate (
document.getUndoStack(), this);
mTable->setItemDelegateForColumn (0, mIdTypeDelegate);
connect (mTable, SIGNAL (doubleClicked (const QModelIndex&)), this, SLOT (show (const QModelIndex&)));
}
@ -26,6 +33,11 @@ void CSVTools::ReportSubView::setEditLock (bool locked)
// ignored. We don't change document state anyway.
}
void CSVTools::ReportSubView::updateEditorSetting (const QString& key, const QString& value)
{
mIdTypeDelegate->updateEditorSetting (key, value);
}
void CSVTools::ReportSubView::show (const QModelIndex& index)
{
focusId (mModel->getUniversalId (index.row()));

@ -16,6 +16,11 @@ namespace CSMTools
class ReportModel;
}
namespace CSVWorld
{
class CommandDelegate;
}
namespace CSVTools
{
class Table;
@ -26,6 +31,7 @@ namespace CSVTools
CSMTools::ReportModel *mModel;
QTableView *mTable;
CSVWorld::CommandDelegate *mIdTypeDelegate;
public:
@ -33,6 +39,8 @@ namespace CSVTools
virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString&, const QString&);
private slots:
void show (const QModelIndex& index);

@ -0,0 +1,35 @@
#include "dialoguecreator.hpp"
#include <components/esm/loaddial.hpp>
#include "../../model/world/data.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/idtable.hpp"
void CSVWorld::DialogueCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
{
int index =
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
findColumnIndex (CSMWorld::Columns::ColumnId_DialogueType);
command.addValue (index, mType);
}
CSVWorld::DialogueCreator::DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, int type)
: GenericCreator (data, undoStack, id), mType (type)
{}
CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMWorld::Data& data,
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
{
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Topic);
}
CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& data,
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
{
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal);
}

@ -0,0 +1,41 @@
#ifndef CSV_WORLD_DIALOGUECREATOR_H
#define CSV_WORLD_DIALOGUECREATOR_H
#include "genericcreator.hpp"
namespace CSVWorld
{
class DialogueCreator : public GenericCreator
{
int mType;
protected:
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
public:
DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, int type);
};
class TopicCreatorFactory : public CreatorFactoryBase
{
public:
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id) const;
///< The ownership of the returned Creator is transferred to the caller.
};
class JournalCreatorFactory : public CreatorFactoryBase
{
public:
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id) const;
///< The ownership of the returned Creator is transferred to the caller.
};
}
#endif

@ -0,0 +1,46 @@
#include "idtypedelegate.hpp"
#include "../../model/world/universalid.hpp"
CSVWorld::IdTypeDelegate::IdTypeDelegate
(const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack, parent)
{}
bool CSVWorld::IdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
/// \todo make the setting key a member variable, that is initialised from a constructor argument
if (settingName == "Referenceable ID Type Display")
{
if (settingValue == "Icon and Text")
mDisplayMode = Mode_IconAndText;
else if (settingValue == "Icon Only")
mDisplayMode = Mode_IconOnly;
else if (settingValue == "Text Only")
mDisplayMode = Mode_TextOnly;
return true;
}
return false;
}
CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory()
{
for (int i=0; i<CSMWorld::UniversalId::NumberOfTypes; ++i)
{
CSMWorld::UniversalId id (static_cast<CSMWorld::UniversalId::Type> (i));
DataDisplayDelegateFactory::add (id.getType(), QString::fromUtf8 (id.getTypeName().c_str()),
QString::fromUtf8 (id.getIcon().c_str()));
}
}
CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new IdTypeDelegate (mValues, mIcons, undoStack, parent);
}

@ -1,5 +1,5 @@
#ifndef REFIDTYPEDELEGATE_HPP
#define REFIDTYPEDELEGATE_HPP
#ifndef IDTYPEDELEGATE_HPP
#define IDTYPEDELEGATE_HPP
#include "enumdelegate.hpp"
#include "util.hpp"
@ -8,29 +8,23 @@
namespace CSVWorld
{
class RefIdTypeDelegate : public DataDisplayDelegate
class IdTypeDelegate : public DataDisplayDelegate
{
public:
RefIdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent);
IdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent);
virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue);
};
class RefIdTypeDelegateFactory : public DataDisplayDelegateFactory
class IdTypeDelegateFactory : public DataDisplayDelegateFactory
{
typedef std::vector < std::pair <CSMWorld::UniversalId::Type, QString> > UidTypeList;
public:
RefIdTypeDelegateFactory();
IdTypeDelegateFactory();
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
private:
UidTypeList buildUidTypeList () const;
};
}

@ -1,62 +0,0 @@
#include "refidtypedelegate.hpp"
#include "../../model/world/universalid.hpp"
CSVWorld::RefIdTypeDelegate::RefIdTypeDelegate
(const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack, parent)
{}
bool CSVWorld::RefIdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
if (settingName == "Referenceable ID Type Display")
{
if (settingValue == "Icon and Text")
mDisplayMode = Mode_IconAndText;
else if (settingValue == "Icon Only")
mDisplayMode = Mode_IconOnly;
else if (settingValue == "Text Only")
mDisplayMode = Mode_TextOnly;
return true;
}
return false;
}
CSVWorld::RefIdTypeDelegateFactory::RefIdTypeDelegateFactory()
{
UidTypeList uIdList = buildUidTypeList();
for (UidTypeList::const_iterator it = uIdList.begin(); it != uIdList.end(); it++)
{
int i = it->first;
DataDisplayDelegateFactory::add (i, QString::fromStdString(CSMWorld::UniversalId(it->first, "").getTypeName()), it->second);
}
}
CSVWorld::CommandDelegate *CSVWorld::RefIdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new RefIdTypeDelegate (mValues, mIcons, undoStack, parent);
}
CSVWorld::RefIdTypeDelegateFactory::UidTypeList CSVWorld::RefIdTypeDelegateFactory::buildUidTypeList() const
{
UidTypeList list;
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listReferenceableTypes();
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
iter!=types.end(); ++iter)
{
CSMWorld::UniversalId id (*iter, "");
list.push_back (std::make_pair (id.getType(), id.getIcon().c_str()));
}
return list;
}

@ -0,0 +1,82 @@
#include "scenesubview.hpp"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include "../../model/doc/document.hpp"
#include "../filter/filterbox.hpp"
#include "tablebottombox.hpp"
#include "creator.hpp"
#include "scenetoolbar.hpp"
#include "scenetoolmode.hpp"
CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: SubView (id)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins (QMargins (0, 0, 0, 0));
layout->addWidget (mBottom =
new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id,
this), 0);
QHBoxLayout *layout2 = new QHBoxLayout;
layout2->setContentsMargins (QMargins (0, 0, 0, 0));
SceneToolbar *toolbar = new SceneToolbar (48, this);
// test
SceneToolMode *tool = new SceneToolMode (toolbar);
tool->addButton (":door.png", "a");
tool->addButton (":GMST.png", "b");
tool->addButton (":Info.png", "c");
toolbar->addTool (tool);
toolbar->addTool (new SceneToolMode (toolbar));
toolbar->addTool (new SceneToolMode (toolbar));
toolbar->addTool (new SceneToolMode (toolbar));
layout2->addWidget (toolbar, 0);
/// \todo replace with rendering widget
QPalette palette2 (palette());
palette2.setColor (QPalette::Background, Qt::white);
QLabel *placeholder = new QLabel ("Here goes the 3D scene", this);
placeholder->setAutoFillBackground (true);
placeholder->setPalette (palette2);
placeholder->setAlignment (Qt::AlignHCenter);
layout2->addWidget (placeholder, 1);
layout->insertLayout (0, layout2, 1);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
layout->insertWidget (0, filterBox);
QWidget *widget = new QWidget;
widget->setLayout (layout);
setWidget (widget);
}
void CSVWorld::SceneSubView::setEditLock (bool locked)
{
}
void CSVWorld::SceneSubView::updateEditorSetting(const QString &settingName, const QString &settingValue)
{
}
void CSVWorld::SceneSubView::setStatusBar (bool show)
{
mBottom->setStatusBar (show);
}

@ -0,0 +1,37 @@
#ifndef CSV_WORLD_SCENESUBVIEW_H
#define CSV_WORLD_SCENESUBVIEW_H
#include "../doc/subview.hpp"
class QModelIndex;
namespace CSMDoc
{
class Document;
}
namespace CSVWorld
{
class Table;
class TableBottomBox;
class CreatorFactoryBase;
class SceneSubView : public CSVDoc::SubView
{
Q_OBJECT
TableBottomBox *mBottom;
public:
SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString& key, const QString& value);
virtual void setStatusBar (bool show);
};
}
#endif

@ -0,0 +1,17 @@
#include "scenetool.hpp"
#include "scenetoolbar.hpp"
CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent)
{
setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
setFixedSize (parent->getButtonSize(), parent->getButtonSize());
connect (this, SIGNAL (clicked()), this, SLOT (openRequest()));
}
void CSVWorld::SceneTool::openRequest()
{
showPanel (parentWidget()->mapToGlobal (pos()));
}

@ -0,0 +1,27 @@
#ifndef CSV_WORLD_SCENETOOL_H
#define CSV_WORLD_SCENETOOL_H
#include <QPushButton>
namespace CSVWorld
{
class SceneToolbar;
///< \brief Tool base class
class SceneTool : public QPushButton
{
Q_OBJECT
public:
SceneTool (SceneToolbar *parent);
virtual void showPanel (const QPoint& position) = 0;
private slots:
void openRequest();
};
}
#endif

@ -0,0 +1,29 @@
#include "scenetoolbar.hpp"
#include <QVBoxLayout>
#include "scenetool.hpp"
CSVWorld::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent)
: QWidget (parent), mButtonSize (buttonSize)
{
setFixedWidth (mButtonSize);
mLayout = new QVBoxLayout (this);
mLayout->setAlignment (Qt::AlignTop);
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
setLayout (mLayout);
}
void CSVWorld::SceneToolbar::addTool (SceneTool *tool)
{
mLayout->addWidget (tool, 0, Qt::AlignTop);
}
int CSVWorld::SceneToolbar::getButtonSize() const
{
return mButtonSize;
}

@ -0,0 +1,29 @@
#ifndef CSV_WORLD_SCENETOOLBAR_H
#define CSV_WORLD_SCENETOOLBAR_H
#include <QWidget>
class QVBoxLayout;
namespace CSVWorld
{
class SceneTool;
class SceneToolbar : public QWidget
{
Q_OBJECT
QVBoxLayout *mLayout;
int mButtonSize;
public:
SceneToolbar (int buttonSize, QWidget *parent = 0);
void addTool (SceneTool *tool);
int getButtonSize() const;
};
}
#endif

@ -0,0 +1,56 @@
#include "scenetoolmode.hpp"
#include <QHBoxLayout>
#include <QFrame>
#include <QSignalMapper>
#include "scenetoolbar.hpp"
CSVWorld::SceneToolMode::SceneToolMode (SceneToolbar *parent)
: SceneTool (parent), mButtonSize (parent->getButtonSize())
{
mPanel = new QFrame (this, Qt::Popup);
mLayout = new QHBoxLayout (mPanel);
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
mPanel->setLayout (mLayout);
}
void CSVWorld::SceneToolMode::showPanel (const QPoint& position)
{
mPanel->move (position);
mPanel->show();
}
void CSVWorld::SceneToolMode::addButton (const std::string& icon, const std::string& id)
{
QPushButton *button = new QPushButton (QIcon (QPixmap (icon.c_str())), "", mPanel);
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
button->setFixedSize (mButtonSize, mButtonSize);
mLayout->addWidget (button);
mButtons.insert (std::make_pair (button, id));
connect (button, SIGNAL (clicked()), this, SLOT (selected()));
if (mButtons.size()==1)
setIcon (button->icon());
}
void CSVWorld::SceneToolMode::selected()
{
std::map<QPushButton *, std::string>::const_iterator iter =
mButtons.find (dynamic_cast<QPushButton *> (sender()));
if (iter!=mButtons.end())
{
mPanel->hide();
setIcon (iter->first->icon());
emit modeChanged (iter->second);
}
}

@ -0,0 +1,42 @@
#ifndef CSV_WORLD_SCENETOOL_MODE_H
#define CSV_WORLD_SCENETOOL_MODE_H
#include "scenetool.hpp"
#include <map>
class QHBoxLayout;
namespace CSVWorld
{
class SceneToolbar;
///< \brief Mode selector tool
class SceneToolMode : public SceneTool
{
Q_OBJECT
QWidget *mPanel;
QHBoxLayout *mLayout;
std::map<QPushButton *, std::string> mButtons; // widget, id
int mButtonSize;
public:
SceneToolMode (SceneToolbar *parent);
virtual void showPanel (const QPoint& position);
void addButton (const std::string& icon, const std::string& id);
signals:
void modeChanged (const std::string& id);
private slots:
void selected();
};
}
#endif

@ -13,6 +13,8 @@
#include "cellcreator.hpp"
#include "referenceablecreator.hpp"
#include "referencecreator.hpp"
#include "scenesubview.hpp"
#include "dialoguecreator.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{
@ -52,6 +54,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_References,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >);
manager.add (CSMWorld::UniversalId::Type_Topics,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, TopicCreatorFactory>);
manager.add (CSMWorld::UniversalId::Type_Journal,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>);
// Subviews for editing/viewing individual records
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
@ -62,4 +70,5 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
new CSVDoc::SubViewFactoryWithCreator<TableSubView,
CreatorFactory<CSVFilter::FilterCreator> >);
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
}

@ -12,8 +12,8 @@
#include "../../model/world/idtableproxymodel.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/record.hpp"
#include "recordstatusdelegate.hpp"
#include "refidtypedelegate.hpp"
#include "util.hpp"
void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
@ -87,19 +87,33 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
{
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
// check record state
CSMWorld::RecordBase::State state =
static_cast<CSMWorld::RecordBase::State> (
mModel->data (mModel->index (index.row(), 1)).toInt());
if (state!=CSMWorld::RecordBase::State_Deleted)
{
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
if (state==CSMWorld::RecordBase::State_Deleted)
continue;
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
toString().toUtf8().constData();
// check other columns (only relevant for a subset of the tables)
int dialogueTypeIndex =
mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_DialogueType);
deletableIds.push_back (id);
if (dialogueTypeIndex!=-1)
{
int type = mModel->data (mModel->index (index.row(), dialogueTypeIndex)).toInt();
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
continue;
}
// add the id to the collection
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
toString().toUtf8().constData();
deletableIds.push_back (id);
}
}

@ -379,8 +379,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding);
mEnvironment.setWindowManager (window);
if (mNewGame)
mEnvironment.getWindowManager()->setNewGame(true);
// Create the world
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles,
@ -390,6 +388,10 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
window->initUI();
if (mNewGame)
// still redundant work here: recreate CharacterCreation(),
// double update visibility etc.
window->setNewGame(true);
window->renderWorldMap();
//Load translation data

@ -324,6 +324,7 @@ namespace MWBase
virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0;
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0;
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0;
virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
@ -389,6 +390,12 @@ namespace MWBase
/// Returns true if teleport spell effects are allowed.
virtual bool isTeleportingEnabled() const = 0;
/// Enables or disables use of levitation spell effect.
virtual void enableLevitation(bool enable) = 0;
/// Returns true if levitation spell effect is allowed.
virtual bool isLevitationEnabled() const = 0;
/// Turn actor into werewolf or normal form.
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0;

@ -16,12 +16,34 @@
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/customdata.hpp"
#include "../mwgui/tooltips.hpp"
#include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp"
namespace
{
struct CustomData : public MWWorld::CustomData
{
float mTime;
///< Time remaining
CustomData(MWWorld::Ptr ptr)
{
MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>();
mTime = ref->mBase->mData.mTime;
}
///< Constructs this CustomData from the base values for Ptr.
virtual MWWorld::CustomData *clone() const
{
return new CustomData (*this);
}
};
}
namespace MWClass
{
void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -182,6 +204,21 @@ namespace MWClass
return action;
}
void Light::setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const
{
ensureCustomData(ptr);
float &timeRemaining = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime;
timeRemaining = duration;
}
float Light::getRemainingUsageTime (const MWWorld::Ptr& ptr) const
{
ensureCustomData(ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime;
}
MWWorld::Ptr
Light::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{
@ -191,6 +228,12 @@ namespace MWClass
return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell);
}
void Light::ensureCustomData (const MWWorld::Ptr& ptr) const
{
if (!ptr.getRefData().getCustomData())
ptr.getRefData().setCustomData(new CustomData(ptr));
}
bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Lights;

@ -10,6 +10,8 @@ namespace MWClass
virtual MWWorld::Ptr
copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const;
void ensureCustomData (const MWWorld::Ptr& ptr) const;
public:
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
@ -56,6 +58,12 @@ namespace MWClass
const;
///< Generate action for using via inventory menu
virtual void setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const;
///< Sets the remaining duration of the object.
virtual float getRemainingUsageTime (const MWWorld::Ptr& ptr) const;
///< Returns the remaining duration of the object.
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual float getWeight (const MWWorld::Ptr& ptr) const;

@ -7,6 +7,7 @@
#include <OgreSceneNode.h>
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadnpc.hpp>
#include "../mwbase/environment.hpp"
@ -396,9 +397,10 @@ namespace MWClass
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
}
weapon.getCellRef().mCharge -= std::min(std::max(1,
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())),
weapon.getCellRef().mCharge);
if (!MWBase::Environment::get().getWorld()->getGodModeState())
weapon.getCellRef().mCharge -= std::min(std::max(1,
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
}
healthdmg = true;
}
@ -769,6 +771,37 @@ namespace MWClass
return x;
}
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
{
MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
const float fallDistanceMin = gmst.find("fFallDamageDistanceMin")->getFloat();
if (fallHeight >= fallDistanceMin)
{
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude;
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
const float fallDistanceMult = gmst.find("fFallDistanceMult")->getFloat();
float x = fallHeight - fallDistanceMin;
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
x = std::max(0.0f, x);
float a = fallAcroBase + fallAcroMult * (100 - acrobaticsSkill);
x = fallDistanceBase + fallDistanceMult * x;
x *= a;
return x;
}
return 0;
}
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
{
ensureCustomData (ptr);

@ -97,6 +97,9 @@ namespace MWClass
virtual float getJump(const MWWorld::Ptr &ptr) const;
///< Return jump velocity (not accounting for movement)
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
///< Return amount of health points lost when falling
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement.

@ -23,6 +23,7 @@ namespace MWGui
, mLastWallpaperChangeTime(0.f)
, mFirstLoad(true)
, mProgress(0)
, mVSyncWasEnabled(false)
{
getWidget(mLoadingText, "LoadingText");
getWidget(mProgressBar, "ProgressBar");
@ -67,6 +68,14 @@ namespace MWGui
void LoadingScreen::loadingOn()
{
// Temporarily turn off VSync, we want to do actual loading rather than waiting for the screen to sync.
// Threaded loading would be even better, of course - especially because some drivers force VSync to on and we can't change it.
// In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged with GLX, nothing we can do :/
mVSyncWasEnabled = mWindow->isVSyncEnabled();
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
mWindow->setVSyncEnabled(false);
#endif
setVisible(true);
if (mFirstLoad)
@ -83,6 +92,12 @@ namespace MWGui
void LoadingScreen::loadingOff()
{
// Re-enable vsync now.
// In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged with GLX, nothing we can do :/
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
mWindow->setVSyncEnabled(mVSyncWasEnabled);
#endif
setVisible(false);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
@ -212,7 +227,8 @@ namespace MWGui
// caused a sync / flush and would be expensive).
// We're doing this so we can do some actual loading while the GPU is busy with the render.
// This means the render is lagging a frame behind, but this is hardly noticable.
mWindow->swapBuffers(false); // never Vsync, makes no sense here
mWindow->swapBuffers();
mWindow->update(false);
if (!hasCompositor)

@ -57,6 +57,8 @@ namespace MWGui
Ogre::StringVector mResources;
bool mVSyncWasEnabled;
void changeWallpaper();
void draw();

@ -70,7 +70,10 @@ namespace MWGui
{
MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f);
if (sender == mButtons["return"])
{
MWBase::Environment::get().getSoundManager ()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);
MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu);
}
else if (sender == mButtons["options"])
MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings);
else if (sender == mButtons["exitgame"])

@ -14,6 +14,7 @@ namespace MWGui
mMessageBoxSpeed = 0.1;
mInterMessageBoxe = NULL;
mStaticMessageBox = NULL;
mLastButtonPressed = -1;
}
void MessageBoxManager::onFrame (float frameDuration)
@ -62,6 +63,7 @@ namespace MWGui
}
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
mLastButtonPressed = mInterMessageBoxe->readPressedButton();
delete mInterMessageBoxe;
mInterMessageBoxe = NULL;
MWBase::Environment::get().getInputManager()->changeInputMode(
@ -107,6 +109,7 @@ namespace MWGui
}
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
mLastButtonPressed = -1;
return true;
}
@ -154,11 +157,9 @@ namespace MWGui
int MessageBoxManager::readPressedButton ()
{
if(mInterMessageBoxe != NULL)
{
return mInterMessageBoxe->readPressedButton();
}
return -1;
int pressed = mLastButtonPressed;
mLastButtonPressed = -1;
return pressed;
}
@ -421,9 +422,7 @@ namespace MWGui
int InteractiveMessageBox::readPressedButton ()
{
int pressed = mButtonPressed;
mButtonPressed = -1;
return pressed;
return mButtonPressed;
}
}

@ -56,6 +56,7 @@ namespace MWGui
MessageBox* mStaticMessageBox;
std::vector<MessageBoxManagerTimer> mTimers;
float mMessageBoxSpeed;
int mLastButtonPressed;
};
class MessageBox : public OEngine::GUI::Layout

@ -363,8 +363,12 @@ namespace MWGui
else if (_sender == mVSyncButton)
{
Settings::Manager::setBool("vsync", "Video", newState);
// Ogre::Window::setVSyncEnabled is bugged in 1.8
#if OGRE_VERSION < (1 << 16 | 9 << 8 | 0)
MWBase::Environment::get().getWindowManager()->
messageBox("VSync will be applied after a restart", std::vector<std::string>());
#endif
apply();
}
else
{

@ -2,6 +2,9 @@
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <iomanip>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
@ -169,13 +172,34 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->getGameSettingString(
ESM::Attribute::sGmstAttributeIds[effectIt->mKey.mArg], "") + ")";
if (!(effect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
ESM::MagicEffect::MagnitudeDisplayType displayType = effect->getMagnitudeDisplayType();
if (displayType == ESM::MagicEffect::MDT_TimesInt)
{
std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", "");
std::stringstream formatter;
formatter << std::fixed << std::setprecision(1) << " " << (effectIt->mMagnitude / 10.0f) << timesInt;
sourcesDescription += formatter.str();
}
else if ( displayType != ESM::MagicEffect::MDT_None )
{
std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "");
std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "");
sourcesDescription += ": " + boost::lexical_cast<std::string>(effectIt->mMagnitude);
sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt);
if ( displayType == ESM::MagicEffect::MDT_Percentage )
sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", "");
else if ( displayType == ESM::MagicEffect::MDT_Feet )
sourcesDescription += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", "");
else if ( displayType == ESM::MagicEffect::MDT_Level )
{
sourcesDescription += " " + ((effectIt->mMagnitude > 1) ?
MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", "") :
MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", "") );
}
else // ESM::MagicEffect::MDT_Points
{
sourcesDescription += " " + ((effectIt->mMagnitude > 1) ?
MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "") :
MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "") );
}
}
}

@ -2,6 +2,9 @@
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <iomanip>
#include <MyGUI_ProgressBar.h>
#include <MyGUI_ImageBox.h>
#include <MyGUI_ControllerManager.h>
@ -405,6 +408,10 @@ namespace MWGui
std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "");
std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "");
std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", "");
std::string ft = MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", "");
std::string lvl = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", "");
std::string lvls = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", "");
std::string to = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "") + " ";
std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", "");
std::string secs = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", "");
@ -421,13 +428,32 @@ namespace MWGui
spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], "");
}
if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
{
if (mEffectParams.mMagnMin == mEffectParams.mMagnMax)
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts);
else
{
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + to + boost::lexical_cast<std::string>(mEffectParams.mMagnMax) + " " + pts;
if (mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) {
ESM::MagicEffect::MagnitudeDisplayType displayType = magicEffect->getMagnitudeDisplayType();
if ( displayType == ESM::MagicEffect::MDT_TimesInt ) {
std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", "");
std::stringstream formatter;
formatter << std::fixed << std::setprecision(1) << " " << (mEffectParams.mMagnMin / 10.0f);
if (mEffectParams.mMagnMin != mEffectParams.mMagnMax)
formatter << to << (mEffectParams.mMagnMax / 10.0f);
formatter << timesInt;
spellLine += formatter.str();
}
else if ( displayType != ESM::MagicEffect::MDT_None ) {
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin);
if (mEffectParams.mMagnMin != mEffectParams.mMagnMax)
spellLine += to + boost::lexical_cast<std::string>(mEffectParams.mMagnMax);
if ( displayType == ESM::MagicEffect::MDT_Percentage )
spellLine += pct;
else if ( displayType == ESM::MagicEffect::MDT_Feet )
spellLine += " " + ft;
else if ( displayType == ESM::MagicEffect::MDT_Level )
spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? lvl : lvls );
else // ESM::MagicEffect::MDT_Points
spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts );
}
}

@ -61,20 +61,23 @@ namespace MWGui
const Compiler::Extensions& extensions, int fpsLevel, OEngine::Render::OgreRenderer *ogre,
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
Translation::Storage& translationDataStorage, ToUTF8::FromType encoding)
: mGuiManager(NULL)
, mConsoleOnlyScripts(consoleOnlyScripts)
: mConsoleOnlyScripts(consoleOnlyScripts)
, mGuiManager(NULL)
, mRendering(ogre)
, mHud(NULL)
, mMap(NULL)
, mMenu(NULL)
, mStatsWindow(NULL)
, mToolTips(NULL)
, mStatsWindow(NULL)
, mMessageBoxManager(NULL)
, mConsole(NULL)
, mJournal(NULL)
, mDialogueWindow(NULL)
, mBookWindow(NULL)
, mContainerWindow(NULL)
, mDragAndDrop(NULL)
, mInventoryWindow(NULL)
, mScrollWindow(NULL)
, mBookWindow(NULL)
, mCountDialog(NULL)
, mTradeWindow(NULL)
, mSpellBuyingWindow(NULL)
@ -83,27 +86,37 @@ namespace MWGui
, mConfirmationDialog(NULL)
, mAlchemyWindow(NULL)
, mSpellWindow(NULL)
, mQuickKeysMenu(NULL)
, mLoadingScreen(NULL)
, mCharGen(NULL)
, mLevelupDialog(NULL)
, mWaitDialog(NULL)
, mSpellCreationDialog(NULL)
, mEnchantingDialog(NULL)
, mTrainingWindow(NULL)
, mMerchantRepair(NULL)
, mRepair(NULL)
, mSoulgemDialog(NULL)
, mRepair(NULL)
, mCompanionWindow(NULL)
, mTranslationDataStorage (translationDataStorage)
, mSoftwareCursor(NULL)
, mCharGen(NULL)
, mInputBlocker(NULL)
, mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD"))
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true)
, mCursorVisible(true)
, mPlayerName()
, mPlayerRaceId()
, mPlayerAttributes()
, mPlayerMajorSkills()
, mPlayerMinorSkills()
, mPlayerMajorSkills()
, mPlayerSkillValues()
, mPlayerHealth()
, mPlayerMagicka()
, mPlayerFatigue()
, mGui(NULL)
, mGuiModes()
, mCursorManager(NULL)
, mGarbageDialogs()
, mShown(GW_ALL)
, mForceHidden(GW_None)
@ -113,13 +126,7 @@ namespace MWGui
, mFPS(0.0f)
, mTriangleCount(0)
, mBatchCount(0)
, mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD"))
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true)
, mTranslationDataStorage (translationDataStorage)
, mCursorManager(NULL)
, mUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI"))
, mCursorVisible(true)
{
// Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath);

@ -468,6 +468,41 @@ namespace MWInput
bool InputManager::keyPressed( const SDL_KeyboardEvent &arg )
{
// Cut, copy & paste
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
if (focus)
{
MyGUI::EditBox* edit = focus->castType<MyGUI::EditBox>(false);
if (edit && !edit->getEditReadOnly())
{
if (arg.keysym.sym == SDLK_v && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
{
char* text = SDL_GetClipboardText();
if (text)
{
edit->addText(MyGUI::UString(text));
SDL_free(text);
}
}
if (arg.keysym.sym == SDLK_x && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
{
std::string text = edit->getTextSelection();
if (text.length())
{
SDL_SetClipboardText(text.c_str());
edit->deleteTextSelection();
}
}
if (arg.keysym.sym == SDLK_c && (arg.keysym.mod & SDL_Keymod(KMOD_CTRL)))
{
std::string text = edit->getTextSelection();
if (text.length())
SDL_SetClipboardText(text.c_str());
}
}
}
mInputBinder->keyPressed (arg);
if(arg.keysym.sym == SDLK_RETURN
@ -577,8 +612,8 @@ namespace MWInput
rot[0] = -y;
rot[1] = 0.0f;
rot[2] = x;
// Only actually turn player when we're not in vanity mode
// Only actually turn player when we're not in vanity mode
if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot))
{
mPlayer->yaw(x/scale);
@ -617,9 +652,15 @@ namespace MWInput
if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video)
MWBase::Environment::get().getWorld ()->stopVideo ();
else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
{
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);
}
else
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx);
}
}
void InputManager::toggleSpell()

@ -31,18 +31,24 @@ namespace MWMechanics
calculateDynamicStats (ptr);
calculateCreatureStatModifiers (ptr);
// AI
if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
{
// AI
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
creatureStats.getAiSequence().execute (ptr);
// fatigue restoration
calculateRestoration(ptr, duration);
}
}
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)
{
if(!paused)
{
updateDrowning(ptr, duration);
updateEquippedLight(ptr, duration);
}
}
void Actors::adjustMagicEffects (const MWWorld::Ptr& creature)
@ -93,39 +99,29 @@ namespace MWMechanics
void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration)
{
CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
float capacity = MWWorld::Class::get(ptr).getCapacity(ptr);
float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr);
float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
if (duration == 3600)
{
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
// the actor is sleeping, restore health and magicka
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
DynamicStat<float> health = stats.getHealth();
health.setCurrent (health.getCurrent() + 0.1 * endurance);
stats.setHealth (health);
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
float fFatigueReturnBase = store.get<ESM::GameSetting>().find("fFatigueReturnBase")->getFloat ();
float fFatigueReturnMult = store.get<ESM::GameSetting>().find("fFatigueReturnMult")->getFloat ();
float fEndFatigueMult = store.get<ESM::GameSetting>().find("fEndFatigueMult")->getFloat ();
float capacity = MWWorld::Class::get(ptr).getCapacity(ptr);
float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr);
float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
x *= fEndFatigueMult * endurance;
DynamicStat<float> fatigue = stats.getFatigue();
fatigue.setCurrent (fatigue.getCurrent() + 3600 * x);
stats.setFatigue (fatigue);
if (!stunted)
{
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat ();
float fRestMagicMult = settings.find("fRestMagicMult")->getFloat ();
DynamicStat<float> magicka = stats.getMagicka();
magicka.setCurrent (magicka.getCurrent()
@ -133,6 +129,19 @@ namespace MWMechanics
stats.setMagicka (magicka);
}
}
// restore fatigue
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
float fEndFatigueMult = settings.find("fEndFatigueMult")->getFloat ();
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
x *= fEndFatigueMult * endurance;
DynamicStat<float> fatigue = stats.getFatigue();
fatigue.setCurrent (fatigue.getCurrent() + duration * x);
stats.setFatigue (fatigue);
}
void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
@ -196,6 +205,49 @@ namespace MWMechanics
stats.setTimeToStartDrowning(20);
}
void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration)
{
//If holding a light...
MWWorld::InventoryStore &inventoryStore = MWWorld::Class::get(ptr).getInventoryStore(ptr);
MWWorld::ContainerStoreIterator heldIter =
inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
if(heldIter.getType() == MWWorld::ContainerStore::Type_Light)
{
// Use time from the player's light
bool isPlayer = ptr.getRefData().getHandle()=="player";
if(isPlayer)
{
float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter);
// -1 is infinite light source. Other negative values are treated as 0.
if(timeRemaining != -1.0f)
{
timeRemaining -= duration;
if(timeRemaining > 0.0f)
heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining);
else
{
heldIter->getRefData().setCount(0); // remove it
return;
}
}
}
// Both NPC and player lights extinguish in water.
if(MWBase::Environment::get().getWorld()->isSwimming(ptr))
{
heldIter->getRefData().setCount(0); // remove it
// ...But, only the player makes a sound.
if(isPlayer)
MWBase::Environment::get().getSoundManager()->playSound("torch out",
1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoEnv);
}
}
}
Actors::Actors() : mDuration (0) {}
void Actors::addActor (const MWWorld::Ptr& ptr)
@ -276,7 +328,8 @@ namespace MWMechanics
}
// If it's the player and God Mode is turned on, keep it alive
if(iter->first.getRefData().getHandle()=="player" && MWBase::Environment::get().getWorld()->getGodModeState())
if(iter->first.getRefData().getHandle()=="player" &&
MWBase::Environment::get().getWorld()->getGodModeState())
{
MWMechanics::DynamicStat<float> stat(stats.getHealth());

@ -44,6 +44,8 @@ namespace MWMechanics
void updateDrowning (const MWWorld::Ptr& ptr, float duration);
void updateEquippedLight (const MWWorld::Ptr& ptr, float duration);
public:
Actors();

@ -767,10 +767,25 @@ void CharacterController::update(float duration)
}
if(sneak || inwater || flying)
{
vec.z = 0.0f;
mFallHeight = mPtr.getRefData().getPosition().pos[2];
}
if(!onground && !flying && !inwater)
{
// The player is in the air (either getting up —ascending part of jump— or falling).
if (world->isSlowFalling(mPtr))
{
// SlowFalling spell effect is active, do not keep previous fall height
mFallHeight = mPtr.getRefData().getPosition().pos[2];
}
else
{
mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]);
}
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
forcestateupdate = (mJumpState != JumpState_Falling);
@ -794,6 +809,8 @@ void CharacterController::update(float duration)
}
else if(vec.z > 0.0f && mJumpState == JumpState_None)
{
// The player has started a jump.
float z = cls.getJump(mPtr);
if(vec.x == 0 && vec.y == 0)
vec = Ogre::Vector3(0.0f, 0.0f, z);
@ -803,13 +820,49 @@ void CharacterController::update(float duration)
vec = Ogre::Vector3(lat.x, lat.y, 1.0f) * z * 0.707f;
}
//decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult;
// advance acrobatics
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0);
// decrease fatigue
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat();
const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat();
const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr);
const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult;
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
cls.getCreatureStats(mPtr).setFatigue(fatigue);
}
else if(mJumpState == JumpState_Falling)
{
// The player is landing.
forcestateupdate = true;
mJumpState = JumpState_Landing;
vec.z = 0.0f;
float healthLost = cls.getFallDamage(mPtr, mFallHeight - mPtr.getRefData().getPosition().pos[2]);
if (healthLost > 0.0f)
{
const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm();
// inflict fall damages
DynamicStat<float> health = cls.getCreatureStats(mPtr).getHealth();
int realHealthLost = healthLost * (1.0f - 0.25 * fatigueTerm);
health.setCurrent(health.getCurrent() - realHealthLost);
cls.getCreatureStats(mPtr).setHealth(health);
// report acrobatics progression
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1);
const float acrobaticsSkill = cls.getNpcStats(mPtr).getSkill(ESM::Skill::Acrobatics).getModified();
if (healthLost > (acrobaticsSkill * fatigueTerm))
{
//TODO: actor falls over
}
}
mFallHeight = mPtr.getRefData().getPosition().pos[2];
}
else
{

@ -3,6 +3,8 @@
#include <OgreVector3.h>
#include <components/esm/loadmgef.hpp>
#include "../mwworld/ptr.hpp"
namespace MWWorld
@ -154,6 +156,9 @@ class CharacterController
float mSecondsOfSwimming;
float mSecondsOfRunning;
// used for acrobatics progress and fall damages
float mFallHeight;
std::string mAttackType; // slash, chop or thrust
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);

@ -187,6 +187,12 @@ namespace MWRender
rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false);
}
void Camera::setSneakOffset()
{
if(mAnimation)
mAnimation->addFirstPersonOffset(Ogre::Vector3(0.f, 0.f, -9.8f));
}
float Camera::getYaw()
{
if(mVanity.enabled || mPreviewMode)

@ -79,6 +79,12 @@ namespace MWRender
void togglePreviewMode(bool enable);
/// \brief Lowers the camera for sneak.
/// As animation is tied to the camera, this needs
/// to be set each frame after the animation is
/// applied.
void setSneakOffset();
bool isFirstPerson() const
{ return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); }

@ -84,7 +84,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
mWeapon(inv.end()),
mShield(inv.end()),
mViewMode(viewMode),
mShowWeapons(false)
mShowWeapons(false),
mFirstPersonOffset(0.f, 0.f, 0.f)
{
mNpc = mPtr.get<ESM::NPC>()->mBase;
@ -392,6 +393,11 @@ void NpcAnimation::updateParts(bool forceupdate)
}
}
void NpcAnimation::addFirstPersonOffset(const Ogre::Vector3 &offset)
{
mFirstPersonOffset += offset;
}
class SetObjectGroup {
int mGroup;
@ -448,7 +454,12 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
float pitch = mCamera->getPitch();
Ogre::Node *node = baseinst->getBone("Bip01 Neck");
node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD);
// This has to be done before this function ends;
// updateSkeletonInstance, below, touches the hands.
node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD);
}
mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame.
for(size_t i = 0;i < ESM::PRT_Count;i++)
{

@ -64,6 +64,8 @@ private:
int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty
int mPartPriorities[ESM::PRT_Count];
Ogre::Vector3 mFirstPersonOffset;
void updateNpcBase();
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename);
@ -89,6 +91,11 @@ public:
void updateParts(bool forceupdate = false);
/// \brief Applies a translation to the arms and hands.
/// This may be called multiple times before the animation
/// is updated to add additional offsets.
void addFirstPersonOffset(const Ogre::Vector3 &offset);
/// Rebuilds the NPC, updating their root model, animation sources, and equipment.
void rebuild();
};

@ -354,6 +354,15 @@ void RenderingManager::update (float duration, bool paused)
mCamera->setCameraDistance(test.second * orig.distance(dest), false, false);
}
// Sink the camera while sneaking
bool isSneaking = MWWorld::Class::get(player).getStance(player, MWWorld::Class::Sneak);
bool isInAir = !world->isOnGround(player);
bool isSwimming = world->isSwimming(player);
if(isSneaking && !(isSwimming || isInAir))
mCamera->setSneakOffset();
mOcclusionQuery->update(duration);
mVideoPlayer->update ();
@ -760,6 +769,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
|| it->second == "resolution y"
|| it->second == "fullscreen"))
changeRes = true;
else if (it->first == "Video" && it->second == "vsync")
{
// setVSyncEnabled is bugged in 1.8
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
mRendering.getWindow()->setVSyncEnabled(Settings::Manager::getBool("vsync", "Video"));
#endif
}
else if (it->second == "field of view" && it->first == "General")
mRendering.setFov(Settings::Manager::getFloat("field of view", "General"));
else if ((it->second == "texture filtering" && it->first == "General")

@ -352,5 +352,7 @@ op 0x200021c: SetWerewolfAcrobaticsExplicit
op 0x200021d: ShowVars
op 0x200021e: ShowVarsExplicit
op 0x200021f: ToggleGodMode
op 0x2000220: DisableLevitation
op 0x2000221: EnableLevitation
opcodes 0x2000220-0x3ffffff unused
opcodes 0x2000222-0x3ffffff unused

@ -635,7 +635,18 @@ namespace MWScript
world->enableTeleporting(Enable);
}
};
template <bool Enable>
class OpEnableLevitation : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
world->enableLevitation(Enable);
}
};
template <class R>
class OpShowVars : public Interpreter::Opcode0
@ -789,6 +800,8 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars<ImplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeShowVarsExplicit, new OpShowVars<ExplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode);
interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation<false>);
interpreter.installSegment5 (Compiler::Misc::opcodeEnableLevitation, new OpEnableLevitation<true>);
}
}
}

@ -132,6 +132,16 @@ namespace MWWorld
throw std::runtime_error ("class does not support unlocking");
}
void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const
{
throw std::runtime_error ("class does not support time-based uses");
}
float Class::getRemainingUsageTime (const Ptr& ptr) const
{
throw std::runtime_error ("class does not support time-based uses");
}
std::string Class::getScript (const Ptr& ptr) const
{
return "";
@ -167,6 +177,11 @@ namespace MWWorld
throw std::runtime_error ("class does not support enchanting");
}
float Class::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
{
return 0;
}
MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
{
throw std::runtime_error ("movement settings not supported by class");

@ -156,6 +156,14 @@ namespace MWWorld
virtual void unlock (const Ptr& ptr) const;
///< Unlock object (default implementation: throw an exception)
virtual void setRemainingUsageTime (const Ptr& ptr, float duration) const;
///< Sets the remaining duration of the object, such as an equippable light
/// source. (default implementation: throw an exception)
virtual float getRemainingUsageTime (const Ptr& ptr) const;
///< Returns the remaining duration of the object, such as an equippable light
/// source. (default implementation: throw an exception)
virtual std::string getScript (const Ptr& ptr) const;
///< Return name of the script attached to ptr (default implementation: return an empty
/// string).
@ -175,6 +183,9 @@ namespace MWWorld
virtual float getJump(const MWWorld::Ptr &ptr) const;
///< Return jump velocity (not accounting for movement)
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
///< Return amount of health points lost when falling
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
///< Return desired movement.

@ -656,26 +656,38 @@ namespace MWWorld
return iterator(mSharedExt.end());
}
/// \todo implement appropriate index
// Return the northernmost cell in the easternmost column.
const ESM::Cell *searchExtByName(const std::string &id) const {
ESM::Cell *cell = 0;
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) {
if (Misc::StringUtils::ciEqual((*it)->mName, id)) {
return *it;
if ( cell == 0 ||
( (*it)->mData.mX > cell->mData.mX ) ||
( (*it)->mData.mX == cell->mData.mX && (*it)->mData.mY > cell->mData.mY ) )
{
cell = *it;
}
}
}
return 0;
return cell;
}
/// \todo implement appropriate index
// Return the northernmost cell in the easternmost column.
const ESM::Cell *searchExtByRegion(const std::string &id) const {
ESM::Cell *cell = 0;
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) {
if (Misc::StringUtils::ciEqual((*it)->mRegion, id)) {
return *it;
if ( cell == 0 ||
( (*it)->mData.mX > cell->mData.mX ) ||
( (*it)->mData.mX == cell->mData.mX && (*it)->mData.mY > cell->mData.mY ) )
{
cell = *it;
}
}
}
return 0;
return cell;
}
size_t getSize() const {

@ -246,8 +246,8 @@ namespace MWWorld
if (mEsm[0].getFormat() == 0)
ensureNeededRecords();
mStore.movePlayerRecord();
mStore.setUp();
mStore.movePlayerRecord();
mGlobalVariables = new Globals (mStore);
@ -1603,6 +1603,19 @@ namespace MWWorld
return false;
}
bool
World::isSlowFalling(const MWWorld::Ptr &ptr) const
{
if(!ptr.getClass().isActor())
return false;
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::SlowFall)).mMagnitude > 0)
return true;
return false;
}
bool World::isSubmerged(const MWWorld::Ptr &object) const
{
float *fpos = object.getRefData().getPosition().pos;
@ -1898,6 +1911,16 @@ namespace MWWorld
return mTeleportEnabled;
}
void World::enableLevitation(bool enable)
{
mLevitationEnabled = enable;
}
bool World::isLevitationEnabled() const
{
return mLevitationEnabled;
}
void World::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
{
MWMechanics::NpcStats& npcStats = Class::get(actor).getNpcStats(actor);

@ -129,6 +129,7 @@ namespace MWWorld
int mPlayIntro;
bool mTeleportEnabled;
bool mLevitationEnabled;
public:
@ -368,6 +369,7 @@ namespace MWWorld
virtual void processChangedSettings(const Settings::CategorySettingVector& settings);
virtual bool isFlying(const MWWorld::Ptr &ptr) const;
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const;
///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const;
virtual bool isSwimming(const MWWorld::Ptr &object) const;
@ -451,6 +453,12 @@ namespace MWWorld
/// Returns true if teleport spell effects are allowed.
virtual bool isTeleportingEnabled() const;
/// Enables or disables use of levitation spell effect.
virtual void enableLevitation(bool enable);
/// Returns true if levitation spell effect is allowed.
virtual bool isLevitationEnabled() const;
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf);
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor);

@ -260,6 +260,8 @@ namespace Compiler
extensions.registerInstruction ("sv", "", opcodeShowVars, opcodeShowVarsExplicit);
extensions.registerInstruction("tgm", "", opcodeToggleGodMode);
extensions.registerInstruction("togglegodmode", "", opcodeToggleGodMode);
extensions.registerInstruction ("disablelevitation", "", opcodeDisableLevitation);
extensions.registerInstruction ("enablelevitation", "", opcodeEnableLevitation);
}
}

@ -222,6 +222,8 @@ namespace Compiler
const int opcodeShowVars = 0x200021d;
const int opcodeShowVarsExplicit = 0x200021e;
const int opcodeToggleGodMode = 0x200021f;
const int opcodeDisableLevitation = 0x2000220;
const int opcodeEnableLevitation = 0x2000221;
}
namespace Sky

@ -38,4 +38,9 @@ void Dialogue::save(ESMWriter &esm) const
}
}
void Dialogue::blank()
{
mInfo.clear();
}
}

@ -37,6 +37,9 @@ struct Dialogue
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank();
///< Set record to default state (does not touch the ID and does not change the type).
};
}
#endif

@ -272,5 +272,23 @@ short MagicEffect::effectStringToId(const std::string &effect)
return name->first;
}
MagicEffect::MagnitudeDisplayType MagicEffect::getMagnitudeDisplayType() const {
if ( mData.mFlags & NoMagnitude )
return MDT_None;
if ( mIndex == 84 )
return MDT_TimesInt;
if ( mIndex == 59 ||
( mIndex >= 64 && mIndex <= 66) )
return MDT_Feet;
if ( mIndex == 118 || mIndex == 119 )
return MDT_Level;
if ( ( mIndex >= 28 && mIndex <= 36 )
|| ( mIndex >= 90 && mIndex <= 99 )
|| mIndex == 40 || mIndex == 47
|| mIndex == 57 || mIndex == 68 )
return MDT_Percentage;
return MDT_Points;
}
}

@ -34,6 +34,15 @@ struct MagicEffect
Negative = 0x0800 // A harmful effect. Will determine whether
// eg. NPCs regard this spell as an attack. (same as 0x10?)
};
enum MagnitudeDisplayType
{
MDT_None,
MDT_Feet,
MDT_Level,
MDT_Percentage,
MDT_Points,
MDT_TimesInt
};
struct MEDTstruct
{
@ -49,6 +58,7 @@ struct MagicEffect
static const std::string &effectIdToString(short effectID);
static short effectStringToId(const std::string &effect);
MagnitudeDisplayType getMagnitudeDisplayType() const;
MEDTstruct mData;

@ -425,7 +425,7 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
Ogre::Matrix4 Node::getLocalTransform() const
{
Ogre::Matrix4 mat4(Ogre::Matrix4::IDENTITY);
Ogre::Matrix4 mat4 = Ogre::Matrix4(Ogre::Matrix4::IDENTITY);
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
return mat4;
}

@ -12,6 +12,7 @@ Marc Zinnschlag (Zini) - Lead Programmer/Project Manager
Adam Hogan (aurix)
Aleksandar Jovanov
Alex Haddad (rainChu)
Alex McKibben (WeirdSexy)
Alexander Nadeau (wareya)
Alexander Olofsson (Ace)
@ -62,6 +63,7 @@ Roman Proskuryakov (humbug)
Sandy Carter (bwrsandman)
Sebastian Wick (swick)
Sergey Shambir
sir_herrbatka
Sylvain Thesnieres (Garvek)
Tom Mason (wheybags)
Torben Leif Carrington (TorbenC)

@ -30,9 +30,6 @@ namespace SFO
InputWrapper::~InputWrapper()
{
if(mSDLWindow != NULL)
SDL_DestroyWindow(mSDLWindow);
mSDLWindow = NULL;
}
void InputWrapper::capture(bool windowEventsOnly)

@ -9,6 +9,7 @@
<!-- Log window -->
<Widget type="EditBox" skin="MW_ConsoleLog" position="5 5 380 328" align="Stretch" name="list_History">
<Property key="MultiLine" value="1"/>
<Property key="ReadOnly" value="true"/>
</Widget>
<!-- Command line -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 615 B

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save