Merge pull request #229 from OpenMW/master

Add OpenMW commits up to 20 Jun 2017
pull/249/merge
David Cernat 8 years ago committed by GitHub
commit df67ae4689

@ -77,9 +77,9 @@ if [ $? -ne 0 ]; then
fi fi
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
msbuild OpenMW.sln //t:Build //m:8 msbuild OpenMW.sln //t:Build //p:Configuration=${CONFIGURATION} //m:8
else else
msbuild OpenMW.sln //t:Build //m:8 //logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" msbuild OpenMW.sln //t:Build //p:Configuration=${CONFIGURATION} //m:8 //logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
fi fi
RET=$? RET=$?

@ -172,9 +172,6 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
} }
} }
if(!setupGameData())
return FirstRunDialogResultFailure;
return setup() ? FirstRunDialogResultContinue : FirstRunDialogResultFailure; return setup() ? FirstRunDialogResultContinue : FirstRunDialogResultFailure;
} }
@ -347,10 +344,6 @@ bool Launcher::MainDialog::setupGameSettings()
file.close(); file.close();
} }
return true;
}
bool Launcher::MainDialog::setupGameData() {
QStringList dataDirs; QStringList dataDirs;
// Check if the paths actually contain data files // Check if the paths actually contain data files
@ -386,6 +379,7 @@ bool Launcher::MainDialog::setupGameData() {
} }
} }
} }
return true; return true;
} }

@ -72,7 +72,6 @@ namespace Launcher
bool setupLauncherSettings(); bool setupLauncherSettings();
bool setupGameSettings(); bool setupGameSettings();
bool setupGraphicsSettings(); bool setupGraphicsSettings();
bool setupGameData();
void setVersionLabel(); void setVersionLabel();

@ -295,21 +295,6 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor)
if (actor == getPlayer()) if (actor == getPlayer())
throw std::runtime_error("Can't add AI packages to player"); throw std::runtime_error("Can't add AI packages to player");
if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPursue)
{
// Notify AiWander of our current position so we can return to it after combat finished
for (std::list<AiPackage *>::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter)
{
if((*iter)->getTypeId() == AiPackage::TypeIdCombat && package.getTypeId() == AiPackage::TypeIdCombat
&& (*iter)->getTarget() == (&package)->getTarget())
{
return; // already in combat with this actor
}
else if ((*iter)->getTypeId() == AiPackage::TypeIdWander)
static_cast<AiWander*>(*iter)->setReturnPosition(actor.getRefData().getPosition().asVec3());
}
}
// Stop combat when a non-combat AI package is added // Stop combat when a non-combat AI package is added
if (isActualAiPackage(package.getTypeId())) if (isActualAiPackage(package.getTypeId()))
stopCombat(); stopCombat();

@ -113,7 +113,7 @@ namespace MWMechanics
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat): AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
mDistance(distance), mDuration(duration), mRemainingDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mDistance(distance), mDuration(duration), mRemainingDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle),
mRepeat(repeat), mStoredInitialActorPosition(false) mRepeat(repeat), mStoredInitialActorPosition(false), mInitialActorPosition(osg::Vec3f(0, 0, 0)), mHasDestination(false), mDestination(osg::Vec3f(0, 0, 0))
{ {
mIdle.resize(8, 0); mIdle.resize(8, 0);
init(); init();
@ -123,9 +123,6 @@ namespace MWMechanics
{ {
// NOTE: mDistance and mDuration must be set already // NOTE: mDistance and mDuration must be set already
mHasReturnPosition = false;
mReturnPosition = osg::Vec3f(0,0,0);
if(mDistance < 0) if(mDistance < 0)
mDistance = 0; mDistance = 0;
if(mDuration < 0) if(mDuration < 0)
@ -212,6 +209,19 @@ namespace MWMechanics
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
// If there is already a destination due to the package having been interrupted by a combat or pursue package,
// rebuild a path to it
if (!mPathFinder.isPathConstructed() && mHasDestination)
{
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(mDestination));
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos));
mPathFinder.buildSyncedPath(start, dest, actor.getCell());
if (mPathFinder.isPathConstructed())
storage.setState(Wander_Walking);
}
doPerFrameActionsForState(actor, duration, storage, pos); doPerFrameActionsForState(actor, duration, storage, pos);
playIdleDialogueRandomly(actor); playIdleDialogueRandomly(actor);
@ -253,9 +263,8 @@ namespace MWMechanics
getAllowedNodes(actor, currentCell->getCell(), storage); getAllowedNodes(actor, currentCell->getCell(), storage);
} }
// Actor becomes stationary - see above URL's for previous research // If the package has a wander distance but no pathgrid is available,
// If a creature or an NPC with a wander distance and no pathgrid is available, // randomly idle or wander near spawn point
// randomly idle or wander around near spawn point
if(storage.mAllowedNodes.empty() && mDistance > 0 && !storage.mIsWanderingManually) { if(storage.mAllowedNodes.empty() && mDistance > 0 && !storage.mIsWanderingManually) {
// Typically want to idle for a short time before the next wander // Typically want to idle for a short time before the next wander
if (Misc::Rng::rollDice(100) >= 96) { if (Misc::Rng::rollDice(100) >= 96) {
@ -277,10 +286,8 @@ namespace MWMechanics
mDistance = 0; mDistance = 0;
// For stationary NPCs, move back to the starting location if another AiPackage moved us elsewhere // For stationary NPCs, move back to the starting location if another AiPackage moved us elsewhere
if (cellChange) if (mDistance == 0 && !cellChange
mHasReturnPosition = false; && (pos.asVec3() - mInitialActorPosition).length2() > (DESTINATION_TOLERANCE * DESTINATION_TOLERANCE))
if (mDistance == 0 && mHasReturnPosition
&& (pos.asVec3() - mReturnPosition).length2() > (DESTINATION_TOLERANCE * DESTINATION_TOLERANCE))
{ {
returnToStartLocation(actor, storage, pos); returnToStartLocation(actor, storage, pos);
} }
@ -334,7 +341,8 @@ namespace MWMechanics
{ {
if (!mPathFinder.isPathConstructed()) if (!mPathFinder.isPathConstructed())
{ {
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(mReturnPosition)); mDestination = mInitialActorPosition;
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(mDestination));
// actor position is already in world coordinates // actor position is already in world coordinates
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos));
@ -345,6 +353,7 @@ namespace MWMechanics
if (mPathFinder.isPathConstructed()) if (mPathFinder.isPathConstructed())
{ {
storage.setState(Wander_Walking); storage.setState(Wander_Walking);
mHasDestination = true;
} }
} }
} }
@ -357,7 +366,6 @@ namespace MWMechanics
const osg::Vec3f currentPositionVec3f = osg::Vec3f(currentPosition.mX, currentPosition.mY, currentPosition.mZ); const osg::Vec3f currentPositionVec3f = osg::Vec3f(currentPosition.mX, currentPosition.mY, currentPosition.mZ);
std::size_t attempts = 10; // If a unit can't wander out of water, don't want to hang here std::size_t attempts = 10; // If a unit can't wander out of water, don't want to hang here
osg::Vec3f destination;
ESM::Pathgrid::Point destinationPosition; ESM::Pathgrid::Point destinationPosition;
bool isWaterCreature = actor.getClass().isPureWaterCreature(actor); bool isWaterCreature = actor.getClass().isPureWaterCreature(actor);
do { do {
@ -369,17 +377,18 @@ namespace MWMechanics
const float destinationY = mInitialActorPosition.y() + wanderRadius * std::sin(randomDirection); const float destinationY = mInitialActorPosition.y() + wanderRadius * std::sin(randomDirection);
const float destinationZ = mInitialActorPosition.z(); const float destinationZ = mInitialActorPosition.z();
destinationPosition = ESM::Pathgrid::Point(destinationX, destinationY, destinationZ); destinationPosition = ESM::Pathgrid::Point(destinationX, destinationY, destinationZ);
destination = osg::Vec3f(destinationX, destinationY, destinationZ); mDestination = osg::Vec3f(destinationX, destinationY, destinationZ);
// Check if land creature will walk onto water or if water creature will swim onto land // Check if land creature will walk onto water or if water creature will swim onto land
if ((!isWaterCreature && !destinationIsAtWater(actor, destination)) || if ((!isWaterCreature && !destinationIsAtWater(actor, mDestination)) ||
(isWaterCreature && !destinationThroughGround(currentPositionVec3f, destination))) { (isWaterCreature && !destinationThroughGround(currentPositionVec3f, mDestination))) {
mPathFinder.buildSyncedPath(currentPosition, destinationPosition, actor.getCell()); mPathFinder.buildSyncedPath(currentPosition, destinationPosition, actor.getCell());
mPathFinder.addPointToPath(destinationPosition); mPathFinder.addPointToPath(destinationPosition);
if (mPathFinder.isPathConstructed()) if (mPathFinder.isPathConstructed())
{ {
storage.setState(Wander_Walking, true); storage.setState(Wander_Walking, true);
mHasDestination = true;
} }
return; return;
} }
@ -466,6 +475,9 @@ namespace MWMechanics
GreetingState& greetingState = storage.mSaidGreeting; GreetingState& greetingState = storage.mSaidGreeting;
if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None)) if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None))
{ {
if (mPathFinder.isPathConstructed())
storage.setState(Wander_Walking);
else
storage.setState(Wander_ChooseAction); storage.setState(Wander_ChooseAction);
} }
} }
@ -478,7 +490,6 @@ namespace MWMechanics
{ {
stopWalking(actor, storage); stopWalking(actor, storage);
storage.setState(Wander_ChooseAction); storage.setState(Wander_ChooseAction);
mHasReturnPosition = false;
} }
else else
{ {
@ -490,8 +501,8 @@ namespace MWMechanics
void AiWander::onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage) void AiWander::onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage)
{ {
short unsigned& idleAnimation = storage.mIdleAnimation; unsigned short idleAnimation = getRandomIdle();
idleAnimation = getRandomIdle(); storage.mIdleAnimation = idleAnimation;
if (!idleAnimation && mDistance) if (!idleAnimation && mDistance)
{ {
@ -525,7 +536,7 @@ namespace MWMechanics
storage.mTrimCurrentNode = true; storage.mTrimCurrentNode = true;
trimAllowedNodes(storage.mAllowedNodes, mPathFinder); trimAllowedNodes(storage.mAllowedNodes, mPathFinder);
mObstacleCheck.clear(); mObstacleCheck.clear();
mPathFinder.clearPath(); stopWalking(actor, storage);
storage.setState(Wander_MoveNow); storage.setState(Wander_MoveNow);
} }
@ -535,9 +546,7 @@ namespace MWMechanics
// if stuck for sufficiently long, act like current location was the destination // if stuck for sufficiently long, act like current location was the destination
if (storage.mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset if (storage.mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset
{ {
//std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl;
mObstacleCheck.clear(); mObstacleCheck.clear();
stopWalking(actor, storage); stopWalking(actor, storage);
storage.setState(Wander_ChooseAction); storage.setState(Wander_ChooseAction);
storage.mStuckCount = 0; storage.mStuckCount = 0;
@ -612,7 +621,7 @@ namespace MWMechanics
if (storage.mState == Wander_Walking) if (storage.mState == Wander_Walking)
{ {
stopWalking(actor, storage); stopWalking(actor, storage, false);
mObstacleCheck.clear(); mObstacleCheck.clear();
storage.setState(Wander_IdleNow); storage.setState(Wander_IdleNow);
} }
@ -657,6 +666,8 @@ namespace MWMechanics
if (mPathFinder.isPathConstructed()) if (mPathFinder.isPathConstructed())
{ {
mDestination = osg::Vec3f(dest.mX, dest.mY, dest.mZ);
mHasDestination = true;
// Remove this node as an option and add back the previously used node (stops NPC from picking the same node): // Remove this node as an option and add back the previously used node (stops NPC from picking the same node):
ESM::Pathgrid::Point temp = storage.mAllowedNodes[randNode]; ESM::Pathgrid::Point temp = storage.mAllowedNodes[randNode];
storage.mAllowedNodes.erase(storage.mAllowedNodes.begin() + randNode); storage.mAllowedNodes.erase(storage.mAllowedNodes.begin() + randNode);
@ -710,9 +721,13 @@ namespace MWMechanics
return TypeIdWander; return TypeIdWander;
} }
void AiWander::stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage) void AiWander::stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage, bool clearPath)
{
if (clearPath)
{ {
mPathFinder.clearPath(); mPathFinder.clearPath();
mHasDestination = false;
}
actor.getClass().getMovementSettings(actor).mPosition[1] = 0; actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
} }
@ -743,15 +758,6 @@ namespace MWMechanics
} }
} }
void AiWander::setReturnPosition(const osg::Vec3f& position)
{
if (!mHasReturnPosition)
{
mHasReturnPosition = true;
mReturnPosition = position;
}
}
short unsigned AiWander::getRandomIdle() short unsigned AiWander::getRandomIdle()
{ {
unsigned short idleRoll = 0; unsigned short idleRoll = 0;
@ -945,6 +951,8 @@ namespace MWMechanics
, mTimeOfDay(wander->mData.mTimeOfDay) , mTimeOfDay(wander->mData.mTimeOfDay)
, mRepeat(wander->mData.mShouldRepeat != 0) , mRepeat(wander->mData.mShouldRepeat != 0)
, mStoredInitialActorPosition(wander->mStoredInitialActorPosition) , mStoredInitialActorPosition(wander->mStoredInitialActorPosition)
, mHasDestination(false)
, mDestination(osg::Vec3f(0, 0, 0))
{ {
if (mStoredInitialActorPosition) if (mStoredInitialActorPosition)
mInitialActorPosition = wander->mInitialActorPosition; mInitialActorPosition = wander->mInitialActorPosition;
@ -953,7 +961,6 @@ namespace MWMechanics
if (mRemainingDuration <= 0 || mRemainingDuration >= 24) if (mRemainingDuration <= 0 || mRemainingDuration >= 24)
mRemainingDuration = mDuration; mRemainingDuration = mDuration;
init(); init();
} }
} }

@ -44,10 +44,6 @@ namespace MWMechanics
virtual int getTypeId() const; virtual int getTypeId() const;
/// Set the position to return to for a stationary (non-wandering) actor
/** In case another AI package moved the actor elsewhere **/
void setReturnPosition (const osg::Vec3f& position);
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const; virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
virtual void fastForward(const MWWorld::Ptr& actor, AiState& state); virtual void fastForward(const MWWorld::Ptr& actor, AiState& state);
@ -70,7 +66,7 @@ namespace MWMechanics
private: private:
// NOTE: mDistance and mDuration must be set already // NOTE: mDistance and mDuration must be set already
void init(); void init();
void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage); void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage, bool clearPath = true);
/// Have the given actor play an idle animation /// Have the given actor play an idle animation
/// @return Success or error /// @return Success or error
@ -102,11 +98,11 @@ namespace MWMechanics
std::vector<unsigned char> mIdle; std::vector<unsigned char> mIdle;
bool mRepeat; bool mRepeat;
bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position,
// if we had the actor in the AiWander constructor...
osg::Vec3f mReturnPosition;
osg::Vec3f mInitialActorPosition;
bool mStoredInitialActorPosition; bool mStoredInitialActorPosition;
osg::Vec3f mInitialActorPosition;
bool mHasDestination;
osg::Vec3f mDestination;
void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage); void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage);

