Merge remote-tracking branch 'scrawl/master'

openmw-35
Marc Zinnschlag 10 years ago
commit 82ff737c31

@ -408,7 +408,7 @@ IF(NOT WIN32 AND NOT APPLE)
# Install binaries
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
IF(BUILD_LAUNCHER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-launcher" DESTINATION "${BINDIR}" )
ENDIF(BUILD_LAUNCHER)
IF(BUILD_BSATOOL)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
@ -417,7 +417,7 @@ IF(NOT WIN32 AND NOT APPLE)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
ENDIF(BUILD_ESMTOOL)
IF(BUILD_MWINIIMPORTER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-iniimporter" DESTINATION "${BINDIR}" )
ENDIF(BUILD_MWINIIMPORTER)
IF(BUILD_ESSIMPORTER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-essimporter" DESTINATION "${BINDIR}" )
@ -476,10 +476,10 @@ if(WIN32)
DESTINATION ".")
IF(BUILD_LAUNCHER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/omwlauncher.exe" DESTINATION ".")
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-launcher.exe" DESTINATION ".")
ENDIF(BUILD_LAUNCHER)
IF(BUILD_MWINIIMPORTER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/mwiniimport.exe" DESTINATION ".")
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-iniimporter.exe" DESTINATION ".")
ENDIF(BUILD_MWINIIMPORTER)
IF(BUILD_ESSIMPORTER)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-essimporter.exe" DESTINATION ".")
@ -506,7 +506,7 @@ if(WIN32)
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW")
IF(BUILD_LAUNCHER)
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};omwlauncher;OpenMW Launcher")
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-launcher;OpenMW Launcher")
ENDIF(BUILD_LAUNCHER)
IF(BUILD_OPENCS)
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};opencs;OpenMW Construction Set")
@ -525,7 +525,7 @@ if(WIN32)
SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}")
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "openmw-launcher.exe")
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp")
@ -699,7 +699,7 @@ if (WIN32)
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_LAUNCHER)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_BSATOOL)
@ -717,7 +717,7 @@ if (WIN32)
set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
endif (BUILD_OPENCS)
if (BUILD_MWINIIMPORTER)
set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MWINIIMPORTER)
endif(MSVC)

@ -25,6 +25,7 @@ set(ESSIMPORTER_FILES
convertcntc.cpp
convertscri.cpp
convertscpt.cpp
convertplayer.cpp
)
add_executable(openmw-essimporter

@ -29,6 +29,12 @@ namespace ESSImport
}
cStats.mGoldPool = acdt.mGoldPool;
cStats.mTalkedTo = acdt.mFlags & TalkedToPlayer;
cStats.mAttacked = acdt.mFlags & Attacked;
}
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats)
{
cStats.mDead = acsc.mFlags & Dead;
}
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats)

@ -15,6 +15,7 @@ namespace ESSImport
void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats);
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats);
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats);
}

@ -274,6 +274,8 @@ namespace ESSImport
const CellRef& cellref = *refIt;
ESM::CellRef out (cellref);
// TODO: use mContext->mCreatures/mNpcs
if (!isIndexedRefId(cellref.mIndexedRefId))
{
// non-indexed RefNum, i.e. no CREC/NPCC/CNTC record associated with it
@ -309,9 +311,12 @@ namespace ESSImport
objstate.blank();
objstate.mRef = out;
objstate.mRef.mRefID = idLower;
// probably need more micromanagement here so we don't overwrite values
// TODO: need more micromanagement here so we don't overwrite values
// from the ESM with default values
convertACDT(cellref.mACDT, objstate.mCreatureStats);
if (cellref.mHasACDT)
convertACDT(cellref.mACDT, objstate.mCreatureStats);
if (cellref.mHasACSC)
convertACSC(cellref.mACSC, objstate.mCreatureStats);
convertNpcData(cellref, objstate.mNpcStats);
convertNPCC(npccIt->second, objstate);
convertCellRef(cellref, objstate);
@ -343,9 +348,12 @@ namespace ESSImport
objstate.blank();
objstate.mRef = out;
objstate.mRef.mRefID = idLower;
convertACDT(cellref.mACDT, objstate.mCreatureStats);
// probably need more micromanagement here so we don't overwrite values
// TODO: need more micromanagement here so we don't overwrite values
// from the ESM with default values
if (cellref.mHasACDT)
convertACDT(cellref.mACDT, objstate.mCreatureStats);
if (cellref.mHasACSC)
convertACSC(cellref.mACSC, objstate.mCreatureStats);
convertCREC(crecIt->second, objstate);
convertCellRef(cellref, objstate);
esm.writeHNT ("OBJE", ESM::REC_CREA);

@ -35,6 +35,7 @@
#include "convertacdt.hpp"
#include "convertnpcc.hpp"
#include "convertscpt.hpp"
#include "convertplayer.hpp"
namespace ESSImport
{
@ -104,10 +105,10 @@ public:
npc.load(esm);
if (id != "player")
{
// TODO:
// this should handle changes to the NPC struct, but since there is no index here
// Handles changes to the NPC struct, but since there is no index here
// it will apply to ALL instances of the class. seems to be the reason for the
// "feature" in MW where changing AI settings of one guard will change it for all guards of that refID.
mContext->mNpcs[Misc::StringUtils::lowerCase(id)] = npc;
}
else
{
@ -139,6 +140,7 @@ public:
ESM::Creature creature;
std::string id = esm.getHNString("NAME");
creature.load(esm);
mContext->mCreatures[Misc::StringUtils::lowerCase(id)] = creature;
}
};
@ -259,32 +261,23 @@ private:
class ConvertPCDT : public Converter
{
public:
ConvertPCDT() : mFirstPersonCam(true) {}
virtual void read(ESM::ESMReader &esm)
{
PCDT pcdt;
pcdt.load(esm);
mContext->mPlayer.mBirthsign = pcdt.mBirthsign;
mContext->mPlayer.mObject.mNpcStats.mBounty = pcdt.mBounty;
for (std::vector<PCDT::FNAM>::const_iterator it = pcdt.mFactions.begin(); it != pcdt.mFactions.end(); ++it)
{
ESM::NpcStats::Faction faction;
faction.mExpelled = (it->mFlags & 0x2) != 0;
faction.mRank = it->mRank;
faction.mReputation = it->mReputation;
mContext->mPlayer.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(it->mFactionName.toString())] = faction;
}
for (int i=0; i<8; ++i)
mContext->mPlayer.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
mContext->mPlayer.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
for (std::vector<std::string>::const_iterator it = pcdt.mKnownDialogueTopics.begin();
it != pcdt.mKnownDialogueTopics.end(); ++it)
{
mContext->mDialogueState.mKnownTopics.push_back(Misc::StringUtils::lowerCase(*it));
}
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam);
}
virtual void write(ESM::ESMWriter &esm)
{
esm.startRecord(ESM::REC_CAM_);
esm.writeHNT("FIRS", mFirstPersonCam);
esm.endRecord(ESM::REC_CAM_);
}
private:
bool mFirstPersonCam;
};
class ConvertCNTC : public Converter
@ -416,7 +409,7 @@ private:
/// Seen responses for a dialogue topic?
/// Each DIAL record is followed by a number of INFO records, I believe, just like in ESMs
/// Dialogue conversion problems (probably have to adjust OpenMW format) -
/// Dialogue conversion problems:
/// - Journal is stored in one continuous HTML markup rather than each entry separately with associated info ID.
/// - Seen dialogue responses only store the INFO id, rather than the fulltext.
/// - Quest stages only store the INFO id, rather than the journal entry fulltext.

@ -0,0 +1,39 @@
#include "convertplayer.hpp"
namespace ESSImport
{
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam)
{
out.mBirthsign = pcdt.mBirthsign;
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
for (std::vector<PCDT::FNAM>::const_iterator it = pcdt.mFactions.begin(); it != pcdt.mFactions.end(); ++it)
{
ESM::NpcStats::Faction faction;
faction.mExpelled = (it->mFlags & 0x2) != 0;
faction.mRank = it->mRank;
faction.mReputation = it->mReputation;
out.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(it->mFactionName.toString())] = faction;
}
for (int i=0; i<8; ++i)
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
out.mObject.mCreatureStats.mDrawState = 1;
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Spell)
out.mObject.mCreatureStats.mDrawState = 2;
// TODO: convert PNAM.mSkillProgress, needs to be converted to uniform scale
// (or change openmw to accept non-uniform skill progress)
firstPersonCam = (pcdt.mPNAM.mCameraState == PCDT::CameraState_FirstPerson);
for (std::vector<std::string>::const_iterator it = pcdt.mKnownDialogueTopics.begin();
it != pcdt.mKnownDialogueTopics.end(); ++it)
{
outDialogueTopics.push_back(Misc::StringUtils::lowerCase(*it));
}
}
}

@ -0,0 +1,15 @@
#ifndef OPENMW_ESSIMPORT_CONVERTPLAYER_H
#define OPENMW_ESSIMPORT_CONVERTPLAYER_H
#include "importplayer.hpp"
#include <components/esm/player.hpp>
namespace ESSImport
{
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam);
}
#endif

@ -20,12 +20,22 @@ namespace ESSImport
ESM::CellRef::loadData(esm);
// FIXME: not all actors have this, add flag
esm.getHNOT(mACDT, "ACDT");
mHasACDT = false;
if (esm.isNextSub("ACDT"))
{
mHasACDT = true;
esm.getHT(mACDT);
}
mHasACSC = false;
if (esm.isNextSub("ACSC"))
{
mHasACSC = true;
esm.getHT(mACSC);
}
ACSC acsc;
esm.getHNOT(acsc, "ACSC");
esm.getHNOT(acsc, "ACSL");
if (esm.isNextSub("ACSL"))
esm.skipHSubSize(112);
if (esm.isNextSub("CSTN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?

@ -17,7 +17,13 @@ namespace ESSImport
enum ACDTFlags
{
TalkedToPlayer = 0x4
TalkedToPlayer = 0x4,
Attacked = 0x100,
Unknown = 0x200
};
enum ACSCFlags
{
Dead = 0x2
};
/// Actor data, shared by (at least) REFR and CellRef
@ -28,23 +34,33 @@ namespace ESSImport
// Note, not stored at *all*:
// - Level changes are lost on reload, except for the player (there it's in the NPC record).
unsigned char mUnknown[12];
unsigned char mFlags; // ACDTFlags
unsigned char mUnknown1[3];
unsigned int mFlags;
float mBreathMeter; // Seconds left before drowning
unsigned char mUnknown2[20];
float mDynamic[3][2];
unsigned char mUnknown3[16];
float mAttributes[8][2];
unsigned char mUnknown4[112];
float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
unsigned char mUnknown4[4];
unsigned int mGoldPool;
unsigned char mUnknown5[4];
};
struct ACSC
{
unsigned char mUnknown1[17];
unsigned char mFlags; // ACSCFlags
unsigned char mUnknown2[94];
};
#pragma pack(pop)
struct ActorData : public ESM::CellRef
{
bool mHasACDT;
ACDT mACDT;
bool mHasACSC;
ACSC mACSC;
int mSkills[27][2];
// creature combat stats, base and modified
@ -60,12 +76,6 @@ namespace ESSImport
void load(ESM::ESMReader& esm);
};
/// Unknown, shared by (at least) REFR and CellRef
struct ACSC
{
unsigned char unknown[112];
};
}
#endif

