forked from teamnwah/openmw-tes3coop
		
	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,
 | 
			
		||||
             *        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool MechanicsManager::sleepInBed(const MWWorld::Ptr &ptr, const MWWorld::Ptr &bed)
 | 
			
		||||
    {
 | 
			
		||||
        if (isAllowedToUse(ptr, bed))
 | 
			
		||||
            return false;
 | 
			
		||||
        MWWorld::Ptr victim;
 | 
			
		||||
        if (!bed.getCellRef().mOwner.empty())
 | 
			
		||||
            victim = MWBase::Environment::get().getWorld()->getPtr(bed.getCellRef().mOwner, true);
 | 
			
		||||
 | 
			
		||||
        if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
 | 
			
		||||
        {
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage64}");
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, int count)
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!isOwned && !isFactionOwned)
 | 
			
		||||
        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…
	
		Reference in a new issue