Merge remote-tracking branch 'upstream/master' into osx-ogre-19

actorid
Nikolay Kasyanov 11 years ago
commit 3993c34739

@ -167,6 +167,7 @@ if(USE_SYSTEM_TINYXML)
find_library(TINYXML_LIBRARIES tinyxml) find_library(TINYXML_LIBRARIES tinyxml)
find_path(TINYXML_INCLUDE_DIR tinyxml.h) find_path(TINYXML_INCLUDE_DIR tinyxml.h)
message(STATUS "Found TinyXML: ${TINYXML_LIBRARIES} ${TINYXML_INCLUDE_DIR}") message(STATUS "Found TinyXML: ${TINYXML_LIBRARIES} ${TINYXML_INCLUDE_DIR}")
add_definitions (-DTIXML_USE_STL)
if(TINYXML_LIBRARIES AND TINYXML_INCLUDE_DIR) if(TINYXML_LIBRARIES AND TINYXML_INCLUDE_DIR)
include_directories(${TINYXML_INCLUDE_DIR}) include_directories(${TINYXML_INCLUDE_DIR})
message(STATUS "Using system TinyXML library.") message(STATUS "Using system TinyXML library.")

@ -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

@ -18,12 +18,12 @@ opencs_hdrs_noqt (model/doc
opencs_units (model/world opencs_units (model/world
idtable idtableproxymodel regionmap idtable idtableproxymodel regionmap data
) )
opencs_units_noqt (model/world opencs_units_noqt (model/world
universalid data record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns refidadapter refiddata refidadapterimp ref collectionbase refcollection columns
) )
@ -59,12 +59,13 @@ 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
) )

@ -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);

@ -107,6 +107,11 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const; virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
void addColumn (Column<ESXRecordT> *column); void addColumn (Column<ESXRecordT> *column);
void setRecord (int index, const Record<ESXRecordT>& record); void setRecord (int index, const Record<ESXRecordT>& record);
@ -293,6 +298,21 @@ namespace CSMWorld
return static_cast<int> (mRecords.size()); return static_cast<int> (mRecords.size());
} }
template<typename ESXRecordT, typename IdAccessorT>
std::vector<std::string> Collection<ESXRecordT, IdAccessorT>::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
for (typename std::map<std::string, int>::const_iterator iter = mIndex.begin();
iter!=mIndex.end(); ++iter)
{
if (listDeleted || !mRecords[iter->second].isDeleted())
ids.push_back (IdAccessorT().getId (mRecords[iter->second].get()));
}
return ids;
}
template<typename ESXRecordT, typename IdAccessorT> template<typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord (const std::string& id) const const Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord (const std::string& id) const
{ {

@ -78,8 +78,12 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const = 0; virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const = 0;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
};
virtual std::vector<std::string> getIds (bool listDeleted = true) const = 0;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
};
} }
#endif #endif

@ -1216,6 +1216,74 @@ namespace CSMWorld
return true; return true;
} }
}; };
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;
}
};
} }
#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,18 @@ 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_UseValue1, "Use value 1" }, { ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue2, "Use value 2" },

@ -45,101 +45,113 @@ 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_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,
// 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.

@ -2,12 +2,14 @@
#include "data.hpp" #include "data.hpp"
#include <stdexcept> #include <stdexcept>
#include <algorithm>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#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"
@ -15,13 +17,31 @@
#include "columns.hpp" #include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1, void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2) UniversalId::Type type2, bool update)
{ {
mModels.push_back (model); mModels.push_back (model);
mModelIndex.insert (std::make_pair (type1, model)); mModelIndex.insert (std::make_pair (type1, model));
if (type2!=UniversalId::Type_None) if (type2!=UniversalId::Type_None)
mModelIndex.insert (std::make_pair (type2, model)); mModelIndex.insert (std::make_pair (type2, model));
if (update)
{
connect (model, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (dataChanged (const QModelIndex&, const QModelIndex&)));
connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (rowsChanged (const QModelIndex&, int, int)));
connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (rowsChanged (const QModelIndex&, int, int)));
}
}
void CSMWorld::Data::appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted)
{
std::vector<std::string> ids2 = collection.getIds (listDeleted);
ids.insert (ids.end(), ids2.begin(), ids2.end());
} }
CSMWorld::Data::Data() : mRefs (mCells) CSMWorld::Data::Data() : mRefs (mCells)
@ -134,6 +154,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>);
@ -144,6 +170,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>);
@ -155,7 +187,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill); addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false);
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction);
addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race);
@ -167,8 +199,8 @@ CSMWorld::Data::Data() : mRefs (mCells)
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);
addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference); addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter); addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
} }
CSMWorld::Data::~Data() CSMWorld::Data::~Data()
@ -341,7 +373,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{ {
RegionMap *table = 0; RegionMap *table = 0;
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap,
UniversalId::Type_None); UniversalId::Type_None, false);
return table; return table;
} }
throw std::logic_error ("No table model available for " + id.toString()); throw std::logic_error ("No table model available for " + id.toString());
@ -440,3 +472,36 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getCells().searchId (id)!=-1 || getCells().searchId (id)!=-1 ||
getReferenceables().searchId (id)!=-1; getReferenceables().searchId (id)!=-1;
} }
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
appendIds (ids, mGlobals, listDeleted);
appendIds (ids, mGmsts, listDeleted);
appendIds (ids, mClasses, listDeleted);
appendIds (ids, mFactions, listDeleted);
appendIds (ids, mRaces, listDeleted);
appendIds (ids, mSounds, listDeleted);
appendIds (ids, mScripts, listDeleted);
appendIds (ids, mRegions, listDeleted);
appendIds (ids, mBirthsigns, listDeleted);
appendIds (ids, mSpells, listDeleted);
appendIds (ids, mCells, listDeleted);
appendIds (ids, mReferenceables, listDeleted);
std::sort (ids.begin(), ids.end());
return ids;
}
void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
if (topLeft.column()<=0)
emit idListChanged();
}
void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
{
emit idListChanged();
}

@ -6,6 +6,9 @@
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <QObject>
#include <QModelIndex>
#include <components/esm/loadglob.hpp> #include <components/esm/loadglob.hpp>
#include <components/esm/loadgmst.hpp> #include <components/esm/loadgmst.hpp>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
@ -30,8 +33,10 @@ class QAbstractItemModel;
namespace CSMWorld namespace CSMWorld
{ {
class Data class Data : public QObject
{ {
Q_OBJECT
IdCollection<ESM::Global> mGlobals; IdCollection<ESM::Global> mGlobals;
IdCollection<ESM::GameSetting> mGmsts; IdCollection<ESM::GameSetting> mGmsts;
IdCollection<ESM::Skill> mSkills; IdCollection<ESM::Skill> mSkills;
@ -55,13 +60,17 @@ namespace CSMWorld
Data& operator= (const Data&); Data& operator= (const Data&);
void addModel (QAbstractItemModel *model, UniversalId::Type type1, void addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2 = UniversalId::Type_None); UniversalId::Type type2 = UniversalId::Type_None, bool update = true);
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted);
///< Append all IDs from collection to \a ids.
public: public:
Data(); Data();
~Data(); virtual ~Data();
const IdCollection<ESM::Global>& getGlobals() const; const IdCollection<ESM::Global>& getGlobals() const;
@ -136,6 +145,21 @@ namespace CSMWorld
///< Merging content of a file into base or modified. ///< Merging content of a file into base or modified.
bool hasId (const std::string& id) const; bool hasId (const std::string& id) const;
std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs that are not internal to the editor.
///
/// \param listDeleted include deleted record in the list
signals:
void idListChanged();
private slots:
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void rowsChanged (const QModelIndex& parent, int start, int end);
}; };
} }

@ -534,3 +534,8 @@ int CSMWorld::RefIdCollection::getAppendIndex (UniversalId::Type type) const
{ {
return mData.getAppendIndex (type); return mData.getAppendIndex (type);
} }
std::vector<std::string> CSMWorld::RefIdCollection::getIds (bool listDeleted) const
{
return mData.getIds (listDeleted);
}

@ -89,6 +89,11 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type) const; virtual int getAppendIndex (UniversalId::Type type) const;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::vector<std::string> getIds (bool listDeleted) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
}; };
} }

