|
| 1 | +--- |
| 2 | +title: Food |
| 3 | +description: Documentation on how to add a custom Meal using the Cult Of The Lamb API |
| 4 | +--- |
| 5 | +Creating custom food is almost identical to creating custom items, and custom food posses all the overrides that custom items do. |
| 6 | +Custom food can also have custom MealEffects that trigger upon consuming the food. |
| 7 | + |
| 8 | +## Creating Meals |
| 9 | + |
| 10 | +To create a custom meal, create a class that overrides `CustomMeal`: |
| 11 | + |
| 12 | +```csharp |
| 13 | +using COTL_API.CustomInventory; |
| 14 | +using COTL_API.Helpers; |
| 15 | +using UnityEngine; |
| 16 | +using System.IO; |
| 17 | + |
| 18 | +public class ExampleMeal : CustomMeal |
| 19 | +{ |
| 20 | + override string InternalName => "Example_Meal"; |
| 21 | + public override string LocalizedName() { return "Example Meal"; } |
| 22 | + public override string LocalizedDescription() { return "This is an example meal"; } |
| 23 | + //used for spawning object in the world |
| 24 | + public override Sprite Sprite => TextureHelper.CreateSpriteFromPath(Path.Combine(Plugin.PluginPath, "Assets", "example_meal.png")); |
| 25 | + |
| 26 | + // A list of Effects that will occur when eating this Meal |
| 27 | + override MealEffect[] MealEffects => |
| 28 | + [ |
| 29 | + new MealEffect() |
| 30 | + { |
| 31 | + MealEffectType = CookingData.MealEffectType.InstantlyVomit, |
| 32 | + Chance = 50; |
| 33 | + } |
| 34 | + ]; |
| 35 | + // used for cooking the meal. |
| 36 | + //the outer list is for storing different recipes for the same Meal |
| 37 | + //the inner list is for the items and quantities that the recipe requires |
| 38 | + public override List<List<InventoryItem>> Recipe => |
| 39 | + [ |
| 40 | + [ |
| 41 | + ] |
| 42 | + ]; |
| 43 | +} |
| 44 | + |
| 45 | +// this is the "Star Rating" of the meal. Range: [0, 3] |
| 46 | +public override int SatiationLevel => 3; |
| 47 | + |
| 48 | +//this is the amount that the "hunger circle" is filled when cooking the meal. Range: [0, 1] |
| 49 | +public override float TummyRating => 0.6f; |
| 50 | +``` |
| 51 | + |
| 52 | + |
| 53 | +Custom Meals support all the overrides that custom items do, despite the fact that many of them are non-functional. all overrides that modify the behaviour of the item in-inventory don't function, as you don't pick up meals into your inventory. |
| 54 | + |
| 55 | +> WARNING: |
| 56 | +> Overriding `ItemPickupToImitate` with any item that isn't a meal will cause an error! |
| 57 | +
|
| 58 | +`CustomMeal` support the following overrides: |
| 59 | + |
| 60 | +| Type | Name | Default | |
| 61 | +|-|-|-| |
| 62 | +|List<List<InventoryItem.ITEM_TYPE>>|Recipe|\[REQUIRED\]| |
| 63 | +|CookingData.MealEffects[]|MealEffects|\[REQUIRED\]| |
| 64 | +|Vector3|ItemDisplayOffset|null| |
| 65 | +|MealQuality|Quality|MealQuality.NORMAL| |
| 66 | +|float|TummyRating|0| |
| 67 | +|int|SatiationLevel|0| |
| 68 | +|bool|MealSafeToEat|true| |
| 69 | + |
| 70 | +## Adding Meals |
| 71 | + |
| 72 | +To add a custom meal into the game, simply use `CustomItemManager.Add()`. |
| 73 | +Example: |
| 74 | + |
| 75 | +```csharp |
| 76 | +using COTL_API.CustomInventory; |
| 77 | + |
| 78 | +public static InventoryItem.ITEM_TYPE ExampleMeal { get; private set; } |
| 79 | + |
| 80 | +private void Awake() |
| 81 | +{ |
| 82 | + ExampleMeal = CustomItemManager.Add(new ExampleMeal()); |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +Assigning the result of `CustomItemManager.Add()` allows you to reference that meal elsewhere in your code using `Plugin.ExampleMeal`. |
| 87 | + |
| 88 | +## Creating Drinks |
| 89 | + |
| 90 | +To create a custom drink, create a class that overrides `CustomDrink`: |
| 91 | + |
| 92 | +```csharp |
| 93 | +using COTL_API.CustomInventory; |
| 94 | +using COTL_API.Helpers; |
| 95 | +using UnityEngine; |
| 96 | +using System.IO; |
| 97 | + |
| 98 | +public class ExampleDrink : CustomDrink |
| 99 | +{ |
| 100 | + override string InternalName => "Example_Drink"; |
| 101 | + public override string LocalizedName() { return "Example Drink"; } |
| 102 | + public override string LocalizedDescription() { return "This is an example drink"; } |
| 103 | + //used for spawning object in the world |
| 104 | + public override Sprite Sprite => TextureHelper.CreateSpriteFromPath(Path.Combine(Plugin.PluginPath, "Assets", "example_drink.png")); |
| 105 | + |
| 106 | + // A list of Effects that will occur when drinking this Drink |
| 107 | + override MealEffect[] MealEffects => |
| 108 | + [ |
| 109 | + new MealEffect() |
| 110 | + { |
| 111 | + MealEffectType = CookingData.MealEffectType.CausesDrunk, |
| 112 | + Chance = 75 |
| 113 | + } |
| 114 | + ]; |
| 115 | + // used for brewing the drink. |
| 116 | + //the outer list is for storing different recipes for the same Drink |
| 117 | + //the inner list is for the items and quantities that the recipe requires |
| 118 | + public override List<List<InventoryItem>> Recipe => |
| 119 | + [ |
| 120 | + [ |
| 121 | + ] |
| 122 | + ]; |
| 123 | +} |
| 124 | + |
| 125 | +// this is the "Star Rating" of the drink. Range: 0-3 |
| 126 | +public override int SatiationLevel => 2; |
| 127 | + |
| 128 | +// this is the amount of Sin gained by the follower who drinks this Drink, |
| 129 | +// range: [0, 65] |
| 130 | +public override int Pleasure => 50; |
| 131 | +``` |
| 132 | +>WARNING: |
| 133 | +> Overriding `ItemPickupToImitate` with any item that isn't a drink will cause an error! |
| 134 | +
|
| 135 | +`CustomDrink` supports the following overrides: |
| 136 | + |
| 137 | +| Type | Name | Default | |
| 138 | +|-|-|-| |
| 139 | +|List<List<InventoryItem.ITEM_TYPE>>|Recipe|\[REQUIRED\]| |
| 140 | +|CookingData.MealEffects[]|MealEffects|\[REQUIRED\]| |
| 141 | +|int|SatiationLevel|0| |
| 142 | +|Vector3|ItemDisplayOffset|null| |
| 143 | +|int|Pleasure|0| |
| 144 | + |
| 145 | +## Adding Drinks |
| 146 | + |
| 147 | +To add a custom drink into the game, simply use `CustomItemManager.Add()`. |
| 148 | +Example: |
| 149 | + |
| 150 | +```csharp |
| 151 | +using COTL_API.CustomInventory; |
| 152 | + |
| 153 | +public static InventoryItem.ITEM_TYPE ExampleDrink { get; private set; } |
| 154 | + |
| 155 | +private void Awake() |
| 156 | +{ |
| 157 | + ExampleDrink = CustomItemManager.Add(new ExampleDrink()); |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +## Creating MealEffects |
| 162 | + |
| 163 | +MealEffects occur when a follower or player consume a meal. To create a custom MealEffect you first create a class overriding `CustomMealEffect`. Example: |
| 164 | + |
| 165 | +```csharp |
| 166 | +using COTL_API.CustomInventory; |
| 167 | +using COTL_API.Helpers; |
| 168 | +using UnityEngine; |
| 169 | +using System.IO; |
| 170 | + |
| 171 | +public class ExampleMealEffect : CustomMealEffect |
| 172 | +{ |
| 173 | + public override string Internal name => "ExampleEffect"; |
| 174 | + public override Action<FollowerBrain> Effect = DoSomething; |
| 175 | + |
| 176 | + public void DoSomething(FollowerBrain follower) |
| 177 | + { |
| 178 | + LogInfo($"my name is {FollowerBrain.Info.Name} and I just ate something."); |
| 179 | + } |
| 180 | +} |
| 181 | +``` |
| 182 | + |
| 183 | +To add the effect to the game, simply use `CustomMealEffectManager.Add()`. |
| 184 | +Example: |
| 185 | + |
| 186 | +```csharp |
| 187 | +using COTL_API.CustomInventory; |
| 188 | + |
| 189 | +public static CookingData.MealEffectType ExampleMealEffect { get; private set; } |
| 190 | + |
| 191 | +private void Awake() |
| 192 | +{ |
| 193 | + ExampleMealEffect = CustomMealEffectManager.Add(new ExampleMealEffect()); |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +Assigning the result of `CustomMealEffectmManager.Add()` allows you to reference that meal elsewhere in your code using `Plugin.ExampleMealEffect`. |
| 198 | + |
| 199 | +> WARNING: Make sure to register Custom Meal Effects before you register your custom meals, otherwise any custom meal effects Won't work. Alternatively use Lazy loading. |
| 200 | +
|
| 201 | +`CustomMealEffect` supports the following overrides: |
| 202 | + |
| 203 | +| Type | Name | Default | |
| 204 | +|-|-|-| |
| 205 | +| string | InternalName | \[REQUIRED\] | |
| 206 | +| Action\<FollowerBrain\> | Effect | \[REQUIRED\]| |
| 207 | +|bool | EffectEnabled()| true | |
| 208 | +|bool|Positive()|true| |
| 209 | +|string| Description()|$"CookingData/{InternalName}/Description"| |
| 210 | +|string|DescriptionSuffix()|""| |
| 211 | + |
| 212 | +## Final Steps |
| 213 | + |
| 214 | +For the icon to load, you need to put it in the appropriate location. For the example, this would be `/Assets/example_food.png` relative to the root folder containing the .dll |
| 215 | +Directory structure: |
| 216 | + |
| 217 | +``` |
| 218 | +📂plugins |
| 219 | + ┣📂Assets |
| 220 | + ┃ ┗🖼️example_meal.png |
| 221 | + ┃ ┗🖼️example_drink.png |
| 222 | + ┗📜mod_name.dll |
| 223 | +``` |
0 commit comments