@ -21,6 +21,8 @@
#include <components/esm/loadlevlist.hpp>
#include <components/esm/loadglob.hpp>
#include <components/to_utf8/to_utf8.hpp>
#include "importercontext.hpp"
#include "converter.hpp"
@ -44,9 +46,10 @@ namespace
namespace ESSImport
{
Importer::Importer(const std::string &essfile, const std::string &outfile)
Importer::Importer(const std::string &essfile, const std::string &outfile, const std::string &encoding)
: mEssFile(essfile)
, mOutFile(outfile)
, mEncoding(encoding)
{
}
@ -167,14 +170,30 @@ namespace ESSImport
std::cout << "Data 1:" << std::endl;
for (unsigned int k=0; k<sub.mData.size(); ++k)
{
bool different = false;
if (k >= sub2.mData.size() || sub2.mData[k] != sub.mData[k])
different = true;
if (different)
std::cout << "\033[033m";
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)sub.mData[k] << " ";
if (different)
std::cout << "\033[0m";
}
std::cout << std::endl;
std::cout << "Data 2:" << std::endl;
for (unsigned int k=0; k<sub2.mData.size(); ++k)
{
bool different = false;
if (k >= sub.mData.size() || sub.mData[k] != sub2.mData[k])
different = true;
if (different)
std::cout << "\033[033m";
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)sub2.mData[k] << " ";
if (different)
std::cout << "\033[0m";
}
std::cout << std::endl;
}
@ -188,10 +207,10 @@ namespace ESSImport
Ogre::LogManager logman;
Ogre::Root root;
// TODO: set up encoding on ESMReader based on openmw.cfg / --encoding switch
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding));
ESM::ESMReader esm;
esm.open(mEssFile);
esm.setEncoder(&encoder);
Context context;

@ -9,7 +9,7 @@ namespace ESSImport
class Importer
{
public:
Importer(const std::string& essfile, const std::string& outfile);
Importer(const std::string& essfile, const std::string& outfile, const std::string& encoding);
void run();
@ -18,6 +18,7 @@ namespace ESSImport
private:
std::string mEssFile;
std::string mOutFile;
std::string mEncoding;
};
}

@ -7,6 +7,8 @@
#include <components/esm/player.hpp>
#include <components/esm/dialoguestate.hpp>
#include <components/esm/globalmap.hpp>
#include <components/esm/loadcrea.hpp>
#include <components/esm/loadnpc.hpp>
#include "importnpcc.hpp"
#include "importcrec.hpp"
@ -15,6 +17,7 @@
namespace ESSImport
{
@ -42,6 +45,9 @@ namespace ESSImport
std::map<std::pair<int, std::string>, NPCC> mNpcChanges;
std::map<std::pair<int, std::string>, CNTC> mContainerChanges;
std::map<std::string, ESM::Creature> mCreatures;
std::map<std::string, ESM::NPC> mNpcs;
Context()
{
mPlayer.mAutoMove = 0;

@ -38,6 +38,17 @@ struct PCDT
std::vector<std::string> mKnownDialogueTopics;
enum DrawState_
{
DrawState_Weapon = 0x80,
DrawState_Spell = 0x100
};
enum CameraState
{
CameraState_FirstPerson = 0x8,
CameraState_ThirdPerson = 0xa
};
#pragma pack(push)
#pragma pack(1)
struct FNAM
@ -49,11 +60,13 @@ struct PCDT
unsigned char mUnknown2[3];
ESM::NAME32 mFactionName;
};
struct PNAM
{
unsigned char mUnknown1[4];
unsigned char mLevelProgress;
unsigned char mUnknown2[111];
short mDrawState; // DrawState
short mCameraState; // CameraState
unsigned int mLevelProgress;
float mSkillProgress[27]; // skill progress, non-uniform scaled
unsigned char mSkillIncreases[8]; // number of skill increases for each attribute
unsigned char mUnknown3[88];
};

@ -5,6 +5,8 @@
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
#include <components/files/configurationmanager.hpp>
#include "importer.hpp"
namespace bpo = boost::program_options;
@ -23,31 +25,36 @@ int main(int argc, char** argv)
("mwsave,m", bpo::value<std::string>(), "morrowind .ess save file")
("output,o", bpo::value<std::string>(), "output file (.omwsave)")
("compare,c", "compare two .ess files")
("encoding", boost::program_options::value<std::string>()->default_value("win1252"), "encoding of the save file")
;
p_desc.add("mwsave", 1).add("output", 1);
bpo::variables_map vm;
bpo::variables_map variables;
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv)
.options(desc)
.positional(p_desc)
.run();
bpo::store(parsed, vm);
bpo::store(parsed, variables);
if(vm.count("help") || !vm.count("mwsave") || !vm.count("output")) {
if(variables.count("help") || !variables.count("mwsave") || !variables.count("output")) {
std::cout << desc;
return 0;
}
bpo::notify(vm);
bpo::notify(variables);
Files::ConfigurationManager cfgManager(true);
cfgManager.readConfiguration(variables, desc);
std::string essFile = vm["mwsave"].as<std::string>();
std::string outputFile = vm["output"].as<std::string>();
std::string essFile = variables["mwsave"].as<std::string>();
std::string outputFile = variables["output"].as<std::string>();
std::string encoding = variables["encoding"].as<std::string>();
ESSImport::Importer importer(essFile, outputFile);
ESSImport::Importer importer(essFile, outputFile, encoding);
if (vm.count("compare"))
if (variables.count("compare"))
importer.compare();
else
{

@ -78,7 +78,7 @@ if(NOT WIN32)
endif(NOT WIN32)
# Main executable
add_executable(omwlauncher
add_executable(openmw-launcher
${GUI_TYPE}
${LAUNCHER}
${LAUNCHER_HEADER}
@ -87,7 +87,7 @@ add_executable(omwlauncher
${UI_HDRS}
)
target_link_libraries(omwlauncher
target_link_libraries(openmw-launcher
${Boost_LIBRARIES}
${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS}
@ -99,6 +99,6 @@ target_link_libraries(omwlauncher
if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage)
target_link_libraries(omwlauncher gcov)
target_link_libraries(openmw-launcher gcov)
endif()

@ -27,25 +27,6 @@ using namespace Process;
Launcher::MainDialog::MainDialog(QWidget *parent)
: mGameSettings(mCfgMgr), QMainWindow (parent)
{
// Install the stylesheet font
QFile file;
QFontDatabase fontDatabase;
const QStringList fonts = fontDatabase.families();
// Check if the font is installed
if (!fonts.contains("EB Garamond")) {
QString font = QString::fromUtf8(mCfgMgr.getGlobalDataPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf");
file.setFileName(font);
if (!file.exists()) {
font = QString::fromUtf8(mCfgMgr.getLocalPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf");
}
fontDatabase.addApplicationFont(font);
}
setupUi(this);
mGameInvoker = new ProcessInvoker();

@ -140,7 +140,7 @@ void Launcher::SettingsPage::on_importerButton_clicked()
qDebug() << "arguments " << arguments;
if (!mImporterInvoker->startProcess(QLatin1String("mwiniimport"), arguments, false))
if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false))
return;
}

@ -9,16 +9,16 @@ set(MWINIIMPORT_HEADER
source_group(launcher FILES ${MWINIIMPORT} ${MWINIIMPORT_HEADER})
add_executable(mwiniimport
add_executable(openmw-iniimporter
${MWINIIMPORT}
)
target_link_libraries(mwiniimport
target_link_libraries(openmw-iniimporter
${Boost_LIBRARIES}
components
)
if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage)
target_link_libraries(mwiniimport gcov)
target_link_libraries(openmw-iniimporter gcov)
endif()

@ -59,7 +59,7 @@ int wmain(int argc, wchar_t *wargv[]) {
try
{
bpo::options_description desc("Syntax: mwiniimporter <options> inifile configfile\nAllowed options");
bpo::options_description desc("Syntax: openmw-iniimporter <options> inifile configfile\nAllowed options");
bpo::positional_options_description p_desc;
desc.add_options()
("help,h", "produce help message")

@ -190,29 +190,23 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
bpo::store(valid_opts, variables);
bpo::notify(variables);
bool run = true;
if (variables.count ("help"))
{
std::cout << desc << std::endl;
run = false;
return false;
}
if (variables.count ("version"))
std::cout << "OpenMW version " << OPENMW_VERSION;
std::string rev = OPENMW_VERSION_COMMITHASH;
std::string tag = OPENMW_VERSION_TAGHASH;
if (!rev.empty() && !tag.empty())
{
std::cout << "OpenMW version " << OPENMW_VERSION << std::endl;
std::string rev = OPENMW_VERSION_COMMITHASH;
std::string tag = OPENMW_VERSION_TAGHASH;
if (!rev.empty() && !tag.empty())
{
rev = rev.substr(0, 10);
std::cout << "Revision " << rev << std::endl;
}
run = false;
rev = rev.substr(0, 10);
std::cout << " (revision " << rev << ")";
}
std::cout << std::endl;
if (!run)
if (variables.count ("version"))
return false;
cfgMgr.readConfiguration(variables, desc);

@ -35,6 +35,7 @@ namespace ESM
struct Class;
class ESMReader;
class ESMWriter;
struct CellId;
}
namespace MWWorld

@ -6,6 +6,8 @@
#include <components/settings/settings.hpp>
#include <components/esm/cellid.hpp>
#include "../mwworld/globals.hpp"
#include "../mwworld/ptr.hpp"
@ -33,7 +35,6 @@ namespace ESM
struct Potion;
struct Spell;
struct NPC;
struct CellId;
struct Armor;
struct Weapon;
struct Clothing;
@ -92,6 +93,7 @@ namespace MWBase
{
std::string name;
float x, y; // world position
ESM::CellId dest;
};
World() {}

@ -228,18 +228,7 @@ namespace MWClass
weapon = *weaponslot;
}
// Reduce fatigue
// somewhat of a guess, but using the weapon weight makes sense
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
MWMechanics::DynamicStat<float> fatigue = stats.getFatigue();
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
if (!weapon.isEmpty())
fatigueLoss += weapon.getClass().getWeight(weapon) * stats.getAttackStrength() * fWeaponFatigueMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
stats.setFatigue(fatigue);
MWMechanics::applyFatigueLoss(ptr, weapon);
// TODO: where is the distance defined?
float dist = 200.f;

@ -93,9 +93,6 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Door> *ref =
ptr.get<ESM::Door>();
if (ptr.getCellRef().getTeleport() && !ptr.getCellRef().getDestCell().empty()) // TODO doors that lead to exteriors
return ptr.getCellRef().getDestCell();
return ref->mBase->mName;
}

@ -486,18 +486,7 @@ namespace MWClass
if(!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name())
weapon = MWWorld::Ptr();
// Reduce fatigue
// somewhat of a guess, but using the weapon weight makes sense
const float fFatigueAttackBase = store.find("fFatigueAttackBase")->getFloat();
const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat();
const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat();
MWMechanics::DynamicStat<float> fatigue = getCreatureStats(ptr).getFatigue();
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
if (!weapon.isEmpty())
fatigueLoss += weapon.getClass().getWeight(weapon) * getNpcStats(ptr).getAttackStrength() * fWeaponFatigueMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
getCreatureStats(ptr).setFatigue(fatigue);
MWMechanics::applyFatigueLoss(ptr, weapon);
const float fCombatDistance = store.find("fCombatDistance")->getFloat();
float dist = fCombatDistance * (!weapon.isEmpty() ?

@ -189,9 +189,8 @@ namespace MWClass
{
return std::string("Item Weapon Longblade Up");
}
// Shortblade and thrown weapons
// thrown weapons may not be entirely correct
if (type == 0 || type == 11)
// Shortblade
if (type == 0)
{
return std::string("Item Weapon Shortblade Up");
}
@ -200,8 +199,8 @@ namespace MWClass
{
return std::string("Item Weapon Spear Up");
}
// Blunts and Axes
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
// Blunts, Axes and Thrown weapons
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8 || type == 11)
{
return std::string("Item Weapon Blunt Up");
}
@ -235,9 +234,8 @@ namespace MWClass
{
return std::string("Item Weapon Longblade Down");
}
// Shortblade and thrown weapons
// thrown weapons may not be entirely correct
if (type == 0 || type == 11)
// Shortblade
if (type == 0)
{
return std::string("Item Weapon Shortblade Down");
}
@ -246,8 +244,8 @@ namespace MWClass
{
return std::string("Item Weapon Spear Down");
}
// Blunts and Axes
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
// Blunts, Axes and Thrown weapons
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8 || type == 11)
{
return std::string("Item Weapon Blunt Down");
}

@ -3,6 +3,22 @@
#include "../mwmechanics/npcstats.hpp"
#include "../mwworld/class.hpp"
namespace
{
void modifyProfit(const MWWorld::Ptr& actor, int diff)
{
std::string script = actor.getClass().getScript(actor);
if (!script.empty())
{
int profit = actor.getRefData().getLocals().getIntVar(script, "minimumprofit");
profit += diff;
actor.getRefData().getLocals().setVarByInt(script, "minimumprofit", profit);
}
}
}
namespace MWGui
{
CompanionItemModel::CompanionItemModel(const MWWorld::Ptr &actor)
@ -12,23 +28,25 @@ namespace MWGui
MWWorld::Ptr CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false)
{
if (mActor.getClass().isNpc())
{
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor);
stats.modifyProfit(item.mBase.getClass().getValue(item.mBase) * count);
}
if (hasProfit(mActor))
modifyProfit(mActor, item.mBase.getClass().getValue(item.mBase) * count);
return InventoryItemModel::copyItem(item, count, setNewOwner);
}
void CompanionItemModel::removeItem (const ItemStack& item, size_t count)
{
if (mActor.getClass().isNpc())
{
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor);
stats.modifyProfit(-item.mBase.getClass().getValue(item.mBase) * count);
}
if (hasProfit(mActor))
modifyProfit(mActor, -item.mBase.getClass().getValue(item.mBase) * count);
InventoryItemModel::removeItem(item, count);
}
bool CompanionItemModel::hasProfit(const MWWorld::Ptr &actor)
{
std::string script = actor.getClass().getScript(actor);
if (script.empty())
return false;
return actor.getRefData().getLocals().hasVar(script, "minimumprofit");
}
}

@ -15,6 +15,8 @@ namespace MWGui
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner);
virtual void removeItem (const ItemStack& item, size_t count);
bool hasProfit(const MWWorld::Ptr& actor);
};
}

