mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 19:19:40 +00:00
Move idle dialogue playback from AiWander (bug #4594)
This commit is contained in:
parent
f405b1e247
commit
cec55119ca
4 changed files with 33 additions and 34 deletions
apps/openmw/mwmechanics
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/misc/rng.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
@ -348,6 +349,33 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Actors::playIdleDialogue(const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
if (!actor.getClass().isActor() || actor == getPlayer() || !MWBase::Environment::get().getSoundManager()->sayDone(actor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const CreatureStats &stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
if (stats.getAiSetting(CreatureStats::AI_Hello).getModified() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const MWMechanics::AiSequence& seq = stats.getAiSequence();
|
||||||
|
if (seq.isInCombat() || seq.hasPackage(AiPackage::TypeIdFollow) || seq.hasPackage(AiPackage::TypeIdEscort))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const osg::Vec3f playerPos(getPlayer().getRefData().getPosition().asVec3());
|
||||||
|
const osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
if (world->isSwimming(actor) || (playerPos - actorPos).length2() >= 3000 * 3000)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Our implementation is not FPS-dependent unlike Morrowind's so it 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.
|
||||||
|
const float delta = MWBase::Environment::get().getFrameDuration() * 6.f;
|
||||||
|
static const float fVoiceIdleOdds = world->getStore().get<ESM::GameSetting>().find("fVoiceIdleOdds")->mValue.getFloat();
|
||||||
|
if (Misc::Rng::rollProbability() * 10000.f < fVoiceIdleOdds * delta && world->getLOS(getPlayer(), actor))
|
||||||
|
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer)
|
void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer)
|
||||||
{
|
{
|
||||||
// No combat for totally static creatures
|
// No combat for totally static creatures
|
||||||
|
@ -1408,7 +1436,10 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first);
|
CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first);
|
||||||
if (isConscious(iter->first))
|
if (isConscious(iter->first))
|
||||||
|
{
|
||||||
stats.getAiSequence().execute(iter->first, *ctrl, duration);
|
stats.getAiSequence().execute(iter->first, *ctrl, duration);
|
||||||
|
playIdleDialogue(iter->first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,8 @@ namespace MWMechanics
|
||||||
*/
|
*/
|
||||||
void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer);
|
void engageCombat(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> >& cachedAllies, bool againstPlayer);
|
||||||
|
|
||||||
|
void playIdleDialogue(const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
void updateHeadTracking(const MWWorld::Ptr& actor, const MWWorld::Ptr& targetActor,
|
void updateHeadTracking(const MWWorld::Ptr& actor, const MWWorld::Ptr& targetActor,
|
||||||
MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance);
|
MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/dialoguemanager.hpp"
|
#include "../mwbase/dialoguemanager.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
@ -167,8 +166,6 @@ namespace MWMechanics
|
||||||
|
|
||||||
doPerFrameActionsForState(actor, duration, storage);
|
doPerFrameActionsForState(actor, duration, storage);
|
||||||
|
|
||||||
playIdleDialogueRandomly(actor);
|
|
||||||
|
|
||||||
float& lastReaction = storage.mReaction;
|
float& lastReaction = storage.mReaction;
|
||||||
lastReaction += duration;
|
lastReaction += duration;
|
||||||
if (AI_REACTION_TIME <= lastReaction)
|
if (AI_REACTION_TIME <= lastReaction)
|
||||||
|
@ -492,36 +489,6 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = getPlayer();
|
|
||||||
|
|
||||||
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
|
|
||||||
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->mValue.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 osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
|
|
||||||
const osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
|
|
||||||
if (roll < x && (playerPos - actorPos).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)
|
void AiWander::playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage)
|
||||||
{
|
{
|
||||||
// Play a random voice greeting if the player gets too close
|
// Play a random voice greeting if the player gets too close
|
||||||
|
|
|
@ -138,7 +138,6 @@ namespace MWMechanics
|
||||||
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
|
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
|
||||||
void playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
void playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void playIdleDialogueRandomly(const MWWorld::Ptr& actor);
|
|
||||||
void turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage);
|
void turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage);
|
||||||
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||||
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||||
|
|
Loading…
Reference in a new issue