forked from mirror/openmw-tes3mp
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 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;
|
||||
|
||||
|
|
|
@ -212,7 +212,10 @@ namespace MWBase
|
|||
virtual void setSpellVisibility(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 void setSelectedSpell(const std::string& spellId, int successChancePercent) = 0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
|
@ -373,6 +374,9 @@ namespace MWClass
|
|||
if (hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0)
|
||||
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);
|
||||
|
||||
if (slots_.first.empty())
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "../mwrender/characterpreview.hpp"
|
||||
|
||||
#include "../mwmechanics/actorutil.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "itemview.hpp"
|
||||
#include "inventoryitemmodel.hpp"
|
||||
|
@ -660,9 +661,18 @@ namespace MWGui
|
|||
|
||||
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;
|
||||
// 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.update();
|
||||
if (model.getItemCount() == 0)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
|
@ -36,6 +37,7 @@ namespace MWGui
|
|||
, mItemSelectionDialog(0)
|
||||
, mMagicSelectionDialog(0)
|
||||
, mSelectedIndex(-1)
|
||||
, mActivatedIndex(-1)
|
||||
{
|
||||
getWidget(mOkButton, "OKButton");
|
||||
getWidget(mInstructionLabel, "InstructionLabel");
|
||||
|
@ -69,6 +71,8 @@ namespace MWGui
|
|||
|
||||
void QuickKeysMenu::clear()
|
||||
{
|
||||
mActivatedIndex = -1;
|
||||
|
||||
for (int i=0; i<10; ++i)
|
||||
{
|
||||
unassign(mQuickKeyButtons[i], i);
|
||||
|
@ -254,6 +258,15 @@ namespace MWGui
|
|||
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)
|
||||
{
|
||||
assert (index-1 >= 0);
|
||||
|
@ -263,6 +276,27 @@ namespace MWGui
|
|||
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
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)
|
||||
{
|
||||
|
@ -309,6 +343,21 @@ namespace MWGui
|
|||
else if (type == Type_Item)
|
||||
{
|
||||
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);
|
||||
MWWorld::ConstContainerStoreIterator rightHand = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
// change draw state only if the item is in player's right hand
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace MWGui
|
|||
void onAssignMagicCancel ();
|
||||
|
||||
void activateQuickKey(int index);
|
||||
void updateActivatedQuickKey();
|
||||
|
||||
/// @note This enum is serialized, so don't move the items around!
|
||||
enum QuickKeyType
|
||||
|
@ -64,7 +65,7 @@ namespace MWGui
|
|||
MagicSelectionDialog* mMagicSelectionDialog;
|
||||
|
||||
int mSelectedIndex;
|
||||
|
||||
int mActivatedIndex;
|
||||
|
||||
void onQuickKeyButtonClicked(MyGUI::Widget* sender);
|
||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
@ -195,6 +196,15 @@ namespace MWGui
|
|||
|
||||
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()));
|
||||
|
||||
SpellModel::ModelIndex selected = 0;
|
||||
|
|
|
@ -518,6 +518,8 @@ namespace MWGui
|
|||
cleanupGarbage();
|
||||
|
||||
mHud->update();
|
||||
|
||||
updateActivatedQuickKey ();
|
||||
}
|
||||
|
||||
void WindowManager::updateVisible()
|
||||
|
@ -1528,6 +1530,11 @@ namespace MWGui
|
|||
mHud->setCrosshairVisible (show && mCrosshairEnabled);
|
||||
}
|
||||
|
||||
void WindowManager::updateActivatedQuickKey ()
|
||||
{
|
||||
mQuickKeysMenu->updateActivatedQuickKey();
|
||||
}
|
||||
|
||||
void WindowManager::activateQuickKey (int index)
|
||||
{
|
||||
mQuickKeysMenu->activateQuickKey(index);
|
||||
|
|
|
@ -241,7 +241,10 @@ namespace MWGui
|
|||
virtual void setSpellVisibility(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 void setSelectedSpell(const std::string& spellId, int successChancePercent);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/statemanager.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
@ -929,6 +930,9 @@ namespace MWInput
|
|||
inventory.getSelectedEnchantItem() == inventory.end())
|
||||
return;
|
||||
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||
return;
|
||||
|
||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
|
||||
mPlayer->setDrawState(MWMechanics::DrawState_Spell);
|
||||
|
@ -944,6 +948,9 @@ namespace MWInput
|
|||
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
||||
return;
|
||||
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||
return;
|
||||
|
||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
||||
mPlayer->setDrawState(MWMechanics::DrawState_Weapon);
|
||||
|
|
|
@ -1788,6 +1788,16 @@ namespace MWMechanics
|
|||
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()
|
||||
{
|
||||
if (!MWBase::Environment::get().getMechanicsManager()->isAIActive())
|
||||
|
|
|
@ -150,6 +150,7 @@ namespace MWMechanics
|
|||
void clear(); // Clear death counter
|
||||
|
||||
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
|
||||
bool isAttackingOrSpell(const MWWorld::Ptr& ptr) const;
|
||||
|
||||
private:
|
||||
PtrActorMap mActors;
|
||||
|
|
|
@ -2228,6 +2228,12 @@ bool CharacterController::isKnockedOut() const
|
|||
return mHitState == CharState_KnockOut;
|
||||
}
|
||||
|
||||
bool CharacterController::isAttackingOrSpell() const
|
||||
{
|
||||
return mUpperBodyState != UpperCharState_Nothing &&
|
||||
mUpperBodyState != UpperCharState_WeapEquiped;
|
||||
}
|
||||
|
||||
bool CharacterController::isSneaking() const
|
||||
{
|
||||
return mIdleState == CharState_IdleSneak ||
|
||||
|
|
|
@ -267,6 +267,7 @@ public:
|
|||
bool isKnockedOut() const;
|
||||
bool isSneaking() const;
|
||||
bool isRunning() const;
|
||||
bool isAttackingOrSpell() const;
|
||||
|
||||
void setAttackingOrSpell(bool attackingOrSpell);
|
||||
void setAIAttackType(const std::string& attackType);
|
||||
|
|
|
@ -1591,6 +1591,11 @@ namespace MWMechanics
|
|||
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)
|
||||
{
|
||||
MWMechanics::NpcStats& npcStats = actor.getClass().getNpcStats(actor);
|
||||
|
|
|
@ -188,6 +188,8 @@ namespace MWMechanics
|
|||
virtual void keepPlayerAlive();
|
||||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue