1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-03 16:49:54 +00:00

Crime is now checked every frame call

This commit is contained in:
Jeffrey Haines 2014-04-03 00:50:09 -04:00
parent 510f2d10ac
commit 58b135a2be
12 changed files with 76 additions and 93 deletions

View file

@ -513,8 +513,6 @@ namespace MWBase
virtual void explodeSpell (const Ogre::Vector3& origin, const MWWorld::Ptr& object, const ESM::EffectList& effects, virtual void explodeSpell (const Ogre::Vector3& origin, const MWWorld::Ptr& object, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName) = 0; const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName) = 0;
virtual void resetCrimes(const MWWorld::Ptr& ptr) = 0;
}; };
} }

View file

@ -29,6 +29,9 @@
#include "aicombat.hpp" #include "aicombat.hpp"
#include "aifollow.hpp" #include "aifollow.hpp"
#include "aipersue.hpp"
#include "../mwbase/dialoguemanager.hpp" //------------------------
namespace namespace
{ {
@ -175,14 +178,16 @@ namespace MWMechanics
adjustMagicEffects (ptr); adjustMagicEffects (ptr);
if (ptr.getClass().getCreatureStats(ptr).needToRecalcDynamicStats()) if (ptr.getClass().getCreatureStats(ptr).needToRecalcDynamicStats())
calculateDynamicStats (ptr); calculateDynamicStats (ptr);
calculateCreatureStatModifiers (ptr, duration); calculateCreatureStatModifiers (ptr, duration);
// AI // AI
if(MWBase::Environment::get().getMechanicsManager()->isAIActive()) if(MWBase::Environment::get().getMechanicsManager()->isAIActive())
{ {
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
//engage combat or not?
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
//engage combat or not?
if(ptr != player && !creatureStats.isHostile()) if(ptr != player && !creatureStats.isHostile())
{ {
ESM::Position playerpos = player.getRefData().getPosition(); ESM::Position playerpos = player.getRefData().getPosition();
@ -214,7 +219,7 @@ namespace MWMechanics
creatureStats.setHostile(true); creatureStats.setHostile(true);
} }
} }
updateCrimePersuit(ptr, duration);
creatureStats.getAiSequence().execute (ptr,duration); creatureStats.getAiSequence().execute (ptr,duration);
} }
@ -711,6 +716,48 @@ namespace MWMechanics
} }
} }
void Actors::updateCrimePersuit(const MWWorld::Ptr& ptr, float duration)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int bounty = player.getClass().getNpcStats(player).getBounty();
// TODO: Move me! I shouldn't be here...
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt()) *
float(esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->getInt()) *
esmStore.get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->getFloat();
if (ptr != player)
{
CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
// Alarmed or not, I will kill you because you've commited heinous against the empire
if ((!creatureStats.isAlarmed() || creatureStats.isAlarmed()) &&
ptr.getClass().isClass(ptr, "Guard") && bounty >= cutoff && !creatureStats.isHostile())
creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)));
else if (creatureStats.isAlarmed())
{
MWBase::Environment::get().getDialogueManager()->say(ptr, "Thief");
if(bounty == 0)
{
creatureStats.setAlarmed(false);
creatureStats.setHostile(false);
if (ptr.getClass().isClass(ptr, "Guard"))
creatureStats.getAiSequence().stopPersue();
creatureStats.getAiSequence().stopCombat();
}
if (ptr.getClass().isClass(ptr, "Guard") && !creatureStats.isHostile())
creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)));
else if (!creatureStats.isHostile())
{
creatureStats.getAiSequence().stack(AiCombat(player));
creatureStats.setHostile(true);
}
}
}
}
Actors::Actors() {} Actors::Actors() {}
Actors::~Actors() Actors::~Actors()

View file

@ -42,6 +42,8 @@ namespace MWMechanics
void updateEquippedLight (const MWWorld::Ptr& ptr, float duration); void updateEquippedLight (const MWWorld::Ptr& ptr, float duration);
void updateCrimePersuit (const MWWorld::Ptr& ptr, float duration);
public: public:
Actors(); Actors();

View file

@ -19,10 +19,8 @@ MWMechanics::AiPersue *MWMechanics::AiPersue::clone() const
{ {
return new AiPersue(*this); return new AiPersue(*this);
} }
bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor,float duration) bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration)
{ {
//TODO: Guards should not dialague with player after crime reset
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
Movement &movement = actor.getClass().getMovementSettings(actor); Movement &movement = actor.getClass().getMovementSettings(actor);

View file

@ -14,7 +14,7 @@ namespace MWMechanics
CreatureStats::CreatureStats() CreatureStats::CreatureStats()
: mLevel (0), mDead (false), mDied (false), mFriendlyHits (0), : mLevel (0), mDead (false), mDied (false), mFriendlyHits (0),
mTalkedTo (false), mAlarmed (false), mTalkedTo (false), mAlarmed (false),
mAttacked (false), mHostile (false), mAttacked (false), mHostile (false), mAssaulted(false),
mAttackingOrSpell(false), mAttackingOrSpell(false),
mIsWerewolf(false), mIsWerewolf(false),
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mHitRecovery(false), mBlock(false), mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mHitRecovery(false), mBlock(false),
@ -316,6 +316,16 @@ namespace MWMechanics
mHostile = hostile; mHostile = hostile;
} }
bool CreatureStats::isAssaulted() const
{
return mAssaulted;
}
void CreatureStats::setAssaulted (bool assaulted)
{
mAssaulted = assaulted;
}
bool CreatureStats::getCreatureTargetted() const bool CreatureStats::getCreatureTargetted() const
{ {
std::string target; std::string target;

View file

@ -39,6 +39,7 @@ namespace MWMechanics
bool mAlarmed; bool mAlarmed;
bool mAttacked; bool mAttacked;
bool mHostile; bool mHostile;
bool mAssaulted;
bool mAttackingOrSpell; bool mAttackingOrSpell;
bool mKnockdown; bool mKnockdown;
bool mHitRecovery; bool mHitRecovery;
@ -186,6 +187,10 @@ namespace MWMechanics
void setHostile (bool hostile); void setHostile (bool hostile);
bool isAssaulted() const;
void setAssaulted (bool assaulted);
bool getCreatureTargetted() const; bool getCreatureTargetted() const;
float getEvasion() const; float getEvasion() const;

View file

@ -1,5 +1,6 @@
#include "mechanicsmanagerimp.hpp" #include "mechanicsmanagerimp.hpp"
#include "npcstats.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
@ -12,10 +13,6 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "aicombat.hpp"
#include "aipersue.hpp"
#include "aiactivate.hpp"
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include "spellcasting.hpp" #include "spellcasting.hpp"
@ -827,11 +824,6 @@ namespace MWMechanics
else if (type == OT_Theft) else if (type == OT_Theft)
alarm = esmStore.get<ESM::GameSetting>().find("iAlarmStealing")->getInt(); alarm = esmStore.get<ESM::GameSetting>().find("iAlarmStealing")->getInt();
// what is the bounty cutoff? To high the guards will attack
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt()) *
float(esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->getInt()) *
esmStore.get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->getFloat();
// Innocent until proven guilty // Innocent until proven guilty
bool reported = false; bool reported = false;
@ -846,8 +838,9 @@ namespace MWMechanics
CreatureStats& creatureStats = MWWorld::Class::get(*it).getCreatureStats(*it); CreatureStats& creatureStats = MWWorld::Class::get(*it).getCreatureStats(*it);
// Did a witness see the crime? // Was the crime seen or the victim assulted?
if ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) ||
type == OT_Assault)
{ {
// Say something! // Say something!
// TODO: Add more messages // TODO: Add more messages
@ -858,7 +851,6 @@ namespace MWMechanics
if (creatureStats.getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm) if (creatureStats.getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm)
{ {
reported = true; reported = true;
reportCrime(ptr, victim, type, arg);
// Tell everyone else // Tell everyone else
for (std::vector<MWWorld::Ptr>::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) for (std::vector<MWWorld::Ptr>::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1)
@ -870,38 +862,13 @@ namespace MWMechanics
CreatureStats& creatureStats1 = MWWorld::Class::get(*it1).getCreatureStats(*it1); CreatureStats& creatureStats1 = MWWorld::Class::get(*it1).getCreatureStats(*it1);
if (creatureStats1.getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm) if (creatureStats1.getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm)
creatureStats1.setAlarmed(true); creatureStats1.setAlarmed(true);
// was the witness a guard?
if (it1->getClass().isClass(*it1, "Guard"))
{
// will the guard try to kill the player?
if (ptr.getClass().getNpcStats(ptr).getBounty() >= cutoff)
{
creatureStats1.getAiSequence().stack(AiCombat(ptr));
creatureStats1.setHostile(true);
creatureStats1.getAiSequence().execute(*it1,0);
}
else // will the guard persue the player?
{
creatureStats1.getAiSequence().stack(AiPersue(ptr.getClass().getId(ptr)));
creatureStats1.getAiSequence().execute(*it1,0);
}
}
// will the witness fight the player?
else if (creatureStats1.getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm ||
type == OT_Assault)
{
creatureStats1.getAiSequence().stack(AiCombat(ptr));
creatureStats1.setHostile(true);
creatureStats1.getAiSequence().execute(*it1,0);
}
} }
break; // Someone saw the crime and everyone has been told break; // Someone saw the crime and everyone has been told
} }
} }
} }
if (reported) if(reported)
MWBase::Environment::get().getWorld()->getPlayer().addPlayerWitnesses(neighbors); reportCrime(ptr, victim, type, arg);
return reported; return reported;
} }

