1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 12:39:55 +00:00
florent.teppe 65cdd489fb create a specific esm reader function for RefID to avoid allocation for string and then again for RefId
Fixed some types

removed useless header

applied clang format

fixed compile tests

fixed clang tidy, and closer to logic before this MR

Removed hardcoded refids

unless there is a returned value we don't use static RefIds
can use == between RefId and hardcoded string

Fix clang format

Fixed a few instances where std::string was used, when only const std::string& was needed

removed unused variable
2022-12-27 19:15:57 +01:00

248 lines
8.5 KiB
C++

#include "misc.hpp"
#include <MyGUI_TextIterator.h>
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/loadmisc.hpp>
#include <components/esm3/loadnpc.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/actionsoulgem.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp"
#include "../mwgui/ustring.hpp"
#include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "classmodel.hpp"
namespace MWClass
{
Miscellaneous::Miscellaneous()
: MWWorld::RegisteredClass<Miscellaneous>(ESM::Miscellaneous::sRecordId)
{
}
bool Miscellaneous::isGold(const MWWorld::ConstPtr& ptr) const
{
return ptr.getCellRef().getRefId() == "gold_001" || ptr.getCellRef().getRefId() == "gold_005"
|| ptr.getCellRef().getRefId() == "gold_010" || ptr.getCellRef().getRefId() == "gold_025"
|| ptr.getCellRef().getRefId() == "gold_100";
}
void Miscellaneous::insertObjectRendering(
const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{
if (!model.empty())
{
renderingInterface.getObjects().insertModel(ptr, model);
}
}
std::string Miscellaneous::getModel(const MWWorld::ConstPtr& ptr) const
{
return getClassModel<ESM::Miscellaneous>(ptr);
}
std::string_view Miscellaneous::getName(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
const std::string& name = ref->mBase->mName;
return !name.empty() ? name : ref->mBase->mId.getRefIdString();
}
std::unique_ptr<MWWorld::Action> Miscellaneous::activate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const
{
return defaultItemActivate(ptr, actor);
}
const ESM::RefId& Miscellaneous::getScript(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
return ref->mBase->mScript;
}
int Miscellaneous::getValue(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
int value = ref->mBase->mData.mValue;
if (ptr.getCellRef().getGoldValue() > 1 && ptr.getRefData().getCount() == 1)
value = ptr.getCellRef().getGoldValue();
if (!ptr.getCellRef().getSoul().empty())
{
const ESM::Creature* creature
= MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ref->mRef.getSoul());
if (creature)
{
int soul = creature->mData.mSoul;
if (Settings::Manager::getBool("rebalance soul gem values", "Game"))
{
// use the 'soul gem value rebalance' formula from the Morrowind Code Patch
float soulValue = 0.0001 * pow(soul, 3) + 2 * soul;
// for Azura's star add the unfilled value
if (ptr.getCellRef().getRefId() == "Misc_SoulGem_Azura")
value += soulValue;
else
value = soulValue;
}
else
value *= soul;
}
}
return value;
}
const ESM::RefId& Miscellaneous::getUpSoundId(const MWWorld::ConstPtr& ptr) const
{
static const ESM::RefId soundGold = ESM::RefId::stringRefId("Item Gold Up");
static const ESM::RefId soundMisc = ESM::RefId::stringRefId("Item Misc Up");
if (isGold(ptr))
return soundGold;
return soundMisc;
}
const ESM::RefId& Miscellaneous::getDownSoundId(const MWWorld::ConstPtr& ptr) const
{
static const ESM::RefId soundGold = ESM::RefId::stringRefId("Item Gold Down");
static const ESM::RefId soundMisc = ESM::RefId::stringRefId("Item Misc Down");
if (isGold(ptr))
return soundGold;
return soundMisc;
}
const std::string& Miscellaneous::getInventoryIcon(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
return ref->mBase->mIcon;
}
MWGui::ToolTipInfo Miscellaneous::getToolTipInfo(const MWWorld::ConstPtr& ptr, int count) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
MWGui::ToolTipInfo info;
bool gold = isGold(ptr);
if (gold)
count *= getValue(ptr);
std::string countString;
if (!gold)
countString = MWGui::ToolTips::getCountString(count);
else // gold displays its count also if it's 1.
countString = " (" + std::to_string(count) + ")";
std::string_view name = getName(ptr);
info.caption = MyGUI::TextIterator::toTagsString(MWGui::toUString(name))
+ MWGui::ToolTips::getCountString(count) + MWGui::ToolTips::getSoulString(ptr.getCellRef());
info.icon = ref->mBase->mIcon;
std::string text;
text += MWGui::ToolTips::getWeightString(ref->mBase->mData.mWeight, "#{sWeight}");
if (!gold && !(ref->mBase->mData.mFlags & ESM::Miscellaneous::Key))
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");
if (MWBase::Environment::get().getWindowManager()->getFullHelp())
{
text += MWGui::ToolTips::getCellRefString(ptr.getCellRef());
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript.getRefIdString(), "Script");
}
info.text = text;
return info;
}
MWWorld::Ptr Miscellaneous::copyToCell(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell, int count) const
{
MWWorld::Ptr newPtr;
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
if (isGold(ptr))
{
int goldAmount = getValue(ptr) * count;
std::string_view base = "gold_001";
if (goldAmount >= 100)
base = "gold_100";
else if (goldAmount >= 25)
base = "gold_025";
else if (goldAmount >= 10)
base = "gold_010";
else if (goldAmount >= 5)
base = "gold_005";
// Really, I have no idea why moving ref out of conditional
// scope causes list::push_back throwing std::bad_alloc
MWWorld::ManualRef newRef(store, ESM::RefId::stringRefId(base));
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = newRef.getPtr().get<ESM::Miscellaneous>();
newPtr = MWWorld::Ptr(cell.insert(ref), &cell);
newPtr.getCellRef().setGoldValue(goldAmount);
newPtr.getRefData().setCount(1);
}
else
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
newPtr = MWWorld::Ptr(cell.insert(ref), &cell);
newPtr.getRefData().setCount(count);
}
newPtr.getCellRef().unsetRefNum();
return newPtr;
}
std::unique_ptr<MWWorld::Action> Miscellaneous::use(const MWWorld::Ptr& ptr, bool force) const
{
if (isSoulGem(ptr))
return std::make_unique<MWWorld::ActionSoulgem>(ptr);
return std::make_unique<MWWorld::NullAction>();
}
bool Miscellaneous::canSell(const MWWorld::ConstPtr& item, int npcServices) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = item.get<ESM::Miscellaneous>();
return !(ref->mBase->mData.mFlags & ESM::Miscellaneous::Key) && (npcServices & ESM::NPC::Misc) && !isGold(item);
}
float Miscellaneous::getWeight(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
return ref->mBase->mData.mWeight;
}
bool Miscellaneous::isKey(const MWWorld::ConstPtr& ptr) const
{
const MWWorld::LiveCellRef<ESM::Miscellaneous>* ref = ptr.get<ESM::Miscellaneous>();
return ref->mBase->mData.mFlags & ESM::Miscellaneous::Key;
}
bool Miscellaneous::isSoulGem(const MWWorld::ConstPtr& ptr) const
{
return Misc::StringUtils::ciStartsWith(ptr.getCellRef().getRefId().getRefIdString(), "misc_soulgem");
}
}