Morrowind Mod:XGetOwnerInfo

The UESPWiki – Your source for The Elder Scrolls since 1995

A function from the MWSE update by Merzasphor.

Ownership of entities in the world in Morrowind is comprised of two parts: owner and condition (this can specify when the player being detected taking or using the entity is not considered a crime). These work in two modes:
The first is where owner is an NPC id, and condition is a global variable - while the global var is set to a non-zero value, activating the entity is never considered a crime.
In the second mode, owner is a faction id, and condition is a rank within it. If the player has equal (or higher) rank in that faction, then he can be seen using or taking the entity without it being a crime. This is how Supply Chests and beds in guildhalls work (their rank requirement is the minimal rank).

This function allows getting full ownership information of an entity: both parts, whatever they may be (as well as what mode is used for the ownership). It is more in-depth than the xGetOwner function, which does not fully handle faction ownership or ownership with a global var requirement.

Syntax and usage[edit]

This function is to be used on a reference, and has 3 return values, all of type long:

type (long) id (long) rankVar (long): ref->xGetOwnerInfo

type: distinguishes between the two ownership modes - the value is the internal game type of the owner record and is one of the following: NPC owner = 1598246990, faction owner = 1413693766 or is 0 if there is no owner.
id: the id string of the owner (an NPC id or a faction id), or 0 if there is no owner.
rankVar: a rank or a global var. If the owner is a faction, this is the required rank (in numerical format, same as the return value of GetPCRank). If the owner is an NPC, this is a string ref to the associated global variable (to be used with xGet/SetGlobal), and 0 if there is no such variable.

Examples[edit]

Boobytrapped Mages Guild and Telvanni faction containers[edit]

begin boobycontainers
;if the player tries to open a container owned by either MG or GHT that he
;doesn't have the required rank to legally take items from, then instead of
;the container opening, the player will be zapped.

short framecount
short temp
short player_rank
long pctarget
long type
long own_id
long own_cond

if ( MenuMode )
	return
endif

set framecount to ( framecount + 1 )
if ( framecount < 30 )
	return
endif
set framecount to 0

setx pctarget to xGetPCTarget
ifx ( pctarget )
	setx type to pctarget->xRefType
	if ( type != 1414418243 ) ;if it's not a container ref type
		return
	endif
	setx type own_id own_cond to pctarget->xGetOwnerInfo
	if ( type != 1413693766 ) ;if it's not a faction ownership type
		return
	endif

	setx temp to xStringCompare own_id "Mages Guild" ;if the owner of the container is MG, temp will be 0
	ifx ( temp ) ;not MG
		setx temp to xStringCompare own_id "Telvanni"
		ifx ( temp )
			;owner is not MG and not GHT, either
			return
		endif
		;owner is GHT
		set player_rank to GetPCRank "Telvanni" ;doesn't hurt here, but remember 0 and -1 are both possible return values of this function
	else
		;owner is MG
		set player_rank to GetPCRank "Mages Guild"
	endif

	set temp to 0
	if ( player_rank >= own_cond ) ;player is of the right rank in whichever faction to be able to claim the container's contents
		set temp to 1
	endif
	ifx ( temp )
		;originally, there was only a return here.
		;the following block is needed in case activation was already blocked by the OnActivate call (the 2nd instance of it, now) on a previous run, but the player since raised in rank enough; without this line, the player will no longer get the trap, but the container may not open (as it normally should), either
		xSetRef pctarget
		set temp to OnActivate
		ifx ( temp )
			pctarget->Activate
		endif
		return
	endif

	;if reached here, player doesn't meet rank requirement
	xSetRef pctarget
	if ( OnActivate ) ;merely CALLING this function will block any further normal activation attempts. it makes the object's activation temporarily only possible through the Activate function
		MessageBox "A trap is sprung!"
		set temp to - ( player->GetFatigue + 1 )
		player->ModCurrentFatigue temp ;makes player fall down ("knocked out") briefly - causes current fatigue to be -1
		player->PlaySound "destruction hit"
	endif
endif

end

World entity destruction with ownership penalty[edit]

begin entitydestruction

;allows the player to destroy objects in the world by striking at them with
;a weapon (or barehanded). but if the player wouldn't have been (legally) allowed to pick up that
;object, he gets a bounty as if he stole it (with respect to the GMST that controls the bounty amount for theft).

;the value of containers is assumed to be only the value of all the items within them.
;the value of doors is assumed to be 100 septims, and of activators, 200 septims.

;this script doesn't take into account whether player is detected (sneaking, invisible),
;etc. well, he's doing a loud and incriminating action, anyway.
;it doesn't do faction expulsion, either...

short framecount
short update_col
long temp
long pctarget
long type
long value
long nextref
long invvalue
long invcount
long ownerid
long condition
float glob
;note: in this script, existing vars are often reused, so that a bunch of
;vars are also used for other purposes than their name suggests.

;for example, because it is the only float and there's no problem with
;overwriting it, 'glob' is used to (temporarily) hold both the result of
;a reading of a global var, and also of reading a float GMST. 


if ( MenuMode )
	return
endif

set framecount to ( framecount + 1 )
if ( framecount < timing1 )
	return
endif
set framecount to 0

if ( player->GetWeaponDrawn == 0 )
	return
endif

if ( player->GetWeaponType == 0 )
	return ;ignore lockpicks and probes; unfortuantely this also applies to Short Blades...
endif

setx temp to xKeyPressed 1 ;left mouse button
setx pctarget to xGetPCTarget

setx temp to xAnd temp pctarget;if player looking at something AND pressing LMB, temp will be 1

if ( temp == 0 )
	return
endif

;you should also be able to just use 'if ( player->GetSoundPlaying "weapon swish" )' instead, to check
;if the player is making a strike, at least on machines where GetSoundPlaying works fine.
;you'd also be able to automatically support all swinging weapons, then.

setx type to pctarget->xRefType
set value to 0
set nextref to 0
if ( type == 1598246990 ) ;NPC
	return
elseif ( type == 1095062083 ) ;creature
	return
elseif ( type == 1414418243 ) ;container
	set nextref to 1 ;flag that we need to tally the container's total value 
	set update_col to 1
elseif ( type == 1380929348 ) ;door      (this script allows player to destroy load doors too, careful)
	set value to 100
	set update_col to 1
elseif ( type == 1230259009 ) ;activator
	set value to 200
	set update_col to 1
endif


set invvalue to 0
set invcount to 0
setx type ownerid condition to pctarget->xGetOwnerInfo
if ( type == 0 ) ;no owner
	set value to 1 ;in case 'value' wasn't determined yet - there's no need to calculate it below
elseif ( type == 1598246990 ) ;NPC owner
	set invvalue to 1 ;(temp flag)
elseif ( type == 1413693766 ) ;faction owner
	set invcount to 1 ;(temp flag)
else
	MessageBox "ERROR?!" ;this should never happen
	return
endif

ifx ( invvalue ) ;NPC owner
	setx temp to xGetRef ownerid
	ifx ( temp )
		xSetRef temp
		set temp to GetHealth
	else
		set temp to 0 ;if can't find the owner, assume he's dead
	endif
	if ( temp <= 0 ) ;if he's dead, then it's all legal...
		set type to 0 ;no ownership
		set value to 1 ;no need to calculate 'value'
	else
		ifx ( condition )
			setx temp glob to xGetGlobal condition
			ifx ( temp ) ;got the global successfully
				ifx ( glob ) ;if it had a true value
					;then player is allowed to take/use the target
					set type to 0
					set value to 1
				endif
			else
				MessageBox "Got a problem..."
			endif
		endif
	endif
endif

ifx ( invcount ) ;faction owner
	;setx temp to xGetPCRank ownerid ;(this function doesn't exist yet)
	set temp to 0 ;temp filler since can't use above line. this makes the player count as of the lowest rank in the faction.

	if ( temp >= condition ) ;if player is of the required rank or above...
		;then it's legal
		set type to 0
		set value to 1
	endif
endif


ifx ( value )
else
	;if value is still 0, we're looking at an item (or a container)
	
	ifx ( nextref ) ;container
		set nextref to 0
		setx temp invcount temp invvalue temp temp nextref to pctarget->xContentList nextref ;values we don't care about get stored in temp and overwritten
		whilex ( invcount ) ;might take a short... while, if container has tons of stacks in it
			set temp to ( invcount * invvalue )
			set value to ( value + temp )
			ifx ( nextref )
				setx temp invcount temp invvalue temp temp nextref to pctarget->xContentList nextref
			else
				set invcount to 0 ;break the loop
			endif
		endwhile
	else ;looking at an item
		setx value to pctarget->xGetValue
	endif
	
endif

pctarget->Disable ;'destroy' the target
player->PlaySound "critical damage"
if ( type ) ;if it was determined to be illegal...
	setx glob to xGetGS 1173 ;GMST fCrimeStealing (default: 1.0)
	set value to ( value * glob )
	ModPCCrimeLevel value
endif

if ( update_col )
	set update_col to 0
	;in the event that that the player just disabled a door or a large
	;container or activator, its collision will normally remain until the
	;cell is re-loaded, and the player won't be able to go through the
	;space it used to occupy.
	;this part of the script solves that issue, making use of the fact that
	;the FixMe function also reloads some stuff in the active cell, such as
	;object coliisions. 

	;unfortunately, it also seems to always teleport the player, and,
	;ironically, sometimes cause him to get stuck. therefore, this line is commented out.

	;FixMe
endif

end

See Also[edit]

xGetOwner
xGetGlobal
xSetGlobal
xGetName
xGetBaseID
xRefType
xGetValue
xGetWeight
xGetEncumb
xGetQuality
xGetCondition
xGetMaxCondition
xGetCharge
xGetMaxCharge
xSetValue
xSetWeight
xSetQuality
xSetCondition
xSetMaxCondition