Decompiled source of EconomicEvents v1.1.1

EconomicEvents/EconomicEvents.dll

Decompiled 3 hours ago
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.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ModSaveBackups;
using UnityEngine;
using cakeslice;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("EconomicEvents")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("raddude")]
[assembly: AssemblyProduct("EconomicEvents")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("47f2429a-1581-46a0-a562-29bc48bfe982")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
namespace EconomicEvents;

internal sealed class Event
{
	private string _itemsDisplay;

	internal int Id { get; private set; }

	internal string Name { get; private set; }

	internal string EventText { get; private set; }

	internal int[] GoodIndexes { get; private set; }

	internal HashSet<int> GoodIndexSet { get; private set; }

	internal int PriceMult { get; private set; }

	internal int EventDuration { get; private set; }

	internal int[] SpecificPorts { get; private set; }

	internal static List<Event> Events { get; private set; }

	internal static Dictionary<int, Event> EventsById { get; private set; }

	internal static Dictionary<int, int> ItemToCrateConversion { get; } = new Dictionary<int, int>
	{
		{ 33, 1 },
		{ 42, 2 },
		{ 54, 4 },
		{ 46, 6 },
		{ 52, 7 },
		{ 53, 8 },
		{ 32, 9 },
		{ 37, 14 },
		{ 41, 15 },
		{ 39, 16 },
		{ 44, 17 },
		{ 36, 18 },
		{ 34, 19 },
		{ 147, 43 },
		{ 144, 44 },
		{ 146, 46 },
		{ 149, 54 }
	};


	private Event(int id, string name, string eventText, int[] goodIndexes, int priceMult, int eventDuration, int[] ports)
	{
		Id = id;
		Name = name;
		EventText = eventText;
		GoodIndexes = goodIndexes;
		GoodIndexSet = new HashSet<int>(goodIndexes);
		PriceMult = priceMult;
		EventDuration = eventDuration;
		SpecificPorts = ports;
	}

	internal static void InitializeEvents()
	{
		List<Event> list = new List<Event>();
		list.Add(new Event(0, "Storm Damage", "A terrible storm swept through and the port needs building supplies\nfor repairs.", new int[2] { 47, 48 }, 3, 7, new int[0]));
		list.Add(new Event(1, "Drought", "A drought has stricken the area. The people are thirsty and are\nin urgent need of water.", new int[1] { 10 }, 3, 7, new int[0]));
		list.Add(new Event(2, "Plague", "A plague is ravaging the port. They are in dire need of more\nmedicine.", new int[1] { 26 }, 2, 14, new int[0]));
		list.Add(new Event(3, "Library Fire", "A fire broke out in the library. They need more books to replace\nthe damged texts.", new int[1] { 30 }, 3, 7, new int[3] { 5, 23, 26 }));
		list.Add(new Event(4, "Volcano Erupted", "Mt. Malefic erupted and destroyed parts of the town. They need\nbuilding supplies for repairs and medicine for the injured.", new int[3] { 47, 48, 26 }, 3, 14, new int[1] { 17 }));
		list.Add(new Event(5, "New Mine", "They are making a new mine on the island and will pay a premium\nfor materials and tools.", new int[3] { 47, 48, 33 }, 2, 14, new int[3] { 19, 0, 28 }));
		list.Add(new Event(6, "Missed Wine Delivery", "A shipment of wine never arrived and the people of the port are\nclamoring for some.", new int[1] { 13 }, 2, 14, new int[0]));
		list.Add(new Event(7, "Increased Relic Production", "Interest in relics is rising. They need gold and gems in Aestra\nAbbey to make more.", new int[2] { 20, 22 }, 3, 7, new int[1] { 26 }));
		list.Add(new Event(8, "Shipwreck", "A ship wrecked was found and the port needs supplies to help the\nsurvivors.", new int[3] { 5, 26, 29 }, 2, 14, new int[0]));
		list.Add(new Event(9, "Festival", "A festival is being held and the port needs supplies for the\ncelebration.", new int[6] { 11, 12, 13, 15, 36, 58 }, 2, 7, new int[0]));
		list.Add(new Event(10, "Shipyard Maintenance", "The shipyard is in need of maintenance and needs supplies for\nthe job.", new int[5] { 47, 48, 33, 21, 35 }, 3, 14, new int[4] { 0, 9, 15, 22 }));
		list.Add(new Event(11, "New Fishing Grounds", "New fishing grounds have been discovered and the port wants\nsupplies to build more fishing boats.", new int[3] { 48, 33, 35 }, 2, 21, new int[0]));
		list.Add(new Event(12, "New Dish", "A new dish is sweeping the area and the residents can't get enough.\nThe port will buy the ingredients at a high price", Ingredients(), 2, 7, new int[0]));
		list.Add(new Event(13, "Silk Shirt Craze", "A new fashion trend has taken hold and the port's clothiers need\nsilk to keep up with demand.", new int[1] { 28 }, 3, 7, new int[0]));
		list.Add(new Event(14, "Global Drought", "A global drought has struck and all ports have a water shortage\ndriving up prices.", new int[1] { 10 }, 4, 21, new int[1] { 999 }));
		list.Add(new Event(15, "Fishing Hook Shortage", "An explosion at the hook maker has left all ports with a fishing\nhook shortage.", new int[1] { 104 }, 5, 14, new int[1] { 999 }));
		list.Add(new Event(16, "Explosive Event", "Moments away from figuring out the how to create gold from everyday\nitems, they suffered an explosion damaging all of their materials.", new int[4] { 11, 23, 50, 55 }, 2, 14, new int[1] { 4 }));
		Events = list;
		EventsById = Events.ToDictionary((Event e) => e.Id, (Event e) => e);
	}

	internal string GetItemsDisplay()
	{
		if (_itemsDisplay != null)
		{
			return _itemsDisplay;
		}
		List<string> list = new List<string>(GoodIndexes.Length);
		int[] goodIndexes = GoodIndexes;
		foreach (int num in goodIndexes)
		{
			int num2 = PrefabsDirectory.GoodToItemIndex(num);
			ShipItem val = PrefabsDirectory.instance.GetItem(num2) ?? PrefabsDirectory.instance.GetItem(num);
			if ((Object)(object)val != (Object)null)
			{
				list.Add("<b>" + val.name + "</b>");
			}
		}
		_itemsDisplay = string.Join(", ", list);
		return _itemsDisplay;
	}

	private static int[] Ingredients()
	{
		List<int> list = new List<int>
		{
			1, 2, 3, 4, 6, 7, 8, 9, 14, 15,
			16, 17, 18, 19, 25, 31, 32, 42, 43, 44,
			46, 54
		};
		List<int> list2 = new List<int> { 24, 53 };
		for (int i = 0; i < 3; i++)
		{
			int index = Random.Range(0, list.Count);
			list2.Add(list.ElementAt(index));
			list.RemoveAt(index);
		}
		return list2.ToArray();
	}
}
internal class EventPatches
{
	[HarmonyPatch(typeof(IslandMarket))]
	private class IslandMarketPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetGoodPriceAtSupply")]
		public static void EventPriceAdjust(int goodIndex, IslandMarket __instance, ref int __result)
		{
			EventPort eventPort = null;
			int portIndex = __instance.GetPortIndex();
			foreach (EventPort portsWithEvent in EventScheduler.Instance.PortsWithEvents)
			{
				if (portsWithEvent.Index == portIndex && portsWithEvent.IsEventActive())
				{
					eventPort = portsWithEvent;
					break;
				}
			}
			if (eventPort != null)
			{
				Event.EventsById.TryGetValue(eventPort.AssignedEvent, out var value);
				if (value != null && value.GoodIndexSet.Contains(goodIndex))
				{
					__result *= value.PriceMult;
				}
			}
		}
	}

	[HarmonyPatch(typeof(Shopkeeper))]
	private class ShopkeeperPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetPrice")]
		public static void EventPriceAdjust(ShipItem item, Shopkeeper __instance, ref int __result)
		{
			if (item.IsBulk())
			{
				return;
			}
			IslandSceneryScene componentInParent = ((Component)__instance).GetComponentInParent<IslandSceneryScene>();
			int portIndex = ((Component)Refs.islands[componentInParent.parentIslandIndex]).GetComponentInChildren<Port>().portIndex;
			EventPort eventPort = null;
			foreach (EventPort portsWithEvent in EventScheduler.Instance.PortsWithEvents)
			{
				if (portsWithEvent.Index == portIndex && portsWithEvent.IsEventActive())
				{
					eventPort = portsWithEvent;
					break;
				}
			}
			if (eventPort == null)
			{
				return;
			}
			Event.EventsById.TryGetValue(eventPort.AssignedEvent, out var value);
			if (value != null)
			{
				int prefabIndex = ((Component)item).gameObject.GetComponent<SaveablePrefab>().prefabIndex;
				int value2;
				bool flag = Event.ItemToCrateConversion.TryGetValue(prefabIndex, out value2);
				if (value.GoodIndexSet.Contains(prefabIndex) || (flag && value.GoodIndexSet.Contains(value2)))
				{
					__result *= value.PriceMult;
				}
			}
		}
	}
}
[Serializable]
public class EventPort
{
	public int Index { get; private set; }

	public string Name { get; private set; }

	public int AssignedEvent { get; set; } = -1;


	public int DayEventStarts { get; set; } = -1;


	public int DayEventEnds { get; set; } = -1;


	public EventPort(int index, string name)
	{
		Index = index;
		Name = name;
	}

	public override string ToString()
	{
		return Name ?? "";
	}

	public bool IsEventActive()
	{
		return HasAssignedEvent() && DayEventStarts <= GameState.day;
	}

	public bool HasAssignedEvent()
	{
		return AssignedEvent >= 0;
	}
}
internal sealed class EventRegion
{
	private readonly List<EventPort> _ports;

	public static readonly EventRegion AlAnkh;

	public static readonly EventRegion EmeraldArchipelago;

	public static readonly EventRegion Aestrin;

	public static readonly EventRegion FireFishLagoon;

	public static readonly IReadOnlyList<EventRegion> AllRegions;

	private static readonly IReadOnlyList<EventPort> AllPortsList;

	private static readonly Dictionary<int, EventPort> PortsByIndex;

	internal int Index { get; private set; }

	internal string Name { get; private set; }

	internal IReadOnlyList<EventPort> Ports => _ports.AsReadOnly();

	public static IReadOnlyList<EventPort> AllPorts => AllPortsList;

	private EventRegion(int index, string name, List<EventPort> ports)
	{
		Index = index;
		Name = name;
		_ports = ports;
	}

	public override string ToString()
	{
		return Name ?? "";
	}

	static EventRegion()
	{
		AlAnkh = new EventRegion(0, "Al'Ankh", new List<EventPort>
		{
			new EventPort(0, "Gold Rock City"),
			new EventPort(1, "Al'Nilem"),
			new EventPort(2, "Neverdin"),
			new EventPort(3, "Albacore Town"),
			new EventPort(4, "Alchemist's Island"),
			new EventPort(5, "Al'Ankh Academy"),
			new EventPort(6, "Oasis"),
			new EventPort(31, "Old Ankh Town"),
			new EventPort(32, "Mirage Mountain"),
			new EventPort(33, "Saffron Island")
		});
		EmeraldArchipelago = new EventRegion(1, "Emerald Archipelago", new List<EventPort>
		{
			new EventPort(9, "Dragon Cliffs"),
			new EventPort(10, "Sanctuary"),
			new EventPort(11, "Crab Beach"),
			new EventPort(12, "New Port"),
			new EventPort(13, "Sage Hills"),
			new EventPort(14, "Serpent Isle"),
			new EventPort(30, "Dead Cove"),
			new EventPort(29, "Turtle Island")
		});
		Aestrin = new EventRegion(2, "Aestrin", new List<EventPort>
		{
			new EventPort(15, "Fort Aestrin"),
			new EventPort(16, "Sunspire"),
			new EventPort(17, "Mount Malefic"),
			new EventPort(18, "Siren Song"),
			new EventPort(19, "Eastwind"),
			new EventPort(28, "Firefly Grotto"),
			new EventPort(26, "Aestra Abbey"),
			new EventPort(27, "Fey Valley"),
			new EventPort(20, "Happy Bay"),
			new EventPort(21, "Chronos")
		});
		FireFishLagoon = new EventRegion(3, "Fire Fish Lagoon", new List<EventPort>
		{
			new EventPort(22, "Kicia Bay"),
			new EventPort(23, "Fire Fish Town"),
			new EventPort(24, "On'na"),
			new EventPort(25, "Sen'na")
		});
		AllRegions = new List<EventRegion> { AlAnkh, EmeraldArchipelago, Aestrin, FireFishLagoon }.AsReadOnly();
		List<EventPort> list = new List<EventPort>();
		foreach (EventRegion allRegion in AllRegions)
		{
			list.AddRange(allRegion.Ports);
		}
		AllPortsList = list.AsReadOnly();
		PortsByIndex = list.ToDictionary((EventPort p) => p.Index, (EventPort p) => p);
	}

	public static EventPort FindPort(int index)
	{
		PortsByIndex.TryGetValue(index, out var value);
		return value;
	}

	public static bool AnyAssignedEvents()
	{
		return AllRegions.Any((EventRegion r) => r.HasAssignedEvent());
	}

	public bool HasAssignedEvent()
	{
		return Ports.Any((EventPort p) => p.HasAssignedEvent());
	}
}
internal class EventScheduler : MonoBehaviour
{
	private readonly List<Event> _eventBuffer = new List<Event>();

	public static EventScheduler Instance { get; private set; }

	internal List<EventPort> PortsWithEvents { get; private set; }

	internal Dictionary<int, int> RegionChance { get; private set; }

	public void Awake()
	{
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Expected O, but got Unknown
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		RegionChance = new Dictionary<int, int>();
		foreach (EventRegion allRegion in EventRegion.AllRegions)
		{
			RegionChance[allRegion.Index] = Configs.eventInRegionBaseChance.Value;
		}
		Event.InitializeEvents();
		PortsWithEvents = new List<EventPort>();
		Sun.OnNewDay += new NewDay(UpdateEvents);
	}

	public void UpdateEvents()
	{
		PortsWithEvents.RemoveAll(delegate(EventPort port)
		{
			if (GameState.day <= port.DayEventEnds)
			{
				return false;
			}
			port.DayEventStarts = -1;
			port.DayEventEnds = -1;
			port.AssignedEvent = -1;
			List<EventPort> loggedEventPorts = EventsUI.Instance.LoggedEventPorts;
			for (int num = loggedEventPorts.Count - 1; num >= 0; num--)
			{
				if (loggedEventPorts[num].Index == port.Index)
				{
					loggedEventPorts.RemoveAt(num);
					break;
				}
			}
			return true;
		});
		ScheduleEvents();
	}

	public void ScheduleEvents()
	{
		if (GameState.day % 14 != 0)
		{
			return;
		}
		if (Configs.enableGlobalEvents.Value && !EventRegion.AnyAssignedEvents() && Random.Range(0, 100) < Configs.globalEventChance.Value)
		{
			ScheduleGlobalEvent();
			return;
		}
		foreach (EventRegion allRegion in EventRegion.AllRegions)
		{
			if (!allRegion.HasAssignedEvent() && Random.Range(0, 100) < RegionChance[allRegion.Index])
			{
				ScheduleEventInRegion(allRegion);
				RegionChance[allRegion.Index] = Configs.eventInRegionBaseChance.Value;
				EE_Plugin.LogDebug($"event scheduled in {allRegion.Name} region on day {GameState.day}");
			}
			if (!allRegion.HasAssignedEvent())
			{
				RegionChance[allRegion.Index] += Random.Range(5, 15);
				EE_Plugin.LogDebug($"{allRegion.Name} chance increased to {RegionChance[allRegion.Index]} on day {GameState.day}");
			}
		}
	}

	public void ScheduleGlobalEvent()
	{
		_eventBuffer.Clear();
		foreach (Event event2 in Event.Events)
		{
			if (event2.SpecificPorts.Contains(999))
			{
				_eventBuffer.Add(event2);
			}
		}
		if (_eventBuffer.Count == 0)
		{
			return;
		}
		Event @event = _eventBuffer[Random.Range(0, _eventBuffer.Count)];
		int num = GameState.day + Random.Range(0, 10);
		EE_Plugin.LogDebug($"event scheduled in all ports on day {GameState.day}");
		foreach (EventPort allPort in EventRegion.AllPorts)
		{
			allPort.AssignedEvent = @event.Id;
			allPort.DayEventStarts = num;
			allPort.DayEventEnds = num + @event.EventDuration;
			PortsWithEvents.Add(allPort);
		}
	}

	public void ScheduleEventInRegion(EventRegion region)
	{
		EventPort eventPort = region.Ports[Random.Range(0, region.Ports.Count)];
		_eventBuffer.Clear();
		foreach (Event event2 in Event.Events)
		{
			if (event2.SpecificPorts.Length == 0 || event2.SpecificPorts.Contains(eventPort.Index))
			{
				_eventBuffer.Add(event2);
			}
		}
		if (_eventBuffer.Count != 0)
		{
			Event @event = _eventBuffer[Random.Range(0, _eventBuffer.Count)];
			int num = GameState.day + Random.Range(0, 10);
			eventPort.AssignedEvent = @event.Id;
			eventPort.DayEventStarts = num;
			eventPort.DayEventEnds = num + @event.EventDuration;
			PortsWithEvents.Add(eventPort);
		}
	}

	internal void LoadPortsWithEvents(List<EventPort> portsWithEvents)
	{
		PortsWithEvents = portsWithEvents;
		foreach (EventPort portsWithEvent in PortsWithEvents)
		{
			EventPort eventPort = EventRegion.FindPort(portsWithEvent.Index);
			if (eventPort != null)
			{
				eventPort.AssignedEvent = portsWithEvent.AssignedEvent;
				eventPort.DayEventStarts = portsWithEvent.DayEventStarts;
				eventPort.DayEventEnds = portsWithEvent.DayEventEnds;
			}
		}
	}

	internal void LoadRegionChance(Dictionary<int, int> regionChance)
	{
		SaveLoadPatches.LoadDictionary(regionChance, RegionChance);
	}
}
[BepInPlugin("com.raddude82.economicevents", "EconomicEvents", "1.1.1")]
[BepInDependency("com.raddude82.modsavebackups", "1.1.1")]
public class EE_Plugin : BaseUnityPlugin
{
	public const string PLUGIN_GUID = "com.raddude82.economicevents";

	public const string PLUGIN_NAME = "EconomicEvents";

	public const string PLUGIN_VERSION = "1.1.1";

	public const string MODSAVEBACKUPS_GUID = "com.raddude82.modsavebackups";

	public const string MODSAVEBACKUPS_VERSION = "1.1.1";

	private static ManualLogSource _logger;

	internal static EE_Plugin Instance { get; private set; }

	internal static void LogDebug(string message)
	{
		_logger.LogDebug((object)message);
	}

	internal static void LogInfo(string message)
	{
		_logger.LogInfo((object)message);
	}

	internal static void LogWarning(string message)
	{
		_logger.LogWarning((object)message);
	}

	internal static void LogError(string message)
	{
		_logger.LogError((object)message);
	}

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_logger = ((BaseUnityPlugin)this).Logger;
		Configs.InitializeConfigs();
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.raddude82.economicevents");
		((Component)this).gameObject.AddComponent<EventScheduler>();
	}
}
internal class SaveLoadPatches
{
	[HarmonyPatch(typeof(SaveLoadManager))]
	private class SaveLoadManagerPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("SaveModData")]
		public static void DoSaveGamePatch()
		{
			EconomicEventsSaveContainer economicEventsSaveContainer = new EconomicEventsSaveContainer
			{
				loggedEventPorts = EventsUI.Instance.LoggedEventPorts.ToList(),
				portsWithEvents = EventScheduler.Instance.PortsWithEvents.ToList(),
				regionChance = EventScheduler.Instance.RegionChance.ToDictionary((KeyValuePair<int, int> entry) => entry.Key, (KeyValuePair<int, int> entry) => entry.Value)
			};
			ModSave.Save(((BaseUnityPlugin)EE_Plugin.Instance).Info, (object)economicEventsSaveContainer);
		}

		[HarmonyPostfix]
		[HarmonyPatch("LoadModData")]
		public static void LoadModDataPatch()
		{
			EconomicEventsSaveContainer economicEventsSaveContainer = default(EconomicEventsSaveContainer);
			if (!ModSave.Load<EconomicEventsSaveContainer>(((BaseUnityPlugin)EE_Plugin.Instance).Info, ref economicEventsSaveContainer))
			{
				EE_Plugin.LogWarning("Save file loading failed. If this is the first time loading this save with this mod, this is normal.");
				return;
			}
			if (economicEventsSaveContainer.loggedEventPorts != null)
			{
				EventsUI.Instance.LoadLoggedEventPorts(economicEventsSaveContainer.loggedEventPorts);
			}
			if (economicEventsSaveContainer.portsWithEvents != null)
			{
				EventScheduler.Instance.LoadPortsWithEvents(economicEventsSaveContainer.portsWithEvents);
			}
			if (economicEventsSaveContainer.regionChance != null)
			{
				EventScheduler.Instance.LoadRegionChance(economicEventsSaveContainer.regionChance);
			}
		}
	}

	public static void LoadDictionary<T>(Dictionary<int, T> saveDict, Dictionary<int, T> gameDict)
	{
		foreach (KeyValuePair<int, T> item in saveDict)
		{
			if (!gameDict.ContainsKey(item.Key))
			{
				EE_Plugin.LogWarning($"LoadData: {item.Key} not found in game");
			}
			else
			{
				gameDict[item.Key] = item.Value;
			}
		}
	}
}
[Serializable]
public class EconomicEventsSaveContainer
{
	public List<EventPort> loggedEventPorts;

	public List<EventPort> portsWithEvents;

	public Dictionary<int, int> regionChance;
}
internal class UpdateEventsPatches
{
	[HarmonyPatch(typeof(BuyItemUI))]
	private class BuyItemUIPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("Awake")]
		public static void CopyMenu(BuyItemUI __instance)
		{
			if (!_initialized)
			{
				_initialized = true;
				GameObject val = Object.Instantiate<GameObject>(((Component)__instance.menu.transform.parent).gameObject);
				((Object)val).name = "update events ui";
				Object.Destroy((Object)(object)val.GetComponent<BuyItemUI>());
				val.AddComponent<UpdateEventsUI>();
				Transform child = val.transform.GetChild(0);
				Object.Destroy((Object)(object)((Component)child.GetChild(0).GetChild(0)).gameObject.GetComponent<GPButtonBuyItem>());
				((Component)child.GetChild(0).GetChild(0)).gameObject.AddComponent<GPButtonUpdateEvents>();
				((Component)child.GetChild(0).GetChild(1)).GetComponent<TextMesh>().text = "update events";
				((Component)child.GetChild(1).GetChild(1)).GetComponent<TextMesh>().text = "Have you heard the latest\nnews?";
				UpdateEventsUI.Instance.UpdateEventsMenu = ((Component)child).gameObject;
			}
		}
	}

	[HarmonyPatch(typeof(PortDude))]
	private class PortDudePatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnTriggerEnter")]
		public static void OnTriggerEnterPatch(PortDude __instance, Collider other)
		{
			if (!((Component)other).CompareTag("Player"))
			{
				return;
			}
			List<EventPort> loggedEventPorts = EventsUI.Instance.LoggedEventPorts;
			foreach (EventPort portsWithEvent in EventScheduler.Instance.PortsWithEvents)
			{
				if (!portsWithEvent.IsEventActive())
				{
					continue;
				}
				bool flag = false;
				for (int i = 0; i < loggedEventPorts.Count; i++)
				{
					if (loggedEventPorts[i].Index == portsWithEvent.Index)
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					continue;
				}
				UpdateEventsUI.Instance.ActivateUI(__instance);
				break;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnTriggerExit")]
		public static void OnTriggerExitPatch(Collider other)
		{
			if (((Component)other).CompareTag("Player"))
			{
				UpdateEventsUI.Instance.DeactivateUI();
			}
		}
	}

	private static bool _initialized;
}
internal class EventsUI : MonoBehaviour
{
	private Dictionary<string, TextMesh> _eventTMs;

