forked from teamnwah/openmw-tes3coop
Implement weapon/spell cycling hotkeys (Fixes #1024)
This commit is contained in:
parent
4d5adfb5dd
commit
935cccf974
11 changed files with 148 additions and 12 deletions
|
@ -342,6 +342,11 @@ namespace MWBase
|
||||||
virtual void setWerewolfOverlay(bool set) = 0;
|
virtual void setWerewolfOverlay(bool set) = 0;
|
||||||
|
|
||||||
virtual void toggleDebugWindow() = 0;
|
virtual void toggleDebugWindow() = 0;
|
||||||
|
|
||||||
|
/// Cycle to next or previous spell
|
||||||
|
virtual void cycleSpell(bool next) = 0;
|
||||||
|
/// Cycle to next or previous weapon
|
||||||
|
virtual void cycleWeapon(bool next) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,19 @@
|
||||||
#include "tradewindow.hpp"
|
#include "tradewindow.hpp"
|
||||||
#include "container.hpp"
|
#include "container.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
bool isRightHandWeapon(const MWWorld::Ptr& item)
|
||||||
|
{
|
||||||
|
if (item.getClass().getTypeName() != typeid(ESM::Weapon).name())
|
||||||
|
return false;
|
||||||
|
std::vector<int> equipmentSlots = item.getClass().getEquipmentSlots(item).first;
|
||||||
|
return (!equipmentSlots.empty() && equipmentSlots.front() == MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -599,4 +612,39 @@ namespace MWGui
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, count);
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InventoryWindow::cycle(bool next)
|
||||||
|
{
|
||||||
|
ItemModel::ModelIndex selected = 0;
|
||||||
|
// not using mSortFilterModel as we only need sorting, not filtering
|
||||||
|
SortFilterItemModel model(new InventoryItemModel(MWBase::Environment::get().getWorld()->getPlayerPtr()));
|
||||||
|
model.setSortByType(false);
|
||||||
|
model.update();
|
||||||
|
if (model.getItemCount() == 0)
|
||||||
|
return;
|
||||||
|
for (ItemModel::ModelIndex i=0; i<int(model.getItemCount()); ++i)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr item = model.getItem(i).mBase;
|
||||||
|
if (model.getItem(i).mType & ItemStack::Type_Equipped && isRightHandWeapon(item))
|
||||||
|
selected = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int incr = next ? 1 : -1;
|
||||||
|
bool found = false;
|
||||||
|
ItemModel::ModelIndex cycled = selected;
|
||||||
|
while (!found)
|
||||||
|
{
|
||||||
|
cycled += incr;
|
||||||
|
cycled = (cycled + model.getItemCount()) % model.getItemCount();
|
||||||
|
|
||||||
|
MWWorld::Ptr item = model.getItem(cycled).mBase;
|
||||||
|
if (item.getClass().getTypeName() == typeid(ESM::Weapon).name() && isRightHandWeapon(item))
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (cycled == selected) // we've been through all items, nothing found
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
useItem(model.getItem(cycled).mBase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,9 @@ namespace MWGui
|
||||||
|
|
||||||
void setGuiMode(GuiMode mode);
|
void setGuiMode(GuiMode mode);
|
||||||
|
|
||||||
|
/// Cycle to previous/next weapon
|
||||||
|
void cycle(bool next);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DragAndDrop* mDragAndDrop;
|
DragAndDrop* mDragAndDrop;
|
||||||
|
|
||||||
|
|
|
@ -41,20 +41,25 @@ namespace
|
||||||
return std::find(mapping.begin(), mapping.end(), type1) < std::find(mapping.begin(), mapping.end(), type2);
|
return std::find(mapping.begin(), mapping.end(), type1) < std::find(mapping.begin(), mapping.end(), type2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compare (const MWGui::ItemStack& left, const MWGui::ItemStack& right)
|
struct Compare
|
||||||
{
|
{
|
||||||
if (left.mType != right.mType)
|
bool mSortByType;
|
||||||
return left.mType < right.mType;
|
Compare() : mSortByType(true) {}
|
||||||
|
bool operator() (const MWGui::ItemStack& left, const MWGui::ItemStack& right)
|
||||||
if (left.mBase.getTypeName() == right.mBase.getTypeName())
|
|
||||||
{
|
{
|
||||||
int cmp = left.mBase.getClass().getName(left.mBase).compare(
|
if (mSortByType && left.mType != right.mType)
|
||||||
right.mBase.getClass().getName(right.mBase));
|
return left.mType < right.mType;
|
||||||
return cmp < 0;
|
|
||||||
|
if (left.mBase.getTypeName() == right.mBase.getTypeName())
|
||||||
|
{
|
||||||
|
int cmp = left.mBase.getClass().getName(left.mBase).compare(
|
||||||
|
right.mBase.getClass().getName(right.mBase));
|
||||||
|
return cmp < 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return compareType(left.mBase.getTypeName(), right.mBase.getTypeName());
|
||||||
}
|
}
|
||||||
else
|
};
|
||||||
return compareType(left.mBase.getTypeName(), right.mBase.getTypeName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -63,6 +68,7 @@ namespace MWGui
|
||||||
SortFilterItemModel::SortFilterItemModel(ItemModel *sourceModel)
|
SortFilterItemModel::SortFilterItemModel(ItemModel *sourceModel)
|
||||||
: mCategory(Category_All)
|
: mCategory(Category_All)
|
||||||
, mShowEquipped(true)
|
, mShowEquipped(true)
|
||||||
|
, mSortByType(true)
|
||||||
, mFilter(0)
|
, mFilter(0)
|
||||||
{
|
{
|
||||||
mSourceModel = sourceModel;
|
mSourceModel = sourceModel;
|
||||||
|
@ -183,7 +189,9 @@ namespace MWGui
|
||||||
mItems.push_back(item);
|
mItems.push_back(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(mItems.begin(), mItems.end(), compare);
|
Compare cmp;
|
||||||
|
cmp.mSortByType = mSortByType;
|
||||||
|
std::sort(mItems.begin(), mItems.end(), cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,9 @@ namespace MWGui
|
||||||
void setFilter (int filter);
|
void setFilter (int filter);
|
||||||
void setShowEquipped (bool show) { mShowEquipped = show; }
|
void setShowEquipped (bool show) { mShowEquipped = show; }
|
||||||
|
|
||||||
|
/// Use ItemStack::Type for sorting?
|
||||||
|
void setSortByType(bool sort) { mSortByType = sort; }
|
||||||
|
|
||||||
static const int Category_Weapon = (1<<1);
|
static const int Category_Weapon = (1<<1);
|
||||||
static const int Category_Apparel = (1<<2);
|
static const int Category_Apparel = (1<<2);
|
||||||
static const int Category_Misc = (1<<3);
|
static const int Category_Misc = (1<<3);
|
||||||
|
@ -47,6 +50,7 @@ namespace MWGui
|
||||||
int mCategory;
|
int mCategory;
|
||||||
int mFilter;
|
int mFilter;
|
||||||
bool mShowEquipped;
|
bool mShowEquipped;
|
||||||
|
bool mSortByType;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,10 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!item.getClass().getEquipmentSlots(item).first.empty()
|
||||||
|
&& item.getClass().canBeEquipped(item, mActor).first == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
float enchantCost = enchant->mData.mCost;
|
float enchantCost = enchant->mData.mCost;
|
||||||
int eSkill = mActor.getClass().getSkill(mActor, ESM::Skill::Enchant);
|
int eSkill = mActor.getClass().getSkill(mActor, ESM::Skill::Enchant);
|
||||||
int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10));
|
int castCost = std::max(1.f, enchantCost - (enchantCost / 100) * (eSkill - 10));
|
||||||
|
|
|
@ -160,4 +160,25 @@ namespace MWGui
|
||||||
|
|
||||||
updateSpells();
|
updateSpells();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpellWindow::cycle(bool next)
|
||||||
|
{
|
||||||
|
mSpellView->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr()));
|
||||||
|
mSpellView->getModel()->update();
|
||||||
|
|
||||||
|
SpellModel::ModelIndex selected = 0;
|
||||||
|
for (SpellModel::ModelIndex i = 0; i<int(mSpellView->getModel()->getItemCount()); ++i)
|
||||||
|
{
|
||||||
|
if (mSpellView->getModel()->getItem(i).mSelected)
|
||||||
|
selected = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
selected += next ? 1 : -1;
|
||||||
|
int itemcount = mSpellView->getModel()->getItemCount();
|
||||||
|
if (itemcount == 0)
|
||||||
|
return;
|
||||||
|
selected = (selected + itemcount) % itemcount;
|
||||||
|
|
||||||
|
onModelIndexSelected(selected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ namespace MWGui
|
||||||
|
|
||||||
void onFrame(float dt) { NoDrop::onFrame(dt); }
|
void onFrame(float dt) { NoDrop::onFrame(dt); }
|
||||||
|
|
||||||
|
/// Cycle to next/previous spell
|
||||||
|
void cycle(bool next);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MyGUI::Widget* mEffectBox;
|
MyGUI::Widget* mEffectBox;
|
||||||
|
|
||||||
|
|
|
@ -1820,4 +1820,14 @@ namespace MWGui
|
||||||
mDebugWindow->setVisible(!mDebugWindow->isVisible());
|
mDebugWindow->setVisible(!mDebugWindow->isVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowManager::cycleSpell(bool next)
|
||||||
|
{
|
||||||
|
mSpellWindow->cycle(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::cycleWeapon(bool next)
|
||||||
|
{
|
||||||
|
mInventoryWindow->cycle(next);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,6 +338,11 @@ namespace MWGui
|
||||||
|
|
||||||
virtual void toggleDebugWindow();
|
virtual void toggleDebugWindow();
|
||||||
|
|
||||||
|
/// Cycle to next or previous spell
|
||||||
|
virtual void cycleSpell(bool next);
|
||||||
|
/// Cycle to next or previous weapon
|
||||||
|
virtual void cycleWeapon(bool next);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mConsoleOnlyScripts;
|
bool mConsoleOnlyScripts;
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,18 @@ namespace MWInput
|
||||||
case A_QuickLoad:
|
case A_QuickLoad:
|
||||||
quickLoad();
|
quickLoad();
|
||||||
break;
|
break;
|
||||||
|
case A_CycleSpellLeft:
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleSpell(false);
|
||||||
|
break;
|
||||||
|
case A_CycleSpellRight:
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleSpell(true);
|
||||||
|
break;
|
||||||
|
case A_CycleWeaponLeft:
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(false);
|
||||||
|
break;
|
||||||
|
case A_CycleWeaponRight:
|
||||||
|
MWBase::Environment::get().getWindowManager()->cycleWeapon(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -894,6 +906,11 @@ namespace MWInput
|
||||||
defaultKeyBindings[A_MoveRight] = SDL_SCANCODE_D;
|
defaultKeyBindings[A_MoveRight] = SDL_SCANCODE_D;
|
||||||
defaultKeyBindings[A_ToggleWeapon] = SDL_SCANCODE_F;
|
defaultKeyBindings[A_ToggleWeapon] = SDL_SCANCODE_F;
|
||||||
defaultKeyBindings[A_ToggleSpell] = SDL_SCANCODE_R;
|
defaultKeyBindings[A_ToggleSpell] = SDL_SCANCODE_R;
|
||||||
|
defaultKeyBindings[A_CycleSpellLeft] = SDL_SCANCODE_MINUS;
|
||||||
|
defaultKeyBindings[A_CycleSpellRight] = SDL_SCANCODE_EQUALS;
|
||||||
|
defaultKeyBindings[A_CycleWeaponLeft] = SDL_SCANCODE_LEFTBRACKET;
|
||||||
|
defaultKeyBindings[A_CycleWeaponRight] = SDL_SCANCODE_RIGHTBRACKET;
|
||||||
|
|
||||||
defaultKeyBindings[A_QuickKeysMenu] = SDL_SCANCODE_F1;
|
defaultKeyBindings[A_QuickKeysMenu] = SDL_SCANCODE_F1;
|
||||||
defaultKeyBindings[A_Console] = SDL_SCANCODE_GRAVE;
|
defaultKeyBindings[A_Console] = SDL_SCANCODE_GRAVE;
|
||||||
defaultKeyBindings[A_Run] = SDL_SCANCODE_LSHIFT;
|
defaultKeyBindings[A_Run] = SDL_SCANCODE_LSHIFT;
|
||||||
|
@ -972,6 +989,10 @@ namespace MWInput
|
||||||
descriptions[A_MoveRight] = "sRight";
|
descriptions[A_MoveRight] = "sRight";
|
||||||
descriptions[A_ToggleWeapon] = "sReady_Weapon";
|
descriptions[A_ToggleWeapon] = "sReady_Weapon";
|
||||||
descriptions[A_ToggleSpell] = "sReady_Magic";
|
descriptions[A_ToggleSpell] = "sReady_Magic";
|
||||||
|
descriptions[A_CycleSpellLeft] = "sPrevSpell";
|
||||||
|
descriptions[A_CycleSpellRight] = "sNextSpell";
|
||||||
|
descriptions[A_CycleWeaponLeft] = "sPrevWeapon";
|
||||||
|
descriptions[A_CycleWeaponRight] = "sNextWeapon";
|
||||||
descriptions[A_Console] = "sConsoleTitle";
|
descriptions[A_Console] = "sConsoleTitle";
|
||||||
descriptions[A_Run] = "sRun";
|
descriptions[A_Run] = "sRun";
|
||||||
descriptions[A_Sneak] = "sCrouch_Sneak";
|
descriptions[A_Sneak] = "sCrouch_Sneak";
|
||||||
|
@ -1032,6 +1053,10 @@ namespace MWInput
|
||||||
ret.push_back(A_Use);
|
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_CycleSpellLeft);
|
||||||
|
ret.push_back(A_CycleSpellRight);
|
||||||
|
ret.push_back(A_CycleWeaponLeft);
|
||||||
|
ret.push_back(A_CycleWeaponRight);
|
||||||
ret.push_back(A_AutoMove);
|
ret.push_back(A_AutoMove);
|
||||||
ret.push_back(A_Jump);
|
ret.push_back(A_Jump);
|
||||||
ret.push_back(A_Inventory);
|
ret.push_back(A_Inventory);
|
||||||
|
|
Loading…
Reference in a new issue