mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 01:45:34 +00:00
Detect crime of sleeping in other NPC's beds. ShowRestMenu needs to support an explicit/implicit reference for this.
This commit is contained in:
parent
b99ca92fee
commit
7b33f6f2ac
7 changed files with 85 additions and 24 deletions
|
@ -104,13 +104,17 @@ namespace MWBase
|
||||||
* @brief Commit a crime. If any actors witness the crime and report it,
|
* @brief Commit a crime. If any actors witness the crime and report it,
|
||||||
* reportCrime will be called automatically.
|
* reportCrime will be called automatically.
|
||||||
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
|
* @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;
|
OffenseType type, int arg=0) = 0;
|
||||||
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
||||||
OffenseType type, int arg=0) = 0;
|
OffenseType type, int arg=0) = 0;
|
||||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
/// 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;
|
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
|
enum PersuasionType
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,27 @@
|
||||||
|
|
||||||
#include "spellcasting.hpp"
|
#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
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
void MechanicsManager::buildPlayer()
|
void MechanicsManager::buildPlayer()
|
||||||
|
@ -729,33 +750,35 @@ namespace MWMechanics
|
||||||
return mAI;
|
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;
|
if (isAllowedToUse(ptr, bed))
|
||||||
bool isOwned = !owner.empty();
|
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;
|
if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
|
||||||
bool isFactionOwned = false;
|
|
||||||
if (!faction.empty())
|
|
||||||
{
|
{
|
||||||
const std::map<std::string, int>& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks();
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage64}");
|
||||||
if (factions.find(Misc::StringUtils::lowerCase(faction)) == factions.end())
|
return true;
|
||||||
isFactionOwned = 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;
|
return;
|
||||||
|
|
||||||
MWWorld::Ptr victim;
|
MWWorld::Ptr victim;
|
||||||
if (!owner.empty())
|
if (!item.getCellRef().mOwner.empty())
|
||||||
victim = MWBase::Environment::get().getWorld()->getPtr(owner, true);
|
victim = MWBase::Environment::get().getWorld()->getPtr(item.getCellRef().mOwner, true);
|
||||||
|
|
||||||
// TODO: expell from faction
|
|
||||||
|
|
||||||
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
|
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
|
// TODO: expell from faction
|
||||||
|
|
||||||
|
@ -787,6 +810,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (reported)
|
if (reported)
|
||||||
reportCrime(ptr, victim, type, arg);
|
reportCrime(ptr, victim, type, arg);
|
||||||
|
return reported;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MechanicsManager::reportCrime(const MWWorld::Ptr &ptr, const MWWorld::Ptr &victim, OffenseType type, int arg)
|
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,
|
* @brief Commit a crime. If any actors witness the crime and report it,
|
||||||
* reportCrime will be called automatically.
|
* reportCrime will be called automatically.
|
||||||
* @param arg Depends on \a type, e.g. for Theft, the value of the item that was stolen.
|
* @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);
|
OffenseType type, int arg=0);
|
||||||
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
||||||
OffenseType type, int arg=0);
|
OffenseType type, int arg=0);
|
||||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
/// 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);
|
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);
|
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
|
|
|
@ -371,4 +371,6 @@ op 0x2000230: Resurrect, explicit
|
||||||
op 0x2000231: GetSpellReadied
|
op 0x2000231: GetSpellReadied
|
||||||
op 0x2000232: GetSpellReadied, explicit
|
op 0x2000232: GetSpellReadied, explicit
|
||||||
op 0x2000233: GetPcJumping
|
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 <components/interpreter/opcodes.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
#include "interpretercontext.hpp"
|
#include "interpretercontext.hpp"
|
||||||
|
#include "ref.hpp"
|
||||||
|
|
||||||
namespace MWScript
|
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
|
class OpShowDialogue : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
MWGui::GuiMode mDialogue;
|
MWGui::GuiMode mDialogue;
|
||||||
|
@ -172,7 +197,8 @@ namespace MWScript
|
||||||
new OpEnableRest ());
|
new OpEnableRest ());
|
||||||
|
|
||||||
interpreter.installSegment5 (Compiler::Gui::opcodeShowRestMenu,
|
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);
|
interpreter.installSegment5 (Compiler::Gui::opcodeGetButtonPressed, new OpGetButtonPressed);
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,7 @@ namespace Compiler
|
||||||
extensions.registerInstruction ("enablerest", "", opcodeEnableRest);
|
extensions.registerInstruction ("enablerest", "", opcodeEnableRest);
|
||||||
extensions.registerInstruction ("enablelevelupmenu", "", opcodeEnableRest);
|
extensions.registerInstruction ("enablelevelupmenu", "", opcodeEnableRest);
|
||||||
|
|
||||||
extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu);
|
extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu, opcodeShowRestMenuExplicit);
|
||||||
|
|
||||||
extensions.registerFunction ("getbuttonpressed", 'l', "", opcodeGetButtonPressed);
|
extensions.registerFunction ("getbuttonpressed", 'l', "", opcodeGetButtonPressed);
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,7 @@ namespace Compiler
|
||||||
const int opcodeEnableStatsMenu = 0x2000016;
|
const int opcodeEnableStatsMenu = 0x2000016;
|
||||||
const int opcodeEnableRest = 0x2000017;
|
const int opcodeEnableRest = 0x2000017;
|
||||||
const int opcodeShowRestMenu = 0x2000018;
|
const int opcodeShowRestMenu = 0x2000018;
|
||||||
|
const int opcodeShowRestMenuExplicit = 0x2000234;
|
||||||
const int opcodeGetButtonPressed = 0x2000137;
|
const int opcodeGetButtonPressed = 0x2000137;
|
||||||
const int opcodeToggleFogOfWar = 0x2000145;
|
const int opcodeToggleFogOfWar = 0x2000145;
|
||||||
const int opcodeToggleFullHelp = 0x2000151;
|
const int opcodeToggleFullHelp = 0x2000151;
|
||||||
|
|
Loading…
Reference in a new issue