2013-05-19 16:40:37 +00:00
|
|
|
#include "security.hpp"
|
|
|
|
|
2017-04-24 16:46:12 +00:00
|
|
|
/*
|
|
|
|
Start of tes3mp addition
|
|
|
|
|
|
|
|
Include additional headers for multiplayer purposes
|
|
|
|
*/
|
2016-10-24 08:43:27 +00:00
|
|
|
#include "../mwmp/Main.hpp"
|
2016-12-16 08:59:15 +00:00
|
|
|
#include "../mwmp/Networking.hpp"
|
2018-05-12 21:42:24 +00:00
|
|
|
#include "../mwmp/ObjectList.hpp"
|
2017-04-24 16:46:12 +00:00
|
|
|
/*
|
|
|
|
End of tes3mp addition
|
|
|
|
*/
|
2016-10-24 08:43:27 +00:00
|
|
|
|
|
|
|
#include "../mwworld/cellstore.hpp"
|
|
|
|
|
2015-04-22 15:58:55 +00:00
|
|
|
#include <components/misc/rng.hpp>
|
2015-03-15 01:07:47 +00:00
|
|
|
|
2013-05-19 16:40:37 +00:00
|
|
|
#include "../mwworld/class.hpp"
|
2013-08-12 23:19:33 +00:00
|
|
|
#include "../mwworld/containerstore.hpp"
|
2014-02-23 19:11:05 +00:00
|
|
|
#include "../mwworld/esmstore.hpp"
|
2013-05-19 16:40:37 +00:00
|
|
|
|
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwbase/environment.hpp"
|
2014-01-10 20:26:24 +00:00
|
|
|
#include "../mwbase/mechanicsmanager.hpp"
|
2013-05-19 16:40:37 +00:00
|
|
|
|
|
|
|
#include "creaturestats.hpp"
|
|
|
|
|
|
|
|
namespace MWMechanics
|
|
|
|
{
|
|
|
|
|
2013-05-19 21:19:48 +00:00
|
|
|
Security::Security(const MWWorld::Ptr &actor)
|
2013-05-20 10:42:11 +00:00
|
|
|
: mActor(actor)
|
2013-05-19 21:19:48 +00:00
|
|
|
{
|
2014-05-22 18:37:22 +00:00
|
|
|
CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor);
|
2018-12-23 11:18:33 +00:00
|
|
|
mAgility = creatureStats.getAttribute(ESM::Attribute::Agility).getModified();
|
|
|
|
mLuck = creatureStats.getAttribute(ESM::Attribute::Luck).getModified();
|
2018-10-08 14:06:30 +00:00
|
|
|
mSecuritySkill = static_cast<float>(actor.getClass().getSkill(actor, ESM::Skill::Security));
|
2013-05-19 21:19:48 +00:00
|
|
|
mFatigueTerm = creatureStats.getFatigueTerm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick,
|
2013-05-19 17:48:51 +00:00
|
|
|
std::string& resultMessage, std::string& resultSound)
|
2013-05-19 16:40:37 +00:00
|
|
|
{
|
2018-06-19 10:17:33 +00:00
|
|
|
if (lock.getCellRef().getLockLevel() <= 0 ||
|
|
|
|
lock.getCellRef().getLockLevel() == ESM::UnbreakableLock ||
|
2019-09-10 19:53:26 +00:00
|
|
|
!lock.getClass().hasToolTip(lock)) //If it's unlocked or can not be unlocked back out immediately
|
2013-05-19 16:40:37 +00:00
|
|
|
return;
|
|
|
|
|
2020-09-21 20:05:26 +00:00
|
|
|
int uses = lockpick.getClass().getItemHealth(lockpick);
|
|
|
|
if (uses == 0)
|
|
|
|
return;
|
|
|
|
|
2014-05-25 12:13:07 +00:00
|
|
|
int lockStrength = lock.getCellRef().getLockLevel();
|
2013-05-19 16:40:37 +00:00
|
|
|
|
|
|
|
float pickQuality = lockpick.get<ESM::Lockpick>()->mBase->mData.mQuality;
|
|
|
|
|
2018-08-29 15:38:12 +00:00
|
|
|
float fPickLockMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPickLockMult")->mValue.getFloat();
|
2013-05-19 16:40:37 +00:00
|
|
|
|
2015-03-08 04:42:07 +00:00
|
|
|
float x = 0.2f * mAgility + 0.1f * mLuck + mSecuritySkill;
|
2013-05-19 21:19:48 +00:00
|
|
|
x *= pickQuality * mFatigueTerm;
|
2013-05-19 16:40:37 +00:00
|
|
|
x += fPickLockMult * lockStrength;
|
|
|
|
|
2020-04-11 22:55:42 +00:00
|
|
|
MWBase::Environment::get().getMechanicsManager()->unlockAttempted(mActor, lock);
|
|
|
|
|
2013-05-19 17:48:51 +00:00
|
|
|
resultSound = "Open Lock Fail";
|
2013-05-19 16:40:37 +00:00
|
|
|
if (x <= 0)
|
2013-05-19 17:48:51 +00:00
|
|
|
resultMessage = "#{sLockImpossible}";
|
2013-05-19 16:40:37 +00:00
|
|
|
else
|
|
|
|
{
|
2015-04-22 15:58:55 +00:00
|
|
|
if (Misc::Rng::roll0to99() <= x)
|
2013-05-19 16:40:37 +00:00
|
|
|
{
|
2018-07-07 21:06:01 +00:00
|
|
|
/*
|
|
|
|
Start of tes3mp change (major)
|
|
|
|
|
|
|
|
Disable unilateral locking on this client and expect the server's reply to our
|
|
|
|
packet to do it instead
|
|
|
|
*/
|
2019-09-18 20:46:08 +00:00
|
|
|
//lock.getCellRef().unlock();
|
2018-07-07 21:06:01 +00:00
|
|
|
/*
|
|
|
|
End of tes3mp change (major)
|
|
|
|
*/
|
2017-05-24 13:25:44 +00:00
|
|
|
|
2017-02-26 14:59:53 +00:00
|
|
|
/*
|
|
|
|
Start of tes3mp addition
|
|
|
|
|
2017-05-24 13:25:44 +00:00
|
|
|
Send an ID_OBJECT_LOCK packet every time an object is unlocked here
|
2017-02-26 14:59:53 +00:00
|
|
|
*/
|
2018-05-12 21:42:24 +00:00
|
|
|
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
|
|
|
objectList->reset();
|
2018-07-22 22:39:43 +00:00
|
|
|
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
|
2018-05-12 21:42:24 +00:00
|
|
|
objectList->addObjectLock(lock, 0);
|
|
|
|
objectList->sendObjectLock();
|
2017-02-26 14:59:53 +00:00
|
|
|
/*
|
|
|
|
End of tes3mp addition
|
|
|
|
*/
|
2016-10-24 08:43:27 +00:00
|
|
|
|
2013-05-19 17:48:51 +00:00
|
|
|
resultMessage = "#{sLockSuccess}";
|
|
|
|
resultSound = "Open Lock";
|
2014-05-22 18:37:22 +00:00
|
|
|
mActor.getClass().skillUsageSucceeded(mActor, ESM::Skill::Security, 1);
|
2013-05-19 16:40:37 +00:00
|
|
|
}
|
2013-05-19 17:48:51 +00:00
|
|
|
else
|
|
|
|
resultMessage = "#{sLockFail}";
|
2013-05-19 16:40:37 +00:00
|
|
|
}
|
|
|
|
|
2020-10-09 16:20:50 +00:00
|
|
|
lockpick.getCellRef().setCharge(--uses);
|
2014-05-25 12:13:07 +00:00
|
|
|
if (!uses)
|
2013-08-12 23:19:33 +00:00
|
|
|
lockpick.getContainerStore()->remove(lockpick, 1, mActor);
|
2013-05-19 16:40:37 +00:00
|
|
|
}
|
|
|
|
|
2013-05-19 21:19:48 +00:00
|
|
|
void Security::probeTrap(const MWWorld::Ptr &trap, const MWWorld::Ptr &probe,
|
2013-05-19 17:48:51 +00:00
|
|
|
std::string& resultMessage, std::string& resultSound)
|
2013-05-19 16:40:37 +00:00
|
|
|
{
|
2020-09-21 20:05:26 +00:00
|
|
|
if (trap.getCellRef().getTrap().empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
int uses = probe.getClass().getItemHealth(probe);
|
|
|
|
if (uses == 0)
|
2013-05-19 16:40:37 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
float probeQuality = probe.get<ESM::Probe>()->mBase->mData.mQuality;
|
|
|
|
|
2014-05-25 12:13:07 +00:00
|
|
|
const ESM::Spell* trapSpell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(trap.getCellRef().getTrap());
|
2015-03-08 04:42:07 +00:00
|
|
|
int trapSpellPoints = trapSpell->mData.mCost;
|
2013-05-19 16:40:37 +00:00
|
|
|
|
2018-08-29 15:38:12 +00:00
|
|
|
float fTrapCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTrapCostMult")->mValue.getFloat();
|
2013-05-19 16:40:37 +00:00
|
|
|
|
2015-03-08 04:42:07 +00:00
|
|
|
float x = 0.2f * mAgility + 0.1f * mLuck + mSecuritySkill;
|
2013-05-19 16:40:37 +00:00
|
|
|
x += fTrapCostMult * trapSpellPoints;
|
2013-05-19 21:19:48 +00:00
|
|
|
x *= probeQuality * mFatigueTerm;
|
2013-05-19 16:40:37 +00:00
|
|
|
|
2020-04-11 22:55:42 +00:00
|
|
|
MWBase::Environment::get().getMechanicsManager()->unlockAttempted(mActor, trap);
|
|
|
|
|
2013-05-19 17:48:51 +00:00
|
|
|
resultSound = "Disarm Trap Fail";
|
2013-05-19 16:40:37 +00:00
|
|
|
if (x <= 0)
|
2013-05-19 17:48:51 +00:00
|
|
|
resultMessage = "#{sTrapImpossible}";
|
2013-05-19 16:40:37 +00:00
|
|
|
else
|
|
|
|
{
|
2015-04-22 15:58:55 +00:00
|
|
|
if (Misc::Rng::roll0to99() <= x)
|
2013-05-19 16:40:37 +00:00
|
|
|
{
|
2018-07-07 23:38:10 +00:00
|
|
|
/*
|
|
|
|
Start of tes3mp change (major)
|
|
|
|
|
|
|
|
Disable unilateral trap disarming on this client and expect the server's reply to our
|
|
|
|
packet to do it instead
|
|
|
|
*/
|
|
|
|
//trap.getCellRef().setTrap("");
|
|
|
|
/*
|
|
|
|
End of tes3mp change (major)
|
|
|
|
*/
|
2013-05-19 17:48:51 +00:00
|
|
|
|
|
|
|
resultSound = "Disarm Trap";
|
|
|
|
resultMessage = "#{sTrapSuccess}";
|
2014-05-22 18:37:22 +00:00
|
|
|
mActor.getClass().skillUsageSucceeded(mActor, ESM::Skill::Security, 0);
|
2017-05-25 22:47:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Start of tes3mp addition
|
|
|
|
|
|
|
|
Send an ID_OBJECT_TRAP packet every time a trap is disarmed
|
|
|
|
*/
|
2018-05-12 21:42:24 +00:00
|
|
|
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
|
|
|
objectList->reset();
|
2018-07-22 22:39:43 +00:00
|
|
|
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
|
2018-05-12 21:42:24 +00:00
|
|
|
objectList->addObjectTrap(trap, trap.getRefData().getPosition(), true);
|
|
|
|
objectList->sendObjectTrap();
|
2017-05-25 22:47:59 +00:00
|
|
|
/*
|
|
|
|
End of tes3mp addition
|
|
|
|
*/
|
2013-05-19 16:40:37 +00:00
|
|
|
}
|
2013-05-19 17:48:51 +00:00
|
|
|
else
|
|
|
|
resultMessage = "#{sTrapFail}";
|
2013-05-19 16:40:37 +00:00
|
|
|
}
|
|
|
|
|
2020-10-09 16:20:50 +00:00
|
|
|
probe.getCellRef().setCharge(--uses);
|
2014-05-25 12:13:07 +00:00
|
|
|
if (!uses)
|
2013-08-12 23:19:33 +00:00
|
|
|
probe.getContainerStore()->remove(probe, 1, mActor);
|
2013-05-19 16:40:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|