View file

@ -810,11 +810,8 @@ namespace MWScript
public: public:
virtual void execute(Interpreter::Runtime &runtime) virtual void execute(Interpreter::Runtime &runtime)
{ {
MWBase::World* world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
player.getClass().getNpcStats(player).setBounty(0); player.getClass().getNpcStats(player).setBounty(0);
world->confiscateStolenItems(player);
world->resetCrimes(player);
} }
}; };
@ -823,10 +820,8 @@ namespace MWScript
public: public:
virtual void execute(Interpreter::Runtime &runtime) virtual void execute(Interpreter::Runtime &runtime)
{ {
MWBase::World* world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
player.getClass().getNpcStats(player).setBounty(0); player.getClass().getNpcStats(player).setBounty(0);
world->resetCrimes(player);
} }
}; };

View file

@ -274,17 +274,4 @@ namespace MWWorld
return false; return false;
} }
void Player::addPlayerWitnesses(std::vector<MWWorld::Ptr> witnesses)
{
mWitnesses.insert(mWitnesses.end(), witnesses.begin(), witnesses.end());
}
std::vector<MWWorld::Ptr> Player::getPlayerWitnesses() const
{
return mWitnesses;
}
void Player::resetPlayerWitnesses()
{
mWitnesses.clear();
}
} }

View file

@ -96,10 +96,6 @@ namespace MWWorld
void write (ESM::ESMWriter& writer) const; void write (ESM::ESMWriter& writer) const;
bool readRecord (ESM::ESMReader& reader, int32_t type); bool readRecord (ESM::ESMReader& reader, int32_t type);
void addPlayerWitnesses(std::vector<MWWorld::Ptr> witnesses);
std::vector<MWWorld::Ptr> getPlayerWitnesses() const;
void resetPlayerWitnesses();
}; };
} }
#endif #endif

View file

@ -2765,33 +2765,12 @@ namespace MWWorld
// TODO: Sleep the player // TODO: Sleep the player
resetCrimes(player);
std::vector<std::string> buttons; std::vector<std::string> buttons;
buttons.push_back("#{sOk}"); buttons.push_back("#{sOk}");
MWBase::Environment::get().getWindowManager()->messageBox(message, buttons); MWBase::Environment::get().getWindowManager()->messageBox(message, buttons);
} }
} }
void World::resetCrimes(const MWWorld::Ptr& ptr)
{
// Reset witnesses to the players crimes
std::vector<MWWorld::Ptr> neighbors = mPlayer->getPlayerWitnesses();
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
// Reset states
// TODO: More research is needed to complete this list
it->getClass().getCreatureStats(*it).setHostile(false);
it->getClass().getCreatureStats(*it).setAlarmed(false);
// Stop guard persue
if(it->getClass().isClass(*it, "Guard"))
it->getClass().getCreatureStats(*it).getAiSequence().stopPersue();
}
mPlayer->resetPlayerWitnesses();
}
void World::spawnRandomCreature(const std::string &creatureList) void World::spawnRandomCreature(const std::string &creatureList)
{ {
const ESM::CreatureLevList* list = getStore().get<ESM::CreatureLevList>().find(creatureList); const ESM::CreatureLevList* list = getStore().get<ESM::CreatureLevList>().find(creatureList);

View file

@ -611,7 +611,6 @@ namespace MWWorld
virtual void explodeSpell (const Ogre::Vector3& origin, const MWWorld::Ptr& object, const ESM::EffectList& effects, virtual void explodeSpell (const Ogre::Vector3& origin, const MWWorld::Ptr& object, const ESM::EffectList& effects,
const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName); const MWWorld::Ptr& caster, const std::string& id, const std::string& sourceName);
virtual void resetCrimes(const MWWorld::Ptr& ptr);
}; };
} }