mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-31 12:36:40 +00:00
Merge pull request #1428 from akortunov/stancechangefixes
[Feedback needed] Stance switching changes, part II
This commit is contained in:
commit
7a79ebb713
16 changed files with 80 additions and 4 deletions
|
@ -247,6 +247,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0;
|
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0;
|
||||||
|
|
||||||
|
virtual bool isAttackPrepairing(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual bool isRunning(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isRunning(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <components/esm/loadlock.hpp>
|
#include <components/esm/loadlock.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"
|
||||||
|
|
||||||
|
@ -155,6 +156,16 @@ namespace MWClass
|
||||||
return MWWorld::Ptr(cell.insert(ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<int, std::string> Lockpick::canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const
|
||||||
|
{
|
||||||
|
// Do not allow equip tools from inventory during attack
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(npc)
|
||||||
|
&& MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
return std::make_pair(0, "#{sCantEquipWeapWarning}");
|
||||||
|
|
||||||
|
return std::make_pair(1, "");
|
||||||
|
}
|
||||||
|
|
||||||
bool Lockpick::canSell (const MWWorld::ConstPtr& item, int npcServices) const
|
bool Lockpick::canSell (const MWWorld::ConstPtr& item, int npcServices) const
|
||||||
{
|
{
|
||||||
return (npcServices & ESM::NPC::Picks) != 0;
|
return (npcServices & ESM::NPC::Picks) != 0;
|
||||||
|
|
|
@ -51,6 +51,8 @@ namespace MWClass
|
||||||
virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const;
|
virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const;
|
||||||
///< Return name of inventory icon.
|
///< Return name of inventory icon.
|
||||||
|
|
||||||
|
virtual std::pair<int, std::string> canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const;
|
||||||
|
|
||||||
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
|
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
|
||||||
const;
|
const;
|
||||||
///< Generate action for using via inventory menu
|
///< Generate action for using via inventory menu
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <components/esm/loadprob.hpp>
|
#include <components/esm/loadprob.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"
|
||||||
|
|
||||||
|
@ -155,6 +156,16 @@ namespace MWClass
|
||||||
return MWWorld::Ptr(cell.insert(ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<int, std::string> Probe::canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const
|
||||||
|
{
|
||||||
|
// Do not allow equip tools from inventory during attack
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(npc)
|
||||||
|
&& MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
return std::make_pair(0, "#{sCantEquipWeapWarning}");
|
||||||
|
|
||||||
|
return std::make_pair(1, "");
|
||||||
|
}
|
||||||
|
|
||||||
bool Probe::canSell (const MWWorld::ConstPtr& item, int npcServices) const
|
bool Probe::canSell (const MWWorld::ConstPtr& item, int npcServices) const
|
||||||
{
|
{
|
||||||
return (npcServices & ESM::NPC::Probes) != 0;
|
return (npcServices & ESM::NPC::Probes) != 0;
|
||||||
|
|
|
@ -51,6 +51,8 @@ namespace MWClass
|
||||||
virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const;
|
virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const;
|
||||||
///< Return name of inventory icon.
|
///< Return name of inventory icon.
|
||||||
|
|
||||||
|
virtual std::pair<int, std::string> canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const;
|
||||||
|
|
||||||
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
|
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
|
||||||
const;
|
const;
|
||||||
///< Generate action for using via inventory menu
|
///< Generate action for using via inventory menu
|
||||||
|
|
|
@ -374,7 +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))
|
// Do not allow equip weapons from inventory during attack
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(npc)
|
||||||
|
&& MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
return std::make_pair(0, "#{sCantEquipWeapWarning}");
|
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);
|
||||||
|
|
|
@ -255,6 +255,19 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we unequip weapon during attack, it can lead to unexpected behaviour
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPtr))
|
||||||
|
{
|
||||||
|
bool isWeapon = item.mBase.getTypeName() == typeid(ESM::Weapon).name();
|
||||||
|
MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr);
|
||||||
|
|
||||||
|
if (isWeapon && invStore.isEquipped(item.mBase))
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sCantEquipWeapWarning}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count > 1 && !shift)
|
if (count > 1 && !shift)
|
||||||
{
|
{
|
||||||
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
|
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
|
||||||
|
|
|
@ -344,16 +344,17 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
MWWorld::Ptr item = *button->getUserData<MWWorld::Ptr>();
|
||||||
bool isWeapon = item.getTypeName() == typeid(ESM::Weapon).name();
|
bool isWeapon = item.getTypeName() == typeid(ESM::Weapon).name();
|
||||||
|
bool isTool = item.getTypeName() == typeid(ESM::Probe).name() || item.getTypeName() == typeid(ESM::Lockpick).name();
|
||||||
|
|
||||||
// delay weapon switching if player is busy
|
// delay weapon switching if player is busy
|
||||||
if (isDelayNeeded && isWeapon)
|
if (isDelayNeeded && (isWeapon || isTool))
|
||||||
{
|
{
|
||||||
mActivatedIndex = index;
|
mActivatedIndex = index;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable weapon switching if player is dead or paralyzed
|
// disable weapon switching if player is dead or paralyzed
|
||||||
if (isReturnNeeded && isWeapon)
|
if (isReturnNeeded && (isWeapon || isTool))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -948,7 +948,11 @@ namespace MWInput
|
||||||
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
// We want to interrupt animation only if attack is prepairing, but still is not triggered
|
||||||
|
// Otherwise we will get a "speedshooting" exploit, when player can skip reload animation by hitting "Toggle Weapon" key twice
|
||||||
|
if (MWBase::Environment::get().getMechanicsManager()->isAttackPrepairing(mPlayer->getPlayer()))
|
||||||
|
mPlayer->setAttackingOrSpell(false);
|
||||||
|
else if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
MWMechanics::DrawState_ state = mPlayer->getDrawState();
|
||||||
|
|
|
@ -802,6 +802,16 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Actors::isAttackPrepairing(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
PtrActorMap::iterator it = mActors.find(ptr);
|
||||||
|
if (it == mActors.end())
|
||||||
|
return false;
|
||||||
|
CharacterController* ctrl = it->second->getCharacterController();
|
||||||
|
|
||||||
|
return ctrl->isAttackPrepairing();
|
||||||
|
}
|
||||||
|
|
||||||
bool Actors::isRunning(const MWWorld::Ptr& ptr)
|
bool Actors::isRunning(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
PtrActorMap::iterator it = mActors.find(ptr);
|
PtrActorMap::iterator it = mActors.find(ptr);
|
||||||
|
|
|
@ -107,6 +107,7 @@ namespace MWMechanics
|
||||||
int countDeaths (const std::string& id) const;
|
int countDeaths (const std::string& id) const;
|
||||||
///< Return the number of deaths for actors with the given ID.
|
///< Return the number of deaths for actors with the given ID.
|
||||||
|
|
||||||
|
bool isAttackPrepairing(const MWWorld::Ptr& ptr);
|
||||||
bool isRunning(const MWWorld::Ptr& ptr);
|
bool isRunning(const MWWorld::Ptr& ptr);
|
||||||
bool isSneaking(const MWWorld::Ptr& ptr);
|
bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
|
|
@ -2218,6 +2218,12 @@ void CharacterController::setAttackTypeBasedOnMovement()
|
||||||
mAttackType = "chop";
|
mAttackType = "chop";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CharacterController::isAttackPrepairing() const
|
||||||
|
{
|
||||||
|
return mUpperBodyState == UpperCharState_StartToMinAttack ||
|
||||||
|
mUpperBodyState == UpperCharState_MinAttackToMaxAttack;
|
||||||
|
}
|
||||||
|
|
||||||
bool CharacterController::isReadyToBlock() const
|
bool CharacterController::isReadyToBlock() const
|
||||||
{
|
{
|
||||||
return updateCarriedLeftVisible(mWeaponType);
|
return updateCarriedLeftVisible(mWeaponType);
|
||||||
|
|
|
@ -263,6 +263,7 @@ public:
|
||||||
|
|
||||||
void forceStateUpdate();
|
void forceStateUpdate();
|
||||||
|
|
||||||
|
bool isAttackPrepairing() const;
|
||||||
bool isReadyToBlock() const;
|
bool isReadyToBlock() const;
|
||||||
bool isKnockedOut() const;
|
bool isKnockedOut() const;
|
||||||
bool isSneaking() const;
|
bool isSneaking() const;
|
||||||
|
|
|
@ -423,6 +423,11 @@ namespace MWMechanics
|
||||||
mObjects.update(duration, paused);
|
mObjects.update(duration, paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MechanicsManager::isAttackPrepairing(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
return mActors.isAttackPrepairing(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr)
|
bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
return mActors.isRunning(ptr);
|
return mActors.isRunning(ptr);
|
||||||
|
|
|
@ -210,8 +210,10 @@ namespace MWMechanics
|
||||||
|
|
||||||
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count);
|
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count);
|
||||||
|
|
||||||
|
virtual bool isAttackPrepairing(const MWWorld::Ptr& ptr);
|
||||||
virtual bool isRunning(const MWWorld::Ptr& ptr);
|
virtual bool isRunning(const MWWorld::Ptr& ptr);
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr);
|
virtual bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
||||||
OffenseType type, int arg=0);
|
OffenseType type, int arg=0);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
@ -919,6 +920,9 @@ void NpcAnimation::showWeapons(bool showWeapon)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
removeIndividualPart(ESM::PRT_Weapon);
|
removeIndividualPart(ESM::PRT_Weapon);
|
||||||
|
// If we remove/hide weapon from player, we should reset attack animation as well
|
||||||
|
if (mPtr == MWMechanics::getPlayer())
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setAttackingOrSpell(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue