Agent Skill
2/7/2026inventory
Inventory system documentation. Reference this only when working with items and inventories.
A
all
0GitHub Stars
1Views
npx skills add All-Out-Games/infection-2
SKILL.md
| Name | inventory |
| Description | Inventory system documentation. Reference this only when working with items and inventories. |
name: inventory description: "Inventory system documentation. Reference this only when working with items and inventories."
CSL Inventory System
The inventory system provides a complete item management solution with support for item definitions, instances, storage, and UI.
Core Concepts
- Item_Definition - A template that defines what an item IS (name, icon, stack size, custom properties)
- Item_Instance - An actual item in the game world/inventory (has a count, can be moved around)
- Inventory - A container that holds item instances in slots
- default_inventory - Every Player has a built-in inventory accessible via
player.default_inventory
Creating Custom Item Types
You can extend Item_Definition and Item_Instance to add custom properties:
// Custom definition with extra properties
Weapon_Definition :: class : Item_Definition {
damage: int;
fire_rate: float;
description: string;
}
// Custom instance with per-item data
Weapon_Item :: class : Item_Instance {
// Add @ao_serialize for data that should be saved/loaded
durability: int @ao_serialize;
kills: int @ao_serialize;
}
Registering Item Definitions
Register item definitions in ao_before_scene_load. Use the Items.create_item_definition helper:
// Global storage for definitions
all_weapon_definitions: [..]Item_Definition;
ao_before_scene_load :: proc() {
// Create item definitions
// Arguments: {id, name, icon_path, stack_size, definition_type, instance_type}
sword_defn := create_item_definition(
{"sword", "Iron Sword", "icons/sword.png", 1, Weapon_Definition, Weapon_Item},
Weapon_Definition
);
sword_defn.damage = 10;
sword_defn.fire_rate = 1.0;
sword_defn.description = "A sturdy iron sword.";
// Store for later use
all_weapon_definitions->append(sword_defn);
// Stackable item example (stack_size = -1 for infinite)
ammo_defn := create_item_definition(
{"ammo", "Bullets", "icons/bullet.png", 99, Item_Definition, Item_Instance},
Item_Definition
);
}
Item_Definition_Desc Fields
Item_Definition_Desc :: struct {
id: string; // Unique identifier (e.g., "sword", "health_potion")
name: string; // Display name (e.g., "Iron Sword")
icon: string; // Path to icon texture (e.g., "icons/sword.png")
stack_size: s64; // Max stack size (1 = not stackable, -1 = infinite)
definition_type: typeid; // Your Item_Definition subclass type
instance_type: typeid; // Your Item_Instance subclass type
}
Creating and Managing Items
Creating Item Instances
// With custom instance type - returns Weapon_Item directly (no cast needed)
item := Items.create_item_instance(sword_defn, Weapon_Item, 1);
// Without custom instance type - returns Item_Instance
basic_item := Items.create_item_instance(basic_defn, 10); // 10 stacked items
Adding Items to Inventory
// Check if there's room first
will_destroy_item: bool;
if Items.can_move_item_to_inventory(item, player.default_inventory, ref will_destroy_item) {
Items.move_item_to_inventory(item, player.default_inventory);
// will_destroy_item is true if item merged into existing stack
}
// Or move as many as possible (for partial transfers)
destroyed_item: bool;
amount_moved := Items.move_as_many_items_as_possible_to_inventory(item, player.default_inventory, ref destroyed_item);
Removing Items from Inventory
// Remove from inventory (item still exists, just not in any inventory)
Items.remove_item_from_inventory(item, player.default_inventory);
// Destroy an item entirely
Items.destroy_item_instance(item); // Destroy entire stack
Items.destroy_item_instance(item, 5); // Destroy only 5 from the stack
Accessing Inventory Contents
// Iterate through inventory slots
for i: 0..player.default_inventory.capacity-1 {
item := player.default_inventory->get_item(i);
if item == null continue;
// Get the item's definition
defn := item->get_definition();
// Cast to your custom type if needed
weapon_defn := defn.(Weapon_Definition);
if weapon_defn != null {
log_info("Found weapon with % damage", {weapon_defn.damage});
}
}
Swapping Items
// Swap items between two inventory slots
if Items.can_swap_items(inventory_a, inventory_b, slot_a, slot_b) {
Items.swap_items(inventory_a, inventory_b, slot_a, slot_b);
}
Inventory API Reference
Items Struct (Static Functions)
Items :: struct {
// Inventory management
create_inventory :: proc(unique_id: string, capacity: s64) -> Inventory;
destroy_inventory :: proc(inventory: Inventory) -> bool;
set_capacity :: proc(inventory: Inventory, capacity: s64);
// Item definition creation
create_item_definition :: proc(desc: Item_Definition_Desc) -> Item_Definition;
// Item instance management
create_item_instance :: proc(definition: Item_Definition, count: s64 = 1) -> Item_Instance;
create_item_instance :: proc(definition: Item_Definition, $T: typeid, count: s64 = 1) -> T; // Returns typed instance
destroy_item_instance :: proc(instance: Item_Instance, count: s64 = -1); // -1 = entire stack
// Inventory operations
calculate_room_in_inventory_for_item :: proc(definition: Item_Definition, inventory: Inventory) -> s64;
can_move_item_to_inventory :: proc(instance: Item_Instance, inventory: Inventory, will_destroy_item: ref bool) -> bool;
move_item_to_inventory :: proc(instance: Item_Instance, inventory: Inventory);
move_as_many_items_as_possible_to_inventory :: proc(instance: Item_Instance, inventory: Inventory, destroyed_item: ref bool) -> s64;
remove_item_from_inventory :: proc(instance: Item_Instance, inventory: Inventory);
can_swap_items :: proc(inventory_a: Inventory, inventory_b: Inventory, slot_a: s64, slot_b: s64) -> bool;
swap_items :: proc(inventory_a: Inventory, inventory_b: Inventory, slot_a: s64, slot_b: s64);
// UI Drawing
draw_inventory :: proc(rect: Rect, inventory: Inventory, options: Inventory_Draw_Options) -> bool;
draw_hotbar :: proc(player: Player, inventory: Inventory, options: Inventory_Draw_Options) -> Draw_Hotbar_Result;
}
Item_Definition Methods
defn->get_name() -> string; // Display name
defn->get_id() -> string; // Unique ID
defn->get_icon() -> Texture_Asset; // Icon texture
Item_Instance Methods
item->get_definition() -> Item_Definition; // Get the definition this instance was created from
Inventory Methods
inventory->get_item(index: s64) -> Item_Instance; // Get item at slot (may be null)
inventory.capacity // Read-only capacity
Drawing Inventory UI
Draw inventory UI in the player's ao_update or ao_late_update (inside is_local_or_server() check).
Hotbar
ao_late_update :: method(dt: float) {
if this->is_local_or_server() {
// Draw hotbar at bottom of screen
options := Inventory_Draw_Options.default();
options.hotbar_item_count = 5;
options.enable_use_from_hotbar = true;
options.scroll_item_selection = true;
options.keyboard_item_selection = true;
result := Items.draw_hotbar(this, default_inventory, options);
// Handle item selection
if result.selected_item != null {
use_item(this, result.selected_item);
}
// Handle drag-drop out of inventory
if result.dropped_item != null {
drop_item(this, result.dropped_item);
}
}
}
Full Inventory Grid
// Draw a full inventory grid in a rect
inventory_rect := UI.get_safe_screen_rect()->inset(100);
options := Inventory_Draw_Options.default();
options.title = "Inventory";
options.show_exit_button = true;
options.show_background = true;
options.columns = 5;
options.rows = 4;
closed := Items.draw_inventory(inventory_rect, player.default_inventory, options);
if closed {
// User clicked exit button
inventory_open = false;
}
Inventory_Draw_Options
Inventory_Draw_Options :: struct {
title: string; // Title text for inventory panel
show_exit_button: bool; // Show X button to close
show_scroll_bar: bool; // Show scroll bar for overflow
show_background: bool; // Draw background panel
allow_drag_drop: bool; // Allow dragging items
drag_drop_color_multiplier: v4; // Tint for dragged items
hotbar_item_count: s32; // Number of hotbar slots (default: 6)
columns: s32; // Grid columns
rows: s32; // Grid rows
force_select_hotbar_index: s32; // Force select specific slot (-1 = none)
hide_bag_button: bool; // Hide the "open bag" button on hotbar
enable_selection: bool; // Allow selecting items
scroll_item_selection: bool; // Scroll wheel changes selection
keyboard_item_selection: bool; // Number keys select items
enable_use_from_hotbar: bool; // Clicking hotbar uses item
default :: proc() -> Inventory_Draw_Options; // Get default options
}
Draw_Hotbar_Result
Draw_Hotbar_Result :: struct {
selected_item: Item_Instance; // Item that was selected/used (or null)
selected_item_index: s64; // Index of selected item
dropped_item: Item_Instance; // Item that was dragged out (or null)
entire_rect: Rect; // The rect the hotbar was drawn in
inventory_open: bool; // Whether full inventory is open
inventory_open_t: float; // Animation progress (0-1)
}
Complete Example
// Item definitions
Artifact_Definition :: class : Item_Definition {
tier: Item_Tier;
description: string;
damage_bonus: float;
}
Artifact_Item :: class : Item_Instance {
// Per-instance data
modifier: float @ao_serialize;
}
Item_Tier :: enum {
COMMON;
UNCOMMON;
RARE;
EPIC;
LEGENDARY;
}
// Store definitions globally
all_artifacts: [..]Item_Definition;
ao_before_scene_load :: proc() {
// Register items
sword := create_item_definition(
{"sword_common", "Iron Sword", "icons/sword.png", 1, Artifact_Definition, Artifact_Item},
Artifact_Definition
);
sword.tier = .COMMON;
sword.damage_bonus = 5;
sword.description = "A basic iron sword.";
all_artifacts->append(sword);
}
// Grant item to player
try_give_item :: proc(player: Player, defn: Item_Definition) {
item := Items.create_item_instance(defn, Artifact_Item);
rng := rng_seed_time();
item.modifier = rng_range_float(ref rng, 0, 2);
will_destroy: bool;
if Items.can_move_item_to_inventory(item, player.default_inventory, ref will_destroy) {
Items.move_item_to_inventory(item, player.default_inventory);
player->add_notification(format_string("Obtained %!", {defn->get_name()}));
}
else {
// Inventory full - destroy the item we just created
Items.destroy_item_instance(item);
player->add_notification("Inventory full!");
}
}
// Calculate total damage bonus from equipped items
calculate_damage_bonus :: proc(player: Player) -> float {
total := 0.0;
for i: 0..player.default_inventory.capacity-1 {
item := player.default_inventory->get_item(i);
if item == null continue;
defn := item->get_definition();
if defn.#type == Artifact_Definition {
artifact_defn := defn.(Artifact_Definition);
total += artifact_defn.damage_bonus;
}
if item.#type == Artifact_Item {
artifact_item := item.(Artifact_Item);
total += artifact_item.modifier;
}
}
return total;
}
Skills Info
Original Name:inventoryAuthor:all
Download