@ -2,6 +2,8 @@
# include "mechanicsmanagerimp.hpp"
# include "mechanicsmanagerimp.hpp"
# include "npcstats.hpp"
# include "npcstats.hpp"
# include <components/esm/stolenitems.hpp>
# include "../mwworld/esmstore.hpp"
# include "../mwworld/esmstore.hpp"
# include "../mwworld/inventorystore.hpp"
# include "../mwworld/inventorystore.hpp"
@ -873,31 +875,31 @@ namespace MWMechanics
mAI = true ;
mAI = true ;
}
}
bool MechanicsManager : : isAllowedToUse ( const MWWorld : : Ptr & ptr , const MWWorld : : Ptr& item , MWWorld : : Ptr & victim )
bool MechanicsManager : : isAllowedToUse ( const MWWorld : : Ptr & ptr , const MWWorld : : CellRef& cellref , MWWorld : : Ptr & victim )
{
{
const std : : string & owner = item. getCellRef ( ) . getOwner ( ) ;
const std : : string & owner = cellref . getOwner ( ) ;
bool isOwned = ! owner . empty ( ) & & owner ! = " player " ;
bool isOwned = ! owner . empty ( ) & & owner ! = " player " ;
const std : : string & faction = item. getCellRef ( ) . getFaction ( ) ;
const std : : string & faction = cellref . getFaction ( ) ;
bool isFactionOwned = false ;
bool isFactionOwned = false ;
if ( ! faction . empty ( ) & & ptr . getClass ( ) . isNpc ( ) )
if ( ! faction . empty ( ) & & ptr . getClass ( ) . isNpc ( ) )
{
{
const std : : map < std : : string , int > & factions = ptr . getClass ( ) . getNpcStats ( ptr ) . getFactionRanks ( ) ;
const std : : map < std : : string , int > & factions = ptr . getClass ( ) . getNpcStats ( ptr ) . getFactionRanks ( ) ;
std : : map < std : : string , int > : : const_iterator found = factions . find ( Misc : : StringUtils : : lowerCase ( faction ) ) ;
std : : map < std : : string , int > : : const_iterator found = factions . find ( Misc : : StringUtils : : lowerCase ( faction ) ) ;
if ( found = = factions . end ( )
if ( found = = factions . end ( )
| | found - > second < item. getCellRef ( ) . getFactionRank ( ) )
| | found - > second < cellref . getFactionRank ( ) )
isFactionOwned = true ;
isFactionOwned = true ;
}
}
const std : : string & globalVariable = item. getCellRef ( ) . getGlobalVariable ( ) ;
const std : : string & globalVariable = cellref . getGlobalVariable ( ) ;
if ( ! globalVariable . empty ( ) & & MWBase : : Environment : : get ( ) . getWorld ( ) - > getGlobalInt ( Misc : : StringUtils : : lowerCase ( globalVariable ) ) = = 1 )
if ( ! globalVariable . empty ( ) & & MWBase : : Environment : : get ( ) . getWorld ( ) - > getGlobalInt ( Misc : : StringUtils : : lowerCase ( globalVariable ) ) = = 1 )
{
{
isOwned = false ;
isOwned = false ;
isFactionOwned = false ;
isFactionOwned = false ;
}
}
if ( ! item. getCellRef ( ) . getOwner ( ) . empty ( ) )
if ( ! cellref . getOwner ( ) . empty ( ) )
victim = MWBase : : Environment : : get ( ) . getWorld ( ) - > searchPtr ( item. getCellRef ( ) . getOwner ( ) , true ) ;
victim = MWBase : : Environment : : get ( ) . getWorld ( ) - > searchPtr ( cellref . getOwner ( ) , true ) ;
return ( ! isOwned & & ! isFactionOwned ) ;
return ( ! isOwned & & ! isFactionOwned ) ;
}
}
@ -916,7 +918,7 @@ namespace MWMechanics
}
}
MWWorld : : Ptr victim ;
MWWorld : : Ptr victim ;
if ( isAllowedToUse ( ptr , bed , victim ) )
if ( isAllowedToUse ( ptr , bed .getCellRef ( ) , victim ) )
return false ;
return false ;
if ( commitCrime ( ptr , victim , OT_SleepingInOwnedBed ) )
if ( commitCrime ( ptr , victim , OT_SleepingInOwnedBed ) )
@ -931,27 +933,82 @@ namespace MWMechanics
void MechanicsManager : : objectOpened ( const MWWorld : : Ptr & ptr , const MWWorld : : Ptr & item )
void MechanicsManager : : objectOpened ( const MWWorld : : Ptr & ptr , const MWWorld : : Ptr & item )
{
{
MWWorld : : Ptr victim ;
MWWorld : : Ptr victim ;
if ( isAllowedToUse ( ptr , item , victim ) )
if ( isAllowedToUse ( ptr , item .getCellRef ( ) , victim ) )
return ;
return ;
commitCrime ( ptr , victim , OT_Trespassing ) ;
commitCrime ( ptr , victim , OT_Trespassing ) ;
}
}
std : : vector < std : : pair < std : : string , int > > MechanicsManager : : getStolenItemOwners ( const std : : string & itemid )
{
std : : vector < std : : pair < std : : string , int > > result ;
StolenItemsMap : : const_iterator it = mStolenItems . find ( Misc : : StringUtils : : lowerCase ( itemid ) ) ;
if ( it = = mStolenItems . end ( ) )
return result ;
else
{
const OwnerMap & owners = it - > second ;
for ( OwnerMap : : const_iterator ownerIt = owners . begin ( ) ; ownerIt ! = owners . end ( ) ; + + ownerIt )
result . push_back ( std : : make_pair ( ownerIt - > first . first , ownerIt - > second ) ) ;
return result ;
}
}
bool MechanicsManager : : isItemStolenFrom ( const std : : string & itemid , const std : : string & ownerid )
{
StolenItemsMap : : const_iterator it = mStolenItems . find ( Misc : : StringUtils : : lowerCase ( itemid ) ) ;
if ( it = = mStolenItems . end ( ) )
return false ;
const OwnerMap & owners = it - > second ;
OwnerMap : : const_iterator ownerFound = owners . find ( std : : make_pair ( Misc : : StringUtils : : lowerCase ( ownerid ) , false ) ) ;
return ownerFound ! = owners . end ( ) ;
}
void MechanicsManager : : confiscateStolenItems ( const MWWorld : : Ptr & player , const MWWorld : : Ptr & targetContainer )
{
MWWorld : : ContainerStore & store = player . getClass ( ) . getContainerStore ( player ) ;
for ( MWWorld : : ContainerStoreIterator it = store . begin ( ) ; it ! = store . end ( ) ; + + it )
{
StolenItemsMap : : iterator stolenIt = mStolenItems . find ( Misc : : StringUtils : : lowerCase ( it - > getClass ( ) . getId ( * it ) ) ) ;
if ( stolenIt = = mStolenItems . end ( ) )
continue ;
OwnerMap & owners = stolenIt - > second ;
int itemCount = it - > getRefData ( ) . getCount ( ) ;
for ( OwnerMap : : iterator ownerIt = owners . begin ( ) ; ownerIt ! = owners . end ( ) ; )
{
int toRemove = std : : min ( itemCount , ownerIt - > second ) ;
itemCount - = toRemove ;
ownerIt - > second - = toRemove ;
if ( ownerIt - > second = = 0 )
owners . erase ( ownerIt + + ) ;
else
+ + ownerIt ;
}
int toMove = it - > getRefData ( ) . getCount ( ) - itemCount ;
targetContainer . getClass ( ) . getContainerStore ( targetContainer ) . add ( * it , toMove , targetContainer ) ;
store . remove ( * it , toMove , player ) ;
}
// TODO: unhardcode the locklevel
targetContainer . getClass ( ) . lock ( targetContainer , 50 ) ;
}
void MechanicsManager : : itemTaken ( const MWWorld : : Ptr & ptr , const MWWorld : : Ptr & item , const MWWorld : : Ptr & container ,
void MechanicsManager : : itemTaken ( const MWWorld : : Ptr & ptr , const MWWorld : : Ptr & item , const MWWorld : : Ptr & container ,
int count )
int count )
{
{
if ( ptr ! = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) )
return ;
MWWorld : : Ptr victim ;
MWWorld : : Ptr victim ;
const MWWorld : : CellRef * ownerCellRef = & item . getCellRef ( ) ;
if ( ! container . isEmpty ( ) )
if ( ! container . isEmpty ( ) )
{
{
// Inherit the owner of the container
// Inherit the owner of the container
if ( isAllowedToUse ( ptr , container , victim ) )
ownerCellRef = & container . getCellRef ( ) ;
return ;
}
}
else
else
{
{
if ( isAllowedToUse ( ptr , item , victim ) )
return ;
if ( ! item . getCellRef ( ) . hasContentFile ( ) )
if ( ! item . getCellRef ( ) . hasContentFile ( ) )
{
{
// this is a manually placed item, which means it was already stolen
// this is a manually placed item, which means it was already stolen
@ -959,6 +1016,20 @@ namespace MWMechanics
}
}
}
}
if ( isAllowedToUse ( ptr , * ownerCellRef , victim ) )
return ;
Owner owner ;
owner . first = ownerCellRef - > getOwner ( ) ;
owner . second = false ;
if ( owner . first . empty ( ) )
{
owner . first = ownerCellRef - > getFaction ( ) ;
owner . second = true ;
}
Misc : : StringUtils : : toLower ( owner . first ) ;
mStolenItems [ Misc : : StringUtils : : lowerCase ( item . getClass ( ) . getId ( item ) ) ] [ owner ] + = count ;
commitCrime ( ptr , victim , OT_Theft , item . getClass ( ) . getValue ( item ) * count ) ;
commitCrime ( ptr , victim , OT_Theft , item . getClass ( ) . getValue ( item ) * count ) ;
}
}
@ -967,7 +1038,7 @@ namespace MWMechanics
// NOTE: victim may be empty
// NOTE: victim may be empty
// Only player can commit crime
// Only player can commit crime
if ( player . getRefData ( ) . getHandle ( ) ! = " player " )
if ( player ! = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) )
return false ;
return false ;
// Find all the actors within the alarm radius
// Find all the actors within the alarm radius
@ -1369,22 +1440,37 @@ namespace MWMechanics
int MechanicsManager : : countSavedGameRecords ( ) const
int MechanicsManager : : countSavedGameRecords ( ) const
{
{
return 1 ; // Death counter
return 1 // Death counter
+ 1 ; // Stolen items
}
}
void MechanicsManager : : write ( ESM : : ESMWriter & writer , Loading : : Listener & listener ) const
void MechanicsManager : : write ( ESM : : ESMWriter & writer , Loading : : Listener & listener ) const
{
{
mActors . write ( writer , listener ) ;
mActors . write ( writer , listener ) ;
ESM : : StolenItems items ;
items . mStolenItems = mStolenItems ;
writer . startRecord ( ESM : : REC_STLN ) ;
items . write ( writer ) ;
writer . endRecord ( ESM : : REC_STLN ) ;
}
}
void MechanicsManager : : readRecord ( ESM : : ESMReader & reader , uint32_t type )
void MechanicsManager : : readRecord ( ESM : : ESMReader & reader , uint32_t type )
{
{
if ( type = = ESM : : REC_STLN )
{
ESM : : StolenItems items ;
items . load ( reader ) ;
mStolenItems = items . mStolenItems ;
}
else
mActors . readRecord ( reader , type ) ;
mActors . readRecord ( reader , type ) ;
}
}
void MechanicsManager : : clear ( )
void MechanicsManager : : clear ( )
{
{
mActors . clear ( ) ;
mActors . clear ( ) ;
mStolenItems . clear ( ) ;
}
}
bool MechanicsManager : : isAggressive ( const MWWorld : : Ptr & ptr , const MWWorld : : Ptr & target )
bool MechanicsManager : : isAggressive ( const MWWorld : : Ptr & ptr , const MWWorld : : Ptr & target )