resolving conflicts

pull/37/head
greye 12 years ago
commit 18cc435aa1

@ -15,7 +15,7 @@ include (OpenMWMacros)
# Version
set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 17)
set (OPENMW_VERSION_MINOR 18)
set (OPENMW_VERSION_RELEASE 0)
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
4355 # Using 'this' in member initialization list
4701 # Potentially uninitialized local variable used
4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt
)
foreach(d ${WARNINGS_DISABLE})
@ -524,6 +525,7 @@ if (WIN32)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif(MSVC)
# Same for MinGW
@ -631,7 +633,7 @@ if (APPLE)
include(CPack)
endif (APPLE)
if (NOT WIN32 AND NOT DPKG_PROGRAM)
if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
## Non Debian based Linux building
# paths
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(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" )
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
const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm");
unsigned int i = 0; // Row number
@ -283,7 +218,7 @@ bool DataFilesPage::setupDataFiles()
ESMReader fileReader;
QStringList availableMasters; // Will contain all found masters
fileReader.setEncoding(variables["encoding"].as<std::string>());
fileReader.setEncoding(encoding.toStdString());
fileReader.open(iter->second.string());
// First we fill the availableMasters and the mMastersWidget
@ -350,10 +285,86 @@ bool DataFilesPage::setupDataFiles()
} catch(std::runtime_error &e) {
// An error occurred while reading the .esp
std::cerr << "Error reading .esp: " << e.what() << std::endl;
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();
return true;
}
@ -1139,11 +1150,13 @@ void DataFilesPage::writeConfig(QString profile)
path = QString::fromStdString(it->string());
path.remove(QChar('\"'));
QDir dir(path);
// Make sure the string is quoted when it contains spaces
if (path.contains(" ")) {
gameConfig << "data=\"" << path << "\"" << endl;
gameConfig << "data=\"" << dir.absolutePath() << "\"" << endl;
} 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.remove(QChar('\"'));
QDir dir(path);
if (path.contains(" ")) {
gameConfig << "data-local=\"" << path << "\"" << endl;
gameConfig << "data-local=\"" << dir.absolutePath() << "\"" << endl;
} else {
gameConfig << "data-local=" << path << endl;
gameConfig << "data-local=" << dir.absolutePath() << endl;
}
}

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

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

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

@ -118,7 +118,7 @@ namespace MWBase
/// Set value for the given ID.
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 (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, int value) = 0;
@ -189,6 +189,8 @@ namespace MWBase
virtual void allowMouse() = 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;
///< 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 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;
///< Set in-game time day.
virtual int getDay() = 0;
virtual int getMonth() = 0;
virtual MWWorld::TimeStamp getTimeStamp() const = 0;
///< 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 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)
const = 0;
///< Convert cell numbers to position.
@ -218,7 +224,7 @@ namespace MWBase
virtual bool toggleCollisionMode() = 0;
///< Toggle collision mode for player. If disabled player object should ignore
/// collisions and gravity.
///< \return Resulting mode
/// \return Resulting mode
virtual bool toggleRenderMode (RenderMode mode) = 0;
///< Toggle a render mode.
@ -276,8 +282,16 @@ namespace MWBase
virtual void togglePlayerLooking(bool enable) = 0;
virtual void renderPlayer() = 0;
virtual void renderGlobalMap() = 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);
std::string headID = ref->base->mHead;
int end = headID.find_last_of("head_") - 4;
std::string bodyRaceID = headID.substr(0, end);
@ -153,6 +154,7 @@ namespace MWClass
model = "meshes\\base_animkna.nif";
}
return model;
}
std::string Npc::getName (const MWWorld::Ptr& ptr) const
@ -297,7 +299,7 @@ namespace MWClass
{
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.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)
{
@ -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;
}
void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<int>& value)
void CharacterCreation::setPlayerMagicka (const MWMechanics::DynamicStat<float>& value)
{
mPlayerMagicka = value;
}
void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<int>& value)
void CharacterCreation::setPlayerFatigue (const MWMechanics::DynamicStat<float>& value)
{
mPlayerFatigue = value;
}

@ -35,14 +35,14 @@ namespace MWGui
//Show a dialog
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::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 configureSkills (const SkillList& major, const SkillList& minor);
@ -65,9 +65,9 @@ namespace MWGui
std::string mPlayerRaceId;
std::string mPlayerBirthSignId;
ESM::Class mPlayerClass;
MWMechanics::DynamicStat<int> mPlayerHealth;
MWMechanics::DynamicStat<int> mPlayerMagicka;
MWMechanics::DynamicStat<int> mPlayerFatigue;
MWMechanics::DynamicStat<float> mPlayerHealth;
MWMechanics::DynamicStat<float> mPlayerMagicka;
MWMechanics::DynamicStat<float> mPlayerFatigue;
//Class generation vars
unsigned mGenerateClassStep; // Keeps track of current step in Generate Class dialog

@ -161,7 +161,7 @@ void HUD::setEffect(const char *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[] =
{

@ -14,7 +14,7 @@ namespace MWGui
public:
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
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 setTriangleCount(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 <OgreVector2.h>
#include <OgreTextureManager.h>
#include <OgreSceneNode.h>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwworld/player.hpp"
using namespace MWGui;
@ -254,18 +257,24 @@ MapWindow::MapWindow(MWBase::WindowManager& parWindowManager) :
getWidget(mLocalMap, "LocalMap");
getWidget(mGlobalMap, "GlobalMap");
getWidget(mPlayerArrow, "Compass");
getWidget(mGlobalMapImage, "GlobalMapImage");
getWidget(mPlayerArrowLocal, "CompassLocal");
getWidget(mPlayerArrowGlobal, "CompassGlobal");
mGlobalMap->setVisible (false);
getWidget(mButton, "WorldButton");
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
mButton->setCaptionWithReplacing("#{sWorld}");
MyGUI::Button* eventbox;
getWidget(eventbox, "EventBox");
eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
getWidget(mEventBoxGlobal, "EventBoxGlobal");
mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
mEventBoxGlobal->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)
@ -273,24 +282,54 @@ void MapWindow::setCellName(const std::string& 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)
{
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)
{
if (_id!=MyGUI::MouseButton::Left) return;
MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
if (!mGlobal)
{
MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
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)
@ -307,3 +346,41 @@ void MapWindow::onPinToggled()
{
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 addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
virtual void open();
private:
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 onWorldButtonClicked(MyGUI::Widget* _sender);
MyGUI::ScrollView* mGlobalMap;
MyGUI::ImageBox* mPlayerArrow;
MyGUI::ImageBox* mGlobalMapImage;
MyGUI::ImageBox* mPlayerArrowLocal;
MyGUI::ImageBox* mPlayerArrowGlobal;
MyGUI::Button* mButton;
MyGUI::IntPoint mLastDragPos;
bool mGlobal;
MyGUI::Button* mEventBoxGlobal;
MyGUI::Button* mEventBoxLocal;
protected:
virtual void onPinToggled();
};

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

@ -40,7 +40,7 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager)
getWidget(mHeadRotate, "HeadRotate");
mHeadRotate->setScrollRange(50);
mHeadRotate->setScrollPosition(20);
mHeadRotate->setScrollPosition(25);
mHeadRotate->setScrollViewPage(10);
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());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
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());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
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());
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 setBirthSign (const std::string &signId);
void setHealth(const MWMechanics::DynamicStat<int>& value);
void setMagicka(const MWMechanics::DynamicStat<int>& value);
void setFatigue(const MWMechanics::DynamicStat<int>& value);
void setHealth(const MWMechanics::DynamicStat<float>& value);
void setMagicka(const MWMechanics::DynamicStat<float>& value);
void setFatigue(const MWMechanics::DynamicStat<float>& value);
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value);

