Make Equip console command to bypass most of restrictions (bug #4460)

pull/457/head
Andrei Kortunov 7 years ago
parent 8834396cdd
commit c77c50e92b

@ -50,6 +50,7 @@
Bug #4457: Item without CanCarry flag prevents shield autoequipping in dark areas
Bug #4458: AiWander console command handles idle chances incorrectly
Bug #4459: NotCell dialogue condition doesn't support partial matches
Bug #4460: Script function "Equip" doesn't bypass beast restrictions
Bug #4461: "Open" spell from non-player caster isn't a crime
Bug #4464: OpenMW keeps AiState cached storages even after we cancel AI packages
Bug #4469: Abot Silt Striders Model turn 90 degrees on horizontal

@ -146,7 +146,7 @@ namespace MWBase
virtual MWGui::TradeWindow* getTradeWindow() = 0;
/// Make the player use an item, while updating GUI state accordingly
virtual void useItem(const MWWorld::Ptr& item) = 0;
virtual void useItem(const MWWorld::Ptr& item, bool force=false) = 0;
virtual void updateSpellWindow() = 0;

@ -124,10 +124,9 @@ namespace MWClass
return info;
}
std::shared_ptr<MWWorld::Action> Apparatus::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Apparatus::use (const MWWorld::Ptr& ptr, bool force) const
{
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionAlchemy());
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionAlchemy(force));
}
MWWorld::Ptr Apparatus::copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const

@ -50,8 +50,7 @@ namespace MWClass
virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const;
///< Return name of inventory icon.
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;

@ -354,9 +354,9 @@ namespace MWClass
return std::make_pair(1,"");
}
std::shared_ptr<MWWorld::Action> Armor::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Armor::use (const MWWorld::Ptr& ptr, bool force) const
{
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr, force));
action->setSound(getUpSoundId(ptr));

@ -73,8 +73,7 @@ namespace MWClass
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. \n
/// Second item in the pair specifies the error message
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;

@ -162,7 +162,7 @@ namespace MWClass
return record->mId;
}
std::shared_ptr<MWWorld::Action> Book::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Book::use (const MWWorld::Ptr& ptr, bool force) const
{
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionRead(ptr));
}

@ -53,7 +53,7 @@ namespace MWClass
virtual std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it.
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;

@ -243,9 +243,9 @@ namespace MWClass
return std::make_pair (1, "");
}
std::shared_ptr<MWWorld::Action> Clothing::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Clothing::use (const MWWorld::Ptr& ptr, bool force) const
{
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr, force));
action->setSound(getUpSoundId(ptr));

@ -65,8 +65,7 @@ namespace MWClass
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that.
/// Second item in the pair specifies the error message
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;

@ -75,7 +75,7 @@ namespace MWClass
}
std::shared_ptr<MWWorld::Action> Ingredient::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Ingredient::use (const MWWorld::Ptr& ptr, bool force) const
{
std::shared_ptr<MWWorld::Action> action (new MWWorld::ActionEat (ptr));

@ -36,8 +36,7 @@ namespace MWClass
virtual int getValue (const MWWorld::ConstPtr& ptr) const;
///< Return trade value of the object. Throws an exception, if the object can't be traded.
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
static void registerSelf();

@ -186,9 +186,9 @@ namespace MWClass
return Class::showsInInventory(ptr);
}
std::shared_ptr<MWWorld::Action> Light::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Light::use (const MWWorld::Ptr& ptr, bool force) const
{
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr, force));
action->setSound(getUpSoundId(ptr));

@ -55,8 +55,7 @@ namespace MWClass
virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const;
///< Return name of inventory icon.
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual void setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const;

@ -140,9 +140,9 @@ namespace MWClass
return info;
}
std::shared_ptr<MWWorld::Action> Lockpick::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Lockpick::use (const MWWorld::Ptr& ptr, bool force) const
{
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr, force));
action->setSound(getUpSoundId(ptr));

@ -53,8 +53,7 @@ namespace MWClass
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)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;

@ -226,7 +226,7 @@ namespace MWClass
return newPtr;
}
std::shared_ptr<MWWorld::Action> Miscellaneous::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Miscellaneous::use (const MWWorld::Ptr& ptr, bool force) const
{
if (ptr.getCellRef().getSoul().empty() || !MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().search(ptr.getCellRef().getSoul()))
return std::shared_ptr<MWWorld::Action>(new MWWorld::NullAction());

@ -49,8 +49,7 @@ namespace MWClass
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual float getWeight (const MWWorld::ConstPtr& ptr) const;

@ -139,7 +139,7 @@ namespace MWClass
return info;
}
std::shared_ptr<MWWorld::Action> Potion::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Potion::use (const MWWorld::Ptr& ptr, bool force) const
{
MWWorld::LiveCellRef<ESM::Potion> *ref =
ptr.get<ESM::Potion>();

@ -36,7 +36,7 @@ namespace MWClass
virtual int getValue (const MWWorld::ConstPtr& ptr) const;
///< Return trade value of the object. Throws an exception, if the object can't be traded.
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
static void registerSelf();

@ -140,9 +140,9 @@ namespace MWClass
return info;
}
std::shared_ptr<MWWorld::Action> Probe::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Probe::use (const MWWorld::Ptr& ptr, bool force) const
{
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr, force));
action->setSound(getUpSoundId(ptr));

@ -53,8 +53,7 @@ namespace MWClass
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)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;

@ -149,9 +149,9 @@ namespace MWClass
return MWWorld::Ptr(cell.insert(ref), &cell);
}
std::shared_ptr<MWWorld::Action> Repair::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Repair::use (const MWWorld::Ptr& ptr, bool force) const
{
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionRepair(ptr));
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionRepair(ptr, force));
}
bool Repair::canSell (const MWWorld::ConstPtr& item, int npcServices) const

@ -49,7 +49,7 @@ namespace MWClass
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false)
const;
///< Generate action for using via inventory menu (default implementation: return a
/// null action).

@ -401,9 +401,9 @@ namespace MWClass
return std::make_pair(1, "");
}
std::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const
std::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr, bool force) const
{
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr));
std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionEquip(ptr, force));
action->setSound(getUpSoundId(ptr));

@ -72,8 +72,7 @@ namespace MWClass
///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that.
/// Second item in the pair specifies the error message
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
virtual std::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr, bool force=false) const;
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::ConstPtr &ptr) const;

@ -25,7 +25,7 @@
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/action.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwscript/interpretercontext.hpp"
#include "../mwmechanics/actorutil.hpp"
@ -474,7 +474,7 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
}
void InventoryWindow::useItem(const MWWorld::Ptr &ptr)
void InventoryWindow::useItem(const MWWorld::Ptr &ptr, bool force)
{
const std::string& script = ptr.getClass().getScript(ptr);
@ -482,8 +482,18 @@ namespace MWGui
// early-out for items that need to be equipped, but can't be equipped: we don't want to set OnPcEquip in that case
if (!ptr.getClass().getEquipmentSlots(ptr).first.empty())
{
if (ptr.getClass().hasItemHealth(ptr) && ptr.getCellRef().getCharge() == 0)
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage1}");
updateItemView();
return;
}
if (!force)
{
std::pair<int, std::string> canEquip = ptr.getClass().canBeEquipped(ptr, player);
if (canEquip.first == 0)
{
MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second);
@ -491,6 +501,7 @@ namespace MWGui
return;
}
}
}
// If the item has a script, set its OnPcEquip to 1
if (!script.empty()
@ -512,8 +523,7 @@ namespace MWGui
{
if (script.empty() || ptr.getRefData().getLocals().getIntVar(script, "pcskipequip") == 0)
{
std::shared_ptr<MWWorld::Action> action = ptr.getClass().use(ptr);
std::shared_ptr<MWWorld::Action> action = ptr.getClass().use(ptr, force);
action->execute(player);
}
else

@ -58,7 +58,7 @@ namespace MWGui
void clear();
void useItem(const MWWorld::Ptr& ptr);
void useItem(const MWWorld::Ptr& ptr, bool force=false);
void setGuiMode(GuiMode mode);

@ -1328,10 +1328,10 @@ namespace MWGui
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; }
void WindowManager::useItem(const MWWorld::Ptr &item)
void WindowManager::useItem(const MWWorld::Ptr &item, bool bypassBeastRestrictions)
{
if (mInventoryWindow)
mInventoryWindow->useItem(item);
mInventoryWindow->useItem(item, bypassBeastRestrictions);
}
bool WindowManager::isAllowed (GuiWindow wnd) const

@ -185,7 +185,7 @@ namespace MWGui
virtual MWGui::TradeWindow* getTradeWindow();
/// Make the player use an item, while updating GUI state accordingly
virtual void useItem(const MWWorld::Ptr& item);
virtual void useItem(const MWWorld::Ptr& item, bool bypassBeastRestrictions=false);
virtual void updateSpellWindow();

@ -20,6 +20,7 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/inventorystore.hpp"
@ -193,12 +194,11 @@ namespace MWScript
"to fulfil requirements of Equip instruction" << std::endl;
}
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
MWBase::Environment::get().getWindowManager()->useItem(*it);
if (ptr == MWMechanics::getPlayer())
MWBase::Environment::get().getWindowManager()->useItem(*it, true);
else
{
std::shared_ptr<MWWorld::Action> action = it->getClass().use(*it);
// No equip sound for actors other than the player
std::shared_ptr<MWWorld::Action> action = it->getClass().use(*it, true);
action->execute(ptr, true);
}
}

@ -9,12 +9,19 @@
namespace MWWorld
{
ActionAlchemy::ActionAlchemy(bool force)
: Action (false)
, mForce(force)
{
}
void ActionAlchemy::executeImp (const Ptr& actor)
{
if (actor != MWMechanics::getPlayer())
return;
if(MWMechanics::isPlayerInCombat()) { //Ensure we're not in combat
if(!mForce && MWMechanics::isPlayerInCombat())
{ //Ensure we're not in combat
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage3}");
return;
}

@ -7,7 +7,11 @@ namespace MWWorld
{
class ActionAlchemy : public Action
{
bool mForce;
virtual void executeImp (const Ptr& actor);
public:
ActionAlchemy(bool force=false);
};
}

@ -14,7 +14,9 @@
namespace MWWorld
{
ActionEquip::ActionEquip (const MWWorld::Ptr& object) : Action (false, object)
ActionEquip::ActionEquip (const MWWorld::Ptr& object, bool force)
: Action (false, object)
, mForce(force)
{
}
@ -23,6 +25,16 @@ namespace MWWorld
MWWorld::Ptr object = getTarget();
MWWorld::InventoryStore& invStore = actor.getClass().getInventoryStore(actor);
if (object.getClass().hasItemHealth(object) && object.getCellRef().getCharge() == 0)
{
if (actor == MWMechanics::getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage1}");
return;
}
if (!mForce)
{
std::pair <int, std::string> result = object.getClass().canBeEquipped (object, actor);
// display error message if the player tried to equip something
@ -36,6 +48,7 @@ namespace MWWorld
default:
break;
}
}
// slots that this item can be equipped in
std::pair<std::vector<int>, bool> slots_ = getTarget().getClass().getEquipmentSlots(getTarget());

@ -2,17 +2,18 @@
#define GAME_MWWORLD_ACTIONEQUIP_H
#include "action.hpp"
#include "ptr.hpp"
namespace MWWorld
{
class ActionEquip : public Action
{
bool mForce;
virtual void executeImp (const Ptr& actor);
public:
/// @param item to equip
ActionEquip (const Ptr& object);
ActionEquip (const Ptr& object, bool force=false);
};
}

@ -8,8 +8,9 @@
namespace MWWorld
{
ActionRepair::ActionRepair(const Ptr &item)
ActionRepair::ActionRepair(const Ptr& item, bool force)
: Action (false, item)
, mForce(force)
{
}
@ -18,7 +19,8 @@ namespace MWWorld
if (actor != MWMechanics::getPlayer())
return;
if(MWMechanics::isPlayerInCombat()) {
if(!mForce && MWMechanics::isPlayerInCombat())
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage2}");
return;
}

@ -7,10 +7,13 @@ namespace MWWorld
{
class ActionRepair : public Action
{
bool mForce;
virtual void executeImp (const Ptr& actor);
public:
ActionRepair(const MWWorld::Ptr& item);
/// @param item repair hammer
ActionRepair(const Ptr& item, bool force=false);
};
}

@ -113,7 +113,7 @@ namespace MWWorld
return std::shared_ptr<Action> (new NullAction);
}
std::shared_ptr<Action> Class::use (const Ptr& ptr) const
std::shared_ptr<Action> Class::use (const Ptr& ptr, bool force) const
{
return std::shared_ptr<Action> (new NullAction);
}

@ -141,7 +141,7 @@ namespace MWWorld
virtual std::shared_ptr<Action> activate (const Ptr& ptr, const Ptr& actor) const;
///< Generate action for activation (default implementation: return a null action).
virtual std::shared_ptr<Action> use (const Ptr& ptr)
virtual std::shared_ptr<Action> use (const Ptr& ptr, bool force=false)
const;
///< Generate action for using via inventory menu (default implementation: return a
/// null action).

Loading…
Cancel
Save