using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
using com.github.zehsteam.Hitmarker.MonoBehaviours;
using com.github.zehsteam.Hitmarker.Patches;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.zehsteam.Hitmarker")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Shows a hitmarker when you successfully hit an enemy. With additional features. (Client-side)")]
[assembly: AssemblyFileVersion("1.2.3.0")]
[assembly: AssemblyInformationalVersion("1.2.3+9f550c00a965039c6c13c3bda8cf3750925b11f7")]
[assembly: AssemblyProduct("Hitmarker")]
[assembly: AssemblyTitle("com.github.zehsteam.Hitmarker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.3.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace com.github.zehsteam.Hitmarker
{
internal class ConfigManager
{
public ConfigEntry<bool> ExtendedLogging { get; private set; }
public ConfigEntry<bool> ShowHitmarkerImage { get; private set; }
public ConfigEntry<int> HitmarkerImageSize { get; private set; }
public ConfigEntry<bool> PlayHitmarkerSound { get; private set; }
public ConfigEntry<float> MessageDuration { get; private set; }
public ConfigEntry<int> MessageFontSize { get; private set; }
public ConfigEntry<bool> ShowDamageMessage { get; private set; }
public ConfigEntry<bool> ShowKillMessage { get; private set; }
public ConfigEntry<bool> OnlyShowLocalKillMessage { get; private set; }
public ConfigManager()
{
BindConfigs();
ClearUnusedEntries();
}
private void BindConfigs()
{
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Expected O, but got Unknown
ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
ExtendedLogging = config.Bind<bool>("General Settings", "ExtendedLogging", false, "Enable extended logging.");
ShowHitmarkerImage = config.Bind<bool>("Hitmarker Settings", "ShowHitmarkerImage", true, "Do you want to show the hitmarker image?");
HitmarkerImageSize = config.Bind<int>("Hitmarker Settings", "HitmarkerImageSize", 40, new ConfigDescription("The size of the hitmarker image in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>()));
PlayHitmarkerSound = config.Bind<bool>("Hitmarker Settings", "PlayHitmarkerSound", true, "Do you want to play the hitmarker sound?");
MessageDuration = config.Bind<float>("Message Settings", "MessageDuration", 4f, "The message duration in seconds.");
MessageFontSize = config.Bind<int>("Message Settings", "MessageFontSize", 35, new ConfigDescription("The message font size in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>()));
ShowDamageMessage = config.Bind<bool>("Message Settings", "ShowDamageMessage", true, "Shows a message of how much damage you did to an enemy.");
ShowKillMessage = config.Bind<bool>("Message Settings", "ShowKillMessage", true, "Shows a message when an enemy is killed.");
OnlyShowLocalKillMessage = config.Bind<bool>("Message Settings", "OnlyShowLocalKillMessage", true, "Will only show your kill messages.");
}
private void ClearUnusedEntries()
{
ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null);
dictionary.Clear();
config.Save();
}
}
internal class Content
{
public static GameObject HitmarkerCanvasPrefab;
public static void Load()
{
LoadAssetsFromAssetBundle();
}
private static void LoadAssetsFromAssetBundle()
{
try
{
string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location);
string text = Path.Combine(directoryName, "hitmarker_assets");
AssetBundle val = AssetBundle.LoadFromFile(text);
HitmarkerCanvasPrefab = val.LoadAsset<GameObject>("HitmarkerCanvas");
Plugin.logger.LogInfo((object)"Successfully loaded assets from AssetBundle!");
}
catch (Exception arg)
{
Plugin.logger.LogError((object)$"Error: failed to load assets from AssetBundle.\n\n{arg}");
}
}
}
[BepInPlugin("com.github.zehsteam.Hitmarker", "Hitmarker", "1.2.3")]
internal class Plugin : BaseUnityPlugin
{
private readonly Harmony harmony = new Harmony("com.github.zehsteam.Hitmarker");
internal static Plugin Instance;
internal static ManualLogSource logger;
internal static ConfigManager ConfigManager;
internal static bool IsHostOrServer => NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
logger = Logger.CreateLogSource("com.github.zehsteam.Hitmarker");
logger.LogInfo((object)"Hitmarker has awoken!");
harmony.PatchAll(typeof(HUDManagerPatch));
harmony.PatchAll(typeof(EnemyAIPatch));
ConfigManager = new ConfigManager();
Content.Load();
}
public void CreateHitmarkerCanvas()
{
if (!((Object)(object)HitmarkerCanvasBehaviour.Instance != (Object)null))
{
Object.Instantiate<GameObject>(Content.HitmarkerCanvasPrefab);
logger.LogInfo((object)"Instantiated Hitmarker canvas.");
}
}
public void LogInfoExtended(object data)
{
if (ConfigManager.ExtendedLogging.Value)
{
logger.LogInfo(data);
}
}
}
internal class Utils
{
public static bool IsLocalPlayer(PlayerControllerB playerScript)
{
return (Object)(object)StartOfRound.Instance.localPlayerController == (Object)(object)playerScript;
}
public static PlayerControllerB GetPlayerScript(int playerWhoHit)
{
if (playerWhoHit < 0 || playerWhoHit > StartOfRound.Instance.allPlayerScripts.Length - 1)
{
return null;
}
return StartOfRound.Instance.allPlayerScripts[playerWhoHit];
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.github.zehsteam.Hitmarker";
public const string PLUGIN_NAME = "Hitmarker";
public const string PLUGIN_VERSION = "1.2.3";
}
}
namespace com.github.zehsteam.Hitmarker.Patches
{
[HarmonyPatch(typeof(EnemyAI))]
internal class EnemyAIPatch
{
[HarmonyPatch("HitEnemyOnLocalClient")]
[HarmonyPrefix]
private static void HitEnemyOnLocalClientPatch(ref EnemyAI __instance, int force, PlayerControllerB playerWhoHit = null)
{
if (!((Object)(object)playerWhoHit == (Object)null) && Utils.IsLocalPlayer(playerWhoHit))
{
HitEnemy(__instance, force, playerWhoHit);
}
}
[HarmonyPatch("HitEnemyServerRpc")]
[HarmonyPrefix]
private static void HitEnemyServerRpcPatch(ref EnemyAI __instance, int force, int playerWhoHit)
{
if (playerWhoHit != -1)
{
PlayerControllerB playerScript = Utils.GetPlayerScript(playerWhoHit);
if (!Utils.IsLocalPlayer(playerScript))
{
HitEnemy(__instance, force, playerScript);
}
}
}
[HarmonyPatch("HitEnemyClientRpc")]
[HarmonyPrefix]
private static void HitEnemyClientRpcPatch(ref EnemyAI __instance, int force, int playerWhoHit)
{
if (playerWhoHit != -1 && !Plugin.IsHostOrServer)
{
PlayerControllerB playerScript = Utils.GetPlayerScript(playerWhoHit);
if (!Utils.IsLocalPlayer(playerScript))
{
HitEnemy(__instance, force, playerScript);
}
}
}
private static void HitEnemy(EnemyAI enemyAI, int force, PlayerControllerB playerWhoHit)
{
if (enemyAI.enemyType.canDie && !enemyAI.isEnemyDead && enemyAI.enemyHP > 0)
{
bool flag = Utils.IsLocalPlayer(playerWhoHit);
string enemyName = enemyAI.enemyType.enemyName;
bool flag2 = enemyAI.enemyHP - force <= 0;
if (flag)
{
HitmarkerCanvasBehaviour.Instance.ShowHitmarker(flag2);
HitmarkerCanvasBehaviour.Instance.ShowDamageMessage(enemyName, force);
}
if (flag2)
{
HitmarkerCanvasBehaviour.Instance.ShowKillMessage(enemyName, flag, playerWhoHit.playerUsername);
}
LogInfoExtended("HitEnemy();", enemyAI, force, playerWhoHit);
}
}
private static void LogInfoExtended(string functionName, EnemyAI enemyAI, int force, PlayerControllerB playerWhoHit)
{
NetworkObject component = ((Component)enemyAI).gameObject.GetComponent<NetworkObject>();
string text = (Utils.IsLocalPlayer(playerWhoHit) ? " (LOCAL)" : "");
string text2 = $"{functionName} NetworkObjectId: {component.NetworkObjectId}\n\n";
text2 += $"Player \"{playerWhoHit.playerUsername}\"{text} hit \"{enemyAI.enemyType.enemyName}\" for {force} force.\n";
text2 += $"isEnemyDead: {enemyAI.isEnemyDead}, enemyHP: {enemyAI.enemyHP}, (new enemyHP should be {enemyAI.enemyHP - force})\n";
Plugin.Instance.LogInfoExtended("\n\n" + text2.Trim() + "\n");
}
}
[HarmonyPatch(typeof(HUDManager))]
internal class HUDManagerPatch
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void StartPatch()
{
Plugin.Instance.CreateHitmarkerCanvas();
}
}
}
namespace com.github.zehsteam.Hitmarker.MonoBehaviours
{
public class HitmarkerCanvasBehaviour : MonoBehaviour
{
public static HitmarkerCanvasBehaviour Instance;
public HitmarkerImageBehaviour HitmarkerImageBehaviour;
public AudioClip HitSFX;
public RectTransform MessageListTransform;
public RectTransform MessageItemPrefab;
private Queue<RectTransform> _messageItemPool = new Queue<RectTransform>();
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
}
private void Start()
{
InitializeMessageItemPool();
}
private void InitializeMessageItemPool()
{
_messageItemPool = new Queue<RectTransform>();
for (int i = 0; i < 20; i++)
{
RectTransform val = Object.Instantiate<RectTransform>(MessageItemPrefab, (Transform)(object)MessageListTransform);
((Component)val).gameObject.SetActive(false);
_messageItemPool.Enqueue(val);
}
}
public void ShowHitmarker(bool killed = false)
{
ShowHitmarkerImage(killed);
PlayHitSFX();
}
private void ShowHitmarkerImage(bool killed = false)
{
if (Plugin.ConfigManager.ShowHitmarkerImage.Value)
{
HitmarkerImageBehaviour.ShowImage(killed);
}
}
private void PlayHitSFX()
{
if (Plugin.ConfigManager.PlayHitmarkerSound.Value)
{
HUDManager.Instance.UIAudio.PlayOneShot(HitSFX);
}
}
public void ShowDamageMessage(string enemyName, int damage = 1)
{
if (Plugin.ConfigManager.ShowDamageMessage.Value)
{
ShowMessage($"{enemyName} -{damage} HP");
}
}
public void ShowKillMessage(string enemyName, bool fromLocalPlayer = true, string fromPlayerName = "")
{
//IL_0063: 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)
if (Plugin.ConfigManager.ShowKillMessage.Value && (fromLocalPlayer || !Plugin.ConfigManager.OnlyShowLocalKillMessage.Value))
{
if (!fromLocalPlayer)
{
ShowMessage(fromPlayerName + " Killed " + enemyName, Color.red);
}
else
{
ShowMessage("Killed " + enemyName, Color.red);
}
}
}
private void ShowMessage(string text)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
ShowMessage(text, Color.white);
}
private void ShowMessage(string text, Color color)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
SpawnMessageItemFromPool(text, color);
}
private RectTransform SpawnMessageItemFromPool(string text, Color color)
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
if (_messageItemPool == null || _messageItemPool.Count == 0)
{
Plugin.logger.LogError((object)"Error: Failed to spawn message item from pool. Message item pool is either null or empty.");
return null;
}
RectTransform val = _messageItemPool.Dequeue();
((Component)val).gameObject.SetActive(true);
((Transform)val).SetAsLastSibling();
MessageItemBehaviour messageItemBehaviour = default(MessageItemBehaviour);
if (((Component)val).TryGetComponent<MessageItemBehaviour>(ref messageItemBehaviour))
{
messageItemBehaviour.SetText(text, color);
}
_messageItemPool.Enqueue(val);
return val;
}
}
public class HitmarkerImageBehaviour : MonoBehaviour
{
public Image Image;
public Color32 DefaultColor;
public Color32 KilledColor;
private Coroutine _fadeOutCoroutine;
private void Start()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
int value = Plugin.ConfigManager.HitmarkerImageSize.Value;
((Graphic)Image).rectTransform.sizeDelta = new Vector2((float)value, (float)value);
SetAlpha(0f);
}
public void ShowImage(bool killed = false)
{
//IL_0013: 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_0018: Unknown result type (might be due to invalid IL or missing references)
((Graphic)Image).color = Color32.op_Implicit(killed ? KilledColor : DefaultColor);
if (_fadeOutCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_fadeOutCoroutine);
}
_fadeOutCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeOut(0.25f));
}
private IEnumerator FadeOut(float duration)
{
SetAlpha(255f);
for (float timer = 0f; timer < duration; timer += Time.deltaTime)
{
float percent = 1f / duration * timer;
float alpha = 255f + -255f * percent;
SetAlpha(alpha);
yield return null;
}
SetAlpha(0f);
}
private void SetAlpha(float a)
{
//IL_0019: 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_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: 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)
a = Mathf.Clamp(a, 0f, 255f);
Color32 val = Color32.op_Implicit(((Graphic)Image).color);
val.a = (byte)a;
((Graphic)Image).color = Color32.op_Implicit(val);
}
}
public class MessageItemBehaviour : MonoBehaviour
{
public TextMeshProUGUI TextUGUI;
private Coroutine _animationCoroutine;
private void Start()
{
((TMP_Text)TextUGUI).fontSize = Plugin.ConfigManager.MessageFontSize.Value;
}
private void OnEnable()
{
if (_animationCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_animationCoroutine);
}
_animationCoroutine = ((MonoBehaviour)this).StartCoroutine(PlayAnimation());
}
private void OnDisable()
{
if (_animationCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_animationCoroutine);
}
}
private IEnumerator PlayAnimation()
{
yield return (object)new WaitForSeconds(Plugin.ConfigManager.MessageDuration.Value);
float fadeOutDuration = 1f;
SetAlpha(255f);
for (float timer = 0f; timer < fadeOutDuration; timer += Time.deltaTime)
{
float percent = 1f / fadeOutDuration * timer;
float alpha = 255f + -255f * percent;
SetAlpha(alpha);
yield return null;
}
SetAlpha(0f);
yield return null;
((Component)this).gameObject.SetActive(false);
}
public void SetText(string text)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
SetText(text, Color.white);
}
public void SetText(string text, Color color)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
((TMP_Text)TextUGUI).text = text;
((Graphic)TextUGUI).color = color;
}
private void SetAlpha(float a)
{
//IL_0019: 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_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: 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)
a = Mathf.Clamp(a, 0f, 255f);
Color32 val = Color32.op_Implicit(((Graphic)TextUGUI).color);
val.a = (byte)a;
((Graphic)TextUGUI).color = Color32.op_Implicit(val);
}
}
}