resolving conflicts

actorid
greye 12 years ago
commit 18cc435aa1

@ -15,7 +15,7 @@ include (OpenMWMacros)
# Version # Version
set (OPENMW_VERSION_MAJOR 0) set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 17) set (OPENMW_VERSION_MINOR 18)
set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@ -513,6 +513,7 @@ if (WIN32)
4309 # Variable overflow, trying to store 128 in a signed char for example 4309 # Variable overflow, trying to store 128 in a signed char for example
4355 # Using 'this' in member initialization list 4355 # Using 'this' in member initialization list
4701 # Potentially uninitialized local variable used 4701 # Potentially uninitialized local variable used
4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt
) )
foreach(d ${WARNINGS_DISABLE}) foreach(d ${WARNINGS_DISABLE})
@ -524,6 +525,7 @@ if (WIN32)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_LAUNCHER) endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif(MSVC) endif(MSVC)
# Same for MinGW # Same for MinGW
@ -631,7 +633,7 @@ if (APPLE)
include(CPack) include(CPack)
endif (APPLE) endif (APPLE)
if (NOT WIN32 AND NOT DPKG_PROGRAM) if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
## Non Debian based Linux building ## Non Debian based Linux building
# paths # paths
set(BINDIR "${CMAKE_INSTALL_PREFIX}/usr/bin" CACHE PATH "Where to install binaries") set(BINDIR "${CMAKE_INSTALL_PREFIX}/usr/bin" CACHE PATH "Where to install binaries")
@ -662,4 +664,4 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM)
# Install resources # Install resources
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" ) INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" )
INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${DATADIR}/resources" ) INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${DATADIR}/resources" )
endif(NOT WIN32 AND NOT DPKG_PROGRAM) endif(NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)

@ -189,73 +189,8 @@ void DataFilesPage::setupConfig()
} }
bool DataFilesPage::setupDataFiles() void DataFilesPage::addDataFiles(Files::Collections &fileCollections, const QString &encoding)
{ {
// We use the Configuration Manager to retrieve the configuration values
boost::program_options::variables_map variables;
boost::program_options::options_description desc;
desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
mCfgMgr.readConfiguration(variables, desc);
// Put the paths in a boost::filesystem vector to use with Files::Collections
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
std::string local = variables["data-local"].as<std::string>();
if (!local.empty()) {
mDataLocal.push_back(Files::PathContainer::value_type(local));
}
if (mDataDirs.size()>1)
mDataDirs.resize (1);
mCfgMgr.processPaths(mDataDirs);
while (mDataDirs.empty()) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error detecting Morrowind installation");
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
QAbstractButton *dirSelectButton =
msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == dirSelectButton) {
// Show a custom dir selection dialog which only accepts valid dirs
QString selectedDir = FileDialog::getExistingDirectory(
this, tr("Select Data Files Directory"),
QDir::currentPath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
// Add the user selected data directory
if (!selectedDir.isEmpty()) {
mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString()));
mCfgMgr.processPaths(mDataDirs);
} else {
// Cancel from within the dir selection dialog
return false;
}
} else {
// Cancel
return false;
}
}
// Create a file collection for the data dirs
Files::Collections fileCollections(mDataDirs, !variables["fs-strict"].as<bool>());
// First we add all the master files // First we add all the master files
const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm"); const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm");
unsigned int i = 0; // Row number unsigned int i = 0; // Row number
@ -283,7 +218,7 @@ bool DataFilesPage::setupDataFiles()
ESMReader fileReader; ESMReader fileReader;
QStringList availableMasters; // Will contain all found masters QStringList availableMasters; // Will contain all found masters
fileReader.setEncoding(variables["encoding"].as<std::string>()); fileReader.setEncoding(encoding.toStdString());
fileReader.open(iter->second.string()); fileReader.open(iter->second.string());
// First we fill the availableMasters and the mMastersWidget // First we fill the availableMasters and the mMastersWidget
@ -350,10 +285,86 @@ bool DataFilesPage::setupDataFiles()
} catch(std::runtime_error &e) { } catch(std::runtime_error &e) {
// An error occurred while reading the .esp // An error occurred while reading the .esp
std::cerr << "Error reading .esp: " << e.what() << std::endl;
continue; continue;
} }
} }
}
bool DataFilesPage::setupDataFiles()
{
// We use the Configuration Manager to retrieve the configuration values
boost::program_options::variables_map variables;
boost::program_options::options_description desc;
desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
mCfgMgr.readConfiguration(variables, desc);
// Put the paths in a boost::filesystem vector to use with Files::Collections
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
std::string local = variables["data-local"].as<std::string>();
if (!local.empty()) {
mDataLocal.push_back(Files::PathContainer::value_type(local));
}
mCfgMgr.processPaths(mDataDirs);
mCfgMgr.processPaths(mDataLocal);
while (mDataDirs.empty()) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error detecting Morrowind installation");
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
QAbstractButton *dirSelectButton =
msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == dirSelectButton) {
// Show a custom dir selection dialog which only accepts valid dirs
QString selectedDir = FileDialog::getExistingDirectory(
this, tr("Select Data Files Directory"),
QDir::currentPath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
// Add the user selected data directory
if (!selectedDir.isEmpty()) {
mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString()));
mCfgMgr.processPaths(mDataDirs);
} else {
// Cancel from within the dir selection dialog
return false;
}
} else {
// Cancel
return false;
}
}
// Add the plugins in the data directories
Files::Collections dataCollections(mDataDirs, !variables["fs-strict"].as<bool>());
Files::Collections dataLocalCollections(mDataLocal, !variables["fs-strict"].as<bool>());
addDataFiles(dataCollections, QString::fromStdString(variables["encoding"].as<std::string>()));
addDataFiles(dataLocalCollections, QString::fromStdString(variables["encoding"].as<std::string>()));
mDataFilesModel->sort(0);
readConfig(); readConfig();
return true; return true;
} }
@ -1139,11 +1150,13 @@ void DataFilesPage::writeConfig(QString profile)
path = QString::fromStdString(it->string()); path = QString::fromStdString(it->string());
path.remove(QChar('\"')); path.remove(QChar('\"'));
QDir dir(path);
// Make sure the string is quoted when it contains spaces // Make sure the string is quoted when it contains spaces
if (path.contains(" ")) { if (path.contains(" ")) {
gameConfig << "data=\"" << path << "\"" << endl; gameConfig << "data=\"" << dir.absolutePath() << "\"" << endl;
} else { } else {
gameConfig << "data=" << path << endl; gameConfig << "data=" << dir.absolutePath() << endl;
} }
} }
@ -1152,10 +1165,12 @@ void DataFilesPage::writeConfig(QString profile)
path = QString::fromStdString(mDataLocal.front().string()); path = QString::fromStdString(mDataLocal.front().string());
path.remove(QChar('\"')); path.remove(QChar('\"'));
QDir dir(path);
if (path.contains(" ")) { if (path.contains(" ")) {
gameConfig << "data-local=\"" << path << "\"" << endl; gameConfig << "data-local=\"" << dir.absolutePath() << "\"" << endl;
} else { } else {
gameConfig << "data-local=" << path << endl; gameConfig << "data-local=" << dir.absolutePath() << endl;
} }
} }

@ -89,6 +89,7 @@ private:
const QStringList checkedPlugins(); const QStringList checkedPlugins();
const QStringList selectedMasters(); const QStringList selectedMasters();
void addDataFiles(Files::Collections &fileCollections, const QString &encoding);
void addPlugins(const QModelIndex &index); void addPlugins(const QModelIndex &index);
void removePlugins(const QModelIndex &index); void removePlugins(const QModelIndex &index);
void uncheckPlugins(); void uncheckPlugins();

@ -16,7 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
compositors characterpreview externalrendering compositors characterpreview externalrendering globalmap
) )
add_openmw_dir (mwinput add_openmw_dir (mwinput
@ -29,7 +29,7 @@ add_openmw_dir (mwgui
map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list
formatting inventorywindow container hud countdialog tradewindow settingswindow formatting inventorywindow container hud countdialog tradewindow settingswindow
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

@ -299,6 +299,7 @@ void OMW::Engine::go()
mOgre->configure( mOgre->configure(
mCfgMgr.getLogPath().string(), mCfgMgr.getLogPath().string(),
renderSystem, renderSystem,
Settings::Manager::getString("opengl rtt mode", "Video"),
false); false);
// This has to be added BEFORE MyGUI is initialized, as it needs // This has to be added BEFORE MyGUI is initialized, as it needs
@ -306,6 +307,8 @@ void OMW::Engine::go()
//addResourcesDirectory(mResDir); //addResourcesDirectory(mResDir);
addResourcesDirectory(mCfgMgr.getCachePath ().string());
addResourcesDirectory(mResDir / "mygui"); addResourcesDirectory(mResDir / "mygui");
addResourcesDirectory(mResDir / "water"); addResourcesDirectory(mResDir / "water");
addResourcesDirectory(mResDir / "gbuffer"); addResourcesDirectory(mResDir / "gbuffer");
@ -366,6 +369,7 @@ void OMW::Engine::go()
pos.pos[2] = 0; pos.pos[2] = 0;
mEnvironment.getWorld()->renderPlayer(); mEnvironment.getWorld()->renderPlayer();
mEnvironment.getWorld()->renderGlobalMap();
if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (mCellName)) if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (mCellName))
{ {

@ -118,7 +118,7 @@ namespace MWBase
/// Set value for the given ID. /// Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0; virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0;
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0; virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0;
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) = 0; virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) = 0;
virtual void setValue (const std::string& id, const std::string& value) = 0; virtual void setValue (const std::string& id, const std::string& value) = 0;
virtual void setValue (const std::string& id, int value) = 0; virtual void setValue (const std::string& id, int value) = 0;
@ -189,6 +189,8 @@ namespace MWBase
virtual void allowMouse() = 0; virtual void allowMouse() = 0;
virtual void notifyInputActionBound() = 0; virtual void notifyInputActionBound() = 0;
virtual void addVisitedLocation(const std::string& name, int x, int y) = 0;
virtual void removeDialog(OEngine::GUI::Layout* dialog) = 0; virtual void removeDialog(OEngine::GUI::Layout* dialog) = 0;
///< Hides dialog and schedules dialog to be deleted. ///< Hides dialog and schedules dialog to be deleted.
@ -219,6 +221,11 @@ namespace MWBase
virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0; virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0;
virtual void loadingDone() = 0; virtual void loadingDone() = 0;
virtual void enableRest() = 0;
virtual bool getRestEnabled() = 0;
virtual bool getPlayerSleeping() = 0;
}; };
} }

@ -160,6 +160,9 @@ namespace MWBase
virtual void setDay (int day) = 0; virtual void setDay (int day) = 0;
///< Set in-game time day. ///< Set in-game time day.
virtual int getDay() = 0;
virtual int getMonth() = 0;
virtual MWWorld::TimeStamp getTimeStamp() const = 0; virtual MWWorld::TimeStamp getTimeStamp() const = 0;
///< Return current in-game time stamp. ///< Return current in-game time stamp.
@ -204,6 +207,9 @@ namespace MWBase
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0; virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0;
virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos) = 0;
///< place an object in a "safe" location (ie not in the void, etc).
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
const = 0; const = 0;
///< Convert cell numbers to position. ///< Convert cell numbers to position.
@ -218,7 +224,7 @@ namespace MWBase
virtual bool toggleCollisionMode() = 0; virtual bool toggleCollisionMode() = 0;
///< Toggle collision mode for player. If disabled player object should ignore ///< Toggle collision mode for player. If disabled player object should ignore
/// collisions and gravity. /// collisions and gravity.
///< \return Resulting mode /// \return Resulting mode
virtual bool toggleRenderMode (RenderMode mode) = 0; virtual bool toggleRenderMode (RenderMode mode) = 0;
///< Toggle a render mode. ///< Toggle a render mode.
@ -276,8 +282,16 @@ namespace MWBase
virtual void togglePlayerLooking(bool enable) = 0; virtual void togglePlayerLooking(bool enable) = 0;
virtual void renderPlayer() = 0; virtual void renderPlayer() = 0;
virtual void renderGlobalMap() = 0;
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0; virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;
virtual int canRest() = 0;
///< check if the player is allowed to rest \n
/// 0 - yes \n
/// 1 - only waiting \n
/// 2 - player is underwater \n
/// 3 - enemies are nearby (not implemented)
}; };
} }

@ -141,6 +141,7 @@ namespace MWClass
assert(ref->base != NULL); assert(ref->base != NULL);
std::string headID = ref->base->mHead; std::string headID = ref->base->mHead;
int end = headID.find_last_of("head_") - 4; int end = headID.find_last_of("head_") - 4;
std::string bodyRaceID = headID.substr(0, end); std::string bodyRaceID = headID.substr(0, end);
@ -153,6 +154,7 @@ namespace MWClass
model = "meshes\\base_animkna.nif"; model = "meshes\\base_animkna.nif";
} }
return model; return model;
} }
std::string Npc::getName (const MWWorld::Ptr& ptr) const std::string Npc::getName (const MWWorld::Ptr& ptr) const
@ -297,7 +299,7 @@ namespace MWClass
{ {
Ogre::Vector3 vector (0, 0, 0); Ogre::Vector3 vector (0, 0, 0);
vector.x = - getMovementSettings (ptr).mLeftRight * 127; vector.x = getMovementSettings (ptr).mLeftRight * 127;
vector.y = getMovementSettings (ptr).mForwardBackward * 127; vector.y = getMovementSettings (ptr).mForwardBackward * 127;
vector.z = getMovementSettings(ptr).mUpDown * 127; vector.z = getMovementSettings(ptr).mUpDown * 127;

@ -151,7 +151,7 @@ void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat
} }
} }
void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
if (mReviewDialog) if (mReviewDialog)
{ {
@ -294,17 +294,17 @@ void CharacterCreation::spawnDialog(const char id)
} }
} }
void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setPlayerHealth (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerHealth = value; mPlayerHealth = value;
} }
void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerMagicka = value; mPlayerMagicka = value;
} }
void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<int>& value) void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<float>& value)
{ {
mPlayerFatigue = value; mPlayerFatigue = value;
} }

@ -35,14 +35,14 @@ namespace MWGui
//Show a dialog //Show a dialog
void spawnDialog(const char id); void spawnDialog(const char id);
void setPlayerHealth (const MWMechanics::DynamicStat<int>& value); void setPlayerHealth (const MWMechanics::DynamicStat<float>& value);
void setPlayerMagicka (const MWMechanics::DynamicStat<int>& value); void setPlayerMagicka (const MWMechanics::DynamicStat<float>& value);
void setPlayerFatigue (const MWMechanics::DynamicStat<int>& value); void setPlayerFatigue (const MWMechanics::DynamicStat<float>& value);
void setValue (const std::string& id, const MWMechanics::Stat<int>& value); void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value); void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void configureSkills (const SkillList& major, const SkillList& minor); void configureSkills (const SkillList& major, const SkillList& minor);
@ -65,9 +65,9 @@ namespace MWGui
std::string mPlayerRaceId; std::string mPlayerRaceId;
std::string mPlayerBirthSignId; std::string mPlayerBirthSignId;
ESM::Class mPlayerClass; ESM::Class mPlayerClass;
MWMechanics::DynamicStat<int> mPlayerHealth; MWMechanics::DynamicStat<float> mPlayerHealth;
MWMechanics::DynamicStat<int> mPlayerMagicka; MWMechanics::DynamicStat<float> mPlayerMagicka;
MWMechanics::DynamicStat<int> mPlayerFatigue; MWMechanics::DynamicStat<float> mPlayerFatigue;
//Class generation vars //Class generation vars
unsigned mGenerateClassStep; // Keeps track of current step in Generate Class dialog unsigned mGenerateClassStep; // Keeps track of current step in Generate Class dialog

@ -161,7 +161,7 @@ void HUD::setEffect(const char *img)
mEffect1->setImageTexture(img); mEffect1->setImageTexture(img);
} }
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& value) void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
static const char *ids[] = static const char *ids[] =
{ {

@ -14,7 +14,7 @@ namespace MWGui
public: public:
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
void setEffect(const char *img); void setEffect(const char *img);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setFPS(float fps); void setFPS(float fps);
void setTriangleCount(unsigned int count); void setTriangleCount(unsigned int count);
void setBatchCount(unsigned int count); void setBatchCount(unsigned int count);

@ -0,0 +1,197 @@
#include "levelupdialog.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/stat.hpp"
#include <components/esm_store/reclists.hpp>
#include <components/esm_store/store.hpp>
namespace MWGui
{
LevelupDialog::LevelupDialog(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_levelup_dialog.layout", parWindowManager)
{
getWidget(mOkButton, "OkButton");
getWidget(mClassImage, "ClassImage");
getWidget(mLevelText, "LevelText");
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onOkButtonClicked);
for (int i=1; i<9; ++i)
{
MyGUI::TextBox* t;
getWidget(t, "AttribVal" + boost::lexical_cast<std::string>(i));
MyGUI::Button* b;
getWidget(b, "Attrib" + boost::lexical_cast<std::string>(i));
b->setUserData (i-1);
b->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onAttributeClicked);
mAttributes.push_back(b);
mAttributeValues.push_back(t);
getWidget(t, "AttribMultiplier" + boost::lexical_cast<std::string>(i));
mAttributeMultipliers.push_back(t);
}
int curX = mMainWidget->getWidth()/2 - (16 + 2) * 1.5;
for (int i=0; i<3; ++i)
{
MyGUI::ImageBox* image = mMainWidget->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(curX,250,16,16), MyGUI::Align::Default);
image->setImageTexture ("icons\\tx_goldicon.dds");
curX += 24+2;
mCoins.push_back(image);
}
center();
}
void LevelupDialog::setAttributeValues()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
for (int i=0; i<8; ++i)
{
int val = creatureStats.getAttribute (i).getBase ();
if (std::find(mSpentAttributes.begin(), mSpentAttributes.end(), i) != mSpentAttributes.end())
{
val += pcStats.getLevelupAttributeMultiplier (i);
}
if (val >= 100)
val = 100;
mAttributeValues[i]->setCaption(boost::lexical_cast<std::string>(val));
}
}
void LevelupDialog::resetCoins ()
{
int curX = mMainWidget->getWidth()/2 - (16 + 2) * 1.5;
for (int i=0; i<3; ++i)
{
MyGUI::ImageBox* image = mCoins[i];
image->setCoord(MyGUI::IntCoord(curX,250,16,16));
curX += 24+2;
}
}
void LevelupDialog::assignCoins ()
{
resetCoins();
for (unsigned int i=0; i<mSpentAttributes.size(); ++i)
{
MyGUI::ImageBox* image = mCoins[i];
int attribute = mSpentAttributes[i];
int xdiff = mAttributeMultipliers[attribute]->getCaption() == "" ? 0 : 30;
MyGUI::IntPoint pos = mAttributes[attribute]->getAbsolutePosition() - mMainWidget->getAbsolutePosition() - MyGUI::IntPoint(24+xdiff,-4);
image->setPosition(pos);
}
setAttributeValues();
}
void LevelupDialog::open()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
center();
mSpentAttributes.clear();
resetCoins();
setAttributeValues();
// set class image
const ESM::Class& playerClass = MWBase::Environment::get().getWorld ()->getPlayer ().getClass ();
// retrieve the ID to this class
std::string classId;
std::map<std::string, ESM::Class> list = MWBase::Environment::get().getWorld()->getStore ().classes.list;
for (std::map<std::string, ESM::Class>::iterator it = list.begin(); it != list.end(); ++it)
{
if (playerClass.mName == it->second.mName)
classId = it->first;
}
mClassImage->setImageTexture ("textures\\levelup\\" + classId + ".dds");
/// \todo replace this with INI-imported texts
int level = creatureStats.getLevel ()+1;
mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + boost::lexical_cast<std::string>(level));
for (int i=0; i<8; ++i)
{
MyGUI::TextBox* text = mAttributeMultipliers[i];
int mult = pcStats.getLevelupAttributeMultiplier (i);
text->setCaption(mult <= 1 ? "" : "x" + boost::lexical_cast<std::string>(mult));
}
}
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get(player).getCreatureStats (player);
MWMechanics::NpcStats& pcStats = MWWorld::Class::get(player).getNpcStats (player);
if (mSpentAttributes.size() < 3)
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage36}", std::vector<std::string>());
else
{
// increase attributes
for (int i=0; i<3; ++i)
{
MWMechanics::Stat<int>& attribute = creatureStats.getAttribute(mSpentAttributes[i]);
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
if (attribute.getBase() >= 100)
attribute.setBase(100);
}
// "When you gain a level, in addition to increasing three primary attributes, your Health
// will automatically increase by 10% of your Endurance attribute. If you increased Endurance this level,
// the Health increase is calculated from the increased Endurance"
creatureStats.increaseLevelHealthBonus (creatureStats.getAttribute(ESM::Attribute::Endurance).getBase() * 0.1f);
creatureStats.setLevel (creatureStats.getLevel()+1);
pcStats.levelUp ();
mWindowManager.removeGuiMode (GM_Levelup);
}
}
void LevelupDialog::onAttributeClicked (MyGUI::Widget *sender)
{
int attribute = *sender->getUserData<int>();
std::vector<int>::iterator found = std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute);
if (found != mSpentAttributes.end())
mSpentAttributes.erase (found);
else
{
if (mSpentAttributes.size() == 3)
mSpentAttributes[2] = attribute;
else
mSpentAttributes.push_back(attribute);
}
assignCoins();
}
}

@ -0,0 +1,39 @@
#ifndef MWGUI_LEVELUPDIALOG_H
#define MWGUI_LEVELUPDIALOG_H
#include "window_base.hpp"
namespace MWGui
{
class LevelupDialog : public WindowBase
{
public:
LevelupDialog(MWBase::WindowManager& parWindowManager);
virtual void open();
private:
MyGUI::Button* mOkButton;
MyGUI::ImageBox* mClassImage;
MyGUI::TextBox* mLevelText;
std::vector<MyGUI::Button*> mAttributes;
std::vector<MyGUI::TextBox*> mAttributeValues;
std::vector<MyGUI::TextBox*> mAttributeMultipliers;
std::vector<MyGUI::ImageBox*> mCoins;
std::vector<int> mSpentAttributes;
void onOkButtonClicked (MyGUI::Widget* sender);
void onAttributeClicked (MyGUI::Widget* sender);
void assignCoins();
void resetCoins();
void setAttributeValues();
};
}
#endif

@ -3,10 +3,13 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <OgreVector2.h> #include <OgreVector2.h>
#include <OgreTextureManager.h>
#include <OgreSceneNode.h>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwworld/player.hpp"
using namespace MWGui; using namespace MWGui;
@ -254,18 +257,24 @@ MapWindow::MapWindow(MWBase::WindowManager& parWindowManager) :
getWidget(mLocalMap, "LocalMap"); getWidget(mLocalMap, "LocalMap");
getWidget(mGlobalMap, "GlobalMap"); getWidget(mGlobalMap, "GlobalMap");
getWidget(mPlayerArrow, "Compass"); getWidget(mGlobalMapImage, "GlobalMapImage");
getWidget(mPlayerArrowLocal, "CompassLocal");
getWidget(mPlayerArrowGlobal, "CompassGlobal");
mGlobalMap->setVisible (false);
getWidget(mButton, "WorldButton"); getWidget(mButton, "WorldButton");
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
mButton->setCaptionWithReplacing("#{sWorld}"); mButton->setCaptionWithReplacing("#{sWorld}");
MyGUI::Button* eventbox; getWidget(mEventBoxGlobal, "EventBoxGlobal");
getWidget(eventbox, "EventBox"); mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); getWidget(mEventBoxLocal, "EventBoxLocal");
mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
LocalMapBase::init(mLocalMap, mPlayerArrow, this); LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this);
} }
void MapWindow::setCellName(const std::string& cellName) void MapWindow::setCellName(const std::string& cellName)
@ -273,24 +282,54 @@ void MapWindow::setCellName(const std::string& cellName)
setTitle(cellName); setTitle(cellName);
} }
void MapWindow::addVisitedLocation(const std::string& name, int x, int y)
{
const int cellSize = 24;
int size = 24 * 61;
MyGUI::IntCoord widgetCoord(
(x+30)*cellSize+6,
(size-1) - (y+30)*cellSize+6,
12, 12);
static int _counter=0;
MyGUI::Button* markerWidget = mGlobalMapImage->createWidget<MyGUI::Button>("ButtonImage",
widgetCoord, MyGUI::Align::Default, "Marker" + boost::lexical_cast<std::string>(_counter));
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTip");
markerWidget->setUserString("Caption_Text", name);
++_counter;
markerWidget = mEventBoxGlobal->createWidget<MyGUI::Button>("",
widgetCoord, MyGUI::Align::Default);
markerWidget->setNeedMouseFocus (true);
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTip");
markerWidget->setUserString("Caption_Text", name);
}
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{ {
if (_id!=MyGUI::MouseButton::Left) return; if (_id!=MyGUI::MouseButton::Left) return;
if (!mGlobal) mLastDragPos = MyGUI::IntPoint(_left, _top);
mLastDragPos = MyGUI::IntPoint(_left, _top);
} }
void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{ {
if (_id!=MyGUI::MouseButton::Left) return; if (_id!=MyGUI::MouseButton::Left) return;
MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
if (!mGlobal) if (!mGlobal)
{
MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff ); mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff );
else
mGlobalMap->setViewOffset( mGlobalMap->getViewOffset() + diff );
mLastDragPos = MyGUI::IntPoint(_left, _top);
} mLastDragPos = MyGUI::IntPoint(_left, _top);
} }
void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender) void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
@ -307,3 +346,41 @@ void MapWindow::onPinToggled()
{ {
mWindowManager.setMinimapVisibility(!mPinned); mWindowManager.setMinimapVisibility(!mPinned);
} }
void MapWindow::open()
{
mGlobalMapImage->setImageTexture("GlobalMap.png");
int size = 24 * 61;
mGlobalMap->setCanvasSize (size, size);
mGlobalMapImage->setSize(size, size);
for (unsigned int i=0; i<mGlobalMapImage->getChildCount (); ++i)
{
if (mGlobalMapImage->getChildAt (i)->getName().substr(0,6) == "Marker")
mGlobalMapImage->getChildAt (i)->castType<MyGUI::Button>()->setImageResource("DoorMarker");
}
Ogre::Vector3 pos = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedPosition ();
Ogre::Quaternion orient = MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer().getRefData ().getBaseNode ()->_getDerivedOrientation ();
Ogre::Vector2 dir (orient.yAxis ().x, -orient.yAxis().z);
float worldX = ((pos.x / 8192.f-0.5) / 30.f+1)/2.f;
float worldY = ((pos.z / 8192.f+1.5) / 30.f+1)/2.f;
// for interiors, we have no choice other than using the last position & direction.
/// \todo save this last position in the savegame?
if (MWBase::Environment::get().getWorld ()->isCellExterior ())
{
mPlayerArrowGlobal->setPosition(MyGUI::IntPoint(size * worldX - 16, size * worldY - 16));
MyGUI::ISubWidget* main = mPlayerArrowGlobal->getSubWidgetMain();
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
float angle = std::atan2(dir.x, dir.y);
rotatingSubskin->setAngle(angle);
}
mPlayerArrowGlobal->setImageTexture ("textures\\compass.dds");
}

@ -62,17 +62,26 @@ namespace MWGui
void setCellName(const std::string& cellName); void setCellName(const std::string& cellName);
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
virtual void open();
private: private:
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id); void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onWorldButtonClicked(MyGUI::Widget* _sender); void onWorldButtonClicked(MyGUI::Widget* _sender);
MyGUI::ScrollView* mGlobalMap; MyGUI::ScrollView* mGlobalMap;
MyGUI::ImageBox* mPlayerArrow; MyGUI::ImageBox* mGlobalMapImage;
MyGUI::ImageBox* mPlayerArrowLocal;
MyGUI::ImageBox* mPlayerArrowGlobal;
MyGUI::Button* mButton; MyGUI::Button* mButton;
MyGUI::IntPoint mLastDragPos; MyGUI::IntPoint mLastDragPos;
bool mGlobal; bool mGlobal;
MyGUI::Button* mEventBoxGlobal;
MyGUI::Button* mEventBoxLocal;
protected: protected:
virtual void onPinToggled(); virtual void onPinToggled();
}; };

@ -20,8 +20,11 @@ namespace MWGui
GM_Dialogue, // NPC interaction GM_Dialogue, // NPC interaction
GM_Barter, GM_Barter,
GM_Rest, GM_Rest,
GM_RestBed,
GM_SpellBuying, GM_SpellBuying,
GM_Levelup,
// Startup character creation dialogs // Startup character creation dialogs
GM_Name, GM_Name,
GM_Race, GM_Race,

@ -40,7 +40,7 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager)
getWidget(mHeadRotate, "HeadRotate"); getWidget(mHeadRotate, "HeadRotate");
mHeadRotate->setScrollRange(50); mHeadRotate->setScrollRange(50);
mHeadRotate->setScrollPosition(20); mHeadRotate->setScrollPosition(25);
mHeadRotate->setScrollViewPage(10); mHeadRotate->setScrollViewPage(10);
mHeadRotate->eventScrollChangePosition += MyGUI::newDelegate(this, &RaceDialog::onHeadRotate); mHeadRotate->eventScrollChangePosition += MyGUI::newDelegate(this, &RaceDialog::onHeadRotate);

@ -134,21 +134,21 @@ void ReviewDialog::setBirthSign(const std::string& signId)
} }
} }
void ReviewDialog::setHealth(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setHealth(const MWMechanics::DynamicStat<float>& value)
{ {
mHealth->setValue(value.getCurrent(), value.getModified()); mHealth->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
mHealth->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); mHealth->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
} }
void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<float>& value)
{ {
mMagicka->setValue(value.getCurrent(), value.getModified()); mMagicka->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
mMagicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); mMagicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
} }
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value)
{ {
mFatigue->setValue(value.getCurrent(), value.getModified()); mFatigue->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());

@ -35,9 +35,9 @@ namespace MWGui
void setClass(const ESM::Class& class_); void setClass(const ESM::Class& class_);
void setBirthSign (const std::string &signId); void setBirthSign (const std::string &signId);
void setHealth(const MWMechanics::DynamicStat<int>& value); void setHealth(const MWMechanics::DynamicStat<float>& value);
void setMagicka(const MWMechanics::DynamicStat<int>& value); void setMagicka(const MWMechanics::DynamicStat<float>& value);
void setFatigue(const MWMechanics::DynamicStat<int>& value); void setFatigue(const MWMechanics::DynamicStat<float>& value);
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value); void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value);

@ -122,6 +122,7 @@ namespace MWGui
getWidget(mInvertYButton, "InvertYButton"); getWidget(mInvertYButton, "InvertYButton");
getWidget(mUISensitivitySlider, "UISensitivitySlider"); getWidget(mUISensitivitySlider, "UISensitivitySlider");
getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider"); getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider");
getWidget(mGammaSlider, "GammaSlider");
mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
@ -143,6 +144,7 @@ namespace MWGui
mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mGammaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
@ -200,6 +202,14 @@ namespace MWGui
getWidget(fovText, "FovText"); getWidget(fovText, "FovText");
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getFloat("field of view", "General"))) + ")"); fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getFloat("field of view", "General"))) + ")");
float gammaVal = (Settings::Manager::getFloat("gamma", "Video")-0.1f)/(3.f-0.1f);
mGammaSlider->setScrollPosition(gammaVal * (mGammaSlider->getScrollRange()-1));
MyGUI::TextBox* gammaText;
getWidget(gammaText, "GammaText");
std::stringstream gamma;
gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video");
gammaText->setCaption("Gamma (" + gamma.str() + ")");
float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0; float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0;
mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1)); mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1));
std::string tf = Settings::Manager::getString("texture filtering", "General"); std::string tf = Settings::Manager::getString("texture filtering", "General");
@ -511,6 +521,15 @@ namespace MWGui
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int((1-val) * sFovMin + val * sFovMax)) + ")"); fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int((1-val) * sFovMin + val * sFovMax)) + ")");
Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax); Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax);
} }
else if (scroller == mGammaSlider)
{
Settings::Manager::setFloat("gamma", "Video", (1-val) * 0.1f + val * 3.f);
MyGUI::TextBox* gammaText;
getWidget(gammaText, "GammaText");
std::stringstream gamma;
gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video");
gammaText->setCaption("Gamma (" + gamma.str() + ")");
}
else if (scroller == mAnisotropySlider) else if (scroller == mAnisotropySlider)
{ {
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(int(val*16)) + ")"); mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(int(val*16)) + ")");

@ -40,6 +40,7 @@ namespace MWGui
MyGUI::Button* mFPSButton; MyGUI::Button* mFPSButton;
MyGUI::ScrollBar* mViewDistanceSlider; MyGUI::ScrollBar* mViewDistanceSlider;
MyGUI::ScrollBar* mFOVSlider; MyGUI::ScrollBar* mFOVSlider;
MyGUI::ScrollBar* mGammaSlider;
MyGUI::ScrollBar* mAnisotropySlider; MyGUI::ScrollBar* mAnisotropySlider;
MyGUI::Button* mTextureFilteringButton; MyGUI::Button* mTextureFilteringButton;
MyGUI::TextBox* mAnisotropyLabel; MyGUI::TextBox* mAnisotropyLabel;

@ -137,7 +137,7 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>&
} }
} }
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
static const char *ids[] = static const char *ids[] =
{ {
@ -150,7 +150,7 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicSta
if (ids[i]==id) if (ids[i]==id)
{ {
std::string id (ids[i]); std::string id (ids[i]);
setBar (id, id + "T", value.getCurrent(), value.getModified()); setBar (id, id + "T", static_cast<int>(value.getCurrent()), static_cast<int>(value.getModified()));
// health, magicka, fatigue tooltip // health, magicka, fatigue tooltip
MyGUI::Widget* w; MyGUI::Widget* w;
@ -236,12 +236,21 @@ void StatsWindow::configureSkills (const std::vector<int>& major, const std::vec
void StatsWindow::onFrame () void StatsWindow::onFrame ()
{ {
if (mMainWidget->getVisible()) if (!mMainWidget->getVisible())
return; return;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player); MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player);
// level progress
MyGUI::Widget* levelWidget;
for (int i=0; i<2; ++i)
{
getWidget(levelWidget, i==0 ? "Level_str" : "LevelText");
levelWidget->setUserString("RangePosition_LevelProgress", boost::lexical_cast<std::string>(PCstats.getLevelProgress()));
levelWidget->setUserString("Caption_LevelProgressText", boost::lexical_cast<std::string>(PCstats.getLevelProgress()) + "/10");
}
setFactions(PCstats.getFactionRanks()); setFactions(PCstats.getFactionRanks());
setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign());

@ -32,7 +32,7 @@ namespace MWGui
/// Set value for the given ID. /// Set value for the given ID.
void setValue (const std::string& id, const MWMechanics::Stat<int>& value); void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
void setValue (const std::string& id, const std::string& value); void setValue (const std::string& id, const std::string& value);
void setValue (const std::string& id, int value); void setValue (const std::string& id, int value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value); void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);

@ -47,10 +47,22 @@ void TextInputDialog::open()
void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) void TextInputDialog::onOkClicked(MyGUI::Widget* _sender)
{ {
eventDone(this); if (mTextEdit->getCaption() == "")
{
mWindowManager.messageBox ("#{sNotifyMessage37}", std::vector<std::string>());
MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit);
}
else
eventDone(this);
} }
void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender)
{ {
eventDone(this); if (mTextEdit->getCaption() == "")
{
mWindowManager.messageBox ("#{sNotifyMessage37}", std::vector<std::string>());
MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit);
}
else
eventDone(this);
} }

@ -0,0 +1,213 @@
#include "waitdialog.hpp"
#include <boost/lexical_cast.hpp>
#include <libs/openengine/ogre/fader.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwworld/timestamp.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "widgets.hpp"
namespace MWGui
{
WaitDialogProgressBar::WaitDialogProgressBar(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_wait_dialog_progressbar.layout", parWindowManager)
{
getWidget(mProgressBar, "ProgressBar");
getWidget(mProgressText, "ProgressText");
}
void WaitDialogProgressBar::open()
{
center();
}
void WaitDialogProgressBar::setProgress (int cur, int total)
{
mProgressBar->setProgressRange (total);
mProgressBar->setProgressPosition (cur);
mProgressText->setCaption(boost::lexical_cast<std::string>(cur) + "/" + boost::lexical_cast<std::string>(total));
}
// ---------------------------------------------------------------------------------------------------------
WaitDialog::WaitDialog(MWBase::WindowManager &parWindowManager)
: WindowBase("openmw_wait_dialog.layout", parWindowManager)
, mProgressBar(parWindowManager)
, mWaiting(false)
, mSleeping(false)
, mHours(1)
, mRemainingTime(0.05)
{
getWidget(mDateTimeText, "DateTimeText");
getWidget(mRestText, "RestText");
getWidget(mHourText, "HourText");
getWidget(mHourSlider, "HourSlider");
getWidget(mUntilHealedButton, "UntilHealedButton");
getWidget(mWaitButton, "WaitButton");
getWidget(mCancelButton, "CancelButton");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WaitDialog::onCancelButtonClicked);
mUntilHealedButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WaitDialog::onUntilHealedButtonClicked);
mWaitButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WaitDialog::onWaitButtonClicked);
mHourSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &WaitDialog::onHourSliderChangedPosition);
mProgressBar.setVisible (false);
}
void WaitDialog::open()
{
if (!MWBase::Environment::get().getWindowManager ()->getRestEnabled ())
{
mWindowManager.popGuiMode ();
}
int canRest = MWBase::Environment::get().getWorld ()->canRest ();
if (canRest == 2)
{
// resting underwater or mid-air not allowed
mWindowManager.messageBox ("#{sNotifyMessage1}", std::vector<std::string>());
mWindowManager.popGuiMode ();
}
setCanRest(canRest == 0);
onHourSliderChangedPosition(mHourSlider, 0);
mHourSlider->setScrollPosition (0);
// http://www.uesp.net/wiki/Lore:Calendar
std::string month;
int m = MWBase::Environment::get().getWorld ()->getMonth ();
if (m == 0)
month = "#{sMonthMorningstar}";
else if (m == 1)
month = "#{sMonthSunsdawn}";
else if (m == 2)
month = "#{sMonthFirstseed}";
else if (m == 3)
month = "#{sMonthRainshand}";
else if (m == 4)
month = "#{sMonthSecondseed}";
else if (m == 5)
month = "#{sMonthMidyear}";
else if (m == 6)
month = "#{sMonthSunsheight}";
else if (m == 7)
month = "#{sMonthLastseed}";
else if (m == 8)
month = "#{sMonthHeartfire}";
else if (m == 9)
month = "#{sMonthFrostfall}";
else if (m == 10)
month = "#{sMonthSunsdusk}";
else if (m == 11)
month = "#{sMonthEveningstar}";
int hour = MWBase::Environment::get().getWorld ()->getTimeStamp ().getHour ();
bool pm = hour >= 12;
if (hour >= 13) hour -= 12;
std::string dateTimeText =
boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getDay ()+1) + " "
+ month + " (#{sDay} " + boost::lexical_cast<std::string>(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay ()+1)
+ ") " + boost::lexical_cast<std::string>(hour) + " " + (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}");
mDateTimeText->setCaptionWithReplacing (dateTimeText);
}
void WaitDialog::onUntilHealedButtonClicked(MyGUI::Widget* sender)
{
startWaiting();
}
void WaitDialog::onWaitButtonClicked(MyGUI::Widget* sender)
{
startWaiting();
}
void WaitDialog::startWaiting ()
{
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.2);
setVisible(false);
mProgressBar.setVisible (true);
mWaiting = true;
mCurHour = 0;
mRemainingTime = 0.05;
mProgressBar.setProgress (0, mHours);
}
void WaitDialog::onCancelButtonClicked(MyGUI::Widget* sender)
{
mWindowManager.popGuiMode ();
}
void WaitDialog::onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position)
{
mHourText->setCaptionWithReplacing (boost::lexical_cast<std::string>(position+1) + " #{sRestMenu2}");
mHours = position+1;
}
void WaitDialog::setCanRest (bool canRest)
{
mUntilHealedButton->setVisible(canRest);
mWaitButton->setCaptionWithReplacing (canRest ? "#{sRest}" : "#{sWait}");
mRestText->setCaptionWithReplacing (canRest ? "#{sRestMenu3}" : "#{sRestIllegal}");
mSleeping = canRest;
dynamic_cast<Widgets::Box*>(mMainWidget)->notifyChildrenSizeChanged();
center();
}
void WaitDialog::onFrame(float dt)
{
if (!mWaiting)
return;
mRemainingTime -= dt;
if (mRemainingTime < 0)
{
mRemainingTime = 0.05;
++mCurHour;
mProgressBar.setProgress (mCurHour, mHours);
if (mCurHour <= mHours)
MWBase::Environment::get().getWorld ()->advanceTime (1);
}
if (mCurHour > mHours)
stopWaiting();
}
void WaitDialog::stopWaiting ()
{
MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.2);
mProgressBar.setVisible (false);
mWindowManager.popGuiMode ();
mWaiting = false;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::NpcStats pcstats = MWWorld::Class::get(player).getNpcStats(player);
// trigger levelup if possible
if (mSleeping && pcstats.getLevelProgress () >= 10)
{
mWindowManager.pushGuiMode (GM_Levelup);
}
}
}

@ -0,0 +1,66 @@
#ifndef MWGUI_WAIT_DIALOG_H
#define MWGUI_WAIT_DIALOG_H
#include "window_base.hpp"
namespace MWGui
{
class WaitDialogProgressBar : public WindowBase
{
public:
WaitDialogProgressBar(MWBase::WindowManager& parWindowManager);
virtual void open();
void setProgress(int cur, int total);
protected:
MyGUI::ProgressBar* mProgressBar;
MyGUI::TextBox* mProgressText;
};
class WaitDialog : public WindowBase
{
public:
WaitDialog(MWBase::WindowManager& parWindowManager);
virtual void open();
void onFrame(float dt);
void bedActivated() { setCanRest(true); }
bool getSleeping() { return mWaiting && mSleeping; }
protected:
MyGUI::TextBox* mDateTimeText;
MyGUI::TextBox* mRestText;
MyGUI::TextBox* mHourText;
MyGUI::ScrollBar* mHourSlider;
MyGUI::Button* mUntilHealedButton;
MyGUI::Button* mWaitButton;
MyGUI::Button* mCancelButton;
bool mWaiting;
bool mSleeping;
int mCurHour;
int mHours;
float mRemainingTime;
WaitDialogProgressBar mProgressBar;
void onUntilHealedButtonClicked(MyGUI::Widget* sender);
void onWaitButtonClicked(MyGUI::Widget* sender);
void onCancelButtonClicked(MyGUI::Widget* sender);
void onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position);
void setCanRest(bool canRest);
void startWaiting();
void stopWaiting();
};
}
#endif

@ -795,7 +795,6 @@ void MWDynamicStat::initialiseOverride()
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
void AutoSizedWidget::notifySizeChange (MyGUI::Widget* w) void AutoSizedWidget::notifySizeChange (MyGUI::Widget* w)
{ {
if (w->getParent () != 0) if (w->getParent () != 0)
@ -869,29 +868,33 @@ void AutoSizedButton::setPropertyOverride(const std::string& _key, const std::st
Box::Box() Box::Box()
: mSpacing(4) : mSpacing(4)
, mPadding(0)
, mAutoResize(false)
{ {
} }
void Box::setPropertyOverride(const std::string& _key, const std::string& _value)
{
if (_key == "Spacing")
{
mSpacing = MyGUI::utility::parseValue<int>(_value);
}
}
void Box::notifyChildrenSizeChanged () void Box::notifyChildrenSizeChanged ()
{ {
align(); align();
} }
void Box::_setPropertyImpl(const std::string& _key, const std::string& _value)
{
if (_key == "Spacing")
mSpacing = MyGUI::utility::parseValue<int>(_value);
else if (_key == "Padding")
mPadding = MyGUI::utility::parseValue<int>(_value);
else if (_key == "AutoResize")
mAutoResize = MyGUI::utility::parseValue<bool>(_value);
}
void HBox::align () void HBox::align ()
{ {
unsigned int count = getChildCount (); unsigned int count = getChildCount ();
size_t h_stretched_count = 0; size_t h_stretched_count = 0;
int total_width = 0; int total_width = 0;
int total_height = 0;
std::vector< std::pair<MyGUI::IntSize, bool> > sizes; std::vector< std::pair<MyGUI::IntSize, bool> > sizes;
for (unsigned int i = 0; i < count; ++i) for (unsigned int i = 0; i < count; ++i)
@ -904,28 +907,43 @@ void HBox::align ()
{ {
sizes.push_back(std::make_pair(aw->getRequestedSize (), hstretch)); sizes.push_back(std::make_pair(aw->getRequestedSize (), hstretch));
total_width += aw->getRequestedSize ().width; total_width += aw->getRequestedSize ().width;
total_height = std::max(total_height, aw->getRequestedSize ().height);
} }
else else
{ {
if (!hstretch) h_stretched_count ++; sizes.push_back (std::make_pair(w->getSize(), hstretch));
sizes.push_back (std::make_pair(MyGUI::IntSize(0,0), true)); total_width += w->getSize().width;
} }
if (i != count-1) if (i != count-1)
total_width += mSpacing; total_width += mSpacing;
} }
if (mAutoResize && (total_width+mPadding*2 != getSize().width || total_height+mPadding*2 != getSize().height))
{
setSize(MyGUI::IntSize(total_width+mPadding*2, total_height+mPadding*2));
return;
}
int curX = 0; int curX = 0;
for (unsigned int i = 0; i < count; ++i) for (unsigned int i = 0; i < count; ++i)
{ {
if (i == 0)
curX += mPadding;
MyGUI::Widget* w = getChildAt(i); MyGUI::Widget* w = getChildAt(i);
bool vstretch = w->getUserString ("VStretch") == "true";
int height = vstretch ? total_height : sizes[i].first.height;
MyGUI::IntCoord widgetCoord; MyGUI::IntCoord widgetCoord;
widgetCoord.left = curX; widgetCoord.left = curX;
widgetCoord.top = (getSize().height - sizes[i].first.height) / 2; widgetCoord.top = mPadding + (getSize().height-mPadding*2 - height) / 2;
int width = sizes[i].second ? sizes[i].first.width + (getSize().width - total_width)/h_stretched_count int width = sizes[i].second ? sizes[i].first.width + (getSize().width-mPadding*2 - total_width)/h_stretched_count
: sizes[i].first.width; : sizes[i].first.width;
widgetCoord.width = width; widgetCoord.width = width;
widgetCoord.height = sizes[i].first.height; widgetCoord.height = height;
w->setCoord(widgetCoord); w->setCoord(widgetCoord);
curX += width; curX += width;
@ -934,12 +952,33 @@ void HBox::align ()
} }
} }
void HBox::setPropertyOverride(const std::string& _key, const std::string& _value)
{
Box::_setPropertyImpl (_key, _value);
}
void HBox::setSize (const MyGUI::IntSize& _value) void HBox::setSize (const MyGUI::IntSize& _value)
{ {
MyGUI::Widget::setSize (_value); MyGUI::Widget::setSize (_value);
align(); align();
} }
void HBox::setCoord (const MyGUI::IntCoord& _value)
{
MyGUI::Widget::setCoord (_value);
align();
}
void HBox::onWidgetCreated(MyGUI::Widget* _widget)
{
align();
}
void HBox::onWidgetDestroy(MyGUI::Widget* _widget)
{
align();
}
MyGUI::IntSize HBox::getRequestedSize () MyGUI::IntSize HBox::getRequestedSize ()
{ {
MyGUI::IntSize size(0,0); MyGUI::IntSize size(0,0);
@ -954,6 +993,19 @@ MyGUI::IntSize HBox::getRequestedSize ()
if (i != getChildCount()-1) if (i != getChildCount()-1)
size.width += mSpacing; size.width += mSpacing;
} }
else
{
MyGUI::IntSize requested = getChildAt(i)->getSize ();
size.height = std::max(size.height, requested.height);
if (getChildAt(i)->getUserString("HStretch") != "true")
size.width = size.width + requested.width;
if (i != getChildCount()-1)
size.width += mSpacing;
}
size.height += mPadding*2;
size.width += mPadding*2;
} }
return size; return size;
} }
@ -963,7 +1015,69 @@ MyGUI::IntSize HBox::getRequestedSize ()
void VBox::align () void VBox::align ()
{ {
// not yet implemented unsigned int count = getChildCount ();
size_t v_stretched_count = 0;
int total_height = 0;
int total_width = 0;
std::vector< std::pair<MyGUI::IntSize, bool> > sizes;
for (unsigned int i = 0; i < count; ++i)
{
MyGUI::Widget* w = getChildAt(i);
bool vstretch = w->getUserString ("VStretch") == "true";
v_stretched_count += vstretch;
AutoSizedWidget* aw = dynamic_cast<AutoSizedWidget*>(w);
if (aw)
{
sizes.push_back(std::make_pair(aw->getRequestedSize (), vstretch));
total_height += aw->getRequestedSize ().height;
total_width = std::max(total_width, aw->getRequestedSize ().width);
}
else
{
sizes.push_back (std::make_pair(w->getSize(), vstretch));
total_height += w->getSize().height;
}
if (i != count-1)
total_height += mSpacing;
}
if (mAutoResize && (total_width+mPadding*2 != getSize().width || total_height+mPadding*2 != getSize().height))
{
setSize(MyGUI::IntSize(total_width+mPadding*2, total_height+mPadding*2));
return;
}
int curY = 0;
for (unsigned int i = 0; i < count; ++i)
{
if (i==0)
curY += mPadding;
MyGUI::Widget* w = getChildAt(i);
bool hstretch = w->getUserString ("HStretch") == "true";
int width = hstretch ? total_width : sizes[i].first.width;
MyGUI::IntCoord widgetCoord;
widgetCoord.top = curY;
widgetCoord.left = mPadding + (getSize().width-mPadding*2 - width) / 2;
int height = sizes[i].second ? sizes[i].first.height + (getSize().height-mPadding*2 - total_height)/v_stretched_count
: sizes[i].first.height;
widgetCoord.height = height;
widgetCoord.width = width;
w->setCoord(widgetCoord);
curY += height;
if (i != count-1)
curY += mSpacing;
}
}
void VBox::setPropertyOverride(const std::string& _key, const std::string& _value)
{
Box::_setPropertyImpl (_key, _value);
} }
void VBox::setSize (const MyGUI::IntSize& _value) void VBox::setSize (const MyGUI::IntSize& _value)
@ -972,6 +1086,12 @@ void VBox::setSize (const MyGUI::IntSize& _value)
align(); align();
} }
void VBox::setCoord (const MyGUI::IntCoord& _value)
{
MyGUI::Widget::setCoord (_value);
align();
}
MyGUI::IntSize VBox::getRequestedSize () MyGUI::IntSize VBox::getRequestedSize ()
{ {
MyGUI::IntSize size(0,0); MyGUI::IntSize size(0,0);
@ -986,6 +1106,29 @@ MyGUI::IntSize VBox::getRequestedSize ()
if (i != getChildCount()-1) if (i != getChildCount()-1)
size.height += mSpacing; size.height += mSpacing;
} }
else
{
MyGUI::IntSize requested = getChildAt(i)->getSize ();
size.width = std::max(size.width, requested.width);
if (getChildAt(i)->getUserString("VStretch") != "true")
size.height = size.height + requested.height;
if (i != getChildCount()-1)
size.height += mSpacing;
}
size.height += mPadding*2;
size.width += mPadding*2;
} }
return size; return size;
} }
void VBox::onWidgetCreated(MyGUI::Widget* _widget)
{
align();
}
void VBox::onWidgetDestroy(MyGUI::Widget* _widget)
{
align();
}

@ -357,10 +357,13 @@ namespace MWGui
protected: protected:
virtual void align() = 0; virtual void align() = 0;
virtual void setPropertyOverride(const std::string& _key, const std::string& _value); virtual void _setPropertyImpl(const std::string& _key, const std::string& _value);
int mSpacing; // how much space to put between elements int mSpacing; // how much space to put between elements
int mPadding; // outer padding
bool mAutoResize; // auto resize the box so that it exactly fits all elements
}; };
class HBox : public Box, public MyGUI::Widget class HBox : public Box, public MyGUI::Widget
@ -369,10 +372,16 @@ namespace MWGui
public: public:
virtual void setSize (const MyGUI::IntSize &_value); virtual void setSize (const MyGUI::IntSize &_value);
virtual void setCoord (const MyGUI::IntCoord &_value);
protected: protected:
virtual void align(); virtual void align();
virtual MyGUI::IntSize getRequestedSize(); virtual MyGUI::IntSize getRequestedSize();
virtual void setPropertyOverride(const std::string& _key, const std::string& _value);
virtual void onWidgetCreated(MyGUI::Widget* _widget);
virtual void onWidgetDestroy(MyGUI::Widget* _widget);
}; };
class VBox : public Box, public MyGUI::Widget class VBox : public Box, public MyGUI::Widget
@ -381,10 +390,16 @@ namespace MWGui
public: public:
virtual void setSize (const MyGUI::IntSize &_value); virtual void setSize (const MyGUI::IntSize &_value);
virtual void setCoord (const MyGUI::IntCoord &_value);
protected: protected:
virtual void align(); virtual void align();
virtual MyGUI::IntSize getRequestedSize(); virtual MyGUI::IntSize getRequestedSize();
virtual void setPropertyOverride(const std::string& _key, const std::string& _value);
virtual void onWidgetCreated(MyGUI::Widget* _widget);
virtual void onWidgetDestroy(MyGUI::Widget* _widget);
}; };
} }
} }

@ -44,6 +44,8 @@
#include "spellwindow.hpp" #include "spellwindow.hpp"
#include "quickkeysmenu.hpp" #include "quickkeysmenu.hpp"
#include "loadingscreen.hpp" #include "loadingscreen.hpp"
#include "levelupdialog.hpp"
#include "waitdialog.hpp"
using namespace MWGui; using namespace MWGui;
@ -70,6 +72,8 @@ WindowManager::WindowManager(
, mSpellWindow(NULL) , mSpellWindow(NULL)
, mLoadingScreen(NULL) , mLoadingScreen(NULL)
, mCharGen(NULL) , mCharGen(NULL)
, mLevelupDialog(NULL)
, mWaitDialog(NULL)
, mPlayerClass() , mPlayerClass()
, mPlayerName() , mPlayerName()
, mPlayerRaceId() , mPlayerRaceId()
@ -84,6 +88,7 @@ WindowManager::WindowManager(
, mGarbageDialogs() , mGarbageDialogs()
, mShown(GW_ALL) , mShown(GW_ALL)
, mAllowed(newGame ? GW_None : GW_ALL) , mAllowed(newGame ? GW_None : GW_ALL)
, mRestAllowed(newGame ? false : true)
, mShowFPSLevel(fpsLevel) , mShowFPSLevel(fpsLevel)
, mFPS(0.0f) , mFPS(0.0f)
, mTriangleCount(0) , mTriangleCount(0)
@ -147,6 +152,8 @@ WindowManager::WindowManager(
mAlchemyWindow = new AlchemyWindow(*this); mAlchemyWindow = new AlchemyWindow(*this);
mSpellWindow = new SpellWindow(*this); mSpellWindow = new SpellWindow(*this);
mQuickKeysMenu = new QuickKeysMenu(*this); mQuickKeysMenu = new QuickKeysMenu(*this);
mLevelupDialog = new LevelupDialog(*this);
mWaitDialog = new WaitDialog(*this);
mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this); mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this);
mLoadingScreen->onResChange (w,h); mLoadingScreen->onResChange (w,h);
@ -200,6 +207,8 @@ WindowManager::~WindowManager()
delete mAlchemyWindow; delete mAlchemyWindow;
delete mSpellWindow; delete mSpellWindow;
delete mLoadingScreen; delete mLoadingScreen;
delete mLevelupDialog;
delete mWaitDialog;
cleanupGarbage(); cleanupGarbage();
@ -247,6 +256,8 @@ void WindowManager::updateVisible()
mAlchemyWindow->setVisible(false); mAlchemyWindow->setVisible(false);
mSpellWindow->setVisible(false); mSpellWindow->setVisible(false);
mQuickKeysMenu->setVisible(false); mQuickKeysMenu->setVisible(false);
mLevelupDialog->setVisible(false);
mWaitDialog->setVisible(false);
mHud->setVisible(true); mHud->setVisible(true);
@ -298,6 +309,16 @@ void WindowManager::updateVisible()
case GM_Alchemy: case GM_Alchemy:
mAlchemyWindow->setVisible(true); mAlchemyWindow->setVisible(true);
break; break;
case GM_Rest:
mWaitDialog->setVisible(true);
break;
case GM_RestBed:
mWaitDialog->setVisible(true);
mWaitDialog->bedActivated();
break;
case GM_Levelup:
mLevelupDialog->setVisible(true);
break;
case GM_Name: case GM_Name:
case GM_Race: case GM_Race:
case GM_Class: case GM_Class:
@ -395,7 +416,7 @@ void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& valu
mPlayerSkillValues[parSkill] = value; mPlayerSkillValues[parSkill] = value;
} }
void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value)
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
mHud->setValue (id, value); mHud->setValue (id, value);
@ -532,6 +553,8 @@ void WindowManager::onFrame (float frameDuration)
mStatsWindow->onFrame(); mStatsWindow->onFrame();
mWaitDialog->onFrame(frameDuration);
mHud->onFrame(frameDuration); mHud->onFrame(frameDuration);
mDialogueWindow->checkReferenceAvailable(); mDialogueWindow->checkReferenceAvailable();
@ -547,7 +570,10 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
{ {
std::string name; std::string name;
if (cell->cell->mName != "") if (cell->cell->mName != "")
{
name = cell->cell->mName; name = cell->cell->mName;
mMap->addVisitedLocation (name, cell->cell->getGridX (), cell->cell->getGridY ());
}
else else
{ {
const ESM::Region* region = MWBase::Environment::get().getWorld()->getStore().regions.search(cell->cell->mRegion); const ESM::Region* region = MWBase::Environment::get().getWorld()->getStore().regions.search(cell->cell->mRegion);
@ -923,3 +949,13 @@ void WindowManager::loadingDone ()
{ {
mLoadingScreen->loadingDone (); mLoadingScreen->loadingDone ();
} }
bool WindowManager::getPlayerSleeping ()
{
return mWaitDialog->getSleeping();
}
void WindowManager::addVisitedLocation(const std::string& name, int x, int y)
{
mMap->addVisitedLocation (name, x, y);
}

@ -62,6 +62,8 @@ namespace MWGui
class AlchemyWindow; class AlchemyWindow;
class QuickKeysMenu; class QuickKeysMenu;
class LoadingScreen; class LoadingScreen;
class LevelupDialog;
class WaitDialog;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -117,7 +119,7 @@ namespace MWGui
///< Set value for the given ID. ///< Set value for the given ID.
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value); virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value); virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value);
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
virtual void setValue (const std::string& id, const std::string& value); virtual void setValue (const std::string& id, const std::string& value);
virtual void setValue (const std::string& id, int value); virtual void setValue (const std::string& id, int value);
@ -170,6 +172,8 @@ namespace MWGui
virtual void allowMouse(); virtual void allowMouse();
virtual void notifyInputActionBound(); virtual void notifyInputActionBound();
virtual void addVisitedLocation(const std::string& name, int x, int y);
virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted.
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons); virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons);
@ -199,6 +203,11 @@ namespace MWGui
virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total); virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total);
virtual void loadingDone(); virtual void loadingDone();
virtual void enableRest() { mRestAllowed = true; }
virtual bool getRestEnabled() { return mRestAllowed; }
virtual bool getPlayerSleeping();
private: private:
OEngine::GUI::MyGUIManager *mGuiManager; OEngine::GUI::MyGUIManager *mGuiManager;
HUD *mHud; HUD *mHud;
@ -224,6 +233,8 @@ namespace MWGui
SpellWindow* mSpellWindow; SpellWindow* mSpellWindow;
QuickKeysMenu* mQuickKeysMenu; QuickKeysMenu* mQuickKeysMenu;
LoadingScreen* mLoadingScreen; LoadingScreen* mLoadingScreen;
LevelupDialog* mLevelupDialog;
WaitDialog* mWaitDialog;
CharacterCreation* mCharGen; CharacterCreation* mCharGen;
@ -241,7 +252,7 @@ namespace MWGui
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes; std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
SkillList mPlayerMajorSkills, mPlayerMinorSkills; SkillList mPlayerMajorSkills, mPlayerMinorSkills;
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues; std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
MWMechanics::DynamicStat<int> mPlayerHealth, mPlayerMagicka, mPlayerFatigue; MWMechanics::DynamicStat<float> mPlayerHealth, mPlayerMagicka, mPlayerFatigue;
MyGUI::Gui *mGui; // Gui MyGUI::Gui *mGui; // Gui
@ -258,6 +269,8 @@ namespace MWGui
allow() and disableAll(). allow() and disableAll().
*/ */
GuiWindow mAllowed; GuiWindow mAllowed;
// is the rest window allowed?
bool mRestAllowed;
void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings

@ -190,6 +190,9 @@ namespace MWInput
case A_ToggleWeapon: case A_ToggleWeapon:
toggleWeapon (); toggleWeapon ();
break; break;
case A_Rest:
rest();
break;
case A_ToggleSpell: case A_ToggleSpell:
toggleSpell (); toggleSpell ();
break; break;
@ -543,6 +546,15 @@ namespace MWInput
} }
} }
void InputManager::rest()
{
if (!mWindows.getRestEnabled () || mWindows.isGuiMode ())
return;
/// \todo check if resting is currently allowed (enemies nearby?)
mWindows.pushGuiMode (MWGui::GM_Rest);
}
void InputManager::screenshot() void InputManager::screenshot()
{ {
mEngine.screenshot(); mEngine.screenshot();

@ -168,6 +168,7 @@ namespace MWInput
void toggleWalking(); void toggleWalking();
void toggleAutoMove(); void toggleAutoMove();
void exitNow(); void exitNow();
void rest();
void quickKey (int index); void quickKey (int index);
void showQuickKeysMenu(); void showQuickKeysMenu();

@ -68,7 +68,7 @@ namespace MWMechanics
creatureStats.getMagicEffects().get (EffectKey (84)).mMagnitude * 0.1 + 0.5; creatureStats.getMagicEffects().get (EffectKey (84)).mMagnitude * 0.1 + 0.5;
creatureStats.getHealth().setBase( creatureStats.getHealth().setBase(
static_cast<int> (0.5 * (strength + endurance))); static_cast<int> (0.5 * (strength + endurance)) + creatureStats.getLevelHealthBonus ());
creatureStats.getMagicka().setBase( creatureStats.getMagicka().setBase(
static_cast<int> (intelligence + magickaFactor * intelligence)); static_cast<int> (intelligence + magickaFactor * intelligence));

@ -9,6 +9,21 @@
namespace MWMechanics namespace MWMechanics
{ {
CreatureStats::CreatureStats()
: mLevelHealthBonus(0.f)
{
}
void CreatureStats::increaseLevelHealthBonus (float value)
{
mLevelHealthBonus += value;
}
float CreatureStats::getLevelHealthBonus () const
{
return mLevelHealthBonus;
}
const AiSequence& CreatureStats::getAiSequence() const const AiSequence& CreatureStats::getAiSequence() const
{ {
return mAiSequence; return mAiSequence;
@ -40,17 +55,17 @@ namespace MWMechanics
return mAttributes[index]; return mAttributes[index];
} }
const DynamicStat<int> &CreatureStats::getHealth() const const DynamicStat<float> &CreatureStats::getHealth() const
{ {
return mDynamic[0]; return mDynamic[0];
} }
const DynamicStat<int> &CreatureStats::getMagicka() const const DynamicStat<float> &CreatureStats::getMagicka() const
{ {
return mDynamic[1]; return mDynamic[1];
} }
const DynamicStat<int> &CreatureStats::getFatigue() const const DynamicStat<float> &CreatureStats::getFatigue() const
{ {
return mDynamic[2]; return mDynamic[2];
} }
@ -103,22 +118,22 @@ namespace MWMechanics
return mAttributes[index]; return mAttributes[index];
} }
DynamicStat<int> &CreatureStats::getHealth() DynamicStat<float> &CreatureStats::getHealth()
{ {
return mDynamic[0]; return mDynamic[0];
} }
DynamicStat<int> &CreatureStats::getMagicka() DynamicStat<float> &CreatureStats::getMagicka()
{ {
return mDynamic[1]; return mDynamic[1];
} }
DynamicStat<int> &CreatureStats::getFatigue() DynamicStat<float> &CreatureStats::getFatigue()
{ {
return mDynamic[2]; return mDynamic[2];
} }
DynamicStat<int> &CreatureStats::getDynamic(int index) DynamicStat<float> &CreatureStats::getDynamic(int index)
{ {
if (index < 0 || index > 2) { if (index < 0 || index > 2) {
throw std::runtime_error("dynamic stat index is out of range"); throw std::runtime_error("dynamic stat index is out of range");
@ -154,17 +169,17 @@ namespace MWMechanics
mAttributes[index] = value; mAttributes[index] = value;
} }
void CreatureStats::setHealth(const DynamicStat<int> &value) void CreatureStats::setHealth(const DynamicStat<float> &value)
{ {
mDynamic[0] = value; mDynamic[0] = value;
} }
void CreatureStats::setMagicka(const DynamicStat<int> &value) void CreatureStats::setMagicka(const DynamicStat<float> &value)
{ {
mDynamic[1] = value; mDynamic[1] = value;
} }
void CreatureStats::setFatigue(const DynamicStat<int> &value) void CreatureStats::setFatigue(const DynamicStat<float> &value)
{ {
mDynamic[2] = value; mDynamic[2] = value;
} }

@ -19,7 +19,7 @@ namespace MWMechanics
class CreatureStats class CreatureStats
{ {
Stat<int> mAttributes[8]; Stat<int> mAttributes[8];
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
int mLevel; int mLevel;
Spells mSpells; Spells mSpells;
ActiveSpells mActiveSpells; ActiveSpells mActiveSpells;
@ -30,15 +30,18 @@ namespace MWMechanics
int mAlarm; int mAlarm;
AiSequence mAiSequence; AiSequence mAiSequence;
float mLevelHealthBonus;
public: public:
CreatureStats();
const Stat<int> & getAttribute(int index) const; const Stat<int> & getAttribute(int index) const;
const DynamicStat<int> & getHealth() const; const DynamicStat<float> & getHealth() const;
const DynamicStat<int> & getMagicka() const; const DynamicStat<float> & getMagicka() const;
const DynamicStat<int> & getFatigue() const; const DynamicStat<float> & getFatigue() const;
const Spells & getSpells() const; const Spells & getSpells() const;
@ -59,13 +62,13 @@ namespace MWMechanics
Stat<int> & getAttribute(int index); Stat<int> & getAttribute(int index);
DynamicStat<int> & getHealth(); DynamicStat<float> & getHealth();
DynamicStat<int> & getMagicka(); DynamicStat<float> & getMagicka();
DynamicStat<int> & getFatigue(); DynamicStat<float> & getFatigue();
DynamicStat<int> & getDynamic(int index); DynamicStat<float> & getDynamic(int index);
Spells & getSpells(); Spells & getSpells();
@ -76,11 +79,11 @@ namespace MWMechanics
void setAttribute(int index, const Stat<int> &value); void setAttribute(int index, const Stat<int> &value);
void setHealth(const DynamicStat<int> &value); void setHealth(const DynamicStat<float> &value);
void setMagicka(const DynamicStat<int> &value); void setMagicka(const DynamicStat<float> &value);
void setFatigue(const DynamicStat<int> &value); void setFatigue(const DynamicStat<float> &value);
void setSpells(const Spells &spells); void setSpells(const Spells &spells);
@ -104,6 +107,10 @@ namespace MWMechanics
float getFatigueTerm() const; float getFatigueTerm() const;
///< Return effective fatigue ///< Return effective fatigue
// small hack to allow the fact that Health permanently increases by 10% of endurance on each level up
void increaseLevelHealthBonus(float value);
float getLevelHealthBonus() const;
}; };
} }

@ -4,6 +4,8 @@
#include <cmath> #include <cmath>
#include <stdexcept> #include <stdexcept>
#include <boost/format.hpp>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include <components/esm/loadclas.hpp> #include <components/esm/loadclas.hpp>
#include <components/esm/loadgmst.hpp> #include <components/esm/loadgmst.hpp>
@ -12,10 +14,17 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
MWMechanics::NpcStats::NpcStats() MWMechanics::NpcStats::NpcStats()
: mMovementFlags (0), mDrawState (DrawState_Nothing) : mMovementFlags (0), mDrawState (DrawState_Nothing)
{} , mLevelProgress(0)
{
mSkillIncreases.resize (ESM::Attribute::Length);
for (int i=0; i<ESM::Attribute::Length; ++i)
mSkillIncreases[i] = 0;
}
MWMechanics::DrawState_ MWMechanics::NpcStats::getDrawState() const MWMechanics::DrawState_ MWMechanics::NpcStats::getDrawState() const
{ {
@ -122,7 +131,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
throw std::runtime_error ("invalid skill specialisation factor"); throw std::runtime_error ("invalid skill specialisation factor");
} }
return 1.0 / (level +1) * (1.0 / skillFactor) * typeFactor * specialisationFactor; return 1.0 / (level +1) * (1.0 / (skillFactor)) * typeFactor * specialisationFactor;
} }
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType) void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType)
@ -134,7 +143,87 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
base += getSkillGain (skillIndex, class_, usageType); base += getSkillGain (skillIndex, class_, usageType);
if (static_cast<int> (base)!=level) if (static_cast<int> (base)!=level)
{
// skill leveled up
increaseSkill(skillIndex, class_, false);
}
else
getSkill (skillIndex).setBase (base);
}
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress)
{
float base = getSkill (skillIndex).getBase();
int level = static_cast<int> (base);
if (level >= 100)
return;
if (preserveProgress)
base += 1;
else
base = level+1; base = level+1;
// if this is a major or minor skill of the class, increase level progress
bool levelProgress = false;
for (int i=0; i<2; ++i)
for (int j=0; j<5; ++j)
{
int skill = class_.mData.mSkills[j][i];
if (skill == skillIndex)
levelProgress = true;
}
mLevelProgress += levelProgress;
// check the attribute this skill belongs to
const ESM::Skill* skill = MWBase::Environment::get().getWorld ()->getStore ().skills.find(skillIndex);
++mSkillIncreases[skill->mData.mAttribute];
// Play sound & skill progress notification
/// \todo check if character is the player, if levelling is ever implemented for NPCs
MWBase::Environment::get().getSoundManager ()->playSound ("skillraise", 1, 1);
std::stringstream message;
message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""))
% std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}")
% base;
MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), std::vector<std::string>());
if (mLevelProgress >= 10)
{
// levelup is possible now
MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}", std::vector<std::string>());
}
getSkill (skillIndex).setBase (base); getSkill (skillIndex).setBase (base);
} }
int MWMechanics::NpcStats::getLevelProgress () const
{
return mLevelProgress;
}
void MWMechanics::NpcStats::levelUp()
{
mLevelProgress -= 10;
for (int i=0; i<ESM::Attribute::Length; ++i)
mSkillIncreases[i] = 0;
}
int MWMechanics::NpcStats::getLevelupAttributeMultiplier(int attribute) const
{
// Source: http://www.uesp.net/wiki/Morrowind:Level#How_to_Level_Up
int num = mSkillIncreases[attribute];
if (num <= 1)
return 1;
else if (num <= 4)
return 2;
else if (num <= 7)
return 3;
else if (num <= 9)
return 4;
else
return 5;
}

@ -4,6 +4,7 @@
#include <map> #include <map>
#include <set> #include <set>
#include <string> #include <string>
#include <vector>
#include "stat.hpp" #include "stat.hpp"
#include "drawstate.hpp" #include "drawstate.hpp"
@ -45,6 +46,10 @@ namespace MWMechanics
unsigned int mMovementFlags; unsigned int mMovementFlags;
Stat<float> mSkill[27]; Stat<float> mSkill[27];
int mLevelProgress; // 0-10
std::vector<int> mSkillIncreases; // number of skill increases for each attribute
public: public:
NpcStats(); NpcStats();
@ -73,6 +78,14 @@ namespace MWMechanics
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1); void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1);
///< Increase skill by usage. ///< Increase skill by usage.
void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress);
int getLevelProgress() const;
int getLevelupAttributeMultiplier(int attribute) const;
void levelUp();
}; };
} }

@ -72,6 +72,8 @@ namespace MWRender
CharacterPreview::~CharacterPreview () CharacterPreview::~CharacterPreview ()
{ {
Ogre::TextureManager::getSingleton().remove(mName); Ogre::TextureManager::getSingleton().remove(mName);
mSceneMgr->destroyCamera (mName);
delete mAnimation;
} }

@ -0,0 +1,148 @@
#include "globalmap.hpp"
#include <boost/filesystem.hpp>
#include <OgreImage.h>
#include <OgreTextureManager.h>
#include <OgreColourValue.h>
#include <OgreHardwareVertexBuffer.h>
#include <OgreRoot.h>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include <components/esm_store/store.hpp>
#include <components/esm_store/reclists.hpp>
namespace MWRender
{
GlobalMap::GlobalMap(const std::string &cacheDir)
: mCacheDir(cacheDir)
{
}
void GlobalMap::render ()
{
Ogre::TexturePtr tex;
if (!boost::filesystem::exists(mCacheDir + "/GlobalMap.png"))
{
int cellSize = 24;
Ogre::Image image;
int width = cellSize*61;
int height = cellSize*61;
Ogre::uchar data[width * height * 3];
for (int x = -30; x <= 30; ++x)
{
for (int y = -30; y <= 30; ++y)
{
ESM::Land* land = MWBase::Environment::get().getWorld ()->getStore ().lands.search (x,y);
if (land)
{
if (!land->isDataLoaded(ESM::Land::DATA_VHGT))
{
land->loadData(ESM::Land::DATA_VHGT);
}
}
for (int cellY=0; cellY<cellSize; ++cellY)
{
for (int cellX=0; cellX<cellSize; ++cellX)
{
int vertexX = float(cellX)/float(cellSize) * ESM::Land::LAND_SIZE;
int vertexY = float(cellY)/float(cellSize) * ESM::Land::LAND_SIZE;
int texelX = (x+30) * cellSize + cellX;
int texelY = (height-1) - ((y+30) * cellSize + cellY);
Ogre::ColourValue waterShallowColour(0.15, 0.2, 0.19);
Ogre::ColourValue waterDeepColour(0.1, 0.14, 0.13);
Ogre::ColourValue groundColour(0.254, 0.19, 0.13);
Ogre::ColourValue mountainColour(0.05, 0.05, 0.05);
Ogre::ColourValue hillColour(0.16, 0.12, 0.08);
float mountainHeight = 15000.f;
float hillHeight = 2500.f;
unsigned char r,g,b;
if (land)
{
float landHeight = land->mLandData->mHeights[vertexY * ESM::Land::LAND_SIZE + vertexX];
if (landHeight >= 0)
{
if (landHeight >= hillHeight)
{
float factor = std::min(1.f, float(landHeight-hillHeight)/mountainHeight);
r = (hillColour.r * (1-factor) + mountainColour.r * factor) * 255;
g = (hillColour.g * (1-factor) + mountainColour.g * factor) * 255;
b = (hillColour.b * (1-factor) + mountainColour.b * factor) * 255;
}
else
{
float factor = std::min(1.f, float(landHeight)/hillHeight);
r = (groundColour.r * (1-factor) + hillColour.r * factor) * 255;
g = (groundColour.g * (1-factor) + hillColour.g * factor) * 255;
b = (groundColour.b * (1-factor) + hillColour.b * factor) * 255;
}
}
else
{
if (landHeight >= -100)
{
float factor = std::min(1.f, -1*landHeight/100.f);
r = (((waterShallowColour+groundColour)/2).r * (1-factor) + waterShallowColour.r * factor) * 255;
g = (((waterShallowColour+groundColour)/2).g * (1-factor) + waterShallowColour.g * factor) * 255;
b = (((waterShallowColour+groundColour)/2).b * (1-factor) + waterShallowColour.b * factor) * 255;
}
else
{
float factor = std::min(1.f, -1*(landHeight-100)/1000.f);
r = (waterShallowColour.r * (1-factor) + waterDeepColour.r * factor) * 255;
g = (waterShallowColour.g * (1-factor) + waterDeepColour.g * factor) * 255;
b = (waterShallowColour.b * (1-factor) + waterDeepColour.b * factor) * 255;
}
}
}
else
{
r = waterDeepColour.r * 255;
g = waterDeepColour.g * 255;
b = waterDeepColour.b * 255;
}
data[texelY * height * 3 + texelX * 3] = r;
data[texelY * height * 3 + texelX * 3+1] = g;
data[texelY * height * 3 + texelX * 3+2] = b;
}
}
}
}
image.loadDynamicImage (data, width, height, Ogre::PF_B8G8R8);
image.save (mCacheDir + "/GlobalMap.png");
tex = Ogre::TextureManager::getSingleton ().createManual ("GlobalMap.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, width, height, 0, Ogre::PF_B8G8R8, Ogre::TU_DEFAULT);
tex->loadImage(image);
}
else
tex = Ogre::TextureManager::getSingleton ().getByName ("GlobalMap.png");
tex->load();
}
}

@ -0,0 +1,23 @@
#ifndef _GAME_RENDER_GLOBALMAP_H
#define _GAME_RENDER_GLOBALMAP_H
#include <string>
namespace MWRender
{
class GlobalMap
{
public:
GlobalMap(const std::string& cacheDir);
void render();
private:
std::string mCacheDir;
};
}
#endif

@ -77,12 +77,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
bodyRaceID = "b_n_"+ref->base->mRace; bodyRaceID = "b_n_"+ref->base->mRace;
std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower);
/*std::cout << "Race: " << ref->base->race ;
if(female)
std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n";
else
std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n";
*/
mInsert = node; mInsert = node;
assert(mInsert); assert(mInsert);

@ -35,6 +35,7 @@
#include "compositors.hpp" #include "compositors.hpp"
#include "npcanimation.hpp" #include "npcanimation.hpp"
#include "externalrendering.hpp" #include "externalrendering.hpp"
#include "globalmap.hpp"
using namespace MWRender; using namespace MWRender;
using namespace Ogre; using namespace Ogre;
@ -43,7 +44,7 @@ namespace MWRender {
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir,
const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine) const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine)
:mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine) : mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine)
{ {
// select best shader mode // select best shader mode
bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos); bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos);
@ -100,7 +101,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 );
// Load resources ResourceGroupManager::getSingleton ().declareResource ("GlobalMap.png", "Texture", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// causes light flicker in opengl when moving.. // causes light flicker in opengl when moving..
@ -129,6 +131,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0))); sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty<sh::Vector3>(new sh::Vector3(0.5, -0.8, 0.2))); sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty<sh::Vector3>(new sh::Vector3(0.5, -0.8, 0.2)));
sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty<sh::Vector2>(new sh::Vector2(1, 0.6))); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty<sh::Vector2>(new sh::Vector2(1, 0.6)));
sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(
Settings::Manager::getFloat ("gamma", "Video"))));
applyCompositors(); applyCompositors();
@ -160,6 +164,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mDebugging = new Debugging(mMwRoot, engine); mDebugging = new Debugging(mMwRoot, engine);
mLocalMap = new MWRender::LocalMap(&mRendering, this); mLocalMap = new MWRender::LocalMap(&mRendering, this);
mGlobalMap = new GlobalMap(cacheDir.string());
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
} }
@ -176,6 +182,7 @@ RenderingManager::~RenderingManager ()
delete mOcclusionQuery; delete mOcclusionQuery;
delete mCompositors; delete mCompositors;
delete mWater; delete mWater;
delete mGlobalMap;
} }
MWRender::SkyManager* RenderingManager::getSkyManager() MWRender::SkyManager* RenderingManager::getSkyManager()
@ -275,13 +282,15 @@ RenderingManager::rotateObject(
float *f = ptr.getRefData().getPosition().rot; float *f = ptr.getRefData().getPosition().rot;
rot.x += f[0], rot.y += f[1], rot.z += f[2]; rot.x += f[0], rot.y += f[1], rot.z += f[2];
} }
if (!isPlayer && isActive) { if (!isPlayer && isActive) {
Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y); Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z); Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z);
ptr.getRefData().getBaseNode()->setOrientation(xr * yr * zr); ptr.getRefData().getBaseNode()->setOrientation(xr * yr * zr);
} }
return force; return force;
} }
@ -747,6 +756,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects"));
mObjects.rebuildStaticGeometry (); mObjects.rebuildStaticGeometry ();
} }
else if (it->second == "gamma" && it->first == "Video")
{
sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(
Settings::Manager::getFloat ("gamma", "Video"))));
}
else if (it->second == "shader mode" && it->first == "General") else if (it->second == "shader mode" && it->first == "General")
{ {
sh::Language lang; sh::Language lang;
@ -887,4 +901,9 @@ void RenderingManager::setupExternalRendering (MWRender::ExternalRendering& rend
rendering.setup (mRendering.getScene()); rendering.setup (mRendering.getScene());
} }
void RenderingManager::renderGlobalMap ()
{
mGlobalMap->render ();
}
} // namespace } // namespace

@ -44,6 +44,7 @@ namespace MWRender
class Water; class Water;
class Compositors; class Compositors;
class ExternalRendering; class ExternalRendering;
class GlobalMap;
class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener { class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener {
@ -194,6 +195,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
void setupExternalRendering (MWRender::ExternalRendering& rendering); void setupExternalRendering (MWRender::ExternalRendering& rendering);
void renderGlobalMap();
protected: protected:
virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowResized(Ogre::RenderWindow* rw);
virtual void windowClosed(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw);
@ -218,6 +221,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
MWRender::Water *mWater; MWRender::Water *mWater;
GlobalMap* mGlobalMap;
OEngine::Render::OgreRenderer &mRendering; OEngine::Render::OgreRenderer &mRendering;
MWRender::Objects mObjects; MWRender::Objects mObjects;

@ -31,7 +31,7 @@ op 0x2000e: PCGetRank implicit
op 0x2000f: PCGetRank explicit op 0x2000f: PCGetRank explicit
op 0x20010: AiWander op 0x20010: AiWander
op 0x20011: AiWander, explicit reference op 0x20011: AiWander, explicit reference
opcodes 0x20012-0x3ffff unused op s 0x20012-0x3ffff unused
Segment 4: Segment 4:
(not implemented yet) (not implemented yet)
@ -183,4 +183,27 @@ op 0x2000172: GetStartingAngle
op 0x2000173: GetStartingAngle, explicit reference op 0x2000173: GetStartingAngle, explicit reference
op 0x2000174: ToggleVanityMode op 0x2000174: ToggleVanityMode
op 0x2000175-0x200018B: Get controls disabled op 0x2000175-0x200018B: Get controls disabled
opcodes 0x200018C-0x3ffffff unused op 0x200018C: GetLevel
op 0x200018D: GetLevel, explicit reference
op 0x200018E: SetLevel
op 0x200018F: SetLevel, explicit reference
op 0x2000190: GetPos
op 0x2000191: GetPosExplicit
op 0x2000192: SetPos
op 0x2000193: SetPosExplicit
op 0x2000194: GetStartingPos
op 0x2000195: GetStartingPosExplicit
op 0x2000196: Position
op 0x2000197: Position Explicit
op 0x2000198: PositionCell
op 0x2000199: PositionCell Explicit
op 0x200019a: PlaceItemCell
op 0x200019b: PlaceItem
op 0x200019c: PlaceAtPc
op 0x200019d: PlaceAtMe
op 0x200019e: PlaceAtMe Explicit
op 0x200019f: GetPcSleep
op 0x20001a0: ShowMap
op 0x20001a1: FillMap
opcodes 0x20001a2-0x3ffffff unused

@ -1,12 +1,17 @@
#include "guiextensions.hpp" #include "guiextensions.hpp"
#include <boost/algorithm/string.hpp>
#include <components/compiler/extensions.hpp> #include <components/compiler/extensions.hpp>
#include <components/interpreter/interpreter.hpp> #include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp> #include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp> #include <components/interpreter/opcodes.hpp>
#include <components/esm_store/store.hpp>
#include <components/esm_store/reclists.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -30,6 +35,16 @@ namespace MWScript
} }
}; };
class OpEnableRest : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWBase::Environment::get().getWindowManager()->enableRest();
}
};
class OpShowDialogue : public Interpreter::Opcode0 class OpShowDialogue : public Interpreter::Opcode0
{ {
MWGui::GuiMode mDialogue; MWGui::GuiMode mDialogue;
@ -81,6 +96,47 @@ namespace MWScript
} }
}; };
class OpShowMap : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
std::string cell = (runtime.getStringLiteral (runtime[0].mInteger));
boost::algorithm::to_lower(cell);
runtime.pop();
// "Will match complete or partial cells, so ShowMap, "Vivec" will show cells Vivec and Vivec, Fred's House as well."
// http://www.uesp.net/wiki/Tes3Mod:ShowMap
const ESMS::CellList::ExtCells& extCells = MWBase::Environment::get().getWorld ()->getStore ().cells.extCells;
for (ESMS::CellList::ExtCells::const_iterator it = extCells.begin(); it != extCells.end(); ++it)
{
std::string name = it->second->mName;
boost::algorithm::to_lower(name);
if (name.find(cell) != std::string::npos)
MWBase::Environment::get().getWindowManager()->addVisitedLocation (it->second->mName, it->first.first, it->first.second);
}
}
};
class OpFillMap : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
const ESMS::CellList::ExtCells& extCells = MWBase::Environment::get().getWorld ()->getStore ().cells.extCells;
for (ESMS::CellList::ExtCells::const_iterator it = extCells.begin(); it != extCells.end(); ++it)
{
std::string name = it->second->mName;
if (name != "")
MWBase::Environment::get().getWindowManager()->addVisitedLocation (name, it->first.first, it->first.second);
}
}
};
const int opcodeEnableBirthMenu = 0x200000e; const int opcodeEnableBirthMenu = 0x200000e;
const int opcodeEnableClassMenu = 0x200000f; const int opcodeEnableClassMenu = 0x200000f;
const int opcodeEnableNameMenu = 0x2000010; const int opcodeEnableNameMenu = 0x2000010;
@ -95,6 +151,8 @@ namespace MWScript
const int opcodeGetButtonPressed = 0x2000137; const int opcodeGetButtonPressed = 0x2000137;
const int opcodeToggleFogOfWar = 0x2000145; const int opcodeToggleFogOfWar = 0x2000145;
const int opcodeToggleFullHelp = 0x2000151; const int opcodeToggleFullHelp = 0x2000151;
const int opcodeShowMap = 0x20001a0;
const int opcodeFillMap = 0x20001a1;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -122,6 +180,9 @@ opcodeEnableStatsReviewMenu);
extensions.registerInstruction ("togglefullhelp", "", opcodeToggleFullHelp); extensions.registerInstruction ("togglefullhelp", "", opcodeToggleFullHelp);
extensions.registerInstruction ("tfh", "", opcodeToggleFullHelp); extensions.registerInstruction ("tfh", "", opcodeToggleFullHelp);
extensions.registerInstruction ("showmap", "S", opcodeShowMap);
extensions.registerInstruction ("fillmap", "", opcodeFillMap);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -146,21 +207,20 @@ opcodeEnableStatsReviewMenu);
interpreter.installSegment5 (opcodeEnableStatsMenu, interpreter.installSegment5 (opcodeEnableStatsMenu,
new OpEnableWindow (MWGui::GW_Stats)); new OpEnableWindow (MWGui::GW_Stats));
/* Not done yet. Enabling rest mode is not really a gui
issue, it's a gameplay issue.
interpreter.installSegment5 (opcodeEnableRest, interpreter.installSegment5 (opcodeEnableRest,
new OpEnableDialogue (MWGui::GM_Rest)); new OpEnableRest ());
*/
interpreter.installSegment5 (opcodeShowRestMenu, interpreter.installSegment5 (opcodeShowRestMenu,
new OpShowDialogue (MWGui::GM_Rest)); new OpShowDialogue (MWGui::GM_RestBed));
interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed); interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed);
interpreter.installSegment5 (opcodeToggleFogOfWar, new OpToggleFogOfWar); interpreter.installSegment5 (opcodeToggleFogOfWar, new OpToggleFogOfWar);
interpreter.installSegment5 (opcodeToggleFullHelp, new OpToggleFullHelp); interpreter.installSegment5 (opcodeToggleFullHelp, new OpToggleFullHelp);
interpreter.installSegment5 (opcodeShowMap, new OpShowMap);
interpreter.installSegment5 (opcodeFillMap, new OpFillMap);
} }
} }
} }

@ -10,6 +10,7 @@
#include <components/interpreter/opcodes.hpp> #include <components/interpreter/opcodes.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
@ -20,6 +21,16 @@ namespace MWScript
{ {
namespace Misc namespace Misc
{ {
class OpGetPcSleep : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
runtime.push (MWBase::Environment::get().getWindowManager ()->getPlayerSleeping());
}
};
class OpXBox : public Interpreter::Opcode0 class OpXBox : public Interpreter::Opcode0
{ {
public: public:
@ -249,6 +260,7 @@ namespace MWScript
const int opcodeTogglePathgrid = 0x2000146; const int opcodeTogglePathgrid = 0x2000146;
const int opcodeDontSaveObject = 0x2000153; const int opcodeDontSaveObject = 0x2000153;
const int opcodeToggleVanityMode = 0x2000174; const int opcodeToggleVanityMode = 0x2000174;
const int opcodeGetPcSleep = 0x200019f;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -273,6 +285,7 @@ namespace MWScript
extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject); extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject);
extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode); extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode);
extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode); extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode);
extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -293,6 +306,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater);
interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject); interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject);
interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode); interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode);
interpreter.installSegment5 (opcodeGetPcSleep, new OpGetPcSleep);
} }
} }
} }

@ -32,6 +32,42 @@ namespace MWScript
{ {
namespace Stats namespace Stats
{ {
template<class R>
class OpGetLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value =
MWWorld::Class::get (ptr)
.getCreatureStats (ptr)
.getLevel();
runtime.push (value);
}
};
template<class R>
class OpSetLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWWorld::Class::get (ptr)
.getCreatureStats (ptr)
.setLevel(value);
}
};
template<class R> template<class R>
class OpGetAttribute : public Interpreter::Opcode0 class OpGetAttribute : public Interpreter::Opcode0
{ {
@ -592,6 +628,11 @@ namespace MWScript
const int opcodeModDisposition = 0x200014d; const int opcodeModDisposition = 0x200014d;
const int opcodeModDispositionExplicit = 0x200014e; const int opcodeModDispositionExplicit = 0x200014e;
const int opcodeGetLevel = 0x200018c;
const int opcodeGetLevelExplicit = 0x200018d;
const int opcodeSetLevel = 0x200018e;
const int opcodeSetLevelExplicit = 0x200018f;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
static const char *attributes[numberOfAttributes] = static const char *attributes[numberOfAttributes] =
@ -674,6 +715,9 @@ namespace MWScript
extensions.registerInstruction("moddisposition","l",opcodeModDisposition, extensions.registerInstruction("moddisposition","l",opcodeModDisposition,
opcodeModDispositionExplicit); opcodeModDispositionExplicit);
extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit); extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit);
extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit);
extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -745,6 +789,12 @@ namespace MWScript
interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>); interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>);
interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>); interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>);
interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>); interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>);
interpreter.installSegment5 (opcodeGetLevel, new OpGetLevel<ImplicitRef>);
interpreter.installSegment5 (opcodeGetLevelExplicit, new OpGetLevel<ExplicitRef>);
interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel<ImplicitRef>);
interpreter.installSegment5 (opcodeSetLevelExplicit, new OpSetLevel<ExplicitRef>);
} }
} }
} }

@ -1,6 +1,10 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <OgreMath.h>
#include <OgreSceneNode.h>
#include <components/esm_store/store.hpp> #include <components/esm_store/store.hpp>
#include <components/esm/loadcell.hpp>
#include <components/compiler/extensions.hpp> #include <components/compiler/extensions.hpp>
@ -11,10 +15,11 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "interpretercontext.hpp" #include "interpretercontext.hpp"
#include "ref.hpp" #include "ref.hpp"
#include "OgreSceneNode.h"
namespace MWScript namespace MWScript
{ {
@ -141,6 +146,368 @@ namespace MWScript
} }
}; };
template<class R>
class OpGetPos : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
if(axis == "x")
{
runtime.push(ptr.getRefData().getPosition().pos[0]);
}
else if(axis == "y")
{
runtime.push(ptr.getRefData().getPosition().pos[1]);
}
else if(axis == "z")
{
runtime.push(ptr.getRefData().getPosition().pos[2]);
}
else
throw std::runtime_error ("invalid rotation axis: " + axis);
}
};
template<class R>
class OpSetPos : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Float pos = runtime[0].mFloat;
runtime.pop();
float ax = ptr.getRefData().getPosition().pos[0];
float ay = ptr.getRefData().getPosition().pos[1];
float az = ptr.getRefData().getPosition().pos[2];
if(axis == "x")
{
MWBase::Environment::get().getWorld()->moveObject(ptr,pos,ay,az);
}
else if(axis == "y")
{
MWBase::Environment::get().getWorld()->moveObject(ptr,ax,pos,az);
}
else if(axis == "z")
{
MWBase::Environment::get().getWorld()->moveObject(ptr,ax,ay,pos);
}
else
throw std::runtime_error ("invalid axis: " + axis);
}
};
template<class R>
class OpGetStartingPos : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
if(axis == "x")
{
runtime.push(ptr.getCellRef().mPos.pos[0]);
}
else if(axis == "y")
{
runtime.push(ptr.getCellRef().mPos.pos[1]);
}
else if(axis == "z")
{
runtime.push(ptr.getCellRef().mPos.pos[2]);
}
else
throw std::runtime_error ("invalid axis: " + axis);
}
};
template<class R>
class OpPositionCell : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float x = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float y = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float z = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float zRot = runtime[0].mFloat;
runtime.pop();
std::string cellID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
MWWorld::CellStore* store = 0;
try
{
store = MWBase::Environment::get().getWorld()->getInterior(cellID);
}
catch(std::exception &e)
{
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID);
if(cell)
{
int cx,cy;
MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy);
store = MWBase::Environment::get().getWorld()->getExterior(cx,cy);
}
}
if(store)
{
MWBase::Environment::get().getWorld()->moveObject(ptr,*store,x,y,z);
float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees();
float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees();
if(ptr.getTypeName() == typeid(ESM::NPC).name())//some morrowind oddity
{
ax = ax/60.;
ay = ay/60.;
zRot = zRot/60.;
}
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot);
}
else
{
throw std::runtime_error ("unknown cell");
}
}
};
template<class R>
class OpPosition : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float x = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float y = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float z = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float zRot = runtime[0].mFloat;
runtime.pop();
int cx,cy;
MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy);
MWBase::Environment::get().getWorld()->moveObject(ptr,
*MWBase::Environment::get().getWorld()->getExterior(cx,cy),x,y,z);
float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees();
float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees();
if(ptr.getTypeName() == typeid(ESM::NPC).name())//some morrowind oddity
{
ax = ax/60.;
ay = ay/60.;
zRot = zRot/60.;
}
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot);
}
};
template<class R>
class OpPlaceItemCell : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
std::string itemID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
std::string cellID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Float x = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float y = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float z = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float zRot = runtime[0].mFloat;
runtime.pop();
MWWorld::CellStore* store = 0;
try
{
store = MWBase::Environment::get().getWorld()->getInterior(cellID);
}
catch(std::exception &e)
{
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID);
if(cell)
{
int cx,cy;
MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy);
store = MWBase::Environment::get().getWorld()->getExterior(cx,cy);
}
}
if(store)
{
ESM::Position pos;
pos.pos[0] = x;
pos.pos[1] = y;
pos.pos[2] = z;
pos.rot[0] = pos.rot[1] = 0;
pos.rot[2] = zRot;
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().getCellRef().mPos = pos;
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,pos);
}
else
{
throw std::runtime_error ("unknown cell");
}
}
};
template<class R>
class OpPlaceItem : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
std::string itemID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Float x = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float y = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float z = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Float zRot = runtime[0].mFloat;
runtime.pop();
int cx,cy;
MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy);
MWWorld::CellStore* store = MWBase::Environment::get().getWorld()->getExterior(cx,cy);
if(store)
{
ESM::Position pos;
pos.pos[0] = x;
pos.pos[1] = y;
pos.pos[2] = z;
pos.rot[0] = pos.rot[1] = 0;
pos.rot[2] = zRot;
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().getCellRef().mPos = pos;
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,pos);
}
else
{
throw std::runtime_error ("unknown cell");
}
}
};
template<class R>
class OpPlaceAtPc : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
std::string itemID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Integer count = runtime[0].mInteger;
runtime.pop();
Interpreter::Type_Float distance = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Integer direction = runtime[0].mInteger;
runtime.pop();
ESM::Position ipos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition();
Ogre::Vector3 pos(ipos.pos[0],ipos.pos[1],ipos.pos[2]);
Ogre::Quaternion rot(Ogre::Radian(ipos.rot[2]), Ogre::Vector3::UNIT_Z);
if(direction == 0) pos = pos + distance*rot.yAxis();
else if(direction == 1) pos = pos - distance*rot.yAxis();
else if(direction == 2) pos = pos - distance*rot.xAxis();
else if(direction == 3) pos = pos + distance*rot.xAxis();
else throw std::runtime_error ("direction must be 0,1,2 or 3");
ipos.pos[0] = pos.x;
ipos.pos[1] = pos.y;
ipos.pos[2] = pos.z;
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
MWWorld::CellStore* store = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().getCellRef().mPos = ipos;
ref.getPtr().getRefData().setCount(count);
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos);
}
};
template<class R>
class OpPlaceAtMe : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr me = R()(runtime);
std::string itemID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Integer count = runtime[0].mInteger;
runtime.pop();
Interpreter::Type_Float distance = runtime[0].mFloat;
runtime.pop();
Interpreter::Type_Integer direction = runtime[0].mInteger;
runtime.pop();
ESM::Position ipos = me.getRefData().getPosition();
Ogre::Vector3 pos(ipos.pos[0],ipos.pos[1],ipos.pos[2]);
Ogre::Quaternion rot(Ogre::Radian(ipos.rot[2]), Ogre::Vector3::UNIT_Z);
if(direction == 0) pos = pos + distance*rot.yAxis();
else if(direction == 1) pos = pos - distance*rot.yAxis();
else if(direction == 2) pos = pos - distance*rot.xAxis();
else if(direction == 3) pos = pos + distance*rot.xAxis();
else throw std::runtime_error ("direction must be 0,1,2 or 3");
ipos.pos[0] = pos.x;
ipos.pos[1] = pos.y;
ipos.pos[2] = pos.z;
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
MWWorld::CellStore* store = me.getCell();
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().getCellRef().mPos = ipos;
ref.getPtr().getRefData().setCount(count);
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos);
}
};
const int opcodeSetScale = 0x2000164; const int opcodeSetScale = 0x2000164;
const int opcodeSetScaleExplicit = 0x2000165; const int opcodeSetScaleExplicit = 0x2000165;
const int opcodeSetAngle = 0x2000166; const int opcodeSetAngle = 0x2000166;
@ -149,8 +516,22 @@ namespace MWScript
const int opcodeGetScaleExplicit = 0x2000169; const int opcodeGetScaleExplicit = 0x2000169;
const int opcodeGetAngle = 0x200016a; const int opcodeGetAngle = 0x200016a;
const int opcodeGetAngleExplicit = 0x200016b; const int opcodeGetAngleExplicit = 0x200016b;
const int opcodeGetStartingAngle = 0x2000172; const int opcodeGetPos = 0x2000190;
const int opcodeGetStartingAngleExplicit = 0x2000173; const int opcodeGetPosExplicit = 0x2000191;
const int opcodeSetPos = 0x2000192;
const int opcodeSetPosExplicit = 0x2000193;
const int opcodeGetStartingPos = 0x2000194;
const int opcodeGetStartingPosExplicit = 0x2000195;
const int opcodePosition = 0x2000196;
const int opcodePositionExplicit = 0x2000197;
const int opcodePositionCell = 0x2000198;
const int opcodePositionCellExplicit = 0x2000199;
const int opcodePlaceItemCell = 0x200019a;
const int opcodePlaceItem = 0x200019b;
const int opcodePlaceAtPc = 0x200019c;
const int opcodePlaceAtMe = 0x200019d;
const int opcodePlaceAtMeExplicit = 0x200019e;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -158,7 +539,15 @@ namespace MWScript
extensions.registerFunction("getscale",'f',"",opcodeGetScale,opcodeGetScaleExplicit); extensions.registerFunction("getscale",'f',"",opcodeGetScale,opcodeGetScaleExplicit);
extensions.registerInstruction("setangle","cf",opcodeSetAngle,opcodeSetAngleExplicit); extensions.registerInstruction("setangle","cf",opcodeSetAngle,opcodeSetAngleExplicit);
extensions.registerFunction("getangle",'f',"c",opcodeGetAngle,opcodeGetAngleExplicit); extensions.registerFunction("getangle",'f',"c",opcodeGetAngle,opcodeGetAngleExplicit);
extensions.registerFunction("getstartingangle",'f',"c",opcodeGetStartingAngle,opcodeGetStartingAngleExplicit); extensions.registerInstruction("setpos","cf",opcodeSetPos,opcodeSetPosExplicit);
extensions.registerFunction("getpos",'f',"c",opcodeGetPos,opcodeGetPosExplicit);
extensions.registerFunction("getstartingpos",'f',"c",opcodeGetStartingPos,opcodeGetStartingPosExplicit);
extensions.registerInstruction("position","ffff",opcodePosition,opcodePositionExplicit);
extensions.registerInstruction("positioncell","ffffc",opcodePositionCell,opcodePositionCellExplicit);
extensions.registerInstruction("placeitemcell","ccffff",opcodePlaceItemCell);
extensions.registerInstruction("placeitem","cffff",opcodePlaceItem);
extensions.registerInstruction("placeatpc","clfl",opcodePlaceAtPc);
extensions.registerInstruction("placeatme","clfl",opcodePlaceAtMe,opcodePlaceAtMeExplicit);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -171,8 +560,21 @@ namespace MWScript
interpreter.installSegment5(opcodeGetScaleExplicit,new OpGetScale<ExplicitRef>); interpreter.installSegment5(opcodeGetScaleExplicit,new OpGetScale<ExplicitRef>);
interpreter.installSegment5(opcodeGetAngle,new OpGetAngle<ImplicitRef>); interpreter.installSegment5(opcodeGetAngle,new OpGetAngle<ImplicitRef>);
interpreter.installSegment5(opcodeGetAngleExplicit,new OpGetAngle<ExplicitRef>); interpreter.installSegment5(opcodeGetAngleExplicit,new OpGetAngle<ExplicitRef>);
interpreter.installSegment5(opcodeGetStartingAngle,new OpGetStartingAngle<ImplicitRef>); interpreter.installSegment5(opcodeGetPos,new OpGetPos<ImplicitRef>);
interpreter.installSegment5(opcodeGetStartingAngleExplicit,new OpGetStartingAngle<ExplicitRef>); interpreter.installSegment5(opcodeGetPosExplicit,new OpGetPos<ExplicitRef>);
interpreter.installSegment5(opcodeSetPos,new OpSetPos<ImplicitRef>);
interpreter.installSegment5(opcodeSetPosExplicit,new OpSetPos<ExplicitRef>);
interpreter.installSegment5(opcodeGetStartingPos,new OpGetStartingPos<ImplicitRef>);
interpreter.installSegment5(opcodeGetStartingPosExplicit,new OpGetStartingPos<ExplicitRef>);
interpreter.installSegment5(opcodePosition,new OpPosition<ImplicitRef>);
interpreter.installSegment5(opcodePositionExplicit,new OpPosition<ExplicitRef>);
interpreter.installSegment5(opcodePositionCell,new OpPositionCell<ImplicitRef>);
interpreter.installSegment5(opcodePositionCellExplicit,new OpPositionCell<ExplicitRef>);
interpreter.installSegment5(opcodePlaceItemCell,new OpPlaceItemCell<ImplicitRef>);
interpreter.installSegment5(opcodePlaceItem,new OpPlaceItem<ImplicitRef>);
interpreter.installSegment5(opcodePlaceAtPc,new OpPlaceAtPc<ImplicitRef>);
interpreter.installSegment5(opcodePlaceAtMe,new OpPlaceAtMe<ImplicitRef>);
interpreter.installSegment5(opcodePlaceAtMeExplicit,new OpPlaceAtMe<ExplicitRef>);
} }
} }
} }

@ -2,10 +2,18 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwgui/bookwindow.hpp" #include "../mwgui/bookwindow.hpp"
#include "../mwgui/scrollwindow.hpp" #include "../mwgui/scrollwindow.hpp"
#include <components/esm_store/store.hpp>
namespace MWWorld namespace MWWorld
{ {
ActionRead::ActionRead (const MWWorld::Ptr& object) : Action (false, object) ActionRead::ActionRead (const MWWorld::Ptr& object) : Action (false, object)
@ -26,5 +34,23 @@ namespace MWWorld
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Book); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Book);
MWBase::Environment::get().getWindowManager()->getBookWindow()->open(getTarget()); MWBase::Environment::get().getWindowManager()->getBookWindow()->open(getTarget());
} }
/*
// Skill gain from books
if (ref->base->data.skillID >= 0 && ref->base->data.skillID < ESM::Skill::Length)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats (player);
MWWorld::LiveCellRef<ESM::NPC> *playerRef = player.get<ESM::NPC>();
const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().classes.find (
playerRef->base->cls);
npcStats.increaseSkill (ref->base->data.skillID, *class_, true);
/// \todo Remove skill from the book. Right now you can read as many times as you want
/// and the skill will still increase.
}
*/
} }
} }

@ -96,6 +96,10 @@ namespace MWWorld
if(hasWater){ if(hasWater){
playerphysics->waterHeight = waterHeight; playerphysics->waterHeight = waterHeight;
} }
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
{
it->second->setCurrentWater(hasWater, waterHeight);
}
} }
@ -172,17 +176,20 @@ namespace MWWorld
//set the DebugRenderingMode. To disable it,set it to 0 //set the DebugRenderingMode. To disable it,set it to 0
//eng->setDebugRenderingMode(1); //eng->setDebugRenderingMode(1);
//set the walkdirection to 0 (no movement) for every actor) //set the movement keys to 0 (no movement) for every actor)
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
{ {
OEngine::Physic::PhysicActor* act = it->second; OEngine::Physic::PhysicActor* act = it->second;
act->setWalkDirection(btVector3(0,0,0)); act->setMovement(0,0,0);
} }
playerMove::playercmd& pm_ref = playerphysics->cmd; playerMove::playercmd& pm_ref = playerphysics->cmd;
pm_ref.rightmove = 0; pm_ref.rightmove = 0;
pm_ref.forwardmove = 0; pm_ref.forwardmove = 0;
pm_ref.upmove = 0; pm_ref.upmove = 0;
//playerphysics->ps.move_type = PM_NOCLIP; //playerphysics->ps.move_type = PM_NOCLIP;
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin()); for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
@ -193,10 +200,12 @@ namespace MWWorld
playerphysics->ps.viewangles.x = playerphysics->ps.viewangles.x =
Ogre::Radian(mPlayerData.pitch).valueDegrees(); Ogre::Radian(mPlayerData.pitch).valueDegrees();
playerphysics->ps.viewangles.y = playerphysics->ps.viewangles.y =
Ogre::Radian(mPlayerData.yaw).valueDegrees() + 90; Ogre::Radian(mPlayerData.yaw).valueDegrees() + 90;
pm_ref.rightmove = -iter->second.x; pm_ref.rightmove = iter->second.x;
pm_ref.forwardmove = -iter->second.y; pm_ref.forwardmove = -iter->second.y;
pm_ref.upmove = iter->second.z; pm_ref.upmove = iter->second.z;
} }
@ -208,16 +217,17 @@ namespace MWWorld
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors) const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
{ {
Pmove(playerphysics); Pmove(playerphysics);
std::vector< std::pair<std::string, Ogre::Vector3> > response; std::vector< std::pair<std::string, Ogre::Vector3> > response;
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
{ {
btVector3 newPos = it->second->getPosition();
Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); Ogre::Vector3 coord = it->second->getPosition();
if(it->first == "player"){ if(it->first == "player"){
coord = playerphysics->ps.origin; coord = playerphysics->ps.origin ;
} }
@ -243,21 +253,15 @@ namespace MWWorld
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position)
{ {
handleToMesh[handle] = mesh; handleToMesh[handle] = mesh;
OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle,scale); OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody(mesh,handle,scale, position, rotation);
mEngine->addRigidBody(body); mEngine->addRigidBody(body);
btTransform tr;
tr.setOrigin(btVector3(position.x,position.y,position.z));
tr.setRotation(btQuaternion(rotation.x,rotation.y,rotation.z,rotation.w));
body->setWorldTransform(tr);
} }
void PhysicsSystem::addActor (const std::string& handle, const std::string& mesh, void PhysicsSystem::addActor (const std::string& handle, const std::string& mesh,
const Ogre::Vector3& position) const Ogre::Vector3& position, float scale, const Ogre::Quaternion& rotation)
{ {
//TODO:optimize this. Searching the std::map isn't very efficient i think. //TODO:optimize this. Searching the std::map isn't very efficient i think.
mEngine->addCharacter(handle); mEngine->addCharacter(handle, mesh, position, scale, rotation);
OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle);
act->setPosition(btVector3(position.x,position.y,position.z));
} }
void PhysicsSystem::removeObject (const std::string& handle) void PhysicsSystem::removeObject (const std::string& handle)
@ -268,15 +272,25 @@ namespace MWWorld
mEngine->deleteRigidBody(handle); mEngine->deleteRigidBody(handle);
} }
void PhysicsSystem::moveObject (const std::string& handle, const Ogre::Vector3& position) void PhysicsSystem::moveObject (const std::string& handle, Ogre::SceneNode* node)
{ {
Ogre::Vector3 position = node->getPosition();
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
{ {
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
// start positions others than 0, 0, 0 // start positions others than 0, 0, 0
btTransform tr = body->getWorldTransform();
tr.setOrigin(btVector3(position.x,position.y,position.z));
body->setWorldTransform(tr); if(dynamic_cast<btBoxShape*>(body->getCollisionShape()) == NULL){
btTransform tr = body->getWorldTransform();
tr.setOrigin(btVector3(position.x,position.y,position.z));
body->setWorldTransform(tr);
}
else{
//For objects that contain a box shape.
//Do any such objects exist? Perhaps animated objects?
mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, position, node->getOrientation());
}
} }
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
{ {
@ -288,34 +302,45 @@ namespace MWWorld
} }
else else
{ {
act->setPosition(btVector3(position.x,position.y,position.z)); act->setPosition(position);
} }
} }
} }
void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation) void PhysicsSystem::rotateObject (const std::string& handle, Ogre::SceneNode* node)
{ {
Ogre::Quaternion rotation = node->getOrientation();
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
{ {
act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); //Needs to be changed
act->setRotation(rotation);
} }
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
{ {
body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); if(dynamic_cast<btBoxShape*>(body->getCollisionShape()) == NULL)
body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
else
mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, node->getPosition(), rotation);
} }
} }
void PhysicsSystem::scaleObject (const std::string& handle, float scale) void PhysicsSystem::scaleObject (const std::string& handle, Ogre::SceneNode* node)
{ {
if(handleToMesh.find(handle) != handleToMesh.end()) if(handleToMesh.find(handle) != handleToMesh.end())
{ {
btTransform transform = mEngine->getRigidBody(handle)->getWorldTransform();
removeObject(handle); removeObject(handle);
Ogre::Quaternion quat = Ogre::Quaternion(transform.getRotation().getW(), transform.getRotation().getX(), transform.getRotation().getY(), transform.getRotation().getZ()); float scale = node->getScale().x;
Ogre::Vector3 vec = Ogre::Vector3(transform.getOrigin().getX(), transform.getOrigin().getY(), transform.getOrigin().getZ()); Ogre::Quaternion quat = node->getOrientation();
Ogre::Vector3 vec = node->getPosition();
addObject(handle, handleToMesh[handle], quat, scale, vec); addObject(handle, handleToMesh[handle], quat, scale, vec);
} }
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
{
float scale = node->getScale().x;
act->setScale(scale);
}
} }
bool PhysicsSystem::toggleCollisionMode() bool PhysicsSystem::toggleCollisionMode()
@ -335,8 +360,6 @@ namespace MWWorld
if(cmode) if(cmode)
{ {
act->enableCollisions(false); act->enableCollisions(false);
act->setGravity(0.);
act->setVerticalVelocity(0);
mFreeFly = true; mFreeFly = true;
return false; return false;
} }
@ -344,8 +367,6 @@ namespace MWWorld
{ {
mFreeFly = false; mFreeFly = false;
act->enableCollisions(true); act->enableCollisions(true);
act->setGravity(4.);
act->setVerticalVelocity(0);
return true; return true;
} }
} }
@ -368,7 +389,7 @@ namespace MWWorld
void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){ void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
addActor (node->getName(), model, node->getPosition()); addActor (node->getName(), model, node->getPosition(), node->getScale().x, node->getOrientation());
} }
bool PhysicsSystem::getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max) bool PhysicsSystem::getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max)

@ -24,7 +24,7 @@ namespace MWWorld
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position);
void addActor (const std::string& handle, const std::string& mesh, void addActor (const std::string& handle, const std::string& mesh,
const Ogre::Vector3& position); const Ogre::Vector3& position, float scale, const Ogre::Quaternion& rotation);
void addHeightField (float* heights, void addHeightField (float* heights,
int x, int y, float yoffset, int x, int y, float yoffset,
@ -34,11 +34,11 @@ namespace MWWorld
void removeObject (const std::string& handle); void removeObject (const std::string& handle);
void moveObject (const std::string& handle, const Ogre::Vector3& position); void moveObject (const std::string& handle, Ogre::SceneNode* node);
void rotateObject (const std::string& handle, const Ogre::Quaternion& rotation); void rotateObject (const std::string& handle, Ogre::SceneNode* node);
void scaleObject (const std::string& handle, float scale); void scaleObject (const std::string& handle, Ogre::SceneNode* node);
bool toggleCollisionMode(); bool toggleCollisionMode();

@ -189,7 +189,9 @@ namespace MWWorld
mPlayer = new MWWorld::Player (mStore.npcs.find ("player"), *this); mPlayer = new MWWorld::Player (mStore.npcs.find ("player"), *this);
mRendering->attachCameraTo(mPlayer->getPlayer()); mRendering->attachCameraTo(mPlayer->getPlayer());
mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); std::string playerCollisionFile = "meshes\\base_anim.nif"; //This is used to make a collision shape for our player
//We will need to support the 1st person file too in the future
mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), playerCollisionFile, Ogre::Vector3 (0, 0, 0), 1, Ogre::Quaternion::ZERO);
// global variables // global variables
mGlobalVariables = new Globals (mStore); mGlobalVariables = new Globals (mStore);
@ -450,6 +452,16 @@ namespace MWWorld
mRendering->skySetDate (mGlobalVariables->getInt ("day"), month); mRendering->skySetDate (mGlobalVariables->getInt ("day"), month);
} }
int World::getDay()
{
return mGlobalVariables->getInt("day");
}
int World::getMonth()
{
return mGlobalVariables->getInt("month");
}
TimeStamp World::getTimeStamp() const TimeStamp World::getTimeStamp() const
{ {
return TimeStamp (mGlobalVariables->getFloat ("gamehour"), return TimeStamp (mGlobalVariables->getFloat ("gamehour"),
@ -541,6 +553,16 @@ namespace MWWorld
} }
} }
std::string toLower (const std::string& name)
{
std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
void World::moveObject(const Ptr &ptr, CellStore &newCell, float x, float y, float z) void World::moveObject(const Ptr &ptr, CellStore &newCell, float x, float y, float z)
{ {
ESM::Position &pos = ptr.getRefData().getPosition(); ESM::Position &pos = ptr.getRefData().getPosition();
@ -550,11 +572,10 @@ namespace MWWorld
CellStore *currCell = ptr.getCell(); CellStore *currCell = ptr.getCell();
bool isPlayer = ptr == mPlayer->getPlayer(); bool isPlayer = ptr == mPlayer->getPlayer();
bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer; bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer;
if (*currCell != newCell) { if (*currCell != newCell) {
if (isPlayer) { if (isPlayer) {
if (!newCell.isExterior()) { if (!newCell.isExterior()) {
changeToInteriorCell(newCell.cell->mName, pos); changeToInteriorCell(toLower(newCell.cell->mName), pos);
} else { } else {
int cellX = newCell.cell->mData.mX; int cellX = newCell.cell->mData.mX;
int cellY = newCell.cell->mData.mY; int cellY = newCell.cell->mData.mY;
@ -594,7 +615,7 @@ namespace MWWorld
} }
if (haveToMove) { if (haveToMove) {
mRendering->moveObject(ptr, vec); mRendering->moveObject(ptr, vec);
mPhysics->moveObject(ptr.getRefData().getHandle(), vec); mPhysics->moveObject (ptr.getRefData().getHandle(), ptr.getRefData().getBaseNode());
} }
} }
@ -615,6 +636,8 @@ namespace MWWorld
void World::moveObject (const Ptr& ptr, float x, float y, float z) void World::moveObject (const Ptr& ptr, float x, float y, float z)
{ {
moveObjectImp(ptr, x, y, z); moveObjectImp(ptr, x, y, z);
} }
void World::scaleObject (const Ptr& ptr, float scale) void World::scaleObject (const Ptr& ptr, float scale)
@ -624,7 +647,7 @@ namespace MWWorld
ptr.getCellRef().mScale = scale; ptr.getCellRef().mScale = scale;
//scale = scale/ptr.getRefData().getBaseNode()->getScale().x; //scale = scale/ptr.getRefData().getBaseNode()->getScale().x;
ptr.getRefData().getBaseNode()->setScale(scale,scale,scale); ptr.getRefData().getBaseNode()->setScale(scale,scale,scale);
mPhysics->scaleObject( ptr.getRefData().getHandle(), scale ); mPhysics->scaleObject( ptr.getRefData().getHandle(), ptr.getRefData().getBaseNode());
} }
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
@ -633,18 +656,25 @@ namespace MWWorld
rot.x = Ogre::Degree(x).valueRadians(); rot.x = Ogre::Degree(x).valueRadians();
rot.y = Ogre::Degree(y).valueRadians(); rot.y = Ogre::Degree(y).valueRadians();
rot.z = Ogre::Degree(z).valueRadians(); rot.z = Ogre::Degree(z).valueRadians();
if (mRendering->rotateObject(ptr, rot, adjust)) { if (mRendering->rotateObject(ptr, rot, adjust)) {
float *objRot = ptr.getRefData().getPosition().rot; float *objRot = ptr.getRefData().getPosition().rot;
objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z; objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z;
if (ptr.getRefData().getBaseNode() != 0) { if (ptr.getRefData().getBaseNode() != 0) {
mPhysics->rotateObject( mPhysics->rotateObject(
ptr.getRefData().getHandle(), ptr.getRefData().getHandle(),
ptr.getRefData().getBaseNode()->getOrientation() ptr.getRefData().getBaseNode()
); );
} }
} }
}
void World::safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos)
{
copyObjectToCell(ptr,Cell,pos);
} }
void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const
@ -1223,8 +1253,37 @@ namespace MWWorld
mRendering->renderPlayer(mPlayer->getPlayer()); mRendering->renderPlayer(mPlayer->getPlayer());
} }
void World::renderGlobalMap ()
{
mRendering->renderGlobalMap ();
}
void World::setupExternalRendering (MWRender::ExternalRendering& rendering) void World::setupExternalRendering (MWRender::ExternalRendering& rendering)
{ {
mRendering->setupExternalRendering (rendering); mRendering->setupExternalRendering (rendering);
} }
int World::canRest ()
{
Ptr::CellStore *currentCell = mWorldScene->getCurrentCell();
Ogre::Vector3 playerPos;
float* pos = mPlayer->getPlayer ().getRefData ().getPosition ().pos;
playerPos.x = pos[0];
playerPos.y = pos[1];
playerPos.z = pos[2];
std::pair<bool, Ogre::Vector3> hit =
mPhysics->castRay(playerPos, Ogre::Vector3(0,0,-1), 50);
bool isOnGround = (hit.first ? (hit.second.distance (playerPos) < 25) : false);
if (!isOnGround || isUnderwater (*currentCell->cell, playerPos))
return 2;
if (currentCell->cell->mData.mFlags & ESM::Cell::NoSleep)
return 1;
return 0;
}
} }

@ -179,6 +179,9 @@ namespace MWWorld
virtual void setDay (int day); virtual void setDay (int day);
///< Set in-game time day. ///< Set in-game time day.
virtual int getDay();
virtual int getMonth();
virtual TimeStamp getTimeStamp() const; virtual TimeStamp getTimeStamp() const;
///< Return current in-game time stamp. ///< Return current in-game time stamp.
@ -223,6 +226,9 @@ namespace MWWorld
/// \param adjust indicates rotation should be set or adjusted /// \param adjust indicates rotation should be set or adjusted
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false); virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos);
///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr.
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
const; const;
///< Convert cell numbers to position. ///< Convert cell numbers to position.
@ -307,8 +313,16 @@ namespace MWWorld
} }
virtual void renderPlayer(); virtual void renderPlayer();
virtual void renderGlobalMap();
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
virtual int canRest();
///< check if the player is allowed to rest \n
/// 0 - yes \n
/// 1 - only waiting \n
/// 2 - player is underwater \n
/// 3 - enemies are nearby (not implemented)
}; };
} }

@ -3,8 +3,6 @@
#include "esm_reader.hpp" #include "esm_reader.hpp"
#include "esm_writer.hpp" #include "esm_writer.hpp"
#include <stdio.h>
namespace namespace
{ {
const int NumberOfHardcodedFlags = 143; const int NumberOfHardcodedFlags = 143;

@ -72,6 +72,9 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
cShape = static_cast<BulletShape *>(resource); cShape = static_cast<BulletShape *>(resource);
resourceName = cShape->getName(); resourceName = cShape->getName();
cShape->collide = false; cShape->collide = false;
mBoundingBox = NULL;
cShape->boxTranslation = Ogre::Vector3(0,0,0);
cShape->boxRotation = Ogre::Quaternion::IDENTITY;
mTriMesh = new btTriangleMesh(); mTriMesh = new btTriangleMesh();
@ -125,9 +128,14 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
delete m_meshInterface; delete m_meshInterface;
} }
}; };
if(mBoundingBox != NULL)
cShape->Shape = mBoundingBox;
currentShape = new TriangleMeshShape(mTriMesh,true); else
cShape->Shape = currentShape; {
currentShape = new TriangleMeshShape(mTriMesh,true);
cShape->Shape = currentShape;
}
} }
bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node) bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node)
@ -218,6 +226,17 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
} }
if(node->hasBounds)
{
btVector3 boxsize = getbtVector((node->boundXYZ));
cShape->boxTranslation = node->boundPos;
cShape->boxRotation = node->boundRot;
mBoundingBox = new btBoxShape(boxsize);
}
// For NiNodes, loop through children // For NiNodes, loop through children
if (node->recType == Nif::RC_NiNode) if (node->recType == Nif::RC_NiNode)

@ -102,8 +102,11 @@ private:
std::string resourceName; std::string resourceName;
std::string resourceGroup; std::string resourceGroup;
BulletShape* cShape;//current shape BulletShape* cShape;//current shape
btTriangleMesh *mTriMesh; btTriangleMesh *mTriMesh;
btBoxShape *mBoundingBox;
btBvhTriangleMeshShape* currentShape;//the shape curently under construction btBvhTriangleMeshShape* currentShape;//the shape curently under construction
}; };

@ -1,3 +1,7 @@
#define gammaCorrectRead(v) pow(v, float3(gammaCorrection,gammaCorrection,gammaCorrection))
#define gammaCorrectOutput(v) pow(v, float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection))
#if SH_HLSL == 1 || SH_CG == 1 #if SH_HLSL == 1 || SH_CG == 1
#define shTexture2D sampler2D #define shTexture2D sampler2D

@ -112,6 +112,8 @@
shUniform(float, far) @shAutoConstant(far, far_clip_distance) shUniform(float, far) @shAutoConstant(far, far_clip_distance)
#endif #endif
shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection)
#if LIGHTING #if LIGHTING
shInput(float3, normalPassthrough) shInput(float3, normalPassthrough)
shInput(float3, objSpacePositionPassthrough) shInput(float3, objSpacePositionPassthrough)
@ -173,7 +175,8 @@
SH_START_PROGRAM SH_START_PROGRAM
{ {
shOutputColour(0) = shSample(diffuseMap, UV); shOutputColour(0) = shSample(diffuseMap, UV);
shOutputColour(0).xyz = gammaCorrectRead(shOutputColour(0).xyz);
#if LIGHTING #if LIGHTING
float3 normal = normalize(normalPassthrough); float3 normal = normalize(normalPassthrough);
float3 lightDir; float3 lightDir;
@ -259,7 +262,7 @@
// regular fog only if fragment is above water // regular fog only if fragment is above water
if (worldPos.y > waterLevel) if (worldPos.y > waterLevel)
#endif #endif
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue);
#endif #endif
// prevent negative colour output (for example with negative lights) // prevent negative colour output (for example with negative lights)
@ -274,12 +277,11 @@
float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz));
waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0));
float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85)) *waterSunGradient * 0.5;
float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0));
waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0);
float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; float3 watercolour = ( gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0;
float3 waterext = float3(0.6, 0.9, 1.0);//water extinction
watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3;
@ -292,6 +294,8 @@
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled); shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled);
#endif #endif
shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz);
#if MRT #if MRT
shOutputColour(1) = float4(depthPassthrough / far,1,1,1); shOutputColour(1) = float4(depthPassthrough / far,1,1,1);
#endif #endif

@ -137,6 +137,8 @@
shSampler2D(normalMap) // global normal map shSampler2D(normalMap) // global normal map
shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection)
@shForeach(@shPropertyString(num_blendmaps)) @shForeach(@shPropertyString(num_blendmaps))
shSampler2D(blendMap@shIterator) shSampler2D(blendMap@shIterator)
@ -247,9 +249,9 @@
#if IS_FIRST_PASS == 1 && @shIterator == 0 #if IS_FIRST_PASS == 1 && @shIterator == 0
// first layer of first pass doesn't need a blend map // first layer of first pass doesn't need a blend map
albedo = shSample(diffuseMap0, UV * 10).rgb; albedo = gammaCorrectRead(shSample(diffuseMap0, UV * 10).rgb);
#else #else
albedo = shLerp(albedo, shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); albedo = shLerp(albedo, gammaCorrectRead(shSample(diffuseMap@shIterator, UV * 10).rgb), blendValues@shPropertyString(blendmap_component_@shIterator));
#endif #endif
@shEndForeach @shEndForeach
@ -336,7 +338,7 @@
// regular fog only if fragment is above water // regular fog only if fragment is above water
if (worldPos.y > waterLevel) if (worldPos.y > waterLevel)
#endif #endif
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue);
#endif #endif
// prevent negative colour output (for example with negative lights) // prevent negative colour output (for example with negative lights)
@ -351,12 +353,12 @@
float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz));
waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0));
float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85))*waterSunGradient * 0.5;
float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0));
waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0);
float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; float3 watercolour = (gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0;
float3 waterext = float3(0.6, 0.9, 1.0);//water extinction float3 waterext = gammaCorrectRead(float3(0.6, 0.9, 1.0));//water extinction
watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT)));
watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3;
@ -369,6 +371,8 @@
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater);
#endif #endif
shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz);
#if MRT #if MRT
shOutputColour(1) = float4(depth / far,1,1,1); shOutputColour(1) = float4(depth / far,1,1,1);

@ -35,7 +35,7 @@ set(MYGUI_FILES
openmw_dialogue_window.layout openmw_dialogue_window.layout
openmw_dialogue_window_skin.xml openmw_dialogue_window_skin.xml
openmw_edit.skin.xml openmw_edit.skin.xml
openmw.font.xml openmw_font.xml
openmw_hud_box.skin.xml openmw_hud_box.skin.xml
openmw_hud_energybar.skin.xml openmw_hud_energybar.skin.xml
openmw_hud.layout openmw_hud.layout
@ -51,7 +51,7 @@ set(MYGUI_FILES
openmw_map_window.layout openmw_map_window.layout
openmw_map_window_skin.xml openmw_map_window_skin.xml
openmw_messagebox.layout openmw_messagebox.layout
openmw.pointer.xml openmw_pointer.xml
openmw_progress.skin.xml openmw_progress.skin.xml
openmw_resources.xml openmw_resources.xml
openmw_scroll.layout openmw_scroll.layout
@ -72,6 +72,9 @@ set(MYGUI_FILES
openmw_magicselection_dialog.layout openmw_magicselection_dialog.layout
openmw_spell_buying_window.layout openmw_spell_buying_window.layout
openmw_loading_screen.layout openmw_loading_screen.layout
openmw_levelup_dialog.layout
openmw_wait_dialog.layout
openmw_wait_dialog_progressbar.layout
smallbars.png smallbars.png
VeraMono.ttf VeraMono.ttf
markers.png markers.png

@ -4,8 +4,8 @@
<List file="core.skin" /> <List file="core.skin" />
<List file="openmw_resources.xml" /> <List file="openmw_resources.xml" />
<List file="openmw_layers.xml" /> <List file="openmw_layers.xml" />
<List file="openmw.pointer.xml" /> <List file="openmw_pointer.xml" />
<List file="openmw.font.xml" /> <List file="openmw_font.xml" />
<List file="openmw_text.skin.xml" /> <List file="openmw_text.skin.xml" />
<List file="openmw_windows.skin.xml" /> <List file="openmw_windows.skin.xml" />
<List file="openmw_button.skin.xml" /> <List file="openmw_button.skin.xml" />

@ -77,8 +77,9 @@
<!-- Buttons --> <!-- Buttons -->
<Widget type="HBox" skin="" position="160 370 380 24"> <Widget type="HBox" skin="" position="160 370 380 24">
<Widget type="Widget"/> <!-- spacer --> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="CreateButton"> <Widget type="AutoSizedButton" skin="MW_Button" name="CreateButton">
<Property key="Caption" value="#{sCreate}"/> <Property key="Caption" value="#{sCreate}"/>
</Widget> </Widget>

@ -15,7 +15,9 @@
<!-- Dialog buttons --> <!-- Dialog buttons -->
<Widget type="HBox" position="0 340 473 24"> <Widget type="HBox" position="0 340 473 24">
<Widget type="Widget"/> <!-- spacer --> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="BackButton"> <Widget type="AutoSizedButton" skin="MW_Button" name="BackButton">
<Property key="Caption" value="#{sBack}"/> <Property key="Caption" value="#{sBack}"/>
</Widget> </Widget>

@ -61,7 +61,9 @@
<!-- Dialog buttons --> <!-- Dialog buttons -->
<Widget type="HBox" position="0 265 476 24"> <Widget type="HBox" position="0 265 476 24">
<Widget type="Widget"/> <!-- spacer --> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="BackButton"> <Widget type="AutoSizedButton" skin="MW_Button" name="BackButton">
<Property key="Caption" value="#{sBack}"/> <Property key="Caption" value="#{sBack}"/>
</Widget> </Widget>

@ -59,7 +59,9 @@
<!-- Dialog buttons --> <!-- Dialog buttons -->
<Widget type="HBox" position="0 158 459 24"> <Widget type="HBox" position="0 158 459 24">
<Widget type="Widget"/> <!-- spacer --> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="DescriptionButton"> <Widget type="AutoSizedButton" skin="MW_Button" name="DescriptionButton">
<Property key="Caption" value="#{sCreateClassMenu1}"/> <Property key="Caption" value="#{sCreateClassMenu1}"/>
</Widget> </Widget>

@ -21,7 +21,9 @@
<!-- Dialog buttons --> <!-- Dialog buttons -->
<Widget type="HBox" position="0 219 319 24"> <Widget type="HBox" position="0 219 319 24">
<Widget type="Widget"/> <!-- spacer --> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="BackButton"> <Widget type="AutoSizedButton" skin="MW_Button" name="BackButton">
<Property key="Caption" value="#{sBack}"/> <Property key="Caption" value="#{sBack}"/>
</Widget> </Widget>

@ -57,7 +57,10 @@
<!-- Dialog buttons --> <!-- Dialog buttons -->
<Widget type="HBox" position="0 397 574 24"> <Widget type="HBox" position="0 397 574 24">
<Widget type="Widget"/> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="471 397 53 23" name="BackButton"> <Widget type="AutoSizedButton" skin="MW_Button" position="471 397 53 23" name="BackButton">
<Property key="Caption" value="#{sBack}"/> <Property key="Caption" value="#{sBack}"/>
</Widget> </Widget>

@ -112,7 +112,9 @@
<!-- Dialog buttons --> <!-- Dialog buttons -->
<Widget type="HBox" position="0 372 502 24"> <Widget type="HBox" position="0 372 502 24">
<Widget type="Widget"/> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="BackButton"> <Widget type="AutoSizedButton" skin="MW_Button" name="BackButton">
<Property key="Caption" value="#{sBack}"/> <Property key="Caption" value="#{sBack}"/>
</Widget> </Widget>

@ -14,7 +14,9 @@
</Widget> </Widget>
<Widget type="HBox" position="0 84 272 24" align="Right Bottom"> <Widget type="HBox" position="0 84 272 24" align="Right Bottom">
<Widget type="Widget"/> <!-- spacer --> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="CancelButton" align="Right Bottom"> <Widget type="AutoSizedButton" skin="MW_Button" name="CancelButton" align="Right Bottom">
<Property key="Caption" value="#{sCancel}"/> <Property key="Caption" value="#{sCancel}"/>
</Widget> </Widget>

@ -12,7 +12,9 @@
</Widget> </Widget>
<Widget type="HBox" position="0 235 580 24" align="Right Bottom"> <Widget type="HBox" position="0 235 580 24" align="Right Bottom">
<Widget type="Widget"/> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="TakeButton" align="Right Bottom"> <Widget type="AutoSizedButton" skin="MW_Button" name="TakeButton" align="Right Bottom">
<Property key="Caption" value="#{sTakeAll}"/> <Property key="Caption" value="#{sTakeAll}"/>
</Widget> </Widget>

@ -22,7 +22,9 @@
<Widget type="HBox" position="0 90 572 24" align="Right Bottom"> <Widget type="HBox" position="0 90 572 24" align="Right Bottom">
<Widget type="Widget"/> <!-- spacer --> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="417 90 60 24" name="CancelButton" align="Right Top"> <Widget type="AutoSizedButton" skin="MW_Button" position="417 90 60 24" name="CancelButton" align="Right Top">
<Property key="Caption" value="#{sCancel}"/> <Property key="Caption" value="#{sCancel}"/>
</Widget> </Widget>

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 440 438" name="_Main">
<Widget type="Widget" skin="MW_Box" position="28 14 391 198">
<Widget type="ImageBox" skin="ImageBox" name="ClassImage" position="4 4 383 190">
</Widget>
</Widget>
<Widget type="TextBox" skin="SandText" position="28 218 391 24" name="LevelText">
</Widget>
<Widget type="Widget" skin="" position="36 280 400 400">
<Widget type="TextBox" skin="SandText" position="0 0 100 24" name="AttribMultiplier1"/>
<Widget type="TextBox" skin="SandText" position="0 24 100 24" name="AttribMultiplier2"/>
<Widget type="TextBox" skin="SandText" position="0 48 100 24" name="AttribMultiplier3"/>
<Widget type="TextBox" skin="SandText" position="0 72 100 24" name="AttribMultiplier4"/>
<Widget type="TextBox" skin="SandText" position="200 0 100 24" name="AttribMultiplier5"/>
<Widget type="TextBox" skin="SandText" position="200 24 100 24" name="AttribMultiplier6"/>
<Widget type="TextBox" skin="SandText" position="200 48 100 24" name="AttribMultiplier7"/>
<Widget type="TextBox" skin="SandText" position="200 72 100 24" name="AttribMultiplier8"/>
<Widget type="HBox" position="22 0 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib1">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeStrength}"/>
<UserString key="Caption_AttributeDescription" value="#{sStrDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_strength.dds"/>
<Property key="Caption" value="#{sAttributeStrength}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal1">
</Widget>
</Widget>
<Widget type="HBox" position="22 24 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib2">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeIntelligence}"/>
<UserString key="Caption_AttributeDescription" value="#{sIntDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_int.dds"/>
<Property key="Caption" value="#{sAttributeIntelligence}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal2">
</Widget>
</Widget>
<Widget type="HBox" position="22 48 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib3">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeWillpower}"/>
<UserString key="Caption_AttributeDescription" value="#{sWilDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_wilpower.dds"/>
<Property key="Caption" value="#{sAttributeWillpower}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal3">
</Widget>
</Widget>
<Widget type="HBox" position="22 72 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib4">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeAgility}"/>
<UserString key="Caption_AttributeDescription" value="#{sAgiDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_agility.dds"/>
<Property key="Caption" value="#{sAttributeAgility}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal4">
</Widget>
</Widget>
<Widget type="HBox" position="222 0 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib5">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeSpeed}"/>
<UserString key="Caption_AttributeDescription" value="#{sSpdDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_speed.dds"/>
<Property key="Caption" value="#{sAttributeSpeed}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal5">
</Widget>
</Widget>
<Widget type="HBox" position="222 24 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib6">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeEndurance}"/>
<UserString key="Caption_AttributeDescription" value="#{sEndDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_endurance.dds"/>
<Property key="Caption" value="#{sAttributeEndurance}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal6">
</Widget>
</Widget>
<Widget type="HBox" position="222 48 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib7">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributePersonality}"/>
<UserString key="Caption_AttributeDescription" value="#{sPerDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_personality.dds"/>
<Property key="Caption" value="#{sAttributePersonality}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal7">
</Widget>
</Widget>
<Widget type="HBox" position="222 72 200 24">
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib8">
<UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
<UserString key="Caption_AttributeName" value="#{sAttributeLuck}"/>
<UserString key="Caption_AttributeDescription" value="#{sLucDesc}"/>
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_luck.dds"/>
<Property key="Caption" value="#{sAttributeLuck}"/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal8">
</Widget>
</Widget>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" position="422 398 0 24" name="OkButton">
<Property key="ExpandDirection" value="Left"/>
<Property key="Caption" value="#{sOk}"/>
</Widget>
</Widget>
</MyGUI>

@ -3,21 +3,32 @@
<MyGUI type="Layout"> <MyGUI type="Layout">
<Widget type="Window" skin="MW_Window_Pinnable" layer="Windows" position="0 0 300 300" name="_Main"> <Widget type="Window" skin="MW_Window_Pinnable" layer="Windows" position="0 0 300 300" name="_Main">
<!-- Global map -->
<Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="ALIGN_STRETCH" name="GlobalMap">
</Widget>
<!-- Local map --> <!-- Local map -->
<Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="ALIGN_STRETCH" name="LocalMap"> <Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="ALIGN_STRETCH" name="LocalMap">
<Property key="CanvasSize" value="1536 1536"/> <Property key="CanvasSize" value="1536 1536"/>
<Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="ALIGN_TOP ALIGN_LEFT" name="Compass"> <Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="ALIGN_TOP ALIGN_LEFT" name="CompassLocal">
<Property key="ImageTexture" value="textures\compass.dds"/>
</Widget>
<Widget type="Button" skin="" position_real="0 0 1 1" name="EventBoxLocal" align="ALIGN_STRETCH"/>
</Widget>
<!-- Global map -->
<Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="ALIGN_STRETCH" name="GlobalMap">
<Property key="CanvasSize" value="1536 1536"/>
<Widget type="ImageBox" skin="ImageBox" position_real="0 0 1 1" align="Stretch" name="GlobalMapImage">
</Widget>
<Widget type="ImageBox" skin="RotatingSkin" position="0 0 32 32" align="ALIGN_TOP ALIGN_LEFT" name="CompassGlobal">
<Property key="ImageTexture" value="textures\compass.dds"/> <Property key="ImageTexture" value="textures\compass.dds"/>
</Widget> </Widget>
<Widget type="Button" skin="" position="0 0 1536 1536" name="EventBox" align="ALIGN_STRETCH"/> <Widget type="Button" skin="" position_real="0 0 1 1" name="EventBoxGlobal" align="ALIGN_STRETCH"/>
</Widget> </Widget>
<!-- World button --> <!-- World button -->
<Widget type="AutoSizedButton" skin="MW_Button" position="213 233 61 22" align="ALIGN_BOTTOM ALIGN_RIGHT" name="WorldButton"> <Widget type="AutoSizedButton" skin="MW_Button" position="213 233 61 22" align="ALIGN_BOTTOM ALIGN_RIGHT" name="WorldButton">
<Property key="ExpandDirection" value="Left"/> <Property key="ExpandDirection" value="Left"/>

@ -157,7 +157,7 @@
<Widget type="TabItem" skin="" position="4 28 344 272"> <Widget type="TabItem" skin="" position="4 28 344 272">
<Property key="Caption" value=" Video "/> <Property key="Caption" value=" Video "/>
<Widget type="ListBox" skin="MW_List" position="4 4 200 150" align="Left Top" name="ResolutionList"/> <Widget type="ListBox" skin="MW_List" position="4 4 200 120" align="Left Top" name="ResolutionList"/>
<Widget type="HBox" position="212 4 300 24"> <Widget type="HBox" position="212 4 300 24">
@ -174,20 +174,37 @@
</Widget> </Widget>
</Widget> </Widget>
<Widget type="HBox" position="212 104 300 24"> <Widget type="HBox" position="212 64 300 24">
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="ShadersButton"/> <Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="ShadersButton"/>
<Widget type="AutoSizedTextBox" skin="SandText" align="Left Top"> <Widget type="AutoSizedTextBox" skin="SandText" align="Left Top">
<Property key="Caption" value="Shaders"/> <Property key="Caption" value="Shaders"/>
</Widget> </Widget>
</Widget> </Widget>
<Widget type="HBox" position="4 163 300 24"> <Widget type="HBox" position="212 94 300 24">
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="FPSButton"/> <Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="FPSButton"/>
<Widget type="AutoSizedTextBox" skin="SandText" align="Left Top"> <Widget type="AutoSizedTextBox" skin="SandText" align="Left Top">
<Property key="Caption" value="Show frames per second"/> <Property key="Caption" value="FPS"/>
</Widget> </Widget>
</Widget> </Widget>
<Widget type="TextBox" skin="NormalText" position="4 128 329 18" align="Left Top" name="GammaText">
<Property key="Caption" value="Gamma"/>
</Widget>
<Widget type="ScrollBar" skin="MW_HSlider" position="4 152 329 18" align="Left Top" name="GammaSlider">
<Property key="Range" value="1000000"/>
</Widget>
<Widget type="TextBox" skin="SandText" position="4 176 329 18" align="Left Top">
<Property key="Caption" value="#{sDark_Gamma}"/>
<Property key="TextAlign" value="Left"/>
</Widget>
<Widget type="TextBox" skin="SandText" position="4 176 329 18" align="Left Top">
<Property key="Caption" value="#{sLight_Gamma}"/>
<Property key="TextAlign" value="Right"/>
</Widget>
<Widget type="TextBox" skin="NormalText" position="4 198 329 18" align="Left Top" name="FovText"> <Widget type="TextBox" skin="NormalText" position="4 198 329 18" align="Left Top" name="FovText">
<Property key="Caption" value="Field of View"/> <Property key="Caption" value="Field of View"/>
</Widget> </Widget>

@ -56,7 +56,9 @@
</Widget> </Widget>
<Widget type="HBox" position="0 60 566 24" align="Right Bottom"> <Widget type="HBox" position="0 60 566 24" align="Right Bottom">
<Widget type="Widget"/> <Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="OfferButton" align="Right Top"> <Widget type="AutoSizedButton" skin="MW_Button" name="OfferButton" align="Right Top">
<Property key="Caption" value="#{sBarterDialog8}"/> <Property key="Caption" value="#{sBarterDialog8}"/>
</Widget> </Widget>

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="VBox" skin="MW_Dialog" layer="Windows" position="0 0 600 200" name="_Main">
<Property key="Padding" value="12"/>
<Property key="Spacing" value="8"/>
<Property key="AutoResize" value="true"/>
<Widget type="AutoSizedTextBox" skin="SandText" name="DateTimeText">
<Property key="Caption" value="24 Herzfeuer (Tag 24) 2 a.m."/>
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="RestText">
</Widget>
<Widget type="AutoSizedTextBox" skin="SandText" name="HourText">
</Widget>
<Widget type="ScrollBar" skin="MW_HScroll" name="HourSlider" position="0 0 0 18">
<Property key="MoveToClick" value="true"/>
<Property key="Range" value="24"/>
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="HBox">
<UserString key="HStretch" value="true"/>
<Widget type="Widget">
<UserString key="HStretch" value="true"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="UntilHealedButton">
<Property key="Caption" value="#{sUntilHealed}"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="WaitButton">
<Property key="Caption" value="#{sRest}"/>
</Widget>
<Widget type="AutoSizedButton" skin="MW_Button" name="CancelButton">
<Property key="Caption" value="#{sCancel}"/>
</Widget>
</Widget>
</Widget>
</MyGUI>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 219 40" name="_Main">
<Widget type="ProgressBar" skin="MW_Progress_Blue" position="5 6 199 20" name="ProgressBar">
<Widget type="TextBox" skin="SandText" position="0 0 199 20" name="ProgressText">
<Property key="TextAlign" value="Center"/>
</Widget>
</Widget>
</Widget>
</MyGUI>

@ -24,6 +24,12 @@ antialiasing = none
vsync = false vsync = false
# opengl render to texture mode, valid options:
# PBuffer, FBO, Copy
opengl rtt mode = FBO
gamma = 2.2
[GUI] [GUI]
# 1 is fully opaque # 1 is fully opaque
menu transparency = 0.84 menu transparency = 0.84

@ -4,7 +4,7 @@
#include <OgreResource.h> #include <OgreResource.h>
#include <OgreResourceManager.h> #include <OgreResourceManager.h>
#include <btBulletCollisionCommon.h> #include <btBulletCollisionCommon.h>
#include <OgreVector3.h>
//For some reason, Ogre Singleton cannot be used in another namespace, that's why there is no namespace here. //For some reason, Ogre Singleton cannot be used in another namespace, that's why there is no namespace here.
//But the risk of name collision seems pretty low here. //But the risk of name collision seems pretty low here.
@ -31,6 +31,8 @@ public:
virtual ~BulletShape(); virtual ~BulletShape();
btCollisionShape* Shape; btCollisionShape* Shape;
Ogre::Vector3 boxTranslation;
Ogre::Quaternion boxRotation;
//this flag indicate if the shape is used for collision or if it's for raycasting only. //this flag indicate if the shape is used for collision or if it's for raycasting only.
bool collide; bool collide;
}; };

@ -2,6 +2,7 @@
#include <btBulletDynamicsCommon.h> #include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h> #include <btBulletCollisionCommon.h>
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h> #include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
#include "pmove.h"
#include <components/nifbullet/bullet_nif_loader.hpp> #include <components/nifbullet/bullet_nif_loader.hpp>
#include "CMotionState.h" #include "CMotionState.h"
#include "OgreRoot.h" #include "OgreRoot.h"
@ -26,111 +27,139 @@ namespace Physic
COL_RAYCASTING = BIT(3) COL_RAYCASTING = BIT(3)
}; };
PhysicActor::PhysicActor(std::string name) PhysicActor::PhysicActor(std::string name, std::string mesh, PhysicEngine* engine, Ogre::Vector3 position, Ogre::Quaternion rotation, float scale):
{ mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0), mBody(0), collisionMode(false), mBoxRotation(0,0,0,0)
mName = name; {
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation);
// The capsule is at the origin Ogre::Quaternion inverse = mBoxRotation.Inverse();
btTransform transform; mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w);
transform.setIdentity(); mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map
pmove = new playerMove;
// External capsule pmove->mEngine = mEngine;
externalGhostObject = new PairCachingGhostObject(name); btBoxShape* box = static_cast<btBoxShape*> (mBody->getCollisionShape());
externalGhostObject->setWorldTransform( transform ); if(box != NULL){
btVector3 size = box->getHalfExtentsWithMargin();
btScalar externalCapsuleHeight = 120; Ogre::Vector3 halfExtents = Ogre::Vector3(size.getX(), size.getY(), size.getZ());
btScalar externalCapsuleWidth = 19; pmove->ps.halfExtents = halfExtents;
}
externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight );
externalCollisionShape->setMargin( 0.1 );
externalGhostObject->setCollisionShape( externalCollisionShape );
externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT );
// Internal capsule
internalGhostObject = new PairCachingGhostObject(name);
internalGhostObject->setWorldTransform( transform );
//internalGhostObject->getBroadphaseHandle()->s
btScalar internalCapsuleHeight = 110;
btScalar internalCapsuleWidth = 17;
internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight );
internalCollisionShape->setMargin( 0.1 );
internalGhostObject->setCollisionShape( internalCollisionShape );
internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT );
mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 40 ),1,4,20,9.8,0.2 );
mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS);
mCharacter->setUseGhostSweepTest(false);
mCharacter->mCollision = false;
setGravity(0);
mTranslation = btVector3(0,0,70);
} }
PhysicActor::~PhysicActor() PhysicActor::~PhysicActor()
{ {
delete mCharacter; if(mBody){
delete internalGhostObject; mEngine->dynamicsWorld->removeRigidBody(mBody);
delete internalCollisionShape; delete mBody;
delete externalGhostObject; }
delete externalCollisionShape; delete pmove;
}
void PhysicActor::setCurrentWater(bool hasWater, int waterHeight){
pmove->hasWater = hasWater;
if(hasWater){
pmove->waterHeight = waterHeight;
}
} }
void PhysicActor::setGravity(float gravity) void PhysicActor::setGravity(float gravity)
{ {
mCharacter->setGravity(gravity); pmove->ps.gravity = gravity;
//mCharacter-> }
void PhysicActor::setSpeed(float speed)
{
pmove->ps.speed = speed;
} }
void PhysicActor::enableCollisions(bool collision) void PhysicActor::enableCollisions(bool collision)
{ {
mCharacter->mCollision = collision; collisionMode = collision;
if(collisionMode)
pmove->ps.move_type=PM_NORMAL;
else
pmove->ps.move_type=PM_NOCLIP;
} }
void PhysicActor::setVerticalVelocity(float z) void PhysicActor::setJumpVelocity(float velocity)
{ {
mCharacter->setVerticalVelocity(z); pmove->ps.jump_velocity = velocity;
} }
bool PhysicActor::getCollisionMode() bool PhysicActor::getCollisionMode()
{ {
return mCharacter->mCollision; return collisionMode;
} }
void PhysicActor::setWalkDirection(const btVector3& mvt) void PhysicActor::setMovement(signed char rightmove, signed char forwardmove, signed char upmove)
{ {
mCharacter->setWalkDirection( mvt ); playerMove::playercmd& pm_ref = pmove->cmd;
pm_ref.rightmove = rightmove;
pm_ref.forwardmove = forwardmove;
pm_ref.upmove = upmove;
} }
void PhysicActor::Rotate(const btQuaternion& quat) void PhysicActor::setPmoveViewAngles(float pitch, float yaw, float roll){
{ pmove->ps.viewangles.x = pitch;
externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat ); pmove->ps.viewangles.y = yaw;
internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat ); pmove->ps.viewangles.z = roll;
} }
void PhysicActor::setRotation(const btQuaternion& quat)
void PhysicActor::setRotation(const Ogre::Quaternion quat)
{ {
externalGhostObject->getWorldTransform().setRotation( quat ); if(!quat.equals(getRotation(), Ogre::Radian(0))){
internalGhostObject->getWorldTransform().setRotation( quat ); mEngine->adjustRigidBody(mBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation);
}
} }
btVector3 PhysicActor::getPosition(void) Ogre::Vector3 PhysicActor::getPosition()
{ {
return internalGhostObject->getWorldTransform().getOrigin() -mTranslation; btVector3 vec = mBody->getWorldTransform().getOrigin();
Ogre::Quaternion rotation = Ogre::Quaternion(mBody->getWorldTransform().getRotation().getW(), mBody->getWorldTransform().getRotation().getX(),
mBody->getWorldTransform().getRotation().getY(), mBody->getWorldTransform().getRotation().getZ());
Ogre::Vector3 transrot = rotation * mBoxScaledTranslation;
Ogre::Vector3 visualPosition = Ogre::Vector3(vec.getX(), vec.getY(), vec.getZ()) - transrot;
return visualPosition;
} }
btQuaternion PhysicActor::getRotation(void) Ogre::Quaternion PhysicActor::getRotation()
{ {
return internalGhostObject->getWorldTransform().getRotation(); btQuaternion quat = mBody->getWorldTransform().getRotation() * mBoxRotationInverse;
return Ogre::Quaternion(quat.getW(), quat.getX(), quat.getY(), quat.getZ());
} }
void PhysicActor::setPosition(const btVector3& pos) void PhysicActor::setPosition(const Ogre::Vector3 pos)
{ {
internalGhostObject->getWorldTransform().setOrigin(pos+mTranslation); mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
externalGhostObject->getWorldTransform().setOrigin(pos+mTranslation); btVector3 vec = mBody->getWorldTransform().getOrigin();
pmove->ps.origin = Ogre::Vector3(vec.getX(), vec.getY(), vec.getZ());
}
void PhysicActor::setScale(float scale){
Ogre::Vector3 position = getPosition();
Ogre::Quaternion rotation = getRotation();
//We only need to change the scaled box translation, box rotations remain the same.
mBoxScaledTranslation = mBoxScaledTranslation / mBody->getCollisionShape()->getLocalScaling().getX();
mBoxScaledTranslation *= scale;
if(mBody){
mEngine->dynamicsWorld->removeRigidBody(mBody);
delete mBody;
}
//Create the newly scaled rigid body
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation);
mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map
btBoxShape* box = static_cast<btBoxShape*> (mBody->getCollisionShape());
if(box != NULL){
btVector3 size = box->getHalfExtentsWithMargin();
Ogre::Vector3 halfExtents = Ogre::Vector3(size.getX(), size.getY(), size.getZ());
pmove->ps.halfExtents = halfExtents;
}
}
void PhysicActor::runPmove(){
Pmove(pmove);
Ogre::Vector3 newpos = pmove->ps.origin;
mBody->getWorldTransform().setOrigin(btVector3(newpos.x, newpos.y, newpos.z));
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -230,8 +259,8 @@ namespace Physic
delete hf_it->second.mBody; delete hf_it->second.mBody;
} }
RigidBodyContainer::iterator rb_it = RigidBodyMap.begin(); RigidBodyContainer::iterator rb_it = ObjectMap.begin();
for (; rb_it != RigidBodyMap.end(); ++rb_it) for (; rb_it != ObjectMap.end(); ++rb_it)
{ {
if (rb_it->second != NULL) if (rb_it->second != NULL)
{ {
@ -247,9 +276,7 @@ namespace Physic
{ {
if (pa_it->second != NULL) if (pa_it->second != NULL)
{ {
dynamicsWorld->removeCollisionObject(pa_it->second->externalGhostObject);
dynamicsWorld->removeCollisionObject(pa_it->second->internalGhostObject);
dynamicsWorld->removeAction(pa_it->second->mCharacter);
delete pa_it->second; delete pa_it->second;
pa_it->second = NULL; pa_it->second = NULL;
@ -332,18 +359,42 @@ namespace Physic
mHeightFieldMap.erase(name); mHeightFieldMap.erase(name);
} }
RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) void PhysicEngine::adjustRigidBody(RigidBody* body, Ogre::Vector3 position, Ogre::Quaternion rotation,
{ Ogre::Vector3 scaledBoxTranslation, Ogre::Quaternion boxRotation){
btTransform tr;
rotation = rotation * boxRotation;
Ogre::Vector3 transrot = rotation * scaledBoxTranslation;
Ogre::Vector3 newPosition = transrot + position;
tr.setOrigin(btVector3(newPosition.x, newPosition.y, newPosition.z));
tr.setRotation(btQuaternion(rotation.x,rotation.y,rotation.z,rotation.w));
body->setWorldTransform(tr);
}
void PhysicEngine::boxAdjustExternal(std::string mesh, RigidBody* body, float scale, Ogre::Vector3 position, Ogre::Quaternion rotation){
std::string sid = (boost::format("%07.3f") % scale).str(); std::string sid = (boost::format("%07.3f") % scale).str();
std::string outputstring = mesh + sid; std::string outputstring = mesh + sid;
//std::cout << "The string" << outputstring << "\n"; //std::cout << "The string" << outputstring << "\n";
//get the shape from the .nif
mShapeLoader->load(outputstring,"General");
BulletShapeManager::getSingletonPtr()->load(outputstring,"General");
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General");
adjustRigidBody(body, position, rotation, shape->boxTranslation * scale, shape->boxRotation);
}
RigidBody* PhysicEngine::createAndAdjustRigidBody(std::string mesh,std::string name,float scale, Ogre::Vector3 position, Ogre::Quaternion rotation,
Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation)
{
std::string sid = (boost::format("%07.3f") % scale).str();
std::string outputstring = mesh + sid;
//get the shape from the .nif //get the shape from the .nif
mShapeLoader->load(outputstring,"General"); mShapeLoader->load(outputstring,"General");
BulletShapeManager::getSingletonPtr()->load(outputstring,"General"); BulletShapeManager::getSingletonPtr()->load(outputstring,"General");
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General");
shape->Shape->setLocalScaling( btVector3(scale,scale,scale)); shape->Shape->setLocalScaling( btVector3(scale,scale,scale));
//btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(dynamic_cast<btBvhTriangleMeshShape*> (shape->Shape), btVector3(scale,scale,scale));
//create the motionState //create the motionState
CMotionState* newMotionState = new CMotionState(this,name); CMotionState* newMotionState = new CMotionState(this,name);
@ -352,11 +403,19 @@ namespace Physic
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape);
RigidBody* body = new RigidBody(CI,name); RigidBody* body = new RigidBody(CI,name);
body->collide = shape->collide; body->collide = shape->collide;
if(scaledBoxTranslation != 0)
*scaledBoxTranslation = shape->boxTranslation * scale;
if(boxRotation != 0)
*boxRotation = shape->boxRotation;
adjustRigidBody(body, position, rotation, shape->boxTranslation * scale, shape->boxRotation);
return body; return body;
} }
void PhysicEngine::addRigidBody(RigidBody* body) void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap)
{ {
if(body) if(body)
{ {
@ -369,21 +428,23 @@ namespace Physic
dynamicsWorld->addRigidBody(body,COL_RAYCASTING,COL_RAYCASTING|COL_WORLD); dynamicsWorld->addRigidBody(body,COL_RAYCASTING,COL_RAYCASTING|COL_WORLD);
} }
body->setActivationState(DISABLE_DEACTIVATION); body->setActivationState(DISABLE_DEACTIVATION);
RigidBody* oldBody = RigidBodyMap[body->mName]; if(addToMap){
if (oldBody != NULL) RigidBody* oldBody = ObjectMap[body->mName];
{ if (oldBody != NULL)
dynamicsWorld->removeRigidBody(oldBody); {
delete oldBody; dynamicsWorld->removeRigidBody(oldBody);
delete oldBody;
}
ObjectMap[body->mName] = body;
} }
RigidBodyMap[body->mName] = body;
} }
} }
void PhysicEngine::removeRigidBody(std::string name) void PhysicEngine::removeRigidBody(std::string name)
{ {
RigidBodyContainer::iterator it = RigidBodyMap.find(name); RigidBodyContainer::iterator it = ObjectMap.find(name);
if (it != RigidBodyMap.end() ) if (it != ObjectMap.end() )
{ {
RigidBody* body = it->second; RigidBody* body = it->second;
if(body != NULL) if(body != NULL)
@ -402,8 +463,8 @@ namespace Physic
void PhysicEngine::deleteRigidBody(std::string name) void PhysicEngine::deleteRigidBody(std::string name)
{ {
RigidBodyContainer::iterator it = RigidBodyMap.find(name); RigidBodyContainer::iterator it = ObjectMap.find(name);
if (it != RigidBodyMap.end() ) if (it != ObjectMap.end() )
{ {
RigidBody* body = it->second; RigidBody* body = it->second;
//btScaledBvhTriangleMeshShape* scaled = dynamic_cast<btScaledBvhTriangleMeshShape*> (body->getCollisionShape()); //btScaledBvhTriangleMeshShape* scaled = dynamic_cast<btScaledBvhTriangleMeshShape*> (body->getCollisionShape());
@ -416,16 +477,16 @@ namespace Physic
{ {
delete scaled; delete scaled;
}*/ }*/
RigidBodyMap.erase(it); ObjectMap.erase(it);
} }
} }
RigidBody* PhysicEngine::getRigidBody(std::string name) RigidBody* PhysicEngine::getRigidBody(std::string name)
{ {
RigidBodyContainer::iterator it = RigidBodyMap.find(name); RigidBodyContainer::iterator it = ObjectMap.find(name);
if (it != RigidBodyMap.end() ) if (it != ObjectMap.end() )
{ {
RigidBody* body = RigidBodyMap[name]; RigidBody* body = ObjectMap[name];
return body; return body;
} }
else else
@ -443,16 +504,17 @@ namespace Physic
} }
} }
void PhysicEngine::addCharacter(std::string name) void PhysicEngine::addCharacter(std::string name, std::string mesh,
Ogre::Vector3 position, float scale, Ogre::Quaternion rotation)
{ {
// Remove character with given name, so we don't make memory // Remove character with given name, so we don't make memory
// leak when character would be added twice // leak when character would be added twice
removeCharacter(name); removeCharacter(name);
PhysicActor* newActor = new PhysicActor(name); PhysicActor* newActor = new PhysicActor(name, mesh, this, position, rotation, scale);
dynamicsWorld->addCollisionObject( newActor->externalGhostObject, COL_ACTOR_EXTERNAL, COL_WORLD |COL_ACTOR_EXTERNAL );
dynamicsWorld->addCollisionObject( newActor->internalGhostObject, COL_ACTOR_INTERNAL, COL_WORLD |COL_ACTOR_INTERNAL );
dynamicsWorld->addAction( newActor->mCharacter ); //dynamicsWorld->addAction( newActor->mCharacter );
PhysicActorMap[name] = newActor; PhysicActorMap[name] = newActor;
} }
@ -465,25 +527,11 @@ namespace Physic
PhysicActor* act = it->second; PhysicActor* act = it->second;
if(act != NULL) if(act != NULL)
{ {
/*broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher);
broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher);
PhysicActorContainer::iterator it2 = PhysicActorMap.begin();
for(;it2!=PhysicActorMap.end();it++)
{
it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher);
it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher);
it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher);
it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher);
}*/
//act->externalGhostObject->
dynamicsWorld->removeCollisionObject(act->externalGhostObject);
dynamicsWorld->removeCollisionObject(act->internalGhostObject);
dynamicsWorld->removeAction(act->mCharacter);
delete act; delete act;
} }
PhysicActorMap.erase(it); PhysicActorMap.erase(it);
} }
//std::cout << "ok";
} }
PhysicActor* PhysicEngine::getCharacter(std::string name) PhysicActor* PhysicEngine::getCharacter(std::string name)

@ -9,14 +9,16 @@
#include "BulletShapeLoader.h" #include "BulletShapeLoader.h"
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
class btRigidBody; class btRigidBody;
class btBroadphaseInterface; class btBroadphaseInterface;
class btDefaultCollisionConfiguration; class btDefaultCollisionConfiguration;
class btSequentialImpulseConstraintSolver; class btSequentialImpulseConstraintSolver;
class btCollisionDispatcher; class btCollisionDispatcher;
class btDiscreteDynamicsWorld; class btDiscreteDynamicsWorld;
class btKinematicCharacterController;
class btHeightfieldTerrainShape; class btHeightfieldTerrainShape;
struct playerMove;
namespace BtOgre namespace BtOgre
{ {
@ -28,11 +30,14 @@ namespace MWWorld
class World; class World;
} }
namespace OEngine { namespace OEngine {
namespace Physic namespace Physic
{ {
class CMotionState; class CMotionState;
struct PhysicEvent; struct PhysicEvent;
class PhysicEngine;
class RigidBody;
/** /**
*This is just used to be able to name objects. *This is just used to be able to name objects.
@ -50,55 +55,88 @@ namespace Physic
}; };
/** /**
* A physic Actor use a modifed KinematicCharacterController taken in the bullet forum. * A physic actor uses a rigid body based on box shapes.
* Pmove is used to move the physic actor around the dynamic world.
*/ */
class PhysicActor class PhysicActor
{ {
public: public:
PhysicActor(std::string name); PhysicActor(std::string name, std::string mesh, PhysicEngine *engine, Ogre::Vector3 position, Ogre::Quaternion rotation, float scale);
~PhysicActor(); ~PhysicActor();
void setCurrentWater(bool hasWater, int waterHeight);
/** /**
* This function set the walkDirection. This is not relative to the actor orientation. * This function sets the movement keys for pmove
* I think it's also needed to take time into account. A typical call should look like this:
* setWalkDirection( mvt * orientation * dt)
*/ */
void setWalkDirection(const btVector3& mvt); void setMovement(signed char rightmove, signed char forwardmove, signed char upmove);
void Rotate(const btQuaternion& quat); /**
* This adjusts the rotation of a PhysicActor
void setRotation(const btQuaternion& quat); * If we have any problems with this (getting stuck in pmove) we should change it
* from setting the visual orientation to setting the orientation of the rigid body directly.
*/
void setRotation(const Ogre::Quaternion quat);
void setGravity(float gravity); void setGravity(float gravity);
void setVerticalVelocity(float z); void setSpeed(float speed);
void setJumpVelocity(float velocity);
void enableCollisions(bool collision); void enableCollisions(bool collision);
bool getCollisionMode(); bool getCollisionMode();
btVector3 getPosition(void); /**
* This returns the visual position of the PhysicActor (used to position a scenenode).
* Note - this is different from the position of the contained mBody.
*/
Ogre::Vector3 getPosition();
btQuaternion getRotation(void); /**
* Returns the visual orientation of the PhysicActor
*/
Ogre::Quaternion getRotation();
void setPosition(const btVector3& pos); /**
* Sets the position of mBody from a visual position input.
* For most cases this should not be used. We should instead let pmove move the PhysicActor around for us
*/
void setPosition(const Ogre::Vector3 pos);
btKinematicCharacterController* mCharacter; /**
* Sets the view angles for pmove directly.
* Remember, add 90 for yaw. Set roll to 0.
*/
void setPmoveViewAngles(float pitch, float yaw, float roll);
PairCachingGhostObject* internalGhostObject; /**
btCollisionShape* internalCollisionShape; * Sets the scale of the PhysicActor
*/
void setScale(float scale);
PairCachingGhostObject* externalGhostObject; /**
btCollisionShape* externalCollisionShape; * Runs pmove for this PhysicActor
*/
void runPmove();
std::string mName;
/**
*NPC scenenode is located on there feet, and you can't simply translate a btShape, so this vector is used private:
*each time get/setposition is called.
*/ OEngine::Physic::RigidBody* mBody;
btVector3 mTranslation; Ogre::Vector3 mBoxScaledTranslation;
btQuaternion mBoxRotationInverse;
Ogre::Quaternion mBoxRotation;
bool collisionMode;
std::string mMesh;
PhysicEngine* mEngine;
std::string mName;
playerMove* pmove;
}; };
/** /**
@ -143,11 +181,22 @@ namespace Physic
~PhysicEngine(); ~PhysicEngine();
/** /**
* Create a RigidBody.It does not add it to the simulation, but it does add it to the rigidBody Map, * Creates a RigidBody. It does not add it to the simulation.
* so you can get it with the getRigidBody function. * After created, the body is set to the correct rotation, position, and scale
*/ */
RigidBody* createRigidBody(std::string mesh,std::string name,float scale); RigidBody* createAndAdjustRigidBody(std::string mesh,std::string name,float scale, Ogre::Vector3 position, Ogre::Quaternion rotation,
Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0);
/**
* Adjusts a rigid body to the right position and rotation
*/
void adjustRigidBody(RigidBody* body, Ogre::Vector3 position, Ogre::Quaternion rotation,
Ogre::Vector3 scaledBoxTranslation = Ogre::Vector3::ZERO, Ogre::Quaternion boxRotation = Ogre::Quaternion::IDENTITY);
/**
Mainly used to (but not limited to) adjust rigid bodies based on box shapes to the right position and rotation.
*/
void boxAdjustExternal(std::string mesh, RigidBody* body, float scale, Ogre::Vector3 position, Ogre::Quaternion rotation);
/** /**
* Add a HeightField to the simulation * Add a HeightField to the simulation
*/ */
@ -163,7 +212,7 @@ namespace Physic
/** /**
* Add a RigidBody to the simulation * Add a RigidBody to the simulation
*/ */
void addRigidBody(RigidBody* body); void addRigidBody(RigidBody* body, bool addToMap = true);
/** /**
* Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. * Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap.
@ -184,7 +233,8 @@ namespace Physic
/** /**
* Create and add a character to the scene, and add it to the ActorMap. * Create and add a character to the scene, and add it to the ActorMap.
*/ */
void addCharacter(std::string name); void addCharacter(std::string name, std::string mesh,
Ogre::Vector3 position, float scale, Ogre::Quaternion rotation);
/** /**
* Remove a character from the scene. TODO:delete it! for now, a small memory leak^^ done? * Remove a character from the scene. TODO:delete it! for now, a small memory leak^^ done?
@ -254,7 +304,7 @@ namespace Physic
HeightFieldContainer mHeightFieldMap; HeightFieldContainer mHeightFieldMap;
typedef std::map<std::string,RigidBody*> RigidBodyContainer; typedef std::map<std::string,RigidBody*> RigidBodyContainer;
RigidBodyContainer RigidBodyMap; RigidBodyContainer ObjectMap;
typedef std::map<std::string, PhysicActor*> PhysicActorContainer; typedef std::map<std::string, PhysicActor*> PhysicActorContainer;
PhysicActorContainer PhysicActorMap; PhysicActorContainer PhysicActorMap;
@ -263,6 +313,7 @@ namespace Physic
BtOgre::DebugDrawer* mDebugDrawer; BtOgre::DebugDrawer* mDebugDrawer;
bool isDebugCreated; bool isDebugCreated;
bool mDebugActive; bool mDebugActive;
}; };

@ -231,7 +231,7 @@ bool PM_SlideMove( bool gravity )
// see if we can make it there // see if we can make it there
//pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemaskg); //pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemaskg);
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj);
newtrace(&trace, pm->ps.origin, end, halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(&trace, pm->ps.origin, end, pm->ps.halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
if (trace.allsolid) if (trace.allsolid)
{ {
@ -301,7 +301,7 @@ bool PM_SlideMove( bool gravity )
if(planes[i].x >= .70) if(planes[i].x >= .70)
{ {
pm->ps.velocity = Ogre::Vector3(0,0,0); pm->ps.velocity.z = 0;
return true; return true;
} }
// see how hard we are hitting things // see how hard we are hitting things
@ -449,7 +449,7 @@ int PM_StepSlideMove( bool gravity )
//pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); //pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
//tracefunc(&trace, start_o, down, , 0, pml.scene); //tracefunc(&trace, start_o, down, , 0, pml.scene);
//tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj); //tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj);
newtrace(&trace, start_o, down, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(&trace, down, start_o, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
// up = vec3(0, 0, 1) // up = vec3(0, 0, 1)
//VectorSet(up, 0, 0, 1); //VectorSet(up, 0, 0, 1);
@ -479,7 +479,7 @@ int PM_StepSlideMove( bool gravity )
// test the player position if they were a stepheight higher // test the player position if they were a stepheight higher
//pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); //pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask);
//tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&up, D3DXVECTOR3(0.0f, STEPSIZE, 0.0f), 0, pml.traceObj); //tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&up, D3DXVECTOR3(0.0f, STEPSIZE, 0.0f), 0, pml.traceObj);
newtrace(&trace, start_o, up, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(&trace, start_o, up, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
if ( trace.allsolid ) if ( trace.allsolid )
{ {
//if ( pm->debugLevel ) //if ( pm->debugLevel )
@ -510,7 +510,7 @@ int PM_StepSlideMove( bool gravity )
//pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj);
newtrace(&trace, pm->ps.origin, down, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(&trace, pm->ps.origin, down, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
if ( !trace.allsolid ) if ( !trace.allsolid )
//VectorCopy (trace.endpos, pm->ps->origin); //VectorCopy (trace.endpos, pm->ps->origin);
pm->ps.origin = trace.endpos; pm->ps.origin = trace.endpos;
@ -527,7 +527,7 @@ int PM_StepSlideMove( bool gravity )
delta = pm->ps.origin.z - start_o.z; delta = pm->ps.origin.z - start_o.z;
if ( delta > 2 ) if ( delta > 2 )
{ {
pm->ps.counter = 5; pm->ps.counter = 10;
/* /*
if (gravity) if (gravity)
@ -657,10 +657,11 @@ static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel
// int i; // int i;
float addspeed, accelspeed, currentspeed; float addspeed, accelspeed, currentspeed;
// currentspeed = pm->ps->velocity dot wishdir // currentspeed = pm->ps->velocity dot wishdir
//currentspeed = DotProduct (pm->ps->velocity, wishdir); //currentspeed = DotProduct (pm->ps->velocity, wishdir);
currentspeed = pm->ps.velocity.dotProduct(wishdir); currentspeed = pm->ps.velocity.dotProduct(wishdir);
addspeed = wishspeed - currentspeed; addspeed = wishspeed - currentspeed;
if (addspeed <= 0) if (addspeed <= 0)
return; return;
@ -675,6 +676,8 @@ static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel
//for (i=0 ; i<3 ; i++) //for (i=0 ; i<3 ; i++)
//pm->ps->velocity[i] += accelspeed * wishdir[i]; //pm->ps->velocity[i] += accelspeed * wishdir[i];
pm->ps.velocity += (wishdir * accelspeed); pm->ps.velocity += (wishdir * accelspeed);
//pm->ps.velocity = wishdir * wishspeed; //New, for instant acceleration
} }
static bool PM_CheckJump(void) static bool PM_CheckJump(void)
@ -701,7 +704,7 @@ static bool PM_CheckJump(void)
//pm->ps->pm_flags |= PMF_JUMP_HELD; //pm->ps->pm_flags |= PMF_JUMP_HELD;
pm->ps.groundEntityNum = ENTITYNUM_NONE; pm->ps.groundEntityNum = ENTITYNUM_NONE;
pm->ps.velocity.z = JUMP_VELOCITY; pm->ps.velocity.z = pm->ps.jump_velocity;
pm->ps.bSnap = false; pm->ps.bSnap = false;
//PM_AddEvent( EV_JUMP ); //PM_AddEvent( EV_JUMP );
@ -899,7 +902,7 @@ static void PM_WalkMove( playerMove* const pmove )
if (pmove->hasWater ) if (pmove->hasWater )
{ {
const float waterHeight = pmove->waterHeight; const float waterHeight = pmove->waterHeight;
const float waterSoundStepHeight = waterHeight + halfExtents.y; const float waterSoundStepHeight = waterHeight + pm->ps.halfExtents.y;
if (pmove->ps.origin.y < waterSoundStepHeight) if (pmove->ps.origin.y < waterSoundStepHeight)
step_underwater = true; step_underwater = true;
} }
@ -1179,7 +1182,7 @@ void PM_GroundTraceMissed()
//pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -64.0f, 0.0f), 0, pml.traceObj); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -64.0f, 0.0f), 0, pml.traceObj);
newtrace(&trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(&trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
//It hit the ground below //It hit the ground below
if ( trace.fraction < 1.0 && pm->ps.origin.z > trace.endpos.z) if ( trace.fraction < 1.0 && pm->ps.origin.z > trace.endpos.z)
{ {
@ -1225,7 +1228,7 @@ static bool PM_CorrectAllSolid(traceResults* const trace)
//pm->trace (trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //pm->trace (trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
//tracefunc(trace, *(const D3DXVECTOR3* const)&point, *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0, pml.traceObj); //tracefunc(trace, *(const D3DXVECTOR3* const)&point, *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0, pml.traceObj);
newtrace(trace, point, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(trace, point, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
if ( !trace->allsolid ) if ( !trace->allsolid )
{ {
@ -1237,7 +1240,7 @@ static bool PM_CorrectAllSolid(traceResults* const trace)
//pm->trace (trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //pm->trace (trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
//tracefunc(trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj); //tracefunc(trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj);
newtrace(trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
pml.groundTrace = *trace; pml.groundTrace = *trace;
return true; return true;
} }
@ -1338,7 +1341,7 @@ static void PM_CrashLand( void )
{ {
const float waterHeight = pm->waterHeight; const float waterHeight = pm->waterHeight;
const float waterHeightSplash = waterHeight + halfExtents.y; const float waterHeightSplash = waterHeight + pm->ps.halfExtents.y;
if (pm->ps.origin.z < waterHeightSplash) if (pm->ps.origin.z < waterHeightSplash)
{ {
splashSound = true; splashSound = true;
@ -1413,7 +1416,7 @@ static void PM_GroundTrace( void )
//pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj);
newtrace(&trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); newtrace(&trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
pml.groundTrace = trace; pml.groundTrace = trace;
// do something corrective if the trace starts in a solid... // do something corrective if the trace starts in a solid...

@ -23,7 +23,7 @@ Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc.
extern SceneInstance* global_lastscene; extern SceneInstance* global_lastscene;
#endif*/ #endif*/
static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2); static const Ogre::Vector3 halfExtentsDefault(14.64f * 2, 14.24f * 2, 33.25f * 2);
#define MAX_CLIP_PLANES 5 #define MAX_CLIP_PLANES 5
#define OVERCLIP 1.001f #define OVERCLIP 1.001f
@ -42,7 +42,6 @@ static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2);
#define ENTITYNUM_NONE (MAX_GENTITIES - 1) #define ENTITYNUM_NONE (MAX_GENTITIES - 1)
#define ENTITYNUM_WORLD (MAX_GENTITIES - 2) #define ENTITYNUM_WORLD (MAX_GENTITIES - 2)
#define MIN_WALK_NORMAL .7f // can't walk on very steep slopes #define MIN_WALK_NORMAL .7f // can't walk on very steep slopes
#define JUMP_VELOCITY (270)
#define PS_PMOVEFRAMECOUNTBITS 6 #define PS_PMOVEFRAMECOUNTBITS 6
#define MINS_Z -24 #define MINS_Z -24
#define DEFAULT_VIEWHEIGHT 26 #define DEFAULT_VIEWHEIGHT 26
@ -90,9 +89,9 @@ struct playerMove
{ {
struct playerStruct struct playerStruct
{ {
playerStruct() : gravity(800.0f), speed(480.0f), pmove_framecount(20), groundEntityNum(ENTITYNUM_NONE), commandTime(40), move_type(PM_NOCLIP), pm_time(0), snappingImplemented(true), bSnap(false), counter(-1) playerStruct() : gravity(800.0f), speed(480.0f), jump_velocity(270), pmove_framecount(20), groundEntityNum(ENTITYNUM_NONE), commandTime(40), move_type(PM_NOCLIP), pm_time(0), snappingImplemented(true), bSnap(false), counter(-1), halfExtents(halfExtentsDefault)
{ {
origin = Ogre::Vector3(733.164f,900.0f, 839.432f); origin = Ogre::Vector3(0.0f, 0.0f, 0.0f);
velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f); velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f);
viewangles = Ogre::Vector3(0.0f, 0.0f, 0.0f); viewangles = Ogre::Vector3(0.0f, 0.0f, 0.0f);
@ -117,11 +116,13 @@ struct playerMove
Ogre::Vector3 velocity; Ogre::Vector3 velocity;
Ogre::Vector3 origin; Ogre::Vector3 origin;
Ogre::Vector3 halfExtents;
bool bSnap; bool bSnap;
bool snappingImplemented; bool snappingImplemented;
int counter; int counter;
float gravity; // default = 800 float gravity; // default = 800
float speed; // default = 320 float speed; // default = 320
float jump_velocity; //default = 270
int commandTime; // the time at which this command was issued (in milliseconds) int commandTime; // the time at which this command was issued (in milliseconds)

@ -13,18 +13,22 @@
void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass) //Traceobj was a Aedra Object void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass) //Traceobj was a Aedra Object
{ {
static float lastyaw = 0.0f;
static float lastpitch = 0.0f;
//if (!traceobj) //if (!traceobj)
// return; // return;
//if (!traceobj->incellptr) //if (!traceobj->incellptr)
// return; // return;
const Ogre::Vector3 rayDir = end - start; const Ogre::Vector3 rayDir = end - start;
// Nudge starting point backwards
//const Position3D nudgestart = start + (rayDir * -0.1f); // by 10% (isn't that too much?)
//const Position3D nudgestart = start;
NewPhysTraceResults out; NewPhysTraceResults out;
//std::cout << "Starting trace\n"; //std::cout << "Starting trace\n";
@ -32,7 +36,7 @@ void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogr
//Ogre::Vector3 endReplace = startReplace; //Ogre::Vector3 endReplace = startReplace;
//endReplace.z -= .25; //endReplace.z -= .25;
const bool hasHit = NewPhysicsTrace<collisionWorldTrace>(&out, start, end, BBHalfExtents, Ogre::Vector3(0.0f, 0.0, rotation), isInterior, enginePass); const bool hasHit = NewPhysicsTrace<collisionWorldTrace>(&out, start, end, BBHalfExtents, Ogre::Vector3(0.0f, 0.0f, 0.0f), isInterior, enginePass);
if (out.fraction < 0.001f) if (out.fraction < 0.001f)
results->startsolid = true; results->startsolid = true;
@ -95,13 +99,14 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3&
//if(enginePass->dynamicsWorld->getCollisionObjectArray().at(60)->getCollisionShape()->isConvex()) //if(enginePass->dynamicsWorld->getCollisionObjectArray().at(60)->getCollisionShape()->isConvex())
// std::cout << "It's convex\n"; // std::cout << "It's convex\n";
const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z); const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z);
const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z); const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z);
const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z
const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z));
//const btCapsuleShapeZ newshape(BBHalfExtents.x, BBHalfExtents.z * 2 - BBHalfExtents.x * 2);
const btTransform from(btrot, btstart); const btTransform from(btrot, btstart);
const btTransform to(btrot, btend); const btTransform to(btrot, btend);
@ -176,7 +181,8 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3&
if (!TestPointAgainstAabb2(aabbMin, aabbMax, *(const btVector3* const)&(start) ) ) if (!TestPointAgainstAabb2(aabbMin, aabbMax, *(const btVector3* const)&(start) ) )
{ {
//We're solid //We're solid
out->startSolid = true; //THIS NEEDS TO BE TURNED OFF IF WE WANT FALLING IN EXTERIORS TO WORK CORRECTLY!!!!!!!
//out->startSolid = true;
} }
} }
} }

@ -5,9 +5,8 @@
#include <btBulletDynamicsCommon.h> #include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h> #include <btBulletCollisionCommon.h>
#include <components/nifbullet/bullet_nif_loader.hpp> #include <components/nifbullet/bullet_nif_loader.hpp>
#include <openengine/bullet/pmove.h>
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include "pmove.h"
enum traceWorldType enum traceWorldType

@ -1,52 +1,50 @@
#include "fader.hpp" #include "fader.hpp"
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include <OgreOverlay.h>
#include <OgreMaterial.h> #include <OgreMaterial.h>
#include <OgreTechnique.h> #include <OgreTechnique.h>
#include <OgreMaterialManager.h> #include <OgreMaterialManager.h>
#include <OgreResourceGroupManager.h> #include <OgreResourceGroupManager.h>
#include <OgreRectangle2D.h>
#include <OgreSceneManager.h>
#define FADE_OVERLAY_NAME "FadeInOutOverlay"
#define FADE_OVERLAY_PANEL_NAME "FadeInOutOverlayPanel"
#define FADE_MATERIAL_NAME "FadeInOutMaterial"
using namespace Ogre; using namespace Ogre;
using namespace OEngine::Render; using namespace OEngine::Render;
Fader::Fader() : Fader::Fader(Ogre::SceneManager* sceneMgr)
mMode(FadingMode_In), : mSceneMgr(sceneMgr)
mRemainingTime(0.f), , mMode(FadingMode_In)
mTargetTime(0.f), , mRemainingTime(0.f)
mTargetAlpha(0.f), , mTargetTime(0.f)
mCurrentAlpha(0.f), , mTargetAlpha(0.f)
mStartAlpha(0.f) , mCurrentAlpha(0.f)
, mStartAlpha(0.f)
{ {
// Create the fading material // Create the fading material
MaterialPtr material = MaterialManager::getSingleton().create( FADE_MATERIAL_NAME, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); MaterialPtr material = MaterialManager::getSingleton().create("FadeInOutMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
Pass* pass = material->getTechnique(0)->getPass(0); Pass* pass = material->getTechnique(0)->getPass(0);
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mFadeTextureUnit = pass->createTextureUnitState(); mFadeTextureUnit = pass->createTextureUnitState();
mFadeTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(0.f, 0.f, 0.f)); // always black colour mFadeTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(0.f, 0.f, 0.f)); // always black colour
// Create the overlay mRectangle = new Ogre::Rectangle2D(true);
OverlayManager& ovm = OverlayManager::getSingleton(); mRectangle->setCorners(-1.0, 1.0, 1.0, -1.0);
mRectangle->setMaterial("FadeInOutMaterial");
mRectangle->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY-1);
// Use infinite AAB to always stay visible
Ogre::AxisAlignedBox aabInf;
aabInf.setInfinite();
mRectangle->setBoundingBox(aabInf);
// Attach background to the scene
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
node->attachObject(mRectangle);
mRectangle->setVisible(false);
mRectangle->setVisibilityFlags (0x01);
}
mOverlay = ovm.create( FADE_OVERLAY_NAME ); Fader::~Fader()
{
OverlayContainer* overlay_panel; delete mRectangle;
overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", FADE_OVERLAY_PANEL_NAME);
// position it over the whole screen
overlay_panel->_setPosition(0, 0);
overlay_panel->_setDimensions(1, 1);
overlay_panel->setMaterialName( FADE_MATERIAL_NAME );
overlay_panel->show();
mOverlay->add2D(overlay_panel);
mOverlay->hide();
} }
void Fader::update(float dt) void Fader::update(float dt)
@ -69,12 +67,12 @@ void Fader::update(float dt)
mRemainingTime -= dt; mRemainingTime -= dt;
} }
if (mCurrentAlpha == 0.f) mOverlay->hide(); if (mCurrentAlpha == 0.f) mRectangle->setVisible(false);
} }
void Fader::applyAlpha() void Fader::applyAlpha()
{ {
mOverlay->show(); mRectangle->setVisible(true);
mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, mCurrentAlpha); mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, mCurrentAlpha);
} }

@ -4,52 +4,52 @@
/* /*
A class that handles fading in the screen from black or fading it out to black. A class that handles fading in the screen from black or fading it out to black.
To achieve this, it uses a full-screen Ogre::Overlay To achieve this, it uses a full-screen Rectangle2d
inspired by http://www.ogre3d.org/tikiwiki/FadeEffectOverlay (heavily adjusted)
*/ */
namespace Ogre namespace Ogre
{ {
class TextureUnitState; class TextureUnitState;
class Overlay; class Rectangle2D;
class SceneManager;
} }
namespace OEngine { namespace OEngine {
namespace Render namespace Render
{ {
class Fader class Fader
{
public:
Fader();
void update(float dt);
void fadeIn(const float time);
void fadeOut(const float time);
void fadeTo(const int percent, const float time);
private:
enum FadingMode
{ {
FadingMode_In, public:
FadingMode_Out Fader(Ogre::SceneManager* sceneMgr);
~Fader();
void update(float dt);
void fadeIn(const float time);
void fadeOut(const float time);
void fadeTo(const int percent, const float time);
private:
enum FadingMode
{
FadingMode_In,
FadingMode_Out
};
void applyAlpha();
Ogre::TextureUnitState* mFadeTextureUnit;
Ogre::Rectangle2D* mRectangle;
FadingMode mMode;
float mRemainingTime;
float mTargetTime;
float mTargetAlpha;
float mCurrentAlpha;
float mStartAlpha;
Ogre::SceneManager* mSceneMgr;
}; };
}}
void applyAlpha();
Ogre::TextureUnitState* mFadeTextureUnit;
Ogre::Overlay* mOverlay;
FadingMode mMode;
float mRemainingTime;
float mTargetTime;
float mTargetAlpha;
float mCurrentAlpha;
float mStartAlpha;
protected:
};
}}
#endif #endif

@ -44,8 +44,10 @@ void OgreRenderer::cleanup()
delete mFader; delete mFader;
mFader = NULL; mFader = NULL;
OGRE_DELETE mRoot; delete mRoot;
mRoot = NULL; mRoot = NULL;
unloadPlugins();
} }
void OgreRenderer::start() void OgreRenderer::start()
@ -78,7 +80,7 @@ void OgreRenderer::start()
#endif #endif
} }
bool OgreRenderer::loadPlugins() void OgreRenderer::loadPlugins()
{ {
#ifdef ENABLE_PLUGIN_GL #ifdef ENABLE_PLUGIN_GL
mGLPlugin = new Ogre::GLPlugin(); mGLPlugin = new Ogre::GLPlugin();
@ -100,7 +102,30 @@ bool OgreRenderer::loadPlugins()
mParticleFXPlugin = new Ogre::ParticleFXPlugin(); mParticleFXPlugin = new Ogre::ParticleFXPlugin();
mRoot->installPlugin(mParticleFXPlugin); mRoot->installPlugin(mParticleFXPlugin);
#endif #endif
return true; }
void OgreRenderer::unloadPlugins()
{
#ifdef ENABLE_PLUGIN_GL
delete mGLPlugin;
mGLPlugin = NULL;
#endif
#ifdef ENABLE_PLUGIN_Direct3D9
delete mD3D9Plugin;
mD3D9Plugin = NULL;
#endif
#ifdef ENABLE_PLUGIN_CgProgramManager
delete mCgPlugin;
mCgPlugin = NULL;
#endif
#ifdef ENABLE_PLUGIN_OctreeSceneManager
delete mOctreePlugin;
mOctreePlugin = NULL;
#endif
#ifdef ENABLE_PLUGIN_ParticleFX
delete mParticleFXPlugin;
mParticleFXPlugin = NULL;
#endif
} }
void OgreRenderer::update(float dt) void OgreRenderer::update(float dt)
@ -120,6 +145,7 @@ float OgreRenderer::getFPS()
void OgreRenderer::configure(const std::string &logPath, void OgreRenderer::configure(const std::string &logPath,
const std::string& renderSystem, const std::string& renderSystem,
const std::string& rttMode,
bool _logging) bool _logging)
{ {
// Set up logging first // Set up logging first
@ -173,6 +199,9 @@ void OgreRenderer::configure(const std::string &logPath,
if (rs == 0) if (rs == 0)
throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded"); throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded");
mRoot->setRenderSystem(rs); mRoot->setRenderSystem(rs);
if (rs->getName().find("OpenGL") != std::string::npos)
rs->setConfigOption ("RTT Preferred Mode", rttMode);
} }
void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings) void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings)
@ -218,7 +247,7 @@ void OgreRenderer::createScene(const std::string& camName, float fov, float near
// Alter the camera aspect ratio to match the viewport // Alter the camera aspect ratio to match the viewport
mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight()));
mFader = new Fader(); mFader = new Fader(mScene);
} }
void OgreRenderer::adjustViewport() void OgreRenderer::adjustViewport()

@ -132,6 +132,7 @@ namespace OEngine
void configure( void configure(
const std::string &logPath, // Path to directory where to store log files const std::string &logPath, // Path to directory where to store log files
const std::string &renderSystem, const std::string &renderSystem,
const std::string &rttMode,
bool _logging); // Enable or disable logging bool _logging); // Enable or disable logging
/// Create a window with the given title /// Create a window with the given title
@ -151,7 +152,9 @@ namespace OEngine
/// Start the main rendering loop /// Start the main rendering loop
void start(); void start();
bool loadPlugins() ; void loadPlugins();
void unloadPlugins();
void update(float dt); void update(float dt);

@ -4,6 +4,7 @@
#include <OgreRenderTexture.h> #include <OgreRenderTexture.h>
#include <OgreSubEntity.h> #include <OgreSubEntity.h>
#include <OgreEntity.h> #include <OgreEntity.h>
#include <stdexcept>
#include <extern/shiny/Main/Factory.hpp> #include <extern/shiny/Main/Factory.hpp>
@ -73,7 +74,7 @@ namespace Render
int id = Ogre::any_cast<int>(subEntity->getParent ()->getUserObjectBindings().getUserAny()); int id = Ogre::any_cast<int>(subEntity->getParent ()->getUserObjectBindings().getUserAny());
bool found = false; bool found = false;
Ogre::ColourValue colour; Ogre::ColourValue colour;
for (std::map<Ogre::ColourValue, int>::iterator it = mColourMap.begin(); it != mColourMap.end(); ++it) for (std::map<Ogre::ColourValue, int, cmp_ColourValue>::iterator it = mColourMap.begin(); it != mColourMap.end(); ++it)
{ {
if (it->second == id) if (it->second == id)
{ {

@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind
OpenMW is an attempt at recreating the engine for the popular role-playing game OpenMW is an attempt at recreating the engine for the popular role-playing game
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
Version: 0.17.0 Version: 0.18.0
License: GPL (see GPL3.txt for more information) License: GPL (see GPL3.txt for more information)
Website: http://www.openmw.org Website: http://www.openmw.org
@ -97,6 +97,39 @@ Allowed options:
CHANGELOG CHANGELOG
0.18.0
Bug #310: Button of the "preferences menu" are too small
Bug #361: Hand-to-hand skill is always 100
Bug #365: NPC and creature animation is jerky; Characters float around when they are not supposed to
Bug #372: playSound3D uses original coordinates instead of current coordinates.
Bug #373: Static OGRE build faulty
Bug #375: Alt-tab toggle view
Bug #376: Screenshots are disable
Bug #378: Exception when drinking self-made potions
Bug #380: Cloth visibility problem
Bug #384: Weird character on doors tooltip.
Bug #398: Some objects do not collide in MW, but do so in OpenMW
Feature #22: Implement level-up
Feature #36: Hide Marker
Feature #88: Hotkey Window
Feature #91: Level-Up Dialogue
Feature #118: Keyboard and Mouse-Button bindings
Feature #119: Spell Buying Window
Feature #133: Handle resources across multiple data directories
Feature #134: Generate a suitable default-value for --data-local
Feature #292: Object Movement/Creation Script Instructions
Feature #340: AIPackage data structures
Feature #356: Ingredients use
Feature #358: Input system rewrite
Feature #370: Target handling in actions
Feature #379: Door markers on the local map
Feature #389: AI framework
Feature #395: Using keys to open doors / containers
Feature #396: Loading screens
Feature #397: Inventory avatar image and race selection head preview
Task #339: Move sounds into Action
0.17.0 0.17.0
Bug #225: Valgrind reports about 40MB of leaked memory Bug #225: Valgrind reports about 40MB of leaked memory

Loading…
Cancel
Save