Merge remote-tracking branch 'upstream/master' into static-deps-build

sceneinput
slothlife 10 years ago
commit 43b1f15af9

@ -18,8 +18,8 @@ addons:
name: "OpenMW/openmw"
description: "<Your project description here>"
notification_email: scrawl@baseoftrash.de
build_command_prepend: "cmake ."
build_command: "make -j3"
build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE"
build_command: "make"
branch_pattern: coverity_scan
matrix:
include:

@ -3,8 +3,9 @@ OpenMW
[![Build Status](https://img.shields.io/travis/OpenMW/openmw.svg)](https://travis-ci.org/OpenMW/openmw) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740)
OpenMW is an attempt at recreating the engine for the popular role-playing game
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
OpenMW is a recreation of the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
OpenMW also comes with OpenMW-CS, a replacement for Morrowind's TES Construction Set.
* Version: 0.36.0
* License: GPL (see docs/license/GPL3.txt for more information)
@ -14,6 +15,13 @@ Morrowind by Bethesda Softworks. You need to own and install the original game f
Font Licenses:
* DejaVuLGCSansMono.ttf: custom (see docs/license/DejaVu Font License.txt for more information)
Current Status
--------------
The main quests in Morrowind, Tribunal and Bloodmoon are all completable. Some issues with side quests are to be expected (but rare). Check the [bug tracker](https://bugs.openmw.org/versions/21) for a list of issues we need to resolve before the "1.0" release. Even before the "1.0" release however, OpenMW boasts some new [features](https://wiki.openmw.org/index.php?title=Features), such as improved graphics and user interfaces.
Pre-existing modifications created for the original Morrowind engine can be hit-and-miss. The OpenMW script compiler performs more thorough error-checking than Morrowind does, meaning that a mod created for Morrowind may not necessarily run in OpenMW. Some mods also rely on quirky behaviour or engine bugs in order to work. We are considering such compatibility issues on a case-by-case basis - in some cases adding a workaround to OpenMW may be feasible, in other cases fixing the mod will be the only option. If you know of any mods that work or don't work, feel free to add them to the [Mod status](https://wiki.openmw.org/index.php?title=Mod_status) wiki page.
Getting Started
---------------

@ -166,7 +166,9 @@ namespace ESSImport
if (i >= file2.mRecords.size())
{
std::ios::fmtflags f(std::cout.flags());
std::cout << "Record in file1 not present in file2: (1) 0x" << std::hex << rec.mFileOffset << std::endl;
std::cout.flags(f);
return;
}
@ -174,7 +176,9 @@ namespace ESSImport
if (rec.mName != rec2.mName)
{
std::ios::fmtflags f(std::cout.flags());
std::cout << "Different record name at (2) 0x" << std::hex << rec2.mFileOffset << std::endl;
std::cout.flags(f);
return; // TODO: try to recover
}
@ -185,7 +189,9 @@ namespace ESSImport
if (j >= rec2.mSubrecords.size())
{
std::ios::fmtflags f(std::cout.flags());
std::cout << "Subrecord in file1 not present in file2: (1) 0x" << std::hex << sub.mFileOffset << std::endl;
std::cout.flags(f);
return;
}
@ -193,8 +199,10 @@ namespace ESSImport
if (sub.mName != sub2.mName)
{
std::ios::fmtflags f(std::cout.flags());
std::cout << "Different subrecord name (" << rec.mName << "." << sub.mName << " vs. " << sub2.mName << ") at (1) 0x" << std::hex << sub.mFileOffset
<< " (2) 0x" << sub2.mFileOffset << std::endl;
std::cout.flags(f);
break; // TODO: try to recover
}
@ -203,6 +211,8 @@ namespace ESSImport
if (blacklist.find(std::make_pair(rec.mName, sub.mName)) != blacklist.end())
continue;
std::ios::fmtflags f(std::cout.flags());
std::cout << "Different subrecord data for " << rec.mName << "." << sub.mName << " at (1) 0x" << std::hex << sub.mFileOffset
<< " (2) 0x" << sub2.mFileOffset << std::endl;
@ -235,6 +245,7 @@ namespace ESSImport
std::cout << "\033[0m";
}
std::cout << std::endl;
std::cout.flags(f);
}
}
}
@ -319,7 +330,11 @@ namespace ESSImport
else
{
if (unknownRecords.insert(n.val).second)
{
std::ios::fmtflags f(std::cerr.flags());
std::cerr << "unknown record " << n.toString() << " (0x" << std::hex << esm.getFileOffset() << ")" << std::endl;
std::cerr.flags(f);
}
esm.skipRecord();
}

@ -49,6 +49,10 @@ namespace ESSImport
std::map<std::string, ESM::NPC> mNpcs;
Context()
: mDay(0)
, mMonth(0)
, mYear(0)
, mHour(0.f)
{
mPlayer.mAutoMove = 0;
ESM::CellId playerCellId;

@ -203,6 +203,8 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
return false; // script does not have a variable of this name.
int index = localDefs.getIndex (name);
if (index < 0)
return false; // shouldn't happen, we checked that variable has a type above, so must exist
const MWScript::Locals& locals = mActor.getRefData().getLocals();

@ -235,8 +235,9 @@ namespace MWGui
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
// Create all cursors in advance
createCursors();
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
mCursorManager->setEnabled(true);
// hide mygui's pointer
@ -896,6 +897,9 @@ namespace MWGui
void WindowManager::updateMap()
{
if (!mLocalMapRender)
return;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
osg::Vec3f playerPosition = player.getRefData().getPosition().asVec3();
@ -1178,31 +1182,7 @@ namespace MWGui
void WindowManager::onCursorChange(const std::string &name)
{
if(!mCursorManager->cursorChanged(name))
return; //the cursor manager doesn't want any more info about this cursor
//See if we can get the information we need out of the cursor resource
ResourceImageSetPointerFix* imgSetPtr = dynamic_cast<ResourceImageSetPointerFix*>(MyGUI::PointerManager::getInstance().getByName(name));
if(imgSetPtr != NULL)
{
MyGUI::ResourceImageSet* imgSet = imgSetPtr->getImageSet();
std::string tex_name = imgSet->getIndexInfo(0,0).texture;
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(tex_name, osg::Texture::CLAMP, osg::Texture::CLAMP);
tex->setUnRefImageDataAfterApply(false); // FIXME?
//everything looks good, send it to the cursor manager
if(tex.valid())
{
Uint8 size_x = imgSetPtr->getSize().width;
Uint8 size_y = imgSetPtr->getSize().height;
Uint8 hotspot_x = imgSetPtr->getHotSpot().left;
Uint8 hotspot_y = imgSetPtr->getHotSpot().top;
int rotation = imgSetPtr->getRotation();
mCursorManager->receiveCursorInfo(name, rotation, tex->getImage(), size_x, size_y, hotspot_x, hotspot_y);
}
}
mCursorManager->cursorChanged(name);
}
void WindowManager::popGuiMode()
@ -1960,6 +1940,33 @@ namespace MWGui
return Misc::ResourceHelpers::correctTexturePath(path, mResourceSystem->getVFS());
}
void WindowManager::createCursors()
{
MyGUI::ResourceManager::EnumeratorPtr enumerator = MyGUI::ResourceManager::getInstance().getEnumerator();
while (enumerator.next())
{
MyGUI::IResource* resource = enumerator.current().second;
ResourceImageSetPointerFix* imgSetPointer = dynamic_cast<ResourceImageSetPointerFix*>(resource);
if (!imgSetPointer)
continue;
std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0,0).texture;
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(tex_name, osg::Texture::CLAMP, osg::Texture::CLAMP);
if(tex.valid())
{
//everything looks good, send it to the cursor manager
Uint8 size_x = imgSetPointer->getSize().width;
Uint8 size_y = imgSetPointer->getSize().height;
Uint8 hotspot_x = imgSetPointer->getHotSpot().left;
Uint8 hotspot_y = imgSetPointer->getHotSpot().top;
int rotation = imgSetPointer->getRotation();
mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, tex->getImage(), size_x, size_y, hotspot_x, hotspot_y);
}
}
}
void WindowManager::createTextures()
{
{

@ -511,6 +511,7 @@ namespace MWGui
void onClipboardRequested(const std::string& _type, std::string& _data);
void createTextures();
void createCursors();
void setMenuTransparency(float value);
};
}

@ -117,7 +117,7 @@ namespace MWMechanics
mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp();
mStoredAvailableNodes = false;
mPopulateAvailableNodes = true;
}
@ -191,7 +191,7 @@ namespace MWMechanics
if(!currentCell || cellChange)
{
currentCell = actor.getCell();
mStoredAvailableNodes = false; // prob. not needed since mDistance = 0
mPopulateAvailableNodes = true;
}
cStats.setDrawState(DrawState_Nothing);
@ -225,8 +225,6 @@ namespace MWMechanics
storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], DESTINATION_TOLERANCE))
{
stopWalking(actor, storage);
moveNow = false;
walking = false;
chooseAction = true;
mHasReturnPosition = false;
}
@ -239,45 +237,7 @@ namespace MWMechanics
zTurn(actor, osg::DegreesToRadians(storage.mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
// Returns true if evasive action needs to be taken
if(mObstacleCheck.check(actor, duration))
{
// first check if we're walking into a door
if(proximityToDoor(actor)) // NOTE: checks interior cells only
{
// remove allowed points then select another random destination
mTrimCurrentNode = true;
trimAllowedNodes(mAllowedNodes, storage.mPathFinder);
mObstacleCheck.clear();
storage.mPathFinder.clearPath();
walking = false;
moveNow = true;
}
else // probably walking into another NPC
{
// TODO: diagonal should have same animation as walk forward
// but doesn't seem to do that?
actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
// change the angle a bit, too
zTurn(actor, osg::DegreesToRadians(storage.mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
}
mStuckCount++; // TODO: maybe no longer needed
}
//#if 0
// TODO: maybe no longer needed
if(mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset
{
//std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl;
mObstacleCheck.clear();
stopWalking(actor, storage);
moveNow = false;
walking = false;
chooseAction = true;
mStuckCount = 0;
}
//#endif
evadeObstacles(actor, storage, duration);
}
@ -325,32 +285,7 @@ namespace MWMechanics
}
}
// Play idle voiced dialogue entries randomly
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
if (hello > 0 && !MWBase::Environment::get().getWorld()->isSwimming(actor)
&& MWBase::Environment::get().getSoundManager()->sayDone(actor))
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
float roll = Misc::Rng::rollProbability() * 10000.0f;
// In vanilla MW the chance was FPS dependent, and did not allow proper changing of fVoiceIdleOdds
// due to the roll being an integer.
// Our implementation does not have these issues, so needs to be recalibrated. We chose to
// use the chance MW would have when run at 60 FPS with the default value of the GMST for calibration.
float x = fVoiceIdleOdds * 0.6f * (MWBase::Environment::get().getFrameDuration() / 0.1f);
// Only say Idle voices when player is in LOS
// A bit counterintuitive, likely vanilla did this to reduce the appearance of
// voices going through walls?
if (roll < x && (player.getRefData().getPosition().asVec3() - pos.asVec3()).length2()
< 3000*3000 // maybe should be fAudioVoiceDefaultMaxDistance*fAudioMaxDistanceMult instead
&& MWBase::Environment::get().getWorld()->getLOS(player, actor))
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
}
playIdleDialogueRandomly(actor);
float& lastReaction = storage.mReaction;
lastReaction += duration;
@ -367,17 +302,8 @@ namespace MWMechanics
{
// End package if duration is complete or mid-night hits:
MWWorld::TimeStamp currentTime = world->getTimeStamp();
if(currentTime.getHour() >= mStartTime.getHour() + mDuration)
{
if(!mRepeat)
{
stopWalking(actor, storage);
return true;
}
else
mStartTime = currentTime;
}
else if(int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay())
if((currentTime.getHour() >= mStartTime.getHour() + mDuration) ||
(int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay()))
{
if(!mRepeat)
{
@ -390,7 +316,7 @@ namespace MWMechanics
}
// Initialization to discover & store allowed node points for this actor.
if(!mStoredAvailableNodes)
if (mPopulateAvailableNodes)
{
getAllowedNodes(actor, currentCell->getCell());
}
@ -432,111 +358,193 @@ namespace MWMechanics
// Allow interrupting a walking actor to trigger a greeting
if(idleNow || walking)
{
// Play a random voice greeting if the player gets too close
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
float helloDistance = static_cast<float>(hello);
static int iGreetDistanceMultiplier =MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("iGreetDistanceMultiplier")->getInt();
helloDistance *= iGreetDistanceMultiplier;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
float playerDistSqr = (playerPos - actorPos).length2();
playGreetingIfPlayerGetsTooClose(actor, storage);
}
int& greetingTimer = storage.mGreetingTimer;
if (greetingState == Greet_None)
if(moveNow && mDistance)
{
// Construct a new path if there isn't one
if(!storage.mPathFinder.isPathConstructed())
{
if ((playerDistSqr <= helloDistance*helloDistance) &&
!player.getClass().getCreatureStats(player).isDead() && MWBase::Environment::get().getWorld()->getLOS(player, actor)
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, actor))
greetingTimer++;
if (greetingTimer >= GREETING_SHOULD_START)
if (mAllowedNodes.size())
{
greetingState = Greet_InProgress;
MWBase::Environment::get().getDialogueManager()->say(actor, "hello");
greetingTimer = 0;
setPathToAnAllowedNode(actor, storage, pos);
}
}
}
return false; // AiWander package not yet completed
}
void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration)
{
if (mObstacleCheck.check(actor, duration))
{
// first check if we're walking into a door
if (proximityToDoor(actor)) // NOTE: checks interior cells only
{
// remove allowed points then select another random destination
mTrimCurrentNode = true;
trimAllowedNodes(mAllowedNodes, storage.mPathFinder);
mObstacleCheck.clear();
storage.mPathFinder.clearPath();
storage.mWalking = false;
storage.mMoveNow = true;
}
if(greetingState == Greet_InProgress)
else // probably walking into another NPC
{
greetingTimer++;
if(walking)
{
stopWalking(actor, storage);
moveNow = false;
walking = false;
mObstacleCheck.clear();
idleNow = true;
getRandomIdle(playedIdle);
}
// TODO: diagonal should have same animation as walk forward
// but doesn't seem to do that?
actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
// change the angle a bit, too
const ESM::Position& pos = actor.getRefData().getPosition();
zTurn(actor, osg::DegreesToRadians(storage.mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
}
mStuckCount++; // TODO: maybe no longer needed
}
//#if 0
// TODO: maybe no longer needed
if (mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset
{
//std::cout << "Reset \""<< cls.getName(actor) << "\"" << std::endl;
mObstacleCheck.clear();
if(!rotate)
{
osg::Vec3f dir = playerPos - actorPos;
stopWalking(actor, storage);
storage.mChooseAction = true;
mStuckCount = 0;
}
//#endif
}
float faceAngleRadians = std::atan2(dir.x(), dir.y());
targetAngleRadians = faceAngleRadians;
rotate = true;
}
if (greetingTimer >= GREETING_SHOULD_END)
{
greetingState = Greet_Done;
greetingTimer = 0;
}
}
if (greetingState == MWMechanics::AiWander::Greet_Done)
void AiWander::playIdleDialogueRandomly(const MWWorld::Ptr& actor)
{
int hello = actor.getClass().getCreatureStats(actor).getAiSetting(CreatureStats::AI_Hello).getModified();
if (hello > 0 && !MWBase::Environment::get().getWorld()->isSwimming(actor)
&& MWBase::Environment::get().getSoundManager()->sayDone(actor))
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
float roll = Misc::Rng::rollProbability() * 10000.0f;
// In vanilla MW the chance was FPS dependent, and did not allow proper changing of fVoiceIdleOdds
// due to the roll being an integer.
// Our implementation does not have these issues, so needs to be recalibrated. We chose to
// use the chance MW would have when run at 60 FPS with the default value of the GMST for calibration.
float x = fVoiceIdleOdds * 0.6f * (MWBase::Environment::get().getFrameDuration() / 0.1f);
// Only say Idle voices when player is in LOS
// A bit counterintuitive, likely vanilla did this to reduce the appearance of
// voices going through walls?
const ESM::Position& pos = actor.getRefData().getPosition();
if (roll < x && (player.getRefData().getPosition().asVec3() - pos.asVec3()).length2()
< 3000 * 3000 // maybe should be fAudioVoiceDefaultMaxDistance*fAudioMaxDistanceMult instead
&& MWBase::Environment::get().getWorld()->getLOS(player, actor))
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
}
}
void AiWander::playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage)
{
// Play a random voice greeting if the player gets too close
int hello = actor.getClass().getCreatureStats(actor).getAiSetting(CreatureStats::AI_Hello).getModified();
float helloDistance = static_cast<float>(hello);
static int iGreetDistanceMultiplier = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("iGreetDistanceMultiplier")->getInt();
helloDistance *= iGreetDistanceMultiplier;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
float playerDistSqr = (playerPos - actorPos).length2();
int& greetingTimer = storage.mGreetingTimer;
GreetingState& greetingState = storage.mSaidGreeting;
if (greetingState == Greet_None)
{
if ((playerDistSqr <= helloDistance*helloDistance) &&
!player.getClass().getCreatureStats(player).isDead() && MWBase::Environment::get().getWorld()->getLOS(player, actor)
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, actor))
greetingTimer++;
if (greetingTimer >= GREETING_SHOULD_START)
{
float resetDist = 2*helloDistance;
if (playerDistSqr >= resetDist*resetDist)
greetingState = Greet_None;
greetingState = Greet_InProgress;
MWBase::Environment::get().getDialogueManager()->say(actor, "hello");
greetingTimer = 0;
}
}
if(moveNow && mDistance)
if (greetingState == Greet_InProgress)
{
// Construct a new path if there isn't one
if(!storage.mPathFinder.isPathConstructed())
greetingTimer++;
if (storage.mWalking)
{
assert(mAllowedNodes.size());
unsigned int randNode = Misc::Rng::rollDice(mAllowedNodes.size());
ESM::Pathgrid::Point dest(mAllowedNodes[randNode]);
ToWorldCoordinates(dest, currentCell->getCell());
stopWalking(actor, storage);
mObstacleCheck.clear();
storage.mIdleNow = true;
getRandomIdle(storage.mPlayedIdle);
}
// actor position is already in world co-ordinates
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos));
if (!storage.mRotate)
{
osg::Vec3f dir = playerPos - actorPos;
// don't take shortcuts for wandering
storage.mPathFinder.buildSyncedPath(start, dest, actor.getCell(), false);
float faceAngleRadians = std::atan2(dir.x(), dir.y());
storage.mTargetAngleRadians = faceAngleRadians;
storage.mRotate = true;
}
if(storage.mPathFinder.isPathConstructed())
{
// 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);
// check if mCurrentNode was taken out of mAllowedNodes
if(mTrimCurrentNode && mAllowedNodes.size() > 1)
mTrimCurrentNode = false;
else
mAllowedNodes.push_back(mCurrentNode);
mCurrentNode = temp;
if (greetingTimer >= GREETING_SHOULD_END)
{
greetingState = Greet_Done;
greetingTimer = 0;
}
}
moveNow = false;
walking = true;
}
// Choose a different node and delete this one from possible nodes because it is uncreachable:
else
mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
}
if (greetingState == MWMechanics::AiWander::Greet_Done)
{
float resetDist = 2 * helloDistance;
if (playerDistSqr >= resetDist*resetDist)
greetingState = Greet_None;
}
}
return false; // AiWander package not yet completed
void AiWander::setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos)
{
unsigned int randNode = Misc::Rng::rollDice(mAllowedNodes.size());
ESM::Pathgrid::Point dest(mAllowedNodes[randNode]);
ToWorldCoordinates(dest, storage.mCell->getCell());
// actor position is already in world co-ordinates
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(actorPos));
// don't take shortcuts for wandering
storage.mPathFinder.buildSyncedPath(start, dest, actor.getCell(), false);
if (storage.mPathFinder.isPathConstructed())
{
// 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);
// check if mCurrentNode was taken out of mAllowedNodes
if (mTrimCurrentNode && mAllowedNodes.size() > 1)
mTrimCurrentNode = false;
else
mAllowedNodes.push_back(mCurrentNode);
mCurrentNode = temp;
storage.mMoveNow = false;
storage.mWalking = true;
}
// Choose a different node and delete this one from possible nodes because it is uncreachable:
else
mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
}
void AiWander::ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell)
@ -583,6 +591,8 @@ namespace MWMechanics
{
storage.mPathFinder.clearPath();
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
storage.mMoveNow = false;
storage.mWalking = false;
}
void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
@ -640,7 +650,7 @@ namespace MWMechanics
if (mDistance == 0)
return;
if (!mStoredAvailableNodes)
if (mPopulateAvailableNodes)
getAllowedNodes(actor, actor.getCell()->getCell());
if (mAllowedNodes.empty())
@ -660,7 +670,7 @@ namespace MWMechanics
actor.getClass().adjustPosition(actor, false);
// may have changed cell
mStoredAvailableNodes = false;
mPopulateAvailableNodes = true;
}
int AiWander::OffsetToPreventOvercrowding()
@ -722,8 +732,9 @@ namespace MWMechanics
{
SetCurrentNodeToClosestAllowedNode(npcPos);
}
mStoredAvailableNodes = true; // set only if successful in finding allowed nodes
}
mPopulateAvailableNodes = false;
}
// When only one path grid point in wander distance,

@ -71,6 +71,10 @@ namespace MWMechanics
void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
void getRandomIdle(unsigned short& playedIdle);
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
void playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration);
void playIdleDialogueRandomly(const MWWorld::Ptr& actor);
int mDistance; // how far the actor can wander from the spawn point
int mDuration;
@ -88,8 +92,8 @@ namespace MWMechanics
// if false triggers calculating allowed nodes based on mDistance
bool mStoredAvailableNodes;
// do we need to calculate allowed nodes based on mDistance
bool mPopulateAvailableNodes;

@ -459,7 +459,7 @@ void NpcAnimation::updateParts()
};
static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]);
bool wasArrowAttached = 0;//(mAmmunition.get() != NULL);
bool wasArrowAttached = (mAmmunition.get() != NULL);
MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++)
@ -622,7 +622,7 @@ void NpcAnimation::updateParts()
continue;
}
if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
if ((!mNpc->isMale()) != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
{
// Allow opposite gender's parts as fallback if parts for our gender are missing
BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart));

@ -59,7 +59,6 @@ namespace MWRender
private:
osg::ref_ptr<osg::Group> mParent;
Resource::ResourceSystem* mResourceSystem;
osg::ref_ptr<osgParticle::ParticleSystem> mParticleSystem;
osg::ref_ptr<osg::PositionAttitudeTransform> mParticleNode;

@ -1064,11 +1064,11 @@ namespace MWWorld
template class MWWorld::Store<ESM::Activator>;
template class MWWorld::Store<ESM::Apparatus>;
template class MWWorld::Store<ESM::Armor>;
template class MWWorld::Store<ESM::Attribute>;
//template class MWWorld::Store<ESM::Attribute>;
template class MWWorld::Store<ESM::BirthSign>;
template class MWWorld::Store<ESM::BodyPart>;
template class MWWorld::Store<ESM::Book>;
template class MWWorld::Store<ESM::Cell>;
//template class MWWorld::Store<ESM::Cell>;
template class MWWorld::Store<ESM::Class>;
template class MWWorld::Store<ESM::Clothing>;
template class MWWorld::Store<ESM::Container>;
@ -1082,21 +1082,21 @@ template class MWWorld::Store<ESM::GameSetting>;
template class MWWorld::Store<ESM::Global>;
template class MWWorld::Store<ESM::Ingredient>;
template class MWWorld::Store<ESM::ItemLevList>;
template class MWWorld::Store<ESM::Land>;
//template class MWWorld::Store<ESM::Land>;
template class MWWorld::Store<ESM::LandTexture>;
template class MWWorld::Store<ESM::Light>;
template class MWWorld::Store<ESM::Lockpick>;
template class MWWorld::Store<ESM::MagicEffect>;
//template class MWWorld::Store<ESM::MagicEffect>;
template class MWWorld::Store<ESM::Miscellaneous>;
template class MWWorld::Store<ESM::NPC>;
template class MWWorld::Store<ESM::Pathgrid>;
//template class MWWorld::Store<ESM::Pathgrid>;
template class MWWorld::Store<ESM::Potion>;
template class MWWorld::Store<ESM::Probe>;
template class MWWorld::Store<ESM::Race>;
template class MWWorld::Store<ESM::Region>;
template class MWWorld::Store<ESM::Repair>;
template class MWWorld::Store<ESM::Script>;
template class MWWorld::Store<ESM::Skill>;
//template class MWWorld::Store<ESM::Skill>;
template class MWWorld::Store<ESM::Sound>;
template class MWWorld::Store<ESM::SoundGenerator>;
template class MWWorld::Store<ESM::Spell>;

@ -319,7 +319,7 @@ namespace MWWorld
public:
Store<ESM::Pathgrid>();
Store();
void setCells(Store<ESM::Cell>& cells);
void load(ESM::ESMReader &esm, const std::string &id);

@ -180,6 +180,7 @@ target_link_libraries(components
${SDL2_LIBRARY}
# For MyGUI platform
${OPENGL_gl_LIBRARY}
${MYGUI_LIBRARIES}
)
if (WIN32)

@ -119,7 +119,7 @@ class Drawable : public osg::Drawable {
// VBOs disabled due to crash in OSG: http://forum.openscenegraph.org/viewtopic.php?t=14909
osg::GLBufferObject* bufferobject = 0;//state->isVertexBufferObjectSupported() ? vbo->getOrCreateGLBufferObject(state->getContextID()) : 0;
if (bufferobject)
if (0)//bufferobject)
{
state->bindVertexBufferObject(bufferobject);

@ -407,7 +407,8 @@ FlipController::FlipController(int texSlot, float delta, std::vector<osg::ref_pt
}
FlipController::FlipController()
: mDelta(0.f)
: mTexSlot(0)
, mDelta(0.f)
{
}

@ -175,23 +175,16 @@ namespace SDLUtil
}
}
bool SDLCursorManager::cursorChanged(const std::string& name)
void SDLCursorManager::cursorChanged(const std::string& name)
{
mCurrentCursor = name;
CursorMap::const_iterator curs_iter = mCursorMap.find(name);
//we have this cursor
if(curs_iter != mCursorMap.end())
{
//we have this cursor
_setGUICursor(name);
return false;
}
else
{
//they should get back to us with more info
return true;
}
}
@ -200,7 +193,7 @@ namespace SDLUtil
SDL_SetCursor(mCursorMap.find(name)->second);
}
void SDLCursorManager::receiveCursorInfo(const std::string& name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y)
void SDLCursorManager::createCursor(const std::string& name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y)
{
_createCursorFromResource(name, rotDegrees, image, size_x, size_y, hotspot_x, hotspot_y);
}

@ -27,11 +27,9 @@ namespace SDLUtil
/// \brief Tell the manager that the cursor has changed, giving the
/// name of the cursor we changed to ("arrow", "ibeam", etc)
/// \return Whether the manager is interested in more information about the cursor
virtual bool cursorChanged(const std::string &name);
virtual void cursorChanged(const std::string &name);
/// \brief Follow up a cursorChanged() call with enough info to create an cursor.
virtual void receiveCursorInfo(const std::string &name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y);
virtual void createCursor(const std::string &name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y);
private:
void _createCursorFromResource(const std::string &name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y);

Loading…
Cancel
Save