Merge branch 'master' of https://github.com/zinnschlag/openmw into enchanting-mechanics

This commit is contained in:
Miroslav Puda 2013-05-27 14:45:22 +02:00
commit 9e1eb8b3b1
20 changed files with 508 additions and 29 deletions

View file

@ -181,6 +181,12 @@ if (UNIX AND NOT APPLE)
find_package (Threads)
endif()
include (CheckIncludeFileCXX)
check_include_file_cxx(unordered_map HAVE_UNORDERED_MAP)
if (HAVE_UNORDERED_MAP)
add_definitions(-DHAVE_UNORDERED_MAP)
endif ()
set(BOOST_COMPONENTS system filesystem program_options thread date_time wave)

View file

@ -342,6 +342,8 @@ namespace MWBase
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
///< get all containers in active cells owned by this Npc
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
///< get all items in active cells owned by this Npc
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;

View file

@ -3,11 +3,39 @@
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
namespace
{
bool stacks (const MWWorld::Ptr& left, const MWWorld::Ptr& right)
{
if (left == right)
return true;
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (left.getContainerStore() && right.getContainerStore())
return left.getContainerStore()->stacks(left, right)
&& right.getContainerStore()->stacks(left, right);
if (left.getContainerStore())
return left.getContainerStore()->stacks(left, right);
if (right.getContainerStore())
return right.getContainerStore()->stacks(left, right);
MWWorld::ContainerStore store;
return store.stacks(left, right);
}
}
namespace MWGui
{
ContainerItemModel::ContainerItemModel(const std::vector<MWWorld::Ptr>& itemSources)
ContainerItemModel::ContainerItemModel(const std::vector<MWWorld::Ptr>& itemSources, const std::vector<MWWorld::Ptr>& worldItems)
: mItemSources(itemSources)
, mWorldItems(worldItems)
{
assert (mItemSources.size());
}
@ -65,8 +93,7 @@ void ContainerItemModel::removeItem (const ItemStack& item, size_t count)
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (*it == item.mBase || (store.stacks(*it, item.mBase) && item.mBase.getContainerStore()->stacks(*it, item.mBase)))
if (stacks(*it, item.mBase))
{
int refCount = it->getRefData().getCount();
it->getRefData().setCount(std::max(0, refCount - toRemove));
@ -76,6 +103,21 @@ void ContainerItemModel::removeItem (const ItemStack& item, size_t count)
}
}
}
for (std::vector<MWWorld::Ptr>::iterator source = mWorldItems.begin(); source != mWorldItems.end(); ++source)
{
if (stacks(*source, item.mBase))
{
int refCount = source->getRefData().getCount();
if (refCount - toRemove <= 0)
MWBase::Environment::get().getWorld()->deleteObject(*source);
else
source->getRefData().setCount(std::max(0, refCount - toRemove));
toRemove -= refCount;
if (toRemove <= 0)
return;
}
}
throw std::runtime_error("Not enough items to remove could be found");
}
@ -91,8 +133,7 @@ void ContainerItemModel::update()
std::vector<ItemStack>::iterator itemStack = mItems.begin();
for (; itemStack != mItems.end(); ++itemStack)
{
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (store.stacks(itemStack->mBase, *it) && it->getContainerStore()->stacks(itemStack->mBase, *it))
if (stacks(*it, itemStack->mBase))
{
// we already have an item stack of this kind, add to it
itemStack->mCount += it->getRefData().getCount();
@ -108,6 +149,26 @@ void ContainerItemModel::update()
}
}
}
for (std::vector<MWWorld::Ptr>::iterator source = mWorldItems.begin(); source != mWorldItems.end(); ++source)
{
std::vector<ItemStack>::iterator itemStack = mItems.begin();
for (; itemStack != mItems.end(); ++itemStack)
{
if (stacks(*source, itemStack->mBase))
{
// we already have an item stack of this kind, add to it
itemStack->mCount += source->getRefData().getCount();
break;
}
}
if (itemStack == mItems.end())
{
// no stack yet, create one
ItemStack newItem (*source, this, source->getRefData().getCount());
mItems.push_back(newItem);
}
}
}
}

View file

@ -11,7 +11,7 @@ namespace MWGui
class ContainerItemModel : public ItemModel
{
public:
ContainerItemModel (const std::vector<MWWorld::Ptr>& itemSources);
ContainerItemModel (const std::vector<MWWorld::Ptr>& itemSources, const std::vector<MWWorld::Ptr>& worldItems);
///< @note The order of elements \a itemSources matters here. The first element has the highest priority for removal,
/// while the last element will be used to add new items to.
@ -28,6 +28,7 @@ namespace MWGui
private:
std::vector<MWWorld::Ptr> mItemSources;
std::vector<MWWorld::Ptr> mWorldItems;
std::vector<ItemStack> mItems;
};

View file

@ -13,8 +13,6 @@ namespace MWGui
, mType(Type_Normal)
, mBase(base)
{
assert(base.getContainerStore());
if (MWWorld::Class::get(base).getEnchantment(base) != "")
mFlags |= Flag_Enchanted;
}
@ -31,18 +29,42 @@ namespace MWGui
{
if(mBase == other.mBase)
return true;
return mBase.getContainerStore()->stacks(mBase, other.mBase)
&& other.mBase.getContainerStore()->stacks(mBase, other.mBase);
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (mBase.getContainerStore() && other.mBase.getContainerStore())
return mBase.getContainerStore()->stacks(mBase, other.mBase)
&& other.mBase.getContainerStore()->stacks(mBase, other.mBase);
if (mBase.getContainerStore())
return mBase.getContainerStore()->stacks(mBase, other.mBase);
if (other.mBase.getContainerStore())
return other.mBase.getContainerStore()->stacks(mBase, other.mBase);
MWWorld::ContainerStore store;
return store.stacks(mBase, other.mBase);
}
bool operator == (const ItemStack& left, const ItemStack& right)
{
if (left.mType != right.mType)
return false;
if(left.mBase == right.mBase)
return true;
return left.mBase.getContainerStore()->stacks(left.mBase, right.mBase)
&& right.mBase.getContainerStore()->stacks(left.mBase, right.mBase);
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (left.mBase.getContainerStore() && right.mBase.getContainerStore())
return left.mBase.getContainerStore()->stacks(left.mBase, right.mBase)
&& right.mBase.getContainerStore()->stacks(left.mBase, right.mBase);
if (left.mBase.getContainerStore())
return left.mBase.getContainerStore()->stacks(left.mBase, right.mBase);
if (right.mBase.getContainerStore())
return right.mBase.getContainerStore()->stacks(left.mBase, right.mBase);
MWWorld::ContainerStore store;
return store.stacks(left.mBase, right.mBase);
}
ItemModel::ItemModel()

View file

@ -71,7 +71,7 @@ namespace MWGui
if (item.mType == ItemStack::Type_Equipped && !mShowEquipped)
return false;
int category;
int category = 0;
if (base.getTypeName() == typeid(ESM::Armor).name()
|| base.getTypeName() == typeid(ESM::Clothing).name())
category = Category_Apparel;

View file

@ -88,8 +88,10 @@ namespace MWGui
MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources);
// Important: actor goes last, so that items purchased by the merchant go into his inventory
itemSources.push_back(actor);
std::vector<MWWorld::Ptr> worldItems;
MWBase::Environment::get().getWorld()->getItemsOwnedBy(actor, worldItems);
mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources), mPtr);
mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources, worldItems), mPtr);
mSortModel = new SortFilterItemModel(mTradeModel);
mItemView->setModel (mSortModel);

View file

@ -29,8 +29,11 @@ namespace MWMechanics
calculateCreatureStatModifiers (ptr);
// AI
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
creatureStats.getAiSequence().execute (ptr);
if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
{
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
creatureStats.getAiSequence().execute (ptr);
}
}
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)

View file

