using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using GrubAdoption.Assets;
using GrubAdoption.Rescuing;
using GrubAdoption.Stats;
using GrubAdoption.Utils;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using WKLib.Assets;
using WKLib.Core;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.anonymousfroggo.grubadoption")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1+d01fbfb03a7f654059ed71cd8d032b7382e254f4")]
[assembly: AssemblyProduct("Grub Adoption")]
[assembly: AssemblyTitle("com.anonymousfroggo.grubadoption")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace GrubAdoption
{
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.anonymousfroggo.grubadoption", "Grub Adoption", "0.2.1")]
public class Plugin : BaseUnityPlugin
{
private bool initialized;
public static Plugin Instance { get; private set; }
public ModContext ModContext { get; private set; }
private void Awake()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
ModContext = ModRegistry.Register("com.anonymousfroggo.grubadoption", "0.2.1");
new Harmony("com.anonymousfroggo.grubadoption").PatchAll();
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
switch (((Scene)(ref scene)).name)
{
case "Intro":
Initialize();
break;
case "Game-Main":
case "Playground":
OnGameLoaded(scene);
break;
}
}
private async void Initialize()
{
if (!initialized)
{
Log.Initialize(((BaseUnityPlugin)this).Logger);
CustomScriptManager.RegisterAssembly(Assembly.GetExecutingAssembly(), ModContext);
await GrubAdoptionAssets.Initialize();
initialized = true;
}
}
private void OnGameLoaded(Scene scene)
{
}
public static GameObject FindGameManagerGameObject(Scene scene)
{
GameObject val = (from gameObject in ((Scene)(ref scene)).GetRootGameObjects()
where ((Object)gameObject).name == "GameManager"
select gameObject).FirstOrDefault();
if ((Object)(object)val == (Object)null)
{
Log.Error("Finding GameManager failed");
return null;
}
return val;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.anonymousfroggo.grubadoption";
public const string PLUGIN_NAME = "Grub Adoption";
public const string PLUGIN_VERSION = "0.2.1";
}
}
namespace GrubAdoption.Utils
{
public static class AssetUtils
{
public const string BASE_DATABASE = "basedatabase";
public static GameObject GetAsset(string name)
{
return CL_AssetManager.GetAssetGameObject(name, "basedatabase");
}
public static Item GetItem(string itemName)
{
return GetAsset(itemName).GetComponent<Item_Object>().itemData;
}
}
public class DebugHelper : MonoBehaviour
{
public static void Initialize(Scene scene)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
GameObject obj = Plugin.FindGameManagerGameObject(scene);
if (obj != null)
{
obj.AddComponent<DebugHelper>();
}
}
private void Start()
{
CommandConsole.AddCommand("grubsstored", (Action<string[]>)GrubsStoredCommand, false);
CommandConsole.AddCommand("liststats", (Action<string[]>)ListStatsCommand, false);
CommandConsole.AddCommand("savestats", (Action<string[]>)SaveStatsCommand, false);
CommandConsole.AddCommand("win", (Action<string[]>)WinCommand, false);
}
private static void GrubsStoredCommand(string[] args)
{
CommandConsole.Log(GrubRescueStation.GetGrubsStored().ToString(), false);
}
private static void ListStatsCommand(string[] args)
{
StatUtils.StatSource result;
if (args.Length == 0)
{
PrintStatsList(StatUtils.StatSource.global);
PrintStatsList(StatUtils.StatSource.gamemode);
PrintStatsList(StatUtils.StatSource.session);
}
else if (!Enum.TryParse<StatUtils.StatSource>(args[0], ignoreCase: true, out result))
{
CommandConsole.LogError("Not a valid stat source: " + args[0]);
}
else
{
PrintStatsList(result);
}
static void PrintStatsList(StatUtils.StatSource source)
{
List<Statistic> list = new List<Statistic>(StatUtils.GetStats(source).statistics);
list.Sort((Statistic x, Statistic y) => x.id.CompareTo(y.id));
foreach (Statistic item in list)
{
CommandConsole.Log($"Stat ({source}): {item.id} = {item.GetString()}", false);
}
}
}
private static void SaveStatsCommand(string[] args)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
ActivateCheats();
foreach (Statistic statistic in StatManager.sessionStats.statistics)
{
StatManager.saveData.gameStats.UpdateStatistic(statistic.id, statistic.GetValue(), statistic.type, statistic.defaultModType, statistic.displayType, (ModType)1);
}
if ((Object)(object)CL_GameManager.gamemode != (Object)null)
{
StatManager.saveData.UpdateGamemodeStats(CL_GameManager.GetGamemodeName(true, false), StatManager.sessionStats);
}
File.WriteAllText(Path.Combine(Application.persistentDataPath, "save.json"), JsonUtility.ToJson((object)StatManager.saveData, true));
StatManager.instance.UpdateUI();
}
private static void WinCommand(string[] args)
{
ActivateCheats();
CL_GameManager.gMan.Win();
}
private static void ActivateCheats()
{
if (!CommandConsole.cheatsEnabled)
{
CommandConsole.instance.ExecuteCommand("cheats");
}
}
}
public static class InventoryUtils
{
public static int TotalItemCount(string itemName)
{
return BagItemCount(itemName) + HandItemCount(itemName);
}
public static int BagItemCount(string itemName)
{
return ENT_Player.GetInventory().bagItems.Count((Item bagItem) => bagItem.itemName.Equals(itemName));
}
public static int HandItemCount(string itemName)
{
return ENT_Player.GetInventory().itemHands.Count((ItemHand itemHand) => itemHand.currentItem != null && itemHand.currentItem.itemName.Equals(itemName));
}
public static void LoadItemIntoBag(Item item)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
Item clone = item.GetClone();
clone.bagPosition = new Vector3(0f, 0f, 1f) + Random.insideUnitSphere * 0.01f;
clone.bagRotation = Quaternion.LookRotation(clone.upDirection);
Inventory.instance.AddItemToInventoryScreen(clone.bagPosition, clone, true, true);
clone.inventory = Inventory.instance;
}
}
public static class Log
{
private static ManualLogSource log;
internal static void Initialize(ManualLogSource log)
{
Log.log = log;
}
public static void Info(object msg)
{
ManualLogSource obj = log;
if (obj != null)
{
obj.LogInfo(msg);
}
}
public static void Warn(object msg)
{
ManualLogSource obj = log;
if (obj != null)
{
obj.LogWarning(msg);
}
}
public static void Error(object msg)
{
ManualLogSource obj = log;
if (obj != null)
{
obj.LogError(msg);
}
}
public static void Debug(object msg)
{
ManualLogSource obj = log;
if (obj != null)
{
obj.LogDebug(msg);
}
}
}
public static class Names
{
public static class Denizens
{
public const string GRUB = "Denizen_SlugGrub";
}
public static class Gamemodes
{
public const string CAMPAIGN = "GM_Campaign";
public const string PLAYGROUND = "GM_Playground";
}
public static class Items
{
public const string GRUB = "SlugGrub";
}
public static class Scenes
{
public const string INTRO = "Intro";
public const string MAIN_MENU = "Main-Menu";
public const string GAME_MAIN = "Game-Main";
public const string PLAYGROUND = "Playground";
}
public static class Stats
{
}
public static class Ui
{
public const string SCORE_PANEL_STANDARD_PREFIX = "ScorePanel_Standard";
public const string SCORE_SCREEN_SESSION_STAT_PREFIX = "session-stat:";
public const string SCORE_SCREEN_GAMEMODE_STAT_PREFIX = "gamemode-stat:";
public const string GAMEMODE_STAT_PREFIX = "stat-";
public const string LOGBOOK_STAT_PREFIX = "stat-";
}
public const string GAME_MANAGER = "GameManager";
public static string Instantiated(string name)
{
return name + "(Clone)";
}
}
public static class Paths
{
}
public static class StatUtils
{
public enum StatSource
{
session,
gamemode,
global
}
public const string STAT_PICKUP_ITEM_PREFIX = "pickup-item-";
public const string STAT_ITEMS_USED = "items-used";
public const string DEFAULT_TEXT_REDACTED = "[REDACTED]";
public static string GetText(CustomStat stat, StatSource statSource)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected I4, but got Unknown
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
GameStats val = (GameStats)((int)statSource switch
{
2 => StatManager.sessionStats,
0 => StatManager.saveData.GetGameMode(CL_GameManager.GetGamemodeName(true, false)).stats,
3 => StatManager.saveData.gameStats,
_ => null,
});
if (!val.HasStatistic(stat.GetId()))
{
return stat.GetDefaultText(statSource);
}
return stat.GetTextPrefix(statSource) + val.GetStatistic(stat.GetId()).GetString();
}
public static bool HasStat(string id)
{
if (!StatManager.saveData.gameStats.HasStatistic(id))
{
return StatManager.sessionStats.HasStatistic(id);
}
return true;
}
public static bool HasPickedUpItem(string itemName)
{
return HasStat("pickup-item-" + itemName);
}
public static object GetValueOrDefault(string id, object defaultValue, StatSource source)
{
Statistic stat = GetStat(id, source);
return ((stat != null) ? stat.GetValue() : null) ?? defaultValue;
}
public static Statistic GetStat(string id, StatSource source)
{
GameStats stats = GetStats(source);
if (stats == null)
{
return null;
}
return stats.GetStatistic(id);
}
public static GameStats GetStats(StatSource source)
{
return (GameStats)(source switch
{
StatSource.session => StatManager.sessionStats,
StatSource.gamemode => StatManager.saveData.GetGameMode(CL_GameManager.GetGamemodeName(true, false))?.stats,
StatSource.global => StatManager.saveData.gameStats,
_ => null,
});
}
}
public static class UiUtils
{
public static void Destroy(Transform child)
{
Object.Destroy((Object)(object)((Component)child).gameObject);
}
public static void DestroyChild(string childName, Transform parent)
{
Transform val = parent.Find(childName);
if ((Object)(object)val == (Object)null)
{
Log.Error("Child " + childName + " of " + ((Object)parent).name + " not found");
}
else
{
Destroy(val);
}
}
}
}
namespace GrubAdoption.Stats
{
public abstract class CustomStat
{
private readonly string id;
protected object value;
private readonly DataType type;
private readonly ModType modType;
private readonly DisplayType displayType;
private readonly ModType globalModType;
protected CustomStat(string id, object initialValue, DataType dataType, ModType modType, DisplayType displayType, ModType globalModType)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
this.id = id;
value = initialValue;
type = dataType;
this.modType = modType;
this.displayType = displayType;
this.globalModType = globalModType;
base..ctor();
}
public void EndGameStatUpdate(bool win)
{
if (CalculateValueOnEndGame(win))
{
WriteToSessionStats();
}
}
protected virtual bool CalculateValueOnEndGame(bool win)
{
return false;
}
private void WriteToSessionStats()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
StatManager.sessionStats.UpdateStatistic(id, value, type, modType, displayType, globalModType);
}
public string GetId()
{
return id;
}
public abstract string GetDefaultText(StatSource statSource);
public abstract string GetTextPrefix(StatSource statSource);
public abstract bool ShouldAddToScoreScreenSession(bool win);
public abstract bool ShouldAddToScoreScreenGamemode(bool win);
public abstract bool ShouldAddToGamemode(M_Gamemode gamemode);
public abstract bool ShouldAddToLogbook();
public virtual int GetScoreScreenSessionIndex()
{
return 0;
}
public virtual int GetScoreScreenGamemodeIndex()
{
return 0;
}
public virtual int GetGamemodeIndex()
{
return 0;
}
public virtual int GetLogbookIndex()
{
return 0;
}
}
[HarmonyPatch]
public class CustomStatManager
{
public enum StatSource
{
gamemode = 0,
session = 2,
global = 3
}
private static readonly CustomStatManager instance = new CustomStatManager();
private readonly CustomStat[] customStats = new CustomStat[2]
{
new GrubsAdopted(),
new MaxGrubsAdopted()
};
public static bool Win { get; set; }
[HarmonyPatch(typeof(CL_GameManager), "EndGameStatUpdate")]
[HarmonyPostfix]
public static void EndGameStatUpdate(bool win)
{
Win = win;
CustomStat[] array = instance.customStats;
for (int i = 0; i < array.Length; i++)
{
array[i].EndGameStatUpdate(Win);
}
GrubStats.UpdateGrubScore();
}
[HarmonyPatch(typeof(UI_ScoreScreen), "ShowScreen")]
[HarmonyPostfix]
public static void AddStatsToScoreScreen(UI_ScoreScreen __instance)
{
if (!((Object)((Component)__instance).gameObject).name.StartsWith("ScorePanel_Standard"))
{
return;
}
Transform val = ((Component)__instance).gameObject.transform.Find("Session Page/Board/Stats/SessionStats/Game Stats Simplified");
Transform val2 = ((Component)__instance).gameObject.transform.Find("Session Page/Board/Stats/Best Stats/Top Score");
CustomStat[] array = instance.customStats;
foreach (CustomStat customStat in array)
{
if (customStat.ShouldAddToScoreScreenSession(Win))
{
GameObject obj = Object.Instantiate<GameObject>(((Component)val.GetChild(4)).gameObject, val);
((Object)obj).name = "session-stat:" + customStat.GetId();
obj.transform.SetSiblingIndex(customStat.GetScoreScreenSessionIndex());
((TMP_Text)obj.GetComponent<TextMeshProUGUI>()).text = StatUtils.GetText(customStat, (StatSource)2);
}
if (customStat.ShouldAddToScoreScreenGamemode(Win))
{
Transform transform = Object.Instantiate<GameObject>(((Component)val2.GetChild(3)).gameObject, val2).transform;
((Object)((Component)transform).gameObject).name = "gamemode-stat:" + customStat.GetId();
transform.SetSiblingIndex(customStat.GetScoreScreenGamemodeIndex());
((TMP_Text)((Component)transform).GetComponent<TextMeshProUGUI>()).text = StatUtils.GetText(customStat, (StatSource)0);
}
}
}
[HarmonyPatch(typeof(UI_GamemodeScreen), "Initialize")]
[HarmonyPostfix]
public static void AddStatsToGamemode(UI_GamemodeScreen __instance, M_Gamemode mode)
{
Transform val = ((Component)__instance).gameObject.transform.Find("Gamemode_Panel_Base_Campaign(Clone)/Mode Page/Board/Stats/Stats/Scoregrid-Extra/");
if ((Object)(object)val == (Object)null)
{
return;
}
CustomStat[] array = instance.customStats;
foreach (CustomStat customStat in array)
{
Transform val2 = val.Find("stat-" + customStat.GetId());
if ((Object)(object)val2 != (Object)null)
{
UiUtils.Destroy(val2);
}
if (customStat.ShouldAddToGamemode(mode))
{
val2 = InstantiateStatText(customStat, val, "stat-", 1);
val2.SetSiblingIndex(customStat.GetGamemodeIndex());
((Component)val2).GetComponent<UT_StatText>().Refresh();
}
}
}
[HarmonyPatch(typeof(UI_MenuScreen), "Initialize")]
[HarmonyPostfix]
public static void AddStatsToLogbook(UI_MenuScreen __instance)
{
if (!((Object)__instance).name.Equals("Logbook"))
{
return;
}
Transform parent = ((Component)__instance).gameObject.transform.Find("Stat Page/Board/Stats/Stats/Scoregrid-Extra");
UiUtils.DestroyChild("Break-Roaches.02", parent);
UiUtils.DestroyChild("Break-Roaches", parent);
CustomStat[] array = instance.customStats;
foreach (CustomStat customStat in array)
{
if (customStat.ShouldAddToLogbook())
{
InstantiateStatText(customStat, parent, "stat-", 1).SetSiblingIndex(customStat.GetLogbookIndex());
}
}
}
private static Transform InstantiateStatText(CustomStat stat, Transform parent, string uiNamePrefix, int instantiationIndex)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
Transform transform = Object.Instantiate<GameObject>(((Component)parent.GetChild(instantiationIndex)).gameObject, parent).transform;
((Object)((Component)transform).gameObject).name = uiNamePrefix + stat.GetId();
UT_StatText component = ((Component)transform).GetComponent<UT_StatText>();
component.defaultText = stat.GetDefaultText(component.source);
component.textPrefix = stat.GetTextPrefix(component.source);
((Object)component).name = uiNamePrefix + stat.GetId();
component.statistic = stat.GetId();
return transform;
}
}
public class GrubsAdopted : CustomStat
{
public const string ID = "grubs-adopted";
public const string DEFAULT_TEXT_NO_GRUBS = "Don't you care about Grubs? :(";
public const string DEFAULT_TEXT_DEATH_WITH_GRUB = "You left your Grub alone T.T";
public const string DEFAULT_TEXT_DEATH_WITH_GRUBS = "You left your Grubs alone T.T";
public const string TEXT_PREFIX_SESSION = "Grubs Adopted: ";
public const string TEXT_PREFIX_GLOBAL = "Total Grubs Adopted: ";
public GrubsAdopted()
: base("grubs-adopted", 0, (DataType)0, (ModType)1, (DisplayType)0, (ModType)1)
{
}
protected override bool CalculateValueOnEndGame(bool win)
{
if (!win)
{
return false;
}
if (GrubStats.GetRescuedGrubsCount() == 0)
{
return false;
}
value = GrubStats.GetRescuedGrubsCount();
return true;
}
public override string GetDefaultText(StatSource statSource)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
if (!StatUtils.HasPickedUpItem("SlugGrub"))
{
return "[REDACTED]";
}
if ((int)statSource == 2)
{
return GrubStats.GetRescuedGrubsCount() switch
{
0 => "Don't you care about Grubs? :(",
1 => "You left your Grub alone T.T",
_ => "You left your Grubs alone T.T",
};
}
return GetTextPrefix(statSource) + 0;
}
public override string GetTextPrefix(StatSource statSource)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
if ((int)statSource != 2)
{
return "Total Grubs Adopted: ";
}
return "Grubs Adopted: ";
}
public override bool ShouldAddToScoreScreenSession(bool win)
{
if (ShouldAddToGamemode(CL_GameManager.gamemode))
{
return StatUtils.HasPickedUpItem("SlugGrub");
}
return false;
}
public override bool ShouldAddToScoreScreenGamemode(bool win)
{
if (ShouldAddToGamemode(CL_GameManager.gamemode))
{
return StatUtils.HasPickedUpItem("SlugGrub");
}
return false;
}
public override bool ShouldAddToGamemode(M_Gamemode gamemode)
{
if (!((Object)gamemode).name.Equals("GM_Campaign"))
{
return ((Object)gamemode).name.Equals("GM_Playground");
}
return true;
}
public override bool ShouldAddToLogbook()
{
return true;
}
public override int GetScoreScreenSessionIndex()
{
return 7;
}
public override int GetScoreScreenGamemodeIndex()
{
return 7;
}
public override int GetGamemodeIndex()
{
return 14;
}
public override int GetLogbookIndex()
{
return 13;
}
}
public static class GrubStats
{
public const string ID_GRUB_SCORE = "grub-score";
public static float winScoreMultiplier = 5f;
public static void UpdateGrubScore()
{
if (CL_GameManager.gMan.GetGameTime() != 0f)
{
float playerBestTravelDistance = CL_GameManager.gMan.GetPlayerBestTravelDistance();
int rescuedGrubsCount = GetRescuedGrubsCount();
float num = CL_GameManager.gMan.GetGameTime() / 60f;
float num2 = (float)rescuedGrubsCount / num;
float num3 = playerBestTravelDistance * num2;
if (CustomStatManager.Win)
{
num3 *= winScoreMultiplier;
}
num3 = (float)Math.Round(num3, 2, MidpointRounding.AwayFromZero);
Log.Info($"Grub Score: {num3}");
Log.Info($" = {num2} (#Grubs/Minute that made it out) * {(int)playerBestTravelDistance} Meters (Distance)" + (CustomStatManager.Win ? " * 5 (Because you escaped)" : ""));
StatManager.sessionStats.UpdateStatistic("grub-score", (object)num3, (DataType)2, (ModType)0, (DisplayType)0, (ModType)2);
string text = StatUtils.GetStat("grub-score", StatUtils.StatSource.gamemode)?.value.ToString();
Log.Info("Previous Best: " + (text ?? "N/A"));
}
}
public static int GetRescuedGrubsCount()
{
int num = GrubRescueStation.GetGrubsStored();
if (CustomStatManager.Win)
{
num += InventoryUtils.TotalItemCount("SlugGrub");
}
return num;
}
}
public class MaxGrubsAdopted : CustomStat
{
public MaxGrubsAdopted()
: base("max-grubs-adopted", 0, (DataType)0, (ModType)2, (DisplayType)0, (ModType)2)
{
}
protected override bool CalculateValueOnEndGame(bool win)
{
if (!win)
{
return false;
}
if (GrubStats.GetRescuedGrubsCount() == 0)
{
return false;
}
value = GrubStats.GetRescuedGrubsCount();
return true;
}
public override string GetDefaultText(StatSource statSource)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
if (!StatUtils.HasPickedUpItem("SlugGrub"))
{
return "[REDACTED]";
}
return GetTextPrefix(statSource) + 0;
}
public override string GetTextPrefix(StatSource statSource)
{
return "Most Adopted in a Run: ";
}
public override bool ShouldAddToScoreScreenSession(bool win)
{
return false;
}
public override bool ShouldAddToScoreScreenGamemode(bool win)
{
if (ShouldAddToGamemode(CL_GameManager.gamemode))
{
return StatUtils.HasPickedUpItem("SlugGrub");
}
return false;
}
public override bool ShouldAddToGamemode(M_Gamemode gamemode)
{
if (!((Object)gamemode).name.Equals("GM_Campaign"))
{
return ((Object)gamemode).name.Equals("GM_Playground");
}
return true;
}
public override bool ShouldAddToLogbook()
{
return true;
}
public override int GetScoreScreenGamemodeIndex()
{
return 8;
}
public override int GetGamemodeIndex()
{
return 15;
}
public override int GetLogbookIndex()
{
return 14;
}
}
public class StatRequirement : CustomScript
{
public enum OverrideMode
{
replace,
and,
or
}
public string id;
public int fromInt = int.MinValue;
public int toInt = int.MaxValue;
public string matchString;
public float fromFloat = float.NegativeInfinity;
public float toFloat = float.PositiveInfinity;
public StatUtils.StatSource source;
public OverrideMode overrideMode;
public bool metWhenUndefined;
private void Start()
{
GameObject gameObject = ((Component)this).gameObject;
gameObject.SetActive(overrideMode switch
{
OverrideMode.replace => IsMet(),
OverrideMode.and => ((Component)this).gameObject.activeInHierarchy && IsMet(),
OverrideMode.or => ((Component)this).gameObject.activeInHierarchy || IsMet(),
_ => ((Component)this).gameObject.activeInHierarchy,
});
}
private bool IsMet()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected I4, but got Unknown
Statistic stat = StatUtils.GetStat(id, source);
if (stat == null)
{
return metWhenUndefined;
}
object value = stat.GetValue();
DataType type = stat.type;
return (int)type switch
{
0 => fromInt <= (int)value && (int)value <= toInt,
1 => (string)value == matchString,
2 => fromFloat <= (float)value && (float)value <= toFloat,
_ => false,
};
}
}
}
namespace GrubAdoption.Rescuing
{
public class GrubDispenser : CustomScript, Clickable
{
[CompilerGenerated]
private sealed class <<Interact>g__PlaySound|3_0>d : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public GrubDispenser <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <<Interact>g__PlaySound|3_0>d(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
GrubDispenser grubDispenser = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSeconds(Random.value * grubDispenser.delayRangeDispenseGrub);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
grubDispenser.clipHandler.PlaySound("grub-dispensing:dispense-grub");
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public float delayRangeDispenseGrub = 0.8f;
private UT_AudioClipHandler clipHandler;
private void Start()
{
clipHandler = ((Component)this).GetComponent<UT_AudioClipHandler>();
}
public void Interact(ENT_Player p, string s)
{
clipHandler.PlaySound("grub-dispensing:boop");
int grubsStored = GrubRescueStation.GetGrubsStored();
Log.Info($"Dispensing grubs: {grubsStored}");
if (grubsStored != 0)
{
Item item = AssetUtils.GetItem("Denizen_SlugGrub");
for (int i = 0; i < grubsStored; i++)
{
InventoryUtils.LoadItemIntoBag(item);
((MonoBehaviour)this).StartCoroutine(PlaySound());
}
GrubRescueStation.ResetGrubsStored();
}
[IteratorStateMachine(typeof(<<Interact>g__PlaySound|3_0>d))]
IEnumerator PlaySound()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <<Interact>g__PlaySound|3_0>d(0)
{
<>4__this = this
};
}
}
public bool CanInteract(ENT_Player p, Hand hand)
{
return true;
}
public ObjectTagger GetTagger()
{
return ((Component)this).gameObject.GetComponent<ObjectTagger>();
}
public GameObject GetGameObject()
{
return ((Component)this).gameObject;
}
}
public class GrubRescueStation : CustomScript
{
[CompilerGenerated]
private sealed class <<InsertGrub>g__PlaySounds|5_0>d : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public GrubRescueStation <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <<InsertGrub>g__PlaySounds|5_0>d(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Expected O, but got Unknown
int num = <>1__state;
GrubRescueStation grubRescueStation = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
if (grubRescueStation.clipHandler.GetGroup("grub-rescuing").GetSet("exit-inventory").aud.isPlaying)
{
<>2__current = (object)new WaitForSeconds(grubRescueStation.delayRangeExitInventory);
<>1__state = 1;
return true;
}
goto IL_0070;
case 1:
<>1__state = -1;
goto IL_0070;
case 2:
{
<>1__state = -1;
grubRescueStation.clipHandler.PlaySound("grub-rescuing:enter-station");
return false;
}
IL_0070:
grubRescueStation.clipHandler.PlaySound("grub-rescuing:exit-inventory");
<>2__current = (object)new WaitForSeconds(grubRescueStation.delayEnterStation);
<>1__state = 2;
return true;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public const string FLAG_GRUBS_STORED = "grubs-stored";
public float delayRangeExitInventory = 0.1f;
public float delayEnterStation = 0.15f;
private UT_AudioClipHandler clipHandler;
private void Start()
{
clipHandler = ((Component)this).GetComponent<UT_AudioClipHandler>();
}
public void InsertGrub()
{
((MonoBehaviour)this).StartCoroutine(PlaySounds());
SetGrubsStored(GetGrubsStored() + 1);
Log.Info($"Grub inserted (stored: {GetGrubsStored()})");
[IteratorStateMachine(typeof(<<InsertGrub>g__PlaySounds|5_0>d))]
IEnumerator PlaySounds()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <<InsertGrub>g__PlaySounds|5_0>d(0)
{
<>4__this = this
};
}
}
public static int GetGrubsStored()
{
SessionFlag gameFlag = CL_GameManager.GetGameFlag("grubs-stored");
if (gameFlag == null || gameFlag.data == null)
{
return 0;
}
return int.Parse(gameFlag.data);
}
public static void ResetGrubsStored()
{
SetGrubsStored(0);
}
private static void SetGrubsStored(int amount)
{
CL_GameManager.SetGameFlag("grubs-stored", true, amount.ToString(), false, false);
}
}
public class GrubSlot : CustomScript, Clickable
{
private const string INTERACTOR_TAG = "GrubSlot";
private GrubRescueStation rescueStation;
private void Start()
{
rescueStation = ((Component)this).GetComponentInParent<GrubRescueStation>();
if ((int)StatUtils.GetValueOrDefault("grubs-adopted", 0, StatUtils.StatSource.global) <= 0)
{
GetTagger().tags.Remove("GrubSlot");
}
}
public void Interact(ENT_Player p, string s = "")
{
rescueStation.InsertGrub();
}
public bool CanInteract(ENT_Player p, Hand hand)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
if ((int)hand.interactState == 5)
{
return hand.inventoryHand.currentItem.itemName == "SlugGrub";
}
return false;
}
public ObjectTagger GetTagger()
{
return ((Component)this).gameObject.GetComponent<ObjectTagger>();
}
public GameObject GetGameObject()
{
return ((Component)this).gameObject;
}
}
[HarmonyPatch]
public static class GrubUsagePrevention
{
private static readonly Dictionary<int, Clickable> interactorClickables = new Dictionary<int, Clickable>
{
{ 0, null },
{ 1, null }
};
[HarmonyPatch(typeof(HandItem_Buff), "Use")]
[HarmonyPrefix]
public static bool PreventGrubUse(HandItem_Buff __instance)
{
Clickable interactorClickable = GetInteractorClickable(((Hand_Base)__instance).hand.id);
if (((HandItem)__instance).item.itemName == "SlugGrub" && (interactorClickable is GrubSlot || interactorClickable is GrubDispenser))
{
return false;
}
return true;
}
[HarmonyPatch(typeof(Item_Interactor_Insertable), "Interact")]
[HarmonyPostfix]
public static void SetInteractorClickables(Hand curhand, Clickable clickable)
{
interactorClickables[curhand.id] = clickable;
}
[HarmonyPatch(typeof(Inventory), "Update")]
[HarmonyPostfix]
public static void ResetInteractorClickables()
{
interactorClickables[0] = null;
interactorClickables[1] = null;
}
public static Clickable GetInteractorClickable(int handId)
{
if (!interactorClickables.ContainsKey(handId))
{
return null;
}
return interactorClickables[handId];
}
}
}
namespace GrubAdoption.Assets
{
public class CustomScript : MonoBehaviour
{
private const char KEY_VALUE_SEPARATOR = ':';
public void Initialize(UT_Null initializer)
{
Dictionary<string, string> dictionary = ParseData(initializer);
Log.Info("Initializing " + initializer.id + " at " + ((Object)((Component)initializer).gameObject).name);
foreach (string key in dictionary.Keys)
{
FieldInfo field = ((object)this).GetType().GetField(key);
if (field == null)
{
CustomScriptManager.Error(initializer, "No public field \"" + key + "\" found in script");
break;
}
object obj = ChangeType(dictionary[key], field.FieldType);
if (obj == null)
{
CustomScriptManager.Error(initializer, $"Couldn't parse {dictionary[key]} to type {field.GetType()}");
}
field.SetValue(this, obj);
}
}
private static Dictionary<string, string> ParseData(UT_Null initializer)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (string datum in initializer.data)
{
string[] array = datum.Split(':');
if (array.Length != 2)
{
CustomScriptManager.Error(initializer, "\"" + datum + "\" is not a valid key-value pair");
}
else
{
dictionary.Add(array[0], array[1]);
}
}
return dictionary;
}
private static object ChangeType(string value, Type type)
{
if (type.IsEnum)
{
return Enum.Parse(type, value, ignoreCase: true);
}
return Convert.ChangeType(value, type);
}
}
public class CustomScriptManager
{
private const char MOD_ID_SCRIPT_NAME_SEPARATOR = ':';
private static MethodInfo addComponentGeneric;
private readonly Dictionary<string, Type> scriptTypes = new Dictionary<string, Type>();
public static CustomScriptManager Instance { get; private set; }
private static void Initialize()
{
Instance = new CustomScriptManager();
addComponentGeneric = typeof(GameObject).GetMethod("AddComponent", Array.Empty<Type>());
UT_Null._OnAwake = (Action<UT_Null>)Delegate.Combine(UT_Null._OnAwake, new Action<UT_Null>(Instance.ReplaceInitializer));
}
public static void RegisterAssembly(Assembly assembly, ModContext modContext)
{
if (Instance == null)
{
Initialize();
}
IEnumerable<Type> enumerable = from type in assembly.GetTypes()
where type.IsSubclassOf(typeof(CustomScript))
select type;
Log.Info($"In assembly {assembly.GetName().Name}: Found {enumerable.Count()} CustomScript type(s)");
foreach (Type item in enumerable)
{
RegisterScriptType(item, modContext);
}
}
public static void RegisterScriptType(Type scriptType, ModContext modContext)
{
if (Instance == null)
{
Initialize();
}
Instance.scriptTypes.Add(modContext.ModID + ":" + scriptType.Name, scriptType);
}
private void ReplaceInitializer(UT_Null initializer)
{
GameObject gameObject = ((Component)initializer).gameObject;
if (!scriptTypes.ContainsKey(initializer.id))
{
if (!initializer.id.Contains(':'))
{
Error(initializer, $"id must be of the form \"<mod context id>{':'}<CustomScript name>\"");
}
else
{
Error(initializer, "Unknown CustomScript name. Did you register your assembly in the CustomScriptManager?");
}
return;
}
Type type = scriptTypes[initializer.id];
CustomScript obj = (CustomScript)addComponentGeneric.MakeGenericMethod(type).Invoke(gameObject, Array.Empty<object>());
if ((Object)(object)obj == (Object)null)
{
Error(initializer, "AddComponent failed");
}
obj.Initialize(initializer);
Object.Destroy((Object)(object)initializer);
}
public static void Error(UT_Null initializer, string msg)
{
Log.Error("Error while parsing UT_Null script \"" + initializer.id + "\" for " + ((Object)((Component)initializer).gameObject).name + ": " + msg);
}
}
[HarmonyPatch]
public static class GrubAdoptionAssets
{
private static readonly string ASSET_BUNDLE_FILE = Path.Combine("..", "anonymousfroggo-GrubAdoption", "grub-adoption.assets");
private static AssetService assetService;
private static AssetBundle assetBundle;
public static GameObject LevelModifications_Campaign { get; private set; }
public static Item_Interactor_Insertable Interactor_Grub { get; private set; }
public static GameObject LevelModifications_Debug { get; private set; }
public static async Task Initialize()
{
if (assetService == null)
{
assetService = new AssetService(Plugin.Instance.ModContext);
assetBundle = await assetService.LoadBundleRelativeAsync(ASSET_BUNDLE_FILE, (IProgress<float>)null);
InitializeLevelModifications();
InitializeGrubInteractor();
}
}
private static void InitializeLevelModifications()
{
LevelModificationLoader levelModificationLoader = new LevelModificationLoader(Plugin.Instance.ModContext, (M_Gamemode gamemode) => ((Object)gamemode).name == "GM_Campaign" && !gamemode.IsIronKnuckle());
LevelModifications_Campaign = assetBundle.LoadAsset<GameObject>("LevelModifications_Campaign");
levelModificationLoader.RegisterModificationsFromChildren(LevelModifications_Campaign);
}
private static void InitializeGrubInteractor()
{
Interactor_Grub = assetBundle.LoadAsset<Item_Interactor_Insertable>("Interactor_Grub");
}
[HarmonyPatch(typeof(Item), "InitializeInHand")]
[HarmonyPostfix]
public static void TrySetInteractor(Item __instance, ref Item_Interactor ___interactor)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
if (!(__instance.itemName != "SlugGrub") && (int)__instance.interactType == 0)
{
___interactor = (Item_Interactor)(object)Object.Instantiate<Item_Interactor_Insertable>(Interactor_Grub);
__instance.interactType = (InteractType)2;
Log.Info("Set interactor to " + ((Object)Interactor_Grub).name);
}
}
}
public class LevelModification
{
private const string ASSET_PREFIX = "LM_";
private readonly GameObject asset;
private readonly LevelModificationLoader loader;
public string Level { get; }
public LevelModification(GameObject asset, LevelModificationLoader loader)
{
this.asset = asset;
this.loader = loader;
string name = ((Object)asset).name;
if (!name.StartsWith("LM_"))
{
Log.Error("Error while loading LevelModification " + name + ": Name must match pattern LM_<level name>");
return;
}
string text = name;
int length = "LM_".Length;
Level = text.Substring(length, text.Length - length);
}
public void InjectInto(GameObject levelObject)
{
Log.Info("Injecting a LevelModification into " + Level);
InjectRecursive(asset.transform, levelObject.transform);
}
private void InjectRecursive(Transform assetNode, Transform levelObjectNode)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
foreach (Transform item in assetNode)
{
Transform val = item;
Transform val2 = levelObjectNode.Find(((Object)val).name);
if ((Object)(object)val2 != (Object)null)
{
InjectRecursive(val, val2);
continue;
}
Log.Info("Injecting " + ((Object)val).name + " at " + ((Object)levelObjectNode).name);
((Object)Object.Instantiate<Transform>(val, levelObjectNode)).name = loader.GetScopedName(((Object)val).name);
}
}
}
[HarmonyPatch]
public class LevelModificationLoader
{
private static readonly List<LevelModificationLoader> loaders = new List<LevelModificationLoader>();
private readonly ModContext modContext;
private readonly Func<M_Gamemode, bool> LoadInGamemode;
private readonly Dictionary<string, LevelModification> modificationsDict = new Dictionary<string, LevelModification>();
public LevelModificationLoader(ModContext modContext, Func<M_Gamemode, bool> LoadInGamemode = null)
{
this.modContext = modContext;
this.LoadInGamemode = LoadInGamemode ?? ((Func<M_Gamemode, bool>)((M_Gamemode _) => true));
loaders.Add(this);
}
public void RegisterModification(GameObject modificationAsset)
{
LevelModification levelModification = new LevelModification(modificationAsset, this);
modificationsDict.Add(levelModification.Level, levelModification);
Log.Info("Registered LevelModification for " + levelModification.Level);
}
public void RegisterModificationsFromChildren(GameObject parent)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
foreach (Transform item in parent.transform)
{
Transform val = item;
RegisterModification(((Component)val).gameObject);
}
}
public string GetScopedName(string name)
{
return name + "(" + modContext.ModID + ")";
}
[HarmonyPatch(typeof(M_Level), "Awake")]
[HarmonyPostfix]
public static void InjectLevelModifications(M_Level __instance)
{
foreach (LevelModificationLoader item in loaders.Where((LevelModificationLoader loader) => loader.LoadInGamemode(CL_GameManager.gamemode) && loader.modificationsDict.ContainsKey(__instance.levelName)))
{
item.modificationsDict[__instance.levelName].InjectInto(((Component)__instance).gameObject);
}
}
}
}