@ -17,6 +17,21 @@
#include "draganddrop.hpp"
#include "countdialog.hpp"
namespace
{
int getProfit(const MWWorld::Ptr& actor)
{
std::string script = actor.getClass().getScript(actor);
if (!script.empty())
{
return actor.getRefData().getLocals().getIntVar(script, "minimumprofit");
}
return 0;
}
}
namespace MWGui
{
@ -116,13 +131,12 @@ void CompanionWindow::updateEncumbranceBar()
float encumbrance = mPtr.getClass().getEncumbrance(mPtr);
mEncumbranceBar->setValue(encumbrance, capacity);
if (mPtr.getTypeName() != typeid(ESM::NPC).name())
mProfitLabel->setCaption("");
else
if (mModel && mModel->hasProfit(mPtr))
{
MWMechanics::NpcStats& stats = mPtr.getClass().getNpcStats(mPtr);
mProfitLabel->setCaptionWithReplacing("#{sProfitValue} " + MyGUI::utility::toString(stats.getProfit()));
mProfitLabel->setCaptionWithReplacing("#{sProfitValue} " + MyGUI::utility::toString(getProfit(mPtr)));
}
else
mProfitLabel->setCaption("");
}
void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
@ -132,7 +146,7 @@ void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
void CompanionWindow::exit()
{
if (mPtr.getTypeName() == typeid(ESM::NPC).name() && mPtr.getClass().getNpcStats(mPtr).getProfit() < 0)
if (mModel && mModel->hasProfit(mPtr) && getProfit(mPtr) < 0)
{
std::vector<std::string> buttons;
buttons.push_back("#{sCompanionWarningButtonOne}");
@ -148,9 +162,6 @@ void CompanionWindow::onMessageBoxButtonClicked(int button)
{
if (button == 0)
{
mPtr.getRefData().getLocals().setVarByInt(mPtr.getClass().getScript(mPtr),
"minimumprofit", mPtr.getClass().getNpcStats(mPtr).getProfit());
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
// Important for Calvus' contract script to work properly
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);

@ -182,6 +182,10 @@ namespace MWGui
HUD::~HUD()
{
mMainWidget->eventMouseLostFocus.clear();
mMainWidget->eventMouseMove.clear();
mMainWidget->eventMouseButtonClick.clear();
delete mSpellIcons;
}

@ -12,6 +12,8 @@
#include <MyGUI_RotatingSkin.h>
#include <MyGUI_FactoryManager.h>
#include <components/esm/globalmap.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
@ -22,10 +24,9 @@
#include "../mwrender/globalmap.hpp"
#include <components/esm/globalmap.hpp>
#include "widgets.hpp"
#include "confirmationdialog.hpp"
#include "tooltips.hpp"
namespace
{
@ -226,7 +227,7 @@ namespace MWGui
redraw();
}
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerPosition& markerPos)
MyGUI::IntPoint LocalMapBase::getMarkerPosition(float worldX, float worldY, MarkerUserData& markerPos)
{
MyGUI::IntPoint widgetPos;
// normalized cell coordinates
@ -295,7 +296,7 @@ namespace MWGui
continue;
}
MarkerPosition markerPos;
MarkerUserData markerPos;
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
@ -380,8 +381,17 @@ namespace MWGui
{
MWBase::World::DoorMarker marker = *it;
MarkerPosition markerPos;
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, markerPos);
std::vector<std::string> destNotes;
for (std::vector<ESM::CustomMarker>::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it)
{
if (it->mCell == marker.dest)
destNotes.push_back(it->mNote);
}
MarkerUserData data;
data.notes = destNotes;
data.caption = marker.name;
MyGUI::IntPoint widgetPos = getMarkerPosition(marker.x, marker.y, data);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4,
8, 8);
@ -392,12 +402,10 @@ namespace MWGui
markerWidget->setHoverColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal_over}")));
markerWidget->setDepth(Local_MarkerLayer);
markerWidget->setNeedMouseFocus(true);
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", marker.name);
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
markerWidget->setUserString("ToolTipType", "MapMarker");
markerWidget->setUserData(data);
doorMarkerCreated(markerWidget);
mDoorMarkerWidgets.push_back(markerWidget);
@ -480,7 +488,7 @@ namespace MWGui
for (std::vector<MWWorld::Ptr>::iterator it = markers.begin(); it != markers.end(); ++it)
{
const ESM::Position& worldPos = it->getRefData().getPosition();
MarkerPosition markerPos;
MarkerUserData markerPos;
MyGUI::IntPoint widgetPos = getMarkerPosition(worldPos.pos[0], worldPos.pos[1], markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4,
@ -490,9 +498,8 @@ namespace MWGui
widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setImageTexture(markerTexture);
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
markerWidget->setColour(markerColour);
markerWidget->setNeedMouseFocus(false);
mMagicMarkerWidgets.push_back(markerWidget);
}
}
@ -526,7 +533,7 @@ namespace MWGui
if (markedCell && markedCell->isExterior() == !mInterior
&& (!mInterior || Misc::StringUtils::ciEqual(markedCell->getCell()->mName, mPrefix)))
{
MarkerPosition markerPos;
MarkerUserData markerPos;
MyGUI::IntPoint widgetPos = getMarkerPosition(markedPosition.pos[0], markedPosition.pos[1], markerPos);
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4,
@ -535,8 +542,7 @@ namespace MWGui
widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
markerWidget->setNeedMouseFocus(false);
mMagicMarkerWidgets.push_back(markerWidget);
}

@ -65,13 +65,15 @@ namespace MWGui
bool toggleFogOfWar();
struct MarkerPosition
struct MarkerUserData
{
bool interior;
int cellX;
int cellY;
float nX;
float nY;
std::vector<std::string> notes;
std::string caption;
};
protected:
@ -100,7 +102,7 @@ namespace MWGui
void applyFogOfWar();
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerPosition& markerPos);
MyGUI::IntPoint getMarkerPosition (float worldX, float worldY, MarkerUserData& markerPos);
virtual void notifyPlayerUpdate() {}
virtual void notifyMapChanged() {}

@ -163,15 +163,19 @@ namespace MWGui
// special handling for markers on the local map: the tooltip should only be visible
// if the marker is not hidden due to the fog of war.
if (focus->getUserString ("IsMarker") == "true")
if (type == "MapMarker")
{
LocalMapBase::MarkerPosition pos = *focus->getUserData<LocalMapBase::MarkerPosition>();
LocalMapBase::MarkerUserData data = *focus->getUserData<LocalMapBase::MarkerUserData>();
if (!MWBase::Environment::get().getWorld ()->isPositionExplored (pos.nX, pos.nY, pos.cellX, pos.cellY, pos.interior))
if (!MWBase::Environment::get().getWorld ()->isPositionExplored (data.nX, data.nY, data.cellX, data.cellY, data.interior))
return;
}
if (type == "ItemPtr")
ToolTipInfo info;
info.text = data.caption;
info.notes = data.notes;
tooltipSize = createToolTip(info);
}
else if (type == "ItemPtr")
{
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
tooltipSize = getToolTipViaPtr(false);
@ -403,16 +407,33 @@ namespace MWGui
MyGUI::IntSize totalSize = MyGUI::IntSize( std::min(std::max(textSize.width,captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),maximumWidth),
((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
for (std::vector<std::string>::const_iterator it = info.notes.begin(); it != info.notes.end(); ++it)
{
MyGUI::ImageBox* icon = mDynamicToolTipBox->createWidget<MyGUI::ImageBox>("MarkerButton",
MyGUI::IntCoord(padding.left, totalSize.height+padding.top, 8, 8), MyGUI::Align::Default);
icon->setColour(MyGUI::Colour(1.0,0.3,0.3));
MyGUI::EditBox* edit = mDynamicToolTipBox->createWidget<MyGUI::EditBox>("SandText",
MyGUI::IntCoord(padding.left+8+4, totalSize.height+padding.top, 300-padding.left-8-4, 300-totalSize.height),
MyGUI::Align::Default);
edit->setEditMultiLine(true);
edit->setEditWordWrap(true);
edit->setCaption(*it);
edit->setSize(edit->getWidth(), edit->getTextSize().height);
icon->setPosition(icon->getLeft(),(edit->getTop()+edit->getBottom())/2-icon->getHeight()/2);
totalSize.height += std::max(edit->getHeight(), icon->getHeight());
totalSize.width = std::max(totalSize.width, edit->getWidth()+8+4);
}
if (!info.effects.empty())
{
MyGUI::Widget* effectArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
MyGUI::IntCoord(padding.left, totalSize.height, 300-padding.left, 300-totalSize.height),
MyGUI::Align::Stretch, "ToolTipEffectArea");
MyGUI::Align::Stretch);
MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
Widgets::MWEffectListPtr effectsWidget = effectArea->createWidget<Widgets::MWEffectList>
("MW_StatName", coord, MyGUI::Align::Default, "ToolTipEffectsWidget");
("MW_StatName", coord, MyGUI::Align::Default);
effectsWidget->setEffectList(info.effects);
std::vector<MyGUI::Widget*> effectItems;
@ -426,12 +447,12 @@ namespace MWGui
assert(enchant);
MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
MyGUI::IntCoord(padding.left, totalSize.height, 300-padding.left, 300-totalSize.height),
MyGUI::Align::Stretch, "ToolTipEnchantArea");
MyGUI::Align::Stretch);
MyGUI::IntCoord coord(0, 6, totalSize.width, 24);
Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget<Widgets::MWEffectList>
("MW_StatName", coord, MyGUI::Align::Default, "ToolTipEnchantWidget");
("MW_StatName", coord, MyGUI::Align::Default);
enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->mEffects));
std::vector<MyGUI::Widget*> enchantEffectItems;
@ -470,7 +491,7 @@ namespace MWGui
chargeCoord = MyGUI::IntCoord((totalSize.width - chargeAndTextWidth)/2 + chargeTextWidth, coord.top+6, chargeWidth, 18);
}
Widgets::MWDynamicStatPtr chargeWidget = enchantArea->createWidget<Widgets::MWDynamicStat>
("MW_ChargeBar", chargeCoord, MyGUI::Align::Default, "ToolTipEnchantCharge");
("MW_ChargeBar", chargeCoord, MyGUI::Align::Default);
chargeWidget->setValue(charge, maxCharge);
totalSize.height += 24;
}
@ -505,7 +526,7 @@ namespace MWGui
{
MyGUI::ImageBox* imageWidget = mDynamicToolTipBox->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord((totalSize.width - captionSize.width - imageCaptionHPadding)/2, 0, imageSize, imageSize),
MyGUI::Align::Left | MyGUI::Align::Top, "ToolTipImage");
MyGUI::Align::Left | MyGUI::Align::Top);
imageWidget->setImageTexture(realImage);
imageWidget->setPosition (imageWidget->getPosition() + padding);
}

