mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-03 15:15:34 +00:00
Merged pull request #1932
This commit is contained in:
commit
6ce6108eb4
2 changed files with 52 additions and 50 deletions
|
@ -501,12 +501,6 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration)
|
||||
{
|
||||
updateDrowning(ptr, duration);
|
||||
calculateNpcStatModifiers(ptr, duration);
|
||||
}
|
||||
|
||||
void Actors::adjustMagicEffects (const MWWorld::Ptr& creature)
|
||||
{
|
||||
CreatureStats& creatureStats = creature.getClass().getCreatureStats (creature);
|
||||
|
@ -926,13 +920,8 @@ namespace MWMechanics
|
|||
return ctrl->isSneaking();
|
||||
}
|
||||
|
||||
void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration)
|
||||
void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration, bool isKnockedOut, bool isPlayer)
|
||||
{
|
||||
PtrActorMap::iterator it = mActors.find(ptr);
|
||||
if (it == mActors.end())
|
||||
return;
|
||||
CharacterController* ctrl = it->second->getCharacterController();
|
||||
|
||||
NpcStats &stats = ptr.getClass().getNpcStats(ptr);
|
||||
|
||||
// When npc stats are just initialized, mTimeToStartDrowning == -1 and we should get value from GMST
|
||||
|
@ -940,9 +929,10 @@ namespace MWMechanics
|
|||
if (stats.getTimeToStartDrowning() == -1.f)
|
||||
stats.setTimeToStartDrowning(fHoldBreathTime);
|
||||
|
||||
if (ptr.getClass().isNpc() && stats.getTimeToStartDrowning() < fHoldBreathTime / 2)
|
||||
if (stats.getTimeToStartDrowning() < fHoldBreathTime / 2)
|
||||
{
|
||||
if(ptr != MWMechanics::getPlayer() ) {
|
||||
if(!isPlayer)
|
||||
{
|
||||
MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdBreathe) //Only add it once
|
||||
seq.stack(MWMechanics::AiBreathe(), ptr);
|
||||
|
@ -950,7 +940,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
bool knockedOutUnderwater = (ctrl->isKnockedOut() && world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3())));
|
||||
bool knockedOutUnderwater = (isKnockedOut && world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3())));
|
||||
if((world->isSubmerged(ptr) || knockedOutUnderwater)
|
||||
&& stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0)
|
||||
{
|
||||
|
@ -965,7 +955,7 @@ namespace MWMechanics
|
|||
stats.setTimeToStartDrowning(timeLeft);
|
||||
}
|
||||
|
||||
bool godmode = ptr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
||||
bool godmode = isPlayer && MWBase::Environment::get().getWorld()->getGodModeState();
|
||||
|
||||
if(timeLeft == 0.0f && !godmode)
|
||||
{
|
||||
|
@ -980,7 +970,7 @@ namespace MWMechanics
|
|||
if(!sndmgr->getSoundPlaying(ptr, "drown"))
|
||||
sndmgr->playSound3D(ptr, "drown", 1.0f, 1.0f);
|
||||
|
||||
if(ptr == world->getPlayerPtr())
|
||||
if(isPlayer)
|
||||
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
|
||||
}
|
||||
}
|
||||
|
@ -1242,21 +1232,24 @@ namespace MWMechanics
|
|||
void Actors::updateCombatMusic ()
|
||||
{
|
||||
MWWorld::Ptr player = getPlayer();
|
||||
int hostilesCount = 0; // need to know this to play Battle music
|
||||
const osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
||||
bool hasHostiles = false; // need to know this to play Battle music
|
||||
bool aiActive = MWBase::Environment::get().getMechanicsManager()->isAIActive();
|
||||
|
||||
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
if (aiActive)
|
||||
{
|
||||
if (!iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
{
|
||||
bool inProcessingRange = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2()
|
||||
<= sqrAiProcessingDistance;
|
||||
if (iter->first == player) continue;
|
||||
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isAIActive() && inProcessingRange)
|
||||
bool inProcessingRange = (playerPos - iter->first.getRefData().getPosition().asVec3()).length2() <= sqrAiProcessingDistance;
|
||||
if (inProcessingRange)
|
||||
{
|
||||
if (iter->first != player)
|
||||
MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first);
|
||||
if (!stats.isDead() && stats.getAiSequence().isInCombat())
|
||||
{
|
||||
MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first);
|
||||
if (stats.getAiSequence().isInCombat() && !stats.isDead()) hostilesCount++;
|
||||
hasHostiles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1265,13 +1258,13 @@ namespace MWMechanics
|
|||
// check if we still have any player enemies to switch music
|
||||
static int currentMusic = 0;
|
||||
|
||||
if (currentMusic != 1 && hostilesCount == 0 && !(player.getClass().getCreatureStats(player).isDead() &&
|
||||
if (currentMusic != 1 && !hasHostiles && !(player.getClass().getCreatureStats(player).isDead() &&
|
||||
MWBase::Environment::get().getSoundManager()->isMusicPlaying()))
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore"));
|
||||
currentMusic = 1;
|
||||
}
|
||||
else if (currentMusic != 2 && hostilesCount > 0)
|
||||
else if (currentMusic != 2 && hasHostiles)
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Battle"));
|
||||
currentMusic = 2;
|
||||
|
@ -1298,17 +1291,29 @@ namespace MWMechanics
|
|||
bool showTorches = MWBase::Environment::get().getWorld()->useTorches();
|
||||
|
||||
MWWorld::Ptr player = getPlayer();
|
||||
const osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
||||
|
||||
/// \todo move update logic to Actor class where appropriate
|
||||
|
||||
std::map<const MWWorld::Ptr, const std::set<MWWorld::Ptr> > cachedAllies; // will be filled as engageCombat iterates
|
||||
|
||||
bool aiActive = MWBase::Environment::get().getMechanicsManager()->isAIActive();
|
||||
int attackedByPlayerId = player.getClass().getCreatureStats(player).getHitAttemptActorId();
|
||||
if (attackedByPlayerId != -1)
|
||||
{
|
||||
const MWWorld::Ptr playerHitAttemptActor = MWBase::Environment::get().getWorld()->searchPtrViaActorId(attackedByPlayerId);
|
||||
|
||||
if (!playerHitAttemptActor.isInCell())
|
||||
player.getClass().getCreatureStats(player).setHitAttemptActorId(-1);
|
||||
}
|
||||
|
||||
// AI and magic effects update
|
||||
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
{
|
||||
bool isPlayer = iter->first == player;
|
||||
CharacterController* ctrl = iter->second->getCharacterController();
|
||||
|
||||
float distSqr = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2();
|
||||
float distSqr = (playerPos - iter->first.getRefData().getPosition().asVec3()).length2();
|
||||
// AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this
|
||||
// (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not)
|
||||
// This distance could be made configurable later, but the setting must be marked with a big warning:
|
||||
|
@ -1316,7 +1321,7 @@ namespace MWMechanics
|
|||
bool inProcessingRange = distSqr <= sqrAiProcessingDistance;
|
||||
|
||||
if (isPlayer)
|
||||
iter->second->getCharacterController()->setAttackingOrSpell(MWBase::Environment::get().getWorld()->getPlayer().getAttackingOrSpell());
|
||||
ctrl->setAttackingOrSpell(MWBase::Environment::get().getWorld()->getPlayer().getAttackingOrSpell());
|
||||
|
||||
// If dead or no longer in combat, no longer store any actors who attempted to hit us. Also remove for the player.
|
||||
if (iter->first != player && (iter->first.getClass().getCreatureStats(iter->first).isDead()
|
||||
|
@ -1328,11 +1333,6 @@ namespace MWMechanics
|
|||
player.getClass().getCreatureStats(player).setHitAttemptActorId(-1);
|
||||
}
|
||||
|
||||
const MWWorld::Ptr playerHitAttemptActor = MWBase::Environment::get().getWorld()->searchPtrViaActorId(player.getClass().getCreatureStats(player).getHitAttemptActorId());
|
||||
|
||||
if (!playerHitAttemptActor.isInCell())
|
||||
player.getClass().getCreatureStats(player).setHitAttemptActorId(-1);
|
||||
|
||||
if (!iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||
{
|
||||
bool cellChanged = MWBase::Environment::get().getWorld()->hasCellChanged();
|
||||
|
@ -1343,7 +1343,7 @@ namespace MWMechanics
|
|||
return; // for now abort update of the old cell when cell changes by teleportation magic effect
|
||||
// a better solution might be to apply cell changes at the end of the frame
|
||||
}
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isAIActive() && inProcessingRange)
|
||||
if (aiActive && inProcessingRange)
|
||||
{
|
||||
if (timerUpdateAITargets == 0)
|
||||
{
|
||||
|
@ -1381,7 +1381,7 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
iter->second->getCharacterController()->setHeadTrackTarget(headTrackTarget);
|
||||
ctrl->setHeadTrackTarget(headTrackTarget);
|
||||
}
|
||||
|
||||
if (iter->first.getClass().isNpc() && iter->first != player)
|
||||
|
@ -1391,13 +1391,14 @@ namespace MWMechanics
|
|||
{
|
||||
CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first);
|
||||
if (isConscious(iter->first))
|
||||
stats.getAiSequence().execute(iter->first, *iter->second->getCharacterController(), duration);
|
||||
stats.getAiSequence().execute(iter->first, *ctrl, duration);
|
||||
}
|
||||
}
|
||||
|
||||
if(iter->first.getTypeName() == typeid(ESM::NPC).name())
|
||||
{
|
||||
updateNpc(iter->first, duration);
|
||||
updateDrowning(iter->first, duration, ctrl->isKnockedOut(), isPlayer);
|
||||
calculateNpcStatModifiers(iter->first, duration);
|
||||
|
||||
if (timerUpdateEquippedLight == 0)
|
||||
updateEquippedLight(iter->first, updateEquippedLightInterval, showTorches);
|
||||
|
@ -1423,7 +1424,7 @@ namespace MWMechanics
|
|||
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
{
|
||||
const float animationDistance = aiProcessingDistance + 400; // Slightly larger than AI distance so there is time to switch back to the idle animation.
|
||||
const float distSqr = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2();
|
||||
const float distSqr = (playerPos - iter->first.getRefData().getPosition().asVec3()).length2();
|
||||
bool isPlayer = iter->first == player;
|
||||
bool inAnimationRange = isPlayer || (animationDistance == 0 || distSqr <= animationDistance*animationDistance);
|
||||
int activeFlag = 1; // Can be changed back to '2' to keep updating bounding boxes off screen (more accurate, but slower)
|
||||
|
@ -1437,22 +1438,24 @@ namespace MWMechanics
|
|||
inAnimationRange = true;
|
||||
active = std::max(1, active);
|
||||
}
|
||||
iter->second->getCharacterController()->setActive(active);
|
||||
|
||||
CharacterController* ctrl = iter->second->getCharacterController();
|
||||
ctrl->setActive(active);
|
||||
|
||||
if (!inAnimationRange)
|
||||
continue;
|
||||
|
||||
if (iter->first.getClass().getCreatureStats(iter->first).isParalyzed())
|
||||
iter->second->getCharacterController()->skipAnim();
|
||||
ctrl->skipAnim();
|
||||
|
||||
// Handle player last, in case a cell transition occurs by casting a teleportation spell
|
||||
// (would invalidate the iterator)
|
||||
if (iter->first == getPlayer())
|
||||
{
|
||||
playerCharacter = iter->second->getCharacterController();
|
||||
playerCharacter = ctrl;
|
||||
continue;
|
||||
}
|
||||
iter->second->getCharacterController()->update(duration);
|
||||
ctrl->update(duration);
|
||||
}
|
||||
|
||||
if (playerCharacter)
|
||||
|
@ -1512,7 +1515,7 @@ namespace MWMechanics
|
|||
continue;
|
||||
|
||||
// is the player in range and can they be detected
|
||||
if ((observer.getRefData().getPosition().asVec3() - player.getRefData().getPosition().asVec3()).length2() <= radius*radius
|
||||
if ((observer.getRefData().getPosition().asVec3() - playerPos).length2() <= radius*radius
|
||||
&& MWBase::Environment::get().getWorld()->getLOS(player, observer))
|
||||
{
|
||||
if (MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, observer))
|
||||
|
@ -1656,7 +1659,8 @@ namespace MWMechanics
|
|||
void Actors::rest(bool sleep)
|
||||
{
|
||||
float duration = 3600.f / MWBase::Environment::get().getWorld()->getTimeScaleFactor();
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
const osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
||||
|
||||
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
|
||||
{
|
||||
|
@ -1666,7 +1670,7 @@ namespace MWMechanics
|
|||
restoreDynamicStats(iter->first, sleep);
|
||||
|
||||
if ((!iter->first.getRefData().getBaseNode()) ||
|
||||
(player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2() > sqrAiProcessingDistance)
|
||||
(playerPos - iter->first.getRefData().getPosition().asVec3()).length2() > sqrAiProcessingDistance)
|
||||
continue;
|
||||
|
||||
adjustMagicEffects (iter->first);
|
||||
|
|
|
@ -28,8 +28,6 @@ namespace MWMechanics
|
|||
void addBoundItem (const std::string& itemId, const MWWorld::Ptr& actor);
|
||||
void removeBoundItem (const std::string& itemId, const MWWorld::Ptr& actor);
|
||||
|
||||
void updateNpc(const MWWorld::Ptr &ptr, float duration);
|
||||
|
||||
void adjustMagicEffects (const MWWorld::Ptr& creature);
|
||||
|
||||
void calculateDynamicStats (const MWWorld::Ptr& ptr);
|
||||
|
@ -39,7 +37,7 @@ namespace MWMechanics
|
|||
|
||||
void calculateRestoration (const MWWorld::Ptr& ptr, float duration);
|
||||
|
||||
void updateDrowning (const MWWorld::Ptr& ptr, float duration);
|
||||
void updateDrowning (const MWWorld::Ptr& ptr, float duration, bool isKnockedOut, bool isPlayer);
|
||||
|
||||
void updateEquippedLight (const MWWorld::Ptr& ptr, float duration, bool mayEquip);
|
||||
|
||||
|
|
Loading…
Reference in a new issue