@ -196,3 +196,25 @@ int CSMWorld::RefIdData::getSize() const
{ {
return mIndex.size(); return mIndex.size();
} }
std::vector<std::string> CSMWorld::RefIdData::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
for (std::map<std::string, LocalIndex>::const_iterator iter (mIndex.begin()); iter!=mIndex.end();
++iter)
{
if (listDeleted || !getRecord (iter->second).isDeleted())
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator container =
mRecordContainers.find (iter->second.second);
if (container==mRecordContainers.end())
throw std::logic_error ("Invalid referenceable ID type");
ids.push_back (container->second->getId (iter->second.first));
}
}
return ids;
}

@ -182,6 +182,11 @@ namespace CSMWorld
void load (const LocalIndex& index, ESM::ESMReader& reader, bool base); void load (const LocalIndex& index, ESM::ESMReader& reader, bool base);
int getSize() const; int getSize() const;
std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
}; };
} }

@ -1,6 +1,14 @@
#include "scriptcontext.hpp" #include "scriptcontext.hpp"
#include <algorithm>
#include <components/misc/stringops.hpp>
#include "data.hpp"
CSMWorld::ScriptContext::ScriptContext (const Data& data) : mData (data), mIdsUpdated (false) {}
bool CSMWorld::ScriptContext::canDeclareLocals() const bool CSMWorld::ScriptContext::canDeclareLocals() const
{ {
return false; return false;
@ -18,5 +26,19 @@ char CSMWorld::ScriptContext::getMemberType (const std::string& name, const std:
bool CSMWorld::ScriptContext::isId (const std::string& name) const bool CSMWorld::ScriptContext::isId (const std::string& name) const
{ {
return false; if (!mIdsUpdated)
{
mIds = mData.getIds();
std::for_each (mIds.begin(), mIds.end(), &Misc::StringUtils::lowerCase);
mIdsUpdated = true;
}
return std::binary_search (mIds.begin(), mIds.end(), Misc::StringUtils::lowerCase (name));
}
void CSMWorld::ScriptContext::invalidateIds()
{
mIdsUpdated = false;
} }

@ -1,14 +1,25 @@
#ifndef CSM_WORLD_SCRIPTCONTEXT_H #ifndef CSM_WORLD_SCRIPTCONTEXT_H
#define CSM_WORLD_SCRIPTCONTEXT_H #define CSM_WORLD_SCRIPTCONTEXT_H
#include <string>
#include <vector>
#include <components/compiler/context.hpp> #include <components/compiler/context.hpp>
namespace CSMWorld namespace CSMWorld
{ {
class Data;
class ScriptContext : public Compiler::Context class ScriptContext : public Compiler::Context
{ {
const Data& mData;
mutable std::vector<std::string> mIds;
mutable bool mIdsUpdated;
public: public:
ScriptContext (const Data& data);
virtual bool canDeclareLocals() const; virtual bool canDeclareLocals() const;
///< Is the compiler allowed to declare local variables? ///< Is the compiler allowed to declare local variables?
@ -20,6 +31,8 @@ namespace CSMWorld
virtual bool isId (const std::string& name) const; virtual bool isId (const std::string& name) const;
///< Does \a name match an ID, that can be referenced? ///< Does \a name match an ID, that can be referenced?
void invalidateIds();
}; };
} }

@ -43,18 +43,18 @@ 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_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 +80,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,11 @@ namespace CSMWorld
Type_Reference, Type_Reference,
Type_RegionMap, Type_RegionMap,
Type_Filter, Type_Filter,
Type_Filters Type_Filters,
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

@ -61,7 +61,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;
} }
@ -70,7 +70,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);
@ -403,6 +407,11 @@ 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::abortOperation (int type) void CSVDoc::View::abortOperation (int type)
{ {
mDocument->abortOperation (type); mDocument->abortOperation (type);

@ -164,6 +164,8 @@ namespace CSVDoc
void addFiltersSubView(); void addFiltersSubView();
void addSceneSubView();
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
{ {

@ -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,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

@ -4,6 +4,7 @@
#include <sstream> #include <sstream>
#include <components/compiler/scanner.hpp> #include <components/compiler/scanner.hpp>
#include <components/compiler/extensions0.hpp>
bool CSVWorld::ScriptHighlighter::parseInt (int value, const Compiler::TokenLoc& loc, bool CSVWorld::ScriptHighlighter::parseInt (int value, const Compiler::TokenLoc& loc,
Compiler::Scanner& scanner) Compiler::Scanner& scanner)
@ -22,7 +23,7 @@ bool CSVWorld::ScriptHighlighter::parseFloat (float value, const Compiler::Token
bool CSVWorld::ScriptHighlighter::parseName (const std::string& name, const Compiler::TokenLoc& loc, bool CSVWorld::ScriptHighlighter::parseName (const std::string& name, const Compiler::TokenLoc& loc,
Compiler::Scanner& scanner) Compiler::Scanner& scanner)
{ {
highlight (loc, Type_Name); highlight (loc, mContext.isId (name) ? Type_Id : Type_Name);
return true; return true;
} }
@ -62,10 +63,10 @@ void CSVWorld::ScriptHighlighter::highlight (const Compiler::TokenLoc& loc, Type
setFormat (index, length, mScheme[type]); setFormat (index, length, mScheme[type]);
} }
CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent) CSVWorld::ScriptHighlighter::ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent)
: QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext) : QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext), mContext (data)
{ {
/// \ŧodo replace this with user settings /// \todo replace this with user settings
{ {
QTextCharFormat format; QTextCharFormat format;
format.setForeground (Qt::darkMagenta); format.setForeground (Qt::darkMagenta);
@ -101,6 +102,16 @@ CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent)
format.setForeground (Qt::green); format.setForeground (Qt::green);
mScheme.insert (std::make_pair (Type_Comment, format)); mScheme.insert (std::make_pair (Type_Comment, format));
} }
{
QTextCharFormat format;
format.setForeground (Qt::blue);
mScheme.insert (std::make_pair (Type_Id, format));
}
// configure compiler
Compiler::registerExtensions (mExtensions);
mContext.setExtensions (&mExtensions);
} }
void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text) void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text)
@ -114,5 +125,9 @@ void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text)
scanner.scan (*this); scanner.scan (*this);
} }
catch (...) {} // ignore syntax errors catch (...) {} // ignore syntax errors
}
void CSVWorld::ScriptHighlighter::invalidateIds()
{
mContext.invalidateIds();
} }

@ -7,6 +7,7 @@
#include <components/compiler/nullerrorhandler.hpp> #include <components/compiler/nullerrorhandler.hpp>
#include <components/compiler/parser.hpp> #include <components/compiler/parser.hpp>
#include <components/compiler/extensions.hpp>
#include "../../model/world/scriptcontext.hpp" #include "../../model/world/scriptcontext.hpp"
@ -23,12 +24,14 @@ namespace CSVWorld
Type_Name, Type_Name,
Type_Keyword, Type_Keyword,
Type_Special, Type_Special,
Type_Comment Type_Comment,
Type_Id
}; };
private: private:
Compiler::NullErrorHandler mErrorHandler; Compiler::NullErrorHandler mErrorHandler;
Compiler::Extensions mExtensions;
CSMWorld::ScriptContext mContext; CSMWorld::ScriptContext mContext;
std::map<Type, QTextCharFormat> mScheme; std::map<Type, QTextCharFormat> mScheme;
@ -71,9 +74,11 @@ namespace CSVWorld
public: public:
ScriptHighlighter (QTextDocument *parent); ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent);
virtual void highlightBlock (const QString& text); virtual void highlightBlock (const QString& text);
void invalidateIds();
}; };
} }

@ -58,7 +58,13 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc:
connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int))); this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int)));
new ScriptHighlighter (mEditor->document()); connect (&document.getData(), SIGNAL (idListChanged()), this, SLOT (idListChanged()));
mHighlighter = new ScriptHighlighter (document.getData(), mEditor->document());
connect (&mUpdateTimer, SIGNAL (timeout()), this, SLOT (updateHighlighting()));
mUpdateTimer.setSingleShot (true);
} }
void CSVWorld::ScriptSubView::setEditLock (bool locked) void CSVWorld::ScriptSubView::setEditLock (bool locked)
@ -66,8 +72,19 @@ void CSVWorld::ScriptSubView::setEditLock (bool locked)
mEditor->setReadOnly (locked); mEditor->setReadOnly (locked);
} }
void CSVWorld::ScriptSubView::idListChanged()
{
mHighlighter->invalidateIds();
if (!mUpdateTimer.isActive())
mUpdateTimer.start (0);
}
void CSVWorld::ScriptSubView::textChanged() void CSVWorld::ScriptSubView::textChanged()
{ {
if (mChangeLocked)
return;
ChangeLock lock (*this); ChangeLock lock (*this);
mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*mModel, mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*mModel,
@ -79,6 +96,8 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo
if (mChangeLocked) if (mChangeLocked)
return; return;
ChangeLock lock (*this);
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row() && if (index.row()>=topLeft.row() && index.row()<=bottomRight.row() &&
@ -96,4 +115,14 @@ void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, i
if (!parent.isValid() && index.row()>=start && index.row()<=end) if (!parent.isValid() && index.row()>=start && index.row()<=end)
deleteLater(); deleteLater();
}
void CSVWorld::ScriptSubView::updateHighlighting()
{
if (mChangeLocked)
return;
ChangeLock lock (*this);
mHighlighter->rehighlight();
} }

@ -3,6 +3,8 @@
#include "../doc/subview.hpp" #include "../doc/subview.hpp"
#include <QTimer>
class QTextEdit; class QTextEdit;
class QModelIndex; class QModelIndex;
@ -18,6 +20,8 @@ namespace CSMWorld
namespace CSVWorld namespace CSVWorld
{ {
class ScriptHighlighter;
class ScriptSubView : public CSVDoc::SubView class ScriptSubView : public CSVDoc::SubView
{ {
Q_OBJECT Q_OBJECT
@ -27,6 +31,8 @@ namespace CSVWorld
CSMWorld::IdTable *mModel; CSMWorld::IdTable *mModel;
int mColumn; int mColumn;
int mChangeLocked; int mChangeLocked;
ScriptHighlighter *mHighlighter;
QTimer mUpdateTimer;
class ChangeLock class ChangeLock
{ {
@ -49,13 +55,19 @@ namespace CSVWorld
virtual void setEditLock (bool locked); virtual void setEditLock (bool locked);
private slots: public slots:
void idListChanged();
void textChanged(); void textChanged();
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
private slots:
void updateHighlighting();
}; };
} }

@ -13,6 +13,7 @@
#include "cellcreator.hpp" #include "cellcreator.hpp"
#include "referenceablecreator.hpp" #include "referenceablecreator.hpp"
#include "referencecreator.hpp" #include "referencecreator.hpp"
#include "scenesubview.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{ {
@ -62,4 +63,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)

@ -119,6 +119,10 @@ target_link_libraries(openmw
components components
) )
if (USE_SYSTEM_TINYXML)
target_link_libraries(openmw ${TINYXML_LIBRARIES})
endif()
if (NOT UNIX) if (NOT UNIX)
target_link_libraries(openmw ${SDL2MAIN_LIBRARY}) target_link_libraries(openmw ${SDL2MAIN_LIBRARY})
endif() endif()

@ -399,8 +399,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, mMaster, mPlugins, mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
@ -410,6 +408,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;
@ -396,6 +403,8 @@ namespace MWBase
/// It only applies to the current form the NPC is in. /// It only applies to the current form the NPC is in.
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0; virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0;
virtual bool getGodModeState() = 0;
virtual bool toggleGodMode() = 0; virtual bool toggleGodMode() = 0;
}; };
} }

@ -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.

@ -250,6 +250,7 @@ namespace MWGui
// remove object from the container it was coming from // remove object from the container it was coming from
mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount); mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount);
mDragAndDrop->finish(); mDragAndDrop->finish();
mDragAndDrop->mSourceModel->update();
} }
else else
{ {

@ -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);

@ -577,15 +577,15 @@ 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);
mPlayer->pitch(-y/scale); mPlayer->pitch(-y/scale);
} }
if (arg.zrel) if (arg.zrel && mControlSwitch["playerviewswitch"]) //Check to make sure you are allowed to zoomout and there is a change
{ {
MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.zrel); MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.zrel);
MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true); MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true);
@ -617,9 +617,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,11 +31,14 @@ 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);
} }
} }
@ -93,39 +96,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 +126,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)
@ -275,9 +281,9 @@ namespace MWMechanics
continue; continue;
} }
// workaround: always keep player alive for now // If it's the player and God Mode is turned on, keep it alive
// \todo remove workaround, once player death can be handled if(iter->first.getRefData().getHandle()=="player" &&
if(iter->first.getRefData().getHandle()=="player") MWBase::Environment::get().getWorld()->getGodModeState())
{ {
MWMechanics::DynamicStat<float> stat(stats.getHealth()); MWMechanics::DynamicStat<float> stat(stats.getHealth());

@ -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);

@ -151,8 +151,7 @@ namespace MWMechanics
for (Collection::const_iterator iter (prev.begin()); iter!=prev.end(); ++iter) for (Collection::const_iterator iter (prev.begin()); iter!=prev.end(); ++iter)
{ {
Collection::const_iterator other = now.mCollection.find (iter->first); Collection::const_iterator other = now.mCollection.find (iter->first);
if (other==now.end())
if (other==prev.end())
{ {
result.add (iter->first, EffectParam() - iter->second); result.add (iter->first, EffectParam() - iter->second);
} }

@ -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
@ -726,8 +737,7 @@ namespace MWScript
bool enabled = MWBase::Environment::get().getWorld()->toggleGodMode(); bool enabled = MWBase::Environment::get().getWorld()->toggleGodMode();
// context.report (enabled ? "God Mode -> On" : "God Mode -> Off"); context.report (enabled ? "God Mode -> On" : "God Mode -> Off");
context.report("Unimplemented");
} }
}; };
@ -790,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>);
} }
} }
} }

@ -167,6 +167,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");

@ -175,6 +175,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 {

@ -170,7 +170,7 @@ namespace MWWorld
mSky (true), mCells (mStore, mEsm), mSky (true), mCells (mStore, mEsm),
mActivationDistanceOverride (mActivationDistanceOverride), mActivationDistanceOverride (mActivationDistanceOverride),
mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true), mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true),
mFacedDistance(FLT_MAX) mFacedDistance(FLT_MAX), mGodMode(false)
{ {
mPhysics = new PhysicsSystem(renderer); mPhysics = new PhysicsSystem(renderer);
mPhysEngine = mPhysics->getEngine(); mPhysEngine = mPhysics->getEngine();
@ -225,8 +225,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);
@ -1582,6 +1582,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;
@ -1877,6 +1890,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);
@ -1948,9 +1971,16 @@ namespace MWWorld
stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0); stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0);
} }
bool World::getGodModeState()
{
return mGodMode;
}
bool World::toggleGodMode() bool World::toggleGodMode()
{ {
return false; mGodMode = !mGodMode;
return mGodMode;
} }
} }

@ -68,6 +68,8 @@ namespace MWWorld
OEngine::Physic::PhysicEngine* mPhysEngine; OEngine::Physic::PhysicEngine* mPhysEngine;
bool mGodMode;
// not implemented // not implemented
World (const World&); World (const World&);
World& operator= (const World&); World& operator= (const World&);
@ -114,6 +116,7 @@ namespace MWWorld
int mPlayIntro; int mPlayIntro;
bool mTeleportEnabled; bool mTeleportEnabled;
bool mLevitationEnabled;
public: public:
@ -353,6 +356,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;
@ -436,10 +440,18 @@ 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);
virtual bool getGodModeState();
virtual bool toggleGodMode(); virtual bool toggleGodMode();
}; };
} }

@ -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

@ -274,5 +274,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;
}
} }

@ -32,6 +32,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
{ {
@ -47,6 +56,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)
@ -47,6 +48,7 @@ Marc Bouvier (CramitDeFrog)
Marcin Hulist (Gohan) Marcin Hulist (Gohan)
Mark Siewert (mark76) Mark Siewert (mark76)
Mateusz Kołaczek (PL_kolek) Mateusz Kołaczek (PL_kolek)
Michael Hogan (Xethik)
Michael Mc Donnell Michael Mc Donnell
Michael Papageorgiou (werdanith) Michael Papageorgiou (werdanith)
Michał Bień (Glorf) Michał Bień (Glorf)
@ -61,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)

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

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

Loading…
Cancel
Save