2013-03-23 08:16:46 +01:00
|
|
|
#include "repair.hpp"
|
|
|
|
|
2015-04-22 17:58:55 +02:00
|
|
|
#include <components/misc/rng.hpp>
|
2015-03-15 14:07:47 +13:00
|
|
|
|
2013-03-23 08:16:46 +01:00
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
#include "../mwbase/windowmanager.hpp"
|
|
|
|
|
|
|
|
#include "../mwworld/containerstore.hpp"
|
|
|
|
#include "../mwworld/class.hpp"
|
2014-02-23 20:11:05 +01:00
|
|
|
#include "../mwworld/esmstore.hpp"
|
2013-03-23 08:16:46 +01:00
|
|
|
|
2015-08-21 21:12:39 +12:00
|
|
|
#include "creaturestats.hpp"
|
|
|
|
#include "actorutil.hpp"
|
2013-03-23 08:16:46 +01:00
|
|
|
|
|
|
|
namespace MWMechanics
|
|
|
|
{
|
|
|
|
|
|
|
|
void Repair::repair(const MWWorld::Ptr &itemToRepair)
|
|
|
|
{
|
2015-08-21 21:12:39 +12:00
|
|
|
MWWorld::Ptr player = getPlayer();
|
2013-03-23 08:16:46 +01:00
|
|
|
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
|
|
|
mTool.get<ESM::Repair>();
|
|
|
|
|
2014-01-02 21:21:28 +01:00
|
|
|
// unstack tool if required
|
|
|
|
player.getClass().getContainerStore(player).unstack(mTool, player);
|
|
|
|
|
2013-03-23 08:16:46 +01:00
|
|
|
// reduce number of uses left
|
2014-05-25 14:13:07 +02:00
|
|
|
int uses = mTool.getClass().getItemHealth(mTool);
|
2020-09-21 23:05:26 +03:00
|
|
|
uses -= std::min(uses, 1);
|
|
|
|
mTool.getCellRef().setCharge(uses);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
2014-05-22 20:37:22 +02:00
|
|
|
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
|
|
|
float fatigueTerm = stats.getFatigueTerm();
|
2018-12-23 15:18:33 +04:00
|
|
|
float pcStrength = stats.getAttribute(ESM::Attribute::Strength).getModified();
|
|
|
|
float pcLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
|
|
|
|
float armorerSkill = player.getClass().getSkill(player, ESM::Skill::Armorer);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
|
|
|
float fRepairAmountMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
2018-08-29 18:38:12 +03:00
|
|
|
.find("fRepairAmountMult")->mValue.getFloat();
|
2013-03-23 08:16:46 +01:00
|
|
|
|
|
|
|
float toolQuality = ref->mBase->mData.mQuality;
|
|
|
|
|
2015-03-08 17:42:07 +13:00
|
|
|
float x = (0.1f * pcStrength + 0.1f * pcLuck + armorerSkill) * fatigueTerm;
|
2013-03-23 08:16:46 +01:00
|
|
|
|
2022-03-06 21:56:02 +02:00
|
|
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
|
|
|
int roll = Misc::Rng::roll0to99(prng);
|
2013-03-23 08:16:46 +01:00
|
|
|
if (roll <= x)
|
|
|
|
{
|
2015-03-08 17:42:07 +13:00
|
|
|
int y = static_cast<int>(fRepairAmountMult * toolQuality * roll);
|
2013-03-23 08:16:46 +01:00
|
|
|
y = std::max(1, y);
|
|
|
|
|
|
|
|
// repair by 'y' points
|
2014-05-25 14:13:07 +02:00
|
|
|
int charge = itemToRepair.getClass().getItemHealth(itemToRepair);
|
|
|
|
charge = std::min(charge + y, itemToRepair.getClass().getItemMaxHealth(itemToRepair));
|
|
|
|
itemToRepair.getCellRef().setCharge(charge);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
2014-07-16 15:30:06 +02:00
|
|
|
// attempt to re-stack item, in case it was fully repaired
|
|
|
|
MWWorld::ContainerStoreIterator stacked = player.getClass().getContainerStore(player).restack(itemToRepair);
|
|
|
|
|
2013-03-23 08:16:46 +01:00
|
|
|
// set the OnPCRepair variable on the item's script
|
2014-07-16 15:30:06 +02:00
|
|
|
std::string script = stacked->getClass().getScript(itemToRepair);
|
2013-03-23 08:16:46 +01:00
|
|
|
if(script != "")
|
2014-07-16 15:30:06 +02:00
|
|
|
stacked->getRefData().getLocals().setVarByInt(script, "onpcrepair", 1);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
|
|
|
// increase skill
|
2014-05-22 20:37:22 +02:00
|
|
|
player.getClass().skillUsageSucceeded(player, ESM::Skill::Armorer, 0);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
2017-07-10 15:48:00 +04:00
|
|
|
MWBase::Environment::get().getWindowManager()->playSound("Repair");
|
2013-03-23 08:16:46 +01:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairSuccess}");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-10 15:48:00 +04:00
|
|
|
MWBase::Environment::get().getWindowManager()->playSound("Repair Fail");
|
2013-03-23 08:16:46 +01:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sRepairFailed}");
|
|
|
|
}
|
|
|
|
|
|
|
|
// tool used up?
|
2014-05-25 14:13:07 +02:00
|
|
|
if (mTool.getCellRef().getCharge() == 0)
|
2013-03-23 08:16:46 +01:00
|
|
|
{
|
2014-05-22 20:37:22 +02:00
|
|
|
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
2013-08-13 01:19:33 +02:00
|
|
|
|
|
|
|
store.remove(mTool, 1, player);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
|
|
|
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
2018-08-29 18:38:12 +03:00
|
|
|
.find("sNotifyMessage51")->mValue.getString();
|
2019-05-19 12:33:57 +04:00
|
|
|
message = Misc::StringUtils::format(message, mTool.getClass().getName(mTool));
|
2013-03-23 08:16:46 +01:00
|
|
|
|
2019-02-23 00:14:07 +03:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox(message);
|
2013-03-23 08:16:46 +01:00
|
|
|
|
|
|
|
// try to find a new tool of the same ID
|
|
|
|
for (MWWorld::ContainerStoreIterator iter (store.begin());
|
|
|
|
iter!=store.end(); ++iter)
|
|
|
|
{
|
2014-05-25 14:13:07 +02:00
|
|
|
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), mTool.getCellRef().getRefId()))
|
2013-03-23 08:16:46 +01:00
|
|
|
{
|
|
|
|
mTool = *iter;
|
2017-04-02 23:19:43 +04:00
|
|
|
|
2017-07-10 15:48:00 +04:00
|
|
|
MWBase::Environment::get().getWindowManager()->playSound("Item Repair Up");
|
2017-04-02 23:19:43 +04:00
|
|
|
|
2013-03-23 08:16:46 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|