@ -38,6 +38,9 @@ namespace MWGui
// effects (for potions, ingredients)
Widgets::SpellEffectList effects;
// local map notes
std::vector<std::string> notes;
bool isPotion; // potions do not show target in the tooltip
bool wordWrap;
};

@ -352,6 +352,12 @@ namespace MWGui
WindowManager::~WindowManager()
{
MyGUI::LanguageManager::getInstance().eventRequestTag.clear();
MyGUI::PointerManager::getInstance().eventChangeMousePointer.clear();
MyGUI::InputManager::getInstance().eventChangeKeyFocus.clear();
MyGUI::ClipboardManager::getInstance().eventClipboardChanged.clear();
MyGUI::ClipboardManager::getInstance().eventClipboardRequested.clear();
delete mConsole;
delete mMessageBoxManager;
delete mHud;
@ -385,7 +391,6 @@ namespace MWGui
delete mMerchantRepair;
delete mRepair;
delete mSoulgemDialog;
delete mCursorManager;
delete mRecharge;
delete mCompanionWindow;
delete mHitFader;
@ -394,6 +399,8 @@ namespace MWGui
delete mBlindnessFader;
delete mDebugWindow;
delete mCursorManager;
cleanupGarbage();
delete mGuiManager;

@ -12,7 +12,7 @@ namespace MWGui
ExposedWindow* window = mMainWidget->castType<ExposedWindow>();
mPinButton = window->getSkinWidget ("Button");
mPinButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonClicked);
mPinButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonPressed);
MyGUI::Button* button = NULL;
MyGUI::VectorWidgetPtr widgets = window->getSkinWidgetsByName("Action");
@ -26,8 +26,11 @@ namespace MWGui
button->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &WindowPinnableBase::onDoubleClick);
}
void WindowPinnableBase::onPinButtonClicked(MyGUI::Widget* _sender)
void WindowPinnableBase::onPinButtonPressed(MyGUI::Widget* _sender, int left, int top, MyGUI::MouseButton id)
{
if (id != MyGUI::MouseButton::Left)
return;
mPinned = !mPinned;
if (mPinned)
@ -46,7 +49,7 @@ namespace MWGui
void WindowPinnableBase::setPinned(bool pinned)
{
if (pinned != mPinned)
onPinButtonClicked(mPinButton);
onPinButtonPressed(mPinButton, 0, 0, MyGUI::MouseButton::Left);
}
void WindowPinnableBase::setPinButtonVisible(bool visible)

@ -16,7 +16,7 @@ namespace MWGui
void setPinButtonVisible(bool visible);
private:
void onPinButtonClicked(MyGUI::Widget* _sender);
void onPinButtonPressed(MyGUI::Widget* _sender, int left, int top, MyGUI::MouseButton id);
void onDoubleClick(MyGUI::Widget* _sender);
protected:

@ -1126,7 +1126,7 @@ bool CharacterController::updateWeaponState()
attackStrength = std::min(1.f, 0.1f + std::rand() / float(RAND_MAX));
}
if(mAttackType != "shoot")
if(mWeaponType != WeapType_Crossbow && mWeaponType != WeapType_BowAndArrow)
{
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();

@ -371,6 +371,23 @@ namespace MWMechanics
sndMgr->playSound3D(victim, "Hand To Hand Hit", 1.0f, 1.0f);
}
void applyFatigueLoss(const MWWorld::Ptr &attacker, const MWWorld::Ptr &weapon)
{
// somewhat of a guess, but using the weapon weight makes sense
const MWWorld::Store<ESM::GameSetting>& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
const float fFatigueAttackBase = store.find("fFatigueAttackBase")->getFloat();
const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat();
const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat();
CreatureStats& stats = attacker.getClass().getCreatureStats(attacker);
MWMechanics::DynamicStat<float> fatigue = stats.getFatigue();
const float normalizedEncumbrance = attacker.getClass().getNormalizedEncumbrance(attacker);
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
if (!weapon.isEmpty())
fatigueLoss += weapon.getClass().getWeight(weapon) * stats.getAttackStrength() * fWeaponFatigueMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
stats.setFatigue(fatigue);
}
bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim)
{
const MWWorld::Class& attackerClass = attacker.getClass();

@ -34,6 +34,9 @@ void adjustWeaponDamage (float& damage, const MWWorld::Ptr& weapon);
void getHandToHandDamage (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, float& damage, bool& healthdmg);
/// Apply the fatigue loss incurred by attacking with the given weapon (weapon may be empty = hand-to-hand)
void applyFatigueLoss(const MWWorld::Ptr& attacker, const MWWorld::Ptr& weapon);
/// Can attacker operate in victim's environment?
/// e.g. If attacker is a fish, is victim in water? Or, if attacker can't swim, is victim on land?
bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim);

@ -495,7 +495,10 @@ namespace MWMechanics
state.mDead = mDead;
state.mDied = mDied;
state.mMurdered = mMurdered;
state.mFriendlyHits = mFriendlyHits;
// The vanilla engine does not store friendly hits in the save file. Since there's no other mechanism
// that ever resets the friendly hits (at least not to my knowledge) this should be regarded a feature
// rather than a bug.
//state.mFriendlyHits = mFriendlyHits;
state.mTalkedTo = mTalkedTo;
state.mAlarmed = mAlarmed;
state.mAttacked = mAttacked;
@ -544,7 +547,6 @@ namespace MWMechanics
mDead = state.mDead;
mDied = state.mDied;
mMurdered = state.mMurdered;
mFriendlyHits = state.mFriendlyHits;
mTalkedTo = state.mTalkedTo;
mAlarmed = state.mAlarmed;
mAttacked = state.mAttacked;

@ -31,7 +31,6 @@ MWMechanics::NpcStats::NpcStats()
, mReputation(0)
, mCrimeId(-1)
, mWerewolfKills (0)
, mProfit(0)
, mTimeToStartDrowning(20.0)
{
mSkillIncreases.resize (ESM::Attribute::Length, 0);
@ -448,16 +447,6 @@ void MWMechanics::NpcStats::addWerewolfKill()
++mWerewolfKills;
}
int MWMechanics::NpcStats::getProfit() const
{
return mProfit;
}
void MWMechanics::NpcStats::modifyProfit(int diff)
{
mProfit += diff;
}
float MWMechanics::NpcStats::getTimeToStartDrowning() const
{
return mTimeToStartDrowning;
@ -501,7 +490,6 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
state.mReputation = mReputation;
state.mWerewolfKills = mWerewolfKills;
state.mProfit = mProfit;
state.mLevelProgress = mLevelProgress;
for (int i=0; i<ESM::Attribute::Length; ++i)
@ -548,7 +536,6 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
mBounty = state.mBounty;
mReputation = state.mReputation;
mWerewolfKills = state.mWerewolfKills;
mProfit = state.mProfit;
mLevelProgress = state.mLevelProgress;
for (int i=0; i<ESM::Attribute::Length; ++i)

@ -28,8 +28,6 @@ namespace MWMechanics
int mReputation;
int mCrimeId;
int mProfit;
// ----- used by the player only, maybe should be moved at some point -------
int mBounty;
int mWerewolfKills;
@ -49,10 +47,6 @@ namespace MWMechanics
NpcStats();
/// for mercenary companions. starts out as 0, and changes when items are added or removed through the UI.
int getProfit() const;
void modifyProfit(int diff);
int getBaseDisposition() const;
void setBaseDisposition(int disposition);

@ -1272,8 +1272,7 @@ void Animation::addEffect(const std::string &model, int effectId, bool loop, con
else
params.mObjects = NifOgre::Loader::createObjects(mSkelBase, bonename, "", mInsert, model);
// TODO: turn off shadow casting
setRenderProperties(params.mObjects, RV_Misc,
setRenderProperties(params.mObjects, RV_Effects,
RQG_Main, RQG_Alpha, 0.f, false, NULL);
params.mLoop = loop;

@ -25,8 +25,7 @@ void EffectManager::addEffect(const std::string &model, std::string textureOverr
NifOgre::ObjectScenePtr scene = NifOgre::Loader::createObjects(sceneNode, model);
// TODO: turn off shadow casting
MWRender::Animation::setRenderProperties(scene, RV_Misc,
MWRender::Animation::setRenderProperties(scene, RV_Effects,
RQG_Main, RQG_Alpha, 0.f, false, NULL);
for(size_t i = 0;i < scene->mControllers.size();i++)

@ -33,7 +33,7 @@ namespace MWRender
Ogre::Viewport* vp = mRenderTarget->addViewport(mCamera);
vp->setOverlaysEnabled(false);
vp->setShadowsEnabled(false);
vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky + RV_FirstPerson);
vp->setVisibilityMask(RV_Refraction);
vp->setMaterialScheme("water_refraction");
vp->setBackgroundColour (Ogre::ColourValue(0.090195, 0.115685, 0.12745));
mRenderTarget->setAutoUpdated(true);

@ -30,39 +30,44 @@ enum RenderQueueGroups
enum VisibilityFlags
{
// Terrain
RV_Terrain = 1,
RV_Terrain = (1<<0),
// Statics (e.g. trees, houses)
RV_Statics = 2,
RV_Statics = (1<<1),
// Small statics
RV_StaticsSmall = 4,
RV_StaticsSmall = (1<<2),
// Water
RV_Water = 8,
RV_Water = (1<<3),
// Actors (npcs, creatures)
RV_Actors = 16,
RV_Actors = (1<<4),
// Misc objects (containers, dynamic objects)
RV_Misc = 32,
RV_Misc = (1<<5),
RV_Sky = 64,
// VFX, don't appear on map and don't cast shadows
RV_Effects = (1<<6),
RV_Sky = (1<<7),
// not visible in reflection
RV_NoReflection = 128,
RV_NoReflection = (1<<8),
RV_OcclusionQuery = 256,
RV_OcclusionQuery = (1<<9),
RV_Debug = 512,
RV_Debug = (1<<10),
// overlays, we only want these on the main render target
RV_Overlay = 1024,
RV_Overlay = (1<<11),
// First person meshes do not cast shadows
RV_FirstPerson = 2048,
RV_FirstPerson = (1<<12),
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water,
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water
RV_Refraction = RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Effects + RV_Sky + RV_FirstPerson
};
}

@ -409,6 +409,7 @@ void RenderingManager::update (float duration, bool paused)
mSkyManager->setGlare(mOcclusionQuery->getSunVisibility());
mWater->changeCell(player.getCell()->getCell());
mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam));

@ -187,6 +187,8 @@ Moon::Moon( const String& textureName,
{
setVisibility(1.0);
mMaterial->setProperty("alphatexture", sh::makeProperty(new sh::StringValue(textureName + "_alpha")));
mPhase = Moon::Phase_Full;
}
@ -215,9 +217,15 @@ void Moon::setPhase(const Moon::Phase& phase)
textureName += ".dds";
if (mType == Moon::Type_Secunda)
{
sh::Factory::getInstance ().setTextureAlias ("secunda_texture", textureName);
sh::Factory::getInstance ().setTextureAlias ("secunda_texture_alpha", "textures\\tx_mooncircle_full_s.dds");
}
else
{
sh::Factory::getInstance ().setTextureAlias ("masser_texture", textureName);
sh::Factory::getInstance ().setTextureAlias ("masser_texture_alpha", "textures\\tx_mooncircle_full_m.dds");
}
mPhase = phase;
}

@ -210,10 +210,10 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend) :
mWaterPlane = Plane(Vector3::UNIT_Z, 0);
int waterScale = 300;
int waterScale = 30;
MeshManager::getSingleton().createPlane("water", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane,
CELL_SIZE*5*waterScale, CELL_SIZE*5*waterScale, 10, 10, true, 1, 3*waterScale,3*waterScale, Vector3::UNIT_Y);
CELL_SIZE*5*waterScale, CELL_SIZE*5*waterScale, 40, 40, true, 1, 3*waterScale,3*waterScale, Vector3::UNIT_Y);
mWater = mSceneMgr->createEntity("water");
mWater->setVisibilityFlags(RV_Water);
@ -305,11 +305,7 @@ Water::~Water()
void Water::changeCell(const ESM::Cell* cell)
{
mTop = cell->mWater;
setHeight(mTop);
if(!(cell->mData.mFlags & cell->Interior))
if(cell->isExterior())
mWaterNode->setPosition(getSceneNodeCoordinates(cell->mData.mX, cell->mData.mY));
}
@ -424,6 +420,7 @@ void Water::applyVisibilityMask()
mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water")
+ (RV_Statics + RV_StaticsSmall + RV_Misc) * Settings::Manager::getBool("reflect statics", "Water")
+ RV_Actors * Settings::Manager::getBool("reflect actors", "Water")
+ RV_Effects
+ RV_Sky;
if (mReflection)

@ -7,12 +7,14 @@
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/combat.hpp"
#include "animation.hpp"
@ -44,9 +46,22 @@ void WeaponAnimation::attachArrow(MWWorld::Ptr actor)
{
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
MWWorld::ContainerStoreIterator weaponSlot = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weaponSlot != inv.end() && weaponSlot->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanThrown)
if (weaponSlot == inv.end())
return;
if (weaponSlot->getTypeName() != typeid(ESM::Weapon).name())
return;
int weaponType = weaponSlot->get<ESM::Weapon>()->mBase->mData.mType;
if (weaponType == ESM::Weapon::MarksmanThrown)
{
std::string soundid = weaponSlot->getClass().getUpSoundId(*weaponSlot);
if(!soundid.empty())
{
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
sndMgr->playSound3D(actor, soundid, 1.0f, 1.0f);
}
showWeapon(true);
else
}
else if (weaponType == ESM::Weapon::MarksmanBow || weaponType == ESM::Weapon::MarksmanCrossbow)
{
NifOgre::ObjectScenePtr weapon = getWeapon();
if (!weapon.get())
@ -72,6 +87,8 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor)
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weapon == inv.end())
return;
if (weapon->getTypeName() != typeid(ESM::Weapon).name())
return;
// The orientation of the launched projectile. Always the same as the actor orientation, even if the ArrowBone's orientation dictates otherwise.
Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
@ -80,19 +97,7 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor)
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
// Reduce fatigue
// somewhat of a guess, but using the weapon weight makes sense
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
MWMechanics::CreatureStats& attackerStats = actor.getClass().getCreatureStats(actor);
MWMechanics::DynamicStat<float> fatigue = attackerStats.getFatigue();
const float normalizedEncumbrance = actor.getClass().getNormalizedEncumbrance(actor);
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
if (!weapon->isEmpty())
fatigueLoss += weapon->getClass().getWeight(*weapon) * attackerStats.getAttackStrength() * fWeaponFatigueMult;
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
attackerStats.setFatigue(fatigue);
MWMechanics::applyFatigueLoss(actor, *weapon);
if (weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanThrown)
{

@ -35,8 +35,11 @@ namespace MWRender
WeaponAnimation() : mPitchFactor(0) {}
virtual ~WeaponAnimation() {}
virtual void attachArrow(MWWorld::Ptr actor);
virtual void releaseArrow(MWWorld::Ptr actor);
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
void attachArrow(MWWorld::Ptr actor);
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
void releaseArrow(MWWorld::Ptr actor);
protected:
NifOgre::ObjectScenePtr mAmmunition;

@ -32,6 +32,21 @@ namespace MWScript
return (mShorts.empty() && mLongs.empty() && mFloats.empty());
}
bool Locals::hasVar(const std::string &script, const std::string &var)
{
try
{
const Compiler::Locals& locals =
MWBase::Environment::get().getScriptManager()->getLocals(script);
int index = locals.getIndex(var);
return (index != -1);
}
catch (const Compiler::SourceException&)
{
return false;
}
}
int Locals::getIntVar(const std::string &script, const std::string &var)
{
const Compiler::Locals& locals = MWBase::Environment::get().getScriptManager()->getLocals(script);

@ -24,11 +24,15 @@ namespace MWScript
bool isEmpty() const;
void configure (const ESM::Script& script);
/// @note var needs to be in lowercase
bool setVarByInt(const std::string& script, const std::string& var, int val);
int getIntVar (const std::string& script, const std::string& var);
///< if var does not exist, returns 0
bool hasVar(const std::string& script, const std::string& var);
/// if var does not exist, returns 0
/// @note var needs to be in lowercase
int getIntVar (const std::string& script, const std::string& var);
void write (ESM::Locals& locals, const std::string& script) const;

@ -518,42 +518,41 @@ namespace MWScript
if (count<0)
throw std::runtime_error ("count must be non-negative");
// no-op
if (count == 0)
return;
ESM::Position ipos = actor.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;
for (int i=0; i<count; ++i)
{
ESM::Position ipos = actor.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;
if (actor.getClass().isActor())
{
// TODO: should this depend on the 'direction' parameter?
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
}
else
{
ipos.rot[0] = actor.getRefData().getPosition().rot[0];
ipos.rot[1] = actor.getRefData().getPosition().rot[1];
ipos.rot[2] = actor.getRefData().getPosition().rot[2];
}
// create item
MWWorld::CellStore* store = actor.getCell();
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1);
ref.getPtr().getCellRef().setPosition(ipos);
if (actor.getClass().isActor())
{
// TODO: should this depend on the 'direction' parameter?
ipos.rot[0] = 0;
ipos.rot[1] = 0;
ipos.rot[2] = 0;
}
else
{
ipos.rot[0] = actor.getRefData().getPosition().rot[0];
ipos.rot[1] = actor.getRefData().getPosition().rot[1];
ipos.rot[2] = actor.getRefData().getPosition().rot[2];
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos);
}
// create item
MWWorld::CellStore* store = actor.getCell();
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, count);
ref.getPtr().getCellRef().setPosition(ipos);
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos);
}
};

@ -25,14 +25,28 @@ void FFmpeg_Decoder::fail(const std::string &msg)
int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size)
{
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
return stream->read(buf, buf_size);
try
{
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
return stream->read(buf, buf_size);
}
catch (std::exception& e)
{
return 0;
}
}
int FFmpeg_Decoder::writePacket(void *user_data, uint8_t *buf, int buf_size)
{
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
return stream->write(buf, buf_size);
try
{
Ogre::DataStreamPtr stream = static_cast<FFmpeg_Decoder*>(user_data)->mDataStream;
return stream->write(buf, buf_size);
}
catch (std::exception& e)
{
return 0;
}
}
int64_t FFmpeg_Decoder::seek(void *user_data, int64_t offset, int whence)

@ -303,26 +303,15 @@ namespace MWWorld
Ogre::Vector3 halfExtents = physicActor->getHalfExtents();
position.z += halfExtents.z;
waterlevel -= halfExtents.z * 0.5;
/*
* A 3/4 submerged example
*
* +---+
* | |
* | | <- (original waterlevel)
* | |
* | | <- position <- waterlevel
* | |
* | |
* | |
* +---+ <- (original position)
*/
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fSwimHeightScale")->getFloat();
float swimlevel = waterlevel + halfExtents.z - (halfExtents.z * 2 * fSwimHeightScale);
OEngine::Physic::ActorTracer tracer;
Ogre::Vector3 inertia = physicActor->getInertialForce();
Ogre::Vector3 velocity;
if(position.z < waterlevel || isFlying)
if(position.z < swimlevel || isFlying)
{
velocity = (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z)*
Ogre::Quaternion(Ogre::Radian(refpos.rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)) * movement;
@ -364,12 +353,10 @@ namespace MWWorld
Ogre::Vector3 nextpos = newPosition + velocity * remainingTime;
// If not able to fly, don't allow to swim up into the air
// TODO: this if condition may not work for large creatures or situations
// where the creature gets above the waterline for some reason
if(newPosition.z < waterlevel && // started 3/4 under water
if(newPosition.z < swimlevel &&
!isFlying && // can't fly
nextpos.z > waterlevel && // but about to go above water
newPosition.z <= waterlevel)
nextpos.z > swimlevel && // but about to go above water
newPosition.z <= swimlevel)
{
const Ogre::Vector3 down(0,0,-1);
Ogre::Real movelen = velocity.normalise();
@ -423,7 +410,7 @@ namespace MWWorld
{
// don't let pure water creatures move out of water after stepMove
if (ptr.getClass().isPureWaterCreature(ptr)
&& newPosition.z > (waterlevel - halfExtents.z * 0.5))
&& newPosition.z + halfExtents.z > waterlevel)
newPosition = oldPosition;
}
else
@ -444,13 +431,13 @@ namespace MWWorld
// Do not allow sliding upward if there is gravity. Stepping will have taken
// care of that.
if(!(newPosition.z < waterlevel || isFlying))
if(!(newPosition.z < swimlevel || isFlying))
velocity.z = std::min(velocity.z, 0.0f);
}
}
bool isOnGround = false;
if (!(inertia.z > 0.f) && !(newPosition.z < waterlevel))
if (!(inertia.z > 0.f) && !(newPosition.z < swimlevel))
{
Ogre::Vector3 from = newPosition;
Ogre::Vector3 to = newPosition - (physicActor->getOnGround() ?
@ -494,7 +481,7 @@ namespace MWWorld
}
}
if(isOnGround || newPosition.z < waterlevel || isFlying)
if(isOnGround || newPosition.z < swimlevel || isFlying)
physicActor->setInertialForce(Ogre::Vector3(0.0f));
else
{

@ -44,7 +44,7 @@ namespace MWWorld
state.mObject->mControllers[i].setSource(Ogre::SharedPtr<MWRender::EffectAnimationTime> (new MWRender::EffectAnimationTime()));
}
MWRender::Animation::setRenderProperties(state.mObject, MWRender::RV_Misc,
MWRender::Animation::setRenderProperties(state.mObject, MWRender::RV_Effects,
MWRender::RQG_Main, MWRender::RQG_Alpha, 0.f, false, NULL);
}

@ -544,9 +544,16 @@ namespace MWWorld
void Scene::addObjectToScene (const Ptr& ptr)
{
addObject(ptr, *mPhysics, mRendering);
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale());
try
{
addObject(ptr, *mPhysics, mRendering);
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale());
}
catch (std::exception& e)
{
std::cerr << "error during rendering: " << e.what() << std::endl;
}
}
void Scene::removeObjectFromScene (const Ptr& ptr)

@ -360,6 +360,8 @@ namespace MWWorld
std::pair<typename Static::iterator, bool> inserted = mStatic.insert(std::make_pair(scpt.mId, scpt));
if (inserted.second)
mShared.push_back(&inserted.first->second);
else
inserted.first->second = scpt;
}
template <>
@ -371,6 +373,8 @@ namespace MWWorld
std::pair<typename Static::iterator, bool> inserted = mStatic.insert(std::make_pair(s.mId, s));
if (inserted.second)
mShared.push_back(&inserted.first->second);
else
inserted.first->second = s;
}
template <>

