forked from mirror/openmw-tes3mp
Merge remote-tracking branch 'scrawl/master'
Conflicts: apps/openmw/main.cpp
This commit is contained in:
commit
2faeceacfa
66 changed files with 525 additions and 254 deletions
|
@ -80,13 +80,6 @@ option(USE_FFMPEG "use ffmpeg for sound" ON)
|
|||
# OS X deployment
|
||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
option(BUILD_WITH_DPKG "enable dpkg-based install for debian and debian derivatives" OFF)
|
||||
if(BUILD_WITH_DPKG)
|
||||
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
|
||||
endif(BUILD_WITH_DPKG)
|
||||
endif(UNIX AND NOT APPLE)
|
||||
|
||||
# Location of morrowind data files
|
||||
if (APPLE)
|
||||
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
||||
|
@ -395,46 +388,36 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
|||
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
## Debian and non debian Linux building
|
||||
# Linux building
|
||||
# Paths
|
||||
IF (DPKG_PROGRAM)
|
||||
## Debian specific
|
||||
SET(CMAKE_INSTALL_PREFIX "/usr")
|
||||
SET(DATAROOTDIR "share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(DATADIR "share/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
SET(ICONDIR "share/pixmaps" CACHE PATH "Set icon dir")
|
||||
SET(SYSCONFDIR "../etc/openmw" CACHE PATH "Set config dir")
|
||||
ELSE ()
|
||||
## Non debian specific
|
||||
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
|
||||
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
|
||||
SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir")
|
||||
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
|
||||
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
|
||||
SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir")
|
||||
|
||||
# Install binaries
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
|
||||
IF(BUILD_LAUNCHER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_LAUNCHER)
|
||||
IF(BUILD_BSATOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_BSATOOL)
|
||||
IF(BUILD_ESMTOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_ESMTOOL)
|
||||
IF(BUILD_MWINIIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_MWINIIMPORTER)
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_OPENCS)
|
||||
# Install binaries
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
|
||||
IF(BUILD_LAUNCHER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_LAUNCHER)
|
||||
IF(BUILD_BSATOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_BSATOOL)
|
||||
IF(BUILD_ESMTOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_ESMTOOL)
|
||||
IF(BUILD_MWINIIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_MWINIIMPORTER)
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_OPENCS)
|
||||
|
||||
# Install licenses
|
||||
INSTALL(FILES "DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
||||
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||
ENDIF (DPKG_PROGRAM)
|
||||
# Install licenses
|
||||
INSTALL(FILES "docs/license/DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
||||
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||
|
||||
# Install icon and desktop file
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
|
|
|
@ -119,10 +119,6 @@ endif(NOT WIN32)
|
|||
|
||||
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS omwlauncher RUNTIME DESTINATION games COMPONENT omwlauncher)
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(omwlauncher gcov)
|
||||
|
|
|
@ -22,8 +22,3 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||
add_definitions (--coverage)
|
||||
target_link_libraries(mwiniimport gcov)
|
||||
endif()
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -199,10 +199,6 @@ target_link_libraries(opencs
|
|||
components
|
||||
)
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS opencs RUNTIME DESTINATION games COMPONENT opencs)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
INSTALL(TARGETS opencs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||
endif()
|
||||
|
|
|
@ -142,10 +142,6 @@ if(APPLE)
|
|||
endif()
|
||||
endif(APPLE)
|
||||
|
||||
if(DPKG_PROGRAM)
|
||||
INSTALL(TARGETS openmw RUNTIME DESTINATION games COMPONENT openmw)
|
||||
endif(DPKG_PROGRAM)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(openmw gcov)
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
#include <components/version/version.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_messagebox.h>
|
||||
#include <SDL_main.h>
|
||||
#include "engine.hpp"
|
||||
|
||||
#include <boost/iostreams/concepts.hpp>
|
||||
|
@ -253,6 +254,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
}
|
||||
|
||||
#if defined(_WIN32) && defined(_DEBUG)
|
||||
|
||||
class DebugOutput : public boost::iostreams::sink
|
||||
{
|
||||
public:
|
||||
|
@ -348,7 +350,7 @@ int main(int argc, char**argv)
|
|||
catch (std::exception &e)
|
||||
{
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
if (isatty(fileno(stdin)) || !SDL_WasInit(SDL_INIT_VIDEO))
|
||||
if (isatty(fileno(stdin)))
|
||||
std::cerr << "\nERROR: " << e.what() << std::endl;
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -76,6 +76,9 @@ namespace MWBase
|
|||
|
||||
/// @return faction1's opinion of faction2
|
||||
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0;
|
||||
|
||||
/// Removes the last added topic response for the given actor from the journal
|
||||
virtual void clearInfoActor (const MWWorld::Ptr& actor) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,12 @@ namespace MWBase
|
|||
virtual int getJournalIndex (const std::string& id) const = 0;
|
||||
///< Get the journal index.
|
||||
|
||||
virtual void addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName) = 0;
|
||||
virtual void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor) = 0;
|
||||
/// \note topicId must be lowercase
|
||||
|
||||
virtual void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName) = 0;
|
||||
///< Removes the last topic response added for the given topicId and actor name.
|
||||
/// \note topicId must be lowercase
|
||||
|
||||
virtual TEntryIter begin() const = 0;
|
||||
///< Iterator pointing to the begin of the main journal.
|
||||
|
|
|
@ -328,6 +328,8 @@ namespace MWBase
|
|||
/** Used when one Modal adds another Modal
|
||||
\param input Pointer to the current modal, to ensure proper modal is removed **/
|
||||
virtual void removeCurrentModal(MWGui::WindowModal* input) = 0;
|
||||
|
||||
virtual void pinWindow (MWGui::GuiWindow window) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -345,7 +345,9 @@ namespace MWClass
|
|||
getCreatureStats(ptr).setAttacked(true);
|
||||
|
||||
// Self defense
|
||||
if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80)
|
||||
if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80
|
||||
&& (canWalk(ptr) || canFly(ptr) || canSwim(ptr))) // No retaliation for totally static creatures
|
||||
// (they have no movement or attacks anyway)
|
||||
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
|
||||
|
||||
if(!successful)
|
||||
|
|
|
@ -14,9 +14,12 @@ namespace MWClass
|
|||
{
|
||||
void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Static> *ref =
|
||||
ptr.get<ESM::Static>();
|
||||
|
||||
const std::string model = getModel(ptr);
|
||||
if (!model.empty()) {
|
||||
renderingInterface.getObjects().insertModel(ptr, model);
|
||||
renderingInterface.getObjects().insertModel(ptr, model, !ref->mBase->mPersistent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,11 @@ namespace MWDialogue
|
|||
mActorKnownTopics.clear();
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
win->startDialogue(actor, actor.getClass().getName (actor));
|
||||
|
||||
// If the dialogue window was already open, keep the existing history
|
||||
bool resetHistory = (!MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Dialogue));
|
||||
|
||||
win->startDialogue(actor, actor.getClass().getName (actor), resetHistory);
|
||||
|
||||
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
|
||||
updateTopics();
|
||||
|
@ -294,7 +298,7 @@ namespace MWDialogue
|
|||
{
|
||||
if (iter->mId == info->mId)
|
||||
{
|
||||
MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor.getClass().getName(mActor));
|
||||
MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +476,7 @@ namespace MWDialogue
|
|||
{
|
||||
if (iter->mId == info->mId)
|
||||
{
|
||||
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor.getClass().getName(mActor));
|
||||
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -694,6 +698,15 @@ namespace MWDialogue
|
|||
return diff;
|
||||
}
|
||||
|
||||
void DialogueManager::clearInfoActor(const MWWorld::Ptr &actor) const
|
||||
{
|
||||
if (actor == mActor && !mLastTopic.empty())
|
||||
{
|
||||
MWBase::Environment::get().getJournal()->removeLastAddedTopicResponse(
|
||||
mLastTopic, actor.getClass().getName(actor));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
|
||||
{
|
||||
std::vector<HyperTextToken> result;
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace MWDialogue
|
|||
bool mTalkedTo;
|
||||
|
||||
int mChoice;
|
||||
std::string mLastTopic;
|
||||
std::string mLastTopic; // last topic ID, lowercase
|
||||
bool mIsInChoice;
|
||||
|
||||
float mTemporaryDispositionChange;
|
||||
|
@ -99,6 +99,9 @@ namespace MWDialogue
|
|||
|
||||
/// @return faction1's opinion of faction2
|
||||
virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const;
|
||||
|
||||
/// Removes the last added topic response for the given actor from the journal
|
||||
virtual void clearInfoActor (const MWWorld::Ptr& actor) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -5,16 +5,21 @@
|
|||
|
||||
#include <components/esm/journalentry.hpp>
|
||||
|
||||
#include <components/interpreter/defines.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwscript/interpretercontext.hpp"
|
||||
|
||||
|
||||
namespace MWDialogue
|
||||
{
|
||||
Entry::Entry() {}
|
||||
|
||||
Entry::Entry (const std::string& topic, const std::string& infoId)
|
||||
Entry::Entry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor)
|
||||
: mInfoId (infoId)
|
||||
{
|
||||
const ESM::Dialogue *dialogue =
|
||||
|
@ -24,8 +29,17 @@ namespace MWDialogue
|
|||
iter!=dialogue->mInfo.end(); ++iter)
|
||||
if (iter->mId == mInfoId)
|
||||
{
|
||||
/// \todo text replacement
|
||||
mText = iter->mResponse;
|
||||
if (actor.isEmpty())
|
||||
{
|
||||
MWScript::InterpreterContext interpreterContext(NULL,MWWorld::Ptr());
|
||||
mText = Interpreter::fixDefinesDialog(iter->mResponse, interpreterContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
MWScript::InterpreterContext interpreterContext(&actor.getRefData().getLocals(),actor);
|
||||
mText = Interpreter::fixDefinesDialog(iter->mResponse, interpreterContext);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -49,8 +63,8 @@ namespace MWDialogue
|
|||
|
||||
JournalEntry::JournalEntry() {}
|
||||
|
||||
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId)
|
||||
: Entry (topic, infoId), mTopic (topic)
|
||||
JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor)
|
||||
: Entry (topic, infoId, actor), mTopic (topic)
|
||||
{}
|
||||
|
||||
JournalEntry::JournalEntry (const ESM::JournalEntry& record)
|
||||
|
@ -65,7 +79,7 @@ namespace MWDialogue
|
|||
|
||||
JournalEntry JournalEntry::makeFromQuest (const std::string& topic, int index)
|
||||
{
|
||||
return JournalEntry (topic, idFromIndex (topic, index));
|
||||
return JournalEntry (topic, idFromIndex (topic, index), MWWorld::Ptr());
|
||||
}
|
||||
|
||||
std::string JournalEntry::idFromIndex (const std::string& topic, int index)
|
||||
|
@ -90,7 +104,7 @@ namespace MWDialogue
|
|||
|
||||
StampedJournalEntry::StampedJournalEntry (const std::string& topic, const std::string& infoId,
|
||||
int day, int month, int dayOfMonth)
|
||||
: JournalEntry (topic, infoId), mDay (day), mMonth (month), mDayOfMonth (dayOfMonth)
|
||||
: JournalEntry (topic, infoId, MWWorld::Ptr()), mDay (day), mMonth (month), mDayOfMonth (dayOfMonth)
|
||||
{}
|
||||
|
||||
StampedJournalEntry::StampedJournalEntry (const ESM::JournalEntry& record)
|
||||
|
|
|
@ -8,6 +8,11 @@ namespace ESM
|
|||
struct JournalEntry;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Ptr;
|
||||
}
|
||||
|
||||
namespace MWDialogue
|
||||
{
|
||||
/// \brief Basic quest/dialogue/topic entry
|
||||
|
@ -19,7 +24,8 @@ namespace MWDialogue
|
|||
|
||||
Entry();
|
||||
|
||||
Entry (const std::string& topic, const std::string& infoId);
|
||||
/// actor is optional
|
||||
Entry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor);
|
||||
|
||||
Entry (const ESM::JournalEntry& record);
|
||||
|
||||
|
@ -37,7 +43,7 @@ namespace MWDialogue
|
|||
|
||||
JournalEntry();
|
||||
|
||||
JournalEntry (const std::string& topic, const std::string& infoId);
|
||||
JournalEntry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor);
|
||||
|
||||
JournalEntry (const ESM::JournalEntry& record);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <components/esm/journalentry.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -103,15 +104,25 @@ namespace MWDialogue
|
|||
quest.setIndex (index);
|
||||
}
|
||||
|
||||
void Journal::addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName)
|
||||
void Journal::addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor)
|
||||
{
|
||||
Topic& topic = getTopic (topicId);
|
||||
|
||||
JournalEntry entry(topicId, infoId);
|
||||
entry.mActorName = actorName;
|
||||
JournalEntry entry(topicId, infoId, actor);
|
||||
entry.mActorName = actor.getClass().getName(actor);
|
||||
topic.addEntry (entry);
|
||||
}
|
||||
|
||||
void Journal::removeLastAddedTopicResponse(const std::string &topicId, const std::string &actorName)
|
||||
{
|
||||
Topic& topic = getTopic (topicId);
|
||||
|
||||
topic.removeLastAddedResponse(actorName);
|
||||
|
||||
if (topic.begin() == topic.end())
|
||||
mTopics.erase(mTopics.find(topicId)); // All responses removed -> remove topic
|
||||
}
|
||||
|
||||
int Journal::getJournalIndex (const std::string& id) const
|
||||
{
|
||||
TQuestContainer::const_iterator iter = mQuests.find (id);
|
||||
|
|
|
@ -38,7 +38,12 @@ namespace MWDialogue
|
|||
virtual int getJournalIndex (const std::string& id) const;
|
||||
///< Get the journal index.
|
||||
|
||||
virtual void addTopic (const std::string& topicId, const std::string& infoId, const std::string& actorName);
|
||||
virtual void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor);
|
||||
/// \note topicId must be lowercase
|
||||
|
||||
virtual void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName);
|
||||
///< Removes the last topic response added for the given topicId and actor name.
|
||||
/// \note topicId must be lowercase
|
||||
|
||||
virtual TEntryIter begin() const;
|
||||
///< Iterator pointing to the begin of the main journal.
|
||||
|
|
|
@ -59,8 +59,16 @@ namespace MWDialogue
|
|||
return mEntries.end();
|
||||
}
|
||||
|
||||
JournalEntry Topic::getEntry (const std::string& infoId) const
|
||||
void Topic::removeLastAddedResponse (const std::string& actorName)
|
||||
{
|
||||
return JournalEntry (mTopic, infoId);
|
||||
for (std::vector<MWDialogue::Entry>::reverse_iterator it = mEntries.rbegin();
|
||||
it != mEntries.rend(); ++it)
|
||||
{
|
||||
if (it->mActorName == actorName)
|
||||
{
|
||||
mEntries.erase( (++it).base() ); // erase doesn't take a reverse_iterator
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,13 +48,13 @@ namespace MWDialogue
|
|||
|
||||
virtual std::string getName() const;
|
||||
|
||||
void removeLastAddedResponse (const std::string& actorName);
|
||||
|
||||
TEntryIter begin() const;
|
||||
///< Iterator pointing to the begin of the journal for this topic.
|
||||
|
||||
TEntryIter end() const;
|
||||
///< Iterator pointing past the end of the journal for this topic.
|
||||
|
||||
JournalEntry getEntry (const std::string& infoId) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -30,9 +30,9 @@ namespace MWGui
|
|||
|
||||
void ConfirmationDialog::exit()
|
||||
{
|
||||
eventCancelClicked();
|
||||
|
||||
setVisible(false);
|
||||
|
||||
eventCancelClicked();
|
||||
}
|
||||
|
||||
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||
|
@ -42,8 +42,8 @@ namespace MWGui
|
|||
|
||||
void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
eventOkClicked();
|
||||
|
||||
setVisible(false);
|
||||
|
||||
eventOkClicked();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -366,10 +366,11 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
|
||||
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName, bool resetHistory)
|
||||
{
|
||||
mGoodbye = false;
|
||||
mEnabled = true;
|
||||
bool sameActor = (mPtr == actor);
|
||||
mPtr = actor;
|
||||
mTopicsList->setEnabled(true);
|
||||
setTitle(npcName);
|
||||
|
@ -378,9 +379,12 @@ namespace MWGui
|
|||
|
||||
mTopicsList->clear();
|
||||
|
||||
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
|
||||
delete (*it);
|
||||
mHistoryContents.clear();
|
||||
if (resetHistory || !sameActor)
|
||||
{
|
||||
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
|
||||
delete (*it);
|
||||
mHistoryContents.clear();
|
||||
}
|
||||
|
||||
for (std::vector<Link*>::iterator it = mLinks.begin(); it != mLinks.end(); ++it)
|
||||
delete (*it);
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace MWGui
|
|||
|
||||
void notifyLinkClicked (TypesetBook::InteractiveId link);
|
||||
|
||||
void startDialogue(MWWorld::Ptr actor, std::string npcName);
|
||||
void startDialogue(MWWorld::Ptr actor, std::string npcName, bool resetHistory);
|
||||
void setKeywords(std::list<std::string> keyWord);
|
||||
|
||||
void addResponse (const std::string& text, const std::string& title="");
|
||||
|
|
|
@ -258,12 +258,16 @@ namespace MWGui
|
|||
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
||||
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
||||
|
||||
// More hacks! The french game uses U+2019, which is nowhere to be found in
|
||||
// the CP437 encoding of the font. Fall back to 39 (regular apostrophe)
|
||||
if (i == 39 && mEncoding == ToUTF8::CP437)
|
||||
// More hacks! The french game uses several win1252 characters that are not included
|
||||
// in the cp437 encoding of the font. Fall back to similar available characters.
|
||||
// Same for U+2013
|
||||
std::map<int, int> additional;
|
||||
additional[39] = 0x2019; // apostrophe
|
||||
additional[45] = 0x2013; // dash
|
||||
if (additional.find(i) != additional.end() && mEncoding == ToUTF8::CP437)
|
||||
{
|
||||
MyGUI::xml::ElementPtr code = codes->createChild("Code");
|
||||
code->addAttribute("index", 0x2019);
|
||||
code->addAttribute("index", additional[i]);
|
||||
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
||||
+ MyGUI::utility::toString(y1) + " "
|
||||
+ MyGUI::utility::toString(w) + " "
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace MWGui
|
|||
Ogre::StringVector groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups ();
|
||||
for (Ogre::StringVector::iterator it = groups.begin(); it != groups.end(); ++it)
|
||||
{
|
||||
Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "Splash_*.tga");
|
||||
Ogre::StringVectorPtr resourcesInThisGroup = Ogre::ResourceGroupManager::getSingleton ().findResourceNames (*it, "Splash/*.tga");
|
||||
mResources.insert(mResources.end(), resourcesInThisGroup->begin(), resourcesInThisGroup->end());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,10 +68,10 @@ namespace MWGui
|
|||
{
|
||||
if (visible)
|
||||
updateMenu();
|
||||
else
|
||||
showBackground(
|
||||
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
|
||||
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame);
|
||||
|
||||
showBackground(
|
||||
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
|
||||
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame);
|
||||
|
||||
OEngine::GUI::Layout::setVisible (visible);
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ namespace MWGui
|
|||
mVideo = mVideoBackground->createWidget<VideoWidget>("ImageBox", 0,0,1,1,
|
||||
MyGUI::Align::Stretch, "Menu");
|
||||
|
||||
mVideo->playVideo("video\\menu_background.bik", false);
|
||||
mVideo->playVideo("video\\menu_background.bik");
|
||||
}
|
||||
|
||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||
|
@ -204,7 +204,7 @@ namespace MWGui
|
|||
if (!mVideo->update())
|
||||
{
|
||||
// If finished playing, start again
|
||||
mVideo->playVideo("video\\menu_background.bik", 0);
|
||||
mVideo->playVideo("video\\menu_background.bik");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +220,6 @@ namespace MWGui
|
|||
|
||||
MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState();
|
||||
|
||||
showBackground(state == MWBase::StateManager::State_NoGame);
|
||||
mVersionText->setVisible(state == MWBase::StateManager::State_NoGame);
|
||||
|
||||
std::vector<std::string> buttons;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "spellwindow.hpp"
|
||||
|
||||
#include "itemwidget.hpp"
|
||||
#include "sortfilteritemmodel.hpp"
|
||||
|
||||
|
||||
namespace MWGui
|
||||
|
@ -134,6 +135,7 @@ namespace MWGui
|
|||
}
|
||||
mItemSelectionDialog->setVisible(true);
|
||||
mItemSelectionDialog->openContainer(MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||
mItemSelectionDialog->setFilter(SortFilterItemModel::Filter_OnlyUsableItems);
|
||||
|
||||
mAssignDialog->setVisible (false);
|
||||
}
|
||||
|
@ -162,7 +164,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::onAssignItem(MWWorld::Ptr item)
|
||||
{
|
||||
assert (mSelectedIndex > 0);
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
|
@ -184,7 +186,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::onAssignMagicItem (MWWorld::Ptr item)
|
||||
{
|
||||
assert (mSelectedIndex > 0);
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
|
@ -203,7 +205,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::onAssignMagic (const std::string& spellId)
|
||||
{
|
||||
assert (mSelectedIndex > 0);
|
||||
assert (mSelectedIndex >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[mSelectedIndex];
|
||||
while (button->getChildCount()) // Destroy number label
|
||||
MyGUI::Gui::getInstance().destroyWidget(button->getChildAt(0));
|
||||
|
@ -245,7 +247,7 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::activateQuickKey(int index)
|
||||
{
|
||||
assert (index-1 > 0);
|
||||
assert (index-1 >= 0);
|
||||
ItemWidget* button = mQuickKeyButtons[index-1];
|
||||
|
||||
QuickKeyType type = mAssigned[index-1];
|
||||
|
|
|
@ -30,11 +30,13 @@ namespace MWGui
|
|||
getWidget(mInfoText, "InfoText");
|
||||
getWidget(mOkButton, "OkButton");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
getWidget(mDeleteButton, "DeleteButton");
|
||||
getWidget(mSaveList, "SaveList");
|
||||
getWidget(mSaveNameEdit, "SaveNameEdit");
|
||||
getWidget(mSpacer, "Spacer");
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SaveGameDialog::onOkButtonClicked);
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SaveGameDialog::onCancelButtonClicked);
|
||||
mDeleteButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteButtonClicked);
|
||||
mCharacterSelection->eventComboChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onCharacterSelected);
|
||||
mSaveList->eventListChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onSlotSelected);
|
||||
mSaveList->eventListMouseItemActivate += MyGUI::newDelegate(this, &SaveGameDialog::onSlotMouseClick);
|
||||
|
@ -54,13 +56,16 @@ namespace MWGui
|
|||
onSlotSelected(sender, pos);
|
||||
|
||||
if (pos != MyGUI::ITEM_NONE && MyGUI::InputManager::getInstance().isShiftPressed())
|
||||
{
|
||||
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
|
||||
dialog->open("#{sMessage3}");
|
||||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotConfirmed);
|
||||
dialog->eventCancelClicked.clear();
|
||||
}
|
||||
confirmDeleteSave();
|
||||
}
|
||||
|
||||
void SaveGameDialog::confirmDeleteSave()
|
||||
{
|
||||
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
|
||||
dialog->open("#{sMessage3}");
|
||||
dialog->eventOkClicked.clear();
|
||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotConfirmed);
|
||||
dialog->eventCancelClicked.clear();
|
||||
}
|
||||
|
||||
void SaveGameDialog::onDeleteSlotConfirmed()
|
||||
|
@ -107,6 +112,7 @@ namespace MWGui
|
|||
mCurrentCharacter = NULL;
|
||||
mCurrentSlot = NULL;
|
||||
mSaveList->removeAllItems();
|
||||
onSlotSelected(mSaveList, MyGUI::ITEM_NONE);
|
||||
|
||||
MWBase::StateManager* mgr = MWBase::Environment::get().getStateManager();
|
||||
if (mgr->characterBegin() == mgr->characterEnd())
|
||||
|
@ -157,6 +163,8 @@ namespace MWGui
|
|||
}
|
||||
|
||||
mCharacterSelection->setIndexSelected(selectedIndex);
|
||||
if (selectedIndex == MyGUI::ITEM_NONE)
|
||||
mCharacterSelection->setCaption("Select Character ...");
|
||||
|
||||
fillSaveList();
|
||||
|
||||
|
@ -175,6 +183,9 @@ namespace MWGui
|
|||
mCharacterSelection->setVisible(load);
|
||||
mSpacer->setUserString("Hidden", load ? "false" : "true");
|
||||
|
||||
mDeleteButton->setUserString("Hidden", load ? "false" : "true");
|
||||
mDeleteButton->setVisible(load);
|
||||
|
||||
if (!load)
|
||||
{
|
||||
mCurrentCharacter = MWBase::Environment::get().getStateManager()->getCurrentCharacter (false);
|
||||
|
@ -188,6 +199,12 @@ namespace MWGui
|
|||
exit();
|
||||
}
|
||||
|
||||
void SaveGameDialog::onDeleteButtonClicked(MyGUI::Widget *sender)
|
||||
{
|
||||
if (mCurrentSlot)
|
||||
confirmDeleteSave();
|
||||
}
|
||||
|
||||
void SaveGameDialog::onConfirmationGiven()
|
||||
{
|
||||
accept(true);
|
||||
|
@ -225,10 +242,8 @@ namespace MWGui
|
|||
}
|
||||
else
|
||||
{
|
||||
if (mCurrentCharacter && mCurrentSlot)
|
||||
{
|
||||
MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot);
|
||||
}
|
||||
assert (mCurrentCharacter && mCurrentSlot);
|
||||
MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,6 +293,9 @@ namespace MWGui
|
|||
|
||||
void SaveGameDialog::onSlotSelected(MyGUI::ListBox *sender, size_t pos)
|
||||
{
|
||||
mOkButton->setEnabled(pos != MyGUI::ITEM_NONE || mSaving);
|
||||
mDeleteButton->setEnabled(pos != MyGUI::ITEM_NONE);
|
||||
|
||||
if (pos == MyGUI::ITEM_NONE)
|
||||
{
|
||||
mCurrentSlot = NULL;
|
||||
|
|
|
@ -24,8 +24,11 @@ namespace MWGui
|
|||
void setLoadOrSave(bool load);
|
||||
|
||||
private:
|
||||
void confirmDeleteSave();
|
||||
|
||||
void onCancelButtonClicked (MyGUI::Widget* sender);
|
||||
void onOkButtonClicked (MyGUI::Widget* sender);
|
||||
void onDeleteButtonClicked (MyGUI::Widget* sender);
|
||||
void onCharacterSelected (MyGUI::ComboBox* sender, size_t pos);
|
||||
// Slot selected (mouse click or arrow keys)
|
||||
void onSlotSelected (MyGUI::ListBox* sender, size_t pos);
|
||||
|
@ -51,6 +54,7 @@ namespace MWGui
|
|||
MyGUI::EditBox* mInfoText;
|
||||
MyGUI::Button* mOkButton;
|
||||
MyGUI::Button* mCancelButton;
|
||||
MyGUI::Button* mDeleteButton;
|
||||
MyGUI::ListBox* mSaveList;
|
||||
MyGUI::EditBox* mSaveNameEdit;
|
||||
MyGUI::Widget* mSpacer;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <components/esm/loadweap.hpp>
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/nullaction.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -126,6 +127,10 @@ namespace MWGui
|
|||
&& !base.get<ESM::Book>()->mBase->mData.mIsScroll)
|
||||
return false;
|
||||
|
||||
if ((mFilter & Filter_OnlyUsableItems) && typeid(*base.getClass().use(base)) == typeid(MWWorld::NullAction)
|
||||
&& base.getClass().getScript(base).empty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace MWGui
|
|||
static const int Filter_OnlyEnchanted = (1<<1);
|
||||
static const int Filter_OnlyEnchantable = (1<<2);
|
||||
static const int Filter_OnlyChargedSoulstones = (1<<3);
|
||||
static const int Filter_OnlyUsableItems = (1<<4); // Only items with a Use action
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,6 +16,24 @@
|
|||
|
||||
#include "tooltips.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
// Sorts a container descending by skill value. If skill value is equal, sorts ascending by skill ID.
|
||||
// pair <skill ID, skill value>
|
||||
bool sortSkills (const std::pair<int, int>& left, const std::pair<int, int>& right)
|
||||
{
|
||||
if (left == right)
|
||||
return false;
|
||||
|
||||
if (left.second > right.second)
|
||||
return true;
|
||||
else if (left.second < right.second)
|
||||
return false;
|
||||
|
||||
return left.first < right.first;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
|
@ -52,29 +70,17 @@ namespace MWGui
|
|||
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats (actor);
|
||||
|
||||
// NPC can train you in his best 3 skills
|
||||
std::vector< std::pair<int, int> > bestSkills;
|
||||
bestSkills.push_back (std::make_pair(-1, -1));
|
||||
bestSkills.push_back (std::make_pair(-1, -1));
|
||||
bestSkills.push_back (std::make_pair(-1, -1));
|
||||
std::vector< std::pair<int, int> > skills;
|
||||
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
int value = npcStats.getSkill (i).getBase ();
|
||||
|
||||
for (int j=0; j<3; ++j)
|
||||
{
|
||||
if (value > bestSkills[j].second)
|
||||
{
|
||||
if (j<2)
|
||||
{
|
||||
bestSkills[j+1] = bestSkills[j];
|
||||
}
|
||||
bestSkills[j] = std::make_pair(i, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
skills.push_back(std::make_pair(i, value));
|
||||
}
|
||||
|
||||
std::sort(skills.begin(), skills.end(), sortSkills);
|
||||
|
||||
MyGUI::EnumeratorWidgetPtr widgets = mTrainingOptions->getEnumerator ();
|
||||
MyGUI::Gui::getInstance ().destroyWidgets (widgets);
|
||||
|
||||
|
@ -86,20 +92,20 @@ namespace MWGui
|
|||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer
|
||||
(mPtr,pcStats.getSkill (bestSkills[i].first).getBase() * gmst.find("iTrainingMod")->getInt (),true);
|
||||
(mPtr,pcStats.getSkill (skills[i].first).getBase() * gmst.find("iTrainingMod")->getInt (),true);
|
||||
|
||||
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>("SandTextButton",
|
||||
MyGUI::IntCoord(5, 5+i*18, mTrainingOptions->getWidth()-10, 18), MyGUI::Align::Default);
|
||||
|
||||
button->setEnabled(price <= playerGold);
|
||||
button->setUserData(bestSkills[i].first);
|
||||
button->setUserData(skills[i].first);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onTrainingSelected);
|
||||
|
||||
button->setCaptionWithReplacing("#{" + ESM::Skill::sSkillNameIds[bestSkills[i].first] + "} - " + boost::lexical_cast<std::string>(price));
|
||||
button->setCaptionWithReplacing("#{" + ESM::Skill::sSkillNameIds[skills[i].first] + "} - " + boost::lexical_cast<std::string>(price));
|
||||
|
||||
button->setSize(button->getTextSize ().width+12, button->getSize().height);
|
||||
|
||||
ToolTips::createSkillToolTip (button, bestSkills[i].first);
|
||||
ToolTips::createSkillToolTip (button, skills[i].first);
|
||||
}
|
||||
|
||||
center();
|
||||
|
|
|
@ -4,17 +4,12 @@ namespace MWGui
|
|||
{
|
||||
|
||||
VideoWidget::VideoWidget()
|
||||
: mAllowSkipping(true)
|
||||
{
|
||||
eventKeyButtonPressed += MyGUI::newDelegate(this, &VideoWidget::onKeyPressed);
|
||||
|
||||
setNeedKeyFocus(true);
|
||||
}
|
||||
|
||||
void VideoWidget::playVideo(const std::string &video, bool allowSkipping)
|
||||
void VideoWidget::playVideo(const std::string &video)
|
||||
{
|
||||
mAllowSkipping = allowSkipping;
|
||||
|
||||
mPlayer.playVideo(video);
|
||||
|
||||
setImageTexture(mPlayer.getTextureName());
|
||||
|
@ -30,19 +25,13 @@ int VideoWidget::getVideoHeight()
|
|||
return mPlayer.getVideoHeight();
|
||||
}
|
||||
|
||||
void VideoWidget::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
|
||||
{
|
||||
if (_key == MyGUI::KeyCode::Escape && mAllowSkipping)
|
||||
mPlayer.stopVideo();
|
||||
}
|
||||
|
||||
bool VideoWidget::update()
|
||||
{
|
||||
mPlayer.update();
|
||||
return mPlayer.isPlaying();
|
||||
}
|
||||
|
||||
void VideoWidget::cleanup()
|
||||
void VideoWidget::stop()
|
||||
{
|
||||
mPlayer.close();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace MWGui
|
|||
{
|
||||
|
||||
/**
|
||||
* Widget that plays a video. Can be skipped by pressing Esc.
|
||||
* Widget that plays a video.
|
||||
*/
|
||||
class VideoWidget : public MyGUI::ImageBox
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ namespace MWGui
|
|||
|
||||
VideoWidget();
|
||||
|
||||
void playVideo (const std::string& video, bool allowSkipping);
|
||||
void playVideo (const std::string& video);
|
||||
|
||||
int getVideoWidth();
|
||||
int getVideoHeight();
|
||||
|
@ -26,15 +26,11 @@ namespace MWGui
|
|||
/// @return Is the video still playing?
|
||||
bool update();
|
||||
|
||||
/// Free video player resources (done automatically on destruction)
|
||||
void cleanup();
|
||||
/// Stop video and free resources (done automatically on destruction)
|
||||
void stop();
|
||||
|
||||
private:
|
||||
bool mAllowSkipping;
|
||||
|
||||
MWRender::VideoPlayer mPlayer;
|
||||
|
||||
void onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -202,8 +202,12 @@ namespace MWGui
|
|||
MyGUI::Align::Default, "Overlay");
|
||||
mVideoBackground->setImageTexture("black.png");
|
||||
mVideoBackground->setVisible(false);
|
||||
mVideoBackground->setNeedMouseFocus(true);
|
||||
mVideoBackground->setNeedKeyFocus(true);
|
||||
|
||||
mVideoWidget = mVideoBackground->createWidgetReal<VideoWidget>("ImageBox", 0,0,1,1, MyGUI::Align::Default);
|
||||
mVideoWidget->setNeedMouseFocus(true);
|
||||
mVideoWidget->setNeedKeyFocus(true);
|
||||
}
|
||||
|
||||
void WindowManager::initUI()
|
||||
|
@ -263,7 +267,7 @@ namespace MWGui
|
|||
mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
|
||||
trackWindow(mCompanionWindow, "companion");
|
||||
|
||||
mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Default,"Windows","");
|
||||
mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Default,"Windows");
|
||||
|
||||
mHud->setVisible(mHudEnabled);
|
||||
|
||||
|
@ -1559,7 +1563,15 @@ namespace MWGui
|
|||
|
||||
void WindowManager::playVideo(const std::string &name, bool allowSkipping)
|
||||
{
|
||||
mVideoWidget->playVideo("video\\" + name, allowSkipping);
|
||||
mVideoWidget->playVideo("video\\" + name);
|
||||
|
||||
mVideoWidget->eventKeyButtonPressed.clear();
|
||||
mVideoBackground->eventKeyButtonPressed.clear();
|
||||
if (allowSkipping)
|
||||
{
|
||||
mVideoWidget->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed);
|
||||
mVideoBackground->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed);
|
||||
}
|
||||
|
||||
// Turn off all rendering except for the GUI
|
||||
mRendering->getScene()->clearSpecialCaseRenderQueues();
|
||||
|
@ -1587,7 +1599,7 @@ namespace MWGui
|
|||
|
||||
mRendering->getWindow()->update();
|
||||
}
|
||||
mVideoWidget->cleanup();
|
||||
mVideoWidget->stop();
|
||||
|
||||
setCursorVisible(cursorWasVisible);
|
||||
|
||||
|
@ -1628,4 +1640,33 @@ namespace MWGui
|
|||
if(input == mCurrentModals.top())
|
||||
mCurrentModals.pop();
|
||||
}
|
||||
|
||||
void WindowManager::onVideoKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
|
||||
{
|
||||
if (_key == MyGUI::KeyCode::Escape)
|
||||
mVideoWidget->stop();
|
||||
}
|
||||
|
||||
void WindowManager::pinWindow(GuiWindow window)
|
||||
{
|
||||
switch (window)
|
||||
{
|
||||
case GW_Inventory:
|
||||
mInventoryWindow->setPinned(true);
|
||||
break;
|
||||
case GW_Map:
|
||||
mMap->setPinned(true);
|
||||
break;
|
||||
case GW_Magic:
|
||||
mSpellWindow->setPinned(true);
|
||||
break;
|
||||
case GW_Stats:
|
||||
mStatsWindow->setPinned(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
updateVisible();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include <MyGUI_KeyCode.h>
|
||||
#include <MyGUI_Types.h>
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Gui;
|
||||
|
@ -316,6 +319,8 @@ namespace MWGui
|
|||
\param input Pointer to the current modal, to ensure proper modal is removed **/
|
||||
virtual void removeCurrentModal(WindowModal* input);
|
||||
|
||||
virtual void pinWindow (MWGui::GuiWindow window);
|
||||
|
||||
private:
|
||||
bool mConsoleOnlyScripts;
|
||||
|
||||
|
@ -424,6 +429,9 @@ namespace MWGui
|
|||
void onCursorChange(const std::string& name);
|
||||
void onKeyFocusChanged(MyGUI::Widget* widget);
|
||||
|
||||
// Key pressed while playing a video
|
||||
void onVideoKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char);
|
||||
|
||||
void sizeVideo(int screenWidth, int screenHeight);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,6 +25,12 @@ namespace MWGui
|
|||
onPinToggled();
|
||||
}
|
||||
|
||||
void WindowPinnableBase::setPinned(bool pinned)
|
||||
{
|
||||
if (pinned != mPinned)
|
||||
onPinButtonClicked(mPinButton);
|
||||
}
|
||||
|
||||
void WindowPinnableBase::setPinButtonVisible(bool visible)
|
||||
{
|
||||
mPinButton->setVisible(visible);
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace MWGui
|
|||
public:
|
||||
WindowPinnableBase(const std::string& parLayout);
|
||||
bool pinned() { return mPinned; }
|
||||
void setPinned (bool pinned);
|
||||
void setPinButtonVisible(bool visible);
|
||||
|
||||
private:
|
||||
|
|
|
@ -117,7 +117,7 @@ namespace MWInput
|
|||
, mPreviewPOVDelay(0.f)
|
||||
, mTimeIdle(0.f)
|
||||
, mOverencumberedMessageDelay(0.f)
|
||||
, mAlwaysRunActive(false)
|
||||
, mAlwaysRunActive(Settings::Manager::getBool("always run", "Input"))
|
||||
, mAttemptJump(false)
|
||||
, mControlsDisabled(false)
|
||||
{
|
||||
|
@ -807,8 +807,9 @@ namespace MWInput
|
|||
if (MyGUI::InputManager::getInstance ().isModalAny())
|
||||
return;
|
||||
|
||||
// Toggle between game mode and journal mode
|
||||
if(!MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
|
||||
if((!MWBase::Environment::get().getWindowManager()->isGuiMode()
|
||||
|| MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Dialogue)
|
||||
&& MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Journal);
|
||||
|
@ -817,7 +818,6 @@ namespace MWInput
|
|||
{
|
||||
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||
}
|
||||
// .. but don't touch any other mode.
|
||||
}
|
||||
|
||||
void InputManager::quickKey (int index)
|
||||
|
@ -857,6 +857,8 @@ namespace MWInput
|
|||
{
|
||||
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
|
||||
mAlwaysRunActive = !mAlwaysRunActive;
|
||||
|
||||
Settings::Manager::setBool("always run", "Input", mAlwaysRunActive);
|
||||
}
|
||||
|
||||
void InputManager::resetIdleTime()
|
||||
|
@ -955,11 +957,6 @@ namespace MWInput
|
|||
mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE);
|
||||
}
|
||||
}
|
||||
|
||||
// Printscreen key should not be allowed because it's captured by system screenshot function
|
||||
// We check this explicitely here to fix up pre-0.26 config files. Can be removed after a few versions
|
||||
if (mInputBinder->getKeyBinding(mInputBinder->getControl(A_Screenshot), ICS::Control::INCREASE) == SDLK_PRINTSCREEN)
|
||||
mInputBinder->addKeyBinding(mInputBinder->getControl(A_Screenshot), SDLK_F12, ICS::Control::INCREASE);
|
||||
}
|
||||
|
||||
std::string InputManager::getActionDescription (int action)
|
||||
|
|
|
@ -832,6 +832,8 @@ bool CharacterController::updateWeaponState()
|
|||
MWRender::Animation::Group_UpperBody, false,
|
||||
weapSpeed, mAttackType+" max attack", mAttackType+" min hit",
|
||||
1.0f-complete, 0);
|
||||
|
||||
complete = 0.f;
|
||||
mUpperBodyState = UpperCharState_MaxAttackToMinHit;
|
||||
}
|
||||
else if (mHitState == CharState_KnockDown)
|
||||
|
@ -975,7 +977,8 @@ bool CharacterController::updateWeaponState()
|
|||
}
|
||||
|
||||
//if playing combat animation and lowerbody is not busy switch to whole body animation
|
||||
if((weaptype != WeapType_None || UpperCharState_UnEquipingWeap) && animPlaying)
|
||||
if((weaptype != WeapType_None || mUpperBodyState == UpperCharState_UnEquipingWeap
|
||||
|| mUpperBodyState == UpperCharState_EquipingWeap) && animPlaying)
|
||||
{
|
||||
if( mMovementState != CharState_None ||
|
||||
mJumpState != JumpState_None ||
|
||||
|
|
|
@ -929,7 +929,10 @@ namespace MWMechanics
|
|||
else if (type == OT_Murder)
|
||||
arg = store.find("iCrimeKilling")->getInt();
|
||||
else if (type == OT_Theft)
|
||||
{
|
||||
arg *= store.find("fCrimeStealing")->getFloat();
|
||||
arg = std::max(1, arg); // Minimum bounty of 1, in case items with zero value are stolen
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sCrimeMessage}");
|
||||
ptr.getClass().getNpcStats(ptr).setBounty(ptr.getClass().getNpcStats(ptr).getBounty()
|
||||
|
|
|
@ -356,28 +356,40 @@ void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScene
|
|||
objlist->mControllers.push_back(Ogre::Controller<Ogre::Real>(src, dest, func));
|
||||
|
||||
bool interior = !(mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior());
|
||||
bool quadratic = fallback->getFallbackBool("LightAttenuation_OutQuadInLin") ?
|
||||
!interior : fallback->getFallbackBool("LightAttenuation_UseQuadratic");
|
||||
|
||||
static bool outQuadInLin = fallback->getFallbackBool("LightAttenuation_OutQuadInLin");
|
||||
static bool useQuadratic = fallback->getFallbackBool("LightAttenuation_UseQuadratic");
|
||||
static float quadraticValue = fallback->getFallbackFloat("LightAttenuation_QuadraticValue");
|
||||
static float quadraticRadiusMult = fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
|
||||
static bool useLinear = fallback->getFallbackBool("LightAttenuation_UseLinear");
|
||||
static float linearRadiusMult = fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
|
||||
static float linearValue = fallback->getFallbackFloat("LightAttenuation_LinearValue");
|
||||
|
||||
bool quadratic = useQuadratic && (!outQuadInLin || !interior);
|
||||
|
||||
|
||||
// with the standard 1 / (c + d*l + d*d*q) equation the attenuation factor never becomes zero,
|
||||
// so we ignore lights if their attenuation falls below this factor.
|
||||
const float threshold = 0.03;
|
||||
|
||||
if (!quadratic)
|
||||
float quadraticAttenuation = 0;
|
||||
float linearAttenuation = 0;
|
||||
float activationRange = 0;
|
||||
if (quadratic)
|
||||
{
|
||||
float r = radius * fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult");
|
||||
float attenuation = fallback->getFallbackFloat("LightAttenuation_LinearValue") / r;
|
||||
float activationRange = 1.0f / (threshold * attenuation);
|
||||
olight->setAttenuation(activationRange, 0, attenuation, 0);
|
||||
float r = radius * quadraticRadiusMult;
|
||||
quadraticAttenuation = quadraticValue / std::pow(r, 2);
|
||||
activationRange = std::sqrt(1.0f / (threshold * quadraticAttenuation));
|
||||
}
|
||||
else
|
||||
if (useLinear)
|
||||
{
|
||||
float r = radius * fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult");
|
||||
float attenuation = fallback->getFallbackFloat("LightAttenuation_QuadraticValue") / std::pow(r, 2);
|
||||
float activationRange = std::sqrt(1.0f / (threshold * attenuation));
|
||||
olight->setAttenuation(activationRange, 0, 0, attenuation);
|
||||
float r = radius * linearRadiusMult;
|
||||
linearAttenuation = linearValue / r;
|
||||
activationRange = std::max(activationRange, 1.0f / (threshold * linearAttenuation));
|
||||
}
|
||||
|
||||
olight->setAttenuation(activationRange, 0, linearAttenuation, quadraticAttenuation);
|
||||
|
||||
// If there's an AttachLight bone, attach the light to that, otherwise put it in the center,
|
||||
if(objlist->mSkelBase && objlist->mSkelBase->getSkeleton()->hasBone("AttachLight"))
|
||||
objlist->mSkelBase->attachObjectToBone("AttachLight", olight);
|
||||
|
|
|
@ -73,7 +73,7 @@ void Objects::insertBegin(const MWWorld::Ptr& ptr)
|
|||
ptr.getRefData().setBaseNode(insert);
|
||||
}
|
||||
|
||||
void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh)
|
||||
void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool batch)
|
||||
{
|
||||
insertBegin(ptr);
|
||||
|
||||
|
@ -99,7 +99,7 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh)
|
|||
mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL;
|
||||
mBounds[ptr.getCell()].merge(bounds);
|
||||
|
||||
if(ptr.getTypeName() == typeid(ESM::Static).name() &&
|
||||
if(batch &&
|
||||
Settings::Manager::getBool("use static geometry", "Objects") &&
|
||||
anim->canBatch())
|
||||
{
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
, mRootNode(NULL)
|
||||
{}
|
||||
~Objects(){}
|
||||
void insertModel(const MWWorld::Ptr& ptr, const std::string &model);
|
||||
void insertModel(const MWWorld::Ptr& ptr, const std::string &model, bool batch=false);
|
||||
|
||||
ObjectAnimation* getAnimation(const MWWorld::Ptr &ptr);
|
||||
|
||||
|
|
|
@ -235,6 +235,18 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class OpClearInfoActor : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
MWBase::Environment::get().getDialogueManager()->clearInfoActor(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
|
@ -256,6 +268,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Dialogue::opcodeModFactionReaction, new OpModFactionReaction);
|
||||
interpreter.installSegment5 (Compiler::Dialogue::opcodeGetFactionReaction, new OpGetFactionReaction);
|
||||
interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActor, new OpClearInfoActor<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActorExplicit, new OpClearInfoActor<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ op 0x20028: RemoveSoulGem, explicit reference
|
|||
op 0x20029: PCRaiseRank, explicit reference
|
||||
op 0x2002a: PCLowerRank, explicit reference
|
||||
op 0x2002b: PCJoinFaction, explicit reference
|
||||
opcodes 0x2002c-0x3ffff unused
|
||||
op 0x2002c: MenuTest
|
||||
opcodes 0x2002d-0x3ffff unused
|
||||
|
||||
Segment 4:
|
||||
(not implemented yet)
|
||||
|
@ -393,5 +394,7 @@ op 0x2000241: onKnockoutExplicit
|
|||
op 0x2000242: ModFactionReaction
|
||||
op 0x2000243: GetFactionReaction
|
||||
op 0x2000244: Activate, explicit
|
||||
op 0x2000245: ClearInfoActor
|
||||
op 0x2000246: ClearInfoActor, explicit
|
||||
|
||||
opcodes 0x2000245-0x3ffffff unused
|
||||
opcodes 0x2000247-0x3ffffff unused
|
||||
|
|
|
@ -162,6 +162,47 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
class OpMenuTest : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
int arg=0;
|
||||
if(arg0>0)
|
||||
{
|
||||
arg = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
}
|
||||
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
MWGui::GuiMode modes[] = { MWGui::GM_Inventory, MWGui::GM_Container };
|
||||
|
||||
for (int i=0; i<2; ++i)
|
||||
{
|
||||
if (MWBase::Environment::get().getWindowManager()->containsMode(modes[i]))
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(modes[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MWGui::GuiWindow gw = MWGui::GW_None;
|
||||
if (arg == 3)
|
||||
gw = MWGui::GW_Stats;
|
||||
if (arg == 4)
|
||||
gw = MWGui::GW_Inventory;
|
||||
if (arg == 5)
|
||||
gw = MWGui::GW_Magic;
|
||||
if (arg == 6)
|
||||
gw = MWGui::GW_Map;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->pinWindow(gw);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
|
@ -200,6 +241,7 @@ namespace MWScript
|
|||
|
||||
interpreter.installSegment5 (Compiler::Gui::opcodeShowMap, new OpShowMap);
|
||||
interpreter.installSegment5 (Compiler::Gui::opcodeFillMap, new OpFillMap);
|
||||
interpreter.installSegment3 (Compiler::Gui::opcodeMenuTest, new OpMenuTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,9 +54,28 @@ void MWState::Character::addSlot (const ESM::SavedGame& profile)
|
|||
Slot slot;
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << mNext++;
|
||||
|
||||
// The profile description is user-supplied, so we need to escape the path
|
||||
for (std::string::const_iterator it = profile.mDescription.begin(); it != profile.mDescription.end(); ++it)
|
||||
{
|
||||
if (std::isalnum(*it)) // Ignores multibyte characters and non alphanumeric characters
|
||||
stream << *it;
|
||||
else
|
||||
stream << "_";
|
||||
}
|
||||
|
||||
slot.mPath = mPath / stream.str();
|
||||
|
||||
// Append an index if necessary to ensure a unique file
|
||||
int i=0;
|
||||
while (boost::filesystem::exists(slot.mPath))
|
||||
{
|
||||
std::ostringstream test;
|
||||
test << stream.str();
|
||||
test << " - " << ++i;
|
||||
slot.mPath = mPath / test.str();
|
||||
}
|
||||
|
||||
slot.mProfile = profile;
|
||||
slot.mTimeStamp = std::time (0);
|
||||
|
||||
|
@ -64,7 +83,7 @@ void MWState::Character::addSlot (const ESM::SavedGame& profile)
|
|||
}
|
||||
|
||||
MWState::Character::Character (const boost::filesystem::path& saves, const std::string& game)
|
||||
: mPath (saves), mNext (0)
|
||||
: mPath (saves)
|
||||
{
|
||||
if (!boost::filesystem::is_directory (mPath))
|
||||
{
|
||||
|
@ -82,13 +101,6 @@ MWState::Character::Character (const boost::filesystem::path& saves, const std::
|
|||
addSlot (slotPath, game);
|
||||
}
|
||||
catch (...) {} // ignoring bad saved game files for now
|
||||
|
||||
std::istringstream stream (slotPath.filename().string());
|
||||
|
||||
int index = 0;
|
||||
|
||||
if ((stream >> index) && index>=mNext)
|
||||
mNext = index+1;
|
||||
}
|
||||
|
||||
std::sort (mSlots.begin(), mSlots.end());
|
||||
|
|
|
@ -26,7 +26,6 @@ namespace MWState
|
|||
|
||||
boost::filesystem::path mPath;
|
||||
std::vector<Slot> mSlots;
|
||||
int mNext;
|
||||
|
||||
void addSlot (const boost::filesystem::path& path, const std::string& game);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
MWState::CharacterManager::CharacterManager (const boost::filesystem::path& saves,
|
||||
const std::string& game)
|
||||
: mPath (saves), mNext (0), mCurrent (0), mGame (game)
|
||||
: mPath (saves), mCurrent (0), mGame (game)
|
||||
{
|
||||
if (!boost::filesystem::is_directory (mPath))
|
||||
{
|
||||
|
@ -28,21 +28,14 @@ MWState::CharacterManager::CharacterManager (const boost::filesystem::path& save
|
|||
if (character.begin()!=character.end())
|
||||
mCharacters.push_back (character);
|
||||
}
|
||||
|
||||
std::istringstream stream (characterDir.filename().string());
|
||||
|
||||
int index = 0;
|
||||
|
||||
if ((stream >> index) && index>=mNext)
|
||||
mNext = index+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create)
|
||||
MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create, const std::string& name)
|
||||
{
|
||||
if (!mCurrent && create)
|
||||
createCharacter();
|
||||
createCharacter(name);
|
||||
|
||||
return mCurrent;
|
||||
}
|
||||
|
@ -63,13 +56,31 @@ void MWState::CharacterManager::deleteSlot(const MWState::Character *character,
|
|||
}
|
||||
}
|
||||
|
||||
void MWState::CharacterManager::createCharacter()
|
||||
void MWState::CharacterManager::createCharacter(const std::string& name)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << mNext++;
|
||||
|
||||
// The character name is user-supplied, so we need to escape the path
|
||||
for (std::string::const_iterator it = name.begin(); it != name.end(); ++it)
|
||||
{
|
||||
if (std::isalnum(*it)) // Ignores multibyte characters and non alphanumeric characters
|
||||
stream << *it;
|
||||
else
|
||||
stream << "_";
|
||||
}
|
||||
|
||||
boost::filesystem::path path = mPath / stream.str();
|
||||
|
||||
// Append an index if necessary to ensure a unique directory
|
||||
int i=0;
|
||||
while (boost::filesystem::exists(path))
|
||||
{
|
||||
std::ostringstream test;
|
||||
test << stream.str();
|
||||
test << " - " << ++i;
|
||||
path = mPath / test.str();
|
||||
}
|
||||
|
||||
mCharacters.push_back (Character (path, mGame));
|
||||
|
||||
mCurrent = &mCharacters.back();
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace MWState
|
|||
class CharacterManager
|
||||
{
|
||||
boost::filesystem::path mPath;
|
||||
int mNext;
|
||||
|
||||
// Uses std::list, so that mCurrent stays valid when characters are deleted
|
||||
std::list<Character> mCharacters;
|
||||
|
@ -32,13 +31,15 @@ namespace MWState
|
|||
|
||||
CharacterManager (const boost::filesystem::path& saves, const std::string& game);
|
||||
|
||||
Character *getCurrentCharacter (bool create = true);
|
||||
Character *getCurrentCharacter (bool create, const std::string& name);
|
||||
///< \param create Create a new character, if there is no current character.
|
||||
/// \param name The character name to use in case a new character is created.
|
||||
|
||||
void deleteSlot(const MWState::Character *character, const MWState::Slot *slot);
|
||||
|
||||
void createCharacter();
|
||||
void createCharacter(const std::string& name);
|
||||
///< Create new character within saved game management
|
||||
/// \param name Name for the character (does not need to be unique)
|
||||
|
||||
void setCurrentCharacter (const Character *character);
|
||||
|
||||
|
|
|
@ -184,9 +184,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
encoded->read(&profile.mScreenshot[0], encoded->size());
|
||||
|
||||
if (!slot)
|
||||
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
|
||||
slot = getCurrentCharacter()->createSlot (profile);
|
||||
else
|
||||
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
|
||||
slot = getCurrentCharacter()->updateSlot (slot, profile);
|
||||
|
||||
boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);
|
||||
|
||||
|
@ -233,6 +233,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
|
||||
writer.close();
|
||||
|
||||
if (stream.fail())
|
||||
throw std::runtime_error("Write operation failed");
|
||||
|
||||
Settings::Manager::setString ("character", "Saves",
|
||||
slot->mPath.parent_path().filename().string());
|
||||
}
|
||||
|
@ -246,6 +249,10 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
std::vector<std::string> buttons;
|
||||
buttons.push_back("#{sOk}");
|
||||
MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons);
|
||||
|
||||
// If no file was written, clean up the slot
|
||||
if (slot && !boost::filesystem::exists(slot->mPath))
|
||||
getCurrentCharacter()->deleteSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +419,10 @@ void MWState::StateManager::deleteGame(const MWState::Character *character, cons
|
|||
|
||||
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)
|
||||
{
|
||||
return mCharacterManager.getCurrentCharacter (create);
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
std::string name = player.getClass().getName(player);
|
||||
|
||||
return mCharacterManager.getCurrentCharacter (create, name);
|
||||
}
|
||||
|
||||
MWState::StateManager::CharacterIterator MWState::StateManager::characterBegin()
|
||||
|
@ -433,11 +443,12 @@ void MWState::StateManager::update (float duration)
|
|||
if (mAskLoadRecent)
|
||||
{
|
||||
int iButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
|
||||
if(iButton==0)
|
||||
MWState::Character *curCharacter = getCurrentCharacter(false);
|
||||
if(iButton==0 && curCharacter)
|
||||
{
|
||||
mAskLoadRecent = false;
|
||||
//Load last saved game for current character
|
||||
MWState::Character *curCharacter = getCurrentCharacter();
|
||||
|
||||
MWState::Slot lastSave = *curCharacter->begin();
|
||||
loadGame(curCharacter, &lastSave);
|
||||
}
|
||||
|
|
|
@ -99,6 +99,13 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
|
|||
}
|
||||
it->second->load(esm, id);
|
||||
|
||||
// DELE can also occur after the usual subrecords
|
||||
if (esm.isNextSub("DELE")) {
|
||||
esm.skipRecord();
|
||||
it->second->eraseStatic(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.val==ESM::REC_DIAL) {
|
||||
dialogue = const_cast<ESM::Dialogue*>(mDialogs.find(id));
|
||||
} else {
|
||||
|
|
|
@ -193,6 +193,11 @@ namespace MWWorld
|
|||
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||
Ogre::Vector3 position(refpos.pos);
|
||||
|
||||
// Early-out for totally static creatures
|
||||
// (Not sure if gravity should still apply?)
|
||||
if (!ptr.getClass().canWalk(ptr) && !isFlying && !ptr.getClass().canSwim(ptr))
|
||||
return position;
|
||||
|
||||
/* Anything to collide with? */
|
||||
OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle());
|
||||
if(!physicActor || !physicActor->getCollisionMode())
|
||||
|
|
|
@ -1703,14 +1703,15 @@ namespace MWWorld
|
|||
|
||||
Ogre::Vector3 orig =
|
||||
Ogre::Vector3(pos.pos);
|
||||
orig.z += 20;
|
||||
Ogre::Vector3 dir = Ogre::Vector3(0, 0, -1);
|
||||
|
||||
float len = (pos.pos[2] >= 0) ? pos.pos[2] : -pos.pos[2];
|
||||
len += 100.0;
|
||||
float len = 100.0;
|
||||
|
||||
std::pair<bool, Ogre::Vector3> hit =
|
||||
mPhysics->castRay(orig, dir, len);
|
||||
pos.pos[2] = hit.second.z;
|
||||
if (hit.first)
|
||||
pos.pos[2] = hit.second.z;
|
||||
|
||||
// copy the object and set its count
|
||||
int origCount = object.getRefData().getCount();
|
||||
|
|
|
@ -181,6 +181,7 @@ namespace Compiler
|
|||
opcodeSameFactionExplicit);
|
||||
extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction);
|
||||
extensions.registerFunction("getfactionreaction", 'l', "ccl", opcodeGetFactionReaction);
|
||||
extensions.registerInstruction("clearinfoactor", "", opcodeClearInfoActor, opcodeClearInfoActorExplicit);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,6 +216,7 @@ namespace Compiler
|
|||
|
||||
extensions.registerInstruction ("showmap", "S", opcodeShowMap);
|
||||
extensions.registerInstruction ("fillmap", "", opcodeFillMap);
|
||||
extensions.registerInstruction ("menutest", "/l", opcodeMenuTest);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,8 @@ namespace Compiler
|
|||
const int opcodeSameFactionExplicit = 0x20001b6;
|
||||
const int opcodeModFactionReaction = 0x2000242;
|
||||
const int opcodeGetFactionReaction = 0x2000243;
|
||||
const int opcodeClearInfoActor = 0x2000245;
|
||||
const int opcodeClearInfoActorExplicit = 0x2000246;
|
||||
}
|
||||
|
||||
namespace Gui
|
||||
|
@ -175,6 +177,7 @@ namespace Compiler
|
|||
const int opcodeToggleFullHelp = 0x2000151;
|
||||
const int opcodeShowMap = 0x20001a0;
|
||||
const int opcodeFillMap = 0x20001a1;
|
||||
const int opcodeMenuTest = 0x2002c;
|
||||
}
|
||||
|
||||
namespace Misc
|
||||
|
|
|
@ -239,7 +239,7 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex &index, const
|
|||
return false;
|
||||
|
||||
EsmFile *file = item(index.row());
|
||||
QString fileName = file->filePath();
|
||||
QString fileName = file->fileName();
|
||||
bool success = false;
|
||||
|
||||
switch(role)
|
||||
|
@ -266,7 +266,7 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex &index, const
|
|||
|
||||
if (success)
|
||||
{
|
||||
success = setCheckState(fileName, value.toBool());
|
||||
success = setCheckState(file->filePath(), value.toBool());
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
}
|
||||
|
@ -277,19 +277,19 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex &index, const
|
|||
int checkValue = value.toInt();
|
||||
bool success = false;
|
||||
bool setState = false;
|
||||
if ((checkValue==Qt::Checked) && !isChecked(fileName))
|
||||
if ((checkValue==Qt::Checked) && !isChecked(file->filePath()))
|
||||
{
|
||||
setState = true;
|
||||
success = true;
|
||||
}
|
||||
else if ((checkValue == Qt::Checked) && isChecked (fileName))
|
||||
else if ((checkValue == Qt::Checked) && isChecked (file->filePath()))
|
||||
setState = true;
|
||||
else if (checkValue == Qt::Unchecked)
|
||||
setState = true;
|
||||
|
||||
if (setState)
|
||||
{
|
||||
setCheckState(fileName, success);
|
||||
setCheckState(file->filePath(), success);
|
||||
emit dataChanged(index, index);
|
||||
|
||||
}
|
||||
|
@ -517,10 +517,10 @@ void ContentSelectorModel::ContentModel::sortFiles()
|
|||
}
|
||||
}
|
||||
|
||||
bool ContentSelectorModel::ContentModel::isChecked(const QString& name) const
|
||||
bool ContentSelectorModel::ContentModel::isChecked(const QString& filepath) const
|
||||
{
|
||||
if (mCheckStates.contains(name))
|
||||
return (mCheckStates[name] == Qt::Checked);
|
||||
if (mCheckStates.contains(filepath))
|
||||
return (mCheckStates[filepath] == Qt::Checked);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -543,12 +543,12 @@ void ContentSelectorModel::ContentModel::refreshModel()
|
|||
emit dataChanged (index(0,0), index(rowCount()-1,0));
|
||||
}
|
||||
|
||||
bool ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool checkState)
|
||||
bool ContentSelectorModel::ContentModel::setCheckState(const QString &filepath, bool checkState)
|
||||
{
|
||||
if (name.isEmpty())
|
||||
if (filepath.isEmpty())
|
||||
return false;
|
||||
|
||||
const EsmFile *file = item(name);
|
||||
const EsmFile *file = item(filepath);
|
||||
|
||||
if (!file)
|
||||
return false;
|
||||
|
@ -558,8 +558,8 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool
|
|||
if (checkState)
|
||||
state = Qt::Checked;
|
||||
|
||||
mCheckStates[name] = state;
|
||||
emit dataChanged(indexFromItem(item(name)), indexFromItem(item(name)));
|
||||
mCheckStates[filepath] = state;
|
||||
emit dataChanged(indexFromItem(item(filepath)), indexFromItem(item(filepath)));
|
||||
|
||||
if (file->isGameFile())
|
||||
refreshModel();
|
||||
|
@ -586,7 +586,10 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool
|
|||
{
|
||||
foreach (const EsmFile *downstreamFile, mFiles)
|
||||
{
|
||||
if (downstreamFile->gameFiles().contains(name))
|
||||
QFileInfo fileInfo(filepath);
|
||||
QString filename = fileInfo.fileName();
|
||||
|
||||
if (downstreamFile->gameFiles().contains(filename))
|
||||
{
|
||||
if (mCheckStates.contains(downstreamFile->filePath()))
|
||||
mCheckStates[downstreamFile->filePath()] = Qt::Unchecked;
|
||||
|
|
|
@ -45,8 +45,8 @@ namespace ContentSelectorModel
|
|||
const EsmFile *item(const QString &name) const;
|
||||
|
||||
bool isEnabled (QModelIndex index) const;
|
||||
bool isChecked(const QString &name) const;
|
||||
bool setCheckState(const QString &name, bool isChecked);
|
||||
bool isChecked(const QString &filepath) const;
|
||||
bool setCheckState(const QString &filepath, bool isChecked);
|
||||
void setCheckStates (const QStringList &fileList, bool isChecked);
|
||||
ContentFileList checkedItems() const;
|
||||
void uncheckAll();
|
||||
|
|
|
@ -53,6 +53,8 @@ namespace ContentSelectorModel
|
|||
inline QDateTime modified() const { return mModified; }
|
||||
inline float format() const { return mFormat; }
|
||||
inline QString filePath() const { return mPath; }
|
||||
|
||||
/// @note Contains file names, not paths.
|
||||
inline const QStringList &gameFiles() const { return mGameFiles; }
|
||||
inline QString description() const { return mDescription; }
|
||||
inline QString toolTip() const { return sToolTip.arg(mAuthor)
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace ESM
|
|||
|
||||
void Potion::load(ESMReader &esm)
|
||||
{
|
||||
mModel = esm.getHNString("MODL");
|
||||
mModel = esm.getHNOString("MODL");
|
||||
mIcon = esm.getHNOString("TEXT"); // not ITEX here for some reason
|
||||
mScript = esm.getHNOString("SCRI");
|
||||
mName = esm.getHNOString("FNAM");
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace ESM
|
|||
|
||||
void Static::load(ESMReader &esm)
|
||||
{
|
||||
mPersistent = esm.getRecordFlags() & 0x0400;
|
||||
mModel = esm.getHNString("MODL");
|
||||
}
|
||||
void Static::save(ESMWriter &esm) const
|
||||
|
|
|
@ -26,6 +26,8 @@ struct Static
|
|||
|
||||
std::string mId, mModel;
|
||||
|
||||
bool mPersistent;
|
||||
|
||||
void load(ESMReader &esm);
|
||||
void save(ESMWriter &esm) const;
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ namespace Translation
|
|||
boost::filesystem::ifstream stream (
|
||||
dataFileCollections.getCollection (extension).getPath (fileName));
|
||||
|
||||
// Configure the stream to throw exception upon error
|
||||
stream.exceptions ( boost::filesystem::ifstream::failbit | boost::filesystem::ifstream::badbit );
|
||||
|
||||
if (!stream.is_open())
|
||||
throw std::runtime_error ("failed to open translation file: " + fileName);
|
||||
|
||||
|
@ -41,6 +44,7 @@ namespace Translation
|
|||
|
||||
void Storage::loadDataFromStream(ContainerType& container, std::istream& stream)
|
||||
{
|
||||
// NOTE: does not handle failbit/badbit. stream must be set up beforehand to throw in these cases.
|
||||
std::string line;
|
||||
while (!stream.eof())
|
||||
{
|
||||
|
|
|
@ -4,28 +4,28 @@
|
|||
<Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 588 433" name="_Main">
|
||||
<Property key="MinSize" value="380 230"/>
|
||||
|
||||
<Widget type="Widget" skin="MW_Box" position="8 8 415 381" align="Stretch" name="Client"/>
|
||||
<Widget type="Widget" skin="MW_Box" position="8 8 381 381" align="Stretch" name="Client"/>
|
||||
|
||||
<Widget type="Widget" position="13 13 391 371" align="Left Top Stretch">
|
||||
<Widget type="BookPage" skin="MW_BookPage" position="0 0 391 371" name="History" align="Left Top Stretch">
|
||||
<Widget type="Widget" position="13 13 357 371" align="Left Top Stretch">
|
||||
<Widget type="BookPage" skin="MW_BookPage" position="0 0 357 371" name="History" align="Left Top Stretch">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="MWScrollBar" skin="MW_VScroll" position="404 13 14 371" align="Right VStretch" name="VScroll">
|
||||
<Widget type="MWScrollBar" skin="MW_VScroll" position="370 13 14 371" align="Right VStretch" name="VScroll">
|
||||
<Property key="Visible" value="false"/>
|
||||
</Widget>
|
||||
|
||||
<!-- The disposition bar-->
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Blue" position="432 8 132 18"
|
||||
<Widget type="ProgressBar" skin="MW_EnergyBar_Blue" position="398 8 166 18"
|
||||
align="Right Top" name="Disposition">
|
||||
<Widget type="EditBox" skin="MW_DispositionEdit" position_real="0 0 1 1" align="Stretch" name="DispositionText"/>
|
||||
</Widget>
|
||||
<!-- The list of topics -->
|
||||
<Widget type="MWList" skin="MW_SimpleList" position="432 31 132 328" name="TopicsList" align="Right VStretch">
|
||||
<Widget type="MWList" skin="MW_SimpleList" position="398 31 166 328" name="TopicsList" align="Right VStretch">
|
||||
</Widget>
|
||||
|
||||
<!-- The Goodbye button -->
|
||||
<Widget type="Button" skin="MW_Button" position="432 366 132 23" name="ByeButton" align="Right Bottom">
|
||||
<Widget type="Button" skin="MW_Button" position="398 366 166 23" name="ByeButton" align="Right Bottom">
|
||||
<Property key="Caption" value="#{sGoodbye}"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="VBox" skin="MW_Dialog" layer="Windows" position="0 0 600 400" name="_Main">
|
||||
<Property key="Padding" value="8"/>
|
||||
<Property key="Spacing" value="6"/>
|
||||
<Property key="Padding" value="8"/>
|
||||
<Property key="Spacing" value="6"/>
|
||||
|
||||
<Widget type="HBox" skin="">
|
||||
<UserString key="HStretch" value="true"/>
|
||||
|
@ -49,10 +49,14 @@
|
|||
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="">
|
||||
<UserString key="HStretch" value="true"/>
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" name="DeleteButton">
|
||||
<Property key="Caption" value="#{sDeleteGame}"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="EditBox" skin="MW_TextEdit" name="SaveNameEdit">
|
||||
<UserString key="HStretch" value="true"/>
|
||||
<UserString key="VStretch" value="true"/>
|
||||
|
|
|
@ -168,6 +168,8 @@ camera y multiplier = 1.0
|
|||
|
||||
ui y multiplier = 1.0
|
||||
|
||||
always run = false
|
||||
|
||||
[Game]
|
||||
# Always use the most powerful attack when striking with a weapon (chop, slash or thrust)
|
||||
best attack = false
|
||||
|
|
Loading…
Reference in a new issue