@ -122,6 +122,7 @@ namespace MWGui
getWidget(mInvertYButton, "InvertYButton");
getWidget(mUISensitivitySlider, "UISensitivitySlider");
getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider");
getWidget(mGammaSlider, "GammaSlider");
mSubtitlesButton->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);
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mGammaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
@ -200,6 +202,14 @@ namespace MWGui
getWidget(fovText, "FovText");
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;
mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1));
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)) + ")");
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)
{
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(int(val*16)) + ")");

@ -40,6 +40,7 @@ namespace MWGui
MyGUI::Button* mFPSButton;
MyGUI::ScrollBar* mViewDistanceSlider;
MyGUI::ScrollBar* mFOVSlider;
MyGUI::ScrollBar* mGammaSlider;
MyGUI::ScrollBar* mAnisotropySlider;
MyGUI::Button* mTextureFilteringButton;
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[] =
{
@ -150,7 +150,7 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicSta
if (ids[i]==id)
{
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
MyGUI::Widget* w;
@ -236,12 +236,21 @@ void StatsWindow::configureSkills (const std::vector<int>& major, const std::vec
void StatsWindow::onFrame ()
{
if (mMainWidget->getVisible())
if (!mMainWidget->getVisible())
return;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
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());
setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign());

@ -32,7 +32,7 @@ namespace MWGui
/// 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::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, int 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)
{
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)
{
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)
{
if (w->getParent () != 0)
@ -869,29 +868,33 @@ void AutoSizedButton::setPropertyOverride(const std::string& _key, const std::st
Box::Box()
: 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 ()
{
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 ()
{
unsigned int count = getChildCount ();
size_t h_stretched_count = 0;
int total_width = 0;
int total_height = 0;
std::vector< std::pair<MyGUI::IntSize, bool> > sizes;
for (unsigned int i = 0; i < count; ++i)
@ -904,28 +907,43 @@ void HBox::align ()
{
sizes.push_back(std::make_pair(aw->getRequestedSize (), hstretch));
total_width += aw->getRequestedSize ().width;
total_height = std::max(total_height, aw->getRequestedSize ().height);
}
else
{
if (!hstretch) h_stretched_count ++;
sizes.push_back (std::make_pair(MyGUI::IntSize(0,0), true));
sizes.push_back (std::make_pair(w->getSize(), hstretch));
total_width += w->getSize().width;
}
if (i != count-1)
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;
for (unsigned int i = 0; i < count; ++i)
{
if (i == 0)
curX += mPadding;
MyGUI::Widget* w = getChildAt(i);
bool vstretch = w->getUserString ("VStretch") == "true";
int height = vstretch ? total_height : sizes[i].first.height;
MyGUI::IntCoord widgetCoord;
widgetCoord.left = curX;
widgetCoord.top = (getSize().height - sizes[i].first.height) / 2;
int width = sizes[i].second ? sizes[i].first.width + (getSize().width - total_width)/h_stretched_count
widgetCoord.top = mPadding + (getSize().height-mPadding*2 - height) / 2;
int width = sizes[i].second ? sizes[i].first.width + (getSize().width-mPadding*2 - total_width)/h_stretched_count
: sizes[i].first.width;
widgetCoord.width = width;
widgetCoord.height = sizes[i].first.height;
widgetCoord.height = height;
w->setCoord(widgetCoord);
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)
{
MyGUI::Widget::setSize (_value);
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 size(0,0);
@ -954,6 +993,19 @@ MyGUI::IntSize HBox::getRequestedSize ()
if (i != getChildCount()-1)
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;
}
@ -963,7 +1015,69 @@ MyGUI::IntSize HBox::getRequestedSize ()
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)
@ -972,6 +1086,12 @@ void VBox::setSize (const MyGUI::IntSize& _value)
align();
}
void VBox::setCoord (const MyGUI::IntCoord& _value)
{
MyGUI::Widget::setCoord (_value);
align();
}
MyGUI::IntSize VBox::getRequestedSize ()
{
MyGUI::IntSize size(0,0);
@ -986,6 +1106,29 @@ MyGUI::IntSize VBox::getRequestedSize ()
if (i != getChildCount()-1)
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;
}
void VBox::onWidgetCreated(MyGUI::Widget* _widget)
{
align();
}
void VBox::onWidgetDestroy(MyGUI::Widget* _widget)
{
align();
}

@ -357,10 +357,13 @@ namespace MWGui
protected:
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 mPadding; // outer padding
bool mAutoResize; // auto resize the box so that it exactly fits all elements
};
class HBox : public Box, public MyGUI::Widget
@ -369,10 +372,16 @@ namespace MWGui
public:
virtual void setSize (const MyGUI::IntSize &_value);
virtual void setCoord (const MyGUI::IntCoord &_value);
protected:
virtual void align();
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
@ -381,10 +390,16 @@ namespace MWGui
public:
virtual void setSize (const MyGUI::IntSize &_value);
virtual void setCoord (const MyGUI::IntCoord &_value);
protected:
virtual void align();
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 "quickkeysmenu.hpp"
#include "loadingscreen.hpp"
#include "levelupdialog.hpp"
#include "waitdialog.hpp"
using namespace MWGui;
@ -70,6 +72,8 @@ WindowManager::WindowManager(
, mSpellWindow(NULL)
, mLoadingScreen(NULL)
, mCharGen(NULL)
, mLevelupDialog(NULL)
, mWaitDialog(NULL)
, mPlayerClass()
, mPlayerName()
, mPlayerRaceId()
@ -84,6 +88,7 @@ WindowManager::WindowManager(
, mGarbageDialogs()
, mShown(GW_ALL)
, mAllowed(newGame ? GW_None : GW_ALL)
, mRestAllowed(newGame ? false : true)
, mShowFPSLevel(fpsLevel)
, mFPS(0.0f)
, mTriangleCount(0)
@ -147,6 +152,8 @@ WindowManager::WindowManager(
mAlchemyWindow = new AlchemyWindow(*this);
mSpellWindow = new SpellWindow(*this);
mQuickKeysMenu = new QuickKeysMenu(*this);
mLevelupDialog = new LevelupDialog(*this);
mWaitDialog = new WaitDialog(*this);
mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this);
mLoadingScreen->onResChange (w,h);
@ -200,6 +207,8 @@ WindowManager::~WindowManager()
delete mAlchemyWindow;
delete mSpellWindow;
delete mLoadingScreen;
delete mLevelupDialog;
delete mWaitDialog;
cleanupGarbage();
@ -247,6 +256,8 @@ void WindowManager::updateVisible()
mAlchemyWindow->setVisible(false);
mSpellWindow->setVisible(false);
mQuickKeysMenu->setVisible(false);
mLevelupDialog->setVisible(false);
mWaitDialog->setVisible(false);
mHud->setVisible(true);
@ -298,6 +309,16 @@ void WindowManager::updateVisible()
case GM_Alchemy:
mAlchemyWindow->setVisible(true);
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_Race:
case GM_Class:
@ -395,7 +416,7 @@ void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& valu
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);
mHud->setValue (id, value);
@ -532,6 +553,8 @@ void WindowManager::onFrame (float frameDuration)
mStatsWindow->onFrame();
mWaitDialog->onFrame(frameDuration);
mHud->onFrame(frameDuration);
mDialogueWindow->checkReferenceAvailable();
@ -547,7 +570,10 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
{
std::string name;
if (cell->cell->mName != "")
{
name = cell->cell->mName;
mMap->addVisitedLocation (name, cell->cell->getGridX (), cell->cell->getGridY ());
}
else
{
const ESM::Region* region = MWBase::Environment::get().getWorld()->getStore().regions.search(cell->cell->mRegion);
@ -923,3 +949,13 @@ void WindowManager::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 QuickKeysMenu;
class LoadingScreen;
class LevelupDialog;
class WaitDialog;
class WindowManager : public MWBase::WindowManager
{
@ -117,7 +119,7 @@ namespace MWGui
///< Set value for the given ID.
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 (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, int value);
@ -170,6 +172,8 @@ namespace MWGui
virtual void allowMouse();
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 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 loadingDone();
virtual void enableRest() { mRestAllowed = true; }
virtual bool getRestEnabled() { return mRestAllowed; }
virtual bool getPlayerSleeping();
private:
OEngine::GUI::MyGUIManager *mGuiManager;
HUD *mHud;
@ -224,6 +233,8 @@ namespace MWGui
SpellWindow* mSpellWindow;
QuickKeysMenu* mQuickKeysMenu;
LoadingScreen* mLoadingScreen;
LevelupDialog* mLevelupDialog;
WaitDialog* mWaitDialog;
CharacterCreation* mCharGen;
@ -241,7 +252,7 @@ namespace MWGui
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
MWMechanics::DynamicStat<int> mPlayerHealth, mPlayerMagicka, mPlayerFatigue;
MWMechanics::DynamicStat<float> mPlayerHealth, mPlayerMagicka, mPlayerFatigue;
MyGUI::Gui *mGui; // Gui
@ -258,6 +269,8 @@ namespace MWGui
allow() and disableAll().
*/
GuiWindow mAllowed;
// is the rest window allowed?
bool mRestAllowed;
void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings

@ -190,6 +190,9 @@ namespace MWInput
case A_ToggleWeapon:
toggleWeapon ();
break;
case A_Rest:
rest();
break;
case A_ToggleSpell:
toggleSpell ();
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()
{
mEngine.screenshot();

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

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

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

@ -19,7 +19,7 @@ namespace MWMechanics
class CreatureStats
{
Stat<int> mAttributes[8];
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
int mLevel;
Spells mSpells;
ActiveSpells mActiveSpells;
@ -30,15 +30,18 @@ namespace MWMechanics
int mAlarm;
AiSequence mAiSequence;
float mLevelHealthBonus;
public:
CreatureStats();
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;
@ -59,13 +62,13 @@ namespace MWMechanics
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();
@ -76,11 +79,11 @@ namespace MWMechanics
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);
@ -104,6 +107,10 @@ namespace MWMechanics
float getFatigueTerm() const;
///< 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 <stdexcept>
#include <boost/format.hpp>
#include <components/esm/loadskil.hpp>
#include <components/esm/loadclas.hpp>
#include <components/esm/loadgmst.hpp>
@ -12,10 +14,17 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
MWMechanics::NpcStats::NpcStats()
: 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
{
@ -122,7 +131,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
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)
@ -134,7 +143,87 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
base += getSkillGain (skillIndex, class_, usageType);
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;
// 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);
}
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 <set>
#include <string>
#include <vector>
#include "stat.hpp"
#include "drawstate.hpp"
@ -45,6 +46,10 @@ namespace MWMechanics
unsigned int mMovementFlags;
Stat<float> mSkill[27];
int mLevelProgress; // 0-10
std::vector<int> mSkillIncreases; // number of skill increases for each attribute
public:
NpcStats();
@ -73,6 +78,14 @@ namespace MWMechanics
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1);
///< 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 ()
{
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;
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;
assert(mInsert);

@ -35,6 +35,7 @@
#include "compositors.hpp"
#include "npcanimation.hpp"
#include "externalrendering.hpp"
#include "globalmap.hpp"
using namespace MWRender;
using namespace Ogre;
@ -43,7 +44,7 @@ namespace MWRender {
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir,
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
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().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();
// 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 ("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 ("gammaCorrection", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(
Settings::Manager::getFloat ("gamma", "Video"))));
applyCompositors();
@ -160,6 +164,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mDebugging = new Debugging(mMwRoot, engine);
mLocalMap = new MWRender::LocalMap(&mRendering, this);
mGlobalMap = new GlobalMap(cacheDir.string());
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
}
@ -176,6 +182,7 @@ RenderingManager::~RenderingManager ()
delete mOcclusionQuery;
delete mCompositors;
delete mWater;
delete mGlobalMap;
}
MWRender::SkyManager* RenderingManager::getSkyManager()
@ -275,13 +282,15 @@ RenderingManager::rotateObject(
float *f = ptr.getRefData().getPosition().rot;
rot.x += f[0], rot.y += f[1], rot.z += f[2];
}
if (!isPlayer && isActive) {
Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z);
ptr.getRefData().getBaseNode()->setOrientation(xr * yr * zr);
}
return force;
}
@ -747,6 +756,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects"));
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")
{
sh::Language lang;
@ -887,4 +901,9 @@ void RenderingManager::setupExternalRendering (MWRender::ExternalRendering& rend
rendering.setup (mRendering.getScene());
}
void RenderingManager::renderGlobalMap ()
{
mGlobalMap->render ();
}
} // namespace

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

@ -31,7 +31,7 @@ op 0x2000e: PCGetRank implicit
op 0x2000f: PCGetRank explicit
op 0x20010: AiWander
op 0x20011: AiWander, explicit reference
opcodes 0x20012-0x3ffff unused
op s 0x20012-0x3ffff unused
Segment 4:
(not implemented yet)
@ -183,4 +183,27 @@ op 0x2000172: GetStartingAngle
op 0x2000173: GetStartingAngle, explicit reference
op 0x2000174: ToggleVanityMode
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 <boost/algorithm/string.hpp>
#include <components/compiler/extensions.hpp>
#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>
#include <components/esm_store/store.hpp>
#include <components/esm_store/reclists.hpp>
#include "../mwbase/environment.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
{
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 opcodeEnableClassMenu = 0x200000f;
const int opcodeEnableNameMenu = 0x2000010;
@ -95,6 +151,8 @@ namespace MWScript
const int opcodeGetButtonPressed = 0x2000137;
const int opcodeToggleFogOfWar = 0x2000145;
const int opcodeToggleFullHelp = 0x2000151;
const int opcodeShowMap = 0x20001a0;
const int opcodeFillMap = 0x20001a1;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -122,6 +180,9 @@ opcodeEnableStatsReviewMenu);
extensions.registerInstruction ("togglefullhelp", "", opcodeToggleFullHelp);
extensions.registerInstruction ("tfh", "", opcodeToggleFullHelp);
extensions.registerInstruction ("showmap", "S", opcodeShowMap);
extensions.registerInstruction ("fillmap", "", opcodeFillMap);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -146,21 +207,20 @@ opcodeEnableStatsReviewMenu);
interpreter.installSegment5 (opcodeEnableStatsMenu,
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,
new OpEnableDialogue (MWGui::GM_Rest));
*/
new OpEnableRest ());
interpreter.installSegment5 (opcodeShowRestMenu,
new OpShowDialogue (MWGui::GM_Rest));
new OpShowDialogue (MWGui::GM_RestBed));
interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed);
interpreter.installSegment5 (opcodeToggleFogOfWar, new OpToggleFogOfWar);
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 "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwworld/class.hpp"
@ -20,6 +21,16 @@ namespace MWScript
{
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
{
public:
@ -249,6 +260,7 @@ namespace MWScript
const int opcodeTogglePathgrid = 0x2000146;
const int opcodeDontSaveObject = 0x2000153;
const int opcodeToggleVanityMode = 0x2000174;
const int opcodeGetPcSleep = 0x200019f;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -273,6 +285,7 @@ namespace MWScript
extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject);
extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode);
extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode);
extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -293,6 +306,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater);
interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject);
interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode);
interpreter.installSegment5 (opcodeGetPcSleep, new OpGetPcSleep);
}
}
}

@ -32,6 +32,42 @@ namespace MWScript
{
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>
class OpGetAttribute : public Interpreter::Opcode0
{
@ -592,6 +628,11 @@ namespace MWScript
const int opcodeModDisposition = 0x200014d;
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)
{
static const char *attributes[numberOfAttributes] =
@ -674,6 +715,9 @@ namespace MWScript
extensions.registerInstruction("moddisposition","l",opcodeModDisposition,
opcodeModDispositionExplicit);
extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit);
extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit);
extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -745,6 +789,12 @@ namespace MWScript
interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>);
interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>);
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 <OgreMath.h>
#include <OgreSceneNode.h>
#include <components/esm_store/store.hpp>
#include <components/esm/loadcell.hpp>
#include <components/compiler/extensions.hpp>
@ -11,10 +15,11 @@
#include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
#include "OgreSceneNode.h"
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 opcodeSetScaleExplicit = 0x2000165;
const int opcodeSetAngle = 0x2000166;
@ -149,8 +516,22 @@ namespace MWScript
const int opcodeGetScaleExplicit = 0x2000169;
const int opcodeGetAngle = 0x200016a;
const int opcodeGetAngleExplicit = 0x200016b;
const int opcodeGetStartingAngle = 0x2000172;
const int opcodeGetStartingAngleExplicit = 0x2000173;
const int opcodeGetPos = 0x2000190;
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)
{
@ -158,7 +539,15 @@ namespace MWScript
extensions.registerFunction("getscale",'f',"",opcodeGetScale,opcodeGetScaleExplicit);
extensions.registerInstruction("setangle","cf",opcodeSetAngle,opcodeSetAngleExplicit);
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)
@ -171,8 +560,21 @@ namespace MWScript
interpreter.installSegment5(opcodeGetScaleExplicit,new OpGetScale<ExplicitRef>);
interpreter.installSegment5(opcodeGetAngle,new OpGetAngle<ImplicitRef>);
interpreter.installSegment5(opcodeGetAngleExplicit,new OpGetAngle<ExplicitRef>);
interpreter.installSegment5(opcodeGetStartingAngle,new OpGetStartingAngle<ImplicitRef>);
interpreter.installSegment5(opcodeGetStartingAngleExplicit,new OpGetStartingAngle<ExplicitRef>);
interpreter.installSegment5(opcodeGetPos,new OpGetPos<ImplicitRef>);
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/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwgui/bookwindow.hpp"
#include "../mwgui/scrollwindow.hpp"
#include <components/esm_store/store.hpp>
namespace MWWorld
{
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()->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){
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
//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++)
{
OEngine::Physic::PhysicActor* act = it->second;
act->setWalkDirection(btVector3(0,0,0));
act->setMovement(0,0,0);
}
playerMove::playercmd& pm_ref = playerphysics->cmd;
pm_ref.rightmove = 0;
pm_ref.forwardmove = 0;
pm_ref.upmove = 0;
//playerphysics->ps.move_type = PM_NOCLIP;
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
@ -193,10 +200,12 @@ namespace MWWorld
playerphysics->ps.viewangles.x =
Ogre::Radian(mPlayerData.pitch).valueDegrees();
playerphysics->ps.viewangles.y =
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.upmove = iter->second.z;
}
@ -208,16 +217,17 @@ namespace MWWorld
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
{
Pmove(playerphysics);
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++)
{
btVector3 newPos = it->second->getPosition();
Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z());
Ogre::Vector3 coord = it->second->getPosition();
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)
{
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);
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,
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.
mEngine->addCharacter(handle);
OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle);
act->setPosition(btVector3(position.x,position.y,position.z));
mEngine->addCharacter(handle, mesh, position, scale, rotation);
}
void PhysicsSystem::removeObject (const std::string& handle)
@ -268,15 +272,25 @@ namespace MWWorld
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))
{
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
// 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))
{
@ -288,34 +302,45 @@ namespace MWWorld
}
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))
{
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))
{
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())
{
btTransform transform = mEngine->getRigidBody(handle)->getWorldTransform();
removeObject(handle);
Ogre::Quaternion quat = Ogre::Quaternion(transform.getRotation().getW(), transform.getRotation().getX(), transform.getRotation().getY(), transform.getRotation().getZ());
Ogre::Vector3 vec = Ogre::Vector3(transform.getOrigin().getX(), transform.getOrigin().getY(), transform.getOrigin().getZ());
float scale = node->getScale().x;
Ogre::Quaternion quat = node->getOrientation();
Ogre::Vector3 vec = node->getPosition();
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()
@ -335,8 +360,6 @@ namespace MWWorld
if(cmode)
{
act->enableCollisions(false);
act->setGravity(0.);
act->setVerticalVelocity(0);
mFreeFly = true;
return false;
}
@ -344,8 +367,6 @@ namespace MWWorld
{
mFreeFly = false;
act->enableCollisions(true);
act->setGravity(4.);
act->setVerticalVelocity(0);
return true;
}
}
@ -368,7 +389,7 @@ namespace MWWorld
void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){
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)

