Merge branch 'master' into sdl_input

actorid
Jordan Milne 12 years ago
commit eff26159d9

@ -7,6 +7,8 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
#include <components/misc/stringops.hpp>
MwIniImporter::MwIniImporter() MwIniImporter::MwIniImporter()
: mVerbose(false) : mVerbose(false)
@ -793,7 +795,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) {
for(std::vector<std::string>::iterator entry = it->second.begin(); entry!=it->second.end(); ++entry) { for(std::vector<std::string>::iterator entry = it->second.begin(); entry!=it->second.end(); ++entry) {
std::string filetype(entry->substr(entry->length()-4, 3)); std::string filetype(entry->substr(entry->length()-4, 3));
std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower); Misc::StringUtils::toLower(filetype);
if(filetype.compare("esm") == 0) { if(filetype.compare("esm") == 0) {
esmFiles.push_back(*entry); esmFiles.push_back(*entry);

@ -12,6 +12,7 @@
#include <QVariant> #include <QVariant>
#include "columnbase.hpp" #include "columnbase.hpp"
#include <components/misc/stringops.hpp>
namespace CSMWorld namespace CSMWorld
{ {
@ -152,10 +153,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
void IdCollection<ESXRecordT>::add (const ESXRecordT& record) void IdCollection<ESXRecordT>::add (const ESXRecordT& record)
{ {
std::string id; std::string id = Misc::StringUtils::lowerCase(record.mId);
std::transform (record.mId.begin(), record.mId.end(), std::back_inserter (id),
(int(*)(int)) std::tolower);
std::map<std::string, int>::iterator iter = mIndex.find (id); std::map<std::string, int>::iterator iter = mIndex.find (id);
@ -281,10 +279,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
int IdCollection<ESXRecordT>::searchId (const std::string& id) const int IdCollection<ESXRecordT>::searchId (const std::string& id) const
{ {
std::string id2; std::string id2 = Misc::StringUtils::lowerCase(id);
std::transform (id.begin(), id.end(), std::back_inserter (id2),
(int(*)(int)) std::tolower);
std::map<std::string, int>::const_iterator iter = mIndex.find (id2); std::map<std::string, int>::const_iterator iter = mIndex.find (id2);

@ -164,9 +164,6 @@ void OMW::Engine::loadBSA()
dataDirectory = iter->string(); dataDirectory = iter->string();
std::cout << "Data dir " << dataDirectory << std::endl; std::cout << "Data dir " << dataDirectory << std::endl;
Bsa::addDir(dataDirectory, mFSStrict); Bsa::addDir(dataDirectory, mFSStrict);
// Workaround until resource listing capabilities are added to DirArchive, we need those to list available splash screens
addResourcesDirectory (dataDirectory);
} }
} }
@ -336,7 +333,8 @@ void OMW::Engine::go()
// Create the world // Create the world
mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster,
mResDir, mCfgMgr.getCachePath(), mNewGame, &encoder, mFallbackMap)); mResDir, mCfgMgr.getCachePath(), mNewGame, &encoder, mFallbackMap,
mActivationDistanceOverride));
//Load translation data //Load translation data
mTranslationDataStorage.setEncoder(&encoder); mTranslationDataStorage.setEncoder(&encoder);
@ -427,12 +425,7 @@ void OMW::Engine::activate()
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
return; return;
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getFacedObject();
if (handle.empty())
return;
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle (handle);
if (ptr.isEmpty()) if (ptr.isEmpty())
return; return;
@ -514,3 +507,9 @@ void OMW::Engine::setStartupScript (const std::string& path)
{ {
mStartupScript = path; mStartupScript = path;
} }
void OMW::Engine::setActivationDistanceOverride (int distance)
{
mActivationDistanceOverride = distance;
}

@ -76,6 +76,7 @@ namespace OMW
std::map<std::string,std::string> mFallbackMap; std::map<std::string,std::string> mFallbackMap;
bool mScriptConsoleMode; bool mScriptConsoleMode;
std::string mStartupScript; std::string mStartupScript;
int mActivationDistanceOverride;
Compiler::Extensions mExtensions; Compiler::Extensions mExtensions;
Compiler::Context *mScriptContext; Compiler::Context *mScriptContext;
@ -167,6 +168,9 @@ namespace OMW
/// Set path for a script that is run on startup in the console. /// Set path for a script that is run on startup in the console.
void setStartupScript (const std::string& path); void setStartupScript (const std::string& path);
/// Override the game setting specified activation distance.
void setActivationDistanceOverride (int distance);
private: private:
Files::ConfigurationManager& mCfgMgr; Files::ConfigurationManager& mCfgMgr;
}; };

@ -149,6 +149,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("fallback", bpo::value<FallbackMap>()->default_value(FallbackMap(), "") ("fallback", bpo::value<FallbackMap>()->default_value(FallbackMap(), "")
->multitoken()->composing(), "fallback values") ->multitoken()->composing(), "fallback values")
("activate-dist", bpo::value <int> ()->default_value (-1), "activation distance override");
; ;
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv) bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
@ -236,6 +238,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap); engine.setFallbackValues(variables["fallback"].as<FallbackMap>().mMap);
engine.setScriptConsoleMode (variables["script-console"].as<bool>()); engine.setScriptConsoleMode (variables["script-console"].as<bool>());
engine.setStartupScript (variables["script-run"].as<std::string>()); engine.setStartupScript (variables["script-run"].as<std::string>());
engine.setActivationDistanceOverride (variables["activate-dist"].as<int>());
return true; return true;
} }

@ -199,8 +199,8 @@ namespace MWBase
virtual void markCellAsUnchanged() = 0; virtual void markCellAsUnchanged() = 0;
virtual std::string getFacedHandle() = 0; virtual MWWorld::Ptr getFacedObject() = 0;
///< Return handle of the object the player is looking at ///< Return pointer to the object the player is looking at, if it is within activation range
virtual void deleteObject (const MWWorld::Ptr& ptr) = 0; virtual void deleteObject (const MWWorld::Ptr& ptr) = 0;
@ -280,7 +280,7 @@ namespace MWBase
/// @param cursor Y (relative 0-1) /// @param cursor Y (relative 0-1)
/// @return true if the object was placed, or false if it was rejected because the position is too far away /// @return true if the object was placed, or false if it was rejected because the position is too far away
virtual void dropObjectOnGround (const MWWorld::Ptr& object) = 0; virtual void dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object) = 0;
virtual bool canPlaceObject (float cursorX, float cursorY) = 0; virtual bool canPlaceObject (float cursorX, float cursorY) = 0;
///< @return true if it is possible to place on object at specified cursor location ///< @return true if it is possible to place on object at specified cursor location

@ -97,11 +97,11 @@ namespace MWClass
// make key id lowercase // make key id lowercase
std::string keyId = ptr.getCellRef().mKey; std::string keyId = ptr.getCellRef().mKey;
std::transform(keyId.begin(), keyId.end(), keyId.begin(), ::tolower); Misc::StringUtils::toLower(keyId);
for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it)
{ {
std::string refId = it->getCellRef().mRefID; std::string refId = it->getCellRef().mRefID;
std::transform(refId.begin(), refId.end(), refId.begin(), ::tolower); Misc::StringUtils::toLower(refId);
if (refId == keyId) if (refId == keyId)
{ {
hasKey = true; hasKey = true;

@ -84,11 +84,11 @@ namespace MWClass
// make key id lowercase // make key id lowercase
std::string keyId = ptr.getCellRef().mKey; std::string keyId = ptr.getCellRef().mKey;
std::transform(keyId.begin(), keyId.end(), keyId.begin(), ::tolower); Misc::StringUtils::toLower(keyId);
for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it)
{ {
std::string refId = it->getCellRef().mRefID; std::string refId = it->getCellRef().mRefID;
std::transform(refId.begin(), refId.end(), refId.begin(), ::tolower); Misc::StringUtils::toLower(refId);
if (refId == keyId) if (refId == keyId)
{ {
hasKey = true; hasKey = true;

@ -65,7 +65,7 @@ namespace MWClass
if (!ref->mBase->mFaction.empty()) if (!ref->mBase->mFaction.empty())
{ {
std::string faction = ref->mBase->mFaction; std::string faction = ref->mBase->mFaction;
boost::algorithm::to_lower(faction); Misc::StringUtils::toLower(faction);
if(ref->mBase->mNpdt52.mGold != -10) if(ref->mBase->mNpdt52.mGold != -10)
{ {
data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt52.mRank; data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt52.mRank;

@ -17,24 +17,11 @@
#include "selectwrapper.hpp" #include "selectwrapper.hpp"
namespace
{
std::string toLower (const std::string& name)
{
std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
}
bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
{ {
// actor id // actor id
if (!info.mActor.empty()) if (!info.mActor.empty())
if (toLower (info.mActor)!=MWWorld::Class::get (mActor).getId (mActor)) if ( Misc::StringUtils::lowerCase (info.mActor)!=MWWorld::Class::get (mActor).getId (mActor))
return false; return false;
bool isCreature = (mActor.getTypeName() != typeid (ESM::NPC).name()); bool isCreature = (mActor.getTypeName() != typeid (ESM::NPC).name());
@ -47,7 +34,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
MWWorld::LiveCellRef<ESM::NPC> *cellRef = mActor.get<ESM::NPC>(); MWWorld::LiveCellRef<ESM::NPC> *cellRef = mActor.get<ESM::NPC>();
if (toLower (info.mRace)!=toLower (cellRef->mBase->mRace)) if (Misc::StringUtils::lowerCase (info.mRace)!= Misc::StringUtils::lowerCase (cellRef->mBase->mRace))
return false; return false;
} }
@ -59,7 +46,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
MWWorld::LiveCellRef<ESM::NPC> *cellRef = mActor.get<ESM::NPC>(); MWWorld::LiveCellRef<ESM::NPC> *cellRef = mActor.get<ESM::NPC>();
if (toLower (info.mClass)!=toLower (cellRef->mBase->mClass)) if ( Misc::StringUtils::lowerCase (info.mClass)!= Misc::StringUtils::lowerCase (cellRef->mBase->mClass))
return false; return false;
} }
@ -70,7 +57,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
return false; return false;
MWMechanics::NpcStats& stats = MWWorld::Class::get (mActor).getNpcStats (mActor); MWMechanics::NpcStats& stats = MWWorld::Class::get (mActor).getNpcStats (mActor);
std::map<std::string, int>::iterator iter = stats.getFactionRanks().find (toLower (info.mNpcFaction)); std::map<std::string, int>::iterator iter = stats.getFactionRanks().find ( Misc::StringUtils::lowerCase (info.mNpcFaction));
if (iter==stats.getFactionRanks().end()) if (iter==stats.getFactionRanks().end())
return false; return false;
@ -99,7 +86,7 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const
if (!info.mPcFaction.empty()) if (!info.mPcFaction.empty())
{ {
MWMechanics::NpcStats& stats = MWWorld::Class::get (player).getNpcStats (player); MWMechanics::NpcStats& stats = MWWorld::Class::get (player).getNpcStats (player);
std::map<std::string,int>::iterator iter = stats.getFactionRanks().find (toLower (info.mPcFaction)); std::map<std::string,int>::iterator iter = stats.getFactionRanks().find (Misc::StringUtils::lowerCase (info.mPcFaction));
if(iter==stats.getFactionRanks().end()) if(iter==stats.getFactionRanks().end())
return false; return false;
@ -111,7 +98,7 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const
// check cell // check cell
if (!info.mCell.empty()) if (!info.mCell.empty())
if (toLower (player.getCell()->mCell->mName) != toLower (info.mCell)) if (Misc::StringUtils::lowerCase (player.getCell()->mCell->mName) != Misc::StringUtils::lowerCase (info.mCell))
return false; return false;
return true; return true;
@ -242,7 +229,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
std::string name = select.getName(); std::string name = select.getName();
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
if (toLower(iter->getCellRef().mRefID) == name) if (Misc::StringUtils::lowerCase(iter->getCellRef().mRefID) == name)
sum += iter->getRefData().getCount(); sum += iter->getRefData().getCount();
return sum; return sum;
@ -408,23 +395,23 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
case SelectWrapper::Function_Id: case SelectWrapper::Function_Id:
return select.getName()==toLower (MWWorld::Class::get (mActor).getId (mActor)); return select.getName()==Misc::StringUtils::lowerCase (MWWorld::Class::get (mActor).getId (mActor));
case SelectWrapper::Function_Faction: case SelectWrapper::Function_Faction:
return toLower (mActor.get<ESM::NPC>()->mBase->mFaction)==select.getName(); return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mFaction)==select.getName();
case SelectWrapper::Function_Class: case SelectWrapper::Function_Class:
return toLower (mActor.get<ESM::NPC>()->mBase->mClass)==select.getName(); return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mClass)==select.getName();
case SelectWrapper::Function_Race: case SelectWrapper::Function_Race:
return toLower (mActor.get<ESM::NPC>()->mBase->mRace)==select.getName(); return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mRace)==select.getName();
case SelectWrapper::Function_Cell: case SelectWrapper::Function_Cell:
return toLower (mActor.getCell()->mCell->mName)==select.getName(); return Misc::StringUtils::lowerCase (mActor.getCell()->mCell->mName)==select.getName();
case SelectWrapper::Function_SameGender: case SelectWrapper::Function_SameGender:
@ -433,8 +420,8 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
case SelectWrapper::Function_SameRace: case SelectWrapper::Function_SameRace:
return toLower (mActor.get<ESM::NPC>()->mBase->mRace)!= return Misc::StringUtils::lowerCase (mActor.get<ESM::NPC>()->mBase->mRace)!=
toLower (player.get<ESM::NPC>()->mBase->mRace); Misc::StringUtils::lowerCase (player.get<ESM::NPC>()->mBase->mRace);
case SelectWrapper::Function_SameFaction: case SelectWrapper::Function_SameFaction:

@ -8,18 +8,10 @@
#include <sstream> #include <sstream>
#include <iterator> #include <iterator>
#include <components/misc/stringops.hpp>
namespace namespace
{ {
std::string toLower (const std::string& name)
{
std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
template<typename T1, typename T2> template<typename T1, typename T2>
bool selectCompareImp (char comp, T1 value1, T2 value2) bool selectCompareImp (char comp, T1 value1, T2 value2)
{ {
@ -307,5 +299,5 @@ bool MWDialogue::SelectWrapper::selectCompare (bool value) const
std::string MWDialogue::SelectWrapper::getName() const std::string MWDialogue::SelectWrapper::getName() const
{ {
return toLower (mSelect.mSelectRule.substr (5)); return Misc::StringUtils::lowerCase (mSelect.mSelectRule.substr (5));
} }

@ -37,10 +37,7 @@ namespace {
std::string lower_string(const std::string& str) std::string lower_string(const std::string& str)
{ {
std::string lowerCase; std::string lowerCase = Misc::StringUtils::lowerCase (str);
std::transform (str.begin(), str.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase; return lowerCase;
} }

@ -220,7 +220,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
if (world->canPlaceObject(mouseX, mouseY)) if (world->canPlaceObject(mouseX, mouseY))
world->placeObject(object, mouseX, mouseY); world->placeObject(object, mouseX, mouseY);
else else
world->dropObjectOnGround(object); world->dropObjectOnGround(world->getPlayer().getPlayer(), object);
MyGUI::PointerManager::getInstance().setPointer("arrow"); MyGUI::PointerManager::getInstance().setPointer("arrow");
@ -244,8 +244,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) ) if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) )
return; return;
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); MWWorld::Ptr object = MWBase::Environment::get().getWorld()->getFacedObject();
MWWorld::Ptr object = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle);
if (mode == GM_Console) if (mode == GM_Console)
MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object);

@ -6,6 +6,7 @@
#include <OgreCompositorChain.h> #include <OgreCompositorChain.h>
#include <OgreMaterial.h> #include <OgreMaterial.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <openengine/ogre/fader.hpp> #include <openengine/ogre/fader.hpp>
@ -16,6 +17,9 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include <components/esm/records.hpp>
namespace MWGui namespace MWGui
{ {
@ -214,27 +218,15 @@ namespace MWGui
void LoadingScreen::changeWallpaper () void LoadingScreen::changeWallpaper ()
{ {
if (mResources.isNull ()) if (mResources.isNull ())
{ mResources = Ogre::ResourceGroupManager::getSingleton ().findResourceNames ("General", "Splash_*.tga");
mResources = Ogre::StringVectorPtr (new Ogre::StringVector);
Ogre::StringVectorPtr resources = Ogre::ResourceGroupManager::getSingleton ().listResourceNames ("General", false);
for (Ogre::StringVector::const_iterator it = resources->begin(); it != resources->end(); ++it)
{
if (it->size() < 6)
continue;
std::string start = it->substr(0, 6);
boost::to_lower(start);
if (start == "splash")
mResources->push_back (*it);
}
}
if (mResources->size()) if (mResources->size())
{ {
std::string randomSplash = mResources->at (rand() % mResources->size()); std::string const & randomSplash = mResources->at (rand() % mResources->size());
Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, "General"); Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, "General");
mBackgroundImage->setImageTexture (randomSplash); mBackgroundImage->setImageTexture (randomSplash);
} }
else else

@ -80,9 +80,8 @@ void ToolTips::onFrame(float frameDuration)
|| (mWindowManager->getMode() == GM_Container) || (mWindowManager->getMode() == GM_Container)
|| (mWindowManager->getMode() == GM_Inventory))) || (mWindowManager->getMode() == GM_Inventory)))
{ {
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); mFocusObject = MWBase::Environment::get().getWorld()->getFacedObject();
mFocusObject = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle);
if (mFocusObject.isEmpty ()) if (mFocusObject.isEmpty ())
return; return;

@ -263,11 +263,11 @@ namespace MWMechanics
bool ActiveSpells::isSpellActive(std::string id) const bool ActiveSpells::isSpellActive(std::string id) const
{ {
boost::algorithm::to_lower(id); Misc::StringUtils::toLower(id);
for (TContainer::iterator iter = mSpells.begin(); iter != mSpells.end(); ++iter) for (TContainer::iterator iter = mSpells.begin(); iter != mSpells.end(); ++iter)
{ {
std::string left = iter->first; std::string left = iter->first;
boost::algorithm::to_lower(left); Misc::StringUtils::toLower(left);
if (iter->first == id) if (iter->first == id)
return true; return true;

@ -377,16 +377,6 @@ namespace MWMechanics
mUpdatePlayer = true; mUpdatePlayer = true;
} }
std::string toLower (const std::string& name)
{
std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
int MechanicsManager::getDerivedDisposition(const MWWorld::Ptr& ptr) int MechanicsManager::getDerivedDisposition(const MWWorld::Ptr& ptr)
{ {
MWMechanics::NpcStats npcSkill = MWWorld::Class::get(ptr).getNpcStats(ptr); MWMechanics::NpcStats npcSkill = MWWorld::Class::get(ptr).getNpcStats(ptr);
@ -398,7 +388,7 @@ namespace MWMechanics
MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr); MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr);
MWMechanics::NpcStats playerNpcStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); MWMechanics::NpcStats playerNpcStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
if (toLower(npc->mBase->mRace) == toLower(player->mBase->mRace)) x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispRaceMod")->getFloat(); if (Misc::StringUtils::lowerCase(npc->mBase->mRace) == Misc::StringUtils::lowerCase(player->mBase->mRace)) x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispRaceMod")->getFloat();
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityMult")->getFloat() x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityMult")->getFloat()
* (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityBase")->getFloat()); * (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityBase")->getFloat());
@ -408,21 +398,21 @@ namespace MWMechanics
std::string npcFaction = ""; std::string npcFaction = "";
if(!npcSkill.getFactionRanks().empty()) npcFaction = npcSkill.getFactionRanks().begin()->first; if(!npcSkill.getFactionRanks().empty()) npcFaction = npcSkill.getFactionRanks().begin()->first;
if (playerNpcStats.getFactionRanks().find(toLower(npcFaction)) != playerNpcStats.getFactionRanks().end()) if (playerNpcStats.getFactionRanks().find(Misc::StringUtils::lowerCase(npcFaction)) != playerNpcStats.getFactionRanks().end())
{ {
for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.begin(); for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(Misc::StringUtils::lowerCase(npcFaction))->mReactions.begin();
it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.end(); it++) it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(Misc::StringUtils::lowerCase(npcFaction))->mReactions.end(); it++)
{ {
if(toLower(it->mFaction) == toLower(npcFaction)) reaction = it->mReaction; if(Misc::StringUtils::lowerCase(it->mFaction) == Misc::StringUtils::lowerCase(npcFaction)) reaction = it->mReaction;
} }
rank = playerNpcStats.getFactionRanks().find(toLower(npcFaction))->second; rank = playerNpcStats.getFactionRanks().find(Misc::StringUtils::lowerCase(npcFaction))->second;
} }
else if (npcFaction != "") else if (npcFaction != "")
{ {
for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.begin(); for(std::vector<ESM::Faction::Reaction>::const_iterator it = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(Misc::StringUtils::lowerCase(npcFaction))->mReactions.begin();
it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(toLower(npcFaction))->mReactions.end();it++) it != MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(Misc::StringUtils::lowerCase(npcFaction))->mReactions.end();it++)
{ {
if(playerNpcStats.getFactionRanks().find(toLower(it->mFaction)) != playerNpcStats.getFactionRanks().end() ) if(playerNpcStats.getFactionRanks().find(Misc::StringUtils::lowerCase(it->mFaction)) != playerNpcStats.getFactionRanks().end() )
{ {
if(it->mReaction<reaction) reaction = it->mReaction; if(it->mReaction<reaction) reaction = it->mReaction;
} }

@ -90,6 +90,7 @@ namespace MWMechanics
virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type,
float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange); float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange);
void toLower(std::string npcFaction);
///< Perform a persuasion action on NPC ///< Perform a persuasion action on NPC
}; };
} }

@ -80,7 +80,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel; mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel;
mBodyPrefix = "b_n_" + mNpc->mRace; mBodyPrefix = "b_n_" + mNpc->mRace;
std::transform(mBodyPrefix.begin(), mBodyPrefix.end(), mBodyPrefix.begin(), ::tolower); Misc::StringUtils::toLower(mBodyPrefix);
mInsert = node; mInsert = node;
assert(mInsert); assert(mInsert);

@ -311,4 +311,9 @@ op 0x20001f4: AddSoulGem, explicit reference
op 0x20001f5: RemoveSoulGem op 0x20001f5: RemoveSoulGem
op 0x20001f6: RemoveSoulGem, explicit reference op 0x20001f6: RemoveSoulGem, explicit reference
op 0x20001f7: PlayBink op 0x20001f7: PlayBink
opcodes 0x20001f8-0x3ffffff unused op 0x20001f8: Drop
op 0x20001f9: Drop, explicit reference
op 0x20001fa: DropSoulGem
op 0x20001fb: DropSoulGem, explicit reference
opcodes 0x20001fa-0x3ffffff unused

@ -102,7 +102,7 @@ namespace MWScript
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
std::string cell = (runtime.getStringLiteral (runtime[0].mInteger)); std::string cell = (runtime.getStringLiteral (runtime[0].mInteger));
boost::algorithm::to_lower(cell); Misc::StringUtils::toLower(cell);
runtime.pop(); runtime.pop();
// "Will match complete or partial cells, so ShowMap, "Vivec" will show cells Vivec and Vivec, Fred's House as well." // "Will match complete or partial cells, so ShowMap, "Vivec" will show cells Vivec and Vivec, Fred's House as well."
@ -115,7 +115,7 @@ namespace MWScript
for (; it != cells.extEnd(); ++it) for (; it != cells.extEnd(); ++it)
{ {
std::string name = it->mName; std::string name = it->mName;
boost::algorithm::to_lower(name); Misc::StringUtils::toLower(name);
if (name.find(cell) != std::string::npos) if (name.find(cell) != std::string::npos)
MWBase::Environment::get().getWindowManager()->addVisitedLocation ( MWBase::Environment::get().getWindowManager()->addVisitedLocation (
it->mName, it->mName,

@ -383,6 +383,88 @@ namespace MWScript
} }
}; };
template<class R>
class OpDrop : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Integer amount = runtime[0].mInteger;
runtime.pop();
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
{
if (::Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item))
{
if(iter->getRefData().getCount() <= amount)
{
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
iter->getRefData().setCount(0);
}
else
{
int original = iter->getRefData().getCount();
iter->getRefData().setCount(amount);
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
iter->getRefData().setCount(original - amount);
}
break;
}
}
}
};
template<class R>
class OpDropSoulGem : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string soul = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
{
if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul))
{
if(iter->getRefData().getCount() <= 1)
{
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
iter->getRefData().setCount(0);
}
else
{
int original = iter->getRefData().getCount();
iter->getRefData().setCount(1);
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
iter->getRefData().setCount(original - 1);
}
break;
}
}
}
};
template <class R> template <class R>
class OpGetAttacked : public Interpreter::Opcode0 class OpGetAttacked : public Interpreter::Opcode0
{ {
@ -495,6 +577,10 @@ namespace MWScript
const int opcodeAddSoulGemExplicit = 0x20001f4; const int opcodeAddSoulGemExplicit = 0x20001f4;
const int opcodeRemoveSoulGem = 0x20001f5; const int opcodeRemoveSoulGem = 0x20001f5;
const int opcodeRemoveSoulGemExplicit = 0x20001f6; const int opcodeRemoveSoulGemExplicit = 0x20001f6;
const int opcodeDrop = 0x20001f8;
const int opcodeDropExplicit = 0x20001f9;
const int opcodeDropSoulGem = 0x20001fa;
const int opcodeDropSoulGemExplicit = 0x20001fb;
const int opcodeGetAttacked = 0x20001d3; const int opcodeGetAttacked = 0x20001d3;
const int opcodeGetAttackedExplicit = 0x20001d4; const int opcodeGetAttackedExplicit = 0x20001d4;
const int opcodeGetWeaponDrawn = 0x20001d7; const int opcodeGetWeaponDrawn = 0x20001d7;
@ -538,6 +624,8 @@ namespace MWScript
extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit); extensions.registerFunction ("geteffect", 'l', "l", opcodeGetEffect, opcodeGetEffectExplicit);
extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit); extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit);
extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit); extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
extensions.registerInstruction ("drop", "cl", opcodeDrop, opcodeDropExplicit);
extensions.registerInstruction ("dropsoulgem", "c", opcodeDropSoulGem, opcodeDropSoulGemExplicit);
extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit); extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit); extensions.registerFunction ("getweapondrawn", 'l', "", opcodeGetWeaponDrawn, opcodeGetWeaponDrawnExplicit);
extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit); extensions.registerFunction ("getspelleffects", 'l', "c", opcodeGetSpellEffects, opcodeGetSpellEffectsExplicit);
@ -576,6 +664,10 @@ namespace MWScript
interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>); interpreter.installSegment5 (opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>);
interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>); interpreter.installSegment5 (opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>); interpreter.installSegment5 (opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
interpreter.installSegment5 (opcodeDrop, new OpDrop<ImplicitRef>);
interpreter.installSegment5 (opcodeDropExplicit, new OpDrop<ExplicitRef>);
interpreter.installSegment5 (opcodeDropSoulGem, new OpDropSoulGem<ImplicitRef>);
interpreter.installSegment5 (opcodeDropSoulGemExplicit, new OpDropSoulGem<ExplicitRef>);
interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>); interpreter.installSegment5 (opcodeGetAttacked, new OpGetAttacked<ImplicitRef>);
interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>); interpreter.installSegment5 (opcodeGetAttackedExplicit, new OpGetAttacked<ExplicitRef>);
interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>); interpreter.installSegment5 (opcodeGetWeaponDrawn, new OpGetWeaponDrawn<ImplicitRef>);

@ -512,7 +512,7 @@ namespace MWScript
factionID = runtime.getStringLiteral (runtime[0].mInteger); factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
} }
boost::algorithm::to_lower(factionID); Misc::StringUtils::toLower(factionID);
if(factionID != "") if(factionID != "")
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
@ -541,7 +541,7 @@ namespace MWScript
factionID = runtime.getStringLiteral (runtime[0].mInteger); factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
} }
boost::algorithm::to_lower(factionID); Misc::StringUtils::toLower(factionID);
if(factionID != "") if(factionID != "")
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
@ -574,7 +574,7 @@ namespace MWScript
factionID = runtime.getStringLiteral (runtime[0].mInteger); factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
} }
boost::algorithm::to_lower(factionID); Misc::StringUtils::toLower(factionID);
if(factionID != "") if(factionID != "")
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
@ -612,7 +612,7 @@ namespace MWScript
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first;
} }
} }
boost::algorithm::to_lower(factionID); Misc::StringUtils::toLower(factionID);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
if(factionID!="") if(factionID!="")
{ {
@ -674,7 +674,7 @@ namespace MWScript
{ {
MWWorld::Ptr ptr = R()(runtime); MWWorld::Ptr ptr = R()(runtime);
runtime.push (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition()); runtime.push (MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr));
} }
}; };
@ -714,7 +714,7 @@ namespace MWScript
if (factionId.empty()) if (factionId.empty())
throw std::runtime_error ("failed to determine faction"); throw std::runtime_error ("failed to determine faction");
boost::algorithm::to_lower (factionId); Misc::StringUtils::toLower (factionId);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
runtime.push ( runtime.push (
@ -750,7 +750,7 @@ namespace MWScript
if (factionId.empty()) if (factionId.empty())
throw std::runtime_error ("failed to determine faction"); throw std::runtime_error ("failed to determine faction");
boost::algorithm::to_lower (factionId); Misc::StringUtils::toLower (factionId);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, value); MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, value);
@ -785,7 +785,7 @@ namespace MWScript
if (factionId.empty()) if (factionId.empty())
throw std::runtime_error ("failed to determine faction"); throw std::runtime_error ("failed to determine faction");
boost::algorithm::to_lower (factionId); Misc::StringUtils::toLower (factionId);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId,
@ -830,11 +830,11 @@ namespace MWScript
MWWorld::Ptr ptr = R()(runtime); MWWorld::Ptr ptr = R()(runtime);
std::string race = runtime.getStringLiteral(runtime[0].mInteger); std::string race = runtime.getStringLiteral(runtime[0].mInteger);
boost::algorithm::to_lower(race); Misc::StringUtils::toLower(race);
runtime.pop(); runtime.pop();
std::string npcRace = ptr.get<ESM::NPC>()->mBase->mRace; std::string npcRace = ptr.get<ESM::NPC>()->mBase->mRace;
boost::algorithm::to_lower(npcRace); Misc::StringUtils::toLower(npcRace);
runtime.push (npcRace == race); runtime.push (npcRace == race);
} }
@ -878,7 +878,7 @@ namespace MWScript
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first; factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().begin()->first;
} }
} }
boost::algorithm::to_lower(factionID); Misc::StringUtils::toLower(factionID);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
if(factionID!="") if(factionID!="")
{ {
@ -929,7 +929,7 @@ namespace MWScript
if(factionID!="") if(factionID!="")
{ {
std::set<std::string>& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled (); std::set<std::string>& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled ();
boost::algorithm::to_lower(factionID); Misc::StringUtils::toLower(factionID);
expelled.insert(factionID); expelled.insert(factionID);
} }
} }
@ -965,7 +965,7 @@ namespace MWScript
if(factionID!="") if(factionID!="")
{ {
std::set<std::string>& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled (); std::set<std::string>& expelled = MWWorld::Class::get(player).getNpcStats(player).getExpelled ();
boost::algorithm::to_lower(factionID); Misc::StringUtils::toLower(factionID);
expelled.erase (factionID); expelled.erase (factionID);
} }
} }

@ -2,6 +2,7 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "inventorystore.hpp" #include "inventorystore.hpp"
#include "player.hpp" #include "player.hpp"
@ -15,8 +16,7 @@ namespace MWWorld
void ActionEquip::executeImp (const Ptr& actor) void ActionEquip::executeImp (const Ptr& actor)
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor);
MWWorld::InventoryStore& invStore = MWWorld::Class::get(player).getInventoryStore(player);
// slots that this item can be equipped in // slots that this item can be equipped in
std::pair<std::vector<int>, bool> slots = MWWorld::Class::get(getTarget()).getEquipmentSlots(getTarget()); std::pair<std::vector<int>, bool> slots = MWWorld::Class::get(getTarget()).getEquipmentSlots(getTarget());
@ -33,10 +33,60 @@ namespace MWWorld
assert(it != invStore.end()); assert(it != invStore.end());
std::string npcRace = actor.get<ESM::NPC>()->mBase->mRace;
// equip the item in the first free slot // equip the item in the first free slot
for (std::vector<int>::const_iterator slot=slots.first.begin(); for (std::vector<int>::const_iterator slot=slots.first.begin();
slot!=slots.first.end(); ++slot) slot!=slots.first.end(); ++slot)
{ {
// Beast races cannot equip shoes / boots, or full helms (head part vs hair part)
if(npcRace == "argonian" || npcRace == "khajiit")
{
if(*slot == MWWorld::InventoryStore::Slot_Helmet){
std::vector<ESM::PartReference> parts;
if(it.getType() == MWWorld::ContainerStore::Type_Clothing)
parts = it->get<ESM::Clothing>()->mBase->mParts.mParts;
else
parts = it->get<ESM::Armor>()->mBase->mParts.mParts;
bool allow = true;
for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr)
{
if((*itr).mPart == ESM::PartReferenceType::PRT_Head)
{
if(actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() )
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage13}", std::vector<std::string>());
allow = false;
break;
}
}
if(!allow)
break;
}
if (*slot == MWWorld::InventoryStore::Slot_Boots)
{
// Only notify the player, not npcs
if(actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer() )
{
if(it.getType() == MWWorld::ContainerStore::Type_Clothing){ // It's shoes
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage15}", std::vector<std::string>());
}
else // It's boots
{
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage14}", std::vector<std::string>());
}
}
break;
}
}
// if all slots are occupied, replace the last slot // if all slots are occupied, replace the last slot
if (slot == --slots.first.end()) if (slot == --slots.first.end())
{ {

@ -153,10 +153,7 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
if (cell.mState==Ptr::CellStore::State_Preloaded) if (cell.mState==Ptr::CellStore::State_Preloaded)
{ {
std::string lowerCase; std::string lowerCase = Misc::StringUtils::lowerCase(name);
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase)) if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase))
{ {

@ -56,10 +56,7 @@ namespace MWWorld
// Get each reference in turn // Get each reference in turn
while (mCell->getNextRef (esm, ref)) while (mCell->getNextRef (esm, ref))
{ {
std::string lowerCase; std::string lowerCase = Misc::StringUtils::lowerCase (ref.mRefID);
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
mIds.push_back (lowerCase); mIds.push_back (lowerCase);
} }
@ -82,10 +79,7 @@ namespace MWWorld
// Get each reference in turn // Get each reference in turn
while(mCell->getNextRef(esm, ref)) while(mCell->getNextRef(esm, ref))
{ {
std::string lowerCase; std::string lowerCase = Misc::StringUtils::lowerCase(ref.mRefID);
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
int rec = store.find(ref.mRefID); int rec = store.find(ref.mRefID);

@ -37,7 +37,7 @@ namespace
bool compare_string_ci(std::string str1, std::string str2) bool compare_string_ci(std::string str1, std::string str2)
{ {
boost::algorithm::to_lower(str1); Misc::StringUtils::toLower(str1);
return str1 == str2; return str1 == str2;
} }
} }

@ -43,7 +43,7 @@ namespace MWWorld
return mEngine; return mEngine;
} }
std::pair<std::string, float> PhysicsSystem::getFacedHandle (MWWorld::World& world) std::pair<float, std::string> PhysicsSystem::getFacedHandle (MWWorld::World& world, float queryDistance)
{ {
btVector3 dir(0, 1, 0); btVector3 dir(0, 1, 0);
dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch);
@ -56,11 +56,14 @@ namespace MWWorld
mPlayerData.eyepos.z); mPlayerData.eyepos.z);
origin += dir * 5; origin += dir * 5;
btVector3 dest = origin + dir * 500; btVector3 dest = origin + dir * queryDistance;
return mEngine->rayTest(origin, dest); std::pair <std::string, float> result;
/*auto*/ result = mEngine->rayTest(origin, dest);
result.second *= queryDistance;
return std::make_pair (result.second, result.first);
} }
std::vector < std::pair <float, std::string> > PhysicsSystem::getFacedObjects () std::vector < std::pair <float, std::string> > PhysicsSystem::getFacedHandles (float queryDistance)
{ {
btVector3 dir(0, 1, 0); btVector3 dir(0, 1, 0);
dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch);
@ -73,22 +76,32 @@ namespace MWWorld
mPlayerData.eyepos.z); mPlayerData.eyepos.z);
origin += dir * 5; origin += dir * 5;
btVector3 dest = origin + dir * 500; btVector3 dest = origin + dir * queryDistance;
return mEngine->rayTest2(origin, dest); std::vector < std::pair <float, std::string> > results;
/* auto */ results = mEngine->rayTest2(origin, dest);
std::vector < std::pair <float, std::string> >::iterator i;
for (/* auto */ i = results.begin (); i != results.end (); ++i)
i->first *= queryDistance;
return results;
} }
std::vector < std::pair <float, std::string> > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) std::vector < std::pair <float, std::string> > PhysicsSystem::getFacedHandles (float mouseX, float mouseY, float queryDistance)
{ {
Ray ray = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); Ray ray = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY);
Ogre::Vector3 from = ray.getOrigin(); Ogre::Vector3 from = ray.getOrigin();
Ogre::Vector3 to = ray.getPoint(500); /// \todo make this distance (ray length) configurable Ogre::Vector3 to = ray.getPoint(queryDistance);
btVector3 _from, _to; btVector3 _from, _to;
// OGRE to MW coordinates // OGRE to MW coordinates
_from = btVector3(from.x, -from.z, from.y); _from = btVector3(from.x, -from.z, from.y);
_to = btVector3(to.x, -to.z, to.y); _to = btVector3(to.x, -to.z, to.y);
return mEngine->rayTest2(_from,_to); std::vector < std::pair <float, std::string> > results;
/* auto */ results = mEngine->rayTest2(_from,_to);
std::vector < std::pair <float, std::string> >::iterator i;
for (/* auto */ i = results.begin (); i != results.end (); ++i)
i->first *= queryDistance;
return results;
} }
void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight) void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight)
@ -110,7 +123,7 @@ namespace MWWorld
Ray centerRay = mRender.getCamera()->getCameraToViewportRay( Ray centerRay = mRender.getCamera()->getCameraToViewportRay(
mRender.getViewport()->getWidth()/2, mRender.getViewport()->getWidth()/2,
mRender.getViewport()->getHeight()/2); mRender.getViewport()->getHeight()/2);
btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable btVector3 result(centerRay.getPoint(extent).x,-centerRay.getPoint(extent).z,centerRay.getPoint(extent).y);
return result; return result;
} }
@ -118,7 +131,7 @@ namespace MWWorld
{ {
//get a ray pointing to the center of the viewport //get a ray pointing to the center of the viewport
Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY);
btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable btVector3 result(centerRay.getPoint(extent).x,-centerRay.getPoint(extent).z,centerRay.getPoint(extent).y);
return result; return result;
} }

@ -41,14 +41,13 @@ namespace MWWorld
bool toggleCollisionMode(); bool toggleCollisionMode();
std::pair<std::string, float> getFacedHandle (MWWorld::World& world); std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance);
std::vector < std::pair <float, std::string> > getFacedHandles (float queryDistance);
std::vector < std::pair <float, std::string> > getFacedHandles (float mouseX, float mouseY, float queryDistance);
btVector3 getRayPoint(float extent); btVector3 getRayPoint(float extent);
btVector3 getRayPoint(float extent, float mouseX, float mouseY); btVector3 getRayPoint(float extent, float mouseX, float mouseY);
std::vector < std::pair <float, std::string> > getFacedObjects ();
std::vector < std::pair <float, std::string> > getFacedObjects (float mouseX, float mouseY);
// cast ray, return true if it hit something // cast ray, return true if it hit something
bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to);

@ -497,7 +497,7 @@ void WeatherManager::update(float duration)
if (exterior) if (exterior)
{ {
std::string regionstr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion; std::string regionstr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion;
boost::algorithm::to_lower(regionstr); Misc::StringUtils::toLower(regionstr);
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
{ {

@ -170,10 +170,10 @@ namespace MWWorld
World::World (OEngine::Render::OgreRenderer& renderer, World::World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame,
ToUTF8::Utf8Encoder* encoder, std::map<std::string,std::string> fallbackMap) ToUTF8::Utf8Encoder* encoder, std::map<std::string,std::string> fallbackMap, int mActivationDistanceOverride)
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
mSky (true), mCells (mStore, mEsm), mSky (true), mCells (mStore, mEsm),
mNumFacing(0) mNumFacing(0), mActivationDistanceOverride (mActivationDistanceOverride)
{ {
mPhysics = new PhysicsSystem(renderer); mPhysics = new PhysicsSystem(renderer);
mPhysEngine = mPhysics->getEngine(); mPhysEngine = mPhysics->getEngine();
@ -573,23 +573,55 @@ namespace MWWorld
return mWorldScene->markCellAsUnchanged(); return mWorldScene->markCellAsUnchanged();
} }
std::string World::getFacedHandle() float World::getMaxActivationDistance ()
{ {
if (mActivationDistanceOverride >= 0)
return mActivationDistanceOverride;
return (std::max) (getNpcActivationDistance (), getObjectActivationDistance ());
}
float World::getNpcActivationDistance ()
{
if (mActivationDistanceOverride >= 0)
return mActivationDistanceOverride;
return getStore().get<ESM::GameSetting>().find ("iMaxActivateDist")->getInt()*5/4;
}
float World::getObjectActivationDistance ()
{
if (mActivationDistanceOverride >= 0)
return mActivationDistanceOverride;
return getStore().get<ESM::GameSetting>().find ("iMaxActivateDist")->getInt();
}
MWWorld::Ptr World::getFacedObject()
{
std::pair<float, std::string> result;
if (!mRendering->occlusionQuerySupported()) if (!mRendering->occlusionQuerySupported())
{ result = mPhysics->getFacedHandle (*this, getMaxActivationDistance ());
std::pair<std::string, float> result = mPhysics->getFacedHandle (*this); else
result = std::make_pair (mFacedDistance, mFacedHandle);
if (result.first.empty() || if (result.second.empty())
result.second>getStore().get<ESM::GameSetting>().find ("iMaxActivateDist")->getInt()) return MWWorld::Ptr ();
return "";
return result.first; MWWorld::Ptr object = searchPtrViaHandle (result.second);
}
float ActivationDistance;
if (object.getTypeName ().find("NPC") != std::string::npos)
ActivationDistance = getNpcActivationDistance ();
else else
{ ActivationDistance = getObjectActivationDistance ();
// updated every few frames in update()
return mFacedHandle; if (result.first > ActivationDistance)
} return MWWorld::Ptr ();
return object;
} }
void World::deleteObject (const Ptr& ptr) void World::deleteObject (const Ptr& ptr)
@ -884,8 +916,6 @@ namespace MWWorld
void World::update (float duration, bool paused) void World::update (float duration, bool paused)
{ {
/// \todo split this function up into subfunctions
mWorldScene->update (duration, paused); mWorldScene->update (duration, paused);
float pitch, yaw; float pitch, yaw;
@ -895,8 +925,15 @@ namespace MWWorld
mWeatherManager->update (duration); mWeatherManager->update (duration);
performUpdateSceneQueries ();
updateWindowManager ();
}
void World::updateWindowManager ()
{
// inform the GUI about focused object // inform the GUI about focused object
MWWorld::Ptr object = searchPtrViaHandle(mFacedHandle); MWWorld::Ptr object = getFacedObject ();
MWBase::Environment::get().getWindowManager()->setFocusObject(object); MWBase::Environment::get().getWindowManager()->setFocusObject(object);
@ -918,7 +955,10 @@ namespace MWWorld
screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]); screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]);
} }
} }
}
void World::performUpdateSceneQueries ()
{
if (!mRendering->occlusionQuerySupported()) if (!mRendering->occlusionQuerySupported())
{ {
// cast a ray from player to sun to detect if the sun is visible // cast a ray from player to sun to detect if the sun is visible
@ -937,119 +977,152 @@ namespace MWWorld
MWRender::OcclusionQuery* query = mRendering->getOcclusionQuery(); MWRender::OcclusionQuery* query = mRendering->getOcclusionQuery();
if (!query->occlusionTestPending()) if (!query->occlusionTestPending())
{ {
// get result of last query processFacedQueryResults (query);
if (mNumFacing == 0) mFacedHandle = ""; beginFacedQueryProcess (query);
else if (mNumFacing == 1) }
{ }
bool result = query->getTestResult(); }
mFacedHandle = result ? mFaced1Name : "";
}
else if (mNumFacing == 2)
{
bool result = query->getTestResult();
mFacedHandle = result ? mFaced2Name : mFaced1Name;
}
// send new query void World::processFacedQueryResults (MWRender::OcclusionQuery* query)
// figure out which object we want to test against {
std::vector < std::pair < float, std::string > > results; // get result of last query
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) if (mNumFacing == 0)
{ {
float x, y; mFacedHandle = "";
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); mFacedDistance = FLT_MAX;
results = mPhysics->getFacedObjects(x, y); }
} else if (mNumFacing == 1)
else {
results = mPhysics->getFacedObjects(); bool result = query->getTestResult();
mFacedHandle = result ? mFaced1Name : "";
mFacedDistance = result ? mFaced1Distance : FLT_MAX;
}
else if (mNumFacing == 2)
{
bool result = query->getTestResult();
mFacedHandle = result ? mFaced2Name : mFaced1Name;
mFacedDistance = result ? mFaced1Distance : mFaced1Distance;
}
}
// ignore the player and other things we're not interested in void World::beginFacedQueryProcess (MWRender::OcclusionQuery* query)
std::vector < std::pair < float, std::string > >::iterator it = results.begin(); {
while (it != results.end()) // send new query
{ // figure out which object we want to test against
if ( (*it).second.find("HeightField") != std::string::npos // not interested in terrain std::vector < std::pair < float, std::string > > results;
|| getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) // not interested in player (unless you want to talk to yourself) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
it = results.erase(it); float x, y;
} MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
else results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ());
++it; }
} else
{
results = mPhysics->getFacedHandles(getMaxActivationDistance ());
}
if (results.size() == 0) // ignore the player and other things we're not interested in
{ std::vector < std::pair < float, std::string > >::iterator it = results.begin();
mNumFacing = 0; while (it != results.end())
} {
else if (results.size() == 1) if ( (*it).second.find("HeightField") != std::string::npos // not interested in terrain
{ || getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) // not interested in player (unless you want to talk to yourself)
mFaced1 = getPtrViaHandle(results.front().second); {
mFaced1Name = results.front().second; it = results.erase(it);
mNumFacing = 1; }
else
++it;
}
btVector3 p; if (results.size() == 0)
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) {
{ mNumFacing = 0;
float x, y; }
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); else if (results.size() == 1)
p = mPhysics->getRayPoint(results.front().first, x, y); {
} beginSingleFacedQueryProcess (query, results);
else }
p = mPhysics->getRayPoint(results.front().first); else
Ogre::Vector3 pos(p.x(), p.z(), -p.y()); {
Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode(); beginDoubleFacedQueryProcess (query, results);
}
}
//std::cout << "Num facing 1 : " << mFaced1Name << std::endl; void World::beginSingleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results)
//std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl; {
mFaced1 = getPtrViaHandle(results.front().second);
mFaced1Name = results.front().second;
mFaced1Distance = results.front().first;
mNumFacing = 1;
query->occlusionTest(pos, node); btVector3 p;
} if (MWBase::Environment::get().getWindowManager()->isGuiMode())
else {
{ float x, y;
mFaced1Name = results.front().second; MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
mFaced2Name = results[1].second; p = mPhysics->getRayPoint(results.front().first, x, y);
mFaced1 = getPtrViaHandle(results.front().second); }
mFaced2 = getPtrViaHandle(results[1].second); else
mNumFacing = 2; p = mPhysics->getRayPoint(results.front().first);
Ogre::Vector3 pos(p.x(), p.z(), -p.y());
btVector3 p; Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode();
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
float x, y;
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
p = mPhysics->getRayPoint(results[1].first, x, y);
}
else
p = mPhysics->getRayPoint(results[1].first);
Ogre::Vector3 pos(p.x(), p.z(), -p.y());
Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode();
Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode();
// no need to test if the first node is not occluder //std::cout << "Num facing 1 : " << mFaced1Name << std::endl;
if (!query->isPotentialOccluder(node1) && (mFaced1.getTypeName().find("Static") == std::string::npos)) //std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl;
{
mFacedHandle = mFaced1Name;
//std::cout << "node1 Not an occluder" << std::endl;
return;
}
// no need to test if the second object is static (thus cannot be activated) query->occlusionTest(pos, node);
if (mFaced2.getTypeName().find("Static") != std::string::npos) }
{
mFacedHandle = mFaced1Name;
return;
}
// work around door problems void World::beginDoubleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results)
if (mFaced1.getTypeName().find("Static") != std::string::npos {
&& mFaced2.getTypeName().find("Door") != std::string::npos) mFaced1Name = results.at (0).second;
{ mFaced2Name = results.at (1).second;
mFacedHandle = mFaced2Name; mFaced1Distance = results.at (0).first;
return; mFaced2Distance = results.at (1).first;
} mFaced1 = getPtrViaHandle(results.at (0).second);
mFaced2 = getPtrViaHandle(results.at (1).second);
mNumFacing = 2;
query->occlusionTest(pos, node2); btVector3 p;
} if (MWBase::Environment::get().getWindowManager()->isGuiMode())
} {
float x, y;
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
p = mPhysics->getRayPoint(results.at (1).first, x, y);
} }
else
p = mPhysics->getRayPoint(results.at (1).first);
Ogre::Vector3 pos(p.x(), p.z(), -p.y());
Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode();
Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode();
// no need to test if the first node is not occluder
if (!query->isPotentialOccluder(node1) && (mFaced1.getTypeName().find("Static") == std::string::npos))
{
mFacedHandle = mFaced1Name;
mFacedDistance = mFaced1Distance;
//std::cout << "node1 Not an occluder" << std::endl;
return;
}
// no need to test if the second object is static (thus cannot be activated)
if (mFaced2.getTypeName().find("Static") != std::string::npos)
{
mFacedHandle = mFaced1Name;
mFacedDistance = mFaced1Distance;
return;
}
// work around door problems
if (mFaced1.getTypeName().find("Static") != std::string::npos
&& mFaced2.getTypeName().find("Door") != std::string::npos)
{
mFacedHandle = mFaced2Name;
mFacedDistance = mFaced2Distance;
return;
}
query->occlusionTest(pos, node2);
} }
bool World::isCellExterior() const bool World::isCellExterior() const
@ -1213,12 +1286,12 @@ namespace MWWorld
} }
} }
void World::dropObjectOnGround (const Ptr& object) void World::dropObjectOnGround (const Ptr& actor, const Ptr& object)
{ {
MWWorld::Ptr::CellStore* cell = getPlayer().getPlayer().getCell(); MWWorld::Ptr::CellStore* cell = actor.getCell();
ESM::Position pos = ESM::Position pos =
getPlayer().getPlayer().getRefData().getPosition(); actor.getRefData().getPosition();
Ogre::Vector3 orig = Ogre::Vector3 orig =
Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]); Ogre::Vector3(pos.pos[0], pos.pos[1], pos.pos[2]);

@ -71,11 +71,15 @@ namespace MWWorld
Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore); Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore);
int mActivationDistanceOverride;
std::string mFacedHandle; std::string mFacedHandle;
float mFacedDistance;
Ptr mFaced1; Ptr mFaced1;
Ptr mFaced2; Ptr mFaced2;
std::string mFaced1Name; std::string mFaced1Name;
std::string mFaced2Name; std::string mFaced2Name;
float mFaced1Distance;
float mFaced2Distance;
int mNumFacing; int mNumFacing;
std::map<std::string,std::string> mFallback; std::map<std::string,std::string> mFallback;
@ -90,12 +94,23 @@ namespace MWWorld
virtual void virtual void
copyObjectToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); copyObjectToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos);
void updateWindowManager ();
void performUpdateSceneQueries ();
void processFacedQueryResults (MWRender::OcclusionQuery* query);
void beginFacedQueryProcess (MWRender::OcclusionQuery* query);
void beginSingleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results);
void beginDoubleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results);
float getMaxActivationDistance ();
float getNpcActivationDistance ();
float getObjectActivationDistance ();
public: public:
World (OEngine::Render::OgreRenderer& renderer, World (OEngine::Render::OgreRenderer& renderer,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame,
ToUTF8::Utf8Encoder* encoder, std::map<std::string,std::string> fallbackMap); ToUTF8::Utf8Encoder* encoder, std::map<std::string,std::string> fallbackMap, int mActivationDistanceOverride);
virtual ~World(); virtual ~World();
@ -217,8 +232,8 @@ namespace MWWorld
virtual void markCellAsUnchanged(); virtual void markCellAsUnchanged();
virtual std::string getFacedHandle(); virtual MWWorld::Ptr getFacedObject();
///< Return handle of the object the player is looking at ///< Return pointer to the object the player is looking at, if it is within activation range
virtual void deleteObject (const Ptr& ptr); virtual void deleteObject (const Ptr& ptr);
@ -296,7 +311,7 @@ namespace MWWorld
/// @param cursor Y (relative 0-1) /// @param cursor Y (relative 0-1)
/// @return true if the object was placed, or false if it was rejected because the position is too far away /// @return true if the object was placed, or false if it was rejected because the position is too far away
virtual void dropObjectOnGround (const Ptr& object); virtual void dropObjectOnGround (const Ptr& actor, const Ptr& object);
virtual bool canPlaceObject(float cursorX, float cursorY); virtual bool canPlaceObject(float cursorX, float cursorY);
///< @return true if it is possible to place on object at specified cursor location ///< @return true if it is possible to place on object at specified cursor location

@ -37,28 +37,142 @@ namespace
using namespace Ogre; using namespace Ogre;
using namespace Bsa; using namespace Bsa;
struct ciLessBoost : std::binary_function<std::string, std::string, bool> struct PathPatternMatcher
{ {
bool operator() (const std::string & s1, const std::string & s2) const { PathPatternMatcher (char const * pattern) : pattern (pattern)
//case insensitive version of is_less {
return boost::ilexicographical_compare(s1, s2); }
bool operator () (char const * input)
{
char const * p = pattern;
char const * i = input;
while (*p && *i)
{
if (*p == '*')
{
++p;
while (*i && *i != *p && *i != '/' && *i != '\\')
++i;
}
else
if (*p == '?')
{
if (*i == '/' || *i == '\\')
break;
++i, ++p;
}
if (*p == '/' || *p == '\\')
{
if (*i != '/' && *i != '\\')
break;
++i, ++p;
}
else
{
if (*i != *p)
break;
++i, ++p;
}
}
return *p == 0 && *i == 0;
} }
private:
char const * pattern;
}; };
struct pathComparer struct FileNameGatherer
{ {
private: StringVectorPtr ptr;
std::string find;
public: FileNameGatherer (StringVectorPtr ptr) : ptr (ptr)
pathComparer(const std::string& toFind) : find(toFind) { } {
}
bool operator() (const std::string& other) void operator () (std::string const & filename) const
{ {
return boost::iequals(find, other); ptr->push_back (filename);
} }
}; };
struct FileInfoGatherer
{
Archive const * archive;
FileInfoListPtr ptr;
FileInfoGatherer (Archive const * archive, FileInfoListPtr ptr) :
archive (archive), ptr (ptr)
{
}
void operator () (std::string filename) const
{
FileInfo fi;
std::size_t pt = filename.rfind ('/');
if (pt == std::string::npos)
pt = 0;
fi.archive = const_cast <Archive *> (archive);
fi.path = filename.substr (0, pt);
fi.filename = filename.substr (pt);
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
};
template <typename file_iterator, typename filename_extractor, typename match_handler>
void matchFiles (bool recursive, std::string const & pattern, file_iterator begin, file_iterator end, filename_extractor filenameExtractor, match_handler matchHandler)
{
if (recursive && pattern == "*")
{
for (file_iterator i = begin; i != end; ++i)
matchHandler (filenameExtractor (*i));
}
else
{
PathPatternMatcher matcher (pattern.c_str ());
if (recursive)
{
for (file_iterator i = begin; i != end; ++i)
{
char const * filename = filenameExtractor (*i);
char const * matchable_part = filename;
for (char const * j = matchable_part; *j; ++j)
{
if (*j == '/' || *j == '\\')
matchable_part = j + 1;
}
if (matcher (matchable_part))
matchHandler (filename);
}
}
else
{
for (file_iterator i = begin; i != end; ++i)
{
char const * filename = filenameExtractor (*i);
if (matcher (filename))
matchHandler (filename);
}
}
}
}
static bool fsstrict = false; static bool fsstrict = false;
/// An OGRE Archive wrapping a BSAFile archive /// An OGRE Archive wrapping a BSAFile archive
@ -94,6 +208,11 @@ class DirArchive: public Ogre::Archive
return mIndex.find (normalized); return mIndex.find (normalized);
} }
static char const * extractFilename (index::value_type const & entry)
{
return entry.first.c_str ();
}
public: public:
DirArchive(const String& name) DirArchive(const String& name)
@ -143,27 +262,20 @@ public:
StringVectorPtr list(bool recursive = true, bool dirs = false) StringVectorPtr list(bool recursive = true, bool dirs = false)
{ {
StringVectorPtr ptr = StringVectorPtr(new StringVector()); return find ("*", recursive, dirs);
std::cout << "DirArchive<" << getName () << ">::list" << std::endl;
return ptr;
} }
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false) FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false)
{ {
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); return findFileInfo ("*", recursive, dirs);
std::cout << "DirArchive<" << getName () << ">::listFileInfo" << std::endl;
return ptr;
} }
StringVectorPtr find(const String& pattern, bool recursive = true, StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false) bool dirs = false)
{ {
std::string normalizedPattern = normalize_path (pattern.begin (), pattern.end ());
StringVectorPtr ptr = StringVectorPtr(new StringVector()); StringVectorPtr ptr = StringVectorPtr(new StringVector());
matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, FileNameGatherer (ptr));
if (pattern == "*")
for (index::const_iterator i = mIndex.begin (); i != mIndex.end (); ++i)
ptr->push_back (i->first);
return ptr; return ptr;
} }
@ -178,21 +290,20 @@ public:
bool dirs = false) const bool dirs = false) const
{ {
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
FileInfoGatherer gatherer (this, ptr);
std::string normalizedPattern = normalize_path (pattern.begin (), pattern.end ());
index::const_iterator i = lookup_filename (pattern); index::const_iterator i = mIndex.find (normalizedPattern);
if (i != mIndex.end ()) if (i != mIndex.end ())
{ {
FileInfo fi; gatherer (i->first);
}
std::size_t npos = i->first.rfind ('/'); else
{
fi.archive = this;
fi.filename = npos != -1 ? i->first.substr (npos) : i->first;
fi.path = npos != -1 ? i->first.substr (0, npos) : "";
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi); matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, gatherer);
} }
return ptr; return ptr;
@ -203,6 +314,11 @@ class BSAArchive : public Archive
{ {
BSAFile arc; BSAFile arc;
static char const * extractFilename (BSAFile::FileStruct const & entry)
{
return entry.name;
}
public: public:
BSAArchive(const String& name) BSAArchive(const String& name)
: Archive(name, "BSA") : Archive(name, "BSA")
@ -230,26 +346,18 @@ public:
return arc.exists(filename.c_str()); return arc.exists(filename.c_str());
} }
bool cexists(const String& filename) const {
return arc.exists(filename.c_str());
}
time_t getModifiedTime(const String&) { return 0; } time_t getModifiedTime(const String&) { return 0; }
// This is never called as far as I can see. // This is never called as far as I can see.
StringVectorPtr list(bool recursive = true, bool dirs = false) StringVectorPtr list(bool recursive = true, bool dirs = false)
{ {
//std::cout << "list(" << recursive << ", " << dirs << ")\n"; return find ("*", recursive, dirs);
StringVectorPtr ptr = StringVectorPtr(new StringVector());
return ptr;
} }
// Also never called. // Also never called.
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false) FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false)
{ {
//std::cout << "listFileInfo(" << recursive << ", " << dirs << ")\n"; return findFileInfo ("*", recursive, dirs);
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
return ptr;
} }
// After load() is called, find("*") is called once. It doesn't seem // After load() is called, find("*") is called once. It doesn't seem
@ -258,17 +366,9 @@ public:
StringVectorPtr find(const String& pattern, bool recursive = true, StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false) bool dirs = false)
{ {
//std::cout << "find(" << pattern << ", " << recursive StringVectorPtr ptr = StringVectorPtr(new StringVector());
// << ", " << dirs << ")\n"; matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileNameGatherer (ptr));
StringVectorPtr ptr = StringVectorPtr(new StringVector()); return ptr;
BSAFile::FileList const & files = arc.getList ();
if (pattern == "*")
for (BSAFile::FileList::const_iterator i = files.begin (); i != files.end (); ++i)
ptr->push_back (i->name);
return ptr;
} }
/* Gets called once for each of the ogre formats, *.program, /* Gets called once for each of the ogre formats, *.program,
@ -281,47 +381,9 @@ public:
*/ */
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true, FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false) const bool dirs = false) const
{
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
// Check if the file exists (only works for single files - wild
// cards and recursive search isn't implemented.)
if(cexists(pattern))
{
FileInfo fi;
fi.archive = this;
fi.filename = pattern;
// It apparently doesn't matter that we return bogus
// information
fi.path = "";
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
return ptr;
}
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false)
{ {
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileInfoGatherer (this, ptr));
// Check if the file exists (only works for single files - wild
// cards and recursive search isn't implemented.)
if(cexists(pattern))
{
FileInfo fi;
fi.archive = this;
fi.filename = pattern;
// It apparently doesn't matter that we return bogus
// information
fi.path = "";
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
return ptr; return ptr;
} }
}; };

