forked from mirror/openmw-tes3mp
Security skill
This commit is contained in:
parent
c7805e7dd2
commit
7a2d1cd8ce
12 changed files with 205 additions and 8 deletions
|
@ -67,7 +67,7 @@ add_openmw_dir (mwclass
|
||||||
add_openmw_dir (mwmechanics
|
add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||||
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
||||||
aiescort aiactivate repair enchanting pathfinding
|
aiescort aiactivate repair enchanting pathfinding security
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwbase
|
add_openmw_dir (mwbase
|
||||||
|
|
|
@ -233,6 +233,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
// transfer everything into the player's inventory
|
// transfer everything into the player's inventory
|
||||||
ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel();
|
ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel();
|
||||||
|
mModel->update();
|
||||||
for (size_t i=0; i<mModel->getItemCount(); ++i)
|
for (size_t i=0; i<mModel->getItemCount(); ++i)
|
||||||
{
|
{
|
||||||
if (i==0)
|
if (i==0)
|
||||||
|
@ -257,7 +258,6 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
onTakeAllButtonClicked(mTakeButton);
|
onTakeAllButtonClicked(mTakeButton);
|
||||||
|
|
||||||
/// \todo if corpse is non-disposable: messagebox #{sDisposeCorpseFail}
|
|
||||||
if (MWWorld::Class::get(mPtr).isPersistent(mPtr))
|
if (MWWorld::Class::get(mPtr).isPersistent(mPtr))
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}");
|
||||||
else
|
else
|
||||||
|
|
|
@ -241,6 +241,10 @@ namespace MWInput
|
||||||
case A_ToggleHUD:
|
case A_ToggleHUD:
|
||||||
mWindows.toggleHud();
|
mWindows.toggleHud();
|
||||||
break;
|
break;
|
||||||
|
case A_Use:
|
||||||
|
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
mPlayer.use();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -803,6 +807,7 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
std::map<int, std::string> descriptions;
|
std::map<int, std::string> descriptions;
|
||||||
|
|
||||||
|
descriptions[A_Use] = "sUse";
|
||||||
descriptions[A_Activate] = "sActivate";
|
descriptions[A_Activate] = "sActivate";
|
||||||
descriptions[A_MoveBackward] = "sBack";
|
descriptions[A_MoveBackward] = "sBack";
|
||||||
descriptions[A_MoveForward] = "sForward";
|
descriptions[A_MoveForward] = "sForward";
|
||||||
|
@ -865,6 +870,7 @@ namespace MWInput
|
||||||
ret.push_back(A_AlwaysRun);
|
ret.push_back(A_AlwaysRun);
|
||||||
ret.push_back(A_Sneak);
|
ret.push_back(A_Sneak);
|
||||||
ret.push_back(A_Activate);
|
ret.push_back(A_Activate);
|
||||||
|
ret.push_back(A_Use);
|
||||||
ret.push_back(A_ToggleWeapon);
|
ret.push_back(A_ToggleWeapon);
|
||||||
ret.push_back(A_ToggleSpell);
|
ret.push_back(A_ToggleSpell);
|
||||||
ret.push_back(A_AutoMove);
|
ret.push_back(A_AutoMove);
|
||||||
|
|
118
apps/openmw/mwmechanics/security.cpp
Normal file
118
apps/openmw/mwmechanics/security.cpp
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#include "security.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
#include "npcstats.hpp"
|
||||||
|
#include "creaturestats.hpp"
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
|
||||||
|
void Security::pickLock(const MWWorld::Ptr &actor, const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick)
|
||||||
|
{
|
||||||
|
if (lock.getCellRef().mLockLevel <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int lockStrength = lock.getCellRef().mLockLevel;
|
||||||
|
|
||||||
|
float pickQuality = lockpick.get<ESM::Lockpick>()->mBase->mData.mQuality;
|
||||||
|
|
||||||
|
CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor);
|
||||||
|
NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats(actor);
|
||||||
|
float pcAgility = creatureStats.getAttribute(ESM::Attribute::Agility).getModified();
|
||||||
|
float pcLuck = creatureStats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||||
|
float securitySkill = npcStats.getSkill(ESM::Skill::Security).getModified();
|
||||||
|
float fatigueTerm = creatureStats.getFatigueTerm();
|
||||||
|
|
||||||
|
float fPickLockMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPickLockMult")->getFloat();
|
||||||
|
|
||||||
|
float x = 0.2 * pcAgility + 0.1 * pcLuck + securitySkill;
|
||||||
|
x *= pickQuality * fatigueTerm;
|
||||||
|
x += fPickLockMult * lockStrength;
|
||||||
|
|
||||||
|
bool isPlayer = actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
|
|
||||||
|
if (x <= 0)
|
||||||
|
{
|
||||||
|
if (isPlayer)
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sLockImpossible}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
|
||||||
|
if (roll <= x)
|
||||||
|
{
|
||||||
|
MWWorld::Class::get(lock).unlock(lock);
|
||||||
|
if (isPlayer)
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sLockSuccess}");
|
||||||
|
MWWorld::Class::get(actor).skillUsageSucceeded(actor, ESM::Skill::Security, 1);
|
||||||
|
}
|
||||||
|
else if (isPlayer)
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sLockFail}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockpick.getCellRef().mCharge == -1)
|
||||||
|
lockpick.getCellRef().mCharge = lockpick.get<ESM::Lockpick>()->mBase->mData.mUses;
|
||||||
|
--lockpick.getCellRef().mCharge;
|
||||||
|
if (!lockpick.getCellRef().mCharge)
|
||||||
|
lockpick.getRefData().setCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Security::probeTrap(const MWWorld::Ptr &actor, const MWWorld::Ptr &trap, const MWWorld::Ptr &probe)
|
||||||
|
{
|
||||||
|
if (trap.getCellRef().mTrap == "")
|
||||||
|
return;
|
||||||
|
|
||||||
|
CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor);
|
||||||
|
NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats(actor);
|
||||||
|
|
||||||
|
float probeQuality = probe.get<ESM::Probe>()->mBase->mData.mQuality;
|
||||||
|
|
||||||
|
const ESM::Spell* trapSpell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(trap.getCellRef().mTrap);
|
||||||
|
float trapSpellPoints = trapSpell->mData.mCost;
|
||||||
|
|
||||||
|
float pcAgility = creatureStats.getAttribute(ESM::Attribute::Agility).getModified();
|
||||||
|
float pcLuck = creatureStats.getAttribute(ESM::Attribute::Luck).getModified();
|
||||||
|
float securitySkill = npcStats.getSkill(ESM::Skill::Security).getModified();
|
||||||
|
float fatigueTerm = creatureStats.getFatigueTerm();
|
||||||
|
|
||||||
|
float fTrapCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTrapCostMult")->getFloat();
|
||||||
|
|
||||||
|
float x = 0.2 * pcAgility + 0.1 * pcLuck + securitySkill;
|
||||||
|
x += fTrapCostMult * trapSpellPoints;
|
||||||
|
x *= probeQuality * fatigueTerm;
|
||||||
|
|
||||||
|
bool isPlayer = actor == MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
|
|
||||||
|
if (x <= 0)
|
||||||
|
{
|
||||||
|
if (isPlayer)
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sTrapImpossible}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
|
||||||
|
if (roll <= x)
|
||||||
|
{
|
||||||
|
trap.getCellRef().mTrap = "";
|
||||||
|
if (isPlayer)
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sTrapSuccess}");
|
||||||
|
MWWorld::Class::get(actor).skillUsageSucceeded(actor, ESM::Skill::Security, 0);
|
||||||
|
}
|
||||||
|
else if (isPlayer)
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sTrapFail}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (probe.getCellRef().mCharge == -1)
|
||||||
|
probe.getCellRef().mCharge = probe.get<ESM::Probe>()->mBase->mData.mUses;
|
||||||
|
--probe.getCellRef().mCharge;
|
||||||
|
if (!probe.getCellRef().mCharge)
|
||||||
|
probe.getRefData().setCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
apps/openmw/mwmechanics/security.hpp
Normal file
19
apps/openmw/mwmechanics/security.hpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef MWMECHANICS_SECURITY_H
|
||||||
|
#define MWMECHANICS_SECURITY_H
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @brief implementation of Security skill
|
||||||
|
class Security
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void pickLock (const MWWorld::Ptr& actor, const MWWorld::Ptr& lock, const MWWorld::Ptr& lockpick);
|
||||||
|
static void probeTrap (const MWWorld::Ptr& actor, const MWWorld::Ptr& trap, const MWWorld::Ptr& probe);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -728,4 +728,12 @@ void Animation::showWeapons(bool showWeapon)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Animation::isPriorityActive(int priority) const
|
||||||
|
{
|
||||||
|
for (AnimStateMap::const_iterator it = mStates.begin(); it != mStates.end(); ++it)
|
||||||
|
if (it->second.mPriority == priority)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,9 @@ public:
|
||||||
|
|
||||||
bool hasAnimation(const std::string &anim);
|
bool hasAnimation(const std::string &anim);
|
||||||
|
|
||||||
|
bool isPriorityActive (int priority) const;
|
||||||
|
///< Is there an animation playing with the given priority?
|
||||||
|
|
||||||
// Specifies the axis' to accumulate on. Non-accumulated axis will just
|
// Specifies the axis' to accumulate on. Non-accumulated axis will just
|
||||||
// move visually, but not affect the actual movement. Each x/y/z value
|
// move visually, but not affect the actual movement. Each x/y/z value
|
||||||
// should be on the scale of 0 to 1.
|
// should be on the scale of 0 to 1.
|
||||||
|
|
|
@ -193,6 +193,7 @@ namespace MWRender
|
||||||
mNode->setOrientation (Ogre::Quaternion::IDENTITY);
|
mNode->setOrientation (Ogre::Quaternion::IDENTITY);
|
||||||
|
|
||||||
mRenderTarget->update();
|
mRenderTarget->update();
|
||||||
|
|
||||||
mSelectionBuffer->update();
|
mSelectionBuffer->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,8 +204,8 @@ namespace MWRender
|
||||||
|
|
||||||
void InventoryPreview::onSetup ()
|
void InventoryPreview::onSetup ()
|
||||||
{
|
{
|
||||||
if (!mSelectionBuffer)
|
delete mSelectionBuffer;
|
||||||
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0);
|
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0);
|
||||||
|
|
||||||
mAnimation->showWeapons(true);
|
mAnimation->showWeapons(true);
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,6 @@ namespace MWRender
|
||||||
|
|
||||||
int getSlotSelected(int posX, int posY);
|
int getSlotSelected(int posX, int posY);
|
||||||
|
|
||||||
void setNpcAnimation (NpcAnimation* anim);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
OEngine::Render::SelectionBuffer* mSelectionBuffer;
|
OEngine::Render::SelectionBuffer* mSelectionBuffer;
|
||||||
|
|
|
@ -128,8 +128,6 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
||||||
assert(viewMode != VM_HeadOnly);
|
assert(viewMode != VM_HeadOnly);
|
||||||
mViewMode = viewMode;
|
mViewMode = viewMode;
|
||||||
|
|
||||||
Ogre::SceneNode *node = mInsert->getParentSceneNode();
|
|
||||||
|
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
|
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
|
||||||
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
||||||
|
|
|
@ -2,11 +2,18 @@
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
#include "../mwmechanics/character.hpp"
|
||||||
|
#include "../mwmechanics/security.hpp"
|
||||||
|
|
||||||
|
#include "../mwrender/animation.hpp"
|
||||||
|
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
|
||||||
|
@ -133,6 +140,42 @@ namespace MWWorld
|
||||||
MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[1] = roll;
|
MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[1] = roll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::use()
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& store = MWWorld::Class::get(getPlayer()).getInventoryStore(getPlayer());
|
||||||
|
MWWorld::ContainerStoreIterator equipped = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
|
||||||
|
if (getDrawState() == MWMechanics::DrawState_Weapon)
|
||||||
|
{
|
||||||
|
if (equipped != store.end())
|
||||||
|
{
|
||||||
|
MWWorld::Ptr item = *equipped;
|
||||||
|
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(getPlayer());
|
||||||
|
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getFacedObject();
|
||||||
|
|
||||||
|
if (anim->isPriorityActive(MWMechanics::Priority_Weapon))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (item.getTypeName() == typeid(ESM::Lockpick).name())
|
||||||
|
{
|
||||||
|
if (!target.isEmpty())
|
||||||
|
MWMechanics::Security::pickLock(getPlayer(), target, item);
|
||||||
|
anim->play("pickprobe", MWMechanics::Priority_Weapon, MWRender::Animation::Group_UpperBody, true, "start", "stop", 0.0, 0);
|
||||||
|
}
|
||||||
|
else if (item.getTypeName() == typeid(ESM::Probe).name())
|
||||||
|
{
|
||||||
|
if (!target.isEmpty())
|
||||||
|
MWMechanics::Security::probeTrap(getPlayer(), target, item);
|
||||||
|
anim->play("pickprobe", MWMechanics::Priority_Weapon, MWRender::Animation::Group_UpperBody, true, "start", "stop", 0.0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tool used up?
|
||||||
|
if (!item.getRefData().getCount())
|
||||||
|
MWBase::Environment::get().getWindowManager()->setSelectedWeapon(MWWorld::Ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MWMechanics::DrawState_ Player::getDrawState()
|
MWMechanics::DrawState_ Player::getDrawState()
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = getPlayer();
|
MWWorld::Ptr ptr = getPlayer();
|
||||||
|
|
|
@ -58,6 +58,9 @@ namespace MWWorld
|
||||||
void setForwardBackward (int value);
|
void setForwardBackward (int value);
|
||||||
void setUpDown(int value);
|
void setUpDown(int value);
|
||||||
|
|
||||||
|
void use ();
|
||||||
|
///< Use item equipped on right hand, or fists
|
||||||
|
|
||||||
void setRunState(bool run);
|
void setRunState(bool run);
|
||||||
void setSneak(bool sneak);
|
void setSneak(bool sneak);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue