using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Notiffy.API;
using PluginConfig.API;
using PluginConfig.API.Decorators;
using PluginConfig.API.Fields;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Crossover")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+06d55002185a931d843a93a72ce8f86a5ce97854")]
[assembly: AssemblyProduct("Crossover")]
[assembly: AssemblyTitle("Crossover")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace Crossover
{
public class ConfigManager
{
public static PluginConfigurator config;
public static BoolField Enable;
public static ColorField AccentColor;
public static BoolField EnableTrackers;
public static IntField TrackerThreshold;
public static Dictionary<string, BoolField> ForceTrackEnemies;
public static BoolField TrackerIgnorePuppets;
public static BoolField TrackerUseSpecificEnemyIcons;
public static BoolField TrackerShowEnemyNames;
public static ColorField TrackerColor;
public static FloatField StartScale;
public static FloatField EndScale;
public static FloatField EnemyHealthThreshold;
public static FloatSliderField CrossMarkOpacity;
public static FloatField ScalingDuration;
public static FloatField ScalingDelay;
public static FloatField VisibleDuration;
public static FloatField TrackerScale;
public static FloatSliderField TrackerMarkOpacity;
public static StringField LastVersion;
public static void Initialize()
{
}
public static bool IsEnemyForceTracked(EnemyType type)
{
return ForceTrackEnemies[((object)(EnemyType)(ref type)).ToString()].value;
}
private static void CreateTrackerForcedEnemies()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
ConfigPanel val = new ConfigPanel(config.rootPanel, "Always track enemy types...", "forcedTrackEnemies");
new ConfigHeader(config.rootPanel, "", 10);
new ConfigHeader(val, "You can, for example, force Powers and Mindflayers to always have an indicator shown. FUCK POWERS FUCK POWERS FUCK POWERS I HATE POWERS", 12, (TextAlignmentOptions)513);
string[] names = Enum.GetNames(typeof(EnemyType));
Array.Sort(names);
foreach (string text in names)
{
ForceTrackEnemies[text] = new BoolField(val, text, "forceTrack" + text, false);
}
}
static ConfigManager()
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Expected O, but got Unknown
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Expected O, but got Unknown
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Expected O, but got Unknown
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Expected O, but got Unknown
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: Expected O, but got Unknown
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Expected O, but got Unknown
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Expected O, but got Unknown
//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Expected O, but got Unknown
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
//IL_0244: Expected O, but got Unknown
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0267: Expected O, but got Unknown
//IL_0280: Unknown result type (might be due to invalid IL or missing references)
//IL_028a: Expected O, but got Unknown
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Expected O, but got Unknown
//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
//IL_02df: Expected O, but got Unknown
//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0302: Expected O, but got Unknown
//IL_031b: Unknown result type (might be due to invalid IL or missing references)
//IL_0325: Expected O, but got Unknown
//IL_033b: Unknown result type (might be due to invalid IL or missing references)
//IL_035a: Unknown result type (might be due to invalid IL or missing references)
//IL_0364: Expected O, but got Unknown
//IL_038c: Unknown result type (might be due to invalid IL or missing references)
//IL_0396: Expected O, but got Unknown
//IL_03af: Unknown result type (might be due to invalid IL or missing references)
//IL_03b9: Expected O, but got Unknown
ForceTrackEnemies = new Dictionary<string, BoolField>();
config = PluginConfigurator.Create("Crossover", "com.github.end-4.crossover");
string text = Path.Combine(Plugin.workingDir, "icon.png");
if (File.Exists(text))
{
config.SetIconWithURL(text);
}
new ConfigHeader(config.rootPanel, "", 10);
new ConfigHeader(config.rootPanel, "-- <color=#db1e39>DEATH CROSSES</color> --", 22);
Enable = new BoolField(config.rootPanel, "Enable death crosses", "enable", true);
AccentColor = new ColorField(config.rootPanel, "Cross accent color", "accentColor", new Color(73f / 85f, 0.11764706f, 19f / 85f));
new ConfigHeader(config.rootPanel, "", 10);
new ConfigHeader(config.rootPanel, "-- <color=#f1b613>ENEMY TRACKERS</color> --", 22);
new ConfigHeader(config.rootPanel, "Shows pointers for enemy locations even when they're out of view", 12);
EnableTrackers = new BoolField(config.rootPanel, "Enable tracker icons", "enableTrackers", false);
TrackerThreshold = new IntField(config.rootPanel, "Reveal last remaining x enemies", "trackerThreshold", 5);
CreateTrackerForcedEnemies();
TrackerIgnorePuppets = new BoolField(config.rootPanel, "Ignore puppets (blood bois)", "trackerIgnorePuppets", false);
TrackerUseSpecificEnemyIcons = new BoolField(config.rootPanel, "Use specific enemy type icons", "trackerUseSpecificEnemyIcons", true);
TrackerShowEnemyNames = new BoolField(config.rootPanel, "Show enemy names", "trackerShowEnemyNames", true);
TrackerColor = new ColorField(config.rootPanel, "Tracker accent color", "trackerColor", new Color(0.94509804f, 0.7137255f, 0.07450981f));
new ConfigHeader(config.rootPanel, "", 10);
new ConfigHeader(config.rootPanel, "-- <color=#ff7f27>ADVANCED</color> --", 22);
new ConfigHeader(config.rootPanel, "// <color=#db1e39>Death crosses</color>", 16, (TextAlignmentOptions)513);
StartScale = new FloatField(config.rootPanel, "Cross starting scale", "startScale", 2f);
EndScale = new FloatField(config.rootPanel, "Cross ending scale", "endScale", 0.35f);
EnemyHealthThreshold = new FloatField(config.rootPanel, "Cross enemy health threshold", "enemyHealthThreshold", 0f);
CrossMarkOpacity = new FloatSliderField(config.rootPanel, "Cross mark opacity", "crossMarkOpacity", new Tuple<float, float>(0f, 1f), 1f);
ScalingDelay = new FloatField(config.rootPanel, "Scaling delay", "scalingDelay", 0f);
ScalingDuration = new FloatField(config.rootPanel, "Scaling duration", "scalingDuration", 0.1333f);
VisibleDuration = new FloatField(config.rootPanel, "Visible duration", "visibleDuration", 0.5333f);
new ConfigHeader(config.rootPanel, "// <color=#f1b613>Enemy trackers</color>", 16, (TextAlignmentOptions)513);
TrackerScale = new FloatField(config.rootPanel, "Tracker mark scale", "trackerScale", 1f);
TrackerMarkOpacity = new FloatSliderField(config.rootPanel, "Tracker mark opacity", "trackerMarkOpacity", new Tuple<float, float>(0f, 1f), 0.7f);
LastVersion = new StringField(config.rootPanel, "Last version", "lastVersion", "0.0.0");
((ConfigField)LastVersion).hidden = true;
}
}
public class CrossBehavior : EnemyTrackingBehavior
{
private enum State
{
Hidden,
Marking
}
public bool startMarkImmediately = true;
public float markLifetime = 0.5333f;
public float scalingDelay;
public float scalingDuration = 0.1333f;
public float startScale = 1f;
public float endScale = 0.2f;
public Tuple<float, Color>[] colorSteps = Array.Empty<Tuple<float, Color>>();
private RectTransform rectTransform;
private CanvasGroup canvasGroup;
private Image frontLayerImage;
private Image backLayerImage;
private State state;
private float startMarkTime;
private float scaleDiff => startScale - endScale;
public Tuple<float, Color>[] GetUpdatedColorSteps()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: 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_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
Color item = Utils.Transparentize(((Graphic)backLayerImage).color);
return new Tuple<float, Color>[8]
{
Tuple.Create<float, Color>(0f, Color.white),
Tuple.Create<float, Color>(0.0333f, Color.black),
Tuple.Create<float, Color>(0.0667f, Color.white),
Tuple.Create<float, Color>(0.1333f, Color.black),
Tuple.Create<float, Color>(0.2f, ((Graphic)backLayerImage).color),
Tuple.Create<float, Color>(0.4f, item),
Tuple.Create<float, Color>(0.4667f, ((Graphic)backLayerImage).color),
Tuple.Create<float, Color>(0.5333f, item)
};
}
private void Awake()
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
frontLayerImage = ((Component)((Component)this).transform.Find("DeathCrossFrontLayer")).gameObject.GetComponent<Image>();
backLayerImage = ((Component)this).gameObject.GetComponent<Image>();
((Graphic)backLayerImage).color = ConfigManager.AccentColor.value;
colorSteps = GetUpdatedColorSteps();
startScale = ConfigManager.StartScale.value;
endScale = ConfigManager.EndScale.value;
scalingDuration = ConfigManager.ScalingDuration.value;
scalingDelay = ConfigManager.ScalingDelay.value;
markLifetime = ConfigManager.VisibleDuration.value;
canvasGroup = ((Component)this).GetComponent<CanvasGroup>();
canvasGroup.alpha = ConfigManager.CrossMarkOpacity.value;
if (canvasGroup.alpha < 1f)
{
((Graphic)backLayerImage).color = Utils.Transparentize(((Graphic)backLayerImage).color);
}
}
protected override void Start()
{
ref RectTransform reference = ref rectTransform;
Transform transform = ((Component)this).transform;
reference = (RectTransform)(object)((transform is RectTransform) ? transform : null);
base.Start();
}
private float Curve(float x)
{
float num = Math.Clamp(x, 0f, 1f);
float num2 = 1f - num;
return 1f - num2 * num2 * num2;
}
private void UpdateColor(float elapsedTime)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
int i = 0;
if (!(elapsedTime < 0f))
{
for (; i < colorSteps.Length && elapsedTime >= colorSteps[i].Item1; i++)
{
}
((Graphic)frontLayerImage).color = colorSteps[i - 1].Item2;
}
}
private void SetScale(float newScale)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
((Transform)rectTransform).localScale = new Vector3(newScale, newScale, newScale);
}
private void UpdateScale(float percentage)
{
float scale = startScale - Curve(percentage) * scaleDiff;
SetScale(scale);
}
protected override void Update()
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
if (state == State.Hidden && (startMarkImmediately || (Object)(object)enemy == (Object)null || enemy.health <= 0f))
{
state = State.Marking;
startMarkTime = Time.time;
}
if (state != 0)
{
float num = Time.time - startMarkTime;
UpdateColor(num);
UpdateScale((num - scalingDelay) / scalingDuration);
base.Update();
((Transform)rectTransform).position = canvasPoint;
if (Time.time - startMarkTime >= markLifetime)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
}
public class EnemyIndicatorController : EnemyTrackingBehavior
{
private bool _show;
private bool _cleanedUp;
private RectTransform rectTransform;
private CanvasGroup canvasGroup;
internal GameObject indicatorObject;
private Image frontLayerImage;
private Image backLayerImage;
private TMP_Text frontLayerText;
private TMP_Text backLayerText;
private static readonly string DEFAULT_ICON = "dot_circle";
private string enemyName = "Enemy";
private bool enemyCountBelowThreshold => (from e in MonoSingleton<EnemyTracker>.Instance.GetCurrentEnemies()
where !e.puppet
select e).Count() <= ConfigManager.TrackerThreshold.value;
private void SetText(string text)
{
if (!((Object)(object)frontLayerText == (Object)null) && !((Object)(object)backLayerText == (Object)null))
{
frontLayerText.text = text;
backLayerText.text = text;
}
}
private void SetAccentColor(Color color)
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)frontLayerImage == (Object)null) && !((Object)(object)frontLayerText == (Object)null))
{
if (((Object)frontLayerImage.sprite).name != DEFAULT_ICON)
{
color = Color.white;
}
((Graphic)frontLayerImage).color = color;
((Graphic)frontLayerText).color = color;
}
}
private void SetBackgroundColor(Color color)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)backLayerImage == (Object)null) && !((Object)(object)backLayerText == (Object)null))
{
((Graphic)backLayerImage).color = color;
((Graphic)backLayerText).color = color;
}
}
private void SetScale(float scale)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)rectTransform == (Object)null))
{
((Transform)rectTransform).localScale = new Vector3(scale, scale, scale);
Rect rect = rectTransform.rect;
float width = ((Rect)(ref rect)).width;
rect = rectTransform.rect;
clampPadding = Math.Max(width, ((Rect)(ref rect)).height);
}
}
private void SetAlpha(float alpha, Tuple<float, float> _ = null)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)canvasGroup == (Object)null))
{
canvasGroup.alpha = alpha;
if (canvasGroup.alpha < 1f)
{
SetBackgroundColor(Utils.Transparentize(((Graphic)backLayerImage).color));
}
else
{
SetBackgroundColor(Utils.Opacitize(((Graphic)backLayerImage).color));
}
}
}
private void SetActive(bool active)
{
if (!((Object)(object)indicatorObject == (Object)null))
{
indicatorObject.SetActive(active);
}
}
private void SetNameActive(bool active)
{
if ((Object)(object)frontLayerText != (Object)null)
{
((Component)frontLayerText).gameObject.SetActive(active);
}
if ((Object)(object)backLayerText != (Object)null)
{
((Component)backLayerText).gameObject.SetActive(active);
}
}
private void SetEnemyIcon(bool useSpecificEnemyIcon)
{
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
string input = ((object)(EnemyType)(ref enemy.enemyType)).ToString();
string key = DEFAULT_ICON;
if (useSpecificEnemyIcon)
{
string text = input.ToSnakeCase();
if (Plugin.EnemyIcons.ContainsKey(text))
{
key = text;
}
else
{
switch (enemy.FullName.ToLower())
{
case "earthmover mortar":
text = "centaur_mortar";
break;
case "earthmover rocket launcher":
text = "centaur_rocket";
break;
case "earthmover tower":
text = "centaur_orb";
break;
case "cancerous rodent":
text = "cancerous_rodent";
break;
case "very cancerous rodent":
text = "very_cancerous_rodent";
break;
case "big johninator":
text = "big_johninator";
break;
}
if (Plugin.EnemyIcons.ContainsKey(text))
{
key = text;
}
}
}
if (Plugin.EnemyIcons.TryGetValue(key, out Sprite value))
{
frontLayerImage.sprite = value;
backLayerImage.sprite = value;
SetAccentColor(ConfigManager.TrackerColor.value);
}
}
private void UpdateAppearance()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)indicatorObject == (Object)null))
{
SetAccentColor(ConfigManager.TrackerColor.value);
SetScale(ConfigManager.TrackerScale.value);
SetAlpha(ConfigManager.TrackerMarkOpacity.value);
SetNameActive(ConfigManager.TrackerShowEnemyNames.value);
SetEnemyIcon(ConfigManager.TrackerUseSpecificEnemyIcons.value);
indicatorObject.SetActive(ConfigManager.EnableTrackers.value);
}
}
private void UpdateShow()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
if (!enemyCountBelowThreshold && !ConfigManager.IsEnemyForceTracked(enemy.enemyType))
{
_show = false;
if ((Object)(object)indicatorObject != (Object)null)
{
indicatorObject.SetActive(false);
}
return;
}
if ((Object)(object)indicatorObject == (Object)null)
{
indicatorObject = Object.Instantiate<GameObject>(Plugin.EnemyIndicatorPrefab, Plugin.CrossoverCanvas.transform);
rectTransform = indicatorObject.GetComponent<RectTransform>();
canvasGroup = indicatorObject.GetComponent<CanvasGroup>();
frontLayerImage = ((Component)indicatorObject.transform.Find("EnemyTrackerFrontLayer")).GetComponent<Image>();
backLayerImage = indicatorObject.GetComponent<Image>();
frontLayerText = ((Component)indicatorObject.transform.Find("EnemyTrackerFrontLayer/FrontEnemyName")).GetComponent<TMP_Text>();
backLayerText = ((Component)indicatorObject.transform.Find("EnemyName")).GetComponent<TMP_Text>();
}
SetText(enemyName);
UpdateAppearance();
_show = true;
}
private void HookStuff()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Expected O, but got Unknown
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
ConfigManager.EnableTrackers.postValueChangeEvent += new PostBoolValueChangeEvent(SetActive);
ConfigManager.TrackerUseSpecificEnemyIcons.postValueChangeEvent += new PostBoolValueChangeEvent(SetEnemyIcon);
ConfigManager.TrackerShowEnemyNames.postValueChangeEvent += new PostBoolValueChangeEvent(SetNameActive);
ConfigManager.TrackerColor.postValueChangeEvent += new PostColorValueChangeEvent(SetAccentColor);
ConfigManager.TrackerScale.postValueChangeEvent += new PostFloatValueChangeEvent(SetScale);
ConfigManager.TrackerMarkOpacity.postValueChangeEvent += new PostFloatSliderValueChangeEvent(SetAlpha);
EnemyListener.EnemyCountChanged += UpdateShow;
enemy.destroyOnDeath.Add(indicatorObject);
}
private void UnhookStuff()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Expected O, but got Unknown
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Expected O, but got Unknown
EnemyListener.EnemyCountChanged -= UpdateShow;
ConfigManager.EnableTrackers.postValueChangeEvent -= new PostBoolValueChangeEvent(SetActive);
ConfigManager.TrackerUseSpecificEnemyIcons.postValueChangeEvent -= new PostBoolValueChangeEvent(SetEnemyIcon);
ConfigManager.TrackerShowEnemyNames.postValueChangeEvent -= new PostBoolValueChangeEvent(SetNameActive);
ConfigManager.TrackerColor.postValueChangeEvent -= new PostColorValueChangeEvent(SetAccentColor);
ConfigManager.TrackerScale.postValueChangeEvent -= new PostFloatValueChangeEvent(SetScale);
ConfigManager.TrackerMarkOpacity.postValueChangeEvent -= new PostFloatSliderValueChangeEvent(SetAlpha);
}
private void Awake()
{
clampToScreen = true;
}
protected override void Start()
{
base.Start();
TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;
EnemyIdentifier obj = enemy;
enemyName = textInfo.ToTitleCase(((obj != null) ? obj.FullName.ToLower() : null) ?? "Enemy");
UpdateShow();
HookStuff();
}
internal void PrintDebugInfo()
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
EnemyIdentifier obj = enemy;
string text = ((obj != null) ? ((object)((Component)obj).transform).ToString() : null) ?? "NULL TRANSFORM";
EnemyIdentifier obj2 = enemy;
Vector3? obj3;
if (obj2 == null)
{
obj3 = null;
}
else
{
Transform transform = ((Component)obj2).transform;
obj3 = ((transform != null) ? new Vector3?(transform.position) : null);
}
Vector3 val = (Vector3)(((??)obj3) ?? (Vector3.one * -1f));
string text2 = ((object)(Vector3)(ref val)).ToString() ?? "";
string text3 = $"{enemy?.health ?? (-1f)}";
GameObject obj4 = indicatorObject;
object obj5;
if (obj4 == null)
{
obj5 = null;
}
else
{
val = obj4.transform.position;
obj5 = ((object)(Vector3)(ref val)).ToString();
}
if (obj5 == null)
{
obj5 = "NULL POS";
}
string text4 = (string)obj5;
Plugin.Log.LogInfo((object)$"--- Enemy {enemyName} | transform: {text} | pos: {text2} | hp: {text3} | indicatorObject: {indicatorObject} | indicatorObjPos: {text4}");
}
protected override void Update()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)enemy == (Object)null || enemy.health <= 0f || (Object)(object)((Component)enemy).transform == (Object)null)
{
RemoveIndicatorAndStop();
}
else if (_show)
{
base.Update();
((Transform)rectTransform).position = canvasPoint;
}
}
private void RemoveIndicatorAndStop()
{
if (!_cleanedUp)
{
_cleanedUp = true;
_show = false;
if ((Object)(object)indicatorObject != (Object)null)
{
Object.Destroy((Object)(object)indicatorObject);
}
UnhookStuff();
Object.Destroy((Object)(object)this);
}
}
private void OnDestroy()
{
UnhookStuff();
if ((Object)(object)indicatorObject != (Object)null)
{
Object.Destroy((Object)(object)indicatorObject);
}
}
}
public static class EnemyListener
{
public delegate void OnSomeEnemyDied();
public static event OnSomeEnemyDied EnemyCountChanged;
internal static void NotifyChange()
{
EnemyListener.EnemyCountChanged?.Invoke();
}
}
public class EnemyTrackingBehavior : MonoBehaviour
{
public Vector3 canvasPoint;
protected Vector3 lastEnemyPosition = Vector3.zero;
public EnemyIdentifier enemy;
protected float enemyHeight;
public bool clampToScreen;
public float clampPadding;
public void SetEnemy(EnemyIdentifier enemy)
{
this.enemy = enemy;
}
protected Vector3 GetEnemyPosition()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: 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_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)enemy != (Object)null && (Object)(object)((Component)enemy).transform != (Object)null)
{
lastEnemyPosition = ((Component)enemy).transform.position;
}
return lastEnemyPosition + enemyHeight / 2f * Vector3.up;
}
private void UpdateCanvasPoint()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = MonoSingleton<CameraController>.Instance.cam.WorldToScreenPoint(GetEnemyPosition());
bool num = val.z < 0f;
int privateField = MonoSingleton<PostProcessV2_Handler>.Instance.GetPrivateField<int>("width");
int privateField2 = MonoSingleton<PostProcessV2_Handler>.Instance.GetPrivateField<int>("height");
val.x *= Screen.width;
val.y *= Screen.height;
val.x /= privateField;
val.y /= privateField2;
if (num)
{
float num2 = (float)privateField / 2f;
float num3 = (float)privateField - val.x - num2;
if (Mathf.Approximately(num3, 0f))
{
num3 = -1f;
}
val.x = num2 + num3 * 100000f;
}
if (clampToScreen)
{
val.x = Mathf.Clamp(val.x, clampPadding, (float)privateField - clampPadding);
val.y = Mathf.Clamp(val.y, clampPadding, (float)privateField2 - clampPadding);
}
canvasPoint = val;
}
protected virtual void Start()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)enemy == (Object)null))
{
Collider component = ((Component)enemy).GetComponent<Collider>();
Bounds bounds = component.bounds;
float y = (((Bounds)(ref bounds)).center - ((Component)enemy).transform.position).y;
bounds = component.bounds;
enemyHeight = y + ((Bounds)(ref bounds)).extents.y;
}
}
protected virtual void Update()
{
UpdateCanvasPoint();
}
}
[BepInPlugin("com.github.end-4.crossover", "Crossover", "1.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource? Log;
public static string workingPath = Assembly.GetExecutingAssembly().Location;
public static string workingDir = Path.GetDirectoryName(workingPath);
public const string PluginGUID = "com.github.end-4.crossover";
public const string PluginName = "Crossover";
public const string PluginVersion = "1.1.1";
internal static GameObject DeathCrossPrefab;
internal static GameObject EnemyIndicatorPrefab;
internal static GameObject CrossoverCanvasPrefab;
internal static GameObject CrossoverCanvas;
internal static Dictionary<string, Sprite> EnemyIcons = new Dictionary<string, Sprite>();
private static readonly string BundlePath = Path.Combine(workingDir, "assets", "crossover.bundle");
internal static string[] IconNames = new string[41]
{
"dot_circle", "big_johninator", "cancerous_rodent", "centaur_mortar", "centaur_orb", "centaur_rocket", "cerberus", "deathcatcher", "drone", "ferryman",
"filth", "flesh_panopticon", "flesh_prison", "gabriel", "gabriel_second", "gutterman", "guttertank", "hideous_mass", "idol", "malicious_face",
"mandalore", "mindflayer", "minos_prime", "minotaur", "mirror_reaper", "power", "providence", "puppet", "schism", "sisyphus",
"sisyphus_prime", "soldier", "stalker", "stray", "mannequin", "streetcleaner", "swordsmachine", "turret", "v2", "very_cancerous_rodent",
"virtue"
};
private void LoadObjects()
{
AssetBundle val = AssetBundle.LoadFromFile(BundlePath);
if ((Object)(object)val == (Object)null)
{
Log.LogError((object)"Couldn't load asset bundle");
}
DeathCrossPrefab = val.LoadAsset<GameObject>("DeathCross");
EnemyIndicatorPrefab = val.LoadAsset<GameObject>("EnemyIndicator");
CrossoverCanvasPrefab = val.LoadAsset<GameObject>("CrossoverCanvas");
CrossoverCanvas = Object.Instantiate<GameObject>(CrossoverCanvasPrefab);
Object.DontDestroyOnLoad((Object)(object)CrossoverCanvas);
((Object)CrossoverCanvas).hideFlags = (HideFlags)61;
for (int i = 0; i < IconNames.Length; i++)
{
string text = IconNames[i];
Sprite value = val.LoadAsset<Sprite>(text);
EnemyIcons.Add(text, value);
}
}
private void Awake()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
ConfigManager.Initialize();
LoadObjects();
new Harmony("Crossover").PatchAll();
UserHints.Initialize();
Log.LogInfo((object)"Crossover loaded!");
}
}
public static class UserHints
{
public static void IssueUpdateNoticeIfNecessary()
{
Version value = new Version(ConfigManager.LastVersion.value);
if (new Version("1.1.0").CompareTo(value) == 1)
{
ConfigManager.LastVersion.value = "1.1.1";
NotificationSystem.NotifySend("<color=#db1e39>Crossover</color> updated", "<b>1.1.0</b>: Added enemy tracking icons. Great for hunting down the last Cyber Grind Schisms or focusing on dangerous enemies. You can enable it in <color=#55c7f6>Options > Plugin Config > Crossover</color>", (Sprite)null, Path.Combine(Plugin.workingDir, "icon.png"), (Urgency)1, "NotifySend", 0u, (Dictionary<string, string>)null, 10000);
}
SceneManager.sceneLoaded -= IssueUpdateNoticeIfNecessary;
}
public static void IssueUpdateNoticeIfNecessary(Scene _, LoadSceneMode __)
{
IssueUpdateNoticeIfNecessary();
}
public static void Initialize()
{
}
static UserHints()
{
SceneManager.sceneLoaded += IssueUpdateNoticeIfNecessary;
}
}
internal static class Utils
{
internal static T GetPrivateField<T>(this object obj, string field)
{
Type type = obj.GetType();
if (type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic) == null)
{
throw new ArgumentException("The field " + field + " does not exist in target class " + type.Name + "!");
}
return (T)type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}
internal static Color Transparentize(Color color)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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_0017: Unknown result type (might be due to invalid IL or missing references)
return new Color(color.r, color.g, color.b, 0f);
}
internal static Color Opacitize(Color color)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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_0017: Unknown result type (might be due to invalid IL or missing references)
return new Color(color.r, color.g, color.b, 1f);
}
internal static string ToSnakeCase(this string input)
{
if (string.IsNullOrEmpty(input))
{
return input;
}
return Regex.Replace(input, "(?<!^)(?=[A-Z][a-z])|(?<=[a-z0-9])(?=[A-Z])", "_").ToLowerInvariant();
}
}
}
namespace Crossover.Patches
{
[HarmonyPatch(typeof(EnemyIdentifier))]
internal class EnemyPatch
{
[HarmonyPostfix]
[HarmonyPatch("ProcessDeath")]
private static void EnemyDied(EnemyIdentifier __instance)
{
if (ConfigManager.Enable.value && !(__instance.health < ConfigManager.EnemyHealthThreshold.value))
{
GameObject obj = Object.Instantiate<GameObject>(Plugin.DeathCrossPrefab, Plugin.CrossoverCanvas.transform);
obj.AddComponent<CrossBehavior>().SetEnemy(__instance);
obj.SetActive(true);
EnemyListener.NotifyChange();
}
}
[HarmonyPostfix]
[HarmonyPatch("Start")]
private static void EnemySpawned(EnemyIdentifier __instance)
{
if (ConfigManager.EnableTrackers.value && (!__instance.puppet || !ConfigManager.TrackerIgnorePuppets.value) && !((Object)(object)((Component)__instance).gameObject.GetComponent<EnemyIndicatorController>() != (Object)null))
{
((Component)__instance).gameObject.AddComponent<EnemyIndicatorController>().SetEnemy(__instance);
EnemyListener.NotifyChange();
}
}
}
}