@ -14,6 +14,7 @@
#include "stringparser.hpp" #include "stringparser.hpp"
#include "extensions.hpp" #include "extensions.hpp"
#include "context.hpp" #include "context.hpp"
#include <components/misc/stringops.hpp>
namespace Compiler namespace Compiler
{ {
@ -199,8 +200,8 @@ namespace Compiler
{ {
mMemberOp = false; mMemberOp = false;
std::string name2 = toLower (name); std::string name2 = Misc::StringUtils::lowerCase (name);
std::string id = toLower (mExplicit); std::string id = Misc::StringUtils::lowerCase (mExplicit);
char type = getContext().getMemberType (name2, id); char type = getContext().getMemberType (name2, id);
@ -285,7 +286,7 @@ namespace Compiler
{ {
start(); start();
std::string name2 = toLower (name); std::string name2 = Misc::StringUtils::lowerCase (name);
char type = mLocals.getType (name2); char type = mLocals.getType (name2);

@ -8,6 +8,7 @@
#include "locals.hpp" #include "locals.hpp"
#include "generator.hpp" #include "generator.hpp"
#include "extensions.hpp" #include "extensions.hpp"
#include <components/misc/stringops.hpp>
namespace Compiler namespace Compiler
{ {
@ -91,13 +92,13 @@ namespace Compiler
return false; return false;
} }
std::string name2 = toLower (name); std::string name2 = Misc::StringUtils::lowerCase (name);
char type = mLocals.getType (name2); char type = mLocals.getType (name2);
if (type!=' ') if (type!=' ')
{ {
getErrorHandler().error ("can't re-declare local variable", loc); getErrorHandler().error ("catoLowern't re-declare local variable", loc);
SkipParser skip (getErrorHandler(), getContext()); SkipParser skip (getErrorHandler(), getContext());
scanner.scan (skip); scanner.scan (skip);
return false; return false;
@ -112,7 +113,7 @@ namespace Compiler
if (mState==SetState) if (mState==SetState)
{ {
std::string name2 = toLower (name); std::string name2 = Misc::StringUtils::lowerCase (name);
mName = name2; mName = name2;
// local variable? // local variable?
@ -138,7 +139,7 @@ namespace Compiler
if (mState==SetMemberVarState) if (mState==SetMemberVarState)
{ {
mMemberName = toLower (name); mMemberName = Misc::StringUtils::lowerCase (name);
char type = getContext().getMemberType (mMemberName, mName); char type = getContext().getMemberType (mMemberName, mName);
if (type!=' ') if (type!=' ')
@ -205,13 +206,13 @@ namespace Compiler
if (mState==BeginState && getContext().isId (name)) if (mState==BeginState && getContext().isId (name))
{ {
mState = PotentialExplicitState; mState = PotentialExplicitState;
mExplicit = toLower (name); mExplicit = Misc::StringUtils::lowerCase (name);
return true; return true;
} }
if (mState==BeginState && mAllowExpression) if (mState==BeginState && mAllowExpression)
{ {
std::string name2 = toLower (name); std::string name2 = Misc::StringUtils::lowerCase (name);
char type = mLocals.getType (name2); char type = mLocals.getType (name2);

@ -9,6 +9,8 @@
#include "exception.hpp" #include "exception.hpp"
#include "scanner.hpp" #include "scanner.hpp"
#include <components/misc/stringops.hpp>
namespace Compiler namespace Compiler
{ {
// Report the error and throw an exception. // Report the error and throw an exception.
@ -57,10 +59,7 @@ namespace Compiler
std::string Parser::toLower (const std::string& name) std::string Parser::toLower (const std::string& name)
{ {
std::string lowerCase; std::string lowerCase = Misc::StringUtils::lowerCase(name);
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase; return lowerCase;
} }

@ -11,6 +11,8 @@
#include "parser.hpp" #include "parser.hpp"
#include "extensions.hpp" #include "extensions.hpp"
#include <components/misc/stringops.hpp>
namespace Compiler namespace Compiler
{ {
bool Scanner::get (char& c) bool Scanner::get (char& c)
@ -268,11 +270,7 @@ namespace Compiler
int i = 0; int i = 0;
std::string lowerCase; std::string lowerCase = Misc::StringUtils::lowerCase(name);
lowerCase.reserve (name.size());
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
for (; keywords[i]; ++i) for (; keywords[i]; ++i)
if (lowerCase==keywords[i]) if (lowerCase==keywords[i])

@ -6,6 +6,7 @@
#include "scanner.hpp" #include "scanner.hpp"
#include "generator.hpp" #include "generator.hpp"
#include <components/misc/stringops.hpp>
namespace Compiler namespace Compiler
{ {
@ -22,7 +23,7 @@ namespace Compiler
{ {
start(); start();
if (mSmashCase) if (mSmashCase)
Generator::pushString (mCode, mLiterals, toLower (name)); Generator::pushString (mCode, mLiterals, Misc::StringUtils::lowerCase (name));
else else
Generator::pushString (mCode, mLiterals, name); Generator::pushString (mCode, mLiterals, name);

@ -3,7 +3,7 @@
#include <iostream> #include <iostream>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp> #include <../components/misc/stringops.hpp>
namespace Files namespace Files
{ {
@ -45,14 +45,14 @@ namespace Files
if( !acceptableExtensions.empty() ) if( !acceptableExtensions.empty() )
{ {
fileExtension = boost::filesystem::path (listIter->extension()).string(); fileExtension = boost::filesystem::path (listIter->extension()).string();
boost::algorithm::to_lower(fileExtension); Misc::StringUtils::toLower(fileExtension);
if(!containsVectorString(acceptableExtensions, fileExtension)) if(!containsVectorString(acceptableExtensions, fileExtension))
continue; continue;
} }
type = boost::filesystem::path (listIter->parent_path().leaf()).string(); type = boost::filesystem::path (listIter->parent_path().leaf()).string();
if (!strict) if (!strict)
boost::algorithm::to_lower(type); Misc::StringUtils::toLower(type);
mMap[type].push_back(*listIter); mMap[type].push_back(*listIter);
// std::cout << "Added path: " << listIter->string() << " in section "<< type <<std::endl; // std::cout << "Added path: " << listIter->string() << " in section "<< type <<std::endl;
@ -63,7 +63,7 @@ namespace Files
bool FileLibrary::containsSection(std::string sectionName, bool strict) bool FileLibrary::containsSection(std::string sectionName, bool strict)
{ {
if (!strict) if (!strict)
boost::algorithm::to_lower(sectionName); Misc::StringUtils::toLower(sectionName);
StringPathContMap::const_iterator mapIter = mMap.find(sectionName); StringPathContMap::const_iterator mapIter = mMap.find(sectionName);
if (mapIter == mMap.end()) if (mapIter == mMap.end())
return false; return false;
@ -75,7 +75,7 @@ namespace Files
const PathContainer* FileLibrary::section(std::string sectionName, bool strict) const PathContainer* FileLibrary::section(std::string sectionName, bool strict)
{ {
if (!strict) if (!strict)
boost::algorithm::to_lower(sectionName); Misc::StringUtils::toLower(sectionName);
StringPathContMap::const_iterator mapIter = mMap.find(sectionName); StringPathContMap::const_iterator mapIter = mMap.find(sectionName);
if (mapIter == mMap.end()) if (mapIter == mMap.end())
{ {

@ -4,6 +4,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <../components/misc/stringops.hpp>
namespace Files namespace Files
{ {
@ -87,7 +88,7 @@ bool isFile(const char *name)
if (!strict) if (!strict)
{ {
boost::algorithm::to_lower(toFindStr); Misc::StringUtils::toLower(toFindStr);
} }
for (Files::PathContainer::const_iterator it = list.begin(); it != list.end(); ++it) for (Files::PathContainer::const_iterator it = list.begin(); it != list.end(); ++it)
@ -99,7 +100,7 @@ bool isFile(const char *name)
if (!strict) if (!strict)
{ {
boost::algorithm::to_lower(fullPath); Misc::StringUtils::toLower(fullPath);
} }
if(endingMatches(fullPath, toFindStr)) if(endingMatches(fullPath, toFindStr))
{ {

@ -44,6 +44,7 @@
#include <extern/shiny/Main/Factory.hpp> #include <extern/shiny/Main/Factory.hpp>
#include <components/nif/node.hpp> #include <components/nif/node.hpp>
#include <components/misc/stringops.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/nifoverrides/nifoverrides.hpp> #include <components/nifoverrides/nifoverrides.hpp>
@ -1003,7 +1004,7 @@ public:
if(mSkelName.length() > 0 && mName != mSkelName) if(mSkelName.length() > 0 && mName != mSkelName)
fullname += "@skel="+mSkelName; fullname += "@skel="+mSkelName;
std::transform(fullname.begin(), fullname.end(), fullname.begin(), ::tolower); Misc::StringUtils::toLower(fullname);
Ogre::MeshPtr mesh = meshMgr.getByName(fullname); Ogre::MeshPtr mesh = meshMgr.getByName(fullname);
if(mesh.isNull()) if(mesh.isNull())
{ {
@ -1045,8 +1046,8 @@ static MeshPairMap sMeshPairMap;
MeshPairList NIFLoader::load(std::string name, std::string skelName, const std::string &group) MeshPairList NIFLoader::load(std::string name, std::string skelName, const std::string &group)
{ {
std::transform(name.begin(), name.end(), name.begin(), ::tolower); Misc::StringUtils::toLower(name);
std::transform(skelName.begin(), skelName.end(), skelName.begin(), ::tolower); Misc::StringUtils::toLower(skelName);
MeshPairMap::const_iterator meshiter = sMeshPairMap.find(name+"@skel="+skelName); MeshPairMap::const_iterator meshiter = sMeshPairMap.find(name+"@skel="+skelName);
if(meshiter != sMeshPairMap.end()) if(meshiter != sMeshPairMap.end())
@ -1159,7 +1160,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo
Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first); Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first);
if(ent->hasSkeleton()) if(ent->hasSkeleton())
{ {
std::transform(meshes[i].second.begin(), meshes[i].second.end(), meshes[i].second.begin(), ::tolower); Misc::StringUtils::toLower(meshes[i].second);
if(meshes[i].second.length() < filter.length() || if(meshes[i].second.length() < filter.length() ||
meshes[i].second.compare(0, filter.length(), filter) != 0) meshes[i].second.compare(0, filter.length(), filter) != 0)

@ -2,7 +2,8 @@
#include <OgreStringConverter.h> #include <OgreStringConverter.h>
#include <boost/algorithm/string.hpp> #include <../components/misc/stringops.hpp>
using namespace NifOverrides; using namespace NifOverrides;
@ -19,7 +20,7 @@ TransparencyResult Overrides::getTransparencyOverride(const std::string& texture
result.first = false; result.first = false;
std::string tex = texture; std::string tex = texture;
boost::to_lower(tex); Misc::StringUtils::toLower(tex);
Ogre::ConfigFile::SectionIterator seci = mTransparencyOverrides.getSectionIterator(); Ogre::ConfigFile::SectionIterator seci = mTransparencyOverrides.getSectionIterator();
while (seci.hasMoreElements()) while (seci.hasMoreElements())

Loading…
Cancel
Save