Decompiled source of EnemyKillBonus v1.0.0

EnemyKillBonus.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.SceneManagement;

[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: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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.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 REPOJP.EnemyKillBonusMod
{
	[BepInPlugin("REPOJP.EnemyKillBonus", "EnemyKillBonus", "1.0.0")]
	public sealed class EnemyKillBonusPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "REPOJP.EnemyKillBonus";

		public const string PluginName = "EnemyKillBonus";

		public const string PluginVersion = "1.0.0";

		internal static EnemyKillBonusPlugin Instance;

		internal static ManualLogSourceWrapper LogWrapper;

		internal static ConfigEntry<int> Tier1MinK;

		internal static ConfigEntry<int> Tier1MaxK;

		internal static ConfigEntry<int> Tier2MinK;

		internal static ConfigEntry<int> Tier2MaxK;

		internal static ConfigEntry<int> Tier3MinK;

		internal static ConfigEntry<int> Tier3MaxK;

		internal static ConfigEntry<bool> DebugLog;

		private Harmony harmony;

		private void Awake()
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			Instance = this;
			LogWrapper = new ManualLogSourceWrapper(((BaseUnityPlugin)this).Logger);
			Tier1MinK = ((BaseUnityPlugin)this).Config.Bind<int>("Reward", "Tier1MinK", 0, "Minimum reward for Tier 1 enemies in k$.ティア1敵の最小報酬k$");
			Tier1MaxK = ((BaseUnityPlugin)this).Config.Bind<int>("Reward", "Tier1MaxK", 2, "Maximum reward for Tier 1 enemies in k$.ティア1敵の最大報酬k$");
			Tier2MinK = ((BaseUnityPlugin)this).Config.Bind<int>("Reward", "Tier2MinK", 2, "Minimum reward for Tier 2 enemies in k$.ティア2敵の最小報酬k$");
			Tier2MaxK = ((BaseUnityPlugin)this).Config.Bind<int>("Reward", "Tier2MaxK", 5, "Maximum reward for Tier 2 enemies in k$.ティア2敵の最大報酬k$");
			Tier3MinK = ((BaseUnityPlugin)this).Config.Bind<int>("Reward", "Tier3MinK", 5, "Minimum reward for Tier 3 enemies in k$.ティア3敵の最小報酬k$");
			Tier3MaxK = ((BaseUnityPlugin)this).Config.Bind<int>("Reward", "Tier3MaxK", 10, "Maximum reward for Tier 3 enemies in k$.ティア3敵の最大報酬k$");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLog", false, "Enable debug logs.デバッグログ有効化");
			ValidateConfig();
			EnemyKillBonusRuntime.Initialize();
			SceneManager.sceneLoaded += OnSceneLoaded;
			harmony = new Harmony("REPOJP.EnemyKillBonus");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"EnemyKillBonus loaded");
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			EnemyKillBonusRuntime.ClearRewardedEnemies();
			if (DebugLog.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Scene loaded -> cleared rewarded enemy cache: " + ((Scene)(ref scene)).name));
			}
		}

		private void ValidateConfig()
		{
			ClampRange(Tier1MinK, Tier1MaxK, "Tier1");
			ClampRange(Tier2MinK, Tier2MaxK, "Tier2");
			ClampRange(Tier3MinK, Tier3MaxK, "Tier3");
		}

		private void ClampRange(ConfigEntry<int> minEntry, ConfigEntry<int> maxEntry, string label)
		{
			int num = minEntry.Value;
			int num2 = maxEntry.Value;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 < 0)
			{
				num2 = 0;
			}
			if (num2 < num)
			{
				num2 = num;
			}
			if (num != minEntry.Value || num2 != maxEntry.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"{label} reward range corrected: Min={num} Max={num2}");
			}
			minEntry.Value = num;
			maxEntry.Value = num2;
		}
	}
	internal static class EnemyKillBonusRuntime
	{
		private static readonly HashSet<int> RewardedEnemyViewIds = new HashSet<int>();

		internal static void Initialize()
		{
			ClearRewardedEnemies();
		}

		internal static void ClearRewardedEnemies()
		{
			RewardedEnemyViewIds.Clear();
		}

		internal static void UnmarkRewarded(EnemyHealth enemyHealth)
		{
			if ((Object)(object)enemyHealth == (Object)null)
			{
				return;
			}
			PhotonView component = ((Component)enemyHealth).GetComponent<PhotonView>();
			if (!((Object)(object)component == (Object)null))
			{
				RewardedEnemyViewIds.Remove(component.ViewID);
				if (EnemyKillBonusPlugin.DebugLog.Value)
				{
					EnemyKillBonusPlugin.LogWrapper.LogInfo("Removed rewarded flag for enemy ViewID=" + component.ViewID);
				}
			}
		}

		internal static void TryHandleEnemyDeath(EnemyHealth enemyHealth)
		{
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemyHealth == (Object)null || !SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.RunIsLevel())
			{
				return;
			}
			PhotonView component = ((Component)enemyHealth).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null)
			{
				if (EnemyKillBonusPlugin.DebugLog.Value)
				{
					EnemyKillBonusPlugin.LogWrapper.LogWarning("Enemy death skipped because PhotonView was not found");
				}
				return;
			}
			if (RewardedEnemyViewIds.Contains(component.ViewID))
			{
				if (EnemyKillBonusPlugin.DebugLog.Value)
				{
					EnemyKillBonusPlugin.LogWrapper.LogInfo("Enemy reward skipped because already rewarded. ViewID=" + component.ViewID);
				}
				return;
			}
			Enemy component2 = ((Component)enemyHealth).GetComponent<Enemy>();
			if ((Object)(object)component2 == (Object)null)
			{
				if (EnemyKillBonusPlugin.DebugLog.Value)
				{
					EnemyKillBonusPlugin.LogWrapper.LogWarning("Enemy death skipped because Enemy component was not found");
				}
				return;
			}
			EnemyParent componentInParent = ((Component)component2).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				if (EnemyKillBonusPlugin.DebugLog.Value)
				{
					EnemyKillBonusPlugin.LogWrapper.LogWarning("Enemy death skipped because EnemyParent was not found");
				}
				return;
			}
			int num = GetRewardByDifficulty(componentInParent.difficulty);
			if (num < 0)
			{
				num = 0;
			}
			RewardedEnemyViewIds.Add(component.ViewID);
			int num2 = SemiFunc.StatGetRunCurrency();
			int num3 = num2 + num;
			SemiFunc.StatSetRunCurrency(num3);
			Vector3 enemyDeathPosition = GetEnemyDeathPosition(component2);
			PlayerAvatar nearestAlivePlayer = GetNearestAlivePlayer(enemyDeathPosition);
			if ((Object)(object)nearestAlivePlayer != (Object)null && (Object)(object)TruckScreenText.instance != (Object)null)
			{
				string playerName = nearestAlivePlayer.playerName;
				string text = "+" + num + "k$";
				TruckScreenText.instance.MessageSendCustom(playerName, text, 0);
				if (EnemyKillBonusPlugin.DebugLog.Value)
				{
					EnemyKillBonusPlugin.LogWrapper.LogInfo($"Reward applied: Enemy={componentInParent.enemyName}, Difficulty={componentInParent.difficulty}, Reward={num}k, Currency {num2} -> {num3}, ChatPlayer={playerName}");
				}
			}
			else if (EnemyKillBonusPlugin.DebugLog.Value)
			{
				EnemyKillBonusPlugin.LogWrapper.LogInfo($"Reward applied without chat: Enemy={componentInParent.enemyName}, Difficulty={componentInParent.difficulty}, Reward={num}k, Currency {num2} -> {num3}");
			}
		}

		private static Vector3 GetEnemyDeathPosition(Enemy enemy)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			//IL_001d: 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)
			if ((Object)(object)enemy.CenterTransform != (Object)null)
			{
				return enemy.CenterTransform.position;
			}
			return ((Component)enemy).transform.position;
		}

		private static PlayerAvatar GetNearestAlivePlayer(Vector3 position)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerAvatar> list = SemiFunc.PlayerGetAll();
			if (list == null || list.Count == 0)
			{
				return null;
			}
			PlayerAvatar result = null;
			float num = float.MaxValue;
			foreach (PlayerAvatar item in list)
			{
				if (IsAlivePlayer(item))
				{
					Vector3 playerDistancePosition = GetPlayerDistancePosition(item);
					float num2 = Vector3.Distance(position, playerDistancePosition);
					if (num2 < num)
					{
						num = num2;
						result = item;
					}
				}
			}
			return result;
		}

		private static bool IsAlivePlayer(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!((Component)player).gameObject.activeInHierarchy)
			{
				return false;
			}
			if (player.isDisabled)
			{
				return false;
			}
			if (player.deadSet)
			{
				return false;
			}
			if ((Object)(object)player.playerHealth == (Object)null)
			{
				return false;
			}
			if (player.playerHealth.health <= 0)
			{
				return false;
			}
			return true;
		}

		private static Vector3 GetPlayerDistancePosition(PlayerAvatar player)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_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)
			if ((Object)(object)player.PlayerVisionTarget != (Object)null && (Object)(object)player.PlayerVisionTarget.VisionTransform != (Object)null)
			{
				return player.PlayerVisionTarget.VisionTransform.position;
			}
			return ((Component)player).transform.position;
		}

		private static int GetRewardByDifficulty(Difficulty difficulty)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected I4, but got Unknown
			int value;
			int num;
			switch ((int)difficulty)
			{
			case 0:
				value = EnemyKillBonusPlugin.Tier1MinK.Value;
				num = EnemyKillBonusPlugin.Tier1MaxK.Value;
				break;
			case 1:
				value = EnemyKillBonusPlugin.Tier2MinK.Value;
				num = EnemyKillBonusPlugin.Tier2MaxK.Value;
				break;
			case 2:
				value = EnemyKillBonusPlugin.Tier3MinK.Value;
				num = EnemyKillBonusPlugin.Tier3MaxK.Value;
				break;
			default:
				value = EnemyKillBonusPlugin.Tier1MinK.Value;
				num = EnemyKillBonusPlugin.Tier1MaxK.Value;
				break;
			}
			if (num < value)
			{
				num = value;
			}
			return Random.Range(value, num + 1);
		}
	}
	[HarmonyPatch]
	internal static class EnemyKillBonusPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyHealth), "DeathImpulseRPC")]
		private static void EnemyHealth_DeathImpulseRPC_Postfix(EnemyHealth __instance)
		{
			try
			{
				EnemyKillBonusRuntime.TryHandleEnemyDeath(__instance);
			}
			catch (Exception ex)
			{
				EnemyKillBonusPlugin.LogWrapper.LogError("Failed in EnemyHealth_DeathImpulseRPC_Postfix\n" + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyHealth), "OnSpawn")]
		private static void EnemyHealth_OnSpawn_Postfix(EnemyHealth __instance)
		{
			try
			{
				EnemyKillBonusRuntime.UnmarkRewarded(__instance);
			}
			catch (Exception ex)
			{
				EnemyKillBonusPlugin.LogWrapper.LogError("Failed in EnemyHealth_OnSpawn_Postfix\n" + ex);
			}
		}
	}
	internal sealed class ManualLogSourceWrapper
	{
		private readonly ManualLogSource logger;

		internal ManualLogSourceWrapper(ManualLogSource logger)
		{
			this.logger = logger;
		}

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

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

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