You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
5.7 KiB
C++
172 lines
5.7 KiB
C++
#include "spellmodel.hpp"
|
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
#include "../mwbase/windowmanager.hpp"
|
|
|
|
#include "../mwmechanics/creaturestats.hpp"
|
|
#include "../mwmechanics/spellcasting.hpp"
|
|
|
|
#include "../mwworld/esmstore.hpp"
|
|
#include "../mwworld/inventorystore.hpp"
|
|
#include "../mwworld/class.hpp"
|
|
|
|
namespace
|
|
{
|
|
|
|
bool sortSpells(const MWGui::Spell& left, const MWGui::Spell& right)
|
|
{
|
|
if (left.mType != right.mType)
|
|
return left.mType < right.mType;
|
|
|
|
std::string leftName = Misc::StringUtils::lowerCase(left.mName);
|
|
std::string rightName = Misc::StringUtils::lowerCase(right.mName);
|
|
|
|
return leftName.compare(rightName) < 0;
|
|
}
|
|
|
|
}
|
|
|
|
namespace MWGui
|
|
{
|
|
|
|
SpellModel::SpellModel(const MWWorld::Ptr &actor, const std::string& filter)
|
|
: mActor(actor), mFilter(filter)
|
|
{
|
|
}
|
|
|
|
SpellModel::SpellModel(const MWWorld::Ptr &actor)
|
|
: mActor(actor)
|
|
{
|
|
}
|
|
|
|
void SpellModel::update()
|
|
{
|
|
mSpells.clear();
|
|
|
|
MWMechanics::CreatureStats& stats = mActor.getClass().getCreatureStats(mActor);
|
|
const MWMechanics::Spells& spells = stats.getSpells();
|
|
|
|
const MWWorld::ESMStore &esmStore =
|
|
MWBase::Environment::get().getWorld()->getStore();
|
|
|
|
std::string filter = Misc::StringUtils::lowerCaseUtf8(mFilter);
|
|
|
|
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
|
|
{
|
|
const ESM::Spell* spell = it->first;
|
|
if (spell->mData.mType != ESM::Spell::ST_Power && spell->mData.mType != ESM::Spell::ST_Spell)
|
|
continue;
|
|
|
|
std::string name = Misc::StringUtils::lowerCaseUtf8(spell->mName);
|
|
|
|
if (name.find(filter) == std::string::npos)
|
|
continue;
|
|
|
|
Spell newSpell;
|
|
newSpell.mName = spell->mName;
|
|
if (spell->mData.mType == ESM::Spell::ST_Spell)
|
|
{
|
|
newSpell.mType = Spell::Type_Spell;
|
|
std::string cost = std::to_string(spell->mData.mCost);
|
|
std::string chance = std::to_string(int(MWMechanics::getSpellSuccessChance(spell, mActor)));
|
|
newSpell.mCostColumn = cost + "/" + chance;
|
|
}
|
|
else
|
|
newSpell.mType = Spell::Type_Power;
|
|
newSpell.mId = spell->mId;
|
|
|
|
newSpell.mSelected = (MWBase::Environment::get().getWindowManager()->getSelectedSpell() == spell->mId);
|
|
newSpell.mActive = true;
|
|
newSpell.mCount = 1;
|
|
mSpells.push_back(newSpell);
|
|
}
|
|
|
|
MWWorld::InventoryStore& invStore = mActor.getClass().getInventoryStore(mActor);
|
|
for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it)
|
|
{
|
|
MWWorld::Ptr item = *it;
|
|
const std::string enchantId = item.getClass().getEnchantment(item);
|
|
if (enchantId.empty())
|
|
continue;
|
|
const ESM::Enchantment* enchant = esmStore.get<ESM::Enchantment>().search(enchantId);
|
|
if (!enchant)
|
|
{
|
|
Log(Debug::Warning) << "Warning: Can't find enchantment '" << enchantId << "' on item " << item.getCellRef().getRefId();
|
|
continue;
|
|
}
|
|
|
|
if (enchant->mData.mType != ESM::Enchantment::WhenUsed && enchant->mData.mType != ESM::Enchantment::CastOnce)
|
|
continue;
|
|
|
|
std::string name = Misc::StringUtils::lowerCaseUtf8(item.getClass().getName(item));
|
|
|
|
if (name.find(filter) == std::string::npos)
|
|
continue;
|
|
|
|
Spell newSpell;
|
|
newSpell.mItem = item;
|
|
newSpell.mId = item.getCellRef().getRefId();
|
|
newSpell.mName = item.getClass().getName(item);
|
|
newSpell.mCount = item.getRefData().getCount();
|
|
newSpell.mType = Spell::Type_EnchantedItem;
|
|
newSpell.mSelected = invStore.getSelectedEnchantItem() == it;
|
|
|
|
// FIXME: move to mwmechanics
|
|
if (enchant->mData.mType == ESM::Enchantment::CastOnce)
|
|
{
|
|
newSpell.mCostColumn = "100/100";
|
|
newSpell.mActive = false;
|
|
}
|
|
else
|
|
{
|
|
if (!item.getClass().getEquipmentSlots(item).first.empty()
|
|
&& item.getClass().canBeEquipped(item, mActor).first == 0)
|
|
continue;
|
|
|
|
int castCost = MWMechanics::getEffectiveEnchantmentCastCost(static_cast<float>(enchant->mData.mCost), mActor);
|
|
|
|
std::string cost = std::to_string(castCost);
|
|
int currentCharge = int(item.getCellRef().getEnchantmentCharge());
|
|
if (currentCharge == -1)
|
|
currentCharge = enchant->mData.mCharge;
|
|
std::string charge = std::to_string(currentCharge);
|
|
newSpell.mCostColumn = cost + "/" + charge;
|
|
|
|
newSpell.mActive = invStore.isEquipped(item);
|
|
}
|
|
mSpells.push_back(newSpell);
|
|
}
|
|
|
|
std::stable_sort(mSpells.begin(), mSpells.end(), sortSpells);
|
|
}
|
|
|
|
size_t SpellModel::getItemCount() const
|
|
{
|
|
return mSpells.size();
|
|
}
|
|
|
|
SpellModel::ModelIndex SpellModel::getSelectedIndex() const
|
|
{
|
|
ModelIndex selected = -1;
|
|
for (SpellModel::ModelIndex i = 0; i<int(getItemCount()); ++i)
|
|
{
|
|
if (getItem(i).mSelected) {
|
|
selected = i;
|
|
break;
|
|
}
|
|
}
|
|
return selected;
|
|
}
|
|
|
|
Spell SpellModel::getItem(ModelIndex index) const
|
|
{
|
|
if (index < 0 || index >= int(mSpells.size()))
|
|
throw std::runtime_error("invalid spell index supplied");
|
|
return mSpells[index];
|
|
}
|
|
|
|
}
|