1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-24 09:39:51 +00:00

message when using empty soul gems, using preferentially filled ones with equip command

This commit is contained in:
myrix 2022-07-24 23:02:26 +03:00
parent b942d70c3c
commit 8817f802cb
5 changed files with 94 additions and 3 deletions

View File

@ -201,6 +201,25 @@ namespace MWClass
return newPtr;
}
std::pair<int, std::string> Miscellaneous::canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const
{
// Special checks for soul gems.
if (::Misc::StringUtils::ciEqualPrefix("misc_soulgem", ptr.getCellRef().getRefId()))
{
if (npc != MWBase::Environment::get().getWorld()->getPlayerPtr())
return std::make_pair(0, "Only the player can use soul gems.");
if (ptr.getCellRef().getSoul().empty())
return std::make_pair(0, "#{sNotifyMessage32}");
if (!MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ptr.getCellRef().getSoul()))
return std::make_pair(0, "Unknown soul creature id.");
}
return std::make_pair(1, "");
}
std::unique_ptr<MWWorld::Action> Miscellaneous::use (const MWWorld::Ptr& ptr, bool force) const
{
if (ptr.getCellRef().getSoul().empty() || !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ptr.getCellRef().getSoul()))

View File

@ -45,6 +45,10 @@ namespace MWClass
std::string getModel(const MWWorld::ConstPtr &ptr) const override;
std::pair<int, std::string> canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const override;
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. \n
/// Second item in the pair specifies the error message
std::unique_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const override;
///< Generate action for using via inventory menu

View File

@ -549,6 +549,19 @@ namespace MWGui
}
}
// Separate check for the soul gems.
else if (::Misc::StringUtils::ciEqualPrefix("misc_soulgem", ptr.getCellRef().getRefId()))
{
std::pair<int, std::string> canEquip = ptr.getClass().canBeEquipped(ptr, player);
if (canEquip.first == 0)
{
MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second);
updateItemView();
return;
}
}
// If the item has a script, set OnPCEquip or PCSkipEquip to 1
if (!script.empty())
{

View File

@ -304,11 +304,38 @@ namespace MWScript
MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
MWWorld::ContainerStoreIterator it = invStore.begin();
for (; it != invStore.end(); ++it)
// With soul gems we prefer filled ones.
if (::Misc::StringUtils::ciEqualPrefix("misc_soulgem", item))
{
if (::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item))
break;
it = invStore.end();
for (auto it_any = invStore.begin(); it_any != invStore.end(); ++it_any)
{
if (::Misc::StringUtils::ciEqual(it_any->getCellRef().getRefId(), item))
{
if (!it_any->getCellRef().getSoul().empty() &&
MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(it_any->getCellRef().getSoul()))
{
it = it_any;
break;
}
else if (it == invStore.end())
it = it_any;
}
}
}
else
{
for (; it != invStore.end(); ++it)
{
if (::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item))
break;
}
}
if (it == invStore.end())
{
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), item, 1);

View File

@ -97,6 +97,34 @@ public:
return ciEqual(x, std::string_view(y, n - 1));
}
template <class X, class Y>
static bool ciEqualPrefix(const X& x, const Y& y)
{
return std::equal(std::begin(x), std::end(x), std::begin(y),
[] (char l, char r) { return toLower(l) == toLower(r); });
}
template <std::size_t n>
static auto ciEqualPrefix(const char(& x)[n], const char(& y)[n])
{
static_assert(n > 0);
return ciEqualPrefix(std::string_view(x, n - 1), std::string_view(y, n - 1));
}
template <std::size_t n, class T>
static auto ciEqualPrefix(const char(& x)[n], const T& y)
{
static_assert(n > 0);
return ciEqualPrefix(std::string_view(x, n - 1), y);
}
template <std::size_t n, class T>
static auto ciEqualPrefix(const T& x, const char(& y)[n])
{
static_assert(n > 0);
return ciEqualPrefix(x, std::string_view(y, n - 1));
}
static int ciCompareLen(std::string_view x, std::string_view y, std::size_t len)
{
std::string_view::const_iterator xit = x.begin();