Decompiled source of SODLethalActionReborn v1.0.4

SOD.LethalActionReborn.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using SOD.Common;
using SOD.Common.BepInEx;
using SOD.Common.BepInEx.Configuration;
using SOD.Common.Extensions;
using SOD.Common.Helpers;
using SOD.LethalActionReborn.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SOD.LethalActionReborn")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+4d12de394cca59f54d683ec13e921db597f69b1f")]
[assembly: AssemblyProduct("SOD.LethalActionReborn")]
[assembly: AssemblyTitle("SOD.LethalActionReborn")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SOD.LethalActionReborn
{
	public interface IPluginBindings
	{
		[Binding(1, "How many hits on the knocked out citizen are required to kill the citizen by the player?", "Citizens.HitsRequiredForKillAfterKo")]
		int HitsRequiredForKillAfterKo { get; set; }

		[Binding("", "Which weapon types won't kill citizens when attacked with by the player? (Comma-seperated) Available types are: fists,rifle,blade,bluntObject,handgun,shotgun", "Weapons.WeaponTypesExcludedFromKilling")]
		string WeaponTypesExcludedFromKilling { get; set; }
	}
	[BepInPlugin("Venomaus.SOD.LethalActionReborn", "LethalActionReborn", "1.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : PluginController<Plugin, IPluginBindings>
	{
		public const string PLUGIN_GUID = "Venomaus.SOD.LethalActionReborn";

		public const string PLUGIN_NAME = "LethalActionReborn";

		public const string PLUGIN_VERSION = "1.0.4";

		public override void Load()
		{
			Lib.SaveGame.OnAfterLoad += SaveGame_OnAfterLoad;
			Lib.SaveGame.OnAfterSave += SaveGame_OnAfterSave;
			Lib.SaveGame.OnAfterDelete += SaveGame_OnAfterDelete;
			base.Harmony.PatchAll(Assembly.GetExecutingAssembly());
			PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Plugin is patched.");
		}

		public override void OnConfigureBindings()
		{
			base.OnConfigureBindings();
			CitizenPatches.Citizen_RecieveDamage.ExcludedWeaponTypes = (from a in base.Config.WeaponTypesExcludedFromKilling.Split(',')
				select Enum.TryParse(typeof(WeaponType), a, ignoreCase: true, out object result) ? ((WeaponType?)result) : null into a
				where a.HasValue
				select a.Value).ToHashSet();
		}

		private void SaveGame_OnAfterDelete(object sender, SaveGameArgs e)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "lethalActioned_" + uniqueString + ".txt");
			if (File.Exists(savestoreDirectoryPath))
			{
				File.Delete(savestoreDirectoryPath);
			}
		}

		private void SaveGame_OnAfterSave(object sender, SaveGameArgs e)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
			File.WriteAllText(Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "lethalActioned_" + uniqueString + ".txt"), string.Join(",", CitizenPatches.Citizen_RecieveDamage.KilledCitizens));
		}

		private void SaveGame_OnAfterLoad(object sender, SaveGameArgs e)
		{
			CitizenPatches.Citizen_RecieveDamage.CitizenHitsTakenOnKo.Clear();
			string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "lethalActioned_" + uniqueString + ".txt");
			if (!File.Exists(savestoreDirectoryPath))
			{
				return;
			}
			HashSet<int> hashSet = (from a in File.ReadAllText(savestoreDirectoryPath).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select int.Parse(a)).ToHashSet();
			HashSet<int> hashSet2 = (from a in EnumerableExtensions.ToList<Human>(CityData.Instance.deadCitizensDirectory)
				select a.humanID).ToHashSet();
			Human val = default(Human);
			foreach (int item in hashSet)
			{
				CitizenPatches.Citizen_RecieveDamage.KilledCitizens.Add(item);
				if (CityData.Instance.citizenDictionary.TryGetValue(item, ref val))
				{
					((Actor)val).SetHealth(0f);
					((Actor)val).animationController.cit.Murder((Human)(object)Player.Instance, false, (Murder)null, (Interactable)null, 1f);
					if (!hashSet2.Contains(item))
					{
						CityData.Instance.deadCitizensDirectory.Add(val);
						hashSet2.Add(item);
					}
					int num = 0;
					while ((Object)(object)MurderController.Instance.currentMurderer != (Object)null && MurderController.Instance.currentMurderer.humanID == item && num < 500)
					{
						num++;
						MurderController.Instance.currentMurderer = null;
						MurderController.Instance.PickNewMurderer();
					}
					num = 0;
					while ((Object)(object)MurderController.Instance.currentVictim != (Object)null && MurderController.Instance.currentVictim.humanID == item && num < 500)
					{
						num++;
						MurderController.Instance.currentVictim = null;
						MurderController.Instance.PickNewVictim();
					}
				}
			}
		}
	}
}
namespace SOD.LethalActionReborn.Patches
{
	internal class CitizenPatches
	{
		[HarmonyPatch(typeof(Citizen), "RecieveDamage")]
		internal static class Citizen_RecieveDamage
		{
			internal static readonly HashSet<int> KilledCitizens = new HashSet<int>();

