using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Hura.Project;
using Hura.Project.Cheats;
using Hura.Project.Utility;
using HuraHappyTimes.Project;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HuraHappyTimes")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("HP")]
[assembly: AssemblyProduct("HuraHappyTimes")]
[assembly: AssemblyCopyright("Copyright © HP 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("36b637e7-d1d5-43d1-94b8-14d41177383c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HuraHappyTimes.Project
{
[HarmonyPatch(typeof(ShipTeleporter))]
public class TeleporterCheat
{
[HarmonyPatch("PressTeleportButtonClientRpc")]
[HarmonyPrefix]
public static void OnTeleportPressedPatch(ref ShipTeleporter __instance)
{
__instance.cooldownAmount = 10f;
}
}
}
namespace Hura
{
[BepInPlugin("Hura.HappyTimes", "Hura Happy Times", "1.0.2")]
public class HuraHappyTimes : BaseUnityPlugin
{
private const string MOD_GUID = "Hura.HappyTimes";
private const string MOD_NAME = "Hura Happy Times";
private const string MOD_VERSION = "1.0.2";
private readonly Harmony harmony = new Harmony("Hura.HappyTimes");
public static HuraHappyTimes Instance { get; private set; }
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
Log.Init(Logger.CreateLogSource("Hura.HappyTimes"));
harmony.PatchAll(typeof(HuraHappyTimes));
harmony.PatchAll(typeof(TerminalHelper));
harmony.PatchAll(typeof(TerminalCheats));
harmony.PatchAll(typeof(TeleporterCheat));
Log.Message("Hura's Happy Times has been loaded!");
}
}
public static class Log
{
private static ManualLogSource logger;
public static void Init(ManualLogSource instance)
{
logger = instance;
}
public static void Message(string message)
{
logger.LogMessage((object)message);
}
public static void Error(string error)
{
logger.LogError((object)error);
}
public static void Warning(string warning)
{
logger.LogWarning((object)warning);
}
public static void NullReference(object obj, string name)
{
logger.LogMessage((object)("Is " + name + " null? " + ((obj == null) ? "Yes" : "No")));
}
}
}
namespace Hura.Project
{
internal static class ItemsHelper
{
public const string WALKIE_TALKIE_NAME = "Walkie-talkie";
public const string FLASHLIGHT_NAME = "Flashlight";
public const string SHOVEL_NAME = "Shovel";
public const string LOCKPICKER_NAME = "Lockpicker";
public const string PRO_FLASHLIGHT_NAME = "Pro-flashlight";
public const string STUN_GRENADE_NAME = "Stun grenade";
public const string BOOMBOX_NAME = "Boombox";
public const string TZP_INHALANT_NAME = "TZP-Inhalant";
public const string ZAP_GUN_NAME = "Zap gun";
public const string JETPACK_NAME = "Jetpack";
public const string EXTENSION_LADDER_NAME = "Extension ladder";
public const string RADAR_BOOSTER_NAME = "Radar-booster";
public const string SPRAY_PAINT_NAME = "Spray paint";
public static Item[] GetItems()
{
return TerminalHelper.Terminal.buyableItemsList;
}
public static Item GetItem(string itemName)
{
Item[] items = GetItems();
foreach (Item val in items)
{
if (val.itemName == itemName)
{
return val;
}
}
Log.Error("Couldn't find item with name: " + itemName + ".");
return null;
}
}
internal static class MoonsHelper
{
public struct MoonData
{
public int Cost { get; set; }
public TerminalNode Node { get; set; }
public TerminalNode ConfirmNode { get; set; }
public string Name => ((Object)Node).name;
}
public enum RerouteID
{
Company = -1,
Moons = -2
}
private static List<MoonData> moons;
public static IReadOnlyList<MoonData> Moons => moons;
public static bool IsMoonsConfirmationNode(TerminalNode node)
{
if (node.buyRerouteToMoon != -1)
{
return node.buyRerouteToMoon != -2;
}
return false;
}
public static void PopulateMoonsData()
{
Terminal terminal = TerminalHelper.Terminal;
if ((Object)(object)terminal == (Object)null)
{
Log.Error("Error while populating moons data. Couldn't find the Terminal.");
return;
}
moons = new List<MoonData>();
TerminalKeyword[] allKeywords = terminal.terminalNodes.allKeywords;
foreach (TerminalKeyword val in allKeywords)
{
if ((Object)(object)val == (Object)null || val.word == null || !(val.word == "route"))
{
continue;
}
CompatibleNoun[] compatibleNouns = val.compatibleNouns;
for (int j = 0; j < compatibleNouns.Length; j++)
{
TerminalNode result = compatibleNouns[j].result;
if ((Object)(object)result == (Object)null || result.buyRerouteToMoon != -2)
{
continue;
}
MoonData item = default(MoonData);
item.Node = result;
item.Cost = result.itemCost;
CompatibleNoun[] terminalOptions = result.terminalOptions;
foreach (CompatibleNoun val2 in terminalOptions)
{
if (val2.result.itemCost > 0)
{
item.ConfirmNode = val2.result;
}
}
moons.Add(item);
Log.Message($"Added Moon. Node: {item.Node}. Cost: {item.Cost}.");
}
}
}
}
public enum SpecialTerminalNode
{
Login,
Home,
CannotAffordItems,
UnableToRouteNeedOrbit,
DevileryVehicleIsFull,
Error,
MissingCreatureData,
UnableToBuyDecorationNeedOrbit,
AlreadyInOrbit,
DataCorrupted,
NoActionWasGivenWithWord,
ParsingError,
ActionWasIncompatibleWithObject,
Help,
AlreadyUnlock,
ShipIsStuck,
ItemNotInStock,
ItemReturnedFromStorage,
LockedFromDemo,
BroadcastCodeEntered,
RadarSwitchToPlayer,
RadarPinged,
TransmissionSent,
FlashedRadar
}
[HarmonyPatch(typeof(Terminal))]
public static class TerminalHelper
{
private static StringBuilder stringBuilder = new StringBuilder();
public static Terminal Terminal { get; private set; }
[HarmonyPatch("Awake")]
[HarmonyPostfix]
public static void RegisterTerminalInstance(ref Terminal __instance)
{
Terminal = __instance;
}
public static TerminalNode CreateNode(string text, bool clear = true)
{
TerminalNode obj = ScriptableObject.CreateInstance<TerminalNode>();
obj.displayText = text;
obj.clearPreviousText = clear;
return obj;
}
public static TerminalKeyword CreateKeyword(string word, bool isVerb, TerminalNode destinationNode)
{
TerminalKeyword obj = ScriptableObject.CreateInstance<TerminalKeyword>();
obj.word = word;
obj.isVerb = isVerb;
obj.specialKeywordResult = destinationNode;
return obj;
}
public static void AddKeyworkToTerminal(TerminalKeyword keyword)
{
ArrayUtility.Add(ref Terminal.terminalNodes.allKeywords, keyword);
}
public static string CreateNodeText(params string[] args)
{
stringBuilder.Clear();
for (int i = 0; i < args.Length; i++)
{
stringBuilder.Append(args[i]).Append("\n");
}
return stringBuilder.ToString();
}
public static CompatibleNoun CreateCompatibleNoun(TerminalKeyword noun, TerminalNode destinationNode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
return new CompatibleNoun
{
noun = noun,
result = destinationNode
};
}
public static void AddCompatibleNounToVerb(TerminalKeyword verb, TerminalKeyword noun, TerminalNode destinationNode)
{
if (!verb.isVerb)
{
Log.Error("Error while adding compatible noun to verb. Given verb is not a verb: " + verb.word);
return;
}
if (noun.isVerb)
{
Log.Error("Error while adding compatible noun to verb. Given noun is a verb: " + noun.word);
return;
}
CompatibleNoun element = CreateCompatibleNoun(noun, destinationNode);
ArrayUtility.Add(ref verb.compatibleNouns, element);
}
public static TerminalNode GetSpecialNode(SpecialTerminalNode specialNode)
{
List<TerminalNode> specialNodes = Terminal.terminalNodes.specialNodes;
if (!specialNodes.IsValidIndex((int)specialNode))
{
Log.Error($"Error while trying to get special node at index [{(int)specialNode}]. Returning the first special node...");
return specialNodes[0];
}
return Terminal.terminalNodes.specialNodes[(int)specialNode];
}
}
internal class UpdateHelper
{
public static void LogAllSpecialNodes()
{
for (int i = 0; i < TerminalHelper.Terminal.terminalNodes.specialNodes.Count; i++)
{
TerminalNode val = TerminalHelper.Terminal.terminalNodes.specialNodes[i];
Log.Message($"Node [{i}]: {val.displayText}]");
}
}
public static void LogAllItemsInfos()
{
Item[] buyableItemsList = TerminalHelper.Terminal.buyableItemsList;
foreach (Item val in buyableItemsList)
{
Log.Message($"Item name: {val.itemName}. Item ID: {val.itemId}.");
}
}
public static void LogAllMoonsInfos()
{
SelectableLevel[] moonsCatalogueList = TerminalHelper.Terminal.moonsCatalogueList;
foreach (SelectableLevel val in moonsCatalogueList)
{
Log.Message($"Moon. Name: {val.PlanetName}. ID: {val.levelID}. Scene Name: {val.sceneName}");
}
Log.Message($"Moon Nodes. {TerminalHelper.Terminal.terminalNodes.terminalNodes.Count}");
foreach (TerminalNode terminalNode in TerminalHelper.Terminal.terminalNodes.terminalNodes)
{
Log.Message($"Moon Node. Name: {((Object)terminalNode).name}. Price: {terminalNode.itemCost}.");
}
TerminalKeyword[] allKeywords = TerminalHelper.Terminal.terminalNodes.allKeywords;
foreach (TerminalKeyword val2 in allKeywords)
{
if (val2.word == "route")
{
CompatibleNoun[] compatibleNouns = val2.compatibleNouns;
foreach (CompatibleNoun val3 in compatibleNouns)
{
Log.Message($"Moon Node. Node Name: {((Object)val3.result).name}. MoonID: {val3.result.buyRerouteToMoon}. Price: {val3.result.itemCost}.");
}
}
}
}
}
}
namespace Hura.Project.Cheats
{
internal abstract class Cheat : ICheat
{
protected TerminalNode node;
public virtual string ID => GetType().ToString();
public abstract string Description { get; }
public abstract bool NeedsOption { get; }
public TerminalNode Node => node;
public abstract void AddToTerminal(Terminal terminal, TerminalKeyword cheatVerb);
public abstract void Execute(string option);
}
internal class CustomItemsPriceCheat : ToggleCheat
{
private const int SKIP_OVERRIDE_VALUE = -1;
public static bool currentSettings = false;
private static Dictionary<string, int> overridePrices = new Dictionary<string, int>
{
{ "Walkie-talkie", -1 },
{ "Flashlight", -1 },
{ "Shovel", -1 },
{ "Lockpicker", -1 },
{ "Pro-flashlight", -1 },
{ "Stun grenade", -1 },
{ "Boombox", 25 },
{ "TZP-Inhalant", 20 },
{ "Zap gun", -1 },
{ "Jetpack", 75 },
{ "Extension ladder", 30 },
{ "Radar-booster", -1 },
{ "Spray paint", 10 }
};
public override string Description => "Set custom item prices.\n\"cheat customitemsprice on\" to enable.\n\"cheat customitemsprice off\" to disable.";
public override void AddToTerminal(Terminal terminal, TerminalKeyword cheatVerb)
{
node = TerminalHelper.CreateNode(TerminalHelper.CreateNodeText("You have set custom items price!"));
node.terminalEvent = ID;
TerminalKeyword val = TerminalHelper.CreateKeyword("customitemsprice", isVerb: false, null);
TerminalHelper.AddCompatibleNounToVerb(cheatVerb, val, node);
TerminalHelper.AddKeyworkToTerminal(val);
}
protected override void OnEnable()
{
OverridePrices();
}
protected override void OnDisable()
{
ResetPriceToDefault();
}
private void OverridePrices()
{
Item[] items = ItemsHelper.GetItems();
foreach (Item val in items)
{
if (overridePrices.TryGetValue(val.itemName, out var value) && value != -1)
{
val.creditsWorth = value;
Log.Message($"Priced overriden on item: {val.itemId}. Item name: {val.itemName}");
}
}
}
private void ResetPriceToDefault()
{
Item[] items = ItemsHelper.GetItems();
foreach (Item val in items)
{
if (TerminalCheats.DefaultItemsPrice.TryGetValue(((Object)val).name, out var value))
{
val.creditsWorth = value;
}
}
}
}
internal class CustomMoonsPrices : ToggleCheat
{
public override string Description => "Set custom moons prices.\n\"cheat custommoonsprice on\" to enable.\n\"cheat custommoonsprice off\" to disable.";
public override void AddToTerminal(Terminal terminal, TerminalKeyword cheatVerb)
{
node = TerminalHelper.CreateNode(TerminalHelper.CreateNodeText("You have set custom moons price!"));
node.terminalEvent = ID;
TerminalKeyword val = TerminalHelper.CreateKeyword("custommoonsprice", isVerb: false, null);
TerminalHelper.AddCompatibleNounToVerb(cheatVerb, val, node);
TerminalHelper.AddKeyworkToTerminal(val);
UpdateHelper.LogAllMoonsInfos();
}
protected override void OnEnable()
{
OverridePrices();
}
protected override void OnDisable()
{
ResetPriceToDefault();
}
private void OverridePrices()
{
foreach (MoonsHelper.MoonData moon in MoonsHelper.Moons)
{
if (moon.Cost > 0)
{
moon.Node.itemCost = 100;
moon.ConfirmNode.itemCost = 100;
}
}
}
private void ResetPriceToDefault()
{
foreach (MoonsHelper.MoonData moon in MoonsHelper.Moons)
{
if (moon.Cost > 0)
{
moon.Node.itemCost = moon.Cost;
moon.ConfirmNode.itemCost = moon.Cost;
}
}
}
}
internal interface ICheat
{
string ID { get; }
bool NeedsOption { get; }
TerminalNode Node { get; }
void AddToTerminal(Terminal terminal, TerminalKeyword cheatVerb);
void Execute(string option);
}
internal class MoneyCheat : Cheat
{
private Terminal terminal;
public override bool NeedsOption => true;
public override string Description => "Add credits to the group.\n\"cheat addmoney X\" where X is the amount you want to add.";
public override void AddToTerminal(Terminal terminal, TerminalKeyword cheatVerb)
{
this.terminal = terminal;
node = TerminalHelper.CreateNode(TerminalHelper.CreateNodeText("You have added money!"));
node.terminalEvent = ID;
TerminalKeyword val = TerminalHelper.CreateKeyword("addmoney", isVerb: false, null);
TerminalHelper.AddCompatibleNounToVerb(cheatVerb, val, node);
TerminalHelper.AddKeyworkToTerminal(val);
}
public override void Execute(string option)
{
if (int.TryParse(option, out var result))
{
AddMoney(result);
}
}
private void AddMoney(int money)
{
Terminal obj = terminal;
obj.groupCredits += money;
terminal.SyncGroupCreditsServerRpc(terminal.groupCredits, terminal.numberOfItemsInDropship);
}
}
[HarmonyPatch(typeof(Terminal))]
internal static class TerminalCheats
{
public const string CHEAT_KEYWORD_NAME = "cheat";
private static readonly ICheat[] cheats = new ICheat[3]
{
new MoneyCheat(),
new CustomItemsPriceCheat(),
new CustomMoonsPrices()
};
private static Dictionary<string, int> defaultItemsPrice = new Dictionary<string, int>();
private static string lastInputOption;
public static IReadOnlyDictionary<string, int> DefaultItemsPrice => defaultItemsPrice;
[HarmonyPatch("Start")]
[HarmonyPostfix]
public static void Initialize()
{
SaveItemsPrice();
MoonsHelper.PopulateMoonsData();
AddCheatCommandsToTerminal();
ICheat[] array = cheats;
for (int i = 0; i < array.Length; i++)
{
if (array[i] is ToggleCheat toggleCheat)
{
toggleCheat.Execute("on");
}
}
}
private static void SaveItemsPrice()
{
Item[] buyableItemsList = TerminalHelper.Terminal.buyableItemsList;
foreach (Item val in buyableItemsList)
{
defaultItemsPrice.Add(val.itemName, val.creditsWorth);
}
}
private static void AddCheatCommandsToTerminal()
{
TerminalNode destinationNode = TerminalHelper.CreateNode(TerminalHelper.CreateNodeText("Welcome to Hura's cheat codes!"));
TerminalKeyword val = TerminalHelper.CreateKeyword("cheat", isVerb: true, destinationNode);
TerminalHelper.AddKeyworkToTerminal(val);
ICheat[] array = cheats;
for (int i = 0; i < array.Length; i++)
{
array[i].AddToTerminal(TerminalHelper.Terminal, val);
}
}
[HarmonyPatch("RunTerminalEvents")]
[HarmonyPostfix]
public static void RunQuizTerminalEvents(TerminalNode node)
{
string terminalEvent = node.terminalEvent;
if (string.IsNullOrEmpty(terminalEvent))
{
return;
}
ICheat[] array = cheats;
foreach (ICheat cheat in array)
{
if (cheat.ID == terminalEvent)
{
cheat.Execute(lastInputOption);
}
}
}
[HarmonyPatch("ParsePlayerSentence")]
[HarmonyPrefix]
private static void ParsePlayerSentencePrefix(ref Terminal __instance, ref TerminalNode __result)
{
string[] array = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded).Split(new char[1] { ' ' });
if (array.Length == 3)
{
lastInputOption = array[2];
}
}
[HarmonyPatch("ParsePlayerSentence")]
[HarmonyPostfix]
private static void ParsePlayerSentencePostfix(ref Terminal __instance, ref TerminalNode __result)
{
string[] array = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded).Split(new char[1] { ' ' });
if (!(array[0] == "cheat"))
{
return;
}
ICheat[] array2 = cheats;
for (int i = 0; i < array2.Length; i++)
{
if (array2[i].NeedsOption && array.Length != 3)
{
__result = TerminalHelper.GetSpecialNode(SpecialTerminalNode.ParsingError);
}
}
}
}
internal abstract class ToggleCheat : Cheat
{
public override bool NeedsOption => true;
public override void Execute(string option)
{
string text = option.ToLower();
if (!(text == "on"))
{
if (text == "off")
{
OnDisable();
}
else
{
Log.Warning("No third argument was given when trying to set a toggle cheat.");
}
}
else
{
OnEnable();
}
}
protected abstract void OnEnable();
protected abstract void OnDisable();
}
}
namespace Hura.Project.Utility
{
internal static class ArrayUtility
{
public static void Add<T>(ref T[] array, T element)
{
if (array == null)
{
array = new T[0];
}
Array.Resize(ref array, array.Length + 1);
array[array.Length - 1] = element;
}
public static bool IsValidIndex<T>(this ICollection<T> list, int index)
{
if (index < 0)
{
return false;
}
if (index >= list.Count)
{
return false;
}
return true;
}
}
}