diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index a134e3dec..846f6d8dc 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -390,8 +390,11 @@ namespace MWMechanics bool canMoveByZ = (actorClass.canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor); + // for distant combat we should know if target is in LOS even if distToTarget < rangeAttack + bool inLOS = distantCombat ? world->getLOS(actor, target) : true; + // (within attack dist) || (not quite attack dist while following) - if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) ) + if(inLOS && (distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck))) { //Melee and Close-up combat @@ -450,7 +453,7 @@ namespace MWMechanics else // remote pathfinding { bool preferShortcut = false; - bool inLOS = world->getLOS(actor, target); + if (!distantCombat) inLOS = world->getLOS(actor, target); // check if shortcut is available if(inLOS && (!isStuck || mReadyToAttack) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 5737c380a..2dea28346 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -853,8 +853,15 @@ namespace MWMechanics // Find all the actors within the alarm radius std::vector neighbors; - mActors.getObjectsInRange(Ogre::Vector3(player.getRefData().getPosition().pos), - esmStore.get().find("fAlarmRadius")->getInt(), neighbors); + + Ogre::Vector3 from = Ogre::Vector3(player.getRefData().getPosition().pos); + int radius = esmStore.get().find("fAlarmRadius")->getInt(); + + mActors.getObjectsInRange(from, radius, neighbors); + + // victim should be considered even beyond alarm radius + if (from.squaredDistance(Ogre::Vector3(victim.getRefData().getPosition().pos)) > radius*radius) + neighbors.push_back(victim); int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId(); @@ -1024,8 +1031,27 @@ namespace MWMechanics { ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr); if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) + { ptr.getClass().getCreatureStats(ptr).setHostile(true); + // if guard starts combat with player, guards pursuing player should do the same + if (ptr.getClass().isClass(ptr, "Guard")) + { + for (Actors::PtrControllerMap::const_iterator iter = mActors.begin(); iter != mActors.end(); ++iter) + { + if (iter->first.getClass().isClass(iter->first, "Guard")) + { + MWMechanics::AiSequence& aiSeq = iter->first.getClass().getCreatureStats(iter->first).getAiSequence(); + if (aiSeq.getActivePackage()->getTypeId() == MWMechanics::AiPackage::TypeIdPursue) + { + aiSeq.stopPursuit(); + aiSeq.stack(MWMechanics::AiCombat(target), ptr); + } + } + } + } + } + // Must be done after the target is set up, so that CreatureTargetted dialogue filter works properly if (ptr.getClass().isNpc()) MWBase::Environment::get().getDialogueManager()->say(ptr, "attack");