using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalNetworkAPI;
using QuotaTournament;
using QuotaTourney.Patches;
using TMPro;
using TerminalApi;
using TerminalApi.Classes;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("QuotaTourney")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QuotaTourney")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ad905924-f5e1-4c12-97b3-cb78bd1cedb3")]
[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 QuotaTournament
{
internal enum MoonIDs
{
Experimentation,
Assurance,
Vow,
Company,
March,
Adamance,
Rend,
Dine,
Offense,
Titan,
Artifice,
Liquidation,
Embrion
}
public class ModNetworkBehavior<T>
{
private T Value;
private LNetworkMessage<T> server;
private LNetworkMessage<T> client;
public ModNetworkBehavior(string networkName, Action<T, ulong> serverResponse, Action<T> clientResponse)
{
server = LNetworkMessage<T>.Create(networkName, serverResponse, (Action<T>)null, (Action<T, ulong>)null);
client = LNetworkMessage<T>.Connect(networkName, (Action<T, ulong>)null, clientResponse, (Action<T, ulong>)null);
}
public void SendClients(T data)
{
server.SendClients(data);
}
public void SendServer(T data)
{
client.SendServer(data);
}
public void SetValue(T value)
{
Value = value;
}
public T GetValue()
{
return Value;
}
}
[BepInPlugin("OreoM.QuotaTournament", "QuotaTournament", "1.4.4")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class QuotaTournament : BaseUnityPlugin
{
private static class TerminalKeywords
{
public static TerminalKeyword seed;
public static TerminalKeyword freq;
public static TerminalKeyword ban;
public static TerminalKeyword blank;
}
private static class TerminalNodes
{
public static TerminalNode seed;
public static TerminalNode freq;
public static TerminalNode ban;
}
private const string modGuid = "OreoM.QuotaTournament";
private const string modName = "QuotaTournament";
private const string modVersion = "1.4.4";
private readonly Harmony harmony = new Harmony("OreoM.QuotaTournament");
private static QuotaTournament Instance;
internal ManualLogSource internalLogger;
private static List<int> allowedMoons = new List<int>();
public const int seedMax = int.MaxValue;
public static bool seedHasBeenSet = false;
public static string terminalInput = "";
private static ConfigEntry<bool> allowShopBypassAnyDay;
private static ConfigEntry<bool> speedrunBonus;
private static ConfigEntry<int> wipeLossPercentage;
private static ModNetworkBehavior<int> netSeed;
private static ModNetworkBehavior<int> netScore;
private static ModNetworkBehavior<string> netBuy;
private static ModNetworkBehavior<string> netMoonFrequency;
private static ModNetworkBehavior<string> netAllowedMoons;
private void Awake()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Expected O, but got Unknown
//IL_0368: Unknown result type (might be due to invalid IL or missing references)
//IL_036d: Unknown result type (might be due to invalid IL or missing references)
//IL_0378: Unknown result type (might be due to invalid IL or missing references)
//IL_0383: Unknown result type (might be due to invalid IL or missing references)
//IL_0395: Unknown result type (might be due to invalid IL or missing references)
//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
//IL_03b0: Expected O, but got Unknown
//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
//IL_03fd: Expected O, but got Unknown
//IL_0402: Unknown result type (might be due to invalid IL or missing references)
//IL_0407: Unknown result type (might be due to invalid IL or missing references)
//IL_0412: Unknown result type (might be due to invalid IL or missing references)
//IL_041d: Unknown result type (might be due to invalid IL or missing references)
//IL_042f: Unknown result type (might be due to invalid IL or missing references)
//IL_043a: Unknown result type (might be due to invalid IL or missing references)
//IL_044a: Expected O, but got Unknown
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
allowShopBypassAnyDay = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Allow shop bypass any day", true, new ConfigDescription("Allow items and cruiser to be bought directly to ship any day instead of only before first day", (AcceptableValueBase)null, Array.Empty<object>()));
speedrunBonus = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Speedrun Bonus", false, new ConfigDescription("Get more score if ship leaves early", (AcceptableValueBase)null, Array.Empty<object>()));
wipeLossPercentage = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Wipe loss percentage", 50, new ConfigDescription("What percentage of score is lost if all players die", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
internalLogger = Logger.CreateLogSource("OreoM.QuotaTournament");
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 is patching.");
try
{
harmony.PatchAll(typeof(QuotaTournament));
harmony.PatchAll(typeof(GameNetworkManagerPatch));
harmony.PatchAll(typeof(StartOfRoundPatch));
harmony.PatchAll(typeof(TerminalPatch));
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 is done patching.");
}
catch (Exception ex)
{
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 failed to patch.");
Debug.LogException(ex);
}
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 is creating the Network");
try
{
netSeed = new ModNetworkBehavior<int>("netSeed", SetSeedClientRequest, SetSeedServerRequest);
netScore = new ModNetworkBehavior<int>("netScore", SyncScoreClientRequest, SyncScoreServerRequest);
netBuy = new ModNetworkBehavior<string>("netBuy", BuyFromShopClientRequest, BuyFromShopServerRequest);
netMoonFrequency = new ModNetworkBehavior<string>("netMoonFrequency", SetMoonFrequencyClientRequest, SetMoonFrequencyServerRequest);
netMoonFrequency.SetValue("day");
netAllowedMoons = new ModNetworkBehavior<string>("netAllowedMoons", BanMoonClientRequest, BanMoonServerRequest);
netAllowedMoons.SetValue("default");
ResetAllowedMoonList();
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 is done creating the Network");
}
catch (Exception ex2)
{
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 failed to create Network");
Debug.LogException(ex2);
}
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 is implementing terminal commands");
try
{
TerminalNodes.seed = TerminalApi.CreateTerminalNode("seedNode", true, "");
TerminalNodes.freq = TerminalApi.CreateTerminalNode("freqNode", true, "");
TerminalNodes.ban = TerminalApi.CreateTerminalNode("banNode", true, "");
TerminalKeywords.blank = TerminalApi.CreateTerminalKeyword("whyCanINotGetCustomInputWithoutThis???", true, (TerminalNode)null);
TerminalKeywords.seed = TerminalApi.CreateTerminalKeyword("seed", false, TerminalNodes.seed);
TerminalKeywords.freq = TerminalApi.CreateTerminalKeyword("freq", false, TerminalNodes.freq);
TerminalKeywords.ban = TerminalApi.CreateTerminalKeyword("ban", false, TerminalNodes.ban);
TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.blank, TerminalKeywords.seed, TerminalNodes.seed);
TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.blank, TerminalKeywords.freq, TerminalNodes.freq);
TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.blank, TerminalKeywords.ban, TerminalNodes.ban);
TerminalKeywords.seed.defaultVerb = TerminalKeywords.blank;
TerminalKeywords.freq.defaultVerb = TerminalKeywords.blank;
TerminalKeywords.ban.defaultVerb = TerminalKeywords.blank;
TerminalApi.AddTerminalKeyword(TerminalKeywords.seed, new CommandInfo
{
Title = "Seed [num]",
TriggerNode = TerminalNodes.seed,
DisplayTextSupplier = SetSeed,
Category = "Other",
Description = "Type a seed to start the challenge"
});
TerminalApi.AddTerminalKeyword(TerminalKeywords.freq, new CommandInfo
{
Title = "Freq [day/quota]",
TriggerNode = TerminalNodes.freq,
DisplayTextSupplier = SetMoonFrequency,
Category = "Other",
Description = "Change the frequency with which moon changes"
});
TerminalApi.AddTerminalKeyword(TerminalKeywords.ban, new CommandInfo
{
Title = "Ban [moon]",
TriggerNode = TerminalNodes.ban,
DisplayTextSupplier = BanMoon,
Category = "Other",
Description = "Ban moon from being choosen"
});
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 is done implementing terminal commands");
}
catch (Exception ex3)
{
internalLogger.LogInfo((object)"QuotaTournament v1.4.4 failed to implement terminal commands");
Debug.LogException(ex3);
}
}
public static void AddScore(int inputScore)
{
float num = (speedrunBonus.Value ? (2f - TimeOfDay.Instance.normalizedTimeOfDay) : 1f);
netScore.SetValue(netScore.GetValue() + (int)((float)inputScore * num));
}
public static void LoseScoreToWipe()
{
netScore.SetValue((int)((float)netScore.GetValue() * (float)(100 - wipeLossPercentage.Value) / 100f));
}
public static void ResetScore()
{
netScore.SetValue(0);
}
public static int GetScore()
{
return netScore.GetValue();
}
public static void SyncScore()
{
netScore.SendServer(0);
}
public static void SyncScoreClientRequest(int option, ulong clientID)
{
if (option == 0)
{
netScore.SendClients(netScore.GetValue());
}
}
public static void SyncScoreServerRequest(int serverScore)
{
netScore.SetValue(serverScore);
}
public static string SetMoonFrequency()
{
if (TimeOfDay.Instance.daysUntilDeadline < 3 || !StartOfRound.Instance.inShipPhase)
{
return "Moon frequency can only be changed before starting the quota\n\n";
}
string text = terminalInput.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1];
if (text != "quota" && text != "day")
{
return text + " is an invalid option\n\n";
}
netMoonFrequency.SendServer(text);
return "Moon will change every " + text + "\n\n";
}
public static void SetMoonFrequencyClientRequest(string config, ulong clientID)
{
netMoonFrequency.SendClients(config);
}
public static void SetMoonFrequencyServerRequest(string config)
{
netMoonFrequency.SetValue(config);
}
public static string GetMoonFrequencyValue()
{
return netMoonFrequency.GetValue();
}
public static string SetSeed()
{
if (TimeOfDay.Instance.daysUntilDeadline < 3 || !StartOfRound.Instance.inShipPhase)
{
return "Seed can only be set before starting the quota\n\n";
}
if (!int.TryParse(terminalInput.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1], out var result))
{
return $"{result} is not a valid number\n\n";
}
netSeed.SendServer(result);
return $"Seed {result} is set\n\n";
}
public static void SetSeedClientRequest(int seed, ulong clientID)
{
StartOfRound.Instance.ChangeLevelServerRpc(allowedMoons[seed % allowedMoons.Count], Object.FindObjectOfType<Terminal>().groupCredits = new Random(seed + 9114523).Next(1000, 1600));
netSeed.SendClients(seed);
}
public static void SetSeedServerRequest(int seed)
{
Debug.Log((object)$"Seed set: {seed}");
netSeed.SetValue(seed);
seedHasBeenSet = true;
StartOfRound instance = StartOfRound.Instance;
instance.randomMapSeed = new Random(netSeed.GetValue()).Next(1, int.MaxValue);
instance.SetPlanetsWeather(0);
instance.overrideRandomSeed = true;
instance.overrideSeedNumber = netSeed.GetValue();
ResetScore();
((TMP_Text)instance.profitQuotaMonitorText).text = "CURRENT SCORE:\n $" + GetScore();
TerminalPatch.ForceItemSales(TimeOfDay.Instance.daysUntilDeadline);
}
public static void BuyFromShop(string buyType)
{
if ((allowShopBypassAnyDay.Value || TimeOfDay.Instance.daysUntilDeadline == 3) && StartOfRound.Instance.inShipPhase)
{
netBuy.SendServer(buyType);
}
}
public static void BuyFromShopClientRequest(string buyType, ulong clientID)
{
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: 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)
Terminal val = Object.FindObjectOfType<Terminal>();
if (buyType.Equals("Item"))
{
foreach (int item in val.orderedItemsFromTerminal)
{
Object.Instantiate<GameObject>(val.buyableItemsList[item].spawnPrefab, new Vector3((float)item / 7f, 2f, -15f + (float)item / 7f), Quaternion.identity, RoundManager.Instance.spawnedScrapContainer).GetComponent<NetworkObject>().Spawn(false);
}
netBuy.SendClients(buyType);
}
if (buyType.Equals("Cruiser"))
{
if (val.orderedVehicleFromTerminal != 1 && !Object.op_Implicit((Object)(object)Object.FindObjectOfType<VehicleController>()))
{
Object.Instantiate<GameObject>(val.buyableVehicles[0].vehiclePrefab, new Vector3(3f, 3f, -21f), new Quaternion(0f, 1f, 0f, 1f), RoundManager.Instance.VehiclesContainer).GetComponent<NetworkObject>().Spawn(false);
StartOfRound.Instance.SetMagnetOn(true);
}
netBuy.SendClients(buyType);
}
}
public static void BuyFromShopServerRequest(string buyType)
{
Terminal val = Object.FindObjectOfType<Terminal>();
if (buyType.Equals("Item"))
{
val.ClearBoughtItems();
}
if (buyType.Equals("Cruiser"))
{
StartOfRound.Instance.magnetLever.boolValue = true;
val.orderedVehicleFromTerminal = -1;
val.vehicleInDropship = false;
}
}
public static string BanMoon()
{
if (seedHasBeenSet)
{
return "Moons can only be banned before setting the seed\n\n";
}
string[] array = terminalInput.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string moon = array[1];
string text = Enum.GetNames(typeof(MoonIDs)).FirstOrDefault((string s) => s.StartsWith(moon, StringComparison.OrdinalIgnoreCase));
if (text != null && allowedMoons.Contains((int)Enum.Parse(typeof(MoonIDs), text)))
{
netAllowedMoons.SendServer(text);
return text + " has been banned from the list\n\n";
}
return moon + " is an invalid option\n\n";
}
public static void BanMoonClientRequest(string moonName, ulong clientID)
{
netAllowedMoons.SendClients(moonName);
}
public static void BanMoonServerRequest(string moonName)
{
netAllowedMoons.SetValue("modified");
allowedMoons.Remove((int)Enum.Parse(typeof(MoonIDs), moonName));
}
public static void ResetAllowedMoonList()
{
allowedMoons.Clear();
foreach (int value in Enum.GetValues(typeof(MoonIDs)))
{
if (value != 3 && value != 11)
{
allowedMoons.Add(value);
}
}
netAllowedMoons.SetValue("default");
}
public static List<int> GetAllowedMoonList()
{
return allowedMoons;
}
}
}
namespace QuotaTourney.Patches
{
[HarmonyPatch(typeof(GameNetworkManager))]
internal class GameNetworkManagerPatch
{
[HarmonyPatch("Disconnect")]
[HarmonyPrefix]
private static void DisconnectPrePatch(ref GameNetworkManager __instance)
{
global::QuotaTournament.QuotaTournament.seedHasBeenSet = false;
global::QuotaTournament.QuotaTournament.ResetAllowedMoonList();
global::QuotaTournament.QuotaTournament.ResetScore();
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal class StartOfRoundPatch
{
[HarmonyPatch("SetShipReadyToLand")]
[HarmonyPostfix]
private static void SetShipReadyToLandPostPatch(ref StartOfRound __instance)
{
if (!global::QuotaTournament.QuotaTournament.seedHasBeenSet)
{
return;
}
if (TimeOfDay.Instance.daysUntilDeadline == 0)
{
RoundManager.Instance.DespawnPropsAtEndOfRound(true);
__instance.ResetShip();
((TMP_Text)__instance.profitQuotaMonitorText).text = "TOTAL SCORE:\n $" + global::QuotaTournament.QuotaTournament.GetScore();
global::QuotaTournament.QuotaTournament.ResetScore();
global::QuotaTournament.QuotaTournament.ResetAllowedMoonList();
if (global::QuotaTournament.QuotaTournament.GetMoonFrequencyValue().Equals("quota"))
{
__instance.ChangeLevelServerRpc(global::QuotaTournament.QuotaTournament.GetAllowedMoonList()[__instance.overrideSeedNumber % global::QuotaTournament.QuotaTournament.GetAllowedMoonList().Count], Object.FindObjectOfType<Terminal>().groupCredits);
}
}
if (global::QuotaTournament.QuotaTournament.GetMoonFrequencyValue().Equals("day"))
{
__instance.ChangeLevelServerRpc(global::QuotaTournament.QuotaTournament.GetAllowedMoonList()[__instance.overrideSeedNumber % global::QuotaTournament.QuotaTournament.GetAllowedMoonList().Count], Object.FindObjectOfType<Terminal>().groupCredits);
}
Debug.Log((object)$"Next seed: {__instance.overrideSeedNumber}\n{global::QuotaTournament.QuotaTournament.GetMoonFrequencyValue()}");
}
[HarmonyPatch("StartGame")]
[HarmonyPrefix]
private static void StartGamePrePatch(ref StartOfRound __instance)
{
if (TimeOfDay.Instance.daysUntilDeadline == 1 && global::QuotaTournament.QuotaTournament.seedHasBeenSet)
{
__instance.isChallengeFile = true;
}
}
[HarmonyPatch("ShipHasLeft")]
[HarmonyPostfix]
private static void ShipHasLeftPostPatch(ref StartOfRound __instance)
{
if (!global::QuotaTournament.QuotaTournament.seedHasBeenSet)
{
return;
}
if (((NetworkBehaviour)StartOfRound.Instance).IsHost)
{
if (__instance.livingPlayers == 0)
{
global::QuotaTournament.QuotaTournament.LoseScoreToWipe();
}
else
{
global::QuotaTournament.QuotaTournament.AddScore(__instance.GetValueOfAllScrap(true, true));
}
global::QuotaTournament.QuotaTournament.SyncScore();
}
__instance.overrideSeedNumber = NextSeed(__instance.overrideSeedNumber);
__instance.randomMapSeed = NextSeed(__instance.randomMapSeed);
__instance.isChallengeFile = false;
}
[HarmonyPatch("ChangeLevel")]
[HarmonyPrefix]
private static void ChangeLevelPrePatch(ref StartOfRound __instance)
{
Debug.Log((object)$"Current random seed: {__instance.randomMapSeed}");
__instance.SetPlanetsWeather(0);
}
[HarmonyPatch("PassTimeToNextDay")]
[HarmonyPostfix]
private static void PassTimeToNextDayPostPatch(ref StartOfRound __instance)
{
if (global::QuotaTournament.QuotaTournament.seedHasBeenSet)
{
((TMP_Text)__instance.profitQuotaMonitorText).text = "CURRENT SCORE:\n $" + global::QuotaTournament.QuotaTournament.GetScore();
TerminalPatch.ForceItemSales(TimeOfDay.Instance.daysUntilDeadline);
}
}
public static int NextSeed(int seed)
{
return new Random(Math.Abs(seed + 84936687)).Next(1, int.MaxValue);
}
}
[HarmonyPatch(typeof(Terminal))]
internal class TerminalPatch
{
[HarmonyPatch("ParsePlayerSentence")]
[HarmonyPrefix]
private static void ParsePlayerSentencePrePatch(ref Terminal __instance)
{
string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded);
StringBuilder stringBuilder = new StringBuilder();
string text2 = text;
foreach (char c in text2)
{
if (!char.IsPunctuation(c))
{
stringBuilder.Append(c);
}
}
global::QuotaTournament.QuotaTournament.terminalInput = stringBuilder.ToString().ToLower();
}
[HarmonyPatch("LoadNewNodeIfAffordable")]
[HarmonyPostfix]
private static void LoadNewNodeIfAffordablePostPatch(ref Terminal __instance)
{
if (global::QuotaTournament.QuotaTournament.seedHasBeenSet)
{
global::QuotaTournament.QuotaTournament.BuyFromShop("Item");
}
}
[HarmonyPatch("BuyVehicleClientRpc")]
[HarmonyPostfix]
private static void BuyVehicleClientRpcPostPatch(ref Terminal __instance)
{
if (global::QuotaTournament.QuotaTournament.seedHasBeenSet)
{
global::QuotaTournament.QuotaTournament.BuyFromShop("Cruiser");
}
}
public static void ForceItemSales(int force)
{
force = ((force == 0) ? 1 : force);
Terminal val = Object.FindObjectOfType<Terminal>();
List<int> list = new List<int>();
for (int i = 0; i < val.buyableItemsList.Length + val.buyableVehicles.Length; i++)
{
list.Add(i);
list[i] = i;
}
Random random = new Random(StartOfRound.Instance.overrideSeedNumber);
int num = 1 + random.Next(0, val.buyableItemsList.Length + val.buyableVehicles.Length) / force;
for (int j = 0; j < num; j++)
{
int num2 = list[random.Next(0, list.Count)];
int num3 = 100 - random.Next(20 * (3 - force), 80) / force;
num3 = (int)Math.Round((double)num3 / 10.0) * 10;
val.itemSalesPercentages[num2] = num3;
list.Remove(num2);
}
}
}
}