From 266702e729b4351f60a458ad58c345abb68dc0c6 Mon Sep 17 00:00:00 2001 From: Aussiemon Date: Tue, 15 Apr 2025 00:42:22 -0600 Subject: [PATCH 1/6] Remove obsolete combat block for immobile creatures and autoformat --- apps/openmw/mwmechanics/actors.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 1e62cc4a21..01e5c21559 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -184,7 +184,7 @@ namespace MWWorld::ContainerStoreIterator gem = container.end(); float gemCapacity = std::numeric_limits::max(); for (auto it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous); it != container.end(); - ++it) + ++it) { if (it->getClass().isSoulGem(*it)) { @@ -605,10 +605,6 @@ namespace MWMechanics void Actors::engageCombat( const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, SidingCache& cachedAllies, bool againstPlayer) const { - // No combat for totally static creatures - if (!actor1.getClass().isMobile(actor1)) - return; - CreatureStats& creatureStats1 = actor1.getClass().getCreatureStats(actor1); if (creatureStats1.isDead() || creatureStats1.getAiSequence().isInCombat(actor2)) return; @@ -1153,8 +1149,7 @@ namespace MWMechanics if (playerStats.getBounty() >= cutoff * iCrimeThresholdMultiplier) { mechanicsManager->startCombat(ptr, player, &cachedAllies.getActorsSidingWith(player)); - creatureStats.setHitAttemptActorId( - playerClass.getCreatureStats(player) + creatureStats.setHitAttemptActorId(playerClass.getCreatureStats(player) .getActorId()); // Stops the guard from quitting combat if player is unreachable } else From a77a8904e599207a58a5ebabf550259713857800 Mon Sep 17 00:00:00 2001 From: Aussiemon Date: Tue, 15 Apr 2025 17:25:58 -0600 Subject: [PATCH 2/6] Immobile creatures should enter combat, but not act --- apps/openmw/mwmechanics/aicombat.cpp | 8 +++++--- apps/openmw/mwmechanics/aipackage.cpp | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 2399961a3a..a96270c2e3 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -104,10 +104,10 @@ namespace MWMechanics bool AiCombat::execute( const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) { - // get or create temporary storage + // Get or create temporary storage AiCombatStorage& storage = state.get(); - // General description + // No combat for dead creatures if (actor.getClass().getCreatureStats(actor).isDead()) return true; @@ -245,7 +245,9 @@ namespace MWMechanics float distToTarget = getDistanceToBounds(actor, target); - storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS); + // Must be attacking, within range, have line of sight, and not be immobile + storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS + && actor.getClass().isMobile(actor)); if (isRangedCombat) { diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 4bcfc7dedd..24792b5bbc 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -135,6 +135,10 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& MWWorld::MovementDirectionFlags supportedMovementDirections, float destTolerance, float endTolerance, PathType pathType) { + // No pathing for totally static creatures + if (!actor.getClass().isMobile(actor)) + return false; + const Misc::TimerStatus timerStatus = mReaction.update(duration); const osg::Vec3f position = actor.getRefData().getPosition().asVec3(); // position of the actor From 23dc226dff12e0576389d2735259cb61ce121ed7 Mon Sep 17 00:00:00 2001 From: Aussiemon Date: Tue, 15 Apr 2025 17:56:48 -0600 Subject: [PATCH 3/6] Revert autoformat changes --- apps/openmw/mwmechanics/actors.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 01e5c21559..a4c2f42f0f 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -184,7 +184,7 @@ namespace MWWorld::ContainerStoreIterator gem = container.end(); float gemCapacity = std::numeric_limits::max(); for (auto it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous); it != container.end(); - ++it) + ++it) { if (it->getClass().isSoulGem(*it)) { @@ -1149,7 +1149,8 @@ namespace MWMechanics if (playerStats.getBounty() >= cutoff * iCrimeThresholdMultiplier) { mechanicsManager->startCombat(ptr, player, &cachedAllies.getActorsSidingWith(player)); - creatureStats.setHitAttemptActorId(playerClass.getCreatureStats(player) + creatureStats.setHitAttemptActorId( + playerClass.getCreatureStats(player) .getActorId()); // Stops the guard from quitting combat if player is unreachable } else From 3df695df4a0f393a534736b558dc02cad983bcf7 Mon Sep 17 00:00:00 2001 From: Aussiemon Date: Tue, 15 Apr 2025 18:38:53 -0600 Subject: [PATCH 4/6] Found better place for early return --- apps/openmw/mwmechanics/aicombat.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index a96270c2e3..82fc9a67a1 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -231,6 +231,10 @@ namespace MWMechanics storage.stopFleeing(); } + // No attack actions for totally static creatures + if (!actor.getClass().isMobile(actor)) + return false; + bool isRangedCombat = false; float& rangeAttack = storage.mAttackRange; @@ -245,9 +249,7 @@ namespace MWMechanics float distToTarget = getDistanceToBounds(actor, target); - // Must be attacking, within range, have line of sight, and not be immobile - storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS - && actor.getClass().isMobile(actor)); + storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS); if (isRangedCombat) { From 09ed5bb234212484da5294ddfab723495edc62b4 Mon Sep 17 00:00:00 2001 From: Aussiemon Date: Tue, 15 Apr 2025 20:02:24 -0600 Subject: [PATCH 5/6] Allow immobile actors to initiate combat when attacked --- apps/openmw/mwclass/creature.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 324ba5f98b..b85bb9e996 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -360,16 +360,12 @@ namespace MWClass { stats.setAttacked(true); - // No retaliation for totally static creatures (they have no movement or attacks anyway) - if (isMobile(ptr)) - { - bool complain = sourceType == MWMechanics::DamageSourceType::Melee; - bool supportFriendlyFire = sourceType != MWMechanics::DamageSourceType::Ranged; - if (supportFriendlyFire && MWMechanics::friendlyHit(attacker, ptr, complain)) - setOnPcHitMe = false; - else - setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker); - } + bool complain = sourceType == MWMechanics::DamageSourceType::Melee; + bool supportFriendlyFire = sourceType != MWMechanics::DamageSourceType::Ranged; + if (supportFriendlyFire && MWMechanics::friendlyHit(attacker, ptr, complain)) + setOnPcHitMe = false; + else + setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker); } // Attacker and target store each other as hitattemptactor if they have no one stored yet From 2db36c49b5d6cd6dd129637e3fb5c06ca2b6f438 Mon Sep 17 00:00:00 2001 From: Aussiemon Date: Sun, 6 Jul 2025 11:41:02 -0600 Subject: [PATCH 6/6] Move early out to better place --- apps/openmw/mwmechanics/aicombat.cpp | 11 +++++++---- apps/openmw/mwmechanics/aipackage.cpp | 4 ---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 82fc9a67a1..1b0b0e5a89 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -124,6 +124,13 @@ namespace MWMechanics if (actor == target) // This should never happen. return true; + // No actions for totally static creatures + if (!actor.getClass().isMobile(actor)) + { + storage.mFleeState = AiCombatStorage::FleeState_Idle; + return false; + } + if (!storage.isFleeing()) { if (storage.mCurrentAction.get()) // need to wait to init action with its attack range @@ -231,10 +238,6 @@ namespace MWMechanics storage.stopFleeing(); } - // No attack actions for totally static creatures - if (!actor.getClass().isMobile(actor)) - return false; - bool isRangedCombat = false; float& rangeAttack = storage.mAttackRange; diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 24792b5bbc..4bcfc7dedd 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -135,10 +135,6 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& MWWorld::MovementDirectionFlags supportedMovementDirections, float destTolerance, float endTolerance, PathType pathType) { - // No pathing for totally static creatures - if (!actor.getClass().isMobile(actor)) - return false; - const Misc::TimerStatus timerStatus = mReaction.update(duration); const osg::Vec3f position = actor.getRefData().getPosition().asVec3(); // position of the actor