### C# Setup Storage Event Listeners Example Source: https://ifbars.github.io/S1API-docs/api/storages Shows how to subscribe to the `OnOpened` and `OnClosed` events of a StorageInstance to execute custom logic when these events occur. ```csharp // Subscribe to storage events public void SetupStorageListeners(StorageInstance storage) { storage.OnOpened += () => { Console.WriteLine("Storage has been opened!"); // Play sound effect, show UI, etc. }; storage.OnClosed += () => { Console.WriteLine("Storage has been closed!"); // Hide UI, save state, etc. }; } ``` -------------------------------- ### Icon Setup Source: https://ifbars.github.io/S1API-docs/api/phone-app Instructions for setting up your app icon. ```APIDOC ## Icon Setup ### Description Instructions for setting up your app icon. ### Steps 1. Create a PNG file for your app icon (recommended size: 128x128 or 256x256). 2. Save it in the UserData folder with the name matching your `IconFileName` property. 3. Transparent background is preferred for better visual integration. ``` -------------------------------- ### Create Cash Instance Example (C#) Source: https://ifbars.github.io/S1API-docs/api/money Shows how to create a new instance of cash with a specified initial quantity. This involves first getting the cash definition and then calling its CreateInstance method. ```csharp // Create a new instance of cash with a specific amount CashDefinition cashDef = (CashDefinition)ItemManager.GetItemDefinition("cash"); CashInstance cashInstance = (CashInstance)cashDef.CreateInstance(100); // 100 units of currency ``` -------------------------------- ### Listening to Storage Events Example Source: https://ifbars.github.io/S1API-docs/api/storages Shows how to subscribe to and handle `OnOpened` and `OnClosed` events from a `StorageInstance`. ```APIDOC ## Listening to Storage Events ### Description This example demonstrates how to subscribe to the `OnOpened` and `OnClosed` events of a `StorageInstance` to trigger actions when the storage is interacted with. ### Code Example ```csharp // Subscribe to storage events public void SetupStorageListeners(StorageInstance storage) { storage.OnOpened += () => { Console.WriteLine("Storage has been opened!"); // Play sound effect, show UI, etc. }; storage.OnClosed += () => { Console.WriteLine("Storage has been closed!"); // Hide UI, save state, etc. }; } ``` ``` -------------------------------- ### Creating a Custom Quest Example Source: https://ifbars.github.io/S1API-docs/api/quests Example demonstrating how to create a custom quest by extending the abstract `Quest` class and implementing quest logic. ```APIDOC ## Usage Example: Creating a Custom Quest ### Description This example shows how to define a `DeliveryQuest` by inheriting from the `Quest` class and implementing its abstract members. It also demonstrates adding and managing `QuestEntry` objects. ### Code ```csharp public class DeliveryQuest : Quest { protected override string Title => "Delivery Request"; protected override string Description => $"Deliver the requested product and collect payment from the drop."; [SaveableField("OrderData")] private OrderData _orderData = new(); private QuestEntry? _deliveryEntry; private QuestEntry? _rewardEntry; protected override void OnCreated() { _deliveryEntry = AddEntry( $"Deliver { _orderData.Amount}x {_orderData.Product?.Name}.", _orderData.DeliveryLocation ); _rewardEntry = AddEntry( $"Collect ${_orderData.Price:N0}.", _orderData.RewardLocation ); // Initially set reward entry as inactive _rewardEntry.SetState(QuestState.Inactive); } public void CompleteDelivery() { _deliveryEntry?.Complete(); _rewardEntry?.SetState(QuestState.Active); } public void CollectReward() { _rewardEntry?.Complete(); // Quest will auto-complete when all entries are completed } } ``` ``` -------------------------------- ### Working with Storage Containers Example Source: https://ifbars.github.io/S1API-docs/api/storages Demonstrates how to access storage contents, check item fit, and add items to a storage container. ```APIDOC ## Working with Storage Containers ### Description This example shows how to iterate through a `StorageInstance`'s slots, display item information, and check if an item can be added before attempting to add it. ### Code Example ```csharp // Access slots in a storage container public void DisplayStorageContents(StorageInstance storage) { Console.WriteLine($"Storage contains {storage.Slots.Length} slots:"); foreach (var slot in storage.Slots) { if (slot.ItemInstance != null) { Console.WriteLine($"- {slot.ItemInstance.Definition.Name} x{slot.Quantity}"); } else { Console.WriteLine("- Empty slot"); } } } // Check if an item can fit in storage public bool TryAddItemToStorage(StorageInstance storage, ItemInstance item, int quantity) { if (storage.CanItemFit(item, quantity)) { storage.AddItem(item); return true; } Console.WriteLine("Item doesn't fit in this storage container."); return false; } ``` ``` -------------------------------- ### Finding Item Definitions Example Source: https://ifbars.github.io/S1API-docs/api/storages Shows how to retrieve item definitions using `ItemManager` and create new item instances. ```APIDOC ## Finding Item Definitions ### Description This example demonstrates how to use the `ItemManager` to get an `ItemDefinition` by its ID, create a new `ItemInstance` from that definition, and add it to a storage container if it fits. ### Code Example ```csharp // Get an item definition by ID public ItemDefinition GetItemByID(string itemID) { return ItemManager.GetItemDefinition(itemID); } // Create a new instance of an item to add to storage public void CreateAndAddToStorage(StorageInstance storage, string itemID, int quantity) { var itemDef = ItemManager.GetItemDefinition(itemID); if (itemDef != null) { var itemInstance = itemDef.CreateInstance(quantity); if (storage.CanItemFit(itemInstance, quantity)) { storage.AddItem(itemInstance); Console.WriteLine($"Added {quantity}x {itemDef.Name} to storage"); } } } ``` ``` -------------------------------- ### Get Cash Definition Example (C#) Source: https://ifbars.github.io/S1API-docs/api/money Demonstrates how to retrieve a reference to a specific cash definition from the ItemManager using its identifier. This is the first step before creating or manipulating cash instances. ```csharp // Get a reference to a cash definition CashDefinition cashDef = (CashDefinition)ItemManager.GetItemDefinition("cash"); ``` -------------------------------- ### Creating a Simple Phone App Source: https://ifbars.github.io/S1API-docs/api/phone-app Example demonstrating how to create a basic custom phone application by extending the PhoneApp class and implementing the necessary methods. ```APIDOC ## Creating a Simple Phone App ### Description Example demonstrating how to create a basic custom phone application by extending the PhoneApp class and implementing the necessary methods. ### Code Example ```csharp // Create a custom phone app by extending the PhoneApp class public class MyAwesomeApp : PhoneApp { // Required app metadata protected override string AppName => "MyAwesomeApp"; protected override string AppTitle => "My Awesome App"; protected override string IconLabel => "Awesome"; protected override string IconFileName => "my_icon.png"; // Called when the app UI is being created protected override void OnCreatedUI(GameObject container) { // Create a panel with black background GameObject panel = UIFactory.Panel("MainPanel", container.transform, Color.black); // Add a text element to the panel UIFactory.Text("HelloText", "Hello from My Awesome App!", panel.transform, 22, TextAnchor.MiddleCenter, FontStyle.Bold); } } ``` ``` -------------------------------- ### Registering Your App with the Phone System Source: https://ifbars.github.io/S1API-docs/api/phone-app Example showing how to register your custom phone app and initialize it within your Melon Mod. ```APIDOC ## Registering Your App with the Phone System ### Description Example showing how to register your custom phone app and initialize it within your Melon Mod. ### Code Example ```csharp using MelonLoader; using S1API.PhoneApp; public class MyMod : MelonMod { public override void OnApplicationStart() { // Register your app PhoneAppManager.Register(new MyAwesomeApp()); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { // Initialize all registered apps when the game scene loads if (sceneName == "MainScene") // Replace with your in-game scene { PhoneAppManager.InitAll(LoggerInstance); } } } ``` ``` -------------------------------- ### Creating Cash Instances Source: https://ifbars.github.io/S1API-docs/api/money Example of how to create a new instance of cash with a specific amount. ```APIDOC ## Creating Cash Instances ### Description Create a new instance of cash with a specific amount. ### Method N/A (Code Example) ### Endpoint N/A ### Parameters N/A ### Request Example ```csharp // Create a new instance of cash with a specific amount CashDefinition cashDef = (CashDefinition)ItemManager.GetItemDefinition("cash"); CashInstance cashInstance = (CashInstance)cashDef.CreateInstance(100); // 100 units of currency ``` ### Response N/A ``` -------------------------------- ### C# Example: Registering App with Phone System Source: https://ifbars.github.io/S1API-docs/api/phone-app Illustrates how to integrate a custom phone app into the game's phone system using 'MelonLoader'. It shows the 'OnApplicationStart' method for registering the app and 'OnSceneWasLoaded' for initializing all registered apps. ```csharp using MelonLoader; using S1API.PhoneApp; public class MyMod : MelonMod { public override void OnApplicationStart() { // Register your app PhoneAppManager.Register(new MyAwesomeApp()); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { // Initialize all registered apps when the game scene loads if (sceneName == "MainScene") // Replace with your in-game scene { PhoneAppManager.InitAll(LoggerInstance); } } } ``` -------------------------------- ### C# Example: Creating Buttons and Handling Clicks with S1API UI Factory Source: https://ifbars.github.io/S1API-docs/api/ui Illustrates the creation of interactive buttons, including standard and rounded types, with associated labels and click event handling. This example shows how to use `ButtonRow`, `ButtonWithLabel`, and `RoundedButtonWithLabel`. ```csharp using S1API.UI; using UnityEngine; using UnityEngine.UI; public class ButtonExample { public void CreateButtonUI(Transform parent) { // Create a button row var buttonRow = UIFactory.ButtonRow("ActionButtons", parent); // Create a standard button var (stdButton, stdBtn, stdText) = UIFactory.ButtonWithLabel( "StandardButton", "Click Me", buttonRow.transform, new Color(0.2f, 0.4f, 0.8f), 120f, 40f); // Set up the button's click handler stdBtn.onClick.AddListener(() => { Debug.Log("Standard button clicked!"); }); // Create a rounded button var (roundedContainer, roundedBtn, roundedText) = UIFactory.RoundedButtonWithLabel( "RoundedButton", "Rounded Button", buttonRow.transform, new Color(0.8f, 0.2f, 0.2f), 150f, 40f, 16, Color.white); // Set up the rounded button's click handler roundedBtn.onClick.AddListener(() => { Debug.Log("Rounded button clicked!"); }); } } ``` -------------------------------- ### C# Display Storage Contents Example Source: https://ifbars.github.io/S1API-docs/api/storages This example function iterates through the slots of a StorageInstance and prints the name and quantity of items found, or indicates if a slot is empty. ```csharp // Access slots in a storage container public void DisplayStorageContents(StorageInstance storage) { Console.WriteLine($"Storage contains {storage.Slots.Length} slots:"); foreach (var slot in storage.Slots) { if (slot.ItemInstance != null) { Console.WriteLine($"- {slot.ItemInstance.Definition.Name} x{slot.Quantity}"); } else { Console.WriteLine("- Empty slot"); } } } ``` -------------------------------- ### Getting Cash Definition Source: https://ifbars.github.io/S1API-docs/api/money Example of how to get a reference to a cash definition from the ItemManager. ```APIDOC ## Getting Cash Definition ### Description Get a reference to a cash definition. ### Method N/A (Code Example) ### Endpoint N/A ### Parameters N/A ### Request Example ```csharp // Get a reference to a cash definition CashDefinition cashDef = (CashDefinition)ItemManager.GetItemDefinition("cash"); ``` ### Response N/A ``` -------------------------------- ### C# Basic Logging Example Source: https://ifbars.github.io/S1API-docs/api/logging Demonstrates the fundamental usage of the `Log` class in C#. It shows how to instantiate a logger with a source name and subsequently log messages across different levels. ```csharp using S1API.Logging; public class MyMod { private Log _logger; public MyMod() { // Create a new logger with your mod name as the source _logger = new Log("MyAwesomeMod"); // Log some messages with different levels _logger.Msg("Mod initialized successfully"); _logger.Warning("This is a warning message"); _logger.Error("Something went wrong!"); _logger.BigError("Critical error occurred!"); } } ``` -------------------------------- ### C# Example: Creating a Simple Phone App Source: https://ifbars.github.io/S1API-docs/api/phone-app Demonstrates how to create a custom phone application by extending the 'PhoneApp' abstract class. It shows the implementation of required properties and the 'OnCreatedUI' method to define the app's interface using 'UIFactory'. ```csharp // Create a custom phone app by extending the PhoneApp class public class MyAwesomeApp : PhoneApp { // Required app metadata protected override string AppName => "MyAwesomeApp"; protected override string AppTitle => "My Awesome App"; protected override string IconLabel => "Awesome"; protected override string IconFileName => "my_icon.png"; // Called when the app UI is being created protected override void OnCreatedUI(GameObject container) { // Create a panel with black background GameObject panel = UIFactory.Panel("MainPanel", container.transform, Color.black); // Add a text element to the panel UIFactory.Text("HelloText", "Hello from My Awesome App!", panel.transform, 22, TextAnchor.MiddleCenter, FontStyle.Bold); } } ``` -------------------------------- ### Get Item Definition Example (C#) Source: https://ifbars.github.io/S1API-docs/api/items Demonstrates how to use the ItemManager to retrieve an item definition by its ID and access its properties such as name, description, category, and stack limit. ```csharp // Get an item definition by its ID var sodaDefinition = ItemManager.GetItemDefinition("cuke"); // Access properties of the definition Console.WriteLine($"Name: {sodaDefinition.Name}"); Console.WriteLine($"Description: {sodaDefinition.Description}"); Console.WriteLine($"Category: {sodaDefinition.Category}"); Console.WriteLine($"Stack Limit: {sodaDefinition.StackLimit}"); ``` -------------------------------- ### C# Usage Examples for TimeManager Source: https://ifbars.github.io/S1API-docs/api/game-time Demonstrates how to use the TimeManager class to get current time information, format time, check time ranges, manipulate game time, and subscribe to time-based events like day passes and sleep endings. ```csharp // Get current day and time information Day today = TimeManager.CurrentDay; int currentTime = TimeManager.CurrentTime; bool isNightTime = TimeManager.IsNight; float dayProgress = TimeManager.NormalizedTime; // 0.0 to 1.0 // Format current time string timeString = TimeManager.GetFormatted12HourTime(); // e.g., "2:30 PM" // Check time conditions bool isOpeningHours = TimeManager.IsCurrentTimeWithinRange(900, 1700); // 9 AM to 5 PM // Manipulate time TimeManager.SetTime(1800); // Set to 6:00 PM TimeManager.SetElapsedDays(10); // Set to day 10 TimeManager.FastForwardToWakeTime(); // Skip to 7 AM // Subscribe to time events TimeManager.OnDayPass += () => { // Handle new day starting Console.WriteLine("A new day has begun!"); }; TimeManager.OnSleepEnd += (minutesSlept) => { Console.WriteLine($"Good morning! You slept for {minutesSlept/60} hours."); }; ``` -------------------------------- ### Managing Items in Slots Example Source: https://ifbars.github.io/S1API-docs/api/storages Provides examples for removing items from storage and counting specific items within storage slots. ```APIDOC ## Managing Items in Slots ### Description This example covers common operations for managing items within storage slots, including removing a specified quantity of an item and counting the total quantity of a particular item. ### Code Example ```csharp // Remove items from storage public void RemoveItemsFromStorage(StorageInstance storage, string itemID, int quantityToRemove) { foreach (var slot in storage.Slots) { if (slot.ItemInstance != null && slot.ItemInstance.Definition.ID == itemID) { int amountToRemove = Math.Min(slot.Quantity, quantityToRemove); slot.AddQuantity(-amountToRemove); quantityToRemove -= amountToRemove; if (quantityToRemove <= 0) break; } } } // Count items in storage public int CountItemsInStorage(StorageInstance storage, string itemID) { int total = 0; foreach (var slot in storage.Slots) { if (slot.ItemInstance != null && slot.ItemInstance.Definition.ID == itemID) { total += slot.Quantity; } } return total; } ``` ``` -------------------------------- ### Example: Modifying Player Cash with ConsoleHelper Source: https://ifbars.github.io/S1API-docs/api/console Demonstrates how to use the ConsoleHelper.RunCashCommand method to modify the player's in-game cash. This example shows both adding and removing cash amounts. ```csharp using S1API.Console; public class ConsoleExample { public void ModifyPlayerCash() { // Add 1000 cash to the player ConsoleHelper.RunCashCommand(1000); // Remove 500 cash from the player ConsoleHelper.RunCashCommand(-500); } } ``` -------------------------------- ### C# Usage Examples for GameDateTime Source: https://ifbars.github.io/S1API-docs/api/game-time Illustrates common operations with the GameDateTime struct, such as instantiation, adding minutes, checking time of day, formatting, and comparing different GameDateTime instances. ```csharp // Create a new game date time (day 3, 2:30 PM) GameDateTime dateTime = new GameDateTime(3, 1430); // Add 60 minutes GameDateTime later = dateTime.AddMinutes(60); // Check if it's night time bool isNight = dateTime.IsNightTime(); // Format the time string timeString = dateTime.GetFormattedTime(); // e.g., "2:30 PM" // Compare game date times bool sameDay = dateTime.IsSameDay(later); bool laterInTime = later > dateTime; ``` -------------------------------- ### C# - Accessing and Iterating Products Source: https://ifbars.github.io/S1API-docs/api/products Example demonstrating how to access all discovered products using ProductManager.DiscoveredProducts and iterate through them, checking for specific product types like WeedDefinition. ```csharp // Access all discovered products ProductDefinition[] products = ProductManager.DiscoveredProducts; // Loop through products foreach (var product in products) { Console.WriteLine($"Product: {product.Name}, Price: ${product.Price}, MV: ${product.MarketValue}"); // Check for specific product types if (product is WeedDefinition weedProduct) { // Handle weed-specific functionality } else if (product is MethDefinition methProduct) { // Handle meth-specific functionality } else if (product is CocaineDefinition cocaineProduct) { // Handle cocaine-specific functionality } } ``` -------------------------------- ### C# Example: Creating a Panel with Text using S1API UI Factory Source: https://ifbars.github.io/S1API-docs/api/ui Demonstrates how to create a basic UI panel with title and description text using the S1API.UI.UIFactory. It utilizes `Panel` and `Text` creation methods, setting colors, anchors, and text properties. ```csharp using S1API.UI; using UnityEngine; public class UIExample { public void CreateSimpleUI(Transform parent) { // Create a background panel var panel = UIFactory.Panel("MainPanel", parent, new Color(0.1f, 0.1f, 0.1f, 0.8f), fullAnchor: true); // Add a title text to the panel UIFactory.Text("Title", "My Custom UI", panel.transform, 24, TextAnchor.MiddleCenter, FontStyle.Bold); // Add a description text UIFactory.Text("Description", "This is an example of creating UI with S1API", panel.transform, 16, TextAnchor.UpperLeft); } } ``` -------------------------------- ### Usage Example: Creating a Custom NPC Source: https://ifbars.github.io/S1API-docs/api/npcs Demonstrates how to create a custom NPC by deriving from the abstract NPC class and implementing specific behaviors. ```APIDOC ## Usage Example: Creating a Custom NPC ### Description This example shows how to create a 'CustomerNPC' that interacts with the player based on budget and daily messages. ### Code ```csharp using S1API.Entities; using S1API.Messaging; using System.Collections.Generic; using UnityEngine; public class CustomerNPC : NPC { // Track customer preferences and state private Dictionary _cart = new Dictionary(); private float _budget; private bool _hasPurchased = false; private int _lastMessageDay = -1; // Create the customer NPC with a unique ID and name public CustomerNPC() : base("s1api_customer", "S1API", "Customer") { // Initialize customer properties IsInvincible = true; Aggressiveness = 0.0f; Scale = 1.0f; _budget = UnityEngine.Random.Range(400f, 2000f); // Subscribe to the day passing event GameEvents.OnDayPass += HandleDayPass; } // Handle when a day passes in the game private void HandleDayPass(int newDay) { // Only send a message if we haven't sent one today if (newDay != _lastMessageDay) { _lastMessageDay = newDay; SendDailyMessage(); } } // Send a daily message to the player private void SendDailyMessage() { var responses = new[] { new Response { Label = "sellproduct", Text = "Okay bet.", OnTriggered = SellProduct }, }; SendTextMessage($"Day {_lastMessageDay}: Hey! I'm looking to buy some product today. Got anything for ${_budget:F0}?", responses); } // Override to handle responses loaded from save file protected override void OnResponseLoaded(Response response) { // Match responses by label and assign callbacks switch(response.Label) { case "sellproduct": response.OnTriggered = SellProduct; break; } } private void SellProduct() { // In a real implementation, you have do something like send the player to a dropoff dead drop with a quest _hasPurchased = true; SendTextMessage("Thanks for the product! See you tomorrow maybe."); } } ``` ``` -------------------------------- ### C# Check and Add Item to Storage Example Source: https://ifbars.github.io/S1API-docs/api/storages Demonstrates how to check if an item can fit into a storage container using `CanItemFit` and then add it using `AddItem` if space is available. ```csharp // Check if an item can fit in storage public bool TryAddItemToStorage(StorageInstance storage, ItemInstance item, int quantity) { if (storage.CanItemFit(item, quantity)) { storage.AddItem(item); return true; } Console.WriteLine("Item doesn't fit in this storage container."); return false; } ``` -------------------------------- ### PropertyWrapper Delegation Examples (C#) Source: https://ifbars.github.io/S1API-docs/api/property Illustrates how the PropertyWrapper class implements the BaseProperty interface by delegating calls to its internal property instance. These examples show direct mapping for properties like 'PropertyName' and layered delegation for getters/setters like 'EmployeeCapacity' and methods like 'IsPointInside'. ```csharp // Property name is directly mapped from the inner property public override string PropertyName => InnerProperty.PropertyName; // Employee capacity has both getter and setter that delegate to inner property public override int EmployeeCapacity { get => InnerProperty.EmployeeCapacity; set => InnerProperty.EmployeeCapacity = value; } // IsPointInside delegates to the DoBoundsContainPoint method of the inner property public override bool IsPointInside(UnityEngine.Vector3 point) => InnerProperty.DoBoundsContainPoint(point); ``` -------------------------------- ### Checking Current Region Example Source: https://ifbars.github.io/S1API-docs/api/map Example demonstrating how to check the player's current region using the Map API. ```APIDOC ## Checking Current Region ### Description This example shows how to retrieve the player's current region and perform actions based on it. ### Method `PlayerManager.GetCurrentRegion()` ### Usage Example ```csharp using S1API.Map; using S1API.Player; public class RegionExample { public void CheckPlayerRegion() { // Get the player's current region Region currentRegion = PlayerManager.GetCurrentRegion(); // Perform different actions based on the current region switch (currentRegion) { case Region.Northtown: Debug.Log("Welcome to Northtown, the starting area!"); break; case Region.Downtown: Debug.Log("Downtown is bustling with activity!"); break; case Region.Uptown: Debug.Log("You've reached Uptown, the most exclusive district!"); break; default: Debug.Log($"You are currently in {currentRegion}"); break; } } } ``` ``` -------------------------------- ### C# Create and Add Item to Storage Example Source: https://ifbars.github.io/S1API-docs/api/storages This function finds an item definition by ID, creates an instance of that item, checks if it fits in storage, and adds it if possible. ```csharp // Create a new instance of an item to add to storage public void CreateAndAddToStorage(StorageInstance storage, string itemID, int quantity) { var itemDef = ItemManager.GetItemDefinition(itemID); if (itemDef != null) { var itemInstance = itemDef.CreateInstance(quantity); if (storage.CanItemFit(itemInstance, quantity)) { storage.AddItem(itemInstance); Console.WriteLine($"Added {quantity}x {itemDef.Name} to storage"); } } } ``` -------------------------------- ### C# - Item Definition Base Class Source: https://ifbars.github.io/S1API-docs/api/products The base class for all item definitions in the S1API, including products and packaging. It contains common properties like GUID, ID, Name, Description, Category, and StackLimit. ```csharp public class ItemDefinition { public string GUID { get; } public string ID { get; } public string Name { get; } public string Description { get; } public ItemCategory Category { get; } public int StackLimit { get; } public virtual ItemInstance CreateInstance(int quantity = 1); } ``` -------------------------------- ### PropertyManager - Finding and Purchasing a Property (C#) Source: https://ifbars.github.io/S1API-docs/api/property Illustrates finding a property by its name using FindPropertyByName and then purchasing it if it's not already owned. This example includes checks for property existence and ownership status before setting it as owned. ```csharp using S1API.Property; using UnityEngine; public class PropertyPurchaseExample { public void PurchasePropertyByName(string propertyName) { // Find the property PropertyWrapper property = PropertyManager.FindPropertyByName(propertyName); if (property == null) { Debug.LogError($"Property '{propertyName}' not found"); return; } // Check if already owned if (property.IsOwned) { Debug.Log($"You already own {property.PropertyName}"); return; } // Purchase the property (game logic would typically handle money transaction) Debug.Log($"Purchasing {property.PropertyName} for ${property.Price}"); property.SetOwned(); // Verify purchase Debug.Log($"Property owned status: {property.IsOwned}"); } } ``` -------------------------------- ### C# Example: Creating a Scrollable List with S1API UI Factory Source: https://ifbars.github.io/S1API-docs/api/ui Shows how to implement a scrollable vertical list using `ScrollableVerticalList`, populating it with items that include panels, text, and clickable rows. It also demonstrates adjusting content height with `FitContentHeight`. ```csharp using S1API.UI; using UnityEngine; using UnityEngine.UI; public class ScrollableListExample { public void CreateScrollableList(Transform parent) { // Create a scrollable list and get its content transform var contentRT = UIFactory.ScrollableVerticalList("ItemList", parent, out ScrollRect scrollRect); // Add several items to the list for (int i = 0; i < 10; i++) { // Create each item var item = UIFactory.Panel($"Item_{i}", contentRT, new Color(0.2f, 0.2f, 0.2f)); UIFactory.HorizontalLayoutOnGO(item); // Add an icon panel GameObject iconPanel, textPanel; var row = UIFactory.CreateQuestRow($"Quest_{i}", item.transform, out iconPanel, out textPanel); // Add text to the row UIFactory.CreateTextBlock(textPanel.transform, $("Item #{i}"), "This is an example item", i > 5); // Make the row clickable UIFactory.CreateRowButton(row, () => { Debug.Log($"Clicked on item {i}"); }, true); } // Adjust content height to fit all items UIFactory.FitContentHeight(contentRT); } } ``` -------------------------------- ### Create Custom NPC (C#) Source: https://ifbars.github.io/S1API-docs/api/npcs This example demonstrates how to create a custom NPC by inheriting from the abstract NPC class and implementing custom logic. Includes initialization, event handling, and message sending. ```csharp using S1API.Entities; using S1API.Messaging; using System.Collections.Generic; using UnityEngine; public class CustomerNPC : NPC { // Track customer preferences and state private Dictionary _cart = new Dictionary(); private float _budget; private bool _hasPurchased = false; private int _lastMessageDay = -1; // Create the customer NPC with a unique ID and name public CustomerNPC() : base("s1api_customer", "S1API", "Customer") { // Initialize customer properties IsInvincible = true; Aggressiveness = 0.0f; Scale = 1.0f; _budget = UnityEngine.Random.Range(400f, 2000f); // Subscribe to the day passing event GameEvents.OnDayPass += HandleDayPass; } // Handle when a day passes in the game private void HandleDayPass(int newDay) { // Only send a message if we haven't sent one today if (newDay != _lastMessageDay) { _lastMessageDay = newDay; SendDailyMessage(); } } // Send a daily message to the player private void SendDailyMessage() { var responses = new[] { new Response { Label = "sellproduct", Text = "Okay bet.", OnTriggered = SellProduct }, }; SendTextMessage($"Day {_lastMessageDay}: Hey! I'm looking to buy some product today. Got anything for ${_budget:F0}?", responses); } // Override to handle responses loaded from save file protected override void OnResponseLoaded(Response response) { // Match responses by label and assign callbacks switch(response.Label) { case "sellproduct": response.OnTriggered = SellProduct; break; } } private void SellProduct() { // In a real implementation, you have do something like send the player to a dropoff dead drop with a quest _hasPurchased = true; SendTextMessage("Thanks for the product! See you tomorrow maybe."); } } ``` -------------------------------- ### Manipulate Cash Amount Examples (C#) Source: https://ifbars.github.io/S1API-docs/api/money Illustrates how to modify the quantity of a cash instance. This includes adding or subtracting amounts using AddQuantity and setting an exact amount using SetQuantity. ```csharp // Add currency to a cash instance cashInstance.AddQuantity(50.0f); // Add 50 to the balance // Remove currency from a cash instance cashInstance.AddQuantity(-25.0f); // Remove 25 from the balance // Set currency to a specific amount cashInstance.SetQuantity(200.0f); // Set to exactly 200 ``` -------------------------------- ### C# - Specialized Drug Definitions Source: https://ifbars.github.io/S1API-docs/api/products Defines specialized product types for different drugs, inheriting from ProductDefinition. Examples include WeedDefinition, MethDefinition, and CocaineDefinition. ```csharp public class WeedDefinition : ProductDefinition { // INTERNAL properties and methods omitted public override ItemInstance CreateInstance(int quantity = 1); } ``` ```csharp public class MethDefinition : ProductDefinition { // INTERNAL properties and methods omitted public override ItemInstance CreateInstance(int quantity = 1); } ``` ```csharp public class CocaineDefinition : ProductDefinition { // INTERNAL properties and methods omitted public override ItemInstance CreateInstance(int quantity = 1); } ``` -------------------------------- ### C# Example: Implementing a Custom DeliveryQuest Source: https://ifbars.github.io/S1API-docs/api/quests Demonstrates how to create a custom quest class, 'DeliveryQuest', by inheriting from the abstract 'Quest' class. It defines quest title, description, adds delivery and reward entries, and includes methods to handle quest progression like 'CompleteDelivery' and 'CollectReward'. Requires a 'SaveableField' attribute and an 'OrderData' class. ```csharp public class DeliveryQuest : Quest { protected override string Title => "Delivery Request"; protected override string Description => $"Deliver the requested product and collect payment from the drop."; [SaveableField("OrderData")] private OrderData _orderData = new(); private QuestEntry? _deliveryEntry; private QuestEntry? _rewardEntry; protected override void OnCreated() { _deliveryEntry = AddEntry( $"Deliver {_orderData.Amount}x {_orderData.Product?.Name}.", _orderData.DeliveryLocation ); _rewardEntry = AddEntry( $"Collect ${_orderData.Price:N0}.", _orderData.RewardLocation ); // Initially set reward entry as inactive _rewardEntry.SetState(QuestState.Inactive); } public void CompleteDelivery() { _deliveryEntry?.Complete(); _rewardEntry?.SetState(QuestState.Active); } public void CollectReward() { _rewardEntry?.Complete(); // Quest will auto-complete when all entries are completed } } ``` -------------------------------- ### C# Reflection Utilities for API Development Source: https://ifbars.github.io/S1API-docs/api/internal Offers generic, reflection-based methods to simplify API development. This includes finding derived classes, retrieving types by name, accessing fields, and getting method information. Use with caution in performance-critical sections. ```csharp using S1API.Internal.Utils; using System; using System.Reflection; using System.Collections.Generic; internal static class ReflectionUtils { internal static List GetDerivedClasses(); internal static Type? GetTypeByName(string typeName); internal static FieldInfo[] GetAllFields(Type? type, BindingFlags bindingFlags); public static MethodInfo? GetMethod(Type? type, string methodName, BindingFlags bindingFlags); } ``` ```csharp // Find all classes that derive from a base class List allItemTypes = ReflectionUtils.GetDerivedClasses(); // Find a type by its name Type itemType = ReflectionUtils.GetTypeByName("InventoryItem"); // Get all fields from a type and its base types FieldInfo[] allFields = ReflectionUtils.GetAllFields(typeof(Player), BindingFlags.Instance | BindingFlags.NonPublic); ``` -------------------------------- ### C# Get Item Definition by ID Example Source: https://ifbars.github.io/S1API-docs/api/storages Retrieves an `ItemDefinition` object using its unique ID by calling the static `GetItemDefinition` method from the `ItemManager` class. ```csharp // Get an item definition by ID public ItemDefinition GetItemByID(string itemID) { return ItemManager.GetItemDefinition(itemID); } ``` -------------------------------- ### Create Product Instance - C# Source: https://ifbars.github.io/S1API-docs/api/products This C# code snippet demonstrates how to retrieve a product definition by name, create a new product instance with a specified quantity, and access various properties of both the definition and the instance, such as the icon, quality, packaging status, and custom properties. It requires access to the ProductManager and related classes. ```csharp using System.Linq; // Get a product definition ProductDefinition productDef = ProductManager.DiscoveredProducts.FirstOrDefault(p => p.Name == "Product Name"); if (productDef != null) { // Create an instance (e.g., to add to inventory) ProductInstance productInstance = (ProductInstance)productDef.CreateInstance(5); // Quantity of 5 // Access the icon for a product Sprite productIcon = productDef.Icon; // Inspect instance-specific data var quality = productInstance.Quality; // Quality enum var isPackaged = productInstance.IsPackaged; var packaging = productInstance.AppliedPackaging; var props = productInstance.Properties; // IReadOnlyList } ``` -------------------------------- ### Using SaveableField in Custom Classes (Example) Source: https://ifbars.github.io/S1API-docs/api/save-system This example demonstrates how to use the SaveableField attribute within custom data classes and integrate them into a Quest class. The OrderData class contains fields that will be automatically saved and loaded when marked with [SaveableField]. ```csharp // Define a custom data class for your save data public class OrderData { public ProductDefinition? Product; public int Amount; public int Price; } // Use it in your Quest class public class MyFancyQuest : Quest { // Mark the field to be automatically saved with the SaveableField attribute [SaveableField("Order")] private OrderData _orderData = new OrderData(); public void SetOrderAmount(int amount) { _orderData.Amount = amount; } public void SetOrderProduct(ProductDefinition product) { _orderData.Product = product; } public void SetOrderPrice(int price) { _orderData.Price = price; } } ``` -------------------------------- ### Work with Dead Drop Storage in C# Source: https://ifbars.github.io/S1API-docs/api/dead-drops Shows how to access the storage associated with a dead drop instance and provides a placeholder for interacting with items in the storage, referencing the StorageInstance documentation. ```csharp // Get a dead drop instance DeadDropInstance deadDrop = DeadDropManager.All.FirstOrDefault(); if (deadDrop != null) { // Access its storage StorageInstance storage = deadDrop.Storage; // Now you can use StorageInstance methods to interact with items // (See StorageInstance documentation for details) } ``` -------------------------------- ### Property API Overview Source: https://ifbars.github.io/S1API-docs/api/property This section details the core classes and interfaces for interacting with properties in the game. ```APIDOC ## BaseProperty Class ### Description Abstract base class that defines the common interface for property entities. ### Members #### Properties - **PropertyName** (string) - Gets the name of the property. - **PropertyCode** (string) - Gets the unique code identifier for the property. - **Price** (float) - Gets the price of the property. - **IsOwned** (bool) - Gets whether the property is currently owned. - **EmployeeCapacity** (int) - Gets or sets the maximum number of employees that can be assigned to the property. #### Methods - **SetOwned()** - Marks the property as owned. - **IsPointInside(UnityEngine.Vector3 point)** - Determines if a point is within the property's boundaries. ## PropertyWrapper Class ### Description Concrete implementation of BaseProperty that wraps the game's internal property class. This class handles the differences between IL2CPP and Mono runtime environments using preprocessor directives. ### Constructor - **PropertyWrapper(ScheduleOne.Property.Property property)** - Constructor accepting the game's internal property instance. ### Overridden Members All members inherited from BaseProperty are implemented by delegating to the corresponding functionality in the wrapped property instance. ## PropertyManager Class ### Description Static utility class for accessing and managing property data. Uses conditional compilation to handle differences between IL2CPP and Mono environments. ### Methods - **GetAllProperties()** - Gets a list of all properties in the game. - **GetOwnedProperties()** - Gets a list of all currently owned properties. - **FindPropertyByName(string name)** - Finds a property by its name. ``` -------------------------------- ### C# - Product Instance Structure Source: https://ifbars.github.io/S1API-docs/api/products Represents an instance of a product within the game, inheriting from ItemInstance. It provides information about the product's packaging, quality, and its definition. ```csharp public class ProductInstance : ItemInstance { // INTERNAL properties and methods omitted public bool IsPackaged { get; } public PackagingDefinition AppliedPackaging { get; } public Quality Quality { get; } public ProductDefinition Definition { get; } public System.Collections.Generic.IReadOnlyList Properties { get; } } ``` -------------------------------- ### Manipulating Cash Amount Source: https://ifbars.github.io/S1API-docs/api/money Examples of how to add currency to or set the specific amount of a cash instance. ```APIDOC ## Manipulating Cash Amount ### Description Add currency to a cash instance or set the currency to a specific amount. ### Method N/A (Code Example) ### Endpoint N/A ### Parameters N/A ### Request Example ```csharp // Add currency to a cash instance cashInstance.AddQuantity(50.0f); // Add 50 to the balance // Remove currency from a cash instance cashInstance.AddQuantity(-25.0f); // Remove 25 from the balance // Set currency to a specific amount cashInstance.SetQuantity(200.0f); // Set to exactly 200 ``` ### Response N/A ``` -------------------------------- ### StorageInstance API Source: https://ifbars.github.io/S1API-docs/api/storages Provides methods and events for interacting with storage containers. ```APIDOC ## StorageInstance API ### Description Represents a storage container in-game, allowing for item manipulation and event subscription. ### Methods - **CanItemFit**(ItemInstance itemInstance, int quantity = 1): bool - Checks if a given item and quantity can fit into the storage. - **AddItem**(ItemInstance itemInstance) - Adds an item instance to the storage. ### Events - **OnOpened**: Action - Triggered when the storage container is opened. - **OnClosed**: Action - Triggered when the storage container is closed. ### Properties - **Slots**: ItemSlotInstance[] - An array representing the slots within the storage container. ``` -------------------------------- ### PropertyManager - Accessing All Properties (C#) Source: https://ifbars.github.io/S1API-docs/api/property Demonstrates how to use the GetAllProperties method to retrieve and log details of all properties in the game. It iterates through the list, printing the property name, price, and ownership status. ```csharp using S1API.Property; using System.Collections.Generic; using UnityEngine; public class PropertyExample { public void ListAllProperties() { List allProperties = PropertyManager.GetAllProperties(); Debug.Log($"Total properties: {allProperties.Count}"); foreach (var property in allProperties) { Debug.Log($"Property: {property.PropertyName}, Price: {property.Price}, Owned: {property.IsOwned}"); } } } ``` -------------------------------- ### Utilities Modules Source: https://ifbars.github.io/S1API-docs/api/index Helper systems designed for mod development, including data persistence and internal utilities for cross-compatibility. ```APIDOC ## Utilities ### Description Helper systems for mod development. ### Available Modules - `S1API.SaveSystem`: Data persistence for mods - `S1API.Internal`: Internal utilities for cross-compatibility ``` -------------------------------- ### C# SystemTriggerType Enum Source: https://ifbars.github.io/S1API-docs/api/phone-calls Specifies the different types of system triggers that can be used in call stages, such as triggers that activate at the start or upon completion of a stage. ```csharp public enum SystemTriggerType { StartTrigger, DoneTrigger } ``` -------------------------------- ### Initialize Console API Source: https://ifbars.github.io/S1API-docs/api/console Initializes the Console API by importing the necessary namespace. This is a prerequisite for using any console-related functionalities. ```csharp using S1API.Console; ``` -------------------------------- ### C# Count Items in Storage Example Source: https://ifbars.github.io/S1API-docs/api/storages Calculates the total quantity of a specific item within a storage container by summing up the quantities from all slots containing that item. ```csharp // Count items in storage public int CountItemsInStorage(StorageInstance storage, string itemID) { int total = 0; foreach (var slot in storage.Slots) { if (slot.ItemInstance != null && slot.ItemInstance.Definition.ID == itemID) { total += slot.Quantity; } } return total; } ``` -------------------------------- ### Key Concepts Source: https://ifbars.github.io/S1API-docs/api/index Important concepts to understand when using S1API, focusing on cross-compatibility and type safety. ```APIDOC ## Key Concepts ### Cross-Compatibility All API classes and methods are designed to work seamlessly across both Mono and Il2Cpp builds. The implementation details are abstracted away, allowing you to focus on your mod's functionality. ### Type Safety S1API provides type-safe wrappers around game objects and functions, helping prevent common errors and making your code more robust. ``` -------------------------------- ### C# - Product Manager Access Source: https://ifbars.github.io/S1API-docs/api/products Provides static access to product information within the game. The DiscoveredProducts property returns an array of all available ProductDefinition objects. ```csharp public static class ProductManager { public static ProductDefinition[] DiscoveredProducts { get; } } ``` -------------------------------- ### C# Remove Items From Storage Example Source: https://ifbars.github.io/S1API-docs/api/storages This function iterates through storage slots to remove a specified quantity of a particular item, updating quantities and stopping when the target amount is removed. ```csharp // Remove items from storage public void RemoveItemsFromStorage(StorageInstance storage, string itemID, int quantityToRemove) { foreach (var slot in storage.Slots) { if (slot.ItemInstance != null && slot.ItemInstance.Definition.ID == itemID) { int amountToRemove = Math.Min(slot.Quantity, quantityToRemove); slot.AddQuantity(-amountToRemove); quantityToRemove -= amountToRemove; if (quantityToRemove <= 0) break; } } } ``` -------------------------------- ### PhoneAppManager Class Source: https://ifbars.github.io/S1API-docs/api/phone-app Static class for managing phone apps and their integration with the game. Handles registration and initialization of all custom phone apps. ```APIDOC ## PhoneAppManager Class ### Description Static class for managing phone apps and their integration with the game. Handles registration and initialization of all custom phone apps. ### Methods - **Register(PhoneApp app)** - Registers a custom phone application with the manager. - **InitAll(MelonLogger.Instance logger)** - Initializes all registered phone applications. ```