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:
parent
510f2d10ac
commit
58b135a2be
12 changed files with 76 additions and 93 deletions
|
@ -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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue