The ItemObject Scriptable Object will not be serialized at runtime, and is intended to store permenent data, rather than mutable data that may change during the game. The GameItemObject is used for runtime use instead. It implements IAmGameModulesObject, and IFitInInventory.
// Owner will be the owner of the GameItemObjectList this is in. If it is not in a
// List, then it will be the value of _owner. The Owner is the IHaveStats objects
// which is affected by the stat effects on these objects.
public IHaveStats Owner => ParentList == null ? _owner : ParentList.Owner;
public ItemObject Parent() // Get the ItemObject scriptable objcet
public string Uid() // Uid of the parent
public virtual string GameId(bool forceNew = false) // In game unique ID of this GameItemObject
public bool QuestItem // Returns true if the ItemObject this is based on is marked quest item.
public Dictionaries dictionaries // The dictionaries for this GameItemObject
public List<GameItemAttribute> Attributes // The GameItemAttributes attached to this.
public string FullName(bool recompute = false) // The full name of this, including all attributes
public string ObjectName() // The name of this
public string ObjectType() // The type this is
public GameItemAttributeList attributes // All the attributes on this GameItemObject
public ModificationLevel ModificationLevel // Returns the modification level for the object
public List<ModificationLevel> ModificationLevels // Modificaiton levels for this + all attributes


Pass in the ItemObject and the owner. The owner can be null, but is required if this ItemObject is meant to affect the stats of the owner. ItemObject can be null as well, if you are creating a container for a future ItemObject.
If ItemObject is not null, the script will create a Clone() of the Dictionaries from the ItemObject Scriptable Object. This way changes to the GameItemObject dictionaries will not affect the Scriptable Object dictionaries.
The Inventory values will also be copied into this new GameItemObject.
public GameItemObject(ItemObject itemObject, IHaveStats newOwner)
owner = newOwner; // Set the owner
_itemObject = itemObject; // Set the Item Object
if (!itemObject) return; // Return if we do not have an ItemObject attached yet
dictionaries = itemObject.dictionaries.Clone(); // Clone the dictionaries object, so we don't overwrite our Scriptable Object data!
_uid = itemObject.uid; // Set the uid to match the Item Object
objectName = itemObject.objectName; // Set the name
objectType = itemObject.objectType; // Set the type
// Set the Inventory module values
inventoryHeight = itemObject.inventoryHeight;
inventoryWidth = itemObject.inventoryWidth;
prefabInventory = itemObject.prefabInventory;
prefabWorld = itemObject.prefabWorld;


Is and Is Not

// If itemAttributeType is not provided, returns true if attributes contains the
// attribute by the name provided
// If itemAttributeType is provided, then it must also have at least one itemAttribute
// of that type.
// Note: The itemAttributeType does not need to be the same as the objectType of the
// itemAttributeName provided.
public bool Is(string itemAttributeName, string itemAttributeType = "")
// Returns true if the attributes list does not contain the itemAttributeName provided
public bool IsNot(string itemAttributeName)


// Returns true if the attributeList contains an attribute with this uid
public bool HasAttribute(string uid)
// Returns true if the attributeList contains at least one attribute of this type
public bool Has(string itemAttributeType)
// If the attributeList contains at least one attribute of this type, returns the
// objectName of the first one found. Otherwise, returns "None".
public string ValueNameOf(string itemAttributeType, string noValueResult = "None")
// Example
uiText.text = $"Enchantment: {gameItemObject.ValueNameOf("Enchantment")}";

Manage Attributes

// Add a GameItemAttribute to this GameItemObject
// attributeUid: The uid of the ItemAttribute to add
// distinct: If true, only one attribute of each uid can be added
// recomputeHumanName: If true, the human name returned with FullName() will be recomputed
// resetModifictionLevel: If true, the modificaiton level for the object will be reset, and recomputed
// setAffectedStatsDirty: If true, the owner will have affected stats set dirty, so they recompute
public GameItemAttribute AddAttribute(string attributeUid, bool distinct = true
, bool recomputeHumanName = true, bool resetModificationLevel = true
, bool setAffectedStatsDirty = true)
// Remove a GameItemAttribute from this GameItemObject
// attributeUid: The uid of hte ItemAttribute to rmeove
// recomputeHumanName: If true, the human name returned with FullName() will be recomputed
// resetModifictionLevel: If true, the modificaiton level for the object will be reset, and recomputed
public void RemoveAttribute(string attributeUid, bool recomputeHumanName = true
, bool resetModificationLevel = true)
// Returns true if the "Allowed Item Attributes" on the ItemObject scriptable object
// have the ItemAttribute of the provided attributeUid toggled on.
public bool CanUseAttribute(string attributeUid)

Get Effect On IHaveStats Target

Often you might want to display or otherwise know the effect a specific GameItemObject will have on an IHaveStats target. The final impact is dependent on both the GameItemObject and the target.
This method will return float values for the impact on "value" and the impact on "proficiency". Optionally, you can exlcude the attributes attached to the object, which would allow you to show the "vanilla" objects effects, or even calculate the impact the attributes are having, and display those differently.
public (float, float) GetEffectOn(string targetStatUid, bool includeAttributes = true)

Additional Methods

// Sets the Owners stats dirty, any stat that the Owner has which are affected by this
// GameItemObject or any of the GameItemAttributes attached to it.
public void SetDirty(bool dirtyValue = true)