Merge pull request #294 from OpenMW/master while resolving conflicts

# Conflicts:
#	apps/openmw/mwmechanics/character.cpp
pull/295/head
David Cernat 7 years ago
commit 7f0ea7d01f

@ -235,6 +235,10 @@ namespace MWBase
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0; virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const = 0; virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const = 0;
/// Check if the target actor was detected by an observer
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) = 0;
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0; virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
/// List the owners that the player has stolen this item from (the owner can be an NPC or a faction). /// List the owners that the player has stolen this item from (the owner can be an NPC or a faction).

@ -82,9 +82,6 @@ namespace MWBase
///< Play a soundifle ///< Play a soundifle
/// \param filename name of a sound file in "Music/" in the data directory. /// \param filename name of a sound file in "Music/" in the data directory.
virtual void startRandomTitle() = 0;
///< Starts a random track from the current playlist
virtual bool isMusicPlaying() = 0; virtual bool isMusicPlaying() = 0;
///< Returns true if music is playing ///< Returns true if music is playing

@ -206,7 +206,8 @@ namespace MWGui
int textButtonPadding = 10; // padding between the text-widget und the button-widget int textButtonPadding = 10; // padding between the text-widget und the button-widget
int buttonLeftPadding = 10; // padding between the buttons if horizontal int buttonLeftPadding = 10; // padding between the buttons if horizontal
int buttonTopPadding = 10; // ^-- if vertical int buttonTopPadding = 10; // ^-- if vertical
int buttonPadding = 5; // padding between button label and button itself int buttonLabelLeftPadding = 12; // padding between button label and button itself, from left
int buttonLabelTopPadding = 4; // padding between button label and button itself, from top
int buttonMainPadding = 10; // padding between buttons and bottom of the main widget int buttonMainPadding = 10; // padding between buttons and bottom of the main widget
mMarkedToDelete = false; mMarkedToDelete = false;
@ -245,10 +246,10 @@ namespace MWGui
if (buttonsWidth != 0) if (buttonsWidth != 0)
buttonsWidth += buttonLeftPadding; buttonsWidth += buttonLeftPadding;
int buttonWidth = button->getTextSize().width + 2*buttonPadding; int buttonWidth = button->getTextSize().width + 2*buttonLabelLeftPadding;
buttonsWidth += buttonWidth; buttonsWidth += buttonWidth;
buttonHeight = button->getTextSize().height + 2*buttonPadding; buttonHeight = button->getTextSize().height + 2*buttonLabelTopPadding;
if (buttonsHeight != 0) if (buttonsHeight != 0)
buttonsHeight += buttonTopPadding; buttonsHeight += buttonTopPadding;
@ -295,8 +296,8 @@ namespace MWGui
buttonCord.left = left; buttonCord.left = left;
buttonCord.top = messageWidgetCoord.top + textSize.height + textButtonPadding; buttonCord.top = messageWidgetCoord.top + textSize.height + textButtonPadding;
buttonSize.width = (*button)->getTextSize().width + 2*buttonPadding; buttonSize.width = (*button)->getTextSize().width + 2*buttonLabelLeftPadding;
buttonSize.height = (*button)->getTextSize().height + 2*buttonPadding; buttonSize.height = (*button)->getTextSize().height + 2*buttonLabelTopPadding;
(*button)->setCoord(buttonCord); (*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize); (*button)->setSize(buttonSize);
@ -322,8 +323,8 @@ namespace MWGui
std::vector<MyGUI::Button*>::const_iterator button; std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button) for(button = mButtons.begin(); button != mButtons.end(); ++button)
{ {
buttonSize.width = (*button)->getTextSize().width + buttonPadding*2; buttonSize.width = (*button)->getTextSize().width + buttonLabelLeftPadding*2;
buttonSize.height = (*button)->getTextSize().height + buttonPadding*2; buttonSize.height = (*button)->getTextSize().height + buttonLabelTopPadding*2;
buttonCord.top = top; buttonCord.top = top;
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2; buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2;

@ -1175,6 +1175,39 @@ namespace MWMechanics
} }
} }
bool Actors::isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer)
{
if (!actor.getClass().isActor())
return false;
// If an observer is NPC, check if he detected an actor
if (!observer.isEmpty() && observer.getClass().isNpc())
{
return
MWBase::Environment::get().getWorld()->getLOS(observer, actor) &&
MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor, observer);
}
// Otherwise check if any actor in AI processing range sees the target actor
std::vector<MWWorld::Ptr> actors;
osg::Vec3f position (actor.getRefData().getPosition().asVec3());
getObjectsInRange(position, aiProcessingDistance, actors);
for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); ++it)
{
if (*it == actor)
continue;
bool result =
MWBase::Environment::get().getWorld()->getLOS(*it, actor) &&
MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor, *it);
if (result)
return true;
}
return false;
}
void Actors::updateActor(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) void Actors::updateActor(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr)
{ {
PtrActorMap::iterator iter = mActors.find(old); PtrActorMap::iterator iter = mActors.find(old);

@ -57,6 +57,10 @@ namespace MWMechanics
PtrActorMap::const_iterator begin() { return mActors.begin(); } PtrActorMap::const_iterator begin() { return mActors.begin(); }
PtrActorMap::const_iterator end() { return mActors.end(); } PtrActorMap::const_iterator end() { return mActors.end(); }
/// Check if the target actor was detected by an observer
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer);
/// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently /// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently
/// paused we may want to do it manually (after equipping permanent enchantment) /// paused we may want to do it manually (after equipping permanent enchantment)
void updateMagicEffects (const MWWorld::Ptr& ptr); void updateMagicEffects (const MWWorld::Ptr& ptr);

@ -2146,76 +2146,71 @@ void CharacterController::unpersistAnimationState()
bool CharacterController::playGroup(const std::string &groupname, int mode, int count, bool persist) bool CharacterController::playGroup(const std::string &groupname, int mode, int count, bool persist)
{ {
if(!mAnimation || !mAnimation->hasAnimation(groupname)) if(!mAnimation || !mAnimation->hasAnimation(groupname))
{
std::cerr<< "Animation "<<groupname<<" not found for " << mPtr.getCellRef().getRefId() << std::endl;
return false; return false;
}
else // If this animation is a looped animation (has a "loop start" key) that is already playing
// and has not yet reached the end of the loop, allow it to continue animating with its existing loop count
// and remove any other animations that were queued.
// This emulates observed behavior from the original allows the script "OutsideBanner" to animate banners correctly.
if (!mAnimQueue.empty() && mAnimQueue.front().mGroup == groupname &&
mAnimation->getTextKeyTime(mAnimQueue.front().mGroup + ": loop start") >= 0 &&
mAnimation->isPlaying(groupname))
{ {
// If this animation is a looped animation (has a "loop start" key) that is already playing float endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": loop stop");
// and has not yet reached the end of the loop, allow it to continue animating with its existing loop count
// and remove any other animations that were queued.
// This emulates observed behavior from the original allows the script "OutsideBanner" to animate banners correctly.
if (!mAnimQueue.empty() && mAnimQueue.front().mGroup == groupname &&
mAnimation->getTextKeyTime(mAnimQueue.front().mGroup + ": loop start") >= 0 &&
mAnimation->isPlaying(groupname))
{
float endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": loop stop");
if (endOfLoop < 0) // if no Loop Stop key was found, use the Stop key if (endOfLoop < 0) // if no Loop Stop key was found, use the Stop key
endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": stop"); endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": stop");
if (endOfLoop > 0 && (mAnimation->getCurrentTime(mAnimQueue.front().mGroup) < endOfLoop)) if (endOfLoop > 0 && (mAnimation->getCurrentTime(mAnimQueue.front().mGroup) < endOfLoop))
{ {
mAnimQueue.resize(1); mAnimQueue.resize(1);
return true; return true;
}
} }
}
count = std::max(count, 1); count = std::max(count, 1);
AnimationQueueEntry entry; AnimationQueueEntry entry;
entry.mGroup = groupname; entry.mGroup = groupname;
entry.mLoopCount = count-1; entry.mLoopCount = count-1;
entry.mPersist = persist; entry.mPersist = persist;
if(mode != 0 || mAnimQueue.empty() || !isAnimPlaying(mAnimQueue.front().mGroup)) if(mode != 0 || mAnimQueue.empty() || !isAnimPlaying(mAnimQueue.front().mGroup))
{ {
clearAnimQueue(); clearAnimQueue();
mAnimQueue.push_back(entry); mAnimQueue.push_back(entry);
mAnimation->disable(mCurrentIdle); mAnimation->disable(mCurrentIdle);
mCurrentIdle.clear(); mCurrentIdle.clear();
mIdleState = CharState_SpecialIdle; mIdleState = CharState_SpecialIdle;
bool loopfallback = (entry.mGroup.compare(0,4,"idle") == 0); bool loopfallback = (entry.mGroup.compare(0,4,"idle") == 0);
mAnimation->play(groupname, Priority_Default, mAnimation->play(groupname, Priority_Default,
MWRender::Animation::BlendMask_All, false, 1.0f, MWRender::Animation::BlendMask_All, false, 1.0f,
((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1, loopfallback); ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1, loopfallback);
/* /*
Start of tes3mp addition Start of tes3mp addition
If we are the cell authority over this actor, we need to record this new If we are the cell authority over this actor, we need to record this new
animation for it animation for it
*/ */
if (mwmp::Main::get().getCellController()->isLocalActor(mPtr)) if (mwmp::Main::get().getCellController()->isLocalActor(mPtr))
{
mwmp::LocalActor *actor = mwmp::Main::get().getCellController()->getLocalActor(mPtr);
actor->animation.groupname = groupname;
actor->animation.mode = mode;
actor->animation.count = count;
actor->animation.persist = persist;
}
/*
End of tes3mp addition
*/
}
else if(mode == 0)
{ {
mAnimQueue.resize(1); mwmp::LocalActor *actor = mwmp::Main::get().getCellController()->getLocalActor(mPtr);
mAnimQueue.push_back(entry); actor->animation.groupname = groupname;
actor->animation.mode = mode;
actor->animation.count = count;
actor->animation.persist = persist;
} }
/*
End of tes3mp addition
*/
}
else if(mode == 0)
{
mAnimQueue.resize(1);
mAnimQueue.push_back(entry);
} }
return true; return true;
} }

@ -436,6 +436,11 @@ namespace MWMechanics
mObjects.update(duration, paused); mObjects.update(duration, paused);
} }
bool MechanicsManager::isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer)
{
return mActors.isActorDetected(actor, observer);
}
bool MechanicsManager::isAttackPrepairing(const MWWorld::Ptr& ptr) bool MechanicsManager::isAttackPrepairing(const MWWorld::Ptr& ptr)
{ {
return mActors.isAttackPrepairing(ptr); return mActors.isAttackPrepairing(ptr);

@ -201,6 +201,10 @@ namespace MWMechanics
/// Is \a ptr casting spell or using weapon now? /// Is \a ptr casting spell or using weapon now?
virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const; virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const;
/// Check if the target actor was detected by an observer
/// If the observer is a non-NPC, check all actors in AI processing distance as observers
virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer);
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer); virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer);
/// List the owners that the player has stolen this item from (the owner can be an NPC or a faction). /// List the owners that the player has stolen this item from (the owner can be an NPC or a faction).

@ -757,8 +757,6 @@ namespace MWRender
break; break;
} }
} }
if(iter == mAnimSources.rend())
std::cerr<< "Failed to find animation "<<groupname<<" for "<<mPtr.getCellRef().getRefId() <<std::endl;
resetActiveGroups(); resetActiveGroups();
} }
@ -795,7 +793,7 @@ namespace MWRender
// We have to ignore extra garbage at the end. // We have to ignore extra garbage at the end.
// The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop". // The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop".
// Why, just why? :( // Why, just why? :(
&& (stopkey->second.size() < stoptag.size() || stopkey->second.substr(0,stoptag.size()) != stoptag)) && (stopkey->second.size() < stoptag.size() || stopkey->second.compare(0,stoptag.size(), stoptag) != 0))
++stopkey; ++stopkey;
if(stopkey == keys.rend()) if(stopkey == keys.rend())
return false; return false;

@ -372,21 +372,14 @@ namespace MWScript
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
MWWorld::Ptr observer = R()(runtime); MWWorld::Ptr observer = R()(runtime, false); // required=false
std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); std::string actorID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true); MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true);
if(!actor.getClass().isActor() || !observer.getClass().isActor()) Interpreter::Type_Integer value = MWBase::Environment::get().getMechanicsManager()->isActorDetected(actor, observer);
{
runtime.push(0);
return;
}
Interpreter::Type_Integer value =
MWBase::Environment::get().getWorld()->getLOS(observer, actor) &&
MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor, observer);
runtime.push (value); runtime.push (value);
} }

@ -391,11 +391,6 @@ namespace MWSound
mMusic->setFadeout(0.5f); mMusic->setFadeout(0.5f);
} }
void SoundManager::streamMusic(const std::string& filename)
{
advanceMusic("Music/"+filename);
}
void SoundManager::startRandomTitle() void SoundManager::startRandomTitle()
{ {
std::vector<std::string> filelist; std::vector<std::string> filelist;
@ -446,6 +441,12 @@ namespace MWSound
tracklist.pop_back(); tracklist.pop_back();
} }
void SoundManager::streamMusic(const std::string& filename)
{
advanceMusic("Music/"+filename);
}
bool SoundManager::isMusicPlaying() bool SoundManager::isMusicPlaying()
{ {
return mMusic && mOutput->isStreamPlaying(mMusic); return mMusic && mOutput->isStreamPlaying(mMusic);

@ -127,6 +127,7 @@ namespace MWSound
void streamMusicFull(const std::string& filename); void streamMusicFull(const std::string& filename);
void advanceMusic(const std::string& filename); void advanceMusic(const std::string& filename);
void startRandomTitle();
void updateSounds(float duration); void updateSounds(float duration);
void updateRegionSound(float duration); void updateRegionSound(float duration);
@ -157,9 +158,6 @@ namespace MWSound
///< Play a soundifle ///< Play a soundifle
/// \param filename name of a sound file in "Music/" in the data directory. /// \param filename name of a sound file in "Music/" in the data directory.
virtual void startRandomTitle();
///< Starts a random track from the current playlist
virtual bool isMusicPlaying(); virtual bool isMusicPlaying();
///< Returns true if music is playing ///< Returns true if music is playing

@ -141,11 +141,11 @@ namespace Resource
void setUnRefImageDataAfterApply(bool unref); void setUnRefImageDataAfterApply(bool unref);
/// @see ResourceManager::updateCache /// @see ResourceManager::updateCache
virtual void updateCache(double referenceTime); void updateCache(double referenceTime) override;
virtual void clearCache(); void clearCache() override;
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const; void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
private: private:

@ -32,9 +32,9 @@ namespace Terrain
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, int lod, unsigned int lodFlags); osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, int lod, unsigned int lodFlags);
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const; void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
virtual void clearCache(); void clearCache() override;
void releaseGLObjects(osg::State* state) override; void releaseGLObjects(osg::State* state) override;

Loading…
Cancel
Save