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 ## make
*~
Doxygen
prebuilt
apps/openmw/config.hpp
Docs/mainpage.hpp
CMakeFiles CMakeFiles
*/CMakeFiles */CMakeFiles
CMakeCache.txt CMakeCache.txt
moc_*.cxx
cmake_install.cmake cmake_install.cmake
*.[ao] CMakeLists.txt.user
Makefile Makefile
makefile makefile
data build
prebuilt
## doxygen
Doxygen
## ides/editors
*~
*.kdev4 *.kdev4
CMakeLists.txt.user
*.swp *.swp
*.swo *.swo
*.kate-swp *.kate-swp
.cproject .cproject
.project .project
.settings/ .settings
.directory .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"); 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) void bloodmoon_fix_ini(std::string& ini, const bfs::path inxPath)
{ {
std::string inx = read_to_string(inxPath); std::string inx = read_to_string(inxPath);
@ -88,95 +90,94 @@ namespace
ini.erase(start, end-start); ini.erase(start, end-start);
std::string category; std::string category;
std::string setting;
category = "General"; category = "General";
{ {
setting = "Werewolf FOV"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Werewolf FOV");
} }
category = "Moons"; category = "Moons";
{ {
setting = "Script Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Script Color");
} }
category = "Weather"; category = "Weather";
{ {
setting = "Snow Ripples"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Ripples");
setting = "Snow Ripple Radius"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Ripple Radius");
setting = "Snow Ripples Per Flake"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Ripples Per Flake");
setting = "Snow Ripple Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Ripple Scale");
setting = "Snow Ripple Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Ripple Speed");
setting = "Snow Gravity Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Gravity Scale");
setting = "Snow High Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow High Kill");
setting = "Snow Low Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Low Kill");
} }
category = "Weather Blight"; 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"; category = "Weather Snow";
{ {
setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Sunrise Color");
setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Day Color");
setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Sunset Color");
setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Night Color");
setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Sunrise Color");
setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Day Color");
setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Sunset Color");
setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Night Color");
setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Sunrise Color");
setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Day Color");
setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Sunset Color");
setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Night Color");
setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Sunrise Color");
setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Day Color");
setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Sunset Color");
setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Night Color");
setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Disc Sunset Color");
setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Transition Delta");
setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Land Fog Day Depth");
setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Land Fog Night Depth");
setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Clouds Maximum Percent");
setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Wind Speed");
setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Cloud Speed");
setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Glare View");
setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Cloud Texture");
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Loop Sound ID");
setting = "Snow Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Threshold");
setting = "Snow Diameter"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Diameter");
setting = "Snow Height Min"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Height Min");
setting = "Snow Height Max"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Height Max");
setting = "Snow Entrance Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Snow Entrance Speed");
setting = "Max Snowflakes"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Max Snowflakes");
} }
category = "Weather Blizzard"; category = "Weather Blizzard";
{ {
setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Sunrise Color");
setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Day Color");
setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Sunset Color");
setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sky Night Color");
setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Sunrise Color");
setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Day Color");
setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Sunset Color");
setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Fog Night Color");
setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Sunrise Color");
setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Day Color");
setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Sunset Color");
setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Night Color");
setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Sunrise Color");
setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Day Color");
setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Sunset Color");
setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Night Color");
setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Sun Disc Sunset Color");
setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Transition Delta");
setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Land Fog Day Depth");
setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Land Fog Night Depth");
setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Clouds Maximum Percent");
setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Wind Speed");
setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Cloud Speed");
setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Glare View");
setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Cloud Texture");
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Ambient Loop Sound ID");
setting = "Storm Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini); FIX("Storm Threshold");
} }
} }
@ -268,6 +269,27 @@ namespace
strptime(time, "%d %B %Y", &tms); strptime(time, "%d %B %Y", &tms);
return mktime(&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) bool UnshieldThread::SetMorrowindPath(const std::string& path)
@ -365,6 +387,8 @@ bool UnshieldThread::extract()
installToPath(dFilesDir, outputDataFilesDir); installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(mwExtractPath, outputDataFilesDir);
// Videos are often kept uncompressed on the cd // Videos are often kept uncompressed on the cd
bfs::path videosPath = findFile(mMorrowindPath.parent_path(), "video", false); bfs::path videosPath = findFile(mMorrowindPath.parent_path(), "video", false);
if(videosPath.string() != "") if(videosPath.string() != "")
@ -399,6 +423,8 @@ bool UnshieldThread::extract()
installToPath(dFilesDir, outputDataFilesDir); installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(tbExtractPath, outputDataFilesDir);
// Mt GOTY CD has Sounds in a seperate folder from the rest of the data files // Mt GOTY CD has Sounds in a seperate folder from the rest of the data files
bfs::path soundsPath = findFile(tbExtractPath, "sounds", false); bfs::path soundsPath = findFile(tbExtractPath, "sounds", false);
if(soundsPath.string() != "") if(soundsPath.string() != "")
@ -426,6 +452,8 @@ bool UnshieldThread::extract()
bfs::path dFilesDir = findFile(bmExtractPath, "bloodmoon.esm").parent_path(); bfs::path dFilesDir = findFile(bmExtractPath, "bloodmoon.esm").parent_path();
installToPath(dFilesDir, outputDataFilesDir); installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(bmExtractPath, outputDataFilesDir);
// My GOTY CD contains a folder within cab files called Tribunal patch, // My GOTY CD contains a folder within cab files called Tribunal patch,
// which contains Tribunal.esm // which contains Tribunal.esm

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

@ -2144,6 +2144,79 @@ void CSMDoc::Document::createBase()
getData().getSkills().add (record); 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, CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,

@ -34,7 +34,7 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
{ {
string = data.toString(); 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))) CSMWorld::Columns::hasEnums (static_cast<CSMWorld::Columns::ColumnId> (mColumnId)))
{ {
int value = data.toInt(); int value = data.toInt();
@ -47,8 +47,10 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
} }
else if (data.type()==QVariant::Bool) 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 else
return false; 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); const std::map<int, int>::const_iterator iter = columns.find (mColumnId);
if (iter==columns.end()) 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) if (iter->second==-1)
return true; return true;
@ -27,7 +27,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
QVariant data = table.data (index); QVariant data = table.data (index);
if (data.type()!=QVariant::Double && data.type()!=QVariant::Bool && data.type()!=QVariant::Int && 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; return false;
double value = data.toDouble(); 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)) << CSMWorld::Columns::getName (static_cast<CSMWorld::Columns::ColumnId> (mColumnId))
<< "\""; << "\"";
stream << ", \""; stream << ", ";
if (mLower==mUpper && mLowerType!=Type_Infinite && mUpperType!=Type_Infinite) if (mLower==mUpper && mLowerType!=Type_Infinite && mUpperType!=Type_Infinite)
stream << mLower; stream << mLower;

@ -19,7 +19,12 @@ int CSMTools::BirthsignCheckStage::setup()
void CSMTools::BirthsignCheckStage::perform (int stage, std::vector<std::string>& messages) 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); 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) 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); 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) 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); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Faction, faction.mId);

@ -9,7 +9,12 @@
void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector<std::string>& messages) 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); 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) 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); 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) 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); 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) 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); 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) 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); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Spell, spell.mId);

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

@ -1246,6 +1246,108 @@ namespace CSMWorld
return false; 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 #endif

@ -51,7 +51,7 @@ namespace CSMWorld
{ ColumnId_FactionIndex, "Faction Index" }, { ColumnId_FactionIndex, "Faction Index" },
{ ColumnId_Charges, "Charges" }, { ColumnId_Charges, "Charges" },
{ ColumnId_Enchantment, "Enchantment" }, { ColumnId_Enchantment, "Enchantment" },
{ ColumnId_Value, "Coin Value" }, { ColumnId_CoinValue, "Coin Value" },
{ ColumnId_Teleport, "Teleport" }, { ColumnId_Teleport, "Teleport" },
{ ColumnId_TeleportCell, "Teleport Cell" }, { ColumnId_TeleportCell, "Teleport Cell" },
{ ColumnId_LockLevel, "Lock Level" }, { ColumnId_LockLevel, "Lock Level" },
@ -147,6 +147,19 @@ namespace CSMWorld
{ ColumnId_Magical, "Magical" }, { ColumnId_Magical, "Magical" },
{ ColumnId_Silver, "Silver" }, { ColumnId_Silver, "Silver" },
{ ColumnId_Filter, "Filter" }, { 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_Scope, "Scope", },
{ ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue1, "Use value 1" },
@ -258,6 +271,11 @@ namespace
"unknown", "none", "short", "integer", "long", "float", "string", 0 "unknown", "none", "short", "integer", "long", "float", "string", 0
}; };
static const char *sDialogueTypeEnums[] =
{
"Topic", "Voice", "Greeting", "Persuasion", 0
};
const char **getEnumNames (CSMWorld::Columns::ColumnId column) const char **getEnumNames (CSMWorld::Columns::ColumnId column)
{ {
switch (column) switch (column)
@ -272,6 +290,7 @@ namespace
case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes; case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes;
case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums; case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums;
case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums; case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums;
case CSMWorld::Columns::ColumnId_DialogueType: return sDialogueTypeEnums;
default: return 0; default: return 0;
} }

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

@ -9,6 +9,7 @@
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
#include <components/esm/loadglob.hpp> #include <components/esm/loadglob.hpp>
#include <components/esm/cellref.hpp>
#include "idtable.hpp" #include "idtable.hpp"
#include "columnimp.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_StarterSpell, 0x2));
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AlwaysSucceeds, 0x4)); 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 StringIdColumn<Cell>);
mCells.addColumn (new RecordStateColumn<Cell>); mCells.addColumn (new RecordStateColumn<Cell>);
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_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 RecordStateColumn<CellRef>);
mRefs.addColumn (new CellColumn<CellRef>); mRefs.addColumn (new CellColumn<CellRef>);
mRefs.addColumn (new IdColumn<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 ScaleColumn<CellRef>);
mRefs.addColumn (new OwnerColumn<CellRef>); mRefs.addColumn (new OwnerColumn<CellRef>);
mRefs.addColumn (new SoulColumn<CellRef>); mRefs.addColumn (new SoulColumn<CellRef>);
@ -174,6 +189,12 @@ CSMWorld::Data::Data() : mRefs (mCells)
mRefs.addColumn (new GoldValueColumn<CellRef>); mRefs.addColumn (new GoldValueColumn<CellRef>);
mRefs.addColumn (new TeleportColumn<CellRef>); mRefs.addColumn (new TeleportColumn<CellRef>);
mRefs.addColumn (new TeleportCellColumn<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 LockLevelColumn<CellRef>);
mRefs.addColumn (new KeyColumn<CellRef>); mRefs.addColumn (new KeyColumn<CellRef>);
mRefs.addColumn (new TrapColumn<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 (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign); addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell); 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 (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables, addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable); UniversalId::Type_Referenceable);
@ -318,6 +341,28 @@ CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells()
return mSpells; 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 const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
{ {
return mCells; 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_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); 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: case ESM::REC_FILT:
if (project) if (project)
@ -484,6 +564,8 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getRegions().searchId (id)!=-1 || getRegions().searchId (id)!=-1 ||
getBirthsigns().searchId (id)!=-1 || getBirthsigns().searchId (id)!=-1 ||
getSpells().searchId (id)!=-1 || getSpells().searchId (id)!=-1 ||
getTopics().searchId (id)!=-1 ||
getJournals().searchId (id)!=-1 ||
getCells().searchId (id)!=-1 || getCells().searchId (id)!=-1 ||
getReferenceables().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, mRegions, listDeleted);
appendIds (ids, mBirthsigns, listDeleted); appendIds (ids, mBirthsigns, listDeleted);
appendIds (ids, mSpells, listDeleted); appendIds (ids, mSpells, listDeleted);
appendIds (ids, mTopics, listDeleted);
appendIds (ids, mJournals, listDeleted);
appendIds (ids, mCells, listDeleted); appendIds (ids, mCells, listDeleted);
appendIds (ids, mReferenceables, listDeleted); appendIds (ids, mReferenceables, listDeleted);

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

@ -7,21 +7,24 @@
namespace CSMWorld namespace CSMWorld
{ {
/// \brief Single type collection of top level records /// \brief Single type collection of top level records
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> > template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
class IdCollection : public Collection<ESXRecordT, IdAccessorT> class IdCollection : public Collection<ESXRecordT, IdAccessorT>
{ {
public: public:
void load (ESM::ESMReader& reader, bool base, 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 (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> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base, void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
UniversalId::Type type)
{ {
std::string id = reader.getHNOString ("NAME"); std::string id = reader.getHNOString ("NAME");
@ -56,30 +59,62 @@ namespace CSMWorld
IdAccessorT().getId (record) = id; IdAccessorT().getId (record) = id;
record.load (reader); record.load (reader);
int index = this->searchId (IdAccessorT().getId (record)); load (record, base);
}
}
if (index==-1) template<typename ESXRecordT, typename IdAccessorT>
{ void IdCollection<ESXRecordT, IdAccessorT>::load (const ESXRecordT& record, bool base)
// new record {
Record<ESXRecordT> record2; int index = this->searchId (IdAccessorT().getId (record));
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
(base ? record2.mBase : record2.mModified) = 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 else
{ record2.setModified (record);
// old record
Record<ESXRecordT> record2 = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
if (base) this->setRecord (index, record2);
record2.mBase = record; }
else }
record2.setModified (record);
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_Regions, "Regions", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 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_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_Cells, "Cells", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
"Referenceables", 0 }, "Referenceables", 0 },
@ -43,18 +45,20 @@ namespace
static const TypeData sIdArg[] = static const TypeData sIdArg[] =
{ {
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", ":./globvar.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":./GMST.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":./skill.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":./class.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":./faction.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":./race.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":./sound.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":./script.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", 0 }, { 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_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_Activator, "Activator", ":./activator.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.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_Static, "Static", ":./static.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.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_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 { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };
static const TypeData sIndexArg[] = static const TypeData sIndexArg[] =
{ {
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, { 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 { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };

@ -86,10 +86,15 @@ namespace CSMWorld
Type_Reference, Type_Reference,
Type_RegionMap, Type_RegionMap,
Type_Filter, 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: 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()) if (path.parent_path().string()==mLocalData.string())
{ {
// path already points to the local data directory // 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; mResultPath = path;
mValid = true; 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 points somewhere else or is a leaf name.
path = mLocalData / path.filename(); 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; mResultPath = path;
mValid = true; mValid = true;

@ -115,6 +115,10 @@ void CSVDoc::View::setupWorldMenu()
world->addSeparator(); // items that don't represent single record lists follow here 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); QAction *regionMap = new QAction (tr ("Region Map"), this);
connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView())); connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView()));
world->addAction (regionMap); world->addAction (regionMap);
@ -159,6 +163,14 @@ void CSVDoc::View::setupMechanicsMenu()
QAction *spells = new QAction (tr ("Spells"), this); QAction *spells = new QAction (tr ("Spells"), this);
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView())); connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
mechanics->addAction (spells); 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() void CSVDoc::View::setupAssetsMenu()
@ -403,6 +415,21 @@ void CSVDoc::View::addFiltersSubView()
addSubView (CSMWorld::UniversalId::Type_Filters); 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) void CSVDoc::View::abortOperation (int type)
{ {
mDocument->abortOperation (type); mDocument->abortOperation (type);

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

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

@ -6,6 +6,8 @@
#include "../../model/tools/reportmodel.hpp" #include "../../model/tools/reportmodel.hpp"
#include "../../view/world/idtypedelegate.hpp"
CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: CSVDoc::SubView (id), mModel (document.getReport (id)) : CSVDoc::SubView (id), mModel (document.getReport (id))
{ {
@ -18,6 +20,11 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc:
mTable->setSelectionBehavior (QAbstractItemView::SelectRows); mTable->setSelectionBehavior (QAbstractItemView::SelectRows);
mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); 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&))); 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. // 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) void CSVTools::ReportSubView::show (const QModelIndex& index)
{ {
focusId (mModel->getUniversalId (index.row())); focusId (mModel->getUniversalId (index.row()));

@ -16,6 +16,11 @@ namespace CSMTools
class ReportModel; class ReportModel;
} }
namespace CSVWorld
{
class CommandDelegate;
}
namespace CSVTools namespace CSVTools
{ {
class Table; class Table;
@ -26,6 +31,7 @@ namespace CSVTools
CSMTools::ReportModel *mModel; CSMTools::ReportModel *mModel;
QTableView *mTable; QTableView *mTable;
CSVWorld::CommandDelegate *mIdTypeDelegate;
public: public:
@ -33,6 +39,8 @@ namespace CSVTools
virtual void setEditLock (bool locked); virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString&, const QString&);
private slots: private slots:
void show (const QModelIndex& index); 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 #ifndef IDTYPEDELEGATE_HPP
#define REFIDTYPEDELEGATE_HPP #define IDTYPEDELEGATE_HPP
#include "enumdelegate.hpp" #include "enumdelegate.hpp"
#include "util.hpp" #include "util.hpp"
@ -8,29 +8,23 @@
namespace CSVWorld namespace CSVWorld
{ {
class RefIdTypeDelegate : public DataDisplayDelegate class IdTypeDelegate : public DataDisplayDelegate
{ {
public: 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); 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: public:
RefIdTypeDelegateFactory();
IdTypeDelegateFactory();
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller. ///< 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 "cellcreator.hpp"
#include "referenceablecreator.hpp" #include "referenceablecreator.hpp"
#include "referencecreator.hpp" #include "referencecreator.hpp"
#include "scenesubview.hpp"
#include "dialoguecreator.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{ {
@ -52,6 +54,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_References, manager.add (CSMWorld::UniversalId::Type_References,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >); 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 // Subviews for editing/viewing individual records
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>); manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
@ -62,4 +70,5 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
new CSVDoc::SubViewFactoryWithCreator<TableSubView, new CSVDoc::SubViewFactoryWithCreator<TableSubView,
CreatorFactory<CSVFilter::FilterCreator> >); 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/idtableproxymodel.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/record.hpp" #include "../../model/world/record.hpp"
#include "recordstatusdelegate.hpp" #include "recordstatusdelegate.hpp"
#include "refidtypedelegate.hpp"
#include "util.hpp" #include "util.hpp"
void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) 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)); QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
// check record state
CSMWorld::RecordBase::State state = CSMWorld::RecordBase::State state =
static_cast<CSMWorld::RecordBase::State> ( static_cast<CSMWorld::RecordBase::State> (
mModel->data (mModel->index (index.row(), 1)).toInt()); mModel->data (mModel->index (index.row(), 1)).toInt());
if (state!=CSMWorld::RecordBase::State_Deleted) if (state==CSMWorld::RecordBase::State_Deleted)
{ continue;
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
std::string id = mModel->data (mModel->index (index.row(), columnIndex)). // check other columns (only relevant for a subset of the tables)
toString().toUtf8().constData(); 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("/"), mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding); mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding);
mEnvironment.setWindowManager (window); mEnvironment.setWindowManager (window);
if (mNewGame)
mEnvironment.getWindowManager()->setNewGame(true);
// Create the world // Create the world
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles, mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles,
@ -390,6 +388,10 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
input->setPlayer(&mEnvironment.getWorld()->getPlayer()); input->setPlayer(&mEnvironment.getWorld()->getPlayer());
window->initUI(); window->initUI();
if (mNewGame)
// still redundant work here: recreate CharacterCreation(),
// double update visibility etc.
window->setNewGame(true);
window->renderWorldMap(); window->renderWorldMap();
//Load translation data //Load translation data

@ -324,6 +324,7 @@ namespace MWBase
virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0; virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0;
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 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; virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
///Is the head of the creature underwater? ///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0; virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
@ -389,6 +390,12 @@ namespace MWBase
/// Returns true if teleport spell effects are allowed. /// Returns true if teleport spell effects are allowed.
virtual bool isTeleportingEnabled() const = 0; 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. /// Turn actor into werewolf or normal form.
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0; virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0;

@ -16,12 +16,34 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/customdata.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.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 namespace MWClass
{ {
void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
@ -182,6 +204,21 @@ namespace MWClass
return action; 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 MWWorld::Ptr
Light::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const Light::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
{ {
@ -191,6 +228,12 @@ namespace MWClass
return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell); 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 bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const
{ {
return npcServices & ESM::NPC::Lights; return npcServices & ESM::NPC::Lights;

@ -10,6 +10,8 @@ namespace MWClass
virtual MWWorld::Ptr virtual MWWorld::Ptr
copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const;
void ensureCustomData (const MWWorld::Ptr& ptr) const;
public: public:
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
@ -56,6 +58,12 @@ namespace MWClass
const; const;
///< Generate action for using via inventory menu ///< 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 std::string getModel(const MWWorld::Ptr &ptr) const;
virtual float getWeight (const MWWorld::Ptr& ptr) const; virtual float getWeight (const MWWorld::Ptr& ptr) const;

@ -7,6 +7,7 @@
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadnpc.hpp> #include <components/esm/loadnpc.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -396,9 +397,10 @@ namespace MWClass
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f); 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())), if (!MWBase::Environment::get().getWorld()->getGodModeState())
weapon.getCellRef().mCharge); weapon.getCellRef().mCharge -= std::min(std::max(1,
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
} }
healthdmg = true; healthdmg = true;
} }
@ -769,6 +771,37 @@ namespace MWClass
return x; 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 MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
{ {
ensureCustomData (ptr); ensureCustomData (ptr);

@ -97,6 +97,9 @@ namespace MWClass
virtual float getJump(const MWWorld::Ptr &ptr) const; virtual float getJump(const MWWorld::Ptr &ptr) const;
///< Return jump velocity (not accounting for movement) ///< 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; virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement. ///< Return desired movement.

@ -23,6 +23,7 @@ namespace MWGui
, mLastWallpaperChangeTime(0.f) , mLastWallpaperChangeTime(0.f)
, mFirstLoad(true) , mFirstLoad(true)
, mProgress(0) , mProgress(0)
, mVSyncWasEnabled(false)
{ {
getWidget(mLoadingText, "LoadingText"); getWidget(mLoadingText, "LoadingText");
getWidget(mProgressBar, "ProgressBar"); getWidget(mProgressBar, "ProgressBar");
@ -67,6 +68,14 @@ namespace MWGui
void LoadingScreen::loadingOn() 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); setVisible(true);
if (mFirstLoad) if (mFirstLoad)
@ -83,6 +92,12 @@ namespace MWGui
void LoadingScreen::loadingOff() 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); setVisible(false);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
@ -212,7 +227,8 @@ namespace MWGui
// caused a sync / flush and would be expensive). // 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. // 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. // 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); mWindow->update(false);
if (!hasCompositor) if (!hasCompositor)

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

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

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

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

@ -363,8 +363,12 @@ namespace MWGui
else if (_sender == mVSyncButton) else if (_sender == mVSyncButton)
{ {
Settings::Manager::setBool("vsync", "Video", newState); 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()-> MWBase::Environment::get().getWindowManager()->
messageBox("VSync will be applied after a restart", std::vector<std::string>()); messageBox("VSync will be applied after a restart", std::vector<std::string>());
#endif
apply();
} }
else else
{ {

@ -2,6 +2,9 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <sstream>
#include <iomanip>
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -169,13 +172,34 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->getGameSettingString( MWBase::Environment::get().getWindowManager()->getGameSettingString(
ESM::Attribute::sGmstAttributeIds[effectIt->mKey.mArg], "") + ")"; 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 += ": " + 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 <boost/lexical_cast.hpp>
#include <sstream>
#include <iomanip>
#include <MyGUI_ProgressBar.h> #include <MyGUI_ProgressBar.h>
#include <MyGUI_ImageBox.h> #include <MyGUI_ImageBox.h>
#include <MyGUI_ControllerManager.h> #include <MyGUI_ControllerManager.h>
@ -405,6 +408,10 @@ namespace MWGui
std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", ""); std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "");
std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", ""); 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 to = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "") + " ";
std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", ""); std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", "");
std::string secs = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", ""); 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], ""); 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 >= 0 || mEffectParams.mMagnMax >= 0) {
{ ESM::MagicEffect::MagnitudeDisplayType displayType = magicEffect->getMagnitudeDisplayType();
if (mEffectParams.mMagnMin == mEffectParams.mMagnMax) if ( displayType == ESM::MagicEffect::MDT_TimesInt ) {
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts); std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", "");
else std::stringstream formatter;
{
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + to + boost::lexical_cast<std::string>(mEffectParams.mMagnMax) + " " + pts; 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 Compiler::Extensions& extensions, int fpsLevel, OEngine::Render::OgreRenderer *ogre,
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
Translation::Storage& translationDataStorage, ToUTF8::FromType encoding) Translation::Storage& translationDataStorage, ToUTF8::FromType encoding)
: mGuiManager(NULL) : mConsoleOnlyScripts(consoleOnlyScripts)
, mConsoleOnlyScripts(consoleOnlyScripts) , mGuiManager(NULL)
, mRendering(ogre) , mRendering(ogre)
, mHud(NULL) , mHud(NULL)
, mMap(NULL) , mMap(NULL)
, mMenu(NULL) , mMenu(NULL)
, mStatsWindow(NULL)
, mToolTips(NULL) , mToolTips(NULL)
, mStatsWindow(NULL)
, mMessageBoxManager(NULL) , mMessageBoxManager(NULL)
, mConsole(NULL) , mConsole(NULL)
, mJournal(NULL) , mJournal(NULL)
, mDialogueWindow(NULL) , mDialogueWindow(NULL)
, mBookWindow(NULL) , mContainerWindow(NULL)
, mDragAndDrop(NULL)
, mInventoryWindow(NULL)
, mScrollWindow(NULL) , mScrollWindow(NULL)
, mBookWindow(NULL)
, mCountDialog(NULL) , mCountDialog(NULL)
, mTradeWindow(NULL) , mTradeWindow(NULL)
, mSpellBuyingWindow(NULL) , mSpellBuyingWindow(NULL)
@ -83,27 +86,37 @@ namespace MWGui
, mConfirmationDialog(NULL) , mConfirmationDialog(NULL)
, mAlchemyWindow(NULL) , mAlchemyWindow(NULL)
, mSpellWindow(NULL) , mSpellWindow(NULL)
, mQuickKeysMenu(NULL)
, mLoadingScreen(NULL) , mLoadingScreen(NULL)
, mCharGen(NULL)
, mLevelupDialog(NULL) , mLevelupDialog(NULL)
, mWaitDialog(NULL) , mWaitDialog(NULL)
, mSpellCreationDialog(NULL) , mSpellCreationDialog(NULL)
, mEnchantingDialog(NULL) , mEnchantingDialog(NULL)
, mTrainingWindow(NULL) , mTrainingWindow(NULL)
, mMerchantRepair(NULL) , mMerchantRepair(NULL)
, mRepair(NULL)
, mSoulgemDialog(NULL) , mSoulgemDialog(NULL)
, mRepair(NULL)
, mCompanionWindow(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() , mPlayerName()
, mPlayerRaceId() , mPlayerRaceId()
, mPlayerAttributes() , mPlayerAttributes()
, mPlayerMajorSkills()
, mPlayerMinorSkills() , mPlayerMinorSkills()
, mPlayerMajorSkills()
, mPlayerSkillValues() , mPlayerSkillValues()
, mPlayerHealth() , mPlayerHealth()
, mPlayerMagicka() , mPlayerMagicka()
, mPlayerFatigue() , mPlayerFatigue()
, mGui(NULL) , mGui(NULL)
, mGuiModes()
, mCursorManager(NULL)
, mGarbageDialogs() , mGarbageDialogs()
, mShown(GW_ALL) , mShown(GW_ALL)
, mForceHidden(GW_None) , mForceHidden(GW_None)
@ -113,13 +126,7 @@ namespace MWGui
, mFPS(0.0f) , mFPS(0.0f)
, mTriangleCount(0) , mTriangleCount(0)
, mBatchCount(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")) , mUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI"))
, mCursorVisible(true)
{ {
// Set up the GUI system // Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath);

@ -468,6 +468,41 @@ namespace MWInput
bool InputManager::keyPressed( const SDL_KeyboardEvent &arg ) 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); mInputBinder->keyPressed (arg);
if(arg.keysym.sym == SDLK_RETURN if(arg.keysym.sym == SDLK_RETURN
@ -577,8 +612,8 @@ namespace MWInput
rot[0] = -y; rot[0] = -y;
rot[1] = 0.0f; rot[1] = 0.0f;
rot[2] = x; 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)) if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot))
{ {
mPlayer->yaw(x/scale); mPlayer->yaw(x/scale);
@ -617,9 +652,15 @@ namespace MWInput
if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video) if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video)
MWBase::Environment::get().getWorld ()->stopVideo (); MWBase::Environment::get().getWorld ()->stopVideo ();
else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
{
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);
}
else else
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx);
}
} }
void InputManager::toggleSpell() void InputManager::toggleSpell()

@ -31,18 +31,24 @@ namespace MWMechanics
calculateDynamicStats (ptr); calculateDynamicStats (ptr);
calculateCreatureStatModifiers (ptr); calculateCreatureStatModifiers (ptr);
// AI
if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
// AI
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
creatureStats.getAiSequence().execute (ptr); creatureStats.getAiSequence().execute (ptr);
// fatigue restoration
calculateRestoration(ptr, duration);
} }
} }
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused) void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)
{ {
if(!paused) if(!paused)
{
updateDrowning(ptr, duration); updateDrowning(ptr, duration);
updateEquippedLight(ptr, duration);
}
} }
void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) void Actors::adjustMagicEffects (const MWWorld::Ptr& creature)
@ -93,39 +99,29 @@ namespace MWMechanics
void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration) void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration)
{ {
CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); 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) 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(); DynamicStat<float> health = stats.getHealth();
health.setCurrent (health.getCurrent() + 0.1 * endurance); health.setCurrent (health.getCurrent() + 0.1 * endurance);
stats.setHealth (health); 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) if (!stunted)
{ {
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat (); float fRestMagicMult = settings.find("fRestMagicMult")->getFloat ();
DynamicStat<float> magicka = stats.getMagicka(); DynamicStat<float> magicka = stats.getMagicka();
magicka.setCurrent (magicka.getCurrent() magicka.setCurrent (magicka.getCurrent()
@ -133,6 +129,19 @@ namespace MWMechanics
stats.setMagicka (magicka); 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) void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
@ -196,6 +205,49 @@ namespace MWMechanics
stats.setTimeToStartDrowning(20); 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) {} Actors::Actors() : mDuration (0) {}
void Actors::addActor (const MWWorld::Ptr& ptr) 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 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()); MWMechanics::DynamicStat<float> stat(stats.getHealth());

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

@ -767,10 +767,25 @@ void CharacterController::update(float duration)
} }
if(sneak || inwater || flying) if(sneak || inwater || flying)
{
vec.z = 0.0f; vec.z = 0.0f;
mFallHeight = mPtr.getRefData().getPosition().pos[2];
}
if(!onground && !flying && !inwater) 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>(); const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
forcestateupdate = (mJumpState != JumpState_Falling); forcestateupdate = (mJumpState != JumpState_Falling);
@ -794,6 +809,8 @@ void CharacterController::update(float duration)
} }
else if(vec.z > 0.0f && mJumpState == JumpState_None) else if(vec.z > 0.0f && mJumpState == JumpState_None)
{ {
// The player has started a jump.
float z = cls.getJump(mPtr); float z = cls.getJump(mPtr);
if(vec.x == 0 && vec.y == 0) if(vec.x == 0 && vec.y == 0)
vec = Ogre::Vector3(0.0f, 0.0f, z); 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; 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) else if(mJumpState == JumpState_Falling)
{ {
// The player is landing.
forcestateupdate = true; forcestateupdate = true;
mJumpState = JumpState_Landing; mJumpState = JumpState_Landing;
vec.z = 0.0f; 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 else
{ {

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

@ -187,6 +187,12 @@ namespace MWRender
rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); 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() float Camera::getYaw()
{ {
if(mVanity.enabled || mPreviewMode) if(mVanity.enabled || mPreviewMode)

@ -79,6 +79,12 @@ namespace MWRender
void togglePreviewMode(bool enable); 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 bool isFirstPerson() const
{ return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); } { return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); }

@ -84,7 +84,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
mWeapon(inv.end()), mWeapon(inv.end()),
mShield(inv.end()), mShield(inv.end()),
mViewMode(viewMode), mViewMode(viewMode),
mShowWeapons(false) mShowWeapons(false),
mFirstPersonOffset(0.f, 0.f, 0.f)
{ {
mNpc = mPtr.get<ESM::NPC>()->mBase; 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 { class SetObjectGroup {
int mGroup; int mGroup;
@ -448,7 +454,12 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
float pitch = mCamera->getPitch(); float pitch = mCamera->getPitch();
Ogre::Node *node = baseinst->getBone("Bip01 Neck"); Ogre::Node *node = baseinst->getBone("Bip01 Neck");
node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); 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++) 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 mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty
int mPartPriorities[ESM::PRT_Count]; int mPartPriorities[ESM::PRT_Count];
Ogre::Vector3 mFirstPersonOffset;
void updateNpcBase(); void updateNpcBase();
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename); NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename);
@ -89,6 +91,11 @@ public:
void updateParts(bool forceupdate = false); 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. /// Rebuilds the NPC, updating their root model, animation sources, and equipment.
void rebuild(); void rebuild();
}; };

@ -354,6 +354,15 @@ void RenderingManager::update (float duration, bool paused)
mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); 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); mOcclusionQuery->update(duration);
mVideoPlayer->update (); mVideoPlayer->update ();
@ -760,6 +769,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
|| it->second == "resolution y" || it->second == "resolution y"
|| it->second == "fullscreen")) || it->second == "fullscreen"))
changeRes = true; 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") else if (it->second == "field of view" && it->first == "General")
mRendering.setFov(Settings::Manager::getFloat("field of view", "General")); mRendering.setFov(Settings::Manager::getFloat("field of view", "General"));
else if ((it->second == "texture filtering" && it->first == "General") else if ((it->second == "texture filtering" && it->first == "General")

@ -352,5 +352,7 @@ op 0x200021c: SetWerewolfAcrobaticsExplicit
op 0x200021d: ShowVars op 0x200021d: ShowVars
op 0x200021e: ShowVarsExplicit op 0x200021e: ShowVarsExplicit
op 0x200021f: ToggleGodMode 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); 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> template <class R>
class OpShowVars : public Interpreter::Opcode0 class OpShowVars : public Interpreter::Opcode0
@ -789,6 +800,8 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars<ImplicitRef>); interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars<ImplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeShowVarsExplicit, new OpShowVars<ExplicitRef>); interpreter.installSegment5 (Compiler::Misc::opcodeShowVarsExplicit, new OpShowVars<ExplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode); 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"); 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 std::string Class::getScript (const Ptr& ptr) const
{ {
return ""; return "";
@ -167,6 +177,11 @@ namespace MWWorld
throw std::runtime_error ("class does not support enchanting"); 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 MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
{ {
throw std::runtime_error ("movement settings not supported by class"); throw std::runtime_error ("movement settings not supported by class");

@ -156,6 +156,14 @@ namespace MWWorld
virtual void unlock (const Ptr& ptr) const; virtual void unlock (const Ptr& ptr) const;
///< Unlock object (default implementation: throw an exception) ///< 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; virtual std::string getScript (const Ptr& ptr) const;
///< Return name of the script attached to ptr (default implementation: return an empty ///< Return name of the script attached to ptr (default implementation: return an empty
/// string). /// string).
@ -175,6 +183,9 @@ namespace MWWorld
virtual float getJump(const MWWorld::Ptr &ptr) const; virtual float getJump(const MWWorld::Ptr &ptr) const;
///< Return jump velocity (not accounting for movement) ///< 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; virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
///< Return desired movement. ///< Return desired movement.

@ -656,26 +656,38 @@ namespace MWWorld
return iterator(mSharedExt.end()); 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 { const ESM::Cell *searchExtByName(const std::string &id) const {
ESM::Cell *cell = 0;
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin(); std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) { for (; it != mSharedExt.end(); ++it) {
if (Misc::StringUtils::ciEqual((*it)->mName, id)) { 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 { const ESM::Cell *searchExtByRegion(const std::string &id) const {
ESM::Cell *cell = 0;
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin(); std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) { for (; it != mSharedExt.end(); ++it) {
if (Misc::StringUtils::ciEqual((*it)->mRegion, id)) { 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 { size_t getSize() const {

@ -246,8 +246,8 @@ namespace MWWorld
if (mEsm[0].getFormat() == 0) if (mEsm[0].getFormat() == 0)
ensureNeededRecords(); ensureNeededRecords();
mStore.movePlayerRecord();
mStore.setUp(); mStore.setUp();
mStore.movePlayerRecord();
mGlobalVariables = new Globals (mStore); mGlobalVariables = new Globals (mStore);
@ -1603,6 +1603,19 @@ namespace MWWorld
return false; 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 bool World::isSubmerged(const MWWorld::Ptr &object) const
{ {
float *fpos = object.getRefData().getPosition().pos; float *fpos = object.getRefData().getPosition().pos;
@ -1898,6 +1911,16 @@ namespace MWWorld
return mTeleportEnabled; return mTeleportEnabled;
} }
void World::enableLevitation(bool enable)
{
mLevitationEnabled = enable;
}
bool World::isLevitationEnabled() const
{
return mLevitationEnabled;
}
void World::setWerewolf(const MWWorld::Ptr& actor, bool werewolf) void World::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
{ {
MWMechanics::NpcStats& npcStats = Class::get(actor).getNpcStats(actor); MWMechanics::NpcStats& npcStats = Class::get(actor).getNpcStats(actor);

@ -129,6 +129,7 @@ namespace MWWorld
int mPlayIntro; int mPlayIntro;
bool mTeleportEnabled; bool mTeleportEnabled;
bool mLevitationEnabled;
public: public:
@ -368,6 +369,7 @@ namespace MWWorld
virtual void processChangedSettings(const Settings::CategorySettingVector& settings); virtual void processChangedSettings(const Settings::CategorySettingVector& settings);
virtual bool isFlying(const MWWorld::Ptr &ptr) const; virtual bool isFlying(const MWWorld::Ptr &ptr) const;
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const;
///Is the head of the creature underwater? ///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const; virtual bool isSubmerged(const MWWorld::Ptr &object) const;
virtual bool isSwimming(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. /// Returns true if teleport spell effects are allowed.
virtual bool isTeleportingEnabled() const; 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 setWerewolf(const MWWorld::Ptr& actor, bool werewolf);
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor); virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor);

@ -260,6 +260,8 @@ namespace Compiler
extensions.registerInstruction ("sv", "", opcodeShowVars, opcodeShowVarsExplicit); extensions.registerInstruction ("sv", "", opcodeShowVars, opcodeShowVarsExplicit);
extensions.registerInstruction("tgm", "", opcodeToggleGodMode); extensions.registerInstruction("tgm", "", opcodeToggleGodMode);
extensions.registerInstruction("togglegodmode", "", 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 opcodeShowVars = 0x200021d;
const int opcodeShowVarsExplicit = 0x200021e; const int opcodeShowVarsExplicit = 0x200021e;
const int opcodeToggleGodMode = 0x200021f; const int opcodeToggleGodMode = 0x200021f;
const int opcodeDisableLevitation = 0x2000220;
const int opcodeEnableLevitation = 0x2000221;
} }
namespace Sky 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 load(ESMReader &esm);
void save(ESMWriter &esm) const; void save(ESMWriter &esm) const;
void blank();
///< Set record to default state (does not touch the ID and does not change the type).
}; };
} }
#endif #endif

@ -272,5 +272,23 @@ short MagicEffect::effectStringToId(const std::string &effect)
return name->first; 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 Negative = 0x0800 // A harmful effect. Will determine whether
// eg. NPCs regard this spell as an attack. (same as 0x10?) // 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 struct MEDTstruct
{ {
@ -49,6 +58,7 @@ struct MagicEffect
static const std::string &effectIdToString(short effectID); static const std::string &effectIdToString(short effectID);
static short effectStringToId(const std::string &effect); static short effectStringToId(const std::string &effect);
MagnitudeDisplayType getMagnitudeDisplayType() const;
MEDTstruct mData; MEDTstruct mData;

@ -425,7 +425,7 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
Ogre::Matrix4 Node::getLocalTransform() const 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)); mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
return mat4; return mat4;
} }

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

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

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