mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:53:53 +00:00
Merge pull request #1405 from akortunov/stancechangefixes
Do not allow player to change weapon/spell during attack or spellcast
This commit is contained in:
commit
dc53573de4
16 changed files with 124 additions and 4 deletions
|
@ -223,6 +223,7 @@ namespace MWBase
|
||||||
virtual void keepPlayerAlive() = 0;
|
virtual void keepPlayerAlive() = 0;
|
||||||
|
|
||||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
|
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
|
||||||
|
virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const = 0;
|
||||||
|
|
||||||
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
|
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,10 @@ namespace MWBase
|
||||||
virtual void setSpellVisibility(bool visible) = 0;
|
virtual void setSpellVisibility(bool visible) = 0;
|
||||||
virtual void setSneakVisibility(bool visible) = 0;
|
virtual void setSneakVisibility(bool visible) = 0;
|
||||||
|
|
||||||
virtual void activateQuickKey (int index) = 0;
|
/// activate selected quick key
|
||||||
|
virtual void activateQuickKey (int index) = 0;
|
||||||
|
/// update activated quick key state (if action executing was delayed for some reason)
|
||||||
|
virtual void updateActivatedQuickKey () = 0;
|
||||||
|
|
||||||
virtual std::string getSelectedSpell() = 0;
|
virtual std::string getSelectedSpell() = 0;
|
||||||
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
|
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
@ -373,6 +374,9 @@ namespace MWClass
|
||||||
if (hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0)
|
if (hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0)
|
||||||
return std::make_pair(0, "#{sInventoryMessage1}");
|
return std::make_pair(0, "#{sInventoryMessage1}");
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(npc))
|
||||||
|
return std::make_pair(0, "#{sCantEquipWeapWarning}");
|
||||||
|
|
||||||
std::pair<std::vector<int>, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr);
|
std::pair<std::vector<int>, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr);
|
||||||
|
|
||||||
if (slots_.first.empty())
|
if (slots_.first.empty())
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "../mwrender/characterpreview.hpp"
|
#include "../mwrender/characterpreview.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "itemview.hpp"
|
#include "itemview.hpp"
|
||||||
#include "inventoryitemmodel.hpp"
|
#include "inventoryitemmodel.hpp"
|
||||||
|
@ -660,9 +661,18 @@ namespace MWGui
|
||||||
|
|
||||||
void InventoryWindow::cycle(bool next)
|
void InventoryWindow::cycle(bool next)
|
||||||
{
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const MWMechanics::CreatureStats &stats = player.getClass().getCreatureStats(player);
|
||||||
|
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery())
|
||||||
|
return;
|
||||||
|
|
||||||
ItemModel::ModelIndex selected = -1;
|
ItemModel::ModelIndex selected = -1;
|
||||||
// not using mSortFilterModel as we only need sorting, not filtering
|
// not using mSortFilterModel as we only need sorting, not filtering
|
||||||
SortFilterItemModel model(new InventoryItemModel(MWMechanics::getPlayer()));
|
SortFilterItemModel model(new InventoryItemModel(player));
|
||||||
model.setSortByType(false);
|
model.setSortByType(false);
|
||||||
model.update();
|
model.update();
|
||||||
if (model.getItemCount() == 0)
|
if (model.getItemCount() == 0)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ namespace MWGui
|
||||||
, mItemSelectionDialog(0)
|
, mItemSelectionDialog(0)
|
||||||
, mMagicSelectionDialog(0)
|
, mMagicSelectionDialog(0)
|
||||||
, mSelectedIndex(-1)
|
, mSelectedIndex(-1)
|
||||||
|
, mActivatedIndex(-1)
|
||||||
{
|
{
|
||||||
getWidget(mOkButton, "OKButton");
|
getWidget(mOkButton, "OKButton");
|
||||||
getWidget(mInstructionLabel, "InstructionLabel");
|
getWidget(mInstructionLabel, "InstructionLabel");
|
||||||
|
@ -69,6 +71,8 @@ namespace MWGui
|
||||||
|
|
||||||
void QuickKeysMenu::clear()
|
void QuickKeysMenu::clear()
|
||||||
{
|
{
|
||||||
|
mActivatedIndex = -1;
|
||||||
|
|
||||||
for (int i=0; i<10; ++i)
|
for (int i=0; i<10; ++i)
|
||||||
{
|
{
|
||||||
unassign(mQuickKeyButtons[i], i);
|
unassign(mQuickKeyButtons[i], i);
|
||||||
|
@ -254,6 +258,15 @@ namespace MWGui
|
||||||
mMagicSelectionDialog->setVisible(false);
|
mMagicSelectionDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuickKeysMenu::updateActivatedQuickKey()
|
||||||
|
{
|
||||||
|
// there is no delayed action, nothing to do.
|
||||||
|
if (mActivatedIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
activateQuickKey(mActivatedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
void QuickKeysMenu::activateQuickKey(int index)
|
void QuickKeysMenu::activateQuickKey(int index)
|
||||||
{
|
{
|
||||||
assert (index-1 >= 0);
|
assert (index-1 >= 0);
|
||||||
|
@ -263,6 +276,27 @@ namespace MWGui
|
||||||
|
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player);
|
||||||
|
|
||||||
|
// Delay action executing,
|
||||||
|
// if player is busy for now (casting a spell, attacking someone, etc.)
|
||||||
|
bool isDelayNeeded = MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player)
|
||||||
|
|| playerStats.getKnockedDown()
|
||||||
|
|| playerStats.getHitRecovery();
|
||||||
|
|
||||||
|
bool isReturnNeeded = playerStats.isParalyzed() || playerStats.isDead();
|
||||||
|
if (isReturnNeeded && type != Type_Item)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDelayNeeded && type != Type_Item)
|
||||||
|
{
|
||||||
|
mActivatedIndex = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mActivatedIndex = -1;
|
||||||
|
|
||||||
if (type == Type_Item || type == Type_MagicItem)
|
if (type == Type_Item || type == Type_MagicItem)
|
||||||
{
|
{
|
||||||
|
@ -309,6 +343,21 @@ namespace MWGui
|
||||||
else if (type == Type_Item)
|
else if (type == Type_Item)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
||||||
|
bool isWeapon = item.getTypeName() == typeid(ESM::Weapon).name();
|
||||||
|
|
||||||
|
// delay weapon switching if player is busy
|
||||||
|
if (isDelayNeeded && isWeapon)
|
||||||
|
{
|
||||||
|
mActivatedIndex = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable weapon switching if player is dead or paralyzed
|
||||||
|
if (isReturnNeeded && isWeapon)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->useItem(item);
|
MWBase::Environment::get().getWindowManager()->useItem(item);
|
||||||
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
// change draw state only if the item is in player's right hand
|
// change draw state only if the item is in player's right hand
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace MWGui
|
||||||
void onAssignMagicCancel ();
|
void onAssignMagicCancel ();
|
||||||
|
|
||||||
void activateQuickKey(int index);
|
void activateQuickKey(int index);
|
||||||
|
void updateActivatedQuickKey();
|
||||||
|
|
||||||
/// @note This enum is serialized, so don't move the items around!
|
/// @note This enum is serialized, so don't move the items around!
|
||||||
enum QuickKeyType
|
enum QuickKeyType
|
||||||
|
@ -64,7 +65,7 @@ namespace MWGui
|
||||||
MagicSelectionDialog* mMagicSelectionDialog;
|
MagicSelectionDialog* mMagicSelectionDialog;
|
||||||
|
|
||||||
int mSelectedIndex;
|
int mSelectedIndex;
|
||||||
|
int mActivatedIndex;
|
||||||
|
|
||||||
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
||||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -195,6 +196,15 @@ namespace MWGui
|
||||||
|
|
||||||
void SpellWindow::cycle(bool next)
|
void SpellWindow::cycle(bool next)
|
||||||
{
|
{
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const MWMechanics::CreatureStats &stats = player.getClass().getCreatureStats(player);
|
||||||
|
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery())
|
||||||
|
return;
|
||||||
|
|
||||||
mSpellView->setModel(new SpellModel(MWMechanics::getPlayer()));
|
mSpellView->setModel(new SpellModel(MWMechanics::getPlayer()));
|
||||||
|
|
||||||
SpellModel::ModelIndex selected = 0;
|
SpellModel::ModelIndex selected = 0;
|
||||||
|
|
|
@ -518,6 +518,8 @@ namespace MWGui
|
||||||
cleanupGarbage();
|
cleanupGarbage();
|
||||||
|
|
||||||
mHud->update();
|
mHud->update();
|
||||||
|
|
||||||
|
updateActivatedQuickKey ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::updateVisible()
|
void WindowManager::updateVisible()
|
||||||
|
@ -1528,6 +1530,11 @@ namespace MWGui
|
||||||
mHud->setCrosshairVisible (show && mCrosshairEnabled);
|
mHud->setCrosshairVisible (show && mCrosshairEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowManager::updateActivatedQuickKey ()
|
||||||
|
{
|
||||||
|
mQuickKeysMenu->updateActivatedQuickKey();
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::activateQuickKey (int index)
|
void WindowManager::activateQuickKey (int index)
|
||||||
{
|
{
|
||||||
mQuickKeysMenu->activateQuickKey(index);
|
mQuickKeysMenu->activateQuickKey(index);
|
||||||
|
|
|
@ -241,7 +241,10 @@ namespace MWGui
|
||||||
virtual void setSpellVisibility(bool visible);
|
virtual void setSpellVisibility(bool visible);
|
||||||
virtual void setSneakVisibility(bool visible);
|
virtual void setSneakVisibility(bool visible);
|
||||||
|
|
||||||
virtual void activateQuickKey (int index);
|
/// activate selected quick key
|
||||||
|
virtual void activateQuickKey (int index);
|
||||||
|
/// update activated quick key state (if action executing was delayed for some reason)
|
||||||
|
virtual void updateActivatedQuickKey ();
|
||||||
|
|
||||||
virtual std::string getSelectedSpell() { return mSelectedSpell; }
|
virtual std::string getSelectedSpell() { return mSelectedSpell; }
|
||||||
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
|
virtual void setSelectedSpell(const std::string& spellId, int successChancePercent);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -929,6 +930,9 @@ namespace MWInput
|
||||||
inventory.getSelectedEnchantItem() == inventory.end())
|
inventory.getSelectedEnchantItem() == inventory.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||||
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
|
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
|
||||||
mPlayer->setDrawState(MWMechanics::DrawState_Spell);
|
mPlayer->setDrawState(MWMechanics::DrawState_Spell);
|
||||||
|
@ -944,6 +948,9 @@ namespace MWInput
|
||||||
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||||
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
||||||
mPlayer->setDrawState(MWMechanics::DrawState_Weapon);
|
mPlayer->setDrawState(MWMechanics::DrawState_Weapon);
|
||||||
|
|
|
@ -1788,6 +1788,16 @@ namespace MWMechanics
|
||||||
return it->second->getCharacterController()->isReadyToBlock();
|
return it->second->getCharacterController()->isReadyToBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Actors::isAttackingOrSpell(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
PtrActorMap::const_iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return false;
|
||||||
|
CharacterController* ctrl = it->second->getCharacterController();
|
||||||
|
|
||||||
|
return ctrl->isAttackingOrSpell();
|
||||||
|
}
|
||||||
|
|
||||||
void Actors::fastForwardAi()
|
void Actors::fastForwardAi()
|
||||||
{
|
{
|
||||||
if (!MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
if (!MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
||||||
|
|
|
@ -150,6 +150,7 @@ namespace MWMechanics
|
||||||
void clear(); // Clear death counter
|
void clear(); // Clear death counter
|
||||||
|
|
||||||
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
||||||
|
bool isAttackingOrSpell(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PtrActorMap mActors;
|
PtrActorMap mActors;
|
||||||
|
|
|
@ -2228,6 +2228,12 @@ bool CharacterController::isKnockedOut() const
|
||||||
return mHitState == CharState_KnockOut;
|
return mHitState == CharState_KnockOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CharacterController::isAttackingOrSpell() const
|
||||||
|
{
|
||||||
|
return mUpperBodyState != UpperCharState_Nothing &&
|
||||||
|
mUpperBodyState != UpperCharState_WeapEquiped;
|
||||||
|
}
|
||||||
|
|
||||||
bool CharacterController::isSneaking() const
|
bool CharacterController::isSneaking() const
|
||||||
{
|
{
|
||||||
return mIdleState == CharState_IdleSneak ||
|
return mIdleState == CharState_IdleSneak ||
|
||||||
|
|
|
@ -267,6 +267,7 @@ public:
|
||||||
bool isKnockedOut() const;
|
bool isKnockedOut() const;
|
||||||
bool isSneaking() const;
|
bool isSneaking() const;
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
bool isAttackingOrSpell() const;
|
||||||
|
|
||||||
void setAttackingOrSpell(bool attackingOrSpell);
|
void setAttackingOrSpell(bool attackingOrSpell);
|
||||||
void setAIAttackType(const std::string& attackType);
|
void setAIAttackType(const std::string& attackType);
|
||||||
|
|
|
@ -1591,6 +1591,11 @@ namespace MWMechanics
|
||||||
return mActors.isReadyToBlock(ptr);
|
return mActors.isReadyToBlock(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isAttackingOrSpell(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return mActors.isAttackingOrSpell(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void MechanicsManager::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
|
void MechanicsManager::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
|
||||||
{
|
{
|
||||||
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats(actor);
|
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats(actor);
|
||||||
|
|
|
@ -188,6 +188,8 @@ namespace MWMechanics
|
||||||
virtual void keepPlayerAlive();
|
virtual void keepPlayerAlive();
|
||||||
|
|
||||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
|
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
|
||||||
|
/// Is \a ptr casting spell or using weapon now?
|
||||||
|
virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const;
|
||||||
|
|
||||||
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer);
|
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue