Decompiled source of FamousLastWords v0.0.0

FamousLastWords.dll

Decompiled 18 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 CatAPI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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;
		}
	}
}
internal static class PluginInfo
{
	public const string PLUGIN_GUID = "com.yummi.dsp.famouslastwords";

	public const string PLUGIN_NAME = "FamousLastWords";

	public const string PLUGIN_VERSION = "0.0.0";
}
namespace FamousLastWords
{
	[HarmonyPatch]
	internal static class DetonationPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameLogic), "OnFactoryFrameEnd")]
		[Guard("813317f2ed4f7c1e")]
		public static void OnFactoryFrameEnd_Postfix()
		{
			if (DSPGame.IsMenuDemo)
			{
				return;
			}
			GameData data = GameMain.data;
			SkillSystem val = data?.spaceSector?.skillSystem;
			if (val == null || data.factories == null)
			{
				return;
			}
			for (int i = 0; i < data.factoryCount; i++)
			{
				PlanetFactory val2 = data.factories[i];
				if (val2?.powerSystem != null)
				{
					ScanFactory(val2, val);
				}
			}
		}

		private static void ScanFactory(PlanetFactory factory, SkillSystem skillSystem)
		{
			PowerGeneratorComponent[] genPool = factory.powerSystem.genPool;
			int genCursor = factory.powerSystem.genCursor;
			for (int i = 1; i < genCursor; i++)
			{
				ref PowerGeneratorComponent reference = ref genPool[i];
				if (reference.id == i && reference.fuelMask == 1 && (Settings.TryGetBlast(reference.fuelId, out var blast) || Settings.TryGetBlast(reference.curFuelId, out blast)) && TakeRods(factory, ref reference, out var rodId, out var rodCount))
				{
					Explosion.Detonate(factory, skillSystem, reference.entityId, rodId, rodCount);
				}
			}
		}

		private static bool TakeRods(PlanetFactory factory, ref PowerGeneratorComponent gen, out int rodId, out int rodCount)
		{
			rodId = 0;
			rodCount = 0;
			lock (factory.entityMutexs[gen.entityId])
			{
				if (Settings.TryGetBlast(gen.fuelId, out var blast))
				{
					rodId = gen.fuelId;
					rodCount += gen.fuelCount;
				}
				if (Settings.TryGetBlast(gen.curFuelId, out blast) && gen.fuelEnergy > 0)
				{
					if (rodId == 0)
					{
						rodId = gen.curFuelId;
					}
					if (rodId == gen.curFuelId)
					{
						rodCount++;
					}
				}
				if (rodId == 0)
				{
					return false;
				}
				gen.fuelId = 0;
				gen.fuelCount = 0;
				gen.fuelInc = 0;
				gen.curFuelId = 0;
				gen.fuelEnergy = 0L;
				gen.fuelHeat = 0L;
			}
			rodCount = Mathf.Max(rodCount, 1);
			return true;
		}
	}
	internal static class Explosion
	{
		private const int SelfDestructDamage = 268435456;

		private const long HpScale = 100L;

		private const int CrystalExplosiveUnit = 1130;

		internal static void Detonate(PlanetFactory factory, SkillSystem skillSystem, int sourceEntityId, int rodId, int rodCount)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			if (!Settings.TryGetBlast(rodId, out var blast))
			{
				return;
			}
			long num = blast.Damage * (100 + (long)Settings.ExtraRodPercent * (long)(rodCount - 1)) / 100 * 100;
			int num2 = (int)((num > 1073741823) ? 1073741823 : num);
			float num3 = (100f + (float)(Settings.ExtraRodRadiusPercent * (rodCount - 1))) / 100f;
			float num4 = blast.Radius * num3;
			int planetId = factory.planetId;
			Vector3 pos = factory.entityPool[sourceEntityId].pos;
			SkillTarget caster = new SkillTarget
			{
				id = 0,
				type = (ETargetType)0,
				astroId = planetId
			};
			PrefabDesc[] prefabDescByModelIndex = PlanetFactory.PrefabDescByModelIndex;
			int num5 = 0;
			PlayEffect(skillSystem, planetId, pos, blast.EffectScale * num3);
			SkillTarget val = new SkillTarget
			{
				id = sourceEntityId,
				type = (ETargetType)0,
				astroId = planetId
			};
			skillSystem.DamageObject(268435456, 1, ref val, ref caster);
			if (num2 > 0)
			{
				EntityData[] entityPool = factory.entityPool;
				for (int i = 1; i < factory.entityCursor; i++)
				{
					ref EntityData reference = ref entityPool[i];
					if (reference.id == i && i != sourceEntityId && InRange(pos, reference.pos, num4, prefabDescByModelIndex, reference.modelIndex))
					{
						Hit(skillSystem, (ETargetType)0, i, planetId, num2, ref caster);
						num5++;
					}
				}
				EnemyData[] enemyPool = factory.enemyPool;
				for (int j = 1; j < factory.enemyCursor; j++)
				{
					ref EnemyData reference2 = ref enemyPool[j];
					if (reference2.id == j && !((EnemyData)(ref reference2)).isInvincible && InRange(pos, VectorLF3.op_Implicit(reference2.pos), num4, prefabDescByModelIndex, reference2.modelIndex))
					{
						Hit(skillSystem, (ETargetType)4, j, planetId, num2, ref caster);
						num5++;
					}
				}
				CraftData[] craftPool = factory.craftPool;
				for (int k = 1; k < factory.craftCursor; k++)
				{
					ref CraftData reference3 = ref craftPool[k];
					if (reference3.id == k && !((CraftData)(ref reference3)).isInvincible && InRange(pos, VectorLF3.op_Implicit(reference3.pos), num4, prefabDescByModelIndex, reference3.modelIndex))
					{
						Hit(skillSystem, (ETargetType)6, k, planetId, num2, ref caster);
						num5++;
					}
				}
				if (HitPlayer(factory, skillSystem, pos, num4, num2))
				{
					num5++;
				}
			}
			ItemProto obj = ((ProtoSet<ItemProto>)(object)LDB.items).Select(rodId);
			string text = ((obj != null) ? ((Proto)obj).name : null) ?? rodId.ToString();
			Plugin.Log.LogInfo((object)$"{factory.planet.displayName}:火电 #{sourceEntityId} 引爆 {rodCount} 根{text},伤害 {(long)num2 / 100L},半径 {num4:0.#} 米,波及 {num5} 个目标");
		}

		private static void PlayEffect(SkillSystem skillSystem, int astroId, Vector3 center, float scale)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if (!(scale <= 0f) && astroId == skillSystem.localAstroId && skillSystem.hitEffects != null)
			{
				int valueOrDefault = (((ProtoSet<ItemProto>)(object)LDB.items).Select(1130)?.prefabDesc?.AmmoHitIndex).GetValueOrDefault();
				if (valueOrDefault <= 0 || valueOrDefault >= skillSystem.hitEffects.Length || skillSystem.hitEffects[valueOrDefault] == null)
				{
					Plugin.Log.LogWarning((object)$"找不到晶石爆破单元的爆炸特效(hitIndex={valueOrDefault}),本次不显示特效。");
					return;
				}
				DataPoolRenderer<ParticleData> val = skillSystem.hitEffects[valueOrDefault];
				ref ParticleData reference = ref val.Add();
				reference.duration = 120;
				reference.astroId = astroId;
				reference.pos = center;
				reference.size = scale;
				skillSystem.audio.PlayPlanetParticleSFX(val, ref reference);
			}
		}

		private static bool InRange(Vector3 center, Vector3 pos, float radius, PrefabDesc[] prefabs, int modelIndex)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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)
			float num = 0f;
			if (modelIndex > 0 && modelIndex < prefabs.Length && prefabs[modelIndex] != null)
			{
				num = prefabs[modelIndex].roughRadius;
			}
			float num2 = radius + num;
			Vector3 val = pos - center;
			return ((Vector3)(ref val)).sqrMagnitude <= num2 * num2;
		}

		private static void Hit(SkillSystem skillSystem, ETargetType type, int id, int astroId, int damage, ref SkillTarget caster)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			SkillTarget val = new SkillTarget
			{
				id = id,
				type = type,
				astroId = astroId
			};
			skillSystem.DamageObject(damage, 1, ref val, ref caster);
		}

		private static bool HitPlayer(PlanetFactory factory, SkillSystem skillSystem, Vector3 center, float radius, int damage)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Player mainPlayer = GameMain.mainPlayer;
			Mecha mecha = skillSystem.mecha;
			if (mainPlayer == null || mecha == null || !mainPlayer.isAlive || mainPlayer.planetId != factory.planetId)
			{
				return false;
			}
			Vector3 val = mainPlayer.position - center;
			if (((Vector3)(ref val)).sqrMagnitude > radius * radius)
			{
				return false;
			}
			mecha.EnergyShieldResist(ref damage);
			if (damage > 0)
			{
				mecha.TakeDamage(damage);
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class FuelNeedsPatch
	{
		internal const int ThermalFuelMask = 1;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemProto), "InitFuelNeeds")]
		[Guard("a3cc8cf615df4a97")]
		public static void InitFuelNeeds_Postfix()
		{
			Extend();
		}

		internal static void Extend()
		{
			int[] array = ItemProto.fuelNeeds[1];
			if (array == null)
			{
				return;
			}
			List<int> list = new List<int>(array);
			int[] rods = Settings.Rods;
			foreach (int num in rods)
			{
				if (!list.Contains(num) && ((ProtoSet<ItemProto>)(object)LDB.items).Select(num) != null)
				{
					list.Add(num);
				}
			}
			if (list.Count != array.Length)
			{
				ItemProto.fuelNeeds[1] = list.ToArray();
			}
		}
	}
	[BepInPlugin("com.yummi.dsp.famouslastwords", "FamousLastWords", "0.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.yummi.dsp.famouslastwords";

		public const string PluginName = "FamousLastWords";

		public const string PluginVersion = "0.0.0";

		private static readonly Harmony harmony = new Harmony("com.yummi.dsp.famouslastwords");

		private static readonly PatchOptions HarnessOptions = new PatchOptions
		{
			ModName = "FamousLastWords"
		};

		internal static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Settings.Bind(((BaseUnityPlugin)this).Config);
			Harness.PatchAll(harmony, typeof(DetonationPatch), HarnessOptions);
			if (!IsPatched(AccessTools.Method(typeof(GameLogic), "OnFactoryFrameEnd", (Type[])null, (Type[])null)))
			{
				Log.LogWarning((object)"引爆检测的补丁没有应用,火电不会接受燃料棒。");
				return;
			}
			Harness.PatchAll(harmony, typeof(FuelNeedsPatch), HarnessOptions);
			if (IsPatched(AccessTools.Method(typeof(ItemProto), "InitFuelNeeds", (Type[])null, (Type[])null)))
			{
				FuelNeedsPatch.Extend();
			}
			else
			{
				Log.LogWarning((object)"燃料列表的补丁没有应用,火电不会接受燃料棒。");
			}
			Log.LogInfo((object)"FamousLastWords v0.0.0 已加载");
		}

		private static bool IsPatched(MethodBase method)
		{
			Patches val = ((method == null) ? null : Harmony.GetPatchInfo(method));
			if (val != null)
			{
				return val.Owners.Contains("com.yummi.dsp.famouslastwords");
			}
			return false;
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
		}
	}
	internal struct Blast
	{
		internal int Damage;

		internal float Radius;

		internal float EffectScale;
	}
	internal static class Settings
	{
		internal const int ConfigSchemaVersion = 2;

		internal const int DeuteronRod = 1802;

		internal const int AntimatterRod = 1803;

		internal const int StrangeAnnihilationRod = 1804;

		internal static readonly int[] Rods = new int[3] { 1802, 1803, 1804 };

		private static ConfigEntry<int> deuteronDamage;

		private static ConfigEntry<float> deuteronRadius;

		private static ConfigEntry<float> deuteronEffect;

		private static ConfigEntry<int> antimatterDamage;

		private static ConfigEntry<float> antimatterRadius;

		private static ConfigEntry<float> antimatterEffect;

		private static ConfigEntry<int> strangeDamage;

		private static ConfigEntry<float> strangeRadius;

		private static ConfigEntry<float> strangeEffect;

		private static ConfigEntry<int> extraRodPercent;

		private static ConfigEntry<int> extraRodRadiusPercent;

		internal static int ExtraRodPercent
		{
			get
			{
				if (extraRodPercent.Value >= 0)
				{
					return extraRodPercent.Value;
				}
				return 0;
			}
		}

		internal static int ExtraRodRadiusPercent
		{
			get
			{
				if (extraRodRadiusPercent.Value >= 0)
				{
					return extraRodRadiusPercent.Value;
				}
				return 0;
			}
		}

		private static string Desc(string en, string zh)
		{
			return en + "\n" + zh;
		}

		internal static void Bind(ConfigFile config)
		{
			//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_0018: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			Harness.ApplyConfigSchema(config, 2, new ConfigSchemaOptions
			{
				WipeIfBelow = 2
			});
			deuteronDamage = BindDamage(config, "Deuteron", 500, "Deuteron Fuel Rod", "氘核燃料棒");
			deuteronRadius = BindRadius(config, "Deuteron", 40f, "Deuteron Fuel Rod", "氘核燃料棒");
			deuteronEffect = BindEffect(config, "Deuteron", 4f, "Deuteron Fuel Rod", "氘核燃料棒");
			antimatterDamage = BindDamage(config, "Antimatter", 3000, "Antimatter Fuel Rod", "反物质燃料棒");
			antimatterRadius = BindRadius(config, "Antimatter", 120f, "Antimatter Fuel Rod", "反物质燃料棒");
			antimatterEffect = BindEffect(config, "Antimatter", 12f, "Antimatter Fuel Rod", "反物质燃料棒");
			strangeDamage = BindDamage(config, "StrangeAnnihilation", 10000, "Strange Annihilation Fuel Rod", "奇异湮灭燃料棒");
			strangeRadius = BindRadius(config, "StrangeAnnihilation", 480f, "Strange Annihilation Fuel Rod", "奇异湮灭燃料棒");
			strangeEffect = BindEffect(config, "StrangeAnnihilation", 36f, "Strange Annihilation Fuel Rod", "奇异湮灭燃料棒");
			extraRodPercent = config.Bind<int>("Blast", "ExtraRodPercent", 50, new ConfigDescription(Desc("Extra damage (percent of the base) for every rod in the plant beyond the first. 50: 3 rods deal 2x damage.", "发电站里除第一根外,每多一根燃料棒增加的伤害(基础伤害的百分比)。50 即 3 根燃料棒造成 2 倍伤害。"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), Array.Empty<object>()));
			extraRodRadiusPercent = config.Bind<int>("Blast", "ExtraRodRadiusPercent", 10, new ConfigDescription(Desc("Extra blast radius (percent of the base) for every rod in the plant beyond the first. 10: 3 rods reach 1.2x radius. The explosion effect grows by the same ratio.", "发电站里除第一根外,每多一根燃料棒增加的爆炸半径(基础半径的百分比)。10 即 3 根燃料棒半径变为 1.2 倍。爆炸特效按同样比例放大。"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), Array.Empty<object>()));
			Harness.PruneConfigKeys(config, (ConfigDefinition[])(object)new ConfigDefinition[12]
			{
				((ConfigEntryBase)deuteronDamage).Definition,
				((ConfigEntryBase)deuteronRadius).Definition,
				((ConfigEntryBase)deuteronEffect).Definition,
				((ConfigEntryBase)antimatterDamage).Definition,
				((ConfigEntryBase)antimatterRadius).Definition,
				((ConfigEntryBase)antimatterEffect).Definition,
				((ConfigEntryBase)strangeDamage).Definition,
				((ConfigEntryBase)strangeRadius).Definition,
				((ConfigEntryBase)strangeEffect).Definition,
				((ConfigEntryBase)extraRodPercent).Definition,
				((ConfigEntryBase)extraRodRadiusPercent).Definition,
				new ConfigDefinition("_ConfigSchema", "Version")
			});
		}

		private static ConfigEntry<int> BindDamage(ConfigFile config, string section, int value, string en, string zh)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			return config.Bind<int>(section, "Damage", value, new ConfigDescription(Desc("Damage dealt to everything in range when a thermal plant detonates one " + en + ".", "火电引爆一根" + zh + "时,对范围内所有目标造成的伤害。"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000000), Array.Empty<object>()));
		}

		private static ConfigEntry<float> BindRadius(ConfigFile config, string section, float value, string en, string zh)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			return config.Bind<float>(section, "Radius", value, new ConfigDescription(Desc("Blast radius in meters for " + en + ".", zh + "的爆炸半径(米)。"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>()));
		}

		private static ConfigEntry<float> BindEffect(ConfigFile config, string section, float value, string en, string zh)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			return config.Bind<float>(section, "EffectScale", value, new ConfigDescription(Desc("Size of the explosion effect for " + en + ", as a multiple of the Crystal Explosive Unit blast. 0 = no effect.", zh + "爆炸特效的大小,按晶石爆破单元爆炸的倍数计。0 为不显示特效。"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
		}

		internal static bool TryGetBlast(int itemId, out Blast blast)
		{
			switch (itemId)
			{
			case 1802:
				blast = new Blast
				{
					Damage = deuteronDamage.Value,
					Radius = deuteronRadius.Value,
					EffectScale = deuteronEffect.Value
				};
				return true;
			case 1803:
				blast = new Blast
				{
					Damage = antimatterDamage.Value,
					Radius = antimatterRadius.Value,
					EffectScale = antimatterEffect.Value
				};
				return true;
			case 1804:
				blast = new Blast
				{
					Damage = strangeDamage.Value,
					Radius = strangeRadius.Value,
					EffectScale = strangeEffect.Value
				};
				return true;
			default:
				blast = default(Blast);
				return false;
			}
		}
	}
}