forked from teamnwah/openmw-tes3coop
Merge branch 'master' of https://github.com/zinnschlag/openmw into enchanting-mechanics
This commit is contained in:
commit
9e1eb8b3b1
20 changed files with 508 additions and 29 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
2
extern/shiny/Docs/Materials.dox
vendored
2
extern/shiny/Docs/Materials.dox
vendored
|
@ -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"
|
||||
|
||||
|
|
2
extern/shiny/Editor/Actions.hpp
vendored
2
extern/shiny/Editor/Actions.hpp
vendored
|
@ -10,7 +10,7 @@ namespace sh
|
|||
{
|
||||
public:
|
||||
virtual void execute() = 0;
|
||||
virtual ~Action();
|
||||
virtual ~Action() {}
|
||||
};
|
||||
|
||||
class ActionDeleteMaterial : public Action
|
||||
|
|
2
extern/shiny/Editor/Query.hpp
vendored
2
extern/shiny/Editor/Query.hpp
vendored
|
@ -15,7 +15,7 @@ class Query
|
|||
public:
|
||||
Query()
|
||||
: mDone(false) {}
|
||||
virtual ~Query();
|
||||
virtual ~Query() {}
|
||||
|
||||
void execute();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue