Security skill

This commit is contained in:
scrawl 2013-05-19 18:40:37 +02:00
parent c7805e7dd2
commit 7a2d1cd8ce
12 changed files with 205 additions and 8 deletions

View file

@ -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

View file

@ -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

View file

@ -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);

View 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);
}
}

View 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

View file

@ -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;
}
} }

View file

@ -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.

View file

@ -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,7 +204,7 @@ 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);

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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);