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

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

@ -235,6 +235,10 @@ namespace MWBase
virtual bool isReadyToBlock (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;
/// 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
/// \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;
///< 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 buttonLeftPadding = 10; // padding between the buttons if horizontal
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
mMarkedToDelete = false;
@ -245,10 +246,10 @@ namespace MWGui
if (buttonsWidth != 0)
buttonsWidth += buttonLeftPadding;
int buttonWidth = button->getTextSize().width + 2*buttonPadding;
int buttonWidth = button->getTextSize().width + 2*buttonLabelLeftPadding;
buttonsWidth += buttonWidth;
buttonHeight = button->getTextSize().height + 2*buttonPadding;
buttonHeight = button->getTextSize().height + 2*buttonLabelTopPadding;
if (buttonsHeight != 0)
buttonsHeight += buttonTopPadding;
@ -295,8 +296,8 @@ namespace MWGui
buttonCord.left = left;
buttonCord.top = messageWidgetCoord.top + textSize.height + textButtonPadding;
buttonSize.width = (*button)->getTextSize().width + 2*buttonPadding;
buttonSize.height = (*button)->getTextSize().height + 2*buttonPadding;
buttonSize.width = (*button)->getTextSize().width + 2*buttonLabelLeftPadding;
buttonSize.height = (*button)->getTextSize().height + 2*buttonLabelTopPadding;
(*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize);
@ -322,8 +323,8 @@ namespace MWGui
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonSize.width = (*button)->getTextSize().width + buttonPadding*2;
buttonSize.height = (*button)->getTextSize().height + buttonPadding*2;
buttonSize.width = (*button)->getTextSize().width + buttonLabelLeftPadding*2;
buttonSize.height = (*button)->getTextSize().height + buttonLabelTopPadding*2;
buttonCord.top = top;
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)
{
PtrActorMap::iterator iter = mActors.find(old);

@ -57,6 +57,10 @@ namespace MWMechanics
PtrActorMap::const_iterator begin() { return mActors.begin(); }
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
/// paused we may want to do it manually (after equipping permanent enchantment)
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)
{
if(!mAnimation || !mAnimation->hasAnimation(groupname))
{
std::cerr<< "Animation "<<groupname<<" not found for " << mPtr.getCellRef().getRefId() << std::endl;
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
// 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");
float endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": loop stop");
if (endOfLoop < 0) // if no Loop Stop key was found, use the Stop key
endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": stop");
if (endOfLoop < 0) // if no Loop Stop key was found, use the Stop key
endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": stop");
if (endOfLoop > 0 && (mAnimation->getCurrentTime(mAnimQueue.front().mGroup) < endOfLoop))
{
mAnimQueue.resize(1);
return true;
}
if (endOfLoop > 0 && (mAnimation->getCurrentTime(mAnimQueue.front().mGroup) < endOfLoop))
{
mAnimQueue.resize(1);
return true;
}
}
count = std::max(count, 1);
count = std::max(count, 1);
AnimationQueueEntry entry;
entry.mGroup = groupname;
entry.mLoopCount = count-1;
entry.mPersist = persist;
AnimationQueueEntry entry;
entry.mGroup = groupname;
entry.mLoopCount = count-1;
entry.mPersist = persist;
if(mode != 0 || mAnimQueue.empty() || !isAnimPlaying(mAnimQueue.front().mGroup))
{
clearAnimQueue();
mAnimQueue.push_back(entry);
if(mode != 0 || mAnimQueue.empty() || !isAnimPlaying(mAnimQueue.front().mGroup))
{
clearAnimQueue();
mAnimQueue.push_back(entry);
mAnimation->disable(mCurrentIdle);
mCurrentIdle.clear();
mAnimation->disable(mCurrentIdle);
mCurrentIdle.clear();
mIdleState = CharState_SpecialIdle;
bool loopfallback = (entry.mGroup.compare(0,4,"idle") == 0);
mAnimation->play(groupname, Priority_Default,
MWRender::Animation::BlendMask_All, false, 1.0f,
((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1, loopfallback);
mIdleState = CharState_SpecialIdle;
bool loopfallback = (entry.mGroup.compare(0,4,"idle") == 0);
mAnimation->play(groupname, Priority_Default,
MWRender::Animation::BlendMask_All, false, 1.0f,
((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
animation for it
*/
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)
If we are the cell authority over this actor, we need to record this new
animation for it
*/
if (mwmp::Main::get().getCellController()->isLocalActor(mPtr))
{
mAnimQueue.resize(1);
mAnimQueue.push_back(entry);
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);
mAnimQueue.push_back(entry);
}
return true;
}

@ -436,6 +436,11 @@ namespace MWMechanics
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)
{
return mActors.isAttackPrepairing(ptr);

@ -201,6 +201,10 @@ namespace MWMechanics
/// Is \a ptr casting spell or using weapon now?
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);
/// 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;
}
}
if(iter == mAnimSources.rend())
std::cerr<< "Failed to find animation "<<groupname<<" for "<<mPtr.getCellRef().getRefId() <<std::endl;
resetActiveGroups();
}
@ -795,7 +793,7 @@ namespace MWRender
// We have to ignore extra garbage at the end.
// The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop".
// 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;
if(stopkey == keys.rend())
return false;

@ -372,21 +372,14 @@ namespace MWScript
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);
runtime.pop();
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true);
if(!actor.getClass().isActor() || !observer.getClass().isActor())
{
runtime.push(0);
return;
}
Interpreter::Type_Integer value =
MWBase::Environment::get().getWorld()->getLOS(observer, actor) &&
MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor, observer);
Interpreter::Type_Integer value = MWBase::Environment::get().getMechanicsManager()->isActorDetected(actor, observer);
runtime.push (value);
}

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

@ -127,6 +127,7 @@ namespace MWSound
void streamMusicFull(const std::string& filename);
void advanceMusic(const std::string& filename);
void startRandomTitle();
void updateSounds(float duration);
void updateRegionSound(float duration);
@ -157,9 +158,6 @@ namespace MWSound
///< Play a soundifle
/// \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();
///< Returns true if music is playing

@ -141,11 +141,11 @@ namespace Resource
void setUnRefImageDataAfterApply(bool unref);
/// @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:

@ -32,9 +32,9 @@ namespace Terrain
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;

Loading…
Cancel
Save