|
|
|
@ -282,6 +282,58 @@ namespace MWMechanics
|
|
|
|
|
rotate = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if idle animation finished
|
|
|
|
|
short unsigned& playedIdle = storage.mPlayedIdle;
|
|
|
|
|
GreetingState& greetingState = storage.mSaidGreeting;
|
|
|
|
|
if(idleNow && !checkIdle(actor, playedIdle) && (greetingState == Greet_Done || greetingState == Greet_None))
|
|
|
|
|
{
|
|
|
|
|
playedIdle = 0;
|
|
|
|
|
idleNow = false;
|
|
|
|
|
chooseAction = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
|
|
|
|
|
|
|
|
|
if(chooseAction)
|
|
|
|
|
{
|
|
|
|
|
playedIdle = 0;
|
|
|
|
|
getRandomIdle(playedIdle); // NOTE: sets mPlayedIdle with a random selection
|
|
|
|
|
|
|
|
|
|
if(!playedIdle && mDistance)
|
|
|
|
|
{
|
|
|
|
|
chooseAction = false;
|
|
|
|
|
moveNow = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
|
|
|
|
|
MWWorld::TimeStamp currentTime = world->getTimeStamp();
|
|
|
|
|
mStartTime = currentTime;
|
|
|
|
|
playIdle(actor, playedIdle);
|
|
|
|
|
chooseAction = false;
|
|
|
|
|
idleNow = true;
|
|
|
|
|
|
|
|
|
|
// Play idle voiced dialogue entries randomly
|
|
|
|
|
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
|
|
|
|
if (hello > 0)
|
|
|
|
|
{
|
|
|
|
|
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
|
|
|
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
|
|
|
|
|
|
// Don't bother if the player is out of hearing range
|
|
|
|
|
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
|
|
|
|
|
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
|
|
|
|
|
|
|
|
|
|
// 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 < fVoiceIdleOdds && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos)) < 1500*1500
|
|
|
|
|
&& MWBase::Environment::get().getWorld()->getLOS(player, actor))
|
|
|
|
|
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float& lastReaction = storage.mReaction;
|
|
|
|
|
lastReaction += duration;
|
|
|
|
|
if(lastReaction < REACTION_INTERVAL)
|
|
|
|
@ -293,7 +345,6 @@ namespace MWMechanics
|
|
|
|
|
|
|
|
|
|
// NOTE: everything below get updated every REACTION_INTERVAL seconds
|
|
|
|
|
|
|
|
|
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
|
|
|
|
if(mDuration)
|
|
|
|
|
{
|
|
|
|
|
// End package if duration is complete or mid-night hits:
|
|
|
|
@ -439,48 +490,6 @@ namespace MWMechanics
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AiWander::GreetingState& greetingState = storage.mSaidGreeting;
|
|
|
|
|
short unsigned& playedIdle = storage.mPlayedIdle;
|
|
|
|
|
if(chooseAction)
|
|
|
|
|
{
|
|
|
|
|
playedIdle = 0;
|
|
|
|
|
getRandomIdle(playedIdle); // NOTE: sets mPlayedIdle with a random selection
|
|
|
|
|
|
|
|
|
|
if(!playedIdle && mDistance)
|
|
|
|
|
{
|
|
|
|
|
chooseAction = false;
|
|
|
|
|
moveNow = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
|
|
|
|
|
MWWorld::TimeStamp currentTime = world->getTimeStamp();
|
|
|
|
|
mStartTime = currentTime;
|
|
|
|
|
playIdle(actor, playedIdle);
|
|
|
|
|
chooseAction = false;
|
|
|
|
|
idleNow = true;
|
|
|
|
|
|
|
|
|
|
// Play idle voiced dialogue entries randomly
|
|
|
|
|
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
|
|
|
|
if (hello > 0)
|
|
|
|
|
{
|
|
|
|
|
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
|
|
|
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
|
|
|
|
|
|
|
|
// Don't bother if the player is out of hearing range
|
|
|
|
|
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
|
|
|
|
|
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
|
|
|
|
|
|
|
|
|
|
// 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 < fVoiceIdleOdds && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos)) < 1500*1500
|
|
|
|
|
&& MWBase::Environment::get().getWorld()->getLOS(player, actor))
|
|
|
|
|
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allow interrupting a walking actor to trigger a greeting
|
|
|
|
|
if(idleNow || walking)
|
|
|
|
|
{
|
|
|
|
@ -496,7 +505,7 @@ namespace MWMechanics
|
|
|
|
|
Ogre::Vector3 playerPos(player.getRefData().getPosition().pos);
|
|
|
|
|
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
|
|
|
|
|
float playerDistSqr = playerPos.squaredDistance(actorPos);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int& greetingTimer = storage.mGreetingTimer;
|
|
|
|
|
if (greetingState == Greet_None)
|
|
|
|
|
{
|
|
|
|
@ -556,14 +565,6 @@ namespace MWMechanics
|
|
|
|
|
if (playerDistSqr >= fGreetDistanceReset*fGreetDistanceReset)
|
|
|
|
|
greetingState = Greet_None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if idle animation finished
|
|
|
|
|
if(!checkIdle(actor, playedIdle) && (playerDistSqr > helloDistance*helloDistance || greetingState == MWMechanics::AiWander::Greet_Done))
|
|
|
|
|
{
|
|
|
|
|
playedIdle = 0;
|
|
|
|
|
idleNow = false;
|
|
|
|
|
chooseAction = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(moveNow && mDistance)
|
|
|
|
|