@ -1,9 +1,51 @@
#include "aiwander.hpp"
#include <iostream>
#include "movement.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include <OgreVector3.h>
namespace
{
float sgn(float a)
{
if(a > 0) return 1.0;
else return -1.0;
}
}
MWMechanics::AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle, bool repeat):
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
{
for(unsigned short counter = 0; counter < mIdle.size(); counter++)
{
if(mIdle[counter] >= 127 || mIdle[counter] < 0)
mIdle[counter] = 0;
}
if(mDistance < 0)
mDistance = 0;
if(mDuration < 0)
mDuration = 0;
if(mDuration == 0)
mTimeOfDay = 0;
srand(time(NULL));
mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp();
mPlayedIdle = 0;
mIdleChanceMultiplier =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fIdleChanceMultiplier")->getFloat();
mStoredAvailableNodes = false;
mChooseAction = true;
mIdleNow = false;
mMoveNow = false;
mWalking = false;
}
MWMechanics::AiPackage * MWMechanics::AiWander::clone() const
@ -13,11 +55,264 @@ MWMechanics::AiPackage * MWMechanics::AiWander::clone() const
bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
{
// Return completed
return true;
if(mDuration)
{
// End package if duration is complete or mid-night hits:
MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp();
if(currentTime.getHour() >= mStartTime.getHour() + mDuration)
{
if(!mRepeat)
{
stopWalking(actor, mPathFinder);
return true;
}
else
mStartTime = currentTime;
}
else if(int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay())
{
if(!mRepeat)
{
stopWalking(actor, mPathFinder);
return true;
}
else
mStartTime = currentTime;
}
}
ESM::Position pos = actor.getRefData().getPosition();
if(!mStoredAvailableNodes)
{
mStoredAvailableNodes = true;
mPathgrid =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
mCellX = actor.getCell()->mCell->mData.mX;
mCellY = actor.getCell()->mCell->mData.mY;
if(mDistance && !mPathgrid->mPoints.empty())
{
mXCell = 0;
mYCell = 0;
if(actor.getCell()->mCell->isExterior())
{
mXCell = mCellX * ESM::Land::REAL_SIZE;
mYCell = mCellY * ESM::Land::REAL_SIZE;
}
Ogre::Vector3 npcPos(actor.getRefData().getPosition().pos);
npcPos[0] = npcPos[0] - mXCell;
npcPos[1] = npcPos[1] - mYCell;
for(unsigned int counter = 0; counter < mPathgrid->mPoints.size(); counter++)
{
Ogre::Vector3 nodePos(mPathgrid->mPoints[counter].mX, mPathgrid->mPoints[counter].mY, mPathgrid->mPoints[counter].mZ);
if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance)
mAllowedNodes.push_back(mPathgrid->mPoints[counter]);
}
if(!mAllowedNodes.empty())
{
Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ);
float closestNode = npcPos.squaredDistance(firstNodePos);
unsigned int index = 0;
for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
{
Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY, mAllowedNodes[counterThree].mZ);
float tempDist = npcPos.squaredDistance(nodePos);
if(tempDist < closestNode)
index = counterThree;
}
mCurrentNode = mAllowedNodes[index];
mAllowedNodes.erase(mAllowedNodes.begin() + index);
if(mAllowedNodes.empty())
mDistance = 0;
}
else
mDistance = 0;
}
}
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
bool cellChange = actor.getCell()->mCell->mData.mX != mCellX || actor.getCell()->mCell->mData.mY != mCellY;
if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
{
int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
// FIXME: This *should* pause the AiWander package instead of terminating it.
if(sideX*(pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / 2.0 - 200))
{
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
return true;
}
}
if(actor.getCell()->mCell->mData.mY != player.getCell()->mCell->mData.mY)
{
int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
// Check if actor is near the border of an inactive cell. If so, disable AiWander.
// FIXME: This *should* pause the AiWander package instead of terminating it.
if(sideY*(pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / 2.0 - 200))
{
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
return true;
}
}
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
if(mDistance && (cellChange || (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY)))
mDistance = 0;
if(mChooseAction)
{
mPlayedIdle = 0;
unsigned short idleRoll = 0;
for(unsigned int counter = 1; counter < mIdle.size(); counter++)
{
unsigned short idleChance = mIdleChanceMultiplier * mIdle[counter];
unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / mIdleChanceMultiplier));
if(randSelect < idleChance && randSelect > idleRoll)
{
mPlayedIdle = counter;
idleRoll = randSelect;
}
}
if(!mPlayedIdle && mDistance)
{
mChooseAction = false;
mMoveNow = true;
}
else
{
// Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp();
mStartTime = currentTime;
playIdle(actor, mPlayedIdle + 1);
mChooseAction = false;
mIdleNow = true;
}
}
if(mIdleNow)
{
if(!checkIdle(actor, mPlayedIdle + 1))
{
mPlayedIdle = 0;
mIdleNow = false;
mChooseAction = true;
}
}
if(mMoveNow && mDistance)
{
if(!mPathFinder.isPathConstructed())
{
unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size());
Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ);
// Remove this node as an option and add back the previously used node (stops NPC from picking the same node):
ESM::Pathgrid::Point temp = mAllowedNodes[randNode];
mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
mAllowedNodes.push_back(mCurrentNode);
mCurrentNode = temp;
ESM::Pathgrid::Point dest;
dest.mX = destNodePos[0] + mXCell;
dest.mY = destNodePos[1] + mYCell;
dest.mZ = destNodePos[2];
ESM::Pathgrid::Point start;
start.mX = pos.pos[0];
start.mY = pos.pos[1];
start.mZ = pos.pos[2];
mPathFinder.buildPath(start,dest,mPathgrid,mXCell,mYCell);
mWalking = true;
}
}
if(mWalking)
{
float zAngle = mPathFinder.getZAngleToNext(pos.pos[0],pos.pos[1],pos.pos[2]);
MWBase::Environment::get().getWorld()->rotateObject(actor,0,0,zAngle,false);
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
// Unclog path nodes by allowing the NPC to be a small distance away from the center. This way two NPCs can be
// at the same path node at the same time and both will complete instead of endlessly walking into eachother:
Ogre::Vector3 destNodePos(mCurrentNode.mX, mCurrentNode.mY, mCurrentNode.mZ);
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
actorPos[0] = actorPos[0] - mXCell;
actorPos[1] = actorPos[1] - mYCell;
float distance = actorPos.squaredDistance(destNodePos);
if(distance < 1200 || mPathFinder.checkIfNextPointReached(pos.pos[0],pos.pos[1],pos.pos[2]))
{
stopWalking(actor, mPathFinder);
mMoveNow = false;
mWalking = false;
mChooseAction = true;
}
}
return false;
}
int MWMechanics::AiWander::getTypeId() const
{
return 0;
}
void MWMechanics::AiWander::stopWalking(const MWWorld::Ptr& actor, PathFinder& path)
{
PathFinder pathClearer;
path = pathClearer;
MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
}
void MWMechanics::AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
{
if(idleSelect == 2)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle2", 0, 1);
else if(idleSelect == 3)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1);
else if(idleSelect == 4)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle4", 0, 1);
else if(idleSelect == 5)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle5", 0, 1);
else if(idleSelect == 6)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle6", 0, 1);
else if(idleSelect == 7)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle7", 0, 1);
else if(idleSelect == 8)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle8", 0, 1);
else if(idleSelect == 9)
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle9", 0, 1);
}
bool MWMechanics::AiWander::checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
{
if(idleSelect == 2)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle2");
else if(idleSelect == 3)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle3");
else if(idleSelect == 4)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle4");
else if(idleSelect == 5)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle5");
else if(idleSelect == 6)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle6");
else if(idleSelect == 7)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle7");
else if(idleSelect == 8)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle8");
else if(idleSelect == 9)
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle9");
else
return false;
}

View file

@ -4,6 +4,10 @@
#include "aipackage.hpp"
#include <vector>
#include "pathfinding.hpp"
#include "../mwworld/timestamp.hpp"
namespace MWMechanics
{
class AiWander : public AiPackage
@ -18,11 +22,42 @@ namespace MWMechanics
///< 0: Wander
private:
void stopWalking(const MWWorld::Ptr& actor, PathFinder& path);
void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
int mDistance;
int mDuration;
int mTimeOfDay;
std::vector<int> mIdle;
bool mRepeat;
float mX;
float mY;
float mZ;
int mCellX;
int mCellY;
float mXCell;
float mYCell;
bool mStoredAvailableNodes;
bool mChooseAction;
bool mIdleNow;
bool mMoveNow;
bool mWalking;
float mIdleChanceMultiplier;
unsigned short mPlayedIdle;
MWWorld::TimeStamp mStartTime;
std::vector<ESM::Pathgrid::Point> mAllowedNodes;
ESM::Pathgrid::Point mCurrentNode;
PathFinder mPathFinder;
const ESM::Pathgrid *mPathgrid;
};
}

View file

@ -64,13 +64,16 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
{
// select best shader mode
bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos);
bool glES = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL ES") != std::string::npos);
// glsl is only supported in opengl mode and hlsl only in direct3d mode.
if (Settings::Manager::getString("shader mode", "General") == ""
|| (openGL && Settings::Manager::getString("shader mode", "General") == "hlsl")
|| (!openGL && Settings::Manager::getString("shader mode", "General") == "glsl"))
std::string currentMode = Settings::Manager::getString("shader mode", "General");
if (currentMode == ""
|| (openGL && currentMode == "hlsl")
|| (!openGL && currentMode == "glsl")
|| (glES && currentMode != "glsles"))
{
Settings::Manager::setString("shader mode", "General", openGL ? "glsl" : "hlsl");
Settings::Manager::setString("shader mode", "General", openGL ? (glES ? "glsles" : "glsl") : "hlsl");
}
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
@ -93,6 +96,8 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
std::string l = Settings::Manager::getString("shader mode", "General");
if (l == "glsl")
lang = sh::Language_GLSL;
else if (l == "glsles")
lang = sh::Language_GLSLES;
else if (l == "hlsl")
lang = sh::Language_HLSL;
else

View file

@ -1,8 +1,6 @@
#ifndef GAME_SOUND_FFMPEG_DECODER_H
#define GAME_SOUND_FFMPEG_DECODER_H
#include <string>
// FIXME: This can't be right? The headers refuse to build without UINT64_C,
// which only gets defined in stdint.h in either C99 mode or with this macro
// defined...
@ -14,6 +12,8 @@ extern "C"
#include <libavformat/avformat.h>
}
#include <string>
#include "sound_decoder.hpp"

View file

@ -1724,4 +1724,31 @@ namespace MWWorld
}
}
}
struct ListHandlesFunctor
{
std::vector<std::string> mHandles;
bool operator() (ESM::CellRef& ref, RefData& data)
{
Ogre::SceneNode* handle = data.getBaseNode();
if (handle)
mHandles.push_back(handle->getName());
return true;
}
};
void World::getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out)
{
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
{
ListHandlesFunctor functor;
(*cellIt)->forEach<ListHandlesFunctor>(functor);
for (std::vector<std::string>::iterator it = functor.mHandles.begin(); it != functor.mHandles.end(); ++it)
if (Misc::StringUtils::ciEqual(searchPtrViaHandle(*it).mCellRef->mOwner, npc.getCellRef().mRefID))
out.push_back(searchPtrViaHandle(*it));
}
}
}

View file

@ -391,6 +391,8 @@ namespace MWWorld
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out);
///< get all containers in active cells owned by this Npc
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out);
///< get all items in active cells owned by this Npc
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);

View file

@ -3,6 +3,8 @@
#ifdef _WIN32
#include <boost/tr1/tr1/unordered_map>
#elif defined HAVE_UNORDERED_MAP
#include <unordered_map>
#else
#include <tr1/unordered_map>
#endif
@ -48,7 +50,11 @@ struct ConfigurationManager
typedef Files::FixedPath<> FixedPathType;
typedef const boost::filesystem::path& (FixedPathType::*path_type_f)() const;
typedef std::tr1::unordered_map<std::string, path_type_f> TokensMappingContainer;
#if defined HAVE_UNORDERED_MAP
typedef std::unordered_map<std::string, path_type_f> TokensMappingContainer;
#else
typedef std::tr1::unordered_map<std::string, path_type_f> TokensMappingContainer;
#endif
void loadConfig(const boost::filesystem::path& path,
boost::program_options::variables_map& variables,

View file

@ -87,6 +87,8 @@
Now, let's get into writing our shader! As you can guess from above, the filename should be 'example.shader'.
Make sure to also copy the 'core.h' file to the same location. It is included in shiny's source tree under 'Extra/'.
Important: a newline at the end of the file is <b>required</b>. Many editors do this automatically or can be configured to do so. If there is no newline at the end of the file, and the last line is '#endif', you will get the rather cryptic error message " ill formed preprocessor directive: #endif" from boost::wave.
\code
#include "core.h"

View file

@ -10,7 +10,7 @@ namespace sh
{
public:
virtual void execute() = 0;
virtual ~Action();
virtual ~Action() {}
};
class ActionDeleteMaterial : public Action

View file

@ -15,7 +15,7 @@ class Query
public:
Query()
: mDone(false) {}
virtual ~Query();
virtual ~Query() {}
void execute();

View file

@ -58,11 +58,20 @@
#endif
#if SH_GLSL == 1
#if SH_GLSL == 1 || SH_GLSLES == 1
#define shFract(val) fract(val)
#if SH_GLSLES == 1
@version 100
#else
@version 120
#endif
#if SH_GLSLES == 1 && SH_FRAGMENT_SHADER
precision mediump int;
precision mediump float;
#endif
#define float2 vec2
#define float3 vec3

View file

@ -206,6 +206,7 @@ void OgreRenderer::configure(const std::string &logPath,
pluginDir = absPluginPath.string();
Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mRoot);
Files::loadOgrePlugin(pluginDir, "RenderSystem_GLES2", *mRoot);
Files::loadOgrePlugin(pluginDir, "RenderSystem_GL3Plus", *mRoot);
Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mRoot);
Files::loadOgrePlugin(pluginDir, "Plugin_CgProgramManager", *mRoot);