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;
}
}
}
}