			private static bool _hasKilled = false;

			internal static HashSet<WeaponType> ExcludedWeaponTypes = null;

			internal static Dictionary<int, int> CitizenHitsTakenOnKo = new Dictionary<int, int>();

			[HarmonyPrefix]
			internal static void Prefix(Citizen __instance, Actor fromWho)
			{
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)fromWho == (Object)(object)Player.Instance) || !((Actor)__instance).ai.ko)
				{
					return;
				}
				if (ExcludedWeaponTypes != null && ExcludedWeaponTypes.Any() && BioScreenController.Instance.selectedSlot != null)
				{
					Interactable interactable = BioScreenController.Instance.selectedSlot.GetInteractable();
					if (interactable != null && (SoCustomComparison)(object)interactable.preset.weapon != (SoCustomComparison)null)
					{
						MurderWeaponPreset weapon = interactable.preset.weapon;
						if (ExcludedWeaponTypes.Contains(weapon.type))
						{
							_hasKilled = false;
							return;
						}
					}
				}
				CitizenHitsTakenOnKo.TryGetValue(((Human)__instance).humanID, out var value);
				value++;
				CitizenHitsTakenOnKo[((Human)__instance).humanID] = value;
				if (value >= ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.HitsRequiredForKillAfterKo)
				{
					_hasKilled = true;
				}
			}

			[HarmonyPostfix]
			internal static void Postfix(Citizen __instance, Actor fromWho)
			{
				if (!((Actor)__instance).isDead && _hasKilled && (Object)(object)fromWho == (Object)(object)Player.Instance)
				{
					_hasKilled = false;
					((Actor)__instance).SetHealth(0f);
					((Actor)__instance).animationController.cit.Murder((Human)(object)Player.Instance, false, (Murder)null, (Interactable)null, 1f);
					CityData.Instance.deadCitizensDirectory.Add((Human)(object)__instance);
					KilledCitizens.Add(((Human)__instance).humanID);
					int num = 0;
					while ((Object)(object)MurderController.Instance.currentMurderer != (Object)null && MurderController.Instance.currentMurderer.humanID == ((Human)__instance).humanID && num < 500)
					{
						num++;
						MurderController.Instance.currentMurderer = null;
						MurderController.Instance.PickNewMurderer();
					}
					num = 0;
					while ((Object)(object)MurderController.Instance.currentVictim != (Object)null && MurderController.Instance.currentVictim.humanID == ((Human)__instance).humanID && num < 500)
					{
						num++;
						MurderController.Instance.currentVictim = null;
						MurderController.Instance.PickNewVictim();
					}
				}
			}
		}

		[HarmonyPatch(typeof(NewAIController), "SetKO")]
		internal static class NewAIController_SetKO
		{
			[HarmonyPostfix]
			internal static void Postfix(NewAIController __instance, bool val)
			{
				if (!val)
				{
					Citizen_RecieveDamage.CitizenHitsTakenOnKo.Remove(__instance.human.humanID);
				}
			}
		}
	}
}