using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ProfitPercent")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProfitPercent")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1aa9f185-5e80-46e0-935b-a30791a11860")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ProfitPercent;
[BepInPlugin("pr0skynesis.profitpercent", "Profit Percent", "1.1.0")]
public class ProfitPercentMain : BaseUnityPlugin
{
public const string pluginGuid = "pr0skynesis.profitpercent";
public const string pluginName = "Profit Percent";
public const string pluginVersion = "1.1.0";
public static ConfigEntry<bool> coloredTextConfig;
public static ConfigEntry<int> greenThresholdConfig;
public static ConfigEntry<int> blueThresholdConfig;
public static ConfigEntry<bool> showBestDealsConfig;
public void Awake()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Expected O, but got Unknown
Harmony val = new Harmony("pr0skynesis.profitpercent");
MethodInfo methodInfo = AccessTools.Method(typeof(EconomyUI), "ShowGoodPage", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.Method(typeof(ProfitPercentPatches), "ShowGoodPage_Patch", (Type[])null, (Type[])null);
coloredTextConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("A) Colored text", "coloredText", true, "Enables the coloring of the profit in red (loss), green (profit), yellow (neither) and blue (high profit)");
greenThresholdConfig = ((BaseUnityPlugin)this).Config.Bind<int>("A) Colored text", "greenThreshold", 0, "Sets the value above which the profit % will be colored in green. E.g.: set to 30 to have the text be displayed as green only above 30% profit.");
blueThresholdConfig = ((BaseUnityPlugin)this).Config.Bind<int>("A) Colored text", "blueThreshold", 100, "Sets the value above which the profit % will be colored in blue, used to identify high profit margins.");
showBestDealsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Best Deals", "showBestDeals", true, "Display the best deals from the current port to the destinations in the currently selected bookmark. Set to false to disable.");
val.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
public class ProfitPercentPatches
{
private static bool instantiated;
[HarmonyPostfix]
public static void ShowGoodPage_Patch(int goodIndex, IslandMarket ___currentIsland, int[][] ___bookmarkIslands, int ___currentBookmark)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Expected O, but got Unknown
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
//IL_0c11: Unknown result type (might be due to invalid IL or missing references)
//IL_0c99: Unknown result type (might be due to invalid IL or missing references)
//IL_0ca0: Expected O, but got Unknown
TextMesh val = new TextMesh();
TextMesh val2 = new TextMesh();
TextMesh val3 = new TextMesh();
TextMesh val4 = new TextMesh();
TextMesh val5 = new TextMesh();
TextMesh val6 = new TextMesh();
TextMesh val7 = new TextMesh();
TextMesh val8 = new TextMesh();
TextMesh val9 = new TextMesh();
TextMesh val10 = new TextMesh();
TextMesh val11 = new TextMesh();
MethodInfo methodInfo = AccessTools.Method(typeof(EconomyUI), "GetBuyPrice", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.Method(typeof(EconomyUI), "GetSellPrice", (Type[])null, (Type[])null);
ShipItem good = PrefabsDirectory.instance.GetGood(goodIndex);
Good component = ((Component)good).GetComponent<Good>();
EconomyUI instance = EconomyUI.instance;
TextMesh[] componentsInChildren = ((Component)instance).GetComponentsInChildren<TextMesh>();
TextMesh val12 = componentsInChildren[2];
TextMesh val13 = componentsInChildren[3];
TextMesh val14 = componentsInChildren[6];
TextMesh val15 = componentsInChildren[7];
TextMesh val16 = componentsInChildren[8];
TextMesh val17 = componentsInChildren[9];
TextMesh val18 = componentsInChildren[11];
TextMesh val19 = componentsInChildren[13];
TextMesh val20 = componentsInChildren[14];
TextMesh val21 = componentsInChildren[16];
if (!instantiated)
{
val = Object.Instantiate<TextMesh>(val12, ((Component)val12).transform.parent);
((Object)val).name = "modIslandNames";
val2 = Object.Instantiate<TextMesh>(val17, ((Component)val17).transform.parent);
((Object)val2).name = "modProfitColumn";
val3 = Object.Instantiate<TextMesh>(val14, ((Component)val14).transform.parent);
((Object)val3).name = "modGoodName";
val4 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val4).name = "productionText";
val5 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val5).name = "percentText";
val6 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val6).name = "perPoundText";
val8 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val8).name = "bdBestDeals";
((Component)val8).transform.Rotate(0f, 0f, 15f);
val8.anchor = (TextAnchor)3;
val9 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val9).name = "bdPercent";
val9.anchor = (TextAnchor)3;
val10 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val10).name = "bdPerPound";
val10.anchor = (TextAnchor)3;
val11 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val11).name = "bdAbsolute";
val11.anchor = (TextAnchor)3;
val7 = Object.Instantiate<TextMesh>(val13, ((Component)val13).transform.parent);
((Object)val7).name = "highlightBar";
val7.anchor = (TextAnchor)3;
instantiated = true;
}
else
{
val = componentsInChildren[18];
val2 = componentsInChildren[19];
val3 = componentsInChildren[20];
val4 = componentsInChildren[21];
val5 = componentsInChildren[22];
val6 = componentsInChildren[23];
val8 = componentsInChildren[24];
val9 = componentsInChildren[25];
val10 = componentsInChildren[26];
val11 = componentsInChildren[27];
val7 = componentsInChildren[28];
}
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null || (Object)(object)val8 == (Object)null || (Object)(object)val9 == (Object)null || (Object)(object)val10 == (Object)null || (Object)(object)val11 == (Object)null)
{
Debug.LogError((object)"ProfitPercent: Some of the new TextMeshes are null!");
return;
}
val.text = "";
val2.text = "";
val3.text = char.ToUpper(good.name[0]) + good.name.Substring(1);
val4.text = "";
val5.text = "";
val6.text = "";
val8.text = "<color=#4D0000>★ Best Deals! ★</color>";
val9.text = BestDeals(instance, ___currentIsland, ___bookmarkIslands, ___currentBookmark, 0);
val10.text = BestDeals(instance, ___currentIsland, ___bookmarkIslands, ___currentBookmark, 1);
val11.text = BestDeals(instance, ___currentIsland, ___bookmarkIslands, ___currentBookmark, 2);
val7.text = "┌───────────────────────────────────┐\n└───────────────────────────────────┘";
for (int i = 0; i < ___bookmarkIslands[___currentBookmark].Length; i++)
{
int num = ___bookmarkIslands[___currentBookmark][i];
object[] parameters = new object[2]
{
___currentIsland.GetPortIndex(),
goodIndex
};
object[] parameters2 = new object[2] { num, goodIndex };
FieldInfo fieldInfo = AccessTools.Field(typeof(Port), "producedGoodPrefabs");
GameObject[] source = (GameObject[])fieldInfo.GetValue(Port.ports[num]);
int[] source2 = source.Select((GameObject go) => go.GetComponent<SaveablePrefab>().prefabIndex).ToArray();
int value = PrefabsDirectory.GoodToItemIndex(goodIndex);
if (source2.Contains(value))
{
TextMesh obj = val4;
obj.text += "✓\n";
}
else
{
TextMesh obj2 = val4;
obj2.text += "- \n";
}
int num2 = (int)methodInfo.Invoke(instance, parameters);
int num3 = (int)methodInfo2.Invoke(instance, parameters2);
float num4 = Mathf.Round((float)(num3 - num2) / (float)num2 * 100f);
float cargoWeight = component.GetCargoWeight();
float num5 = (float)Math.Round((float)(num3 - num2) / cargoWeight, 2);
if (ProfitPercentMain.coloredTextConfig.Value)
{
int value2 = ProfitPercentMain.blueThresholdConfig.Value;
int value3 = ProfitPercentMain.greenThresholdConfig.Value;
if (ProfitPercentMain.blueThresholdConfig.Value < ProfitPercentMain.greenThresholdConfig.Value)
{
value2 = ProfitPercentMain.greenThresholdConfig.Value;
value3 = ProfitPercentMain.blueThresholdConfig.Value;
}
if (float.IsInfinity(num4))
{
TextMesh obj3 = val2;
obj3.text += "<color=#CC7F00>- </color>\n";
TextMesh obj4 = val5;
obj4.text += "<color=#CC7F00>- </color>\n";
TextMesh obj5 = val6;
obj5.text += "<color=#CC7F00>- </color>\n";
}
else if (num4 > (float)value2)
{
TextMesh obj6 = val2;
obj6.text += $"<color=#051139>{num3 - num2}</color>\n";
TextMesh obj7 = val5;
obj7.text += $"<color=#051139>{num4}<size=40%>%</size></color>\n";
TextMesh obj8 = val6;
obj8.text += $"<color=#051139>{num5}</color>\n";
}
else if (num4 > (float)value3)
{
TextMesh obj9 = val2;
obj9.text += $"<color=#003300>{num3 - num2}</color>\n";
TextMesh obj10 = val5;
obj10.text += $"<color=#003300>{num4}<size=40%>%</size></color>\n";
TextMesh obj11 = val6;
obj11.text += $"<color=#003300>{num5}</color>\n";
}
else if (num4 < 0f)
{
TextMesh obj12 = val2;
obj12.text += $"<color=#4D0000>{num3 - num2}</color>\n";
TextMesh obj13 = val5;
obj13.text += $"<color=#4D0000>{num4}<size=40%>%</size></color>\n";
TextMesh obj14 = val6;
obj14.text += $"<color=#4D0000>{num5}</color>\n";
}
else
{
TextMesh obj15 = val2;
obj15.text += $"<color=#CC7F00>{num3 - num2}</color>\n";
TextMesh obj16 = val5;
obj16.text += $"<color=#CC7F00>{num4}<size=40%>%</size></color>\n";
TextMesh obj17 = val6;
obj17.text += $"<color=#CC7F00>{num5}</color>\n";
}
if (num == ___currentIsland.GetPortIndex())
{
TextMesh obj18 = val;
obj18.text = obj18.text + "<color=#4D0000>• " + Port.ports[num].GetPortName() + "</color>\n";
}
else
{
TextMesh obj19 = val;
obj19.text = obj19.text + Port.ports[num].GetPortName() + "\n";
}
}
else
{
if (num == ___currentIsland.GetPortIndex())
{
TextMesh obj20 = val;
obj20.text = obj20.text + "• " + Port.ports[num].GetPortName() + "\n";
}
else
{
TextMesh obj21 = val;
obj21.text = obj21.text + Port.ports[num].GetPortName() + "\n";
}
TextMesh obj22 = val2;
obj22.text += $"{num3 - num2}\n";
TextMesh obj23 = val5;
obj23.text += $"{num4}<size=40%>%</size>\n";
TextMesh obj24 = val6;
obj24.text += $"{num5}\n";
}
}
val16.characterSize = 0.85f;
val16.text = "days ago P. buy sell profit % p. pound";
val19.text = " | | | | | |";
float characterSize = (val6.characterSize = (val5.characterSize = (val17.characterSize = (val15.characterSize = (val13.characterSize = (val4.characterSize = (val18.characterSize = (val12.characterSize = (val2.characterSize = (val.characterSize = 0.8f))))))))));
val21.characterSize = characterSize;
MoveX(((Component)val).transform, 0.23f);
MoveX(((Component)val2).transform, -0.45f);
MoveX(((Component)val14).transform, 100f);
MoveX(((Component)val12).transform, 100f);
MoveX(((Component)val18).transform, 0.133f);
MoveX(((Component)val4).transform, 0.05f);
MoveX(((Component)val13).transform, -0.11f);
MoveX(((Component)val15).transform, -0.27f);
MoveX(((Component)val17).transform, 100f);
MoveX(((Component)val5).transform, -0.61f);
MoveX(((Component)val6).transform, -0.78f);
MoveX(((Component)val20).transform, -0.94f);
MoveXY(((Component)val21).transform, 0.64f, -0.8f);
val8.characterSize = 1.1f;
val9.characterSize = 0.7f;
val10.characterSize = 0.7f;
val11.characterSize = 0.7f;
MoveXY(((Component)val8).transform, 0.74f, -0.15f);
MoveXY(((Component)val9).transform, 0.64f, -0.2f);
MoveXY(((Component)val10).transform, 0.64f, -0.25f);
MoveXY(((Component)val11).transform, 0.64f, -0.3f);
if (!ProfitPercentMain.showBestDealsConfig.Value)
{
MoveX(((Component)val8).transform, 100f);
MoveX(((Component)val9).transform, 100f);
MoveX(((Component)val10).transform, 100f);
MoveX(((Component)val11).transform, 100f);
}
val7.lineSpacing = 0.9f;
val7.color = new Color(0.25f, 0f, 0f);
float[] array = new float[7] { 0.622f, 0.549f, 0.476f, 0.401f, 0.328f, 0.255f, 0.182f };
MoveXY(((Component)val7).transform, 0.64f, array[GetUIPortIndex(___currentIsland.GetPortIndex())]);
if (BookmarkCheck(___currentIsland.GetPortIndex()) != ___currentBookmark)
{
MoveX(((Component)val7).transform, 100f);
}
FieldInfo fieldInfo2 = AccessTools.Field(typeof(EconomyUI), "islandHighlightBar");
Transform val22 = (Transform)fieldInfo2.GetValue(instance);
MoveX(((Component)val22).transform, 100f);
}
private static void MoveX(Transform transform, float x)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
Vector3 localPosition = transform.localPosition;
localPosition.x = x;
transform.localPosition = localPosition;
}
private static void MoveXY(Transform transform, float x, float y)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
Vector3 localPosition = transform.localPosition;
localPosition.x = x;
localPosition.y = y;
transform.localPosition = localPosition;
}
private static string BestDeals(EconomyUI eco, IslandMarket currentIsland, int[][] bookmarkIslands, int currentBookmark, int selector)
{
if (!ProfitPercentMain.showBestDealsConfig.Value)
{
return "";
}
MethodInfo methodInfo = AccessTools.Method(typeof(EconomyUI), "GetBuyPrice", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.Method(typeof(EconomyUI), "GetSellPrice", (Type[])null, (Type[])null);
GameObject[] directory = PrefabsDirectory.instance.directory;
TransactionCategory[] array = new TransactionCategory[4];
RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
TransactionCategory[] validCategories = (TransactionCategory[])(object)array;
ShipItem[] array2 = (from go in directory
where (Object)(object)go != (Object)null
select go.GetComponent<ShipItem>() into shipItem
where (Object)(object)shipItem != (Object)null && validCategories.Contains(shipItem.category)
select shipItem).ToArray();
int[] array3 = new int[array2.Length];
int[] array4 = new int[array2.Length];
int index = 0;
int index2 = 0;
int index3 = 0;
int num = 0;
int num2 = 0;
int num3 = 0;
float num4 = -1000f;
float num5 = -1000f;
int num6 = -1000;
for (int i = 0; i < array3.Length; i++)
{
int num7 = i + 1;
if (i >= 44)
{
num7++;
}
object[] parameters = new object[2]
{
currentIsland.GetPortIndex(),
num7
};
array3[i] = (int)methodInfo.Invoke(eco, parameters);
for (int j = 0; j < bookmarkIslands[currentBookmark].Length; j++)
{
int num8 = bookmarkIslands[currentBookmark][j];
for (int k = 0; k < array4.Length; k++)
{
int num9 = k + 1;
if (k >= 44)
{
num9++;
}
float cargoWeight = ((Component)array2[k]).GetComponent<Good>().GetCargoWeight();
object[] parameters2 = new object[2] { num8, num9 };
int num10 = (int)methodInfo2.Invoke(eco, parameters2);
float num11;
float num12;
if (array3[k] == 0)
{
num11 = -10000f;
num12 = -10000f;
array4[k] = -10000;
}
else
{
num11 = Mathf.Round((float)(num10 - array3[k]) / (float)array3[k] * 100f);
num12 = (float)Math.Round((float)(num10 - array3[k]) / cargoWeight, 2);
array4[k] = num10 - array3[k];
}
if (num11 > num4)
{
num = k;
num4 = num11;
index = j;
}
if (num12 > num5)
{
num2 = k;
num5 = num12;
index2 = j;
}
if (array4[k] > num6)
{
num3 = k;
num6 = array4[k];
index3 = j;
}
}
}
}
switch (selector)
{
case 0:
{
string name3 = array2[num].name;
string portName3 = Port.ports[FixPortIndex(index, currentBookmark)].GetPortName();
string text3 = $"{num4}%";
name3 = char.ToUpper(name3[0]) + name3.Substring(1);
return "• " + name3 + " to " + portName3 + " will return a profit of " + text3 + "!";
}
case 1:
{
string name2 = array2[num2].name;
string portName2 = Port.ports[FixPortIndex(index2, currentBookmark)].GetPortName();
string text2 = $"{num5} per pound";
name2 = char.ToUpper(name2[0]) + name2.Substring(1);
return "• " + name2 + " to " + portName2 + " will return a profit of " + text2 + "!";
}
case 2:
{
string name = array2[num3].name;
string portName = Port.ports[FixPortIndex(index3, currentBookmark)].GetPortName();
string text = $"{num6} per unit";
name = char.ToUpper(name[0]) + name.Substring(1);
return "• " + name + " to " + portName + " will return a profit of " + text + "!";
}
default:
return "Something is wrong in this place...";
}
}
private static int FixPortIndex(int index, int currentBookmark)
{
switch (currentBookmark)
{
case 0:
{
int[] array4 = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
return array4[index];
}
case 1:
{
int[] array3 = new int[6] { 9, 10, 11, 12, 13, 14 };
return array3[index];
}
case 2:
{
int[] array2 = new int[6] { 15, 16, 17, 18, 19, 20 };
return array2[index];
}
default:
{
int[] array = new int[4] { 22, 23, 24, 25 };
return array[index];
}
}
}
private static int GetUIPortIndex(int portIndex)
{
if (portIndex <= 6)
{
return portIndex;
}
if (portIndex >= 9 && portIndex <= 14)
{
return portIndex - 9;
}
if (portIndex >= 15 && portIndex <= 20)
{
return portIndex - 15;
}
if (portIndex >= 22 && portIndex <= 25)
{
return portIndex - 22;
}
if (portIndex == 21)
{
return 0;
}
return 0;
}
private static int BookmarkCheck(int portIndex)
{
int[] source = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
int[] source2 = new int[6] { 9, 10, 11, 12, 13, 14 };
int[] source3 = new int[6] { 15, 16, 17, 18, 19, 20 };
int[] source4 = new int[4] { 22, 23, 24, 25 };
if (source.Contains(portIndex))
{
return 0;
}
if (source2.Contains(portIndex))
{
return 1;
}
if (source3.Contains(portIndex))
{
return 2;
}
if (source4.Contains(portIndex))
{
return 3;
}
return 0;
}
}