Detect crime of sleeping in other NPC's beds. ShowRestMenu needs to support an explicit/implicit reference for this.

actorid
scrawl 11 years ago
parent b99ca92fee
commit 7b33f6f2ac

@ -104,13 +104,17 @@ namespace MWBase
* @brief Commit a crime. If any actors witness the crime and report it,
* reportCrime will be called automatically.
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
* @return was the crime reported?
*/
virtual void commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
virtual bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0;
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0;
/// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
/// @return was it illegal, and someone saw you doing it?
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
enum PersuasionType
{

@ -16,6 +16,27 @@
#include "spellcasting.hpp"
namespace
{
/// @return is \a ptr allowed to take/use \a item or is it a crime?
bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item)
{
const std::string& owner = item.getCellRef().mOwner;
bool isOwned = !owner.empty();
const std::string& faction = item.getCellRef().mFaction;
bool isFactionOwned = false;
if (!faction.empty())
{
const std::map<std::string, int>& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks();
if (factions.find(Misc::StringUtils::lowerCase(faction)) == factions.end())
isFactionOwned = true;
}
return (!isOwned && !isFactionOwned);
}
}
namespace MWMechanics
{
void MechanicsManager::buildPlayer()
@ -729,33 +750,35 @@ namespace MWMechanics
return mAI;
}
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, int count)
bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed)
{
const std::string& owner = item.getCellRef().mOwner;
bool isOwned = !owner.empty();
if (isAllowedToUse(ptr, bed))
return false;
MWWorld::Ptr victim;
if (!bed.getCellRef().mOwner.empty())
victim = MWBase::Environment::get().getWorld()->getPtr(bed.getCellRef().mOwner, true);
const std::string& faction = item.getCellRef().mFaction;
bool isFactionOwned = false;
if (!faction.empty())
if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
{
const std::map<std::string, int>& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks();
if (factions.find(Misc::StringUtils::lowerCase(faction)) == factions.end())
isFactionOwned = true;
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage64}");
return true;
}
else
return false;
}
if (!isOwned && !isFactionOwned)
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, int count)
{
if (isAllowedToUse(ptr, item))
return;
MWWorld::Ptr victim;
if (!owner.empty())
victim = MWBase::Environment::get().getWorld()->getPtr(owner, true);
// TODO: expell from faction
if (!item.getCellRef().mOwner.empty())
victim = MWBase::Environment::get().getWorld()->getPtr(item.getCellRef().mOwner, true);
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
}
void MechanicsManager::commitCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg)
bool MechanicsManager::commitCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg)
{
// TODO: expell from faction
@ -787,6 +810,7 @@ namespace MWMechanics
if (reported)
reportCrime(ptr, victim, type, arg);
return reported;
}
void MechanicsManager::reportCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg)

@ -105,13 +105,17 @@ namespace MWMechanics
* @brief Commit a crime. If any actors witness the crime and report it,
* reportCrime will be called automatically.
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
* @return was the crime reported?
*/
virtual void commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
virtual bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0);
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0);
/// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count);
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
/// @return was it illegal, and someone saw you doing it?
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed);
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);

@ -371,4 +371,6 @@ op 0x2000230: Resurrect, explicit
op 0x2000231: GetSpellReadied
op 0x2000232: GetSpellReadied, explicit
op 0x2000233: GetPcJumping
opcodes 0x2000234-0x3ffffff unused
op 0x2000234: ShowRestMenu, explicit
opcodes 0x2000235-0x3ffffff unused

@ -11,11 +11,15 @@
#include <components/interpreter/opcodes.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
namespace MWScript
{
@ -45,6 +49,27 @@ namespace MWScript
}
};
template <class R>
class OpShowRestMenu : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
// FIXME: No way to tell if we have a reference before trying to get it, and it will
// cause an exception is there isn't one :(
MWWorld::Ptr bed;
try {
bed = R()(runtime);
}
catch(std::runtime_error&) {
}
if (bed.isEmpty() || !MWBase::Environment::get().getMechanicsManager()->sleepInBed(MWBase::Environment::get().getWorld()->getPlayer().getPlayer(),
bed))
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_RestBed);
}
};
class OpShowDialogue : public Interpreter::Opcode0
{
MWGui::GuiMode mDialogue;
@ -172,7 +197,8 @@ namespace MWScript
new OpEnableRest ());
interpreter.installSegment5 (Compiler::Gui::opcodeShowRestMenu,
new OpShowDialogue (MWGui::GM_RestBed));
new OpShowRestMenu<ImplicitRef>);
interpreter.installSegment5 (Compiler::Gui::opcodeShowRestMenuExplicit, new OpShowRestMenu<ExplicitRef>);
interpreter.installSegment5 (Compiler::Gui::opcodeGetButtonPressed, new OpGetButtonPressed);

@ -198,7 +198,7 @@ namespace Compiler
extensions.registerInstruction ("enablerest", "", opcodeEnableRest);
extensions.registerInstruction ("enablelevelupmenu", "", opcodeEnableRest);
extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu);
extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu, opcodeShowRestMenuExplicit);
extensions.registerFunction ("getbuttonpressed", 'l', "", opcodeGetButtonPressed);

@ -161,6 +161,7 @@ namespace Compiler
const int opcodeEnableStatsMenu = 0x2000016;
const int opcodeEnableRest = 0x2000017;
const int opcodeShowRestMenu = 0x2000018;
const int opcodeShowRestMenuExplicit = 0x2000234;
const int opcodeGetButtonPressed = 0x2000137;
const int opcodeToggleFogOfWar = 0x2000145;
const int opcodeToggleFullHelp = 0x2000151;

Loading…
Cancel
Save