@ -156,6 +156,16 @@ int MWWorld::ContainerStore::count(const std::string &id)
return total; return total;
} }
int MWWorld::ContainerStore::restockCount(const std::string &id)
{
int total=0;
for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id))
if (iter->getCellRef().getSoul().empty())
total += iter->getRefData().getCount();
return total;
}
MWWorld::ContainerStoreListener* MWWorld::ContainerStore::getContListener() const MWWorld::ContainerStoreListener* MWWorld::ContainerStore::getContListener() const
{ {
return mListener; return mListener;
@ -512,7 +522,7 @@ void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MW
for (std::map<std::pair<std::string, std::string>, int>::iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end();) for (std::map<std::pair<std::string, std::string>, int>::iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end();)
{ {
int spawnedCount = it->second; //How many items should be in shop originally int spawnedCount = it->second; //How many items should be in shop originally
int itemCount = count(it->first.first); //How many items are there in shop now int itemCount = restockCount(it->first.first); //How many items are there in shop now
//If something was not sold //If something was not sold
if(itemCount >= spawnedCount) if(itemCount >= spawnedCount)
{ {
@ -578,7 +588,7 @@ void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MW
else else
{ {
//Restocking static item - just restock to the max count //Restocking static item - just restock to the max count
int currentCount = count(itemOrList); int currentCount = restockCount(itemOrList);
if (currentCount < std::abs(it->mCount)) if (currentCount < std::abs(it->mCount))
addInitialItem(itemOrList, owner, -(std::abs(it->mCount) - currentCount), true); addInitialItem(itemOrList, owner, -(std::abs(it->mCount) - currentCount), true);
} }

@ -162,8 +162,12 @@ namespace MWWorld
/// If a compatible stack is found, the item's count is added to that stack, then the original is deleted. /// If a compatible stack is found, the item's count is added to that stack, then the original is deleted.
/// @return If the item was stacked, return the stack, otherwise return the old (untouched) item. /// @return If the item was stacked, return the stack, otherwise return the old (untouched) item.
/// @return How many items with refID \a id are in this container?
int count (const std::string& id); int count (const std::string& id);
///< @return How many items with refID \a id are in this container?
int restockCount (const std::string& id);
///< Item count with restock adjustments (such as ignoring filled soul gems).
/// @return How many items with refID \a id are in this container?
ContainerStoreListener* getContListener() const; ContainerStoreListener* getContListener() const;
void setContListener(ContainerStoreListener* listener); void setContListener(ContainerStoreListener* listener);

@ -203,8 +203,7 @@ void BulletNifLoader::handleNode(const Nif::Node *node, int flags,
// affecting the entire subtree of this node // affecting the entire subtree of this node
Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e; Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e;
// not sure what the difference between NCO and NCC is, or if there even is one if (Misc::StringUtils::ciCompareLen(sd->string, "NC", 2) == 0)
if (sd->string == "NCO" || sd->string == "NCC")
{ {
// No collision. Use an internal flag setting to mark this. // No collision. Use an internal flag setting to mark this.
flags |= 0x800; flags |= 0x800;

Loading…
Cancel
Save