@ -187,6 +187,8 @@ namespace MWWorld
mStore.setUp();
mStore.movePlayerRecord();
mSwimHeightScale = mStore.get<ESM::GameSetting>().find("fSwimHeightScale")->getFloat();
mGlobalVariables.fill (mStore);
mWorldScene = new Scene(*mRendering, mPhysics);
@ -1735,6 +1737,23 @@ namespace MWWorld
World::DoorMarker newMarker;
newMarker.name = MWClass::Door::getDestination(ref);
ESM::CellId cellid;
if (!ref.mRef.getDestCell().empty())
{
cellid.mWorldspace = ref.mRef.getDestCell();
cellid.mPaged = false;
}
else
{
cellid.mPaged = true;
MWBase::Environment::get().getWorld()->positionToIndex(
ref.mRef.getDoorDest().pos[0],
ref.mRef.getDoorDest().pos[1],
cellid.mIndex.mX,
cellid.mIndex.mY);
}
newMarker.dest = cellid;
ESM::Position pos = ref.mData.getPosition ();
newMarker.x = pos.pos[0];
@ -1935,8 +1954,7 @@ namespace MWWorld
mRendering->getTriangleBatchCount(triangles, batches);
}
bool
World::isFlying(const MWWorld::Ptr &ptr) const
bool World::isFlying(const MWWorld::Ptr &ptr) const
{
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
bool isParalyzed = (stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0);
@ -1961,8 +1979,7 @@ namespace MWWorld
return false;
}
bool
World::isSlowFalling(const MWWorld::Ptr &ptr) const
bool World::isSlowFalling(const MWWorld::Ptr &ptr) const
{
if(!ptr.getClass().isActor())
return false;
@ -1976,27 +1993,21 @@ namespace MWWorld
bool World::isSubmerged(const MWWorld::Ptr &object) const
{
const float neckDeep = 1.85f;
return isUnderwater(object, neckDeep);
return isUnderwater(object, 1.0/mSwimHeightScale);
}
bool
World::isSwimming(const MWWorld::Ptr &object) const
bool World::isSwimming(const MWWorld::Ptr &object) const
{
/// \todo add check ifActor() - only actors can swim
/// \fixme 3/4ths submerged?
return isUnderwater(object, 1.5f);
return isUnderwater(object, mSwimHeightScale);
}
bool
World::isWading(const MWWorld::Ptr &object) const
bool World::isWading(const MWWorld::Ptr &object) const
{
const float kneeDeep = 0.5f;
const float kneeDeep = 0.25f;
return isUnderwater(object, kneeDeep);
}
bool
World::isUnderwater(const MWWorld::Ptr &object, const float heightRatio) const
bool World::isUnderwater(const MWWorld::Ptr &object, const float heightRatio) const
{
const float *fpos = object.getRefData().getPosition().pos;
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
@ -2004,14 +2015,13 @@ namespace MWWorld
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(object.getRefData().getHandle());
if (actor)
{
pos.z += heightRatio*actor->getHalfExtents().z;
pos.z += heightRatio*2*actor->getHalfExtents().z;
}
return isUnderwater(object.getCell(), pos);
}
bool
World::isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const
bool World::isUnderwater(const MWWorld::CellStore* cell, const Ogre::Vector3 &pos) const
{
if (!(cell->getCell()->mData.mFlags & ESM::Cell::HasWater)) {
return false;
@ -2606,7 +2616,7 @@ namespace MWWorld
// Check mana
MWMechanics::DynamicStat<float> magicka = stats.getMagicka();
if (magicka.getCurrent() < spell->mData.mCost)
if (magicka.getCurrent() < spell->mData.mCost && !(isPlayer && getGodModeState()))
{
message = "#{sMagicInsufficientSP}";
fail = true;

@ -139,6 +139,7 @@ namespace MWWorld
void loadContentFiles(const Files::Collections& fileCollections,
const std::vector<std::string>& content, ContentLoader& contentLoader);
float mSwimHeightScale;
bool isUnderwater(const MWWorld::Ptr &object, const float heightRatio) const;
///< helper function for implementing isSwimming(), isSubmerged(), isWading()

@ -281,7 +281,7 @@ void Wizard::MainWizard::runSettingsImporter()
arguments.append(QLatin1String("--cfg"));
arguments.append(userPath + QLatin1String("openmw.cfg"));
if (!mImporterInvoker->startProcess(QLatin1String("mwiniimport"), arguments, false))
if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false))
return qApp->quit();
}

@ -153,7 +153,7 @@ void ESM::CellRef::blank()
mLockLevel = 0;
mKey.clear();
mTrap.clear();
mReferenceBlocked = 0;
mReferenceBlocked = -1;
mTeleport = false;
for (int i=0; i<3; ++i)

@ -24,8 +24,8 @@ void ESM::CreatureStats::load (ESMReader &esm)
mMurdered = false;
esm.getHNOT (mMurdered, "MURD");
mFriendlyHits = 0;
esm.getHNOT (mFriendlyHits, "FRHT");
if (esm.isNextSub("FRHT"))
esm.skipHSub(); // Friendly hits, no longer used
mTalkedTo = false;
esm.getHNOT (mTalkedTo, "TALK");
@ -140,9 +140,6 @@ void ESM::CreatureStats::save (ESMWriter &esm) const
if (mMurdered)
esm.writeHNT ("MURD", mMurdered);
if (mFriendlyHits)
esm.writeHNT ("FRHT", mFriendlyHits);
if (mTalkedTo)
esm.writeHNT ("TALK", mTalkedTo);
@ -235,7 +232,6 @@ void ESM::CreatureStats::blank()
mDead = false;
mDied = false;
mMurdered = false;
mFriendlyHits = 0;
mTalkedTo = false;
mAlarmed = false;
mAttacked = false;

@ -42,7 +42,6 @@ namespace ESM
bool mDead;
bool mDied;
bool mMurdered;
int mFriendlyHits;
bool mTalkedTo;
bool mAlarmed;
bool mAttacked;

@ -123,7 +123,7 @@ std::string ESMReader::getHString()
// Skip the following zero byte
mCtx.leftRec--;
char c;
mEsm->read(&c, 1);
getExact(&c, 1);
return "";
}
@ -186,7 +186,7 @@ void ESMReader::getSubName()
}
// reading the subrecord data anyway.
mEsm->read(mCtx.subName.name, 4);
getExact(mCtx.subName.name, 4);
mCtx.leftRec -= 4;
}
@ -194,7 +194,7 @@ bool ESMReader::isEmptyOrGetName()
{
if (mCtx.leftRec)
{
mEsm->read(mCtx.subName.name, 4);
getExact(mCtx.subName.name, 4);
mCtx.leftRec -= 4;
return false;
}
@ -294,9 +294,16 @@ void ESMReader::getRecHeader(uint32_t &flags)
void ESMReader::getExact(void*x, int size)
{
int t = mEsm->read(x, size);
if (t != size)
fail("Read error");
try
{
int t = mEsm->read(x, size);
if (t != size)
fail("Read error");
}
catch (std::exception& e)
{
fail(std::string("Read error: ") + e.what());
}
}
std::string ESMReader::getString(int size)

@ -57,12 +57,13 @@ void ESM::NpcStats::load (ESMReader &esm)
mWerewolfKills = 0;
esm.getHNOT (mWerewolfKills, "WKIL");
mProfit = 0;
esm.getHNOT (mProfit, "PROF");
// No longer used
if (esm.isNextSub("PROF"))
esm.skipHSub(); // int profit
// No longer used. Now part of CreatureStats.
float attackStrength = 0;
esm.getHNOT (attackStrength, "ASTR");
if (esm.isNextSub("ASTR"))
esm.skipHSub(); // attackStrength
mLevelProgress = 0;
esm.getHNOT (mLevelProgress, "LPRO");
@ -132,9 +133,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const
if (mWerewolfKills)
esm.writeHNT ("WKIL", mWerewolfKills);
if (mProfit)
esm.writeHNT ("PROF", mProfit);
if (mLevelProgress)
esm.writeHNT ("LPRO", mLevelProgress);
@ -158,7 +156,6 @@ void ESM::NpcStats::blank()
mBounty = 0;
mReputation = 0;
mWerewolfKills = 0;
mProfit = 0;
mLevelProgress = 0;
for (int i=0; i<8; ++i)
mSkillIncrease[i] = 0;

@ -40,7 +40,6 @@ namespace ESM
int mBounty;
int mReputation;
int mWerewolfKills;
int mProfit;
int mLevelProgress;
int mSkillIncrease[8];
std::vector<std::string> mUsedIds; // lower case IDs

@ -27,8 +27,9 @@ const char* const localToken = "?local?";
const char* const userDataToken = "?userdata?";
const char* const globalToken = "?global?";
ConfigurationManager::ConfigurationManager()
ConfigurationManager::ConfigurationManager(bool silent)
: mFixedPath(applicationName)
, mSilent(silent)
{
setupTokensMapping();
@ -129,7 +130,8 @@ void ConfigurationManager::loadConfig(const boost::filesystem::path& path,
cfgFile /= std::string(openmwCfgFile);
if (boost::filesystem::is_regular_file(cfgFile))
{
std::cout << "Loading config file: " << cfgFile.string() << "... ";
if (!mSilent)
std::cout << "Loading config file: " << cfgFile.string() << "... ";
boost::filesystem::ifstream configFileStream(cfgFile);
if (configFileStream.is_open())
@ -137,11 +139,13 @@ void ConfigurationManager::loadConfig(const boost::filesystem::path& path,
boost::program_options::store(boost::program_options::parse_config_file(
configFileStream, description, true), variables);
std::cout << "done." << std::endl;
if (!mSilent)
std::cout << "done." << std::endl;
}
else
{
std::cout << "failed." << std::endl;
if (!mSilent)
std::cout << "failed." << std::endl;
}
}
}

@ -25,7 +25,7 @@ namespace Files
*/
struct ConfigurationManager
{
ConfigurationManager();
ConfigurationManager(bool silent=false); /// @param silent Emit log messages to cout?
virtual ~ConfigurationManager();
void readConfiguration(boost::program_options::variables_map& variables,
@ -69,6 +69,8 @@ struct ConfigurationManager
boost::filesystem::path mLogPath;
TokensMappingContainer mTokensMapping;
bool mSilent;
};
} /* namespace Cfg */

@ -11,162 +11,172 @@ namespace {
class ConstrainedDataStream : public Ogre::DataStream {
public:
static const size_t sBufferSize = 4096; // somewhat arbitrary though 64KB buffers didn't seem to improve performance any
static const size_t sBufferThreshold = 1024; // reads larger than this bypass buffering as cost of memcpy outweighs cost of system call
static const size_t sBufferSize = 4096; // somewhat arbitrary though 64KB buffers didn't seem to improve performance any
static const size_t sBufferThreshold = 1024; // reads larger than this bypass buffering as cost of memcpy outweighs cost of system call
ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length)
{
mFile.open (fname.c_str ());
mSize = length != 0xFFFFFFFF ? length : mFile.size () - start;
: Ogre::DataStream(fname)
{
mFile.open (fname.c_str ());
mSize = length != 0xFFFFFFFF ? length : mFile.size () - start;
mPos = 0;
mOrigin = start;
mExtent = start + mSize;
mPos = 0;
mOrigin = start;
mExtent = start + mSize;
mBufferOrigin = 0;
mBufferExtent = 0;
}
mBufferOrigin = 0;
mBufferExtent = 0;
}
size_t read(void* buf, size_t count)
{
assert (mPos <= mSize);
size_t read(void* buf, size_t count)
{
try
{
assert (mPos <= mSize);
uint8_t * out = reinterpret_cast <uint8_t *> (buf);
uint8_t * out = reinterpret_cast <uint8_t *> (buf);
size_t posBeg = mOrigin + mPos;
size_t posEnd = posBeg + count;
size_t posBeg = mOrigin + mPos;
size_t posEnd = posBeg + count;
if (posEnd > mExtent)
posEnd = mExtent;
if (posEnd > mExtent)
posEnd = mExtent;
size_t posCur = posBeg;
size_t posCur = posBeg;
while (posCur != posEnd)
{
size_t readLeft = posEnd - posCur;
while (posCur != posEnd)
{
size_t readLeft = posEnd - posCur;
if (posCur < mBufferOrigin || posCur >= mBufferExtent)
{
if (readLeft >= sBufferThreshold || (posCur == mOrigin && posEnd == mExtent))
{
assert (mFile.tell () == mBufferExtent);
if (posCur < mBufferOrigin || posCur >= mBufferExtent)
{
if (readLeft >= sBufferThreshold || (posCur == mOrigin && posEnd == mExtent))
{
assert (mFile.tell () == mBufferExtent);
if (posCur != mBufferExtent)
mFile.seek (posCur);
if (posCur != mBufferExtent)
mFile.seek (posCur);
posCur += mFile.read (out, readLeft);
posCur += mFile.read (out, readLeft);
mBufferOrigin = mBufferExtent = posCur;
mBufferOrigin = mBufferExtent = posCur;
mPos = posCur - mOrigin;
mPos = posCur - mOrigin;
return posCur - posBeg;
}
else
{
size_t newBufferOrigin;
return posCur - posBeg;
}
else
{
size_t newBufferOrigin;
if ((posCur < mBufferOrigin) && (mBufferOrigin - posCur < sBufferSize))
newBufferOrigin = std::max (mOrigin, mBufferOrigin > sBufferSize ? mBufferOrigin - sBufferSize : 0);
else
newBufferOrigin = posCur;
if ((posCur < mBufferOrigin) && (mBufferOrigin - posCur < sBufferSize))
newBufferOrigin = std::max (mOrigin, mBufferOrigin > sBufferSize ? mBufferOrigin - sBufferSize : 0);
else
newBufferOrigin = posCur;
fill (newBufferOrigin);
}
}
fill (newBufferOrigin);
}
}
size_t xfer = std::min (readLeft, mBufferExtent - posCur);
size_t xfer = std::min (readLeft, mBufferExtent - posCur);
memcpy (out, mBuffer + (posCur - mBufferOrigin), xfer);
memcpy (out, mBuffer + (posCur - mBufferOrigin), xfer);
posCur += xfer;
out += xfer;
}
posCur += xfer;
out += xfer;
}
count = posEnd - posBeg;
mPos += count;
return count;
}
count = posEnd - posBeg;
mPos += count;
return count;
}
catch (std::exception& e)
{
std::stringstream error;
error << "Failed to read '" << mName << "': " << e.what();
throw std::runtime_error(error.str());
}
}
void skip(long count)
{
assert (mPos <= mSize);
assert (mPos <= mSize);
if((count >= 0 && (size_t)count <= mSize-mPos) ||
(count < 0 && (size_t)-count <= mPos))
mPos += count;
mPos += count;
}
void seek(size_t pos)
{
assert (mPos <= mSize);
assert (mPos <= mSize);
if (pos < mSize)
mPos = pos;
mPos = pos;
}
virtual size_t tell() const
{
assert (mPos <= mSize);
assert (mPos <= mSize);
return mPos;
}
return mPos;
}
virtual bool eof() const
{
assert (mPos <= mSize);
assert (mPos <= mSize);
return mPos == mSize;
}
return mPos == mSize;
}
virtual void close()
{
mFile.close();
}
mFile.close();
}
private:
void fill (size_t newOrigin)
{
assert (mFile.tell () == mBufferExtent);
void fill (size_t newOrigin)
{
assert (mFile.tell () == mBufferExtent);
size_t newExtent = newOrigin + sBufferSize;
size_t newExtent = newOrigin + sBufferSize;
if (newExtent > mExtent)
newExtent = mExtent;
if (newExtent > mExtent)
newExtent = mExtent;
size_t oldExtent = mBufferExtent;
size_t oldExtent = mBufferExtent;
if (newOrigin != oldExtent)
mFile.seek (newOrigin);
if (newOrigin != oldExtent)
mFile.seek (newOrigin);
mBufferOrigin = mBufferExtent = newOrigin;
mBufferOrigin = mBufferExtent = newOrigin;
size_t amountRequested = newExtent - newOrigin;
size_t amountRequested = newExtent - newOrigin;
size_t amountRead = mFile.read (mBuffer, amountRequested);
size_t amountRead = mFile.read (mBuffer, amountRequested);
if (amountRead != amountRequested)
throw std::runtime_error ("An unexpected condition occurred while reading from a file.");
if (amountRead != amountRequested)
throw std::runtime_error ("An unexpected condition occurred while reading from a file.");
mBufferExtent = newExtent;
}
mBufferExtent = newExtent;
}
LowLevelFile mFile;
LowLevelFile mFile;
size_t mOrigin;
size_t mExtent;
size_t mPos;
size_t mOrigin;
size_t mExtent;
size_t mPos;
uint8_t mBuffer [sBufferSize];
size_t mBufferOrigin;
size_t mBufferExtent;
uint8_t mBuffer [sBufferSize];
size_t mBufferOrigin;
size_t mBufferExtent;
};
} // end of unnamed namespace
Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset, size_t length)
{
return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, offset, length));
return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, offset, length));
}

@ -13,196 +13,196 @@
#if FILE_API == FILE_API_STDIO
/*
*
* Implementation of LowLevelFile methods using c stdio
* Implementation of LowLevelFile methods using c stdio
*
*/
LowLevelFile::LowLevelFile ()
{
mHandle = NULL;
mHandle = NULL;
}
LowLevelFile::~LowLevelFile ()
{
if (mHandle != NULL)
fclose (mHandle);
if (mHandle != NULL)
fclose (mHandle);
}
void LowLevelFile::open (char const * filename)
{
assert (mHandle == NULL);
assert (mHandle == NULL);
mHandle = fopen (filename, "rb");
mHandle = fopen (filename, "rb");
if (mHandle == NULL)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
if (mHandle == NULL)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
}
void LowLevelFile::close ()
{
assert (mHandle != NULL);
assert (mHandle != NULL);
fclose (mHandle);
fclose (mHandle);
mHandle = NULL;
mHandle = NULL;
}
size_t LowLevelFile::size ()
{
assert (mHandle != NULL);
assert (mHandle != NULL);
long oldPosition = ftell (mHandle);
long oldPosition = ftell (mHandle);
if (oldPosition == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (oldPosition == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (fseek (mHandle, 0, SEEK_END) != 0)
throw std::runtime_error ("A query operation on a file failed.");
if (fseek (mHandle, 0, SEEK_END) != 0)
throw std::runtime_error ("A query operation on a file failed.");
long Size = ftell (mHandle);
long Size = ftell (mHandle);
if (Size == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (Size == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (fseek (mHandle, oldPosition, SEEK_SET) != 0)
throw std::runtime_error ("A query operation on a file failed.");
if (fseek (mHandle, oldPosition, SEEK_SET) != 0)
throw std::runtime_error ("A query operation on a file failed.");
return size_t (Size);
return size_t (Size);
}
void LowLevelFile::seek (size_t Position)
{
assert (mHandle != NULL);
assert (mHandle != NULL);
if (fseek (mHandle, Position, SEEK_SET) != 0)
throw std::runtime_error ("A seek operation on a file failed.");
if (fseek (mHandle, Position, SEEK_SET) != 0)
throw std::runtime_error ("A seek operation on a file failed.");
}
size_t LowLevelFile::tell ()
{
assert (mHandle != NULL);
assert (mHandle != NULL);
long Position = ftell (mHandle);
long Position = ftell (mHandle);
if (Position == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (Position == -1)
throw std::runtime_error ("A query operation on a file failed.");
return size_t (Position);
return size_t (Position);
}
size_t LowLevelFile::read (void * data, size_t size)
{
assert (mHandle != NULL);
assert (mHandle != NULL);
int amount = fread (data, 1, size, mHandle);
int amount = fread (data, 1, size, mHandle);
if (amount == 0 && ferror (mHandle))
throw std::runtime_error ("A read operation on a file failed.");
if (amount == 0 && ferror (mHandle))
throw std::runtime_error ("A read operation on a file failed.");
return amount;
return amount;
}
#elif FILE_API == FILE_API_POSIX
/*
*
* Implementation of LowLevelFile methods using posix IO calls
* Implementation of LowLevelFile methods using posix IO calls
*
*/
LowLevelFile::LowLevelFile ()
{
mHandle = -1;
mHandle = -1;
}
LowLevelFile::~LowLevelFile ()
{
if (mHandle != -1)
::close (mHandle);
if (mHandle != -1)
::close (mHandle);
}
void LowLevelFile::open (char const * filename)
{
assert (mHandle == -1);
assert (mHandle == -1);
#ifdef O_BINARY
static const int openFlags = O_RDONLY | O_BINARY;
static const int openFlags = O_RDONLY | O_BINARY;
#else
static const int openFlags = O_RDONLY;
static const int openFlags = O_RDONLY;
#endif
mHandle = ::open (filename, openFlags, 0);
mHandle = ::open (filename, openFlags, 0);
if (mHandle == -1)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
if (mHandle == -1)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
}
void LowLevelFile::close ()
{
assert (mHandle != -1);
assert (mHandle != -1);
::close (mHandle);
::close (mHandle);
mHandle = -1;
mHandle = -1;
}
size_t LowLevelFile::size ()
{
assert (mHandle != -1);
assert (mHandle != -1);
size_t oldPosition = ::lseek (mHandle, 0, SEEK_CUR);
size_t oldPosition = ::lseek (mHandle, 0, SEEK_CUR);
if (oldPosition == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
if (oldPosition == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
size_t Size = ::lseek (mHandle, 0, SEEK_END);
size_t Size = ::lseek (mHandle, 0, SEEK_END);
if (Size == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
if (Size == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
if (lseek (mHandle, oldPosition, SEEK_SET) == -1)
throw std::runtime_error ("A query operation on a file failed.");
if (lseek (mHandle, oldPosition, SEEK_SET) == -1)
throw std::runtime_error ("A query operation on a file failed.");
return Size;
return Size;
}
void LowLevelFile::seek (size_t Position)
{
assert (mHandle != -1);
assert (mHandle != -1);
if (::lseek (mHandle, Position, SEEK_SET) == -1)
throw std::runtime_error ("A seek operation on a file failed.");
if (::lseek (mHandle, Position, SEEK_SET) == -1)
throw std::runtime_error ("A seek operation on a file failed.");
}
size_t LowLevelFile::tell ()
{
assert (mHandle != -1);
assert (mHandle != -1);
size_t Position = ::lseek (mHandle, 0, SEEK_CUR);
size_t Position = ::lseek (mHandle, 0, SEEK_CUR);
if (Position == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
if (Position == size_t (-1))
throw std::runtime_error ("A query operation on a file failed.");
return Position;
return Position;
}
size_t LowLevelFile::read (void * data, size_t size)
{
assert (mHandle != -1);
assert (mHandle != -1);
int amount = ::read (mHandle, data, size);
int amount = ::read (mHandle, data, size);
if (amount == -1)
throw std::runtime_error ("A read operation on a file failed.");
if (amount == -1)
throw std::runtime_error ("A read operation on a file failed.");
return amount;
return amount;
}
#elif FILE_API == FILE_API_WIN32
@ -210,93 +210,93 @@ size_t LowLevelFile::read (void * data, size_t size)
#include <boost/locale.hpp>
/*
*
* Implementation of LowLevelFile methods using Win32 API calls
* Implementation of LowLevelFile methods using Win32 API calls
*
*/
LowLevelFile::LowLevelFile ()
{
mHandle = INVALID_HANDLE_VALUE;
mHandle = INVALID_HANDLE_VALUE;
}
LowLevelFile::~LowLevelFile ()
{
if (mHandle != INVALID_HANDLE_VALUE)
CloseHandle (mHandle);
if (mHandle != INVALID_HANDLE_VALUE)
CloseHandle (mHandle);
}
void LowLevelFile::open (char const * filename)
{
assert (mHandle == INVALID_HANDLE_VALUE);
assert (mHandle == INVALID_HANDLE_VALUE);
std::wstring wname = boost::locale::conv::utf_to_utf<wchar_t>(filename);
HANDLE handle = CreateFileW (wname.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
std::wstring wname = boost::locale::conv::utf_to_utf<wchar_t>(filename);
HANDLE handle = CreateFileW (wname.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (handle == INVALID_HANDLE_VALUE)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
if (handle == INVALID_HANDLE_VALUE)
{
std::ostringstream os;
os << "Failed to open '" << filename << "' for reading.";
throw std::runtime_error (os.str ());
}
mHandle = handle;
mHandle = handle;
}
void LowLevelFile::close ()
{
assert (mHandle != INVALID_HANDLE_VALUE);
assert (mHandle != INVALID_HANDLE_VALUE);
CloseHandle (mHandle);
CloseHandle (mHandle);
mHandle = INVALID_HANDLE_VALUE;
mHandle = INVALID_HANDLE_VALUE;
}
size_t LowLevelFile::size ()
{
assert (mHandle != INVALID_HANDLE_VALUE);
assert (mHandle != INVALID_HANDLE_VALUE);
BY_HANDLE_FILE_INFORMATION info;
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle (mHandle, &info))
throw std::runtime_error ("A query operation on a file failed.");
if (!GetFileInformationByHandle (mHandle, &info))
throw std::runtime_error ("A query operation on a file failed.");
if (info.nFileSizeHigh != 0)
throw std::runtime_error ("Files greater that 4GB are not supported.");
if (info.nFileSizeHigh != 0)
throw std::runtime_error ("Files greater that 4GB are not supported.");
return info.nFileSizeLow;
return info.nFileSizeLow;
}
void LowLevelFile::seek (size_t Position)
{
assert (mHandle != INVALID_HANDLE_VALUE);
assert (mHandle != INVALID_HANDLE_VALUE);
if (SetFilePointer (mHandle, Position, NULL, SEEK_SET) == INVALID_SET_FILE_POINTER)
if (GetLastError () != NO_ERROR)
throw std::runtime_error ("A seek operation on a file failed.");
if (SetFilePointer (mHandle, Position, NULL, SEEK_SET) == INVALID_SET_FILE_POINTER)
if (GetLastError () != NO_ERROR)
throw std::runtime_error ("A seek operation on a file failed.");
}
size_t LowLevelFile::tell ()
{
assert (mHandle != INVALID_HANDLE_VALUE);
assert (mHandle != INVALID_HANDLE_VALUE);
DWORD value = SetFilePointer (mHandle, 0, NULL, SEEK_CUR);
DWORD value = SetFilePointer (mHandle, 0, NULL, SEEK_CUR);
if (value == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
throw std::runtime_error ("A query operation on a file failed.");
if (value == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
throw std::runtime_error ("A query operation on a file failed.");
return value;
return value;
}
size_t LowLevelFile::read (void * data, size_t size)
{
assert (mHandle != INVALID_HANDLE_VALUE);
assert (mHandle != INVALID_HANDLE_VALUE);
DWORD read;
DWORD read;
if (!ReadFile (mHandle, data, size, &read, NULL))
throw std::runtime_error ("A read operation on a file failed.");
if (!ReadFile (mHandle, data, size, &read, NULL))
throw std::runtime_error ("A read operation on a file failed.");
return read;
return read;
}
#endif

@ -5,16 +5,16 @@
#include <cstdlib>
#define FILE_API_STDIO 0
#define FILE_API_POSIX 1
#define FILE_API_WIN32 2
#define FILE_API_STDIO 0
#define FILE_API_POSIX 1
#define FILE_API_WIN32 2
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
#define FILE_API FILE_API_POSIX
#define FILE_API FILE_API_POSIX
#elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define FILE_API FILE_API_WIN32
#define FILE_API FILE_API_WIN32
#else
#define FILE_API FILE_API_STDIO
#define FILE_API FILE_API_STDIO
#endif
#if FILE_API == FILE_API_STDIO
@ -30,26 +30,26 @@ class LowLevelFile
{
public:
LowLevelFile ();
~LowLevelFile ();
LowLevelFile ();
~LowLevelFile ();
void open (char const * filename);
void close ();
void open (char const * filename);
void close ();
size_t size ();
size_t size ();
void seek (size_t Position);
size_t tell ();
void seek (size_t Position);
size_t tell ();
size_t read (void * data, size_t size);
size_t read (void * data, size_t size);
private:
#if FILE_API == FILE_API_STDIO
FILE* mHandle;
FILE* mHandle;
#elif FILE_API == FILE_API_POSIX
int mHandle;
int mHandle;
#elif FILE_API == FILE_API_WIN32
HANDLE mHandle;
HANDLE mHandle;
#endif
};

@ -37,31 +37,7 @@ public:
NIFStream (NIFFile * file, Ogre::DataStreamPtr inp): file (file), inp (inp) {}
/*************************************************
Parser functions
****************************************************/
template <typename T>
struct GetHandler
{
typedef T (NIFStream::*fn_t)();
static const fn_t sValue; // this is specialized per supported type in the .cpp file
static T read (NIFStream* nif)
{
return (nif->*sValue) ();
}
};
template <typename T>
void read (NIFStream* nif, T & Value)
{
Value = GetHandler <T>::read (nif);
}
void skip(size_t size) { inp->skip(size); }
void read (void * data, size_t size) { inp->read (data, size); }
char getChar() { return read_byte(); }
short getShort() { return read_le16(); }

@ -175,13 +175,27 @@ void PacketQueue::clear()
int VideoState::OgreResource_Read(void *user_data, uint8_t *buf, int buf_size)
{
Ogre::DataStreamPtr stream = static_cast<VideoState*>(user_data)->stream;
return stream->read(buf, buf_size);
try
{
return stream->read(buf, buf_size);
}
catch (std::exception& e)
{
return 0;
}
}
int VideoState::OgreResource_Write(void *user_data, uint8_t *buf, int buf_size)
{
Ogre::DataStreamPtr stream = static_cast<VideoState*>(user_data)->stream;
return stream->write(buf, buf_size);
try
{
return stream->write(buf, buf_size);
}
catch (std::exception& e)
{
return 0;
}
}
int64_t VideoState::OgreResource_Seek(void *user_data, int64_t offset, int whence)

@ -38,16 +38,14 @@ shUniform(float4x4, projection) @shAutoConstant(projection, projection_matrix)
SH_START_PROGRAM
{
float4 tex = shSample(diffuseMap, UV);
shOutputColour(0) = float4(materialEmissive.xyz, 1) * tex;
shOutputColour(0).a = shSample(alphaMap, UV).a * materialDiffuse.a;
shOutputColour(0).rgb += (1.0-tex.a) * shOutputColour(0).a * atmosphereColour.rgb; //fill dark side of moon with atmosphereColour
shOutputColour(0).rgb += (1.0-materialDiffuse.a) * atmosphereColour.rgb; //fade bump
float4 phaseTex = shSample(diffuseMap, UV);
float4 fullCircleTex = shSample(alphaMap, UV);
shOutputColour(0).a = max(phaseTex.a, fullCircleTex.a) * materialDiffuse.a;
shOutputColour(0).xyz = fullCircleTex.xyz * atmosphereColour.xyz;
shOutputColour(0).xyz = shLerp(shOutputColour(0).xyz, phaseTex.xyz, phaseTex.a);
shOutputColour(0).xyz *= materialEmissive.xyz;
}
#endif

@ -50,7 +50,7 @@ material openmw_moon
texture_unit alphaMap
{
direct_texture textures\tx_secunda_full.dds
texture_alias $alphatexture
}
}
}

@ -71,8 +71,6 @@
SH_BEGIN_PROGRAM
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
shOutput(float3, screenCoordsPassthrough)
shOutput(float4, position)
@ -98,7 +96,6 @@
SH_START_PROGRAM
{
shOutputPosition = shMatrixMult(wvp, shInputPosition);
UV = uv0;
#if !SH_GLSL
@ -187,7 +184,6 @@
}
SH_BEGIN_PROGRAM
shInput(float2, UV)
shInput(float3, screenCoordsPassthrough)
shInput(float4, position)
shInput(float, depthPassthrough)
@ -206,9 +202,10 @@
shSampler2D(depthMap)
shSampler2D(normalMap)
shUniform(float4x4, wMat) @shAutoConstant(wMat, world_matrix)
#if RIPPLES
shSampler2D(rippleNormalMap)
shUniform(float4x4, wMat) @shAutoConstant(wMat, world_matrix)
#endif
shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed)
@ -251,6 +248,10 @@
SH_START_PROGRAM
{
float3 worldPos = shMatrixMult (wMat, position).xyz;
float2 UV = worldPos.xy / (8192.0*5.0) * 3.0;
UV.y *= -1.0;
#if SHADOWS
float shadow = depthShadowPCF (shadowMap0, lightSpacePos0, invShadowmapSize0);
#endif

@ -137,4 +137,19 @@
</Widget>
</Resource>
<!-- Same as MW_Caption, but reserves some free space on the right for the Pin button -
i.e. not allowing the caption label to stretch there, but still showing the tiling background. -->
<Resource type="ResourceLayout" name="MW_Caption_Pin" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 88 20" name="Root">
<Widget type="Widget" skin="HB_ALL" position="0 0 30 20" align="Default" name="Left"/>
<Widget type="Widget" skin="" position="0 0 69 20" align="Stretch">
<Widget type="TextBox" skin="SandText" position="30 0 28 20" align="Left VStretch" name="Client">
<Property key="FontName" value="Default"/>
<Property key="TextAlign" value="Center"/>
</Widget>
</Widget>
<Widget type="Widget" skin="HB_ALL" position="0 0 30 20" align="Right" name="Right"/>
</Widget>
</Resource>
</MyGUI>

@ -804,7 +804,7 @@
</Child>
<!-- Caption -->
<Child type="WindowCaption" skin="MW_Caption" offset="4 4 228 20" align="HStretch Top" name="Caption">
<Child type="WindowCaption" skin="MW_Caption_Pin" offset="4 4 248 20" align="HStretch Top" name="Caption">
</Child>
<!-- This invisible button makes it possible to move the

@ -4,8 +4,8 @@ Name=OpenMW Launcher
GenericName=Role Playing Game
Comment=An engine replacement for The Elder Scrolls III: Morrowind
Keywords=Morrowind;Reimplementation Mods;esm;bsa;
TryExec=omwlauncher
Exec=omwlauncher
TryExec=openmw-launcher
Exec=openmw-launcher
Icon=openmw
Categories=Game;RolePlaying;

@ -44,7 +44,6 @@
border-radius: 2px;
font-size: 12pt;
font-family: &quot;EB Garamond&quot;, &quot;EB Garamond 08&quot;;
color: black;
}
@ -95,7 +94,6 @@
<property name="styleSheet">
<string notr="true">#profileLabel {
font-size: 18pt;
font-family: &quot;EB Garamond&quot;, &quot;EB Garamond 08&quot;;
color: black;
}
</string>
@ -133,7 +131,6 @@
stop:1 rgba(0, 0, 0, 100));
font-size: 26pt;
font-family: &quot;EB Garamond&quot;, &quot;EB Garamond 08&quot;;
color: black;
border-right: 1px solid rgba(0, 0, 0, 155);

Loading…
Cancel
Save