Fix for bug #1080, can't read/repair/make potions/use soul gems/rest/sleep while in combat.

The radius for being in combat with the player is fAlarmDistance, which looked like the only pertinent thing.
actorid
Thomas 11 years ago
parent 5b681e2199
commit f3272c941f

@ -161,9 +161,14 @@ namespace MWBase
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0;
///return the list of actors which are following the given actor (ie AiFollow is active and the target is the actor)
///return the list of actors which are following the given actor
/**ie AiFollow is active and the target is the actor**/
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor) = 0;
///Returns a list of actors who are fighting the given actor within the fAlarmDistance
/** ie AiCombat is active and the target is the actor **/
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor) = 0;
virtual void playerLoaded() = 0;
};
}

@ -19,6 +19,7 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/statemanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
@ -693,8 +694,12 @@ namespace MWInput
if (!MWBase::Environment::get().getWindowManager()->getRestEnabled () || MWBase::Environment::get().getWindowManager()->isGuiMode ())
return;
/// \todo check if resting is currently allowed (enemies nearby?)
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest);
if(mPlayer->isInCombat()) {//Check if in combat
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}"); //Nope,
return;
}
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest); //Open rest GUI
}
void InputManager::screenshot()

@ -176,7 +176,7 @@ namespace MWMechanics
adjustMagicEffects (ptr);
if (ptr.getClass().getCreatureStats(ptr).needToRecalcDynamicStats())
calculateDynamicStats (ptr);
calculateCreatureStatModifiers (ptr, duration);
// AI
@ -764,7 +764,7 @@ namespace MWMechanics
creatureStats.setHostile(false);
creatureStats.setAttacked(false);
creatureStats.setAlarmed(false);
// Update witness crime id
npcStats.setCrimeId(-1);
}
@ -1038,4 +1038,26 @@ namespace MWMechanics
}
return list;
}
std::list<MWWorld::Ptr> Actors::getActorsFighting(const MWWorld::Ptr& actor) {
std::list<MWWorld::Ptr> list;
std::vector<MWWorld::Ptr> neighbors;
Ogre::Vector3 position = Ogre::Vector3(actor.getRefData().getPosition().pos);
getObjectsInRange(position,
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(),
neighbors); //only care about those within the alarm disance
for(std::vector<MWWorld::Ptr>::iterator iter(neighbors.begin());iter != neighbors.end();iter++)
{
const MWWorld::Class &cls = MWWorld::Class::get(*iter);
CreatureStats &stats = cls.getCreatureStats(*iter);
if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
{
MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage());
if(package->getTargetId() == actor.getCellRef().mRefID)
list.push_front(*iter);
}
}
return list;
}
}

@ -98,8 +98,13 @@ namespace MWMechanics
void getObjectsInRange(const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& out);
///Returns the list of actors which are following the given actor
/**ie AiFollow is active and the target is the actor **/
std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
///<return the list of actors which are following the given actor (ie AiFollow is active and the target is the actor)
///Returns the list of actors which are fighting the given actor
/**ie AiCombat is active and the target is the actor **/
std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);
private:
PtrControllerMap mActors;

@ -772,6 +772,11 @@ namespace MWMechanics
bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed)
{
if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) {
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage2}");
return true;
}
MWWorld::Ptr victim;
if (isAllowedToUse(ptr, bed, victim))
return false;
@ -832,17 +837,17 @@ namespace MWMechanics
// Find all the NPCs within the alarm radius
std::vector<MWWorld::Ptr> neighbors;
mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos),
mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos),
esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getInt(), neighbors);
// Find an actor who witnessed the crime
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
{
if (*it == ptr) continue; // not the player
// Was the crime seen?
if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) ||
type == OT_Assault )
type == OT_Assault )
{
// Will the witness report the crime?
@ -853,7 +858,7 @@ namespace MWMechanics
// Tell everyone, including yourself
for (std::vector<MWWorld::Ptr>::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1)
{
{
if (*it1 == ptr) continue; // not the player
// TODO: Add more messages
@ -861,9 +866,9 @@ namespace MWMechanics
MWBase::Environment::get().getDialogueManager()->say(*it1, "thief");
else if (type == OT_Assault)
MWBase::Environment::get().getDialogueManager()->say(*it1, "attack");
// Will other witnesses paticipate in crime
if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm
if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm
|| type == OT_Assault )
{
it1->getClass().getNpcStats(*it1).setCrimeId(id);
@ -884,7 +889,7 @@ namespace MWMechanics
void MechanicsManager::reportCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg)
{
const MWWorld::Store<ESM::GameSetting>& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
// Bounty for each type of crime
if (type == OT_Trespassing || type == OT_SleepingInOwnedBed)
arg = store.find("iCrimeTresspass")->getInt();
@ -993,4 +998,8 @@ namespace MWMechanics
{
return mActors.getActorsFollowing(actor);
}
std::list<MWWorld::Ptr> MechanicsManager::getActorsFighting(const MWWorld::Ptr& actor) {
return mActors.getActorsFighting(actor);
}
}

@ -120,7 +120,7 @@ namespace MWMechanics
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item);
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
/// @return was it illegal, and someone saw you doing it?
/// @return was it illegal, and someone saw you doing it? Also returns fail when enemies are nearby
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed);
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
@ -137,6 +137,8 @@ namespace MWMechanics
virtual std::list<MWWorld::Ptr> getActorsFollowing(const MWWorld::Ptr& actor);
virtual std::list<MWWorld::Ptr> getActorsFighting(const MWWorld::Ptr& actor);
virtual bool toggleAI();
virtual bool isAIActive();

@ -235,9 +235,12 @@ void MWState::StateManager::quickSave(std::string name) {
if (it->mProfile.mDescription == name)
slot = &*it;
}
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage4}"); //Saving...
MWBase::Environment::get().getStateManager()->saveGame(name, slot);
}
}
else
MWBase::Environment::get().getWindowManager()->messageBox("#{sSaveGameDenied}"); //You can not save your game right now
}
void MWState::StateManager::loadGame (const Character *character, const Slot *slot)
@ -351,6 +354,7 @@ void MWState::StateManager::quickLoad() {
if(mCurrentCharacter) { //Ensure a current character exists
const MWState::Slot* slot = &*mCurrentCharacter->begin(); //Get newest save
if(slot) //Don't even try loading it if there's no prior save.
//MWBase::Environment::get().getWindowManager()->messageBox("#{sLoadingMessage14}"); //it overlaps
MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); //load newest save. That was easy!
}
}

@ -2,11 +2,19 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
namespace MWWorld
{
void ActionAlchemy::executeImp (const Ptr& actor)
{
if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { //Ensure we're not in combat
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage3}");
return;
}
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Alchemy);
}
}

@ -3,6 +3,9 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/npcstats.hpp"
@ -19,8 +22,13 @@ namespace MWWorld
{
}
void ActionRead::executeImp (const MWWorld::Ptr& actor)
{
void ActionRead::executeImp (const MWWorld::Ptr& actor) {
if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { //Ensure we're not in combat
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage4}");
return;
}
LiveCellRef<ESM::Book> *ref = getTarget().get<ESM::Book>();
if (ref->mBase->mData.mIsScroll)

@ -2,6 +2,8 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
namespace MWWorld
{
@ -12,6 +14,11 @@ namespace MWWorld
void ActionRepair::executeImp (const Ptr& actor)
{
if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) {
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage2}");
return;
}
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Repair);
MWBase::Environment::get().getWindowManager()->startRepairItem(getTarget());
}

@ -2,20 +2,26 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
namespace MWWorld
{
ActionSoulgem::ActionSoulgem(const Ptr &object)
: Action(false, object)
{
ActionSoulgem::ActionSoulgem(const Ptr &object)
: Action(false, object)
{
}
}
void ActionSoulgem::executeImp(const Ptr &actor)
{
MWBase::Environment::get().getWindowManager()->showSoulgemDialog(getTarget());
}
void ActionSoulgem::executeImp(const Ptr &actor)
{
if(MWBase::Environment::get().getWorld()->getPlayer().isInCombat()) { //Ensure we're not in combat
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage5}");
return;
}
MWBase::Environment::get().getWindowManager()->showSoulgemDialog(getTarget());
}
}

@ -13,6 +13,7 @@
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwmechanics/movement.hpp"
#include "../mwmechanics/npcstats.hpp"
@ -166,6 +167,10 @@ namespace MWWorld
mTeleported = teleported;
}
bool Player::isInCombat() {
return MWBase::Environment::get().getMechanicsManager()->getActorsFighting(getPlayer()).size() != 0;
}
void Player::markPosition(CellStore *markedCell, ESM::Position markedPosition)
{
mMarkedCell = markedCell;

@ -44,7 +44,7 @@ namespace MWWorld
int mCurrentCrimeId; // the id assigned witnesses
int mPayedCrimeId; // the last id payed off (0 bounty)
public:
Player(const ESM::NPC *player, const MWBase::World& world);
@ -90,6 +90,9 @@ namespace MWWorld
bool wasTeleported() const;
void setTeleported(bool teleported);
///Checks all actors to see if anyone has an aipackage against you
bool isInCombat();
void clear();
void write (ESM::ESMWriter& writer) const;

Loading…
Cancel
Save