Add Inventory Object using Pure Scripts by Cherry
Warning
This is definitely NOT a tutorial to teach you how to make script mods. If you're looking for tutorials to teach you how to make script mods step-by-step, you should read the tutorials over here first.
Also, this is NOT a fully explained tutorial to teach you how to achieve this. I expect modders using this as a quick reference to learn how to add inventory object without using object mods, therefore only code fragments and simple comments to explain all things.
Just a Reminding
When player remove the mod, and some sims still have their inventory object, script errors will occur. It's better to add a debug interaction for players to remove all relevant objects before removing the mod. 
Main Usage
Adding inventory object to sims is used to store additional information of sims. Probably, you'll need to define your own fields and methods, or make use of the object anywhere of your code to make this really useful in your mod. I'm only showing you how to add an object to sims' inventory, if you follow this without adding other things, you'll end up with an useless inventory object with custom thumbnail, or something hidden deeply in sims' inventory and no one knows.
Basic Structure of an Inventory Object
// Note: Using Sims3.Gameplay.Objects is necessary, otherwise the game crash
namespace Sims3.Gameplay.Objects.MiniLibrary {
[Persistable]
internal class InventoryObject : GameObject {
public InventoryObject() {
}
public static InventoryObject CreateAndAddTo(Sim sim) {
// Add new object to sims' inventory
// Usage: InventoryObject.CreateAndAddTo(sim);
InventoryObject obj = GlobalFunctions.CreateObjectOutOfWorld("Coupon", typeof(InventoryObject)) as InventoryObject;
if ((obj != null) && sim.Inventory.TryToAdd(obj)) {
return obj;
}
obj.Destroy();
return null;
}
public override ThumbnailKey GetThumbnailKey() {
// Use custom thumbnail instead of ugly coupon
// Resource Type: IMAG 0x2F7D0004
// Size and Format: 54x54 PNG Image
return new ThumbnailKey(ResourceKey.CreatePNGKey("ResourceName", 0), ThumbnailSize.Medium);
}
public override string ToTooltipString() {
// Tooltip string shown when mouse over the object in inventory
return "Inventory Object";
}
public override void OnStartup() {
base.OnStartup();
base.AddComponent<ItemComponent>(new object[] { ItemComponent.SimInventoryItem });
// base.AddFlags(GameObject.FlagField.DoesNotStack);
}
}
}
Object Configuration
public override bool CanBeSold() {
// Object can be sold or not
return false;
}
public override bool HandToolAllowPlacement(ref string errorStr) {
// Usually you don't want inventory object could be dragged on floor
return false;
}
public override bool HandToolAllowDragDrop(IGameObject objectToDrop) {
// Allow the object to be dragged
// Turning on this will be more convenient to player to sort inventory,
// but this doesn't stop the object dragged from one sim to other,
// see code below to make object stick to original owner only.
return true;
}
Stick to Original Owner
namespace Sims3.Gameplay.Objects.MiniLibrary {
[Persistable]
internal class OwnerOnlyObj : GameObject {
[Persistable(false)]
IGameObject mOwner;
public OwnerOnlyObj() {
}
private bool CanAddToInventory(Inventory inventory) {
return (this.mOwner == null || inventory.Owner == this.mOwner));
}
public override void OnStartup() {
// Blah blah blah...(Same as InventoryObject)
this.mOwner = base.InInventory ? base.ItemComp.InventoryParent.Owner : null;
base.ItemComp.CanAddToInventoryDelegate = new ItemComponent.CanAddToInventoryCallback(this.CanAddToInventory);
}
}
}
Hidden Object Stored in Sims' Inventory
namespace Sims3.Gameplay.Objects.MiniLibrary {
[Persistable]
internal class HiddenObject : GameObject {
public HiddenObject() {
}
public static bool CreateAndAddTo(Sim sim) {
// Add a hidden object to sims' inventory
// Usage: HiddenObject.CreateAndAddTo(sim);
HiddenObject obj1 = GlobalFunctions.CreateObjectOutOfWorld("Coupon", tyepof(HiddenObject)) as HiddenObject;
HiddenObject obj2 = GlobalFunctions.CreateObjectOutOfWorld("Coupon", tyepof(HiddenObject)) as HiddenObject;
// Note: It's neccessary to make two objects first
if ((obj1 != null) && (obj2 != null)) {
List<IGameObject> list = new List<IGameObject>();
list.Add(obj1);
list.Add(obj2);
uint stack = sim.Inventory.CreateNewStack(list);
sim.Inventory.SetStackHidden(stack, true);
obj2.Destory();
return true;
}
return false;
}
public override void OnStartup() {
base.OnStartup();
base.AddComponent<ItemComponent>(new object[] { ItemComponent.SimInventoryItem });
}
}
}
Please feel free to ask any questions if you got some. 