@ -24,7 +24,7 @@ namespace MWWorld
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position);
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,
int x, int y, float yoffset,
@ -34,11 +34,11 @@ namespace MWWorld
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();

@ -189,7 +189,9 @@ namespace MWWorld
mPlayer = new MWWorld::Player (mStore.npcs.find ("player"), *this);
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
mGlobalVariables = new Globals (mStore);
@ -450,6 +452,16 @@ namespace MWWorld
mRendering->skySetDate (mGlobalVariables->getInt ("day"), month);
}
int World::getDay()
{
return mGlobalVariables->getInt("day");
}
int World::getMonth()
{
return mGlobalVariables->getInt("month");
}
TimeStamp World::getTimeStamp() const
{
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)
{
ESM::Position &pos = ptr.getRefData().getPosition();
@ -550,11 +572,10 @@ namespace MWWorld
CellStore *currCell = ptr.getCell();
bool isPlayer = ptr == mPlayer->getPlayer();
bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer;
if (*currCell != newCell) {
if (isPlayer) {
if (!newCell.isExterior()) {
changeToInteriorCell(newCell.cell->mName, pos);
changeToInteriorCell(toLower(newCell.cell->mName), pos);
} else {
int cellX = newCell.cell->mData.mX;
int cellY = newCell.cell->mData.mY;
@ -594,7 +615,7 @@ namespace MWWorld
}
if (haveToMove) {
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)
{
moveObjectImp(ptr, x, y, z);
}
void World::scaleObject (const Ptr& ptr, float scale)
@ -624,7 +647,7 @@ namespace MWWorld
ptr.getCellRef().mScale = scale;
//scale = scale/ptr.getRefData().getBaseNode()->getScale().x;
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)
@ -633,18 +656,25 @@ namespace MWWorld
rot.x = Ogre::Degree(x).valueRadians();
rot.y = Ogre::Degree(y).valueRadians();
rot.z = Ogre::Degree(z).valueRadians();
if (mRendering->rotateObject(ptr, rot, adjust)) {
float *objRot = ptr.getRefData().getPosition().rot;
objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z;
if (ptr.getRefData().getBaseNode() != 0) {
mPhysics->rotateObject(
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
@ -1223,8 +1253,37 @@ namespace MWWorld
mRendering->renderPlayer(mPlayer->getPlayer());
}
void World::renderGlobalMap ()
{
mRendering->renderGlobalMap ();
}
void World::setupExternalRendering (MWRender::ExternalRendering& 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);
///< Set in-game time day.
virtual int getDay();
virtual int getMonth();
virtual TimeStamp getTimeStamp() const;
///< Return current in-game time stamp.
@ -223,6 +226,9 @@ namespace MWWorld
/// \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 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)
const;
///< Convert cell numbers to position.
@ -307,8 +313,16 @@ namespace MWWorld
}
virtual void renderPlayer();
virtual void renderGlobalMap();
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_writer.hpp"
#include <stdio.h>
namespace
{
const int NumberOfHardcodedFlags = 143;

@ -72,6 +72,9 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
cShape = static_cast<BulletShape *>(resource);
resourceName = cShape->getName();
cShape->collide = false;
mBoundingBox = NULL;
cShape->boxTranslation = Ogre::Vector3(0,0,0);
cShape->boxRotation = Ogre::Quaternion::IDENTITY;
mTriMesh = new btTriangleMesh();
@ -125,9 +128,14 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
delete m_meshInterface;
}
};
if(mBoundingBox != NULL)
cShape->Shape = mBoundingBox;
currentShape = new TriangleMeshShape(mTriMesh,true);
cShape->Shape = currentShape;
else
{
currentShape = new TriangleMeshShape(mTriMesh,true);
cShape->Shape = currentShape;
}
}
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
if (node->recType == Nif::RC_NiNode)

@ -102,8 +102,11 @@ private:
std::string resourceName;
std::string resourceGroup;
BulletShape* cShape;//current shape
btTriangleMesh *mTriMesh;
btBoxShape *mBoundingBox;
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
#define shTexture2D sampler2D

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

@ -137,6 +137,8 @@
shSampler2D(normalMap) // global normal map
shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection)
@shForeach(@shPropertyString(num_blendmaps))
shSampler2D(blendMap@shIterator)
@ -247,9 +249,9 @@
#if IS_FIRST_PASS == 1 && @shIterator == 0
// 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
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
@shEndForeach
@ -336,7 +338,7 @@
// regular fog only if fragment is above water
if (worldPos.y > waterLevel)
#endif
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue);
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue);
#endif
// prevent negative colour output (for example with negative lights)
@ -351,12 +353,12 @@
float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz));
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));
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 waterext = float3(0.6, 0.9, 1.0);//water extinction
float3 watercolour = (gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0;
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 = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3;
@ -369,6 +371,8 @@
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater);
#endif
shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz);
#if MRT
shOutputColour(1) = float4(depth / far,1,1,1);

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

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

@ -77,8 +77,9 @@
<!-- Buttons -->
<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">
<Property key="Caption" value="#{sCreate}"/>
</Widget>

@ -15,7 +15,9 @@
<!-- Dialog buttons -->
<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">
<Property key="Caption" value="#{sBack}"/>
</Widget>

@ -61,7 +61,9 @@
<!-- Dialog buttons -->
<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">
<Property key="Caption" value="#{sBack}"/>
</Widget>

@ -59,7 +59,9 @@
<!-- Dialog buttons -->
<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">
<Property key="Caption" value="#{sCreateClassMenu1}"/>
</Widget>

@ -21,7 +21,9 @@
<!-- Dialog buttons -->
<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">
<Property key="Caption" value="#{sBack}"/>
</Widget>

@ -57,7 +57,10 @@
<!-- Dialog buttons -->
<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">
<Property key="Caption" value="#{sBack}"/>
</Widget>

@ -112,7 +112,9 @@
<!-- Dialog buttons -->
<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">
<Property key="Caption" value="#{sBack}"/>
</Widget>

@ -14,7 +14,9 @@
</Widget>
<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">
<Property key="Caption" value="#{sCancel}"/>
</Widget>

@ -12,7 +12,9 @@
</Widget>
<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">
<Property key="Caption" value="#{sTakeAll}"/>
</Widget>

@ -22,7 +22,9 @@
<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">
<Property key="Caption" value="#{sCancel}"/>
</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">
<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 -->
<Widget type="ScrollView" skin="MW_MapView" position="0 0 284 264" align="ALIGN_STRETCH" name="LocalMap">
<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"/>
</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>
<!-- World button -->
<Widget type="AutoSizedButton" skin="MW_Button" position="213 233 61 22" align="ALIGN_BOTTOM ALIGN_RIGHT" name="WorldButton">
<Property key="ExpandDirection" value="Left"/>

@ -157,7 +157,7 @@
<Widget type="TabItem" skin="" position="4 28 344 272">
<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">
@ -174,20 +174,37 @@
</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="AutoSizedTextBox" skin="SandText" align="Left Top">
<Property key="Caption" value="Shaders"/>
</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="AutoSizedTextBox" skin="SandText" align="Left Top">
<Property key="Caption" value="Show frames per second"/>
<Property key="Caption" value="FPS"/>
</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">
<Property key="Caption" value="Field of View"/>
</Widget>

@ -56,7 +56,9 @@
</Widget>
<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">
<Property key="Caption" value="#{sBarterDialog8}"/>
</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
# opengl render to texture mode, valid options:
# PBuffer, FBO, Copy
opengl rtt mode = FBO
gamma = 2.2
[GUI]
# 1 is fully opaque
menu transparency = 0.84

@ -4,7 +4,7 @@
#include <OgreResource.h>
#include <OgreResourceManager.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.
//But the risk of name collision seems pretty low here.
@ -31,6 +31,8 @@ public:
virtual ~BulletShape();
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.
bool collide;
};

@ -2,6 +2,7 @@
#include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h>
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
#include "pmove.h"
#include <components/nifbullet/bullet_nif_loader.hpp>
#include "CMotionState.h"
#include "OgreRoot.h"
@ -26,111 +27,139 @@ namespace Physic
COL_RAYCASTING = BIT(3)
};
PhysicActor::PhysicActor(std::string name)
{
mName = name;
// The capsule is at the origin
btTransform transform;
transform.setIdentity();
// External capsule
externalGhostObject = new PairCachingGhostObject(name);
externalGhostObject->setWorldTransform( transform );
btScalar externalCapsuleHeight = 120;
btScalar externalCapsuleWidth = 19;
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(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)
{
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation);
Ogre::Quaternion inverse = mBoxRotation.Inverse();
mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w);
mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map
pmove = new playerMove;
pmove->mEngine = mEngine;
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;
}
}
PhysicActor::~PhysicActor()
{
delete mCharacter;
delete internalGhostObject;
delete internalCollisionShape;
delete externalGhostObject;
delete externalCollisionShape;
if(mBody){
mEngine->dynamicsWorld->removeRigidBody(mBody);
delete mBody;
}
delete pmove;
}
void PhysicActor::setCurrentWater(bool hasWater, int waterHeight){
pmove->hasWater = hasWater;
if(hasWater){
pmove->waterHeight = waterHeight;
}
}
void PhysicActor::setGravity(float gravity)
{
mCharacter->setGravity(gravity);
//mCharacter->
pmove->ps.gravity = gravity;
}
void PhysicActor::setSpeed(float speed)
{
pmove->ps.speed = speed;
}
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()
{
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)
{
externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat );
internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat );
void PhysicActor::setPmoveViewAngles(float pitch, float yaw, float roll){
pmove->ps.viewangles.x = pitch;
pmove->ps.viewangles.y = yaw;
pmove->ps.viewangles.z = roll;
}
void PhysicActor::setRotation(const btQuaternion& quat)
void PhysicActor::setRotation(const Ogre::Quaternion quat)
{
externalGhostObject->getWorldTransform().setRotation( quat );
internalGhostObject->getWorldTransform().setRotation( quat );
if(!quat.equals(getRotation(), Ogre::Radian(0))){
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);
externalGhostObject->getWorldTransform().setOrigin(pos+mTranslation);
mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
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;
}
RigidBodyContainer::iterator rb_it = RigidBodyMap.begin();
for (; rb_it != RigidBodyMap.end(); ++rb_it)
RigidBodyContainer::iterator rb_it = ObjectMap.begin();
for (; rb_it != ObjectMap.end(); ++rb_it)
{
if (rb_it->second != NULL)
{
@ -247,9 +276,7 @@ namespace Physic
{
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;
pa_it->second = NULL;
@ -332,18 +359,42 @@ namespace Physic
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 outputstring = mesh + sid;
//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
mShapeLoader->load(outputstring,"General");
BulletShapeManager::getSingletonPtr()->load(outputstring,"General");
BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General");
shape->Shape->setLocalScaling( btVector3(scale,scale,scale));
//btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(dynamic_cast<btBvhTriangleMeshShape*> (shape->Shape), btVector3(scale,scale,scale));
//create the motionState
CMotionState* newMotionState = new CMotionState(this,name);
@ -352,11 +403,19 @@ namespace Physic
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape);
RigidBody* body = new RigidBody(CI,name);
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;
}
void PhysicEngine::addRigidBody(RigidBody* body)
void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap)
{
if(body)
{
@ -369,21 +428,23 @@ namespace Physic
dynamicsWorld->addRigidBody(body,COL_RAYCASTING,COL_RAYCASTING|COL_WORLD);
}
body->setActivationState(DISABLE_DEACTIVATION);
RigidBody* oldBody = RigidBodyMap[body->mName];
if (oldBody != NULL)
{
dynamicsWorld->removeRigidBody(oldBody);
delete oldBody;
if(addToMap){
RigidBody* oldBody = ObjectMap[body->mName];
if (oldBody != NULL)
{
dynamicsWorld->removeRigidBody(oldBody);
delete oldBody;
}
ObjectMap[body->mName] = body;
}
RigidBodyMap[body->mName] = body;
}
}
void PhysicEngine::removeRigidBody(std::string name)
{
RigidBodyContainer::iterator it = RigidBodyMap.find(name);
if (it != RigidBodyMap.end() )
RigidBodyContainer::iterator it = ObjectMap.find(name);
if (it != ObjectMap.end() )
{
RigidBody* body = it->second;
if(body != NULL)
@ -402,8 +463,8 @@ namespace Physic
void PhysicEngine::deleteRigidBody(std::string name)
{
RigidBodyContainer::iterator it = RigidBodyMap.find(name);
if (it != RigidBodyMap.end() )
RigidBodyContainer::iterator it = ObjectMap.find(name);
if (it != ObjectMap.end() )
{
RigidBody* body = it->second;
//btScaledBvhTriangleMeshShape* scaled = dynamic_cast<btScaledBvhTriangleMeshShape*> (body->getCollisionShape());
@ -416,16 +477,16 @@ namespace Physic
{
delete scaled;
}*/
RigidBodyMap.erase(it);
ObjectMap.erase(it);
}
}
RigidBody* PhysicEngine::getRigidBody(std::string name)
{
RigidBodyContainer::iterator it = RigidBodyMap.find(name);
if (it != RigidBodyMap.end() )
RigidBodyContainer::iterator it = ObjectMap.find(name);
if (it != ObjectMap.end() )
{
RigidBody* body = RigidBodyMap[name];
RigidBody* body = ObjectMap[name];
return body;
}
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
// leak when character would be added twice
removeCharacter(name);
PhysicActor* newActor = new PhysicActor(name);
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 );
PhysicActor* newActor = new PhysicActor(name, mesh, this, position, rotation, scale);
//dynamicsWorld->addAction( newActor->mCharacter );
PhysicActorMap[name] = newActor;
}
@ -465,25 +527,11 @@ namespace Physic
PhysicActor* act = it->second;
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;
}
PhysicActorMap.erase(it);
}
//std::cout << "ok";
}
PhysicActor* PhysicEngine::getCharacter(std::string name)

@ -9,14 +9,16 @@
#include "BulletShapeLoader.h"
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
class btRigidBody;
class btBroadphaseInterface;
class btDefaultCollisionConfiguration;
class btSequentialImpulseConstraintSolver;
class btCollisionDispatcher;
class btDiscreteDynamicsWorld;
class btKinematicCharacterController;
class btHeightfieldTerrainShape;
struct playerMove;
namespace BtOgre
{
@ -28,11 +30,14 @@ namespace MWWorld
class World;
}
namespace OEngine {
namespace Physic
{
class CMotionState;
struct PhysicEvent;
class PhysicEngine;
class RigidBody;
/**
*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
{
public:
PhysicActor(std::string name);
PhysicActor(std::string name, std::string mesh, PhysicEngine *engine, Ogre::Vector3 position, Ogre::Quaternion rotation, float scale);
~PhysicActor();
void setCurrentWater(bool hasWater, int waterHeight);
/**
* This function set the walkDirection. This is not relative to the actor orientation.
* I think it's also needed to take time into account. A typical call should look like this:
* setWalkDirection( mvt * orientation * dt)
* This function sets the movement keys for pmove
*/
void setWalkDirection(const btVector3& mvt);
void setMovement(signed char rightmove, signed char forwardmove, signed char upmove);
void Rotate(const btQuaternion& quat);
void setRotation(const btQuaternion& quat);
/**
* This adjusts the rotation of a PhysicActor
* 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 setVerticalVelocity(float z);
void setSpeed(float speed);
void setJumpVelocity(float velocity);
void enableCollisions(bool collision);
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
*each time get/setposition is called.
*/
btVector3 mTranslation;
private:
OEngine::Physic::RigidBody* mBody;
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();
/**
* Create a RigidBody.It does not add it to the simulation, but it does add it to the rigidBody Map,
* so you can get it with the getRigidBody function.
* Creates a RigidBody. It does not add it to the simulation.
* 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
*/
@ -163,7 +212,7 @@ namespace Physic
/**
* 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.
@ -184,7 +233,8 @@ namespace Physic
/**
* 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?
@ -254,7 +304,7 @@ namespace Physic
HeightFieldContainer mHeightFieldMap;
typedef std::map<std::string,RigidBody*> RigidBodyContainer;
RigidBodyContainer RigidBodyMap;
RigidBodyContainer ObjectMap;
typedef std::map<std::string, PhysicActor*> PhysicActorContainer;
PhysicActorContainer PhysicActorMap;
@ -263,6 +313,7 @@ namespace Physic
BtOgre::DebugDrawer* mDebugDrawer;
bool isDebugCreated;
bool mDebugActive;
};

@ -231,7 +231,7 @@ bool PM_SlideMove( bool gravity )
// see if we can make it there
//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);
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)
{
@ -301,7 +301,7 @@ bool PM_SlideMove( bool gravity )
if(planes[i].x >= .70)
{
pm->ps.velocity = Ogre::Vector3(0,0,0);
pm->ps.velocity.z = 0;
return true;
}
// 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);
//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);
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)
//VectorSet(up, 0, 0, 1);
@ -479,7 +479,7 @@ int PM_StepSlideMove( bool gravity )
// 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);
//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 ( 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);
//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 )
//VectorCopy (trace.endpos, pm->ps->origin);
pm->ps.origin = trace.endpos;
@ -527,7 +527,7 @@ int PM_StepSlideMove( bool gravity )
delta = pm->ps.origin.z - start_o.z;
if ( delta > 2 )
{
pm->ps.counter = 5;
pm->ps.counter = 10;
/*
if (gravity)
@ -657,10 +657,11 @@ static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel
// int i;
float addspeed, accelspeed, currentspeed;
// currentspeed = pm->ps->velocity dot wishdir
//currentspeed = DotProduct (pm->ps->velocity, wishdir);
currentspeed = pm->ps.velocity.dotProduct(wishdir);
addspeed = wishspeed - currentspeed;
if (addspeed <= 0)
return;
@ -675,6 +676,8 @@ static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel
//for (i=0 ; i<3 ; i++)
//pm->ps->velocity[i] += accelspeed * wishdir[i];
pm->ps.velocity += (wishdir * accelspeed);
//pm->ps.velocity = wishdir * wishspeed; //New, for instant acceleration
}
static bool PM_CheckJump(void)
@ -701,7 +704,7 @@ static bool PM_CheckJump(void)
//pm->ps->pm_flags |= PMF_JUMP_HELD;
pm->ps.groundEntityNum = ENTITYNUM_NONE;
pm->ps.velocity.z = JUMP_VELOCITY;
pm->ps.velocity.z = pm->ps.jump_velocity;
pm->ps.bSnap = false;
//PM_AddEvent( EV_JUMP );
@ -899,7 +902,7 @@ static void PM_WalkMove( playerMove* const pmove )
if (pmove->hasWater )
{
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)
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);
//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
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);
//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 )
{
@ -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);
//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;
return true;
}
@ -1338,7 +1341,7 @@ static void PM_CrashLand( void )
{
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)
{
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);
//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;
// 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;
#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 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_WORLD (MAX_GENTITIES - 2)
#define MIN_WALK_NORMAL .7f // can't walk on very steep slopes
#define JUMP_VELOCITY (270)
#define PS_PMOVEFRAMECOUNTBITS 6
#define MINS_Z -24
#define DEFAULT_VIEWHEIGHT 26
@ -90,9 +89,9 @@ struct playerMove
{
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);
viewangles = Ogre::Vector3(0.0f, 0.0f, 0.0f);
@ -117,11 +116,13 @@ struct playerMove
Ogre::Vector3 velocity;
Ogre::Vector3 origin;
Ogre::Vector3 halfExtents;
bool bSnap;
bool snappingImplemented;
int counter;
float gravity; // default = 800
float speed; // default = 320
float jump_velocity; //default = 270
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
{
static float lastyaw = 0.0f;
static float lastpitch = 0.0f;
//if (!traceobj)
// return;
//if (!traceobj->incellptr)
// return;
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;
//std::cout << "Starting trace\n";
@ -32,7 +36,7 @@ void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogr
//Ogre::Vector3 endReplace = startReplace;
//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)
results->startsolid = true;
@ -95,13 +99,14 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3&
//if(enginePass->dynamicsWorld->getCollisionObjectArray().at(60)->getCollisionShape()->isConvex())
// std::cout << "It's convex\n";
const btVector3 btstart(start.x, start.y, start.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 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 to(btrot, btend);
@ -176,7 +181,8 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3&
if (!TestPointAgainstAabb2(aabbMin, aabbMax, *(const btVector3* const)&(start) ) )
{
//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 <btBulletCollisionCommon.h>
#include <components/nifbullet/bullet_nif_loader.hpp>
#include <openengine/bullet/pmove.h>
#include <openengine/bullet/physic.hpp>
#include "pmove.h"
enum traceWorldType

@ -1,52 +1,50 @@
#include "fader.hpp"
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include <OgreOverlay.h>
#include <OgreMaterial.h>
#include <OgreTechnique.h>
#include <OgreMaterialManager.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 OEngine::Render;
Fader::Fader() :
mMode(FadingMode_In),
mRemainingTime(0.f),
mTargetTime(0.f),
mTargetAlpha(0.f),
mCurrentAlpha(0.f),
mStartAlpha(0.f)
Fader::Fader(Ogre::SceneManager* sceneMgr)
: mSceneMgr(sceneMgr)
, mMode(FadingMode_In)
, mRemainingTime(0.f)
, mTargetTime(0.f)
, mTargetAlpha(0.f)
, mCurrentAlpha(0.f)
, mStartAlpha(0.f)
{
// 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->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mFadeTextureUnit = pass->createTextureUnitState();
mFadeTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(0.f, 0.f, 0.f)); // always black colour
// Create the overlay
OverlayManager& ovm = OverlayManager::getSingleton();
mRectangle = new Ogre::Rectangle2D(true);
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 );
OverlayContainer* overlay_panel;
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();
Fader::~Fader()
{
delete mRectangle;
}
void Fader::update(float dt)
@ -69,12 +67,12 @@ void Fader::update(float dt)
mRemainingTime -= dt;
}
if (mCurrentAlpha == 0.f) mOverlay->hide();
if (mCurrentAlpha == 0.f) mRectangle->setVisible(false);
}
void Fader::applyAlpha()
{
mOverlay->show();
mRectangle->setVisible(true);
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.
To achieve this, it uses a full-screen Ogre::Overlay
inspired by http://www.ogre3d.org/tikiwiki/FadeEffectOverlay (heavily adjusted)
To achieve this, it uses a full-screen Rectangle2d
*/
namespace Ogre
{
class TextureUnitState;
class Overlay;
class Rectangle2D;
class SceneManager;
}
namespace OEngine {
namespace Render
{
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
class Fader
{
FadingMode_In,
FadingMode_Out
public:
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

@ -44,8 +44,10 @@ void OgreRenderer::cleanup()
delete mFader;
mFader = NULL;
OGRE_DELETE mRoot;
delete mRoot;
mRoot = NULL;
unloadPlugins();
}
void OgreRenderer::start()
@ -78,7 +80,7 @@ void OgreRenderer::start()
#endif
}
bool OgreRenderer::loadPlugins()
void OgreRenderer::loadPlugins()
{
#ifdef ENABLE_PLUGIN_GL
mGLPlugin = new Ogre::GLPlugin();
@ -100,7 +102,30 @@ bool OgreRenderer::loadPlugins()
mParticleFXPlugin = new Ogre::ParticleFXPlugin();
mRoot->installPlugin(mParticleFXPlugin);
#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)
@ -120,6 +145,7 @@ float OgreRenderer::getFPS()
void OgreRenderer::configure(const std::string &logPath,
const std::string& renderSystem,
const std::string& rttMode,
bool _logging)
{
// Set up logging first
@ -173,6 +199,9 @@ void OgreRenderer::configure(const std::string &logPath,
if (rs == 0)
throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded");
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)
@ -218,7 +247,7 @@ void OgreRenderer::createScene(const std::string& camName, float fov, float near
// Alter the camera aspect ratio to match the viewport
mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight()));
mFader = new Fader();
mFader = new Fader(mScene);
}
void OgreRenderer::adjustViewport()

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

@ -4,6 +4,7 @@
#include <OgreRenderTexture.h>
#include <OgreSubEntity.h>
#include <OgreEntity.h>
#include <stdexcept>
#include <extern/shiny/Main/Factory.hpp>
@ -73,7 +74,7 @@ namespace Render
int id = Ogre::any_cast<int>(subEntity->getParent ()->getUserObjectBindings().getUserAny());
bool found = false;
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)
{

@ -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
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)
Website: http://www.openmw.org
@ -97,6 +97,39 @@ Allowed options:
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
Bug #225: Valgrind reports about 40MB of leaked memory

Loading…
Cancel
Save