	public static EventsUI Instance { get; private set; }

	internal List<EventPort> LoggedEventPorts { get; set; }

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_eventTMs = new Dictionary<string, TextMesh>();
		LoggedEventPorts = new List<EventPort>();
	}

	public void UpdatePage()
	{
		for (int i = 0; i < 4; i++)
		{
			_eventTMs[$"event{i}"].text = string.Empty;
			_eventTMs[$"event{i}_description"].text = string.Empty;
			_eventTMs[$"event{i}_items"].text = string.Empty;
			_eventTMs[$"event{i}_multiplier"].text = string.Empty;
			_eventTMs[$"event{i}_duration"].text = string.Empty;
		}
		if (LoggedEventPorts.Count == 0)
		{
			_eventTMs["event0"].text = "No active events";
			return;
		}
		if (Event.EventsById.TryGetValue(LoggedEventPorts[0].AssignedEvent, out var value) && value.SpecificPorts.Length != 0 && value.SpecificPorts[0] == 999)
		{
			UpdateTexts(0, global: true);
			return;
		}
		for (int j = 0; j < LoggedEventPorts.Count; j++)
		{
			UpdateTexts(j, global: false);
		}
	}

	private void UpdateTexts(int i, bool global)
	{
		if (Event.EventsById.TryGetValue(LoggedEventPorts[i].AssignedEvent, out var value))
		{
			string itemsDisplay = value.GetItemsDisplay();
			int num = LoggedEventPorts[i].DayEventEnds - GameState.day;
			_eventTMs[$"event{i}"].text = (global ? (value.Name ?? "") : (value.Name + " in " + LoggedEventPorts[i].Name));
			_eventTMs[$"event{i}_description"].text = value.EventText;
			_eventTMs[$"event{i}_items"].text = (global ? ("Items affected: " + itemsDisplay) : ("Items needed: " + itemsDisplay));
			_eventTMs[$"event{i}_multiplier"].text = $"Price multiplier: <b>{value.PriceMult}X</b>";
			_eventTMs[$"event{i}_duration"].text = ((num == 0) ? "<b>Ends today</b>" : $"<b>Ends in {num} days</b>");
		}
	}

	internal void SetUIElems(Dictionary<string, TextMesh> eventTMs)
	{
		_eventTMs = eventTMs;
	}

	internal void LoadLoggedEventPorts(List<EventPort> loggedEventPorts)
	{
		LoggedEventPorts = loggedEventPorts;
	}
}
internal class LogUIPatches
{
	[HarmonyPatch(typeof(MissionListUI))]
	private class MissionListUIPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		public static void StartPatch(GameObject ___modeButtons, GameObject ___reputationUI)
		{
			UIBuilder.MakeBookmark(___modeButtons);
			eventsUI = UIBuilder.MakeEventsUI(___reputationUI);
		}

		[HarmonyAfter(new string[] { "com.raddude82.sailadex" })]
		[HarmonyPostfix]
		[HarmonyPatch("SwitchMode")]
		public static void SwitchModePatches(MissionListMode mode)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			eventsUI.SetActive(false);
			if ((int)mode == 8)
			{
				eventsUI.SetActive(true);
				EventsUI.Instance.UpdatePage();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("HideUI")]
		public static void HideUIPatches()
		{
			eventsUI.SetActive(false);
		}
	}

	private static GameObject eventsUI;
}
public class GPButtonUpdateEvents : GoPointerButton
{
	public override void OnActivate()
	{
		UpdateEventsUI.Instance.UpdateEvents();
		UpdateEventsUI.Instance.DeactivateUI();
	}
}
internal class UIBuilder
{
	private const int HEADER_FONT_SIZE = 55;

	private const int FONT_SIZE = 42;

	internal const MissionListMode EVENTS = 8;

	internal static void MakeBookmark(GameObject modeButtons)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		GameObject gameObject = ((Component)modeButtons.transform.GetChild(9)).gameObject;
		GameObject val = Object.Instantiate<GameObject>(gameObject);
		val.transform.parent = modeButtons.transform;
		val.transform.localPosition = new Vector3(-0.515f, -0.0032f, 0.071f);
		val.transform.localRotation = Quaternion.Euler(270f, 180f, 0f);
		val.transform.localScale = gameObject.transform.localScale;
		((Object)val).name = "bookmark events";
		((Component)val.transform.GetChild(0)).gameObject.GetComponent<TextMesh>().text = "events";
		val.transform.GetChild(0).localRotation = Quaternion.Euler(0f, 180f, 180f);
		GPButtonLogMode component = val.GetComponent<GPButtonLogMode>();
		Traverse.Create((object)component).Field("mode").SetValue((object)(MissionListMode)8);
		Object.Destroy((Object)(object)val.GetComponent<Outline>());
	}

	internal static GameObject MakeEventsUI(GameObject repUI)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0344: Unknown result type (might be due to invalid IL or missing references)
		//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0504: Unknown result type (might be due to invalid IL or missing references)
		//IL_066c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0671: Unknown result type (might be due to invalid IL or missing references)
		//IL_067b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0693: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_07bc: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(repUI);
		Object.Destroy((Object)(object)val.GetComponent<ReputationUI>());
		val.transform.parent = repUI.transform.parent;
		val.transform.localPosition = repUI.transform.localPosition;
		val.transform.localRotation = repUI.transform.localRotation;
		val.transform.localScale = repUI.transform.localScale;
		((Object)val).name = "events ui";
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(7)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(6)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(5)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)val.transform.GetChild(0)).gameObject);
		val.AddComponent<EventsUI>();
		GameObject gameObject = ((Component)val.transform.GetChild(1)).gameObject;
		gameObject.SetActive(true);
		gameObject.transform.localPosition = new Vector3(0.835f, -0.085f, -0.007f);
		gameObject.GetComponent<TextMesh>().font = ((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().font;
		gameObject.GetComponent<TextMesh>().fontSize = 42;
		gameObject.GetComponent<TextMesh>().characterSize = 1f;
		gameObject.GetComponent<TextMesh>().fontStyle = (FontStyle)1;
		gameObject.GetComponent<TextMesh>().anchor = (TextAnchor)0;
		gameObject.GetComponent<TextMesh>().text = string.Empty;
		((Renderer)gameObject.GetComponent<MeshRenderer>()).material = ((Renderer)((Component)gameObject.transform.GetChild(1)).GetComponent<MeshRenderer>()).material;
		((Object)((Component)gameObject.transform.GetChild(0)).gameObject).name = "description";
		gameObject.transform.GetChild(0).localPosition = new Vector3(0f, -5f, 0f);
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().font = ((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().font;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().fontSize = 42;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().characterSize = 1f;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().lineSpacing = 1f;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().anchor = (TextAnchor)0;
		((Component)gameObject.transform.GetChild(0)).GetComponent<TextMesh>().text = string.Empty;
		((Renderer)((Component)gameObject.transform.GetChild(0)).GetComponent<MeshRenderer>()).material = ((Renderer)((Component)gameObject.transform.GetChild(1)).GetComponent<MeshRenderer>()).material;
		((Object)((Component)gameObject.transform.GetChild(1)).gameObject).name = "items";
		gameObject.transform.GetChild(1).localPosition = new Vector3(0f, -17f, 0f);
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().fontSize = 42;
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().anchor = (TextAnchor)0;
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().fontStyle = (FontStyle)0;
		((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().text = string.Empty;
		((Object)((Component)gameObject.transform.GetChild(2)).gameObject).name = "multiplier";
		gameObject.transform.GetChild(2).localPosition = new Vector3(0f, -23f, 0f);
		((Component)gameObject.transform.GetChild(2)).GetComponent<TextMesh>().font = ((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().font;
		((Component)gameObject.transform.GetChild(2)).GetComponent<TextMesh>().fontSize = 42;
		((Component)gameObject.transform.GetChild(2)).GetComponent<TextMesh>().anchor = (TextAnchor)0;
		((Component)gameObject.transform.GetChild(2)).GetComponent<TextMesh>().fontStyle = (FontStyle)0;
		((Renderer)((Component)gameObject.transform.GetChild(2)).GetComponent<MeshRenderer>()).material = ((Renderer)((Component)gameObject.transform.GetChild(1)).GetComponent<MeshRenderer>()).material;
		((Component)gameObject.transform.GetChild(2)).GetComponent<TextMesh>().text = string.Empty;
		((Component)gameObject.transform.GetChild(2)).gameObject.SetActive(true);
		((Object)((Component)gameObject.transform.GetChild(3)).gameObject).name = "duration";
		gameObject.transform.GetChild(3).localPosition = new Vector3(0f, -29f, 0f);
		((Component)gameObject.transform.GetChild(3)).GetComponent<TextMesh>().font = ((Component)gameObject.transform.GetChild(1)).GetComponent<TextMesh>().font;
		((Component)gameObject.transform.GetChild(3)).GetComponent<TextMesh>().fontSize = 42;
		((Component)gameObject.transform.GetChild(3)).GetComponent<TextMesh>().anchor = (TextAnchor)0;
		((Component)gameObject.transform.GetChild(3)).GetComponent<TextMesh>().fontStyle = (FontStyle)0;
		((Renderer)((Component)gameObject.transform.GetChild(3)).GetComponent<MeshRenderer>()).material = ((Renderer)((Component)gameObject.transform.GetChild(1)).GetComponent<MeshRenderer>()).material;
		((Component)gameObject.transform.GetChild(3)).GetComponent<TextMesh>().text = string.Empty;
		((Component)gameObject.transform.GetChild(3)).gameObject.SetActive(true);
		Dictionary<string, TextMesh> dictionary = new Dictionary<string, TextMesh>();
		for (int i = 0; i < EventRegion.AllRegions.Count; i++)
		{
			string text = $"event{i}";
			float num = 0.835f;
			GameObject val2 = Object.Instantiate<GameObject>(gameObject);
			Object.Destroy((Object)(object)((Component)val2.transform.GetChild(4)).gameObject);
			((Object)val2).name = text;
			val2.transform.parent = gameObject.transform.parent;
			Transform transform = val2.transform;
			float num2 = 0.215f - 0.125f * (float)i;
			Vector3 localPosition = gameObject.transform.localPosition;
			transform.localPosition = new Vector3(num, num2, ((Vector3)(ref localPosition))[2]);
			val2.transform.localRotation = gameObject.transform.localRotation;
			val2.transform.localScale = gameObject.transform.localScale;
			dictionary[text ?? ""] = val2.GetComponent<TextMesh>();
			dictionary[text + "_description"] = ((Component)val2.transform.GetChild(0)).GetComponent<TextMesh>();
			dictionary[text + "_items"] = ((Component)val2.transform.GetChild(1)).GetComponent<TextMesh>();
			dictionary[text + "_multiplier"] = ((Component)val2.transform.GetChild(2)).GetComponent<TextMesh>();
			dictionary[text + "_duration"] = ((Component)val2.transform.GetChild(3)).GetComponent<TextMesh>();
		}
		EventsUI.Instance.SetUIElems(dictionary);
		((Object)gameObject).name = "events header";
		gameObject.GetComponent<TextMesh>().text = "Economic Events";
		gameObject.transform.localPosition = new Vector3(0.835f, 0.25f, -0.007f);
		gameObject.GetComponent<TextMesh>().fontSize = 55;
		gameObject.GetComponent<TextMesh>().fontStyle = (FontStyle)1;
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(4)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(3)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(2)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(1)).gameObject);
		Object.Destroy((Object)(object)((Component)gameObject.transform.GetChild(0)).gameObject);
		EE_Plugin.LogInfo("Loaded events UI");
		return val;
	}
}
internal class UpdateEventsUI : MonoBehaviour
{
	internal static UpdateEventsUI Instance { get; private set; }

	internal GameObject UpdateEventsMenu { get; set; }

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
		else
		{
			Instance = this;
		}
	}

	private void Update()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if (UpdateEventsMenu.activeInHierarchy)
		{
			((Component)this).transform.rotation = ((Component)Refs.observerMirror).transform.rotation;
		}
	}

	internal void ActivateUI(PortDude portDude)
	{
		//IL_000d: 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)
		((Component)this).transform.position = ((Component)portDude).transform.position;
		((Component)this).transform.rotation = ((Component)Refs.observerMirror).transform.rotation;
		UpdateEventsMenu.SetActive(true);
	}

	internal void DeactivateUI()
	{
		UpdateEventsMenu.SetActive(false);
	}

	internal void UpdateEvents()
	{
		UISoundPlayer.instance.PlayWritingSound();
		NotificationUi.instance.ShowNotification("Logbook updated");
		EventsUI.Instance.LoggedEventPorts = (from ep in EventScheduler.Instance.PortsWithEvents
			where ep.IsEventActive()
			orderby ep.DayEventEnds
			select ep).ToList();
	}
}
internal class Configs
{
	internal static ConfigEntry<int> eventInRegionBaseChance;

	internal static ConfigEntry<bool> enableGlobalEvents;

	internal static ConfigEntry<int> globalEventChance;

	internal static void InitializeConfigs()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		ConfigFile config = ((BaseUnityPlugin)EE_Plugin.Instance).Config;
		eventInRegionBaseChance = config.Bind<int>("Settings", "BaseEventInRegionChance", 20, new ConfigDescription("Base chance for an event to occur in a region.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		enableGlobalEvents = config.Bind<bool>("Settings", "EnableGlobalEvents", true, "Enable global events that affect all ports at once. If disabled, only regional events will occur.");
		globalEventChance = config.Bind<int>("Settings", "GlobalEventChance", 5, new ConfigDescription("Chance for a global event to occur.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
	}
}