-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Creature Eggs, AddHint, resource tracking, and various fixes (#451
) * Fixed bothersome grammar * Added PrefabUtils.AddResourceTracker * Added `AssetReference.ForceValid` extension method * Added `ErrorMessage.AddHint` extension method * Added EggTemplate * Added EggGadget * Added example for creature eggs * Formatting fixes (wtf Metious) * Fix compilation errors on BZ branch * Use chelicerate egg for BZ example * Use hardcoded string for hint * Remove unused using * Fix problematic example mod patch --------- Co-authored-by: LeeTwentyThree <31892011+LeeTwentyThree@users.noreply.github.com>
- Loading branch information
1 parent
f04d892
commit c127bd9
Showing
10 changed files
with
650 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
using System.Reflection; | ||
using BepInEx; | ||
using HarmonyLib; | ||
using Nautilus.Assets; | ||
using Nautilus.Assets.Gadgets; | ||
using Nautilus.Assets.PrefabTemplates; | ||
using Nautilus.Extensions; | ||
using UnityEngine; | ||
using UnityEngine.AddressableAssets; | ||
using UWE; | ||
|
||
namespace Nautilus.Examples; | ||
|
||
[BepInPlugin("com.snmodding.nautilus.creatureegg", "Nautilus Creature Egg Example Mod", Nautilus.PluginInfo.PLUGIN_VERSION)] | ||
[BepInDependency("com.snmodding.nautilus")] | ||
public class CreatureEggExample : BaseUnityPlugin | ||
{ | ||
/// <summary> | ||
/// This patch is required because the reaper leviathan doesn't have a WaterParkCreature component and it's required for creatures in the ACU to work properly. | ||
/// </summary> | ||
[HarmonyPatch(typeof(LiveMixin), nameof(LiveMixin.Awake))] | ||
private static class Patcher | ||
{ | ||
[HarmonyPostfix] | ||
private static void AwakePostfix(Creature __instance) | ||
{ | ||
# if SUBNAUTICA | ||
if (!__instance.TryGetComponent(out ReaperLeviathan _)) | ||
#else | ||
if (!__instance.TryGetComponent(out Chelicerate _)) | ||
#endif | ||
{ | ||
return; | ||
} | ||
|
||
#if SUBNAUTICA | ||
if (!PrefabDatabase.TryGetPrefabFilename(CraftData.GetClassIdForTechType(TechType.ReaperLeviathan), out var filename)) | ||
#else | ||
if (!PrefabDatabase.TryGetPrefabFilename(CraftData.GetClassIdForTechType(TechType.Chelicerate), out var filename)) | ||
#endif | ||
{ | ||
return; | ||
} | ||
|
||
var wpc = __instance.gameObject.EnsureComponent<WaterParkCreature>(); | ||
wpc.data = ScriptableObject.CreateInstance<WaterParkCreatureData>(); | ||
wpc.data.eggOrChildPrefab = new AssetReferenceGameObject(filename).ForceValid(); | ||
wpc.data.canBreed = true; | ||
// Initial size is when the creature just hatched | ||
wpc.data.initialSize = 0.04f; | ||
|
||
// Max size is the maximum size this creature can reach inside the ACU | ||
wpc.data.maxSize = 0.05f; | ||
|
||
// Outside size is when you drop the creature outside of the ACU | ||
wpc.data.outsideSize = 0.07f; | ||
|
||
// How long will it take for this creature to reach the maximum size | ||
wpc.data.daysToGrow = 6; | ||
|
||
wpc.data.isPickupableOutside = false; | ||
} | ||
} | ||
private void Awake() | ||
{ | ||
#if SUBNAUTICA | ||
CustomPrefab customEgg = new CustomPrefab("ReaperEgg", "Reaper Leviathan Egg", "Reaper Leviathan Egg that makes me go yes."); | ||
#else | ||
CustomPrefab customEgg = new CustomPrefab("ChelicerateEgg", "Chelicerate Egg", "Chelicerate Egg that makes me go yes."); | ||
#endif | ||
customEgg.Info.WithSizeInInventory(new Vector2int(3, 3)); | ||
|
||
/* | ||
* Here we make the creature egg immune to the brine acid. Please note that a creature egg doesn't require an egg gadget to work. | ||
* The egg gadget simply has methods that add additional item functionality to the egg, but the egg will still work like an | ||
* egg without this gadget. | ||
* In this example, we've used the egg gadget simply to make it acid immune. | ||
*/ | ||
EggGadget eggGadget = customEgg.CreateCreatureEgg(); | ||
eggGadget.SetAcidImmune(true); | ||
|
||
/* | ||
* Here we set the required ACU stacks to two. This means that you cannot drop this egg in an ACU unless you have 2 ACUs stacks on top of each other. | ||
*/ | ||
eggGadget.WithRequiredAcuSize(2); | ||
|
||
/* | ||
* Here we create an egg template instance that copies the Crash Egg model. | ||
* In the object initializer, we're setting the hatching creature to ReaperLeviathan and also made the egg take 3 days to hatch. | ||
*/ | ||
#if SUBNAUTICA | ||
EggTemplate egg = new EggTemplate(customEgg.Info, TechType.CrashEgg) | ||
#else | ||
EggTemplate egg = new EggTemplate(customEgg.Info, TechType.RockPuncherEgg) | ||
#endif | ||
{ | ||
#if SUBNAUTICA | ||
HatchingCreature = TechType.ReaperLeviathan, | ||
#else | ||
HatchingCreature = TechType.Chelicerate, | ||
#endif | ||
HatchingTime = 3 | ||
}; | ||
|
||
/* | ||
* Here we make this egg have an unidentified egg tech type before hatching. Once it hatches, it will receive the main egg tech type. | ||
*/ | ||
egg.SetUndiscoveredTechType(); | ||
|
||
/* | ||
* Set the game object of our custom prefab to the egg template we setup. | ||
*/ | ||
customEgg.SetGameObject(egg); | ||
|
||
/* | ||
* Register our custom fabricator to the game. | ||
* After this point, do not edit the prefab or modify gadgets as they will not be applied. | ||
*/ | ||
customEgg.Register(); | ||
|
||
Harmony.CreateAndPatchAll(typeof(CreatureEggExample), PluginInfo.PLUGIN_GUID); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
using Nautilus.Extensions; | ||
using Nautilus.Patchers; | ||
using Nautilus.Utility; | ||
|
||
namespace Nautilus.Assets.Gadgets; | ||
|
||
/// <summary> | ||
/// Represents a creature egg gadget. | ||
/// </summary> | ||
public class EggGadget : Gadget | ||
{ | ||
/// <summary> | ||
/// The total amount of ACU floors required for the egg to be dropped in the ACU. defaulted to 1. | ||
/// </summary> | ||
public int RequiredAcuSize { get; set; } = 1; | ||
|
||
/// <summary> | ||
/// makes the egg immune to the Lost River's Acidic Brine. | ||
/// </summary> | ||
public bool AcidImmune { get; set; } = true; | ||
|
||
/// <summary> | ||
/// Constructs a Creature egg gadget instance. | ||
/// </summary> | ||
/// <param name="prefab">The custom prefab to operate on.</param> | ||
/// <param name="requiredAcuSize">The total amount of ACU floors required for the egg to be dropped in the ACU.</param> | ||
public EggGadget(ICustomPrefab prefab, int requiredAcuSize = 1) : base(prefab) | ||
{ | ||
RequiredAcuSize = requiredAcuSize; | ||
} | ||
|
||
/// <summary> | ||
/// The total amount of ACU floors required for the egg to be dropped in the ACU. | ||
/// </summary> | ||
/// <param name="requiredAcuSize">The ACU stacks value.</param> | ||
/// <returns>A reference to this instance after the operation has completed.</returns> | ||
public EggGadget WithRequiredAcuSize(int requiredAcuSize) | ||
{ | ||
RequiredAcuSize = requiredAcuSize; | ||
|
||
return this; | ||
} | ||
|
||
/// <summary> | ||
/// makes the egg immune to the Lost River's Acidic Brine. | ||
/// </summary> | ||
/// <param name="isAcidImmune">Should this item be acid immune?</param> | ||
/// <returns>A reference to this instance after the operation has completed.</returns> | ||
public EggGadget SetAcidImmune(bool isAcidImmune) | ||
{ | ||
AcidImmune = isAcidImmune; | ||
|
||
return this; | ||
} | ||
|
||
/// <inheritdoc/> | ||
protected internal override void Build() | ||
{ | ||
if (prefab.Info.TechType is TechType.None) | ||
{ | ||
InternalLogger.Error($"Prefab '{prefab.Info}' does not contain a TechType. Skipping {nameof(EggGadget)} build."); | ||
return; | ||
} | ||
|
||
if (AcidImmune) | ||
DamageSystem.acidImmune.Add(prefab.Info.TechType); | ||
|
||
if (RequiredAcuSize > 1) | ||
{ | ||
WaterParkPatcher.requiredAcuSize[prefab.Info.TechType] = RequiredAcuSize; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.