Skip to content

Commit 1dfbcec

Browse files
Merge pull request #103 from zelzmiy/CustomCrops
Custom Crops
2 parents 0612268 + 971dd73 commit 1dfbcec

File tree

12 files changed

+247
-13
lines changed

12 files changed

+247
-13
lines changed

COTL_API.Common.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<PropertyGroup>
33
<TargetFramework>net472</TargetFramework>
4-
<Version>0.2.6</Version>
4+
<Version>0.2.7</Version>
55
<LangVersion>latest</LangVersion>
66
<DebugType>portable</DebugType>
77
<IsPackable>true</IsPackable>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using UnityEngine;
2+
3+
namespace COTL_API.CustomInventory;
4+
5+
public abstract class CustomCrop : CustomInventoryItem
6+
{
7+
internal StructureBrain.TYPES StructureType { get; set; }
8+
internal int CropStatesCount => CropStates.Count;
9+
10+
/// <summary>
11+
/// The States of this crop, the last state should be the fully grown state. Requires at least two states.
12+
/// </summary>
13+
public virtual List<Sprite> CropStates { get; } = [];
14+
15+
/// <summary>
16+
/// The time it takes for this crop to grow, in game ticks.
17+
/// </summary>
18+
public virtual float CropGrowthTime => 9f;
19+
20+
/// <summary>
21+
/// The Crop and Seed that drops when this is harvested. Must be size 2
22+
/// </summary>
23+
public abstract List<InventoryItem.ITEM_TYPE> HarvestResult { get; }
24+
25+
/// <summary>
26+
/// How long (in seconds) it takes to pick this crop.
27+
/// </summary>
28+
public virtual float PickingTime => 2.5f;
29+
30+
/// <summary>
31+
/// The range in how many resources will drop when collecting.
32+
/// </summary>
33+
public virtual Vector2Int CropCountToDropRange => new(3, 4);
34+
35+
/// <summary>
36+
/// Shows when hovering the crop to harvest it.
37+
/// </summary>
38+
public virtual string HarvestText => "Pick <color=#FD1D03>Berries</color>";
39+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using COTL_API.Guid;
2+
using HarmonyLib;
3+
using UnityEngine;
4+
using UnityEngine.AddressableAssets;
5+
using UnityEngine.ResourceManagement.AsyncOperations;
6+
using static UnityEngine.Object;
7+
8+
namespace COTL_API.CustomInventory;
9+
10+
public static partial class CustomItemManager
11+
{
12+
internal static GameObject CropPrefab = null!;
13+
14+
public static Dictionary<InventoryItem.ITEM_TYPE, CustomCrop> CustomCropList { get; } = [];
15+
private static Dictionary<InventoryItem.ITEM_TYPE, CropController> CropObjectList { get; } = [];
16+
17+
private const string AssetPath = "Prefabs/Structures/Crops/Berry Crop";
18+
19+
public static InventoryItem.ITEM_TYPE Add(CustomCrop crop)
20+
{
21+
var item = Add(crop as CustomInventoryItem);
22+
crop.ItemType = item;
23+
crop.StructureType =
24+
GuidManager.GetEnumValue<StructureBrain.TYPES>(CustomItemList[item].ModPrefix, crop.InternalName);
25+
26+
CustomCropList.Add(item, crop);
27+
28+
return item;
29+
}
30+
31+
private static void CreateCropObject(CustomCrop crop)
32+
{
33+
if (CropPrefab == null)
34+
throw new NullReferenceException("This REALLY shouldn't happen, send a bug report!");
35+
36+
var duplicate = Instantiate(CropPrefab);
37+
38+
if (duplicate == null)
39+
throw new NullReferenceException("Somehow, the Crop Prefab could not be instantiated, send a bug report");
40+
41+
duplicate.transform.name = $"{crop.Name()} Crop";
42+
43+
var cropController = duplicate.GetComponent<CropController>();
44+
45+
cropController.CropStates = [];
46+
cropController.SeedType = crop.ItemType;
47+
48+
// remove extra growth stages in case there are less than 4
49+
DestroyImmediate(duplicate.transform.GetChild(1).gameObject); // Stage 2
50+
DestroyImmediate(duplicate.transform.GetChild(1).gameObject); // Stage 3
51+
DestroyImmediate(duplicate.transform.GetChild(1).gameObject); // Stage 4
52+
53+
var harvest = duplicate.transform.GetChild(1);
54+
var bush = harvest.GetChild(2).GetChild(0).GetChild(0);
55+
56+
var bumperHarvest = duplicate.transform.GetChild(2);
57+
var bumperBush = bumperHarvest.GetChild(3).GetChild(0).GetChild(0);
58+
59+
var cropState = duplicate.transform.GetChild(0);
60+
cropController.CropStates.Add(cropState.gameObject);
61+
62+
if (crop.CropStates.Count > 0)
63+
{
64+
bush.GetComponent<SpriteRenderer>().sprite = crop.CropStates.Last();
65+
bumperBush.GetComponent<SpriteRenderer>().sprite = crop.CropStates.Last();
66+
cropState.GetComponent<SpriteRenderer>().sprite = crop.CropStates[0];
67+
}
68+
69+
for (var i = 1; i < crop.CropStates.Count - 1; i++)
70+
{
71+
var newState = Instantiate(cropState, duplicate.transform);
72+
newState.name = $"Crop {i + 1}";
73+
newState.SetSiblingIndex(i);
74+
newState.GetComponent<SpriteRenderer>().sprite = crop.CropStates[i];
75+
cropController.CropStates.Add(newState.gameObject);
76+
}
77+
78+
cropController.CropStates.Add(harvest.gameObject);
79+
80+
// Ensures that the object doesn't get deleted between scene loads
81+
duplicate.hideFlags = HideFlags.HideAndDontSave;
82+
83+
CropObjectList.Add(crop.ItemType, duplicate.GetComponent<CropController>());
84+
}
85+
86+
public static void InitiateCustomCrops()
87+
{
88+
LogInfo("Getting Crop Asset");
89+
var op = Addressables.Instance.LoadAssetAsync<GameObject>(AssetPath);
90+
op.Completed += (handle) =>
91+
{
92+
if (op.Status != AsyncOperationStatus.Succeeded)
93+
throw new NullReferenceException("Couldn't Find Berry Crop Object, Send a bug report!");
94+
95+
CropPrefab = handle.Result;
96+
CustomCropList.Do(x => CreateCropObject(x.Value));
97+
};
98+
}
99+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using HarmonyLib;
2+
using MonoMod.Utils;
3+
using UnityEngine;
4+
using Object = UnityEngine.Object;
5+
6+
namespace COTL_API.CustomInventory;
7+
8+
[HarmonyPatch]
9+
public static partial class CustomItemManager
10+
{
11+
[HarmonyPatch(typeof(CropController), nameof(CropController.CropStatesForSeedType))]
12+
[HarmonyPostfix]
13+
private static void CropController_CropStatesForSeedType(InventoryItem.ITEM_TYPE seedType, ref int __result)
14+
{
15+
if (!CustomCropList.TryGetValue(seedType, out var item)) return;
16+
17+
__result = item.CropStatesCount;
18+
}
19+
20+
[HarmonyPatch(typeof(CropController), nameof(CropController.CropGrowthTimes))]
21+
[HarmonyPostfix]
22+
private static void CropController_CropGrowthTimes(InventoryItem.ITEM_TYPE seedType, ref float __result)
23+
{
24+
if (!CustomCropList.TryGetValue(seedType, out var item)) return;
25+
26+
__result = item.CropGrowthTime;
27+
}
28+
29+
30+
[HarmonyPatch(typeof(StructuresData), nameof(StructuresData.GetInfoByType))]
31+
[HarmonyPostfix]
32+
private static void StructureData_GetInfoByType(StructureBrain.TYPES Type, ref StructuresData __result)
33+
{
34+
if (CustomCropList.Values.All(x => x.StructureType != Type)) return;
35+
36+
var crop = CustomCropList.Values.First(x => x.StructureType == Type);
37+
// Not sure that this is necessary but just in case?
38+
__result = new StructuresData
39+
{
40+
PrefabPath = "Prefabs/Structures/Other/Berry Bush",
41+
DontLoadMe = true,
42+
ProgressTarget = crop.PickingTime,
43+
MultipleLootToDrop = crop.HarvestResult,
44+
LootCountToDropRange = crop.CropCountToDropRange,
45+
Type = crop.StructureType
46+
};
47+
}
48+
49+
[HarmonyPatch(typeof(StructureBrain), nameof(StructureBrain.CreateBrain))]
50+
[HarmonyPostfix]
51+
private static void StructureBrain_CreateBrain(StructuresData data, ref StructureBrain __result)
52+
{
53+
if (CustomCropList.Values.All(x => x.StructureType != data.Type)) return;
54+
55+
__result = new Structures_BerryBush();
56+
}
57+
58+
[HarmonyPatch(typeof(FarmPlot), nameof(FarmPlot.Awake))]
59+
[HarmonyPostfix]
60+
private static void FarmPlot_Awake(FarmPlot __instance)
61+
{
62+
foreach(var kvp in CropObjectList)
63+
{
64+
__instance._cropPrefabsBySeedType.Add(kvp.Key, kvp.Value);
65+
}
66+
}
67+
68+
[HarmonyPatch(typeof(Interaction_Berries), nameof(Interaction_Berries.OnBrainAssigned))]
69+
[HarmonyPostfix]
70+
private static void Interaction_Berries_OnBrainAssigned(Interaction_Berries __instance)
71+
{
72+
var cropController = __instance.GetComponentInParent<CropController>();
73+
74+
if (cropController == null) return;
75+
if (!CustomCropList.TryGetValue(cropController.SeedType, out var crop)) return;
76+
77+
__instance.StructureBrain.Data.MultipleLootToDrop = crop.HarvestResult;
78+
__instance.StructureBrain.Data.LootCountToDropRange = crop.CropCountToDropRange;
79+
__instance.BerryPickingIncrements = 1.25f / crop.PickingTime;
80+
}
81+
82+
[HarmonyPatch(typeof(Interaction_Berries), nameof(Interaction_Berries.UpdateLocalisation))]
83+
[HarmonyPostfix]
84+
private static void Interaction_Berries_UpdateLocalisation(Interaction_Berries __instance)
85+
{
86+
var cropController = __instance.GetComponentInParent<CropController>();
87+
if (cropController == null) return;
88+
if (!CustomCropList.TryGetValue(cropController.SeedType, out var crop)) return;
89+
90+
__instance.sLabelName = crop.HarvestText;
91+
}
92+
}

COTL_API/CustomInventory/CustomFood/CustomDrinks/CustomDrink.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ namespace COTL_API.CustomInventory;
33
public abstract class CustomDrink : CustomFood
44
{
55
internal FollowerBrain.PleasureActions PleasureAction { get; set; }
6-
public override InventoryItem.ITEM_TYPE ItemPickUpToImitate { get; } = InventoryItem.ITEM_TYPE.DRINK_GIN;
6+
public sealed override InventoryItem.ITEM_TYPE ItemPickUpToImitate { get; } = InventoryItem.ITEM_TYPE.DRINK_GIN;
77

88
/// <summary>
99
/// The amount of Sin gained by the follower. Range: 0-65

COTL_API/CustomInventory/CustomFood/CustomMeals/CustomMeal.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public abstract class CustomMeal : CustomFood
88
/// </summary>
99
public abstract float TummyRating { get; }
1010

11-
public override InventoryItem.ITEM_TYPE ItemPickUpToImitate { get; } = InventoryItem.ITEM_TYPE.MEAL;
11+
public sealed override InventoryItem.ITEM_TYPE ItemPickUpToImitate { get; } = InventoryItem.ITEM_TYPE.MEAL;
1212
public virtual MealQuality Quality { get; } = MealQuality.NORMAL;
1313
public virtual bool MealSafeToEat { get; } = true;
1414
}

COTL_API/CustomInventory/CustomInventoryItem.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ public abstract class CustomInventoryItem
2929
public virtual bool IsFood => false;
3030
public virtual bool IsBigFish => false;
3131
public virtual bool IsCurrency => false;
32-
public virtual bool IsSeed => false;
33-
public virtual bool IsPlantable => false;
3432
public virtual bool IsBurnableFuel => false;
3533

3634
public virtual bool CanBeGivenToFollower => false;

COTL_API/CustomInventory/Patches/CustomInventoryPatches.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ private static bool InventoryItem_CapacityString(InventoryItem.ITEM_TYPE type, i
217217
[HarmonyPostfix]
218218
private static void InventoryItem_AllPlantables(ref List<InventoryItem.ITEM_TYPE> __result)
219219
{
220-
__result.AddRange(CustomItemList.Where(x => x.Value.IsPlantable).Select(x => x.Key));
220+
__result.AddRange(CustomCropList.Select(x => x.Key));
221221
}
222222

223223
[HarmonyPatch(typeof(InventoryItem), nameof(InventoryItem.GiveToFollowerCallbacks))]
@@ -239,7 +239,7 @@ private static bool InventoryItem_GiveToFollowerCallbacks(InventoryItem.ITEM_TYP
239239
[HarmonyPostfix]
240240
private static void InventoryItem_AllSeeds(ref List<InventoryItem.ITEM_TYPE> __result)
241241
{
242-
__result.AddRange(CustomItemList.Where(x => x.Value.IsSeed).Select(x => x.Key));
242+
__result.AddRange(CustomCropList.Select(x => x.Key));
243243
}
244244

245245
[HarmonyPatch(typeof(InventoryItem), nameof(InventoryItem.AllBurnableFuel), MethodType.Getter)]

COTL_API/Debug/DebugItemClass2.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22

33
namespace COTL_API.Debug;
44

5-
public class DebugItemClass2 : CustomInventoryItem
5+
public class DebugItemClass2 : CustomCrop
66
{
77
public override string InternalName => "DEBUG_ITEM_2";
88

99
public override CustomInventoryItemType InventoryItemType => CustomInventoryItemType.FOOD;
1010

1111
public override bool IsFood => true;
12-
public override bool IsSeed => true;
12+
13+
public override List<InventoryItem.ITEM_TYPE> HarvestResult { get; } =
14+
[
15+
Plugin.Instance.DebugItem,
16+
Plugin.Instance.DebugItem2,
17+
];
1318
}

COTL_API/Debug/DebugItemClass3.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,4 @@ public class DebugItemClass3 : CustomInventoryItem
66
{
77
public override string InternalName => "DEBUG_ITEM_3";
88

9-
public override bool IsPlantable => true;
109
}

0 commit comments

Comments
 (0)