mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Merge remote-tracking branch 'upstream/master' into osgshadow-test-vdsm
This commit is contained in:
commit
0f6f097cf2
36 changed files with 409 additions and 221 deletions
|
@ -79,12 +79,14 @@ void OMW::Engine::executeLocalScripts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OMW::Engine::frame(float frametime)
|
bool OMW::Engine::frame(float frametime)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mStartTick = mViewer->getStartTick();
|
mStartTick = mViewer->getStartTick();
|
||||||
|
|
||||||
|
mEnvironment.setFrameDuration(frametime);
|
||||||
|
|
||||||
// update input
|
// update input
|
||||||
mEnvironment.getInputManager()->update(frametime, false);
|
mEnvironment.getInputManager()->update(frametime, false);
|
||||||
|
|
||||||
|
@ -92,7 +94,7 @@ void OMW::Engine::frame(float frametime)
|
||||||
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
|
// If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
|
||||||
// and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
|
// and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
|
||||||
if (!mEnvironment.getInputManager()->isWindowVisible())
|
if (!mEnvironment.getInputManager()->isWindowVisible())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// sound
|
// sound
|
||||||
if (mUseSound)
|
if (mUseSound)
|
||||||
|
@ -187,8 +189,9 @@ void OMW::Engine::frame(float frametime)
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << "Error in framelistener: " << e.what() << std::endl;
|
std::cerr << "Error in frame: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||||
|
@ -686,17 +689,9 @@ void OMW::Engine::go()
|
||||||
frameTimer.setStartTick();
|
frameTimer.setStartTick();
|
||||||
dt = std::min(dt, 0.2);
|
dt = std::min(dt, 0.2);
|
||||||
|
|
||||||
bool guiActive = mEnvironment.getWindowManager()->isGuiMode();
|
|
||||||
if (!guiActive)
|
|
||||||
simulationTime += dt;
|
|
||||||
|
|
||||||
mViewer->advance(simulationTime);
|
mViewer->advance(simulationTime);
|
||||||
|
|
||||||
mEnvironment.setFrameDuration(dt);
|
if (!frame(dt))
|
||||||
|
|
||||||
frame(dt);
|
|
||||||
|
|
||||||
if (!mEnvironment.getInputManager()->isWindowVisible())
|
|
||||||
{
|
{
|
||||||
OpenThreads::Thread::microSleep(5000);
|
OpenThreads::Thread::microSleep(5000);
|
||||||
continue;
|
continue;
|
||||||
|
@ -709,6 +704,10 @@ void OMW::Engine::go()
|
||||||
mEnvironment.getWorld()->updateWindowManager();
|
mEnvironment.getWorld()->updateWindowManager();
|
||||||
|
|
||||||
mViewer->renderingTraversals();
|
mViewer->renderingTraversals();
|
||||||
|
|
||||||
|
bool guiActive = mEnvironment.getWindowManager()->isGuiMode();
|
||||||
|
if (!guiActive)
|
||||||
|
simulationTime += dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
mEnvironment.limitFrameRate(frameTimer.time_s());
|
mEnvironment.limitFrameRate(frameTimer.time_s());
|
||||||
|
|
|
@ -118,7 +118,7 @@ namespace OMW
|
||||||
|
|
||||||
void executeLocalScripts();
|
void executeLocalScripts();
|
||||||
|
|
||||||
void frame (float dt);
|
bool frame (float dt);
|
||||||
|
|
||||||
/// Load settings from various files, returns the path to the user settings file
|
/// Load settings from various files, returns the path to the user settings file
|
||||||
std::string loadSettings (Settings::Manager & settings);
|
std::string loadSettings (Settings::Manager & settings);
|
||||||
|
|
|
@ -140,7 +140,7 @@ namespace MWBase
|
||||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||||
/// @param container The container the item is in; may be empty for an item in the world
|
/// @param container The container the item is in; may be empty for an item in the world
|
||||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
||||||
int count) = 0;
|
int count, bool alarm = true) = 0;
|
||||||
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
||||||
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) = 0;
|
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) = 0;
|
||||||
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
||||||
|
@ -238,6 +238,7 @@ namespace MWBase
|
||||||
/// Has the player stolen this item from the given owner?
|
/// Has the player stolen this item from the given owner?
|
||||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
||||||
|
|
||||||
|
virtual bool isBoundItem(const MWWorld::Ptr& item) = 0;
|
||||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) = 0;
|
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) = 0;
|
||||||
|
|
||||||
/// Turn actor into werewolf or normal form.
|
/// Turn actor into werewolf or normal form.
|
||||||
|
@ -250,7 +251,6 @@ namespace MWBase
|
||||||
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0;
|
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0;
|
||||||
|
|
||||||
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0;
|
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0;
|
||||||
|
|
||||||
virtual bool isAttackPrepairing(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isAttackPrepairing(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual bool isRunning(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isRunning(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
|
@ -77,6 +77,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
void DialogueManager::parseText (const std::string& text)
|
void DialogueManager::parseText (const std::string& text)
|
||||||
{
|
{
|
||||||
|
updateActorKnownTopics();
|
||||||
std::vector<HyperTextParser::Token> hypertext = HyperTextParser::parseHyperText(text);
|
std::vector<HyperTextParser::Token> hypertext = HyperTextParser::parseHyperText(text);
|
||||||
|
|
||||||
for (std::vector<HyperTextParser::Token>::iterator tok = hypertext.begin(); tok != hypertext.end(); ++tok)
|
for (std::vector<HyperTextParser::Token>::iterator tok = hypertext.begin(); tok != hypertext.end(); ++tok)
|
||||||
|
@ -145,18 +146,13 @@ namespace MWDialogue
|
||||||
// TODO play sound
|
// TODO play sound
|
||||||
}
|
}
|
||||||
|
|
||||||
// first topics update so that parseText knows the keywords to highlight
|
|
||||||
updateActorKnownTopics();
|
|
||||||
|
|
||||||
parseText (info->mResponse);
|
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||||
callback->addResponse("", Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
callback->addResponse("", Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||||
executeScript (info->mResultScript, mActor);
|
executeScript (info->mResultScript, mActor);
|
||||||
mLastTopic = it->mId;
|
mLastTopic = it->mId;
|
||||||
|
|
||||||
// update topics again to accommodate changes resulting from executeScript
|
parseText (info->mResponse);
|
||||||
updateActorKnownTopics();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -252,8 +248,6 @@ namespace MWDialogue
|
||||||
const ESM::DialInfo* info = filter.search(dialogue, true);
|
const ESM::DialInfo* info = filter.search(dialogue, true);
|
||||||
if (info)
|
if (info)
|
||||||
{
|
{
|
||||||
parseText (info->mResponse);
|
|
||||||
|
|
||||||
std::string title;
|
std::string title;
|
||||||
if (dialogue.mType==ESM::Dialogue::Persuasion)
|
if (dialogue.mType==ESM::Dialogue::Persuasion)
|
||||||
{
|
{
|
||||||
|
@ -292,6 +286,8 @@ namespace MWDialogue
|
||||||
|
|
||||||
executeScript (info->mResultScript, mActor);
|
executeScript (info->mResultScript, mActor);
|
||||||
|
|
||||||
|
parseText (info->mResponse);
|
||||||
|
|
||||||
mLastTopic = topic;
|
mLastTopic = topic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,10 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/dialoguemanager.hpp"
|
#include "../mwbase/dialoguemanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/pickpocket.hpp"
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "countdialog.hpp"
|
#include "countdialog.hpp"
|
||||||
|
@ -33,7 +31,6 @@ namespace MWGui
|
||||||
ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop)
|
ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop)
|
||||||
: WindowBase("openmw_container_window.layout")
|
: WindowBase("openmw_container_window.layout")
|
||||||
, mDragAndDrop(dragAndDrop)
|
, mDragAndDrop(dragAndDrop)
|
||||||
, mPickpocketDetected(false)
|
|
||||||
, mSortModel(NULL)
|
, mSortModel(NULL)
|
||||||
, mModel(NULL)
|
, mModel(NULL)
|
||||||
, mSelectedItem(-1)
|
, mSelectedItem(-1)
|
||||||
|
@ -55,9 +52,8 @@ namespace MWGui
|
||||||
|
|
||||||
void ContainerWindow::onItemSelected(int index)
|
void ContainerWindow::onItemSelected(int index)
|
||||||
{
|
{
|
||||||
if (mDragAndDrop->mIsOnDragAndDrop)
|
if (mDragAndDrop->mIsOnDragAndDrop && mModel)
|
||||||
{
|
{
|
||||||
if (mModel && mModel->allowedToInsertItems())
|
|
||||||
dropItem();
|
dropItem();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -100,39 +96,20 @@ namespace MWGui
|
||||||
|
|
||||||
void ContainerWindow::dropItem()
|
void ContainerWindow::dropItem()
|
||||||
{
|
{
|
||||||
if (mPtr.getTypeName() == typeid(ESM::Container).name())
|
bool success = mModel->onDropItem(mDragAndDrop->mItem.mBase, mDragAndDrop->mDraggedCount);
|
||||||
{
|
|
||||||
// check container organic flag
|
|
||||||
MWWorld::LiveCellRef<ESM::Container>* ref = mPtr.get<ESM::Container>();
|
|
||||||
if (ref->mBase->mFlags & ESM::Container::Organic)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->
|
|
||||||
messageBox("#{sContentsMessage2}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that we don't exceed container capacity
|
|
||||||
MWWorld::Ptr item = mDragAndDrop->mItem.mBase;
|
|
||||||
float weight = item.getClass().getWeight(item) * mDragAndDrop->mDraggedCount;
|
|
||||||
if (mPtr.getClass().getCapacity(mPtr) < mPtr.getClass().getEncumbrance(mPtr) + weight)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sContentsMessage3}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (success)
|
||||||
mDragAndDrop->drop(mModel, mItemView);
|
mDragAndDrop->drop(mModel, mItemView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::onBackgroundSelected()
|
void ContainerWindow::onBackgroundSelected()
|
||||||
{
|
{
|
||||||
if (mDragAndDrop->mIsOnDragAndDrop && mModel && mModel->allowedToInsertItems())
|
if (mDragAndDrop->mIsOnDragAndDrop && mModel)
|
||||||
dropItem();
|
dropItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::setPtr(const MWWorld::Ptr& container)
|
void ContainerWindow::setPtr(const MWWorld::Ptr& container)
|
||||||
{
|
{
|
||||||
mPickpocketDetected = false;
|
|
||||||
mPtr = container;
|
mPtr = container;
|
||||||
|
|
||||||
bool loot = mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead();
|
bool loot = mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead();
|
||||||
|
@ -142,8 +119,7 @@ namespace MWGui
|
||||||
if (mPtr.getClass().isNpc() && !loot)
|
if (mPtr.getClass().isNpc() && !loot)
|
||||||
{
|
{
|
||||||
// we are stealing stuff
|
// we are stealing stuff
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
mModel = new PickpocketItemModel(mPtr, new InventoryItemModel(container),
|
||||||
mModel = new PickpocketItemModel(player, new InventoryItemModel(container),
|
|
||||||
!mPtr.getClass().getCreatureStats(mPtr).getKnockedDown());
|
!mPtr.getClass().getCreatureStats(mPtr).getKnockedDown());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -178,24 +154,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
WindowBase::onClose();
|
WindowBase::onClose();
|
||||||
|
|
||||||
if (dynamic_cast<PickpocketItemModel*>(mModel)
|
mModel->onClose();
|
||||||
// Make sure we were actually closed, rather than just temporarily hidden (e.g. console or main menu opened)
|
|
||||||
&& !MWBase::Environment::get().getWindowManager()->containsMode(GM_Container)
|
|
||||||
// If it was already detected while taking an item, no need to check now
|
|
||||||
&& !mPickpocketDetected
|
|
||||||
)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
|
||||||
MWMechanics::Pickpocket pickpocket(player, mPtr);
|
|
||||||
if (pickpocket.finish())
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
|
||||||
player, mPtr, MWBase::MechanicsManager::OT_Pickpocket, 0, true);
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
|
||||||
mPickpocketDetected = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||||
|
@ -271,32 +230,7 @@ namespace MWGui
|
||||||
|
|
||||||
bool ContainerWindow::onTakeItem(const ItemStack &item, int count)
|
bool ContainerWindow::onTakeItem(const ItemStack &item, int count)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
return mModel->onTakeItem(item.mBase, count);
|
||||||
// TODO: move to ItemModels
|
|
||||||
if (dynamic_cast<PickpocketItemModel*>(mModel)
|
|
||||||
&& !mPtr.getClass().getCreatureStats(mPtr).getKnockedDown())
|
|
||||||
{
|
|
||||||
MWMechanics::Pickpocket pickpocket(player, mPtr);
|
|
||||||
if (pickpocket.pick(item.mBase, count))
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
|
||||||
player, mPtr, MWBase::MechanicsManager::OT_Pickpocket, 0, true);
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
|
||||||
mPickpocketDetected = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
player.getClass().skillUsageSucceeded(player, ESM::Skill::Sneak, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Looting a dead corpse is considered OK
|
|
||||||
if (mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead())
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, mPtr, count);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,6 @@ namespace MWGui
|
||||||
private:
|
private:
|
||||||
DragAndDrop* mDragAndDrop;
|
DragAndDrop* mDragAndDrop;
|
||||||
|
|
||||||
bool mPickpocketDetected;
|
|
||||||
|
|
||||||
MWGui::ItemView* mItemView;
|
MWGui::ItemView* mItemView;
|
||||||
SortFilterItemModel* mSortModel;
|
SortFilterItemModel* mSortModel;
|
||||||
ItemModel* mModel;
|
ItemModel* mModel;
|
||||||
|
|
|
@ -2,12 +2,16 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
|
@ -185,5 +189,51 @@ void ContainerItemModel::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool ContainerItemModel::onDropItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
if (mItemSources.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MWWorld::Ptr target = mItemSources[0];
|
||||||
|
|
||||||
|
if (target.getTypeName() != typeid(ESM::Container).name())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// check container organic flag
|
||||||
|
MWWorld::LiveCellRef<ESM::Container>* ref = target.get<ESM::Container>();
|
||||||
|
if (ref->mBase->mFlags & ESM::Container::Organic)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->
|
||||||
|
messageBox("#{sContentsMessage2}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that we don't exceed container capacity
|
||||||
|
float weight = item.getClass().getWeight(item) * count;
|
||||||
|
if (target.getClass().getCapacity(target) < target.getClass().getEncumbrance(target) + weight)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sContentsMessage3}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ContainerItemModel::onTakeItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
if (mItemSources.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MWWorld::Ptr target = mItemSources[0];
|
||||||
|
|
||||||
|
// Looting a dead corpse is considered OK
|
||||||
|
if (target.getClass().isActor() && target.getClass().getCreatureStats(target).isDead())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item, target, count);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,10 @@ namespace MWGui
|
||||||
ContainerItemModel (const MWWorld::Ptr& source);
|
ContainerItemModel (const MWWorld::Ptr& source);
|
||||||
|
|
||||||
virtual bool allowedToUseItems() const;
|
virtual bool allowedToUseItems() const;
|
||||||
|
|
||||||
|
virtual bool onDropItem(const MWWorld::Ptr &item, int count);
|
||||||
|
virtual bool onTakeItem(const MWWorld::Ptr &item, int count);
|
||||||
|
|
||||||
virtual ItemStack getItem (ModelIndex index);
|
virtual ItemStack getItem (ModelIndex index);
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
virtual size_t getItemCount();
|
virtual size_t getItemCount();
|
||||||
|
|
|
@ -45,6 +45,11 @@ namespace MWGui
|
||||||
mWindow->addResponse(title, text, mNeedMargin);
|
mWindow->addResponse(title, text, mNeedMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateTopics()
|
||||||
|
{
|
||||||
|
mWindow->updateTopics();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DialogueWindow* mWindow;
|
DialogueWindow* mWindow;
|
||||||
bool mNeedMargin;
|
bool mNeedMargin;
|
||||||
|
@ -91,6 +96,7 @@ namespace MWGui
|
||||||
type = MWBase::MechanicsManager::PT_Bribe1000;
|
type = MWBase::MechanicsManager::PT_Bribe1000;
|
||||||
|
|
||||||
MWBase::Environment::get().getDialogueManager()->persuade(type, mCallback.get());
|
MWBase::Environment::get().getDialogueManager()->persuade(type, mCallback.get());
|
||||||
|
mCallback->updateTopics();
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
|
@ -395,6 +401,8 @@ namespace MWGui
|
||||||
else if (topic == gmst.find("sRepair")->getString())
|
else if (topic == gmst.find("sRepair")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
updateTopics();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +440,9 @@ namespace MWGui
|
||||||
|
|
||||||
setTitle(mPtr.getClass().getName(mPtr));
|
setTitle(mPtr.getClass().getName(mPtr));
|
||||||
|
|
||||||
updateTopicsPane();
|
updateTopics();
|
||||||
|
updateTopicsPane(); // force update for new services
|
||||||
|
|
||||||
updateDisposition();
|
updateDisposition();
|
||||||
restock();
|
restock();
|
||||||
}
|
}
|
||||||
|
@ -620,11 +630,13 @@ namespace MWGui
|
||||||
void DialogueWindow::onTopicActivated(const std::string &topicId)
|
void DialogueWindow::onTopicActivated(const std::string &topicId)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(topicId, mCallback.get());
|
MWBase::Environment::get().getDialogueManager()->keywordSelected(topicId, mCallback.get());
|
||||||
|
updateTopics();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onChoiceActivated(int id)
|
void DialogueWindow::onChoiceActivated(int id)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getDialogueManager()->questionAnswered(id, mCallback.get());
|
MWBase::Environment::get().getDialogueManager()->questionAnswered(id, mCallback.get());
|
||||||
|
updateTopics();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onGoodbyeActivated()
|
void DialogueWindow::onGoodbyeActivated()
|
||||||
|
|
|
@ -131,8 +131,9 @@ namespace MWGui
|
||||||
void onFrame(float dt);
|
void onFrame(float dt);
|
||||||
void clear() { resetReference(); }
|
void clear() { resetReference(); }
|
||||||
|
|
||||||
protected:
|
|
||||||
void updateTopics();
|
void updateTopics();
|
||||||
|
|
||||||
|
protected:
|
||||||
void updateTopicsPane();
|
void updateTopicsPane();
|
||||||
bool isCompanion(const MWWorld::Ptr& actor);
|
bool isCompanion(const MWWorld::Ptr& actor);
|
||||||
bool isCompanion();
|
bool isCompanion();
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -116,4 +119,16 @@ void InventoryItemModel::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InventoryItemModel::onTakeItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
// Looting a dead corpse is considered OK
|
||||||
|
if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item, mActor, count);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ namespace MWGui
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
virtual size_t getItemCount();
|
virtual size_t getItemCount();
|
||||||
|
|
||||||
|
virtual bool onTakeItem(const MWWorld::Ptr &item, int count);
|
||||||
|
|
||||||
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
@ -23,38 +24,7 @@ namespace MWGui
|
||||||
if (base.getClass().getEnchantment(base) != "")
|
if (base.getClass().getEnchantment(base) != "")
|
||||||
mFlags |= Flag_Enchanted;
|
mFlags |= Flag_Enchanted;
|
||||||
|
|
||||||
static std::set<std::string> boundItemIDCache;
|
if (MWBase::Environment::get().getMechanicsManager()->isBoundItem(base))
|
||||||
|
|
||||||
// If this is empty then we haven't executed the GMST cache logic yet; or there isn't any sMagicBound* GMST's for some reason
|
|
||||||
if (boundItemIDCache.empty())
|
|
||||||
{
|
|
||||||
// Build a list of known bound item ID's
|
|
||||||
const MWWorld::Store<ESM::GameSetting> &gameSettings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
|
||||||
|
|
||||||
for (MWWorld::Store<ESM::GameSetting>::iterator currentIteration = gameSettings.begin(); currentIteration != gameSettings.end(); ++currentIteration)
|
|
||||||
{
|
|
||||||
const ESM::GameSetting ¤tSetting = *currentIteration;
|
|
||||||
std::string currentGMSTID = currentSetting.mId;
|
|
||||||
Misc::StringUtils::lowerCaseInPlace(currentGMSTID);
|
|
||||||
|
|
||||||
// Don't bother checking this GMST if it's not a sMagicBound* one.
|
|
||||||
const std::string& toFind = "smagicbound";
|
|
||||||
if (currentGMSTID.compare(0, toFind.length(), toFind) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// All sMagicBound* GMST's should be of type string
|
|
||||||
std::string currentGMSTValue = currentSetting.getString();
|
|
||||||
Misc::StringUtils::lowerCaseInPlace(currentGMSTValue);
|
|
||||||
|
|
||||||
boundItemIDCache.insert(currentGMSTValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform bound item check and assign the Flag_Bound bit if it passes
|
|
||||||
std::string tempItemID = base.getCellRef().getRefId();
|
|
||||||
Misc::StringUtils::lowerCaseInPlace(tempItemID);
|
|
||||||
|
|
||||||
if (boundItemIDCache.count(tempItemID) != 0)
|
|
||||||
mFlags |= Flag_Bound;
|
mFlags |= Flag_Bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +94,12 @@ namespace MWGui
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ItemModel::allowedToInsertItems() const
|
bool ItemModel::onDropItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemModel::onTakeItem(const MWWorld::Ptr &item, int count)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -198,4 +173,18 @@ namespace MWGui
|
||||||
mSourceModel = sourceModel;
|
mSourceModel = sourceModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProxyItemModel::onClose()
|
||||||
|
{
|
||||||
|
mSourceModel->onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyItemModel::onDropItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
return mSourceModel->onDropItem(item, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyItemModel::onTakeItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
return mSourceModel->onTakeItem(item, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,9 +72,11 @@ namespace MWGui
|
||||||
|
|
||||||
/// Is the player allowed to use items from this item model? (default true)
|
/// Is the player allowed to use items from this item model? (default true)
|
||||||
virtual bool allowedToUseItems() const;
|
virtual bool allowedToUseItems() const;
|
||||||
|
virtual void onClose()
|
||||||
/// Is the player allowed to insert items into this model? (default true)
|
{
|
||||||
virtual bool allowedToInsertItems() const;
|
}
|
||||||
|
virtual bool onDropItem(const MWWorld::Ptr &item, int count);
|
||||||
|
virtual bool onTakeItem(const MWWorld::Ptr &item, int count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ItemModel(const ItemModel&);
|
ItemModel(const ItemModel&);
|
||||||
|
@ -91,6 +93,10 @@ namespace MWGui
|
||||||
|
|
||||||
bool allowedToUseItems() const;
|
bool allowedToUseItems() const;
|
||||||
|
|
||||||
|
virtual void onClose();
|
||||||
|
virtual bool onDropItem(const MWWorld::Ptr &item, int count);
|
||||||
|
virtual bool onTakeItem(const MWWorld::Ptr &item, int count);
|
||||||
|
|
||||||
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
|
|
|
@ -3,15 +3,26 @@
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
#include "../mwmechanics/pickpocket.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/containerstore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
PickpocketItemModel::PickpocketItemModel(const MWWorld::Ptr& thief, ItemModel *sourceModel, bool hideItems)
|
PickpocketItemModel::PickpocketItemModel(const MWWorld::Ptr& actor, ItemModel *sourceModel, bool hideItems)
|
||||||
|
: mActor(actor), mPickpocketDetected(false)
|
||||||
{
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
mSourceModel = sourceModel;
|
mSourceModel = sourceModel;
|
||||||
int chance = thief.getClass().getSkill(thief, ESM::Skill::Sneak);
|
int chance = player.getClass().getSkill(player, ESM::Skill::Sneak);
|
||||||
|
|
||||||
mSourceModel->update();
|
mSourceModel->update();
|
||||||
|
|
||||||
|
@ -66,13 +77,63 @@ namespace MWGui
|
||||||
void PickpocketItemModel::removeItem (const ItemStack &item, size_t count)
|
void PickpocketItemModel::removeItem (const ItemStack &item, size_t count)
|
||||||
{
|
{
|
||||||
ProxyItemModel::removeItem(item, count);
|
ProxyItemModel::removeItem(item, count);
|
||||||
/// \todo check if player is detected
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PickpocketItemModel::allowedToInsertItems() const
|
bool PickpocketItemModel::onDropItem(const MWWorld::Ptr &item, int count)
|
||||||
{
|
{
|
||||||
// don't allow "reverse pickpocket" (yet)
|
// don't allow "reverse pickpocket" (it will be handled by scripts after 1.0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PickpocketItemModel::onClose()
|
||||||
|
{
|
||||||
|
// Make sure we were actually closed, rather than just temporarily hidden (e.g. console or main menu opened)
|
||||||
|
if (MWBase::Environment::get().getWindowManager()->containsMode(GM_Container)
|
||||||
|
// If it was already detected while taking an item, no need to check now
|
||||||
|
|| mPickpocketDetected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
MWMechanics::Pickpocket pickpocket(player, mActor);
|
||||||
|
if (pickpocket.finish())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
||||||
|
player, mActor, MWBase::MechanicsManager::OT_Pickpocket, 0, true);
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||||
|
mPickpocketDetected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PickpocketItemModel::onTakeItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
if (mActor.getClass().getCreatureStats(mActor).getKnockedDown())
|
||||||
|
return mSourceModel->onTakeItem(item, count);
|
||||||
|
|
||||||
|
bool success = stealItem(item, count);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item, mActor, count, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PickpocketItemModel::stealItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
MWMechanics::Pickpocket pickpocket(player, mActor);
|
||||||
|
if (pickpocket.pick(item, count))
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
||||||
|
player, mActor, MWBase::MechanicsManager::OT_Pickpocket, 0, true);
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||||
|
mPickpocketDetected = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
player.getClass().skillUsageSucceeded(player, ESM::Skill::Sneak, 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,14 @@ namespace MWGui
|
||||||
virtual size_t getItemCount();
|
virtual size_t getItemCount();
|
||||||
virtual void update();
|
virtual void update();
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
virtual bool allowedToInsertItems() const;
|
virtual void onClose();
|
||||||
|
virtual bool onDropItem(const MWWorld::Ptr &item, int count);
|
||||||
|
virtual bool onTakeItem(const MWWorld::Ptr &item, int count);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MWWorld::Ptr mActor;
|
||||||
|
bool mPickpocketDetected;
|
||||||
|
bool stealItem(const MWWorld::Ptr &item, int count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ItemStack> mHiddenItems;
|
std::vector<ItemStack> mHiddenItems;
|
||||||
|
|
|
@ -311,4 +311,18 @@ namespace MWGui
|
||||||
std::sort(mItems.begin(), mItems.end(), cmp);
|
std::sort(mItems.begin(), mItems.end(), cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SortFilterItemModel::onClose()
|
||||||
|
{
|
||||||
|
mSourceModel->onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SortFilterItemModel::onDropItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
return mSourceModel->onDropItem(item, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SortFilterItemModel::onTakeItem(const MWWorld::Ptr &item, int count)
|
||||||
|
{
|
||||||
|
return mSourceModel->onTakeItem(item, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,10 @@ namespace MWGui
|
||||||
/// Use ItemStack::Type for sorting?
|
/// Use ItemStack::Type for sorting?
|
||||||
void setSortByType(bool sort) { mSortByType = sort; }
|
void setSortByType(bool sort) { mSortByType = sort; }
|
||||||
|
|
||||||
|
void onClose();
|
||||||
|
bool onDropItem(const MWWorld::Ptr &item, int count);
|
||||||
|
bool onTakeItem(const MWWorld::Ptr &item, int count);
|
||||||
|
|
||||||
static const int Category_Weapon = (1<<1);
|
static const int Category_Weapon = (1<<1);
|
||||||
static const int Category_Apparel = (1<<2);
|
static const int Category_Apparel = (1<<2);
|
||||||
static const int Category_Misc = (1<<3);
|
static const int Category_Misc = (1<<3);
|
||||||
|
|
|
@ -176,6 +176,8 @@ namespace MWInput
|
||||||
|
|
||||||
void InputManager::handleGuiArrowKey(int action)
|
void InputManager::handleGuiArrowKey(int action)
|
||||||
{
|
{
|
||||||
|
if (SDL_IsTextInputActive())
|
||||||
|
return;
|
||||||
MyGUI::KeyCode key;
|
MyGUI::KeyCode key;
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
|
@ -1111,7 +1113,10 @@ namespace MWInput
|
||||||
void InputManager::activate()
|
void InputManager::activate()
|
||||||
{
|
{
|
||||||
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
{
|
||||||
|
if (!SDL_IsTextInputActive())
|
||||||
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Return, 0);
|
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Return, 0);
|
||||||
|
}
|
||||||
else if (mControlSwitch["playercontrols"])
|
else if (mControlSwitch["playercontrols"])
|
||||||
mPlayer->activate();
|
mPlayer->activate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1230,8 +1230,13 @@ namespace MWMechanics
|
||||||
float sqrHeadTrackDistance = std::numeric_limits<float>::max();
|
float sqrHeadTrackDistance = std::numeric_limits<float>::max();
|
||||||
MWWorld::Ptr headTrackTarget;
|
MWWorld::Ptr headTrackTarget;
|
||||||
|
|
||||||
|
MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first);
|
||||||
|
|
||||||
// Unconsious actor can not track target
|
// Unconsious actor can not track target
|
||||||
if (!iter->first.getClass().getCreatureStats(iter->first).getKnockedDown())
|
// Also actors in combat and pursue mode do not bother to headtrack
|
||||||
|
if (!stats.getKnockedDown() &&
|
||||||
|
!stats.getAiSequence().isInCombat() &&
|
||||||
|
!stats.getAiSequence().hasPackage(AiPackage::TypeIdPursue))
|
||||||
{
|
{
|
||||||
for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it)
|
for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -1239,8 +1244,9 @@ namespace MWMechanics
|
||||||
continue;
|
continue;
|
||||||
updateHeadTracking(iter->first, it->first, headTrackTarget, sqrHeadTrackDistance);
|
updateHeadTracking(iter->first, it->first, headTrackTarget, sqrHeadTrackDistance);
|
||||||
}
|
}
|
||||||
iter->second->getCharacterController()->setHeadTrackTarget(headTrackTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iter->second->getCharacterController()->setHeadTrackTarget(headTrackTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter->first.getClass().isNpc() && iter->first != player)
|
if (iter->first.getClass().isNpc() && iter->first != player)
|
||||||
|
|
|
@ -489,17 +489,8 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiCombatStorage::startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target)
|
void AiCombatStorage::startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target)
|
||||||
{
|
|
||||||
if (mMovement.mPosition[0] || mMovement.mPosition[1])
|
|
||||||
{
|
|
||||||
mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability();
|
|
||||||
mCombatMove = true;
|
|
||||||
}
|
|
||||||
// dodge movements (for NPCs and bipedal creatures)
|
|
||||||
else if (actor.getClass().isBipedal(actor))
|
|
||||||
{
|
{
|
||||||
// get the range of the target's weapon
|
// get the range of the target's weapon
|
||||||
float rangeAttackOfTarget = 0.f;
|
|
||||||
MWWorld::Ptr targetWeapon = MWWorld::Ptr();
|
MWWorld::Ptr targetWeapon = MWWorld::Ptr();
|
||||||
const MWWorld::Class& targetClass = target.getClass();
|
const MWWorld::Class& targetClass = target.getClass();
|
||||||
|
|
||||||
|
@ -512,14 +503,17 @@ namespace MWMechanics
|
||||||
targetWeapon = *weaponSlot;
|
targetWeapon = *weaponSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Action> targetWeaponAction (new ActionWeapon(targetWeapon));
|
bool targetUsesRanged = false;
|
||||||
|
float rangeAttackOfTarget = ActionWeapon(targetWeapon).getCombatRange(targetUsesRanged);
|
||||||
|
|
||||||
if (targetWeaponAction.get())
|
if (mMovement.mPosition[0] || mMovement.mPosition[1])
|
||||||
{
|
{
|
||||||
bool isRangedCombat = false;
|
mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability();
|
||||||
rangeAttackOfTarget = targetWeaponAction->getCombatRange(isRangedCombat);
|
mCombatMove = true;
|
||||||
}
|
}
|
||||||
|
// dodge movements (for NPCs and bipedal creatures)
|
||||||
|
else if (actor.getClass().isBipedal(actor))
|
||||||
|
{
|
||||||
// apply sideway movement (kind of dodging) with some probability
|
// apply sideway movement (kind of dodging) with some probability
|
||||||
// if actor is within range of target's weapon
|
// if actor is within range of target's weapon
|
||||||
if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
|
if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
|
||||||
|
@ -530,15 +524,17 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Below behavior for backing up during ranged combat differs from vanilla.
|
// Backing up behaviour
|
||||||
// Vanilla is observed as backing up only as far as fCombatDistance or
|
// Actor backs up slightly further away than opponent's weapon range
|
||||||
// opponent's weapon range, or not backing up if opponent is also using a ranged weapon
|
// (in vanilla - only as far as oponent's weapon range),
|
||||||
if (isDistantCombat && distToTarget < rangeAttack / 4)
|
// or not at all if opponent is using a ranged weapon
|
||||||
|
if (isDistantCombat)
|
||||||
{
|
{
|
||||||
// actor should not back up into water
|
// actor should not back up into water
|
||||||
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(actor), 0.5f))
|
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(actor), 0.5f))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!targetUsesRanged && distToTarget <= rangeAttackOfTarget*1.5) // Don't back up if the target is wielding ranged weapon
|
||||||
mMovement.mPosition[1] = -1;
|
mMovement.mPosition[1] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ namespace MWMechanics
|
||||||
isRanged = false;
|
isRanged = false;
|
||||||
|
|
||||||
static const float fCombatDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCombatDistance")->getFloat();
|
static const float fCombatDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCombatDistance")->getFloat();
|
||||||
|
static const float fProjectileMaxSpeed = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fProjectileMaxSpeed")->getFloat();
|
||||||
|
|
||||||
if (mWeapon.isEmpty())
|
if (mWeapon.isEmpty())
|
||||||
{
|
{
|
||||||
|
@ -128,7 +129,7 @@ namespace MWMechanics
|
||||||
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow)
|
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow)
|
||||||
{
|
{
|
||||||
isRanged = true;
|
isRanged = true;
|
||||||
return 1000.f;
|
return fProjectileMaxSpeed;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return weapon->mData.mReach * fCombatDistance;
|
return weapon->mData.mReach * fCombatDistance;
|
||||||
|
|
|
@ -55,7 +55,7 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
|
||||||
float pathTolerance = 100.0;
|
float pathTolerance = 100.0;
|
||||||
|
|
||||||
if (pathTo(actor, dest, duration, pathTolerance) &&
|
if (pathTo(actor, dest, duration, pathTolerance) &&
|
||||||
abs(dest.mZ - aPos.pos[2]) < pathTolerance) // check the true distance in case the target is far away in Z-direction
|
std::abs(dest.mZ - aPos.pos[2]) < pathTolerance) // check the true distance in case the target is far away in Z-direction
|
||||||
{
|
{
|
||||||
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
|
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -196,8 +196,6 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
||||||
float mSecondsOfSwimming;
|
float mSecondsOfSwimming;
|
||||||
float mSecondsOfRunning;
|
float mSecondsOfRunning;
|
||||||
|
|
||||||
float mTimeUntilWake;
|
|
||||||
|
|
||||||
MWWorld::ConstPtr mHeadTrackTarget;
|
MWWorld::ConstPtr mHeadTrackTarget;
|
||||||
|
|
||||||
float mTurnAnimationThreshold; // how long to continue playing turning animation after actor stopped turning
|
float mTurnAnimationThreshold; // how long to continue playing turning animation after actor stopped turning
|
||||||
|
@ -206,6 +204,8 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
||||||
|
|
||||||
bool mAttackingOrSpell;
|
bool mAttackingOrSpell;
|
||||||
|
|
||||||
|
float mTimeUntilWake;
|
||||||
|
|
||||||
void setAttackTypeBasedOnMovement();
|
void setAttackTypeBasedOnMovement();
|
||||||
|
|
||||||
void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false);
|
void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false);
|
||||||
|
|
|
@ -840,6 +840,45 @@ namespace MWMechanics
|
||||||
mAI = true;
|
mAI = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isBoundItem(const MWWorld::Ptr& item)
|
||||||
|
{
|
||||||
|
static std::set<std::string> boundItemIDCache;
|
||||||
|
|
||||||
|
// If this is empty then we haven't executed the GMST cache logic yet; or there isn't any sMagicBound* GMST's for some reason
|
||||||
|
if (boundItemIDCache.empty())
|
||||||
|
{
|
||||||
|
// Build a list of known bound item ID's
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &gameSettings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
for (MWWorld::Store<ESM::GameSetting>::iterator currentIteration = gameSettings.begin(); currentIteration != gameSettings.end(); ++currentIteration)
|
||||||
|
{
|
||||||
|
const ESM::GameSetting ¤tSetting = *currentIteration;
|
||||||
|
std::string currentGMSTID = currentSetting.mId;
|
||||||
|
Misc::StringUtils::lowerCaseInPlace(currentGMSTID);
|
||||||
|
|
||||||
|
// Don't bother checking this GMST if it's not a sMagicBound* one.
|
||||||
|
const std::string& toFind = "smagicbound";
|
||||||
|
if (currentGMSTID.compare(0, toFind.length(), toFind) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// All sMagicBound* GMST's should be of type string
|
||||||
|
std::string currentGMSTValue = currentSetting.getString();
|
||||||
|
Misc::StringUtils::lowerCaseInPlace(currentGMSTValue);
|
||||||
|
|
||||||
|
boundItemIDCache.insert(currentGMSTValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform bound item check and assign the Flag_Bound bit if it passes
|
||||||
|
std::string tempItemID = item.getCellRef().getRefId();
|
||||||
|
Misc::StringUtils::lowerCaseInPlace(tempItemID);
|
||||||
|
|
||||||
|
if (boundItemIDCache.count(tempItemID) != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim)
|
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim)
|
||||||
{
|
{
|
||||||
if (target.isEmpty())
|
if (target.isEmpty())
|
||||||
|
@ -1024,7 +1063,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, const MWWorld::Ptr& container,
|
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, const MWWorld::Ptr& container,
|
||||||
int count)
|
int count, bool alarm)
|
||||||
{
|
{
|
||||||
if (ptr != getPlayer())
|
if (ptr != getPlayer())
|
||||||
return;
|
return;
|
||||||
|
@ -1053,18 +1092,28 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Owner owner;
|
Owner owner;
|
||||||
owner.first = ownerCellRef->getOwner();
|
|
||||||
owner.second = false;
|
owner.second = false;
|
||||||
|
if (!container.isEmpty() && container.getClass().isActor())
|
||||||
|
{
|
||||||
|
// "container" is an actor inventory, so just take actor's ID
|
||||||
|
owner.first = ownerCellRef->getRefId();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
owner.first = ownerCellRef->getOwner();
|
||||||
if (owner.first.empty())
|
if (owner.first.empty())
|
||||||
{
|
{
|
||||||
owner.first = ownerCellRef->getFaction();
|
owner.first = ownerCellRef->getFaction();
|
||||||
owner.second = true;
|
owner.second = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Misc::StringUtils::lowerCaseInPlace(owner.first);
|
Misc::StringUtils::lowerCaseInPlace(owner.first);
|
||||||
|
|
||||||
if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId))
|
if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId))
|
||||||
mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count;
|
mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count;
|
||||||
|
|
||||||
|
if (alarm)
|
||||||
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
|
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ namespace MWMechanics
|
||||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||||
/// @param container The container the item is in; may be empty for an item in the world
|
/// @param container The container the item is in; may be empty for an item in the world
|
||||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
||||||
int count);
|
int count, bool alarm = true);
|
||||||
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
||||||
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item);
|
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item);
|
||||||
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
||||||
|
@ -204,6 +204,8 @@ namespace MWMechanics
|
||||||
/// Has the player stolen this item from the given owner?
|
/// Has the player stolen this item from the given owner?
|
||||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid);
|
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid);
|
||||||
|
|
||||||
|
virtual bool isBoundItem(const MWWorld::Ptr& item);
|
||||||
|
|
||||||
/// @return is \a ptr allowed to take/use \a target or is it a crime?
|
/// @return is \a ptr allowed to take/use \a target or is it a crime?
|
||||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim);
|
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim);
|
||||||
|
|
||||||
|
|
|
@ -536,7 +536,7 @@ namespace MWRender
|
||||||
return mKeyframes->mTextKeys;
|
return mKeyframes->mTextKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::addAnimSource(const std::string &model)
|
void Animation::addAnimSource(const std::string &model, const std::string& baseModel)
|
||||||
{
|
{
|
||||||
std::string kfname = model;
|
std::string kfname = model;
|
||||||
Misc::StringUtils::lowerCaseInPlace(kfname);
|
Misc::StringUtils::lowerCaseInPlace(kfname);
|
||||||
|
@ -565,7 +565,7 @@ namespace MWRender
|
||||||
NodeMap::const_iterator found = nodeMap.find(bonename);
|
NodeMap::const_iterator found = nodeMap.find(bonename);
|
||||||
if (found == nodeMap.end())
|
if (found == nodeMap.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: addAnimSource: can't find bone '" + bonename << "' in " << model << " (referenced by " << kfname << ")" << std::endl;
|
std::cerr << "Warning: addAnimSource: can't find bone '" + bonename << "' in " << baseModel << " (referenced by " << kfname << ")" << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1668,7 +1668,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
setObjectRoot(model, false, false, false);
|
setObjectRoot(model, false, false, false);
|
||||||
if (animated)
|
if (animated)
|
||||||
addAnimSource(model);
|
addAnimSource(model, model);
|
||||||
|
|
||||||
if (!ptr.getClass().getEnchantment(ptr).empty())
|
if (!ptr.getClass().getEnchantment(ptr).empty())
|
||||||
addGlow(mObjectRoot, getEnchantmentColor(ptr));
|
addGlow(mObjectRoot, getEnchantmentColor(ptr));
|
||||||
|
|
|
@ -309,11 +309,12 @@ protected:
|
||||||
*/
|
*/
|
||||||
void setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature);
|
void setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature);
|
||||||
|
|
||||||
/** Adds the keyframe controllers in the specified model as a new animation source. Note that the .nif
|
/** Adds the keyframe controllers in the specified model as a new animation source.
|
||||||
* file extension will be replaced with .kf.
|
|
||||||
* @note Later added animation sources have the highest priority when it comes to finding a particular animation.
|
* @note Later added animation sources have the highest priority when it comes to finding a particular animation.
|
||||||
|
* @param model The file to add the keyframes for. Note that the .nif file extension will be replaced with .kf.
|
||||||
|
* @param baseModel The filename of the mObjectRoot, only used for error messages.
|
||||||
*/
|
*/
|
||||||
void addAnimSource(const std::string &model);
|
void addAnimSource(const std::string &model, const std::string& baseModel);
|
||||||
|
|
||||||
/** Adds an additional light to the given node using the specified ESM record. */
|
/** Adds an additional light to the given node using the specified ESM record. */
|
||||||
void addExtraLight(osg::ref_ptr<osg::Group> parent, const ESM::Light *light);
|
void addExtraLight(osg::ref_ptr<osg::Group> parent, const ESM::Light *light);
|
||||||
|
|
|
@ -33,8 +33,8 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr,
|
||||||
setObjectRoot(model, false, false, true);
|
setObjectRoot(model, false, false, true);
|
||||||
|
|
||||||
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
||||||
addAnimSource("meshes\\xbase_anim.nif");
|
addAnimSource("meshes\\xbase_anim.nif", model);
|
||||||
addAnimSource(model);
|
addAnimSource(model, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const
|
||||||
setObjectRoot(model, true, false, true);
|
setObjectRoot(model, true, false, true);
|
||||||
|
|
||||||
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
||||||
addAnimSource("meshes\\xbase_anim.nif");
|
addAnimSource("meshes\\xbase_anim.nif", model);
|
||||||
addAnimSource(model);
|
addAnimSource(model, model);
|
||||||
|
|
||||||
mPtr.getClass().getInventoryStore(mPtr).setInvListener(this, mPtr);
|
mPtr.getClass().getInventoryStore(mPtr).setInvListener(this, mPtr);
|
||||||
|
|
||||||
|
|
|
@ -482,25 +482,25 @@ void NpcAnimation::updateNpcBase()
|
||||||
{
|
{
|
||||||
const std::string base = "meshes\\xbase_anim.nif";
|
const std::string base = "meshes\\xbase_anim.nif";
|
||||||
if (smodel != base)
|
if (smodel != base)
|
||||||
addAnimSource(base);
|
addAnimSource(base, smodel);
|
||||||
|
|
||||||
addAnimSource(smodel);
|
addAnimSource(smodel, smodel);
|
||||||
|
|
||||||
if(!isWerewolf)
|
if(!isWerewolf)
|
||||||
{
|
{
|
||||||
if(mNpc->mModel.length() > 0)
|
if(mNpc->mModel.length() > 0)
|
||||||
addAnimSource(Misc::ResourceHelpers::correctActorModelPath("meshes\\" + mNpc->mModel, mResourceSystem->getVFS()));
|
addAnimSource(Misc::ResourceHelpers::correctActorModelPath("meshes\\" + mNpc->mModel, mResourceSystem->getVFS()), smodel);
|
||||||
if(Misc::StringUtils::lowerCase(mNpc->mRace).find("argonian") != std::string::npos)
|
if(Misc::StringUtils::lowerCase(mNpc->mRace).find("argonian") != std::string::npos)
|
||||||
addAnimSource("meshes\\xargonian_swimkna.nif");
|
addAnimSource("meshes\\xargonian_swimkna.nif", smodel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const std::string base = "meshes\\xbase_anim.1st.nif";
|
const std::string base = "meshes\\xbase_anim.1st.nif";
|
||||||
if (smodel != base)
|
if (smodel != base)
|
||||||
addAnimSource(base);
|
addAnimSource(base, smodel);
|
||||||
|
|
||||||
addAnimSource(smodel);
|
addAnimSource(smodel, smodel);
|
||||||
|
|
||||||
mObjectRoot->setNodeMask(Mask_FirstPerson);
|
mObjectRoot->setNodeMask(Mask_FirstPerson);
|
||||||
mObjectRoot->addCullCallback(new OverrideFieldOfViewCallback(mFirstPersonFieldOfView));
|
mObjectRoot->addCullCallback(new OverrideFieldOfViewCallback(mFirstPersonFieldOfView));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "escape.hpp"
|
#include "escape.hpp"
|
||||||
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
namespace Files
|
namespace Files
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ namespace Files
|
||||||
const int escape_hash_filter::sEscapeIdentifier = 'a';
|
const int escape_hash_filter::sEscapeIdentifier = 'a';
|
||||||
const int escape_hash_filter::sHashIdentifier = 'h';
|
const int escape_hash_filter::sHashIdentifier = 'h';
|
||||||
|
|
||||||
escape_hash_filter::escape_hash_filter() : mNext(), mPrevious(), mSeenNonWhitespace(false), mFinishLine(false)
|
escape_hash_filter::escape_hash_filter() : mSeenNonWhitespace(false), mFinishLine(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,14 @@ namespace Files
|
||||||
|
|
||||||
std::string EscapeHashString::processString(const std::string & str)
|
std::string EscapeHashString::processString(const std::string & str)
|
||||||
{
|
{
|
||||||
std::string temp = boost::replace_all_copy<std::string>(str, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sHashIdentifier, "#");
|
std::string temp = str;
|
||||||
boost::replace_all(temp, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sEscapeIdentifier, std::string((char)escape_hash_filter::sEscape, 1));
|
|
||||||
|
static const char hash[] = { escape_hash_filter::sEscape, escape_hash_filter::sHashIdentifier };
|
||||||
|
Misc::StringUtils::replaceAll(temp, hash, "#", 2, 1);
|
||||||
|
|
||||||
|
static const char escape[] = { escape_hash_filter::sEscape, escape_hash_filter::sEscapeIdentifier };
|
||||||
|
Misc::StringUtils::replaceAll(temp, escape, "@", 2, 1);
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ namespace Files
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::queue<int> mNext;
|
std::queue<int> mNext;
|
||||||
int mPrevious;
|
|
||||||
|
|
||||||
bool mSeenNonWhitespace;
|
bool mSeenNonWhitespace;
|
||||||
bool mFinishLine;
|
bool mFinishLine;
|
||||||
|
@ -42,11 +41,9 @@ namespace Files
|
||||||
if (mNext.empty())
|
if (mNext.empty())
|
||||||
{
|
{
|
||||||
int character = boost::iostreams::get(src);
|
int character = boost::iostreams::get(src);
|
||||||
bool record = true;
|
|
||||||
if (character == boost::iostreams::WOULD_BLOCK)
|
if (character == boost::iostreams::WOULD_BLOCK)
|
||||||
{
|
{
|
||||||
mNext.push(character);
|
mNext.push(character);
|
||||||
record = false;
|
|
||||||
}
|
}
|
||||||
else if (character == EOF)
|
else if (character == EOF)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +75,7 @@ namespace Files
|
||||||
mFinishLine = true;
|
mFinishLine = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mPrevious == sEscape)
|
else if (character == sEscape)
|
||||||
{
|
{
|
||||||
mNext.push(sEscape);
|
mNext.push(sEscape);
|
||||||
mNext.push(sEscapeIdentifier);
|
mNext.push(sEscapeIdentifier);
|
||||||
|
@ -89,8 +86,6 @@ namespace Files
|
||||||
}
|
}
|
||||||
if (!mSeenNonWhitespace && !isspace(character))
|
if (!mSeenNonWhitespace && !isspace(character))
|
||||||
mSeenNonWhitespace = true;
|
mSeenNonWhitespace = true;
|
||||||
if (record)
|
|
||||||
mPrevious = character;
|
|
||||||
}
|
}
|
||||||
int retval = mNext.front();
|
int retval = mNext.front();
|
||||||
mNext.pop();
|
mNext.pop();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define MISC_STRINGOPS_H
|
#define MISC_STRINGOPS_H
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -138,6 +139,35 @@ public:
|
||||||
|
|
||||||
return notFound;
|
return notFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Replaces all occurrences of a string in another string.
|
||||||
|
*
|
||||||
|
* @param str The string to operate on.
|
||||||
|
* @param what The string to replace.
|
||||||
|
* @param with The replacement string.
|
||||||
|
* @param whatLen The length of the string to replace.
|
||||||
|
* @param withLen The length of the replacement string.
|
||||||
|
*
|
||||||
|
* @return A reference to the string passed in @p str.
|
||||||
|
*/
|
||||||
|
static std::string &replaceAll(std::string &str, const char *what, const char *with,
|
||||||
|
std::size_t whatLen=std::string::npos, std::size_t withLen=std::string::npos)
|
||||||
|
{
|
||||||
|
if (whatLen == std::string::npos)
|
||||||
|
whatLen = strlen(what);
|
||||||
|
|
||||||
|
if (withLen == std::string::npos)
|
||||||
|
withLen = strlen(with);
|
||||||
|
|
||||||
|
std::size_t found;
|
||||||
|
std::size_t offset = 0;
|
||||||
|
while((found = str.find(what, offset, whatLen)) != std::string::npos)
|
||||||
|
{
|
||||||
|
str.replace(found, whatLen, with, withLen);
|
||||||
|
offset = found + withLen;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -432,13 +432,18 @@ namespace Resource
|
||||||
|
|
||||||
bool canOptimize(const std::string& filename)
|
bool canOptimize(const std::string& filename)
|
||||||
{
|
{
|
||||||
// xmesh.nif can not be optimized because there are keyframes added in post
|
|
||||||
size_t slashpos = filename.find_last_of("\\/");
|
size_t slashpos = filename.find_last_of("\\/");
|
||||||
if (slashpos != std::string::npos && slashpos+1 < filename.size())
|
if (slashpos != std::string::npos && slashpos+1 < filename.size())
|
||||||
{
|
{
|
||||||
std::string basename = filename.substr(slashpos+1);
|
std::string basename = filename.substr(slashpos+1);
|
||||||
|
// xmesh.nif can not be optimized because there are keyframes added in post
|
||||||
if (!basename.empty() && basename[0] == 'x')
|
if (!basename.empty() && basename[0] == 'x')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// NPC skeleton files can not be optimized because of keyframes added in post
|
||||||
|
// (most of them are usually named like 'xbase_anim.nif' anyway, but not all of them :( )
|
||||||
|
if (basename.compare(0, 9, "base_anim") == 0 || basename.compare(0, 4, "skin") == 0)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For spell VFX, DummyXX nodes must remain intact. Not adding those to reservedNames to avoid being overly cautious - instead, decide on filename
|
// For spell VFX, DummyXX nodes must remain intact. Not adding those to reservedNames to avoid being overly cautious - instead, decide on filename
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<Property key="TextAlign" value="Left Top"/>
|
<Property key="TextAlign" value="Left Top"/>
|
||||||
<Property key="TextColour" value="1 1 1"/>
|
<Property key="TextColour" value="1 1 1"/>
|
||||||
<Property key="InvertSelected" value="false"/>
|
<Property key="InvertSelected" value="false"/>
|
||||||
|
<Property key="WordWrap" value="true"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<!-- Command line -->
|
<!-- Command line -->
|
||||||
|
|
|
@ -53,18 +53,17 @@
|
||||||
<Property key="TextAlign" value="Center"/>
|
<Property key="TextAlign" value="Center"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="AutoSizedButton" skin="MW_Button" position="0 60 60 24" name="MaxSaleButton" align="Left Top">
|
<Widget type="HBox" position="0 60 566 24" align="Left Bottom HStretch">
|
||||||
|
<Widget type="AutoSizedButton" skin="MW_Button" name="MaxSaleButton">
|
||||||
<Property key="Caption" value="#{sMaxSale}"/>
|
<Property key="Caption" value="#{sMaxSale}"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="HBox" position="0 60 566 24" align="Right Bottom">
|
|
||||||
<Widget type="Widget">
|
<Widget type="Widget">
|
||||||
<UserString key="HStretch" value="true"/>
|
<UserString key="HStretch" value="true"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="AutoSizedButton" skin="MW_Button" name="OfferButton" align="Right Top">
|
<Widget type="AutoSizedButton" skin="MW_Button" name="OfferButton">
|
||||||
<Property key="Caption" value="#{sBarterDialog8}"/>
|
<Property key="Caption" value="#{sBarterDialog8}"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="AutoSizedButton" skin="MW_Button" name="CancelButton" align="Right Top">
|
<Widget type="AutoSizedButton" skin="MW_Button" name="CancelButton">
|
||||||
<Property key="Caption" value="#{sCancel}"/>
|
<Property key="Caption" value="#{sCancel}"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
Loading…
Reference in a new issue