Decompiled source of BloodbugMode v1.0.3
BloodbugMode.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
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.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DarkMachine.AI; using HarmonyLib; using Microsoft.CodeAnalysis; using Rewired; using TrinketAndBindingFramework; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Rendering; using UnityEngine.Rendering.PostProcessing; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BloodbugMode")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3+8d24d5c310cd5f8a91eddbda211de5ea4b5f16bd")] [assembly: AssemblyProduct("BloodbugMode")] [assembly: AssemblyTitle("BloodbugMode")] [assembly: InternalsVisibleTo("BloodbugMode.SelfTest")] [assembly: AssemblyVersion("1.0.3.0")] [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; } } } namespace BloodbugMode { internal static class Balance { public const float Scale = 0.4f; public const float WalkSpeed = 0.7f; public const float ThrowStrength = 0.5f; public const float CarryStrength = 0.5f; public const float LightBodyKnockback = 1.6f; public const float WetDrainMultiplier = 2f; public const float WetSeconds = 15f; public const float InjurySpeed = 12.5f; public const float InjuryStaminaLoss = 0.25f; public const float InjurySeconds = 60f; public const int MaxInjuries = 3; public const float CruiseSpeed = 8f; public const float BurstSpeed = 14f; public const float Inertia = 0.85f; public const float Wobble = 0.85f; public const float HungryBelow = 0.3f; public const float StarvingSpeed = 0.75f; public const float MaxStamina = 75f; public const float HoverDrain = 7f; public const float CruiseDrain = 12f; public const float BurstDrain = 16f; public const float GroundRegen = 17f; public const float PerchRegen = 14f; public const float FoodStamina = 40f; public const float RoachStamina = 25f; public const float PlatinumRoachStamina = 32f; public const float RubyRoachStamina = 40f; public const float MoonRocksDrain = 0.75f; public const float PillSeconds = 35f; public const float FloatSeconds = 5f; public const float CrashSpeed = 10f; public const float CrashBaseDamage = 0.5f; public const float CrashDamagePerSpeed = 0.2f; public const float FallDistance = 2f; public const float ChargeDamage = 3f; public const float ChargeStamina = 20f; public const float ChargeCooldown = 2.5f; public const float FeedStaminaRate = 30f; public const float FeedHealRate = 0.3f; public const float BloodPerDenizen = 70f; public const float ScoreMultiplierBonus = 0.35f; public const float BugViewSharpTo = 10f; public const float NearClip = 0.375f; public const float HearingNear = 4f; public const float HearingFar = 16f; public const float HearingCutoff = 1200f; public const float HearingResonance = 1.5f; } internal static class BloodbugContent { public const string PerkId = "Perk_Senkodev_BloodbugForm"; public const string LightBodyId = "Perk_Senkodev_BloodbugLightBody"; public const string WetWingsId = "Perk_Senkodev_BloodbugWetWings"; public const string WingInjuryId = "Perk_Senkodev_BloodbugWingInjury"; public const string BindingId = "Senkodev_Bloodbug"; public const string TrinketName = "Trinket_Senkodev_Bloodbug"; public const string DatabaseId = "senkodev-bloodbugmode"; public const string FormBuffId = "senkodev-bloodbugform"; private const string CardArtPerkId = "Perk_Binding_HalfInventory"; private static WKAssetDatabase database; public static Perk Perk { get; private set; } public static Sprite Icon { get; private set; } public static Sprite Pixel { get; private set; } public static Perk LightBody { get; private set; } public static Perk WetWings { get; private set; } public static Perk WingInjury { get; private set; } public static void RegisterBinding() { Create(); TrinketRegistry.RegisterBinding("Senkodev_Bloodbug", "Bloodbug Mode", Description(), "", 1, 0.35f, 0f, Icon, (Func<List<Item_Object>>)null, (Func<List<Perk>>)(() => new List<Perk> { Perk }), 0); TrinketRegistry.RegisterMutexHub("Senkodev_Bloodbug", new string[1] { "Binding_RoachMode" }); } public static void Register() { if (!((Object)(object)CL_AssetManager.baseDatabase == (Object)null)) { CL_AssetManager.AddNewDatabase("senkodev-bloodbugmode", database); if (GameAssets.Load()) { UseGameCardArt(); } } } private static string Description() { return "You were unfortunate enough to become a <color=red>Bloodbug</color>.\nFly on limited stamina, rest on walls and charge at denizens.\nEnable Half Inventory and Survival Mode for the full Bloodbug experience!"; } public static void ApplyBiteKey() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) string text = ((object)Plugin.BiteKey.Value/*cast due to .constrained prefix*/).ToString(); string text2 = (Plugin.AllowClimbing.Value ? "hammers, pitons, rebars or computers" : "hammers, pitons, rebars, handholds or computers"); Perk.description = "(+) You can fly and rest on walls and ceilings.\n(+) Press " + text + " to charge at a denizen, hold " + text + " to feed on it.\n(+) Bloodbugs leave you alone.\n(-) You are short-sighted, color blind and hard of hearing.\n(-) You are small, slow on foot and crashing into things hurts.\n(-) No using " + text2 + "."; ENT_Player playerObject = ENT_Player.playerObject; Perk val = (((Object)(object)playerObject != (Object)null) ? playerObject.GetPerk("Perk_Senkodev_BloodbugForm") : null); if ((Object)(object)val != (Object)null) { val.description = Perk.description; } } private static void Create() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0109: Expected O, but got Unknown Icon = ModFiles.LoadSprite("binding_icon.png", "Binding_Icon_Bloodbug"); Pixel = ModFiles.WhitePixel(); Perk = NewPerk("Perk_Senkodev_BloodbugForm", "Bloodbug Mode", (PerkType)9, Icon); ApplyBiteKey(); Perk.flavorText = "bzzzzzz"; Perk.tags = new List<string> { "binding" }; Perk.playerTag = new List<string> { "Senkodev_BloodbugKin" }; Perk.modules = new List<PerkModule> { (PerkModule)(object)new BloodbugModule() }; Perk.useBuff = true; Perk.buff = new BuffContainer { id = "senkodev-bloodbugform", desc = "", loseOverTime = false, loseRate = 0f, buffs = new List<Buff> { new Buff { id = "addPlayerScale", maxAmount = -0.6f } } }; LightBody = NewPerk("Perk_Senkodev_BloodbugLightBody", "Light Body", (PerkType)2, ModFiles.LoadSprite("debuff_light_body.png", "Debuff_Icon_LightBody")); WetWings = NewPerk("Perk_Senkodev_BloodbugWetWings", "Wet Wings", (PerkType)2, ModFiles.LoadSprite("debuff_wet_wings.png", "Debuff_Icon_WetWings")); WingInjury = NewPerk("Perk_Senkodev_BloodbugWingInjury", "Wing Injury", (PerkType)2, ModFiles.LoadSprite("debuff_wing_injury.png", "Debuff_Icon_WingInjury")); WingInjury.canStack = true; database = ModFiles.Keep<WKAssetDatabase>(ScriptableObject.CreateInstance<WKAssetDatabase>()); ((Object)database).name = "senkodev-bloodbugmode"; database.id = "senkodev-bloodbugmode"; database.perkAssets.AddRange((IEnumerable<Perk>)(object)new Perk[4] { Perk, LightBody, WetWings, WingInjury }); LightBody.description = "(-) You weigh next to nothing.\nBlows, blasts, fans and steam throw you " + Percent(0.6f) + "% further."; WetWings.description = "(-) Your wings are soaked.\nFlying costs " + Percent(1f) + "% more stamina until they dry out."; WingInjury.description = "(-) A hard crash has torn one of your wings.\nEach injury takes " + Percent(0.25f) + "% off your flight stamina until it heals."; WingInjury.stackMax = 3; } private static Perk NewPerk(string id, string title, PerkType type, Sprite icon) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown Perk obj = ModFiles.Keep<Perk>(ScriptableObject.CreateInstance<Perk>()); ((Object)obj).name = id; obj.id = id; obj.title = title; obj.description = ""; obj.flavorText = ""; obj.icon = icon; obj.perkType = type; obj.sortingCategory = -10; obj.spawnPool = (PerkPool)2; obj.spawnInEndless = false; obj.competitive = false; obj.removeOnCleanse = false; obj.canStack = false; obj.stackMax = 1; obj.multiplierCurve = AnimationCurve.Constant(0f, 1f, 1f); obj.useBuff = false; obj.buff = new BuffContainer { id = "", desc = "", buffs = new List<Buff>() }; obj.useBaseBuff = false; obj.baseBuff = new BuffContainer { id = "", desc = "", buffs = new List<Buff>() }; obj.tags = new List<string>(); obj.flags = new List<string>(); obj.playerTag = new List<string>(); obj.modules = new List<PerkModule>(); obj.unlockProgressionID = ""; return obj; } private static void UseGameCardArt() { Perk val = CL_AssetManager.GetBaseAssetDatabase().perkAssets.Find((Perk perk) => perk.id == "Perk_Binding_HalfInventory"); if (!((Object)(object)val == (Object)null)) { Perk[] array = (Perk[])(object)new Perk[4] { Perk, LightBody, WetWings, WingInjury }; foreach (Perk obj in array) { obj.perkCard = val.perkCard; obj.perkFrame = val.perkFrame; obj.iconMat = val.iconMat; } } } private static string Percent(float fraction) { return Mathf.RoundToInt(fraction * 100f).ToString(); } } internal static class BugHands { private const string Id = "senkodev-bloodbug-hands"; private const int CellSize = 128; private const int Columns = 10; private const string PointerPrefix = "interact-"; private static Cosmetic_HandItem cosmetic; private static bool failed; public static Cosmetic_HandItem Cosmetic { get { if ((Object)(object)cosmetic == (Object)null && !failed) { try { cosmetic = Build(); } catch (Exception arg) { Plugin.Log.LogError((object)$"failed to build the bug hands: {arg}"); } failed = (Object)(object)cosmetic == (Object)null; } return cosmetic; } } private static Cosmetic_HandItem Build() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_01f8: 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_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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_01a3: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown string[] array = Encoding.UTF8.GetString(ModFiles.Read("bug_hands.txt")).Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, ModFiles.Read("bug_hands.png")); Cosmetic_HandItem_Data val2 = new Cosmetic_HandItem_Data { id = "senkodev-bloodbug-hands", cosmeticName = "Bloodbug", author = "senkodev", description = "", unlock = "", globalMaterialBase = "", flags = new List<string>(), emotes = new List<HandEmote>(), palettes = new List<ColorPalette>(), allowedSpecialtyPoses = new List<string>(), globalSecondary = new List<SecondaryTextures>(), swapSprites = new List<SwapSprite>(), interactSwaps = new List<InteractSwap>() }; Dictionary<string, List<SwapSprite>> dictionary = new Dictionary<string, List<SwapSprite>>(); for (int i = 0; i < array.Length; i++) { string text = array[i]; int x = i % 10 * 128; int y = ((Texture)val).height - (i / 10 + 1) * 128; Sprite val3 = CutSprite(val, x, y, text); if (text.StartsWith("interact-")) { val2.interactSwaps.Add(new InteractSwap { spriteName = text, replacementSpriteName = text, replacementSprite = val3 }); continue; } SwapSprite item = new SwapSprite { spriteName = text, replacementSpriteNames = new List<string> { text }, replacementSprites = new List<Sprite> { val3 }, secondaryTextures = new List<SecondaryTextures>(), materialBase = "" }; val2.swapSprites.Add(item); dictionary[text] = new List<SwapSprite> { item }; } Object.Destroy((Object)(object)val); Cosmetic_HandItem obj = ModFiles.Keep<Cosmetic_HandItem>(ScriptableObject.CreateInstance<Cosmetic_HandItem>()); ((Object)obj).name = "Cosmetic_Hand_Senkodev_Bloodbug"; obj.cosmeticData = val2; ((Cosmetic_Base)obj).cosmeticInfo = new Cosmetic_Info { id = "senkodev-bloodbug-hands", cosmeticName = val2.cosmeticName, tag = "hand", author = val2.author, description = "", unlock = "", flags = val2.flags }; SetPrivate(obj, "materialDict", new Dictionary<string, Material>()); SetPrivate(obj, "hands", new Dictionary<int, HandMaterials>()); SetPrivate(obj, "swapDict", dictionary); SetPrivate(obj, "spriteNames", new Dictionary<Sprite, string>()); EnsureReturnList(); Plugin.Log.LogInfo((object)$"bug hands: {val2.swapSprites.Count} poses, {val2.interactSwaps.Count} pointers"); return obj; } private static Sprite CutSprite(Texture2D atlas, int x, int y, string name) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) Texture2D obj = ModFiles.Keep<Texture2D>(new Texture2D(128, 128, (TextureFormat)4, false)); ((Object)obj).name = "Bloodbug_" + name; obj.SetPixels(atlas.GetPixels(x, y, 128, 128)); ((Texture)obj).filterMode = (FilterMode)0; ((Texture)obj).wrapMode = (TextureWrapMode)1; obj.Apply(false, true); Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 0f, 128f, 128f); Sprite obj2 = ModFiles.Keep<Sprite>(Sprite.Create(obj, val, new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0)); ((Object)obj2).name = name; return obj2; } private static void EnsureReturnList() { FieldInfo fieldInfo = RequireField("returnSprites"); if (fieldInfo.GetValue(null) == null) { fieldInfo.SetValue(null, (IList)Activator.CreateInstance(fieldInfo.FieldType)); } } private static void SetPrivate(Cosmetic_HandItem target, string name, object value) { RequireField(name).SetValue(target, value); } private static FieldInfo RequireField(string name) { FieldInfo fieldInfo = AccessTools.Field(typeof(Cosmetic_HandItem), name); if (fieldInfo == null) { throw new MissingFieldException("Cosmetic_HandItem", name); } return fieldInfo; } } internal static class GameAssets { public const string MoonRocksId = "Perk_Trinket_MoonRock"; private const string BloodbugPrefabName = "Denizen_Bloodbug"; private const string HealedClipName = "player_injury_healed"; private const string LemonRoachName = "Denizen_Roach_Lemon"; private static readonly string[] HurtSets = new string[3] { "hurt", "hurt-falling", "hurt-heat" }; private static readonly string[] DeathSets = new string[1] { "death" }; private static readonly Dictionary<string, List<AudioClip>> sounds = new Dictionary<string, List<AudioClip>>(); private static AudioClip healedClip; private static int healedClipSearches; private static bool loaded; public static GameObject BloodbugPrefab { get; private set; } public static AudioClip BuzzClip { get; private set; } public static AudioClipHandlerOverride Voice { get; private set; } public static AudioClip RoachEatClip { get; private set; } public static float RoachEatVolume { get; private set; } = 1f; public static AudioClip HealedClip { get { if ((Object)(object)healedClip != (Object)null || healedClipSearches >= 3) { return healedClip; } healedClipSearches++; AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>(); foreach (AudioClip val in array) { if (((Object)val).name == "player_injury_healed") { healedClip = val; return val; } } Plugin.Log.LogWarning((object)"player_injury_healed isn't loaded"); return null; } } public static bool Load() { if (loaded) { return false; } loaded = true; BloodbugPrefab = FindBloodbugPrefab(CL_AssetManager.GetBaseAssetDatabase()); if ((Object)(object)BloodbugPrefab != (Object)null) { AudioSource component = BloodbugPrefab.GetComponent<AudioSource>(); BuzzClip = (((Object)(object)component != (Object)null) ? component.clip : null); Voice = CreateVoice(BloodbugPrefab.GetComponent<UT_AudioClipHandler>()); } GameObject assetGameObject = CL_AssetManager.GetAssetGameObject("Denizen_Roach_Lemon", ""); Item_Object val = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null); HandItem_Buff val2 = (HandItem_Buff)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 != (Object)null) { RoachEatClip = val2.audioClip; RoachEatVolume = val2.audioVolume; } Plugin.Log.LogInfo((object)("game assets: prefab=" + Name((Object)(object)BloodbugPrefab) + ", buzz=" + Name((Object)(object)BuzzClip) + ", " + $"voice={(((Object)(object)Voice != (Object)null) ? Voice.setOverrides.Count : 0)} sets, roach eating={Name((Object)(object)RoachEatClip)}")); return true; } public static AudioClip Sound(string set) { if (sounds.TryGetValue(set, out var value)) { return value[Random.Range(0, value.Count)]; } return null; } private static GameObject FindBloodbugPrefab(WKAssetDatabase game) { GameObject val = null; foreach (GameObject denizenPrefab in game.denizenPrefabs) { if (!((Object)(object)denizenPrefab == (Object)null) && ((Object)denizenPrefab).name.StartsWith("Denizen_Bloodbug") && !((Object)(object)denizenPrefab.GetComponentInChildren<Animator>(true) == (Object)null) && ((Object)(object)val == (Object)null || ((Object)denizenPrefab).name == "Denizen_Bloodbug")) { val = denizenPrefab; } } return val; } private static AudioClipHandlerOverride CreateVoice(UT_AudioClipHandler bloodbug) { if ((Object)(object)bloodbug == (Object)null) { return null; } foreach (AudioGroup group in bloodbug.groups) { foreach (AudioSet audioSet in group.audioSets) { if (audioSet.clips.Count > 0) { sounds[audioSet.name] = audioSet.clips; } } } sounds.TryGetValue("hurt", out var value); if (!sounds.TryGetValue("die", out var value2)) { sounds.TryGetValue("death", out value2); } AudioClipHandlerOverride val = ModFiles.Keep<AudioClipHandlerOverride>(ScriptableObject.CreateInstance<AudioClipHandlerOverride>()); ((Object)val).name = "Bloodbug_Voice"; val.setOverrides = new List<AudioSetOverride>(); AddOverrides(val, HurtSets, value); AddOverrides(val, DeathSets, value2); if (val.setOverrides.Count <= 0) { return null; } return val; } private static void AddOverrides(AudioClipHandlerOverride voice, string[] playerSets, List<AudioClip> clips) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0037: Expected O, but got Unknown if (clips != null) { foreach (string setName in playerSets) { voice.setOverrides.Add(new AudioSetOverride { groupName = "player", setName = setName, clips = clips }); } } } private static string Name(Object asset) { if (!(asset != (Object)null)) { return "none"; } return asset.name; } } internal static class ModFiles { private static readonly string Folder = Path.GetDirectoryName(typeof(ModFiles).Assembly.Location); public static byte[] Read(string fileName) { return File.ReadAllBytes(Path.Combine(Folder, fileName)); } public static Sprite LoadSprite(string fileName, string spriteName) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = ModFiles.Keep<Texture2D>(new Texture2D(2, 2, (TextureFormat)4, false)); ((Object)val).name = spriteName; ImageConversion.LoadImage(val, Read(fileName)); ((Texture)val).filterMode = (FilterMode)0; ((Texture)val).wrapMode = (TextureWrapMode)1; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height); Sprite obj = ModFiles.Keep<Sprite>(Sprite.Create(val, val2, new Vector2(0.5f, 0.5f), 100f)); ((Object)obj).name = spriteName; return obj; } public static Sprite WhitePixel() { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) Texture2D obj = ModFiles.Keep<Texture2D>(new Texture2D(1, 1, (TextureFormat)4, false)); ((Object)obj).name = "Bloodbug_Pixel"; obj.SetPixel(0, 0, Color.white); obj.Apply(); ((Texture)obj).filterMode = (FilterMode)0; return ModFiles.Keep<Sprite>(Sprite.Create(obj, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 1f)); } public static T Keep<T>(T asset) where T : Object { ((Object)asset).hideFlags = (HideFlags)32; return asset; } } internal class BodyOutline { private class Body { public Denizen denizen; public Renderer[] renderers; } private const float DepthPush = 0.06f; private const float Width = 2f; private const float MaxDistance = 25f; private static readonly Color EdibleColor = Color32.op_Implicit(new Color32((byte)193, (byte)48, (byte)48, byte.MaxValue)); private static readonly Color InReachColor = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)150, (byte)150, byte.MaxValue)); private static readonly Vector2[] Offsets = (Vector2[])(object)new Vector2[8] { new Vector2(1f, 0f), new Vector2(-1f, 0f), new Vector2(0f, 1f), new Vector2(0f, -1f), new Vector2(0.7f, 0.7f), new Vector2(-0.7f, 0.7f), new Vector2(0.7f, -0.7f), new Vector2(-0.7f, -0.7f) }; private static readonly List<Body> bodies = new List<Body>(); private readonly Camera camera; private readonly BloodbugController bug; private readonly CommandBuffer buffer; private readonly Material edible; private readonly Material inReach; private bool shown; private bool attached; public static int Count => bodies.Count; private BodyOutline(Camera camera, BloodbugController bug, Shader shader) { //IL_0016: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown this.camera = camera; this.bug = bug; edible = FlatMaterial(shader, EdibleColor); inReach = FlatMaterial(shader, InReachColor); buffer = new CommandBuffer { name = "Bloodbug prey outline" }; } public static BodyOutline Create(Camera camera, BloodbugController bug) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown Shader val = Shader.Find("Hidden/Internal-Colored"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"Hidden/Internal-Colored shader not found"); return null; } TrackDead(Object.FindObjectsByType<Denizen>((FindObjectsSortMode)0)); BodyOutline bodyOutline = new BodyOutline(camera, bug, val); Camera.onPreRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(bodyOutline.Draw)); return bodyOutline; } public static void Track(Denizen denizen) { if (!bodies.Exists((Body body) => (Object)(object)body.denizen == (Object)(object)denizen)) { bodies.Add(new Body { denizen = denizen }); } } public static void TrackDead(IEnumerable<Denizen> denizens) { foreach (Denizen denizen in denizens) { if (((GameEntity)denizen).dead) { Track(denizen); } } } public static void Forget() { bodies.Clear(); } public void Destroy() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(Draw)); Detach(); buffer.Release(); Object.Destroy((Object)(object)edible); Object.Destroy((Object)(object)inReach); } public void Show(bool wanted) { shown = wanted; if (!wanted) { Detach(); } } private void Draw(Camera rendering) { //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) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_0189: 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) if ((Object)(object)rendering != (Object)(object)camera || !shown) { return; } buffer.Clear(); Matrix4x4 worldToCameraMatrix = camera.worldToCameraMatrix; Matrix4x4 projectionMatrix = camera.projectionMatrix; Vector2 pixel = default(Vector2); ((Vector2)(ref pixel))..ctor(4f / (float)camera.pixelWidth, 4f / (float)camera.pixelHeight); Vector3 position = ((Component)camera).transform.position; bool flag = false; for (int num = bodies.Count - 1; num >= 0; num--) { Body body = bodies[num]; if ((Object)(object)body.denizen == (Object)null || bug.BloodLeft((GameEntity)(object)body.denizen) <= 0f) { bodies.RemoveAt(num); } else { float num2 = Vector3.Distance(((Component)body.denizen).transform.position, position); if (!(num2 > 25f) && ((Component)body.denizen).gameObject.activeInHierarchy) { if (body.renderers == null) { body.renderers = ((Component)body.denizen).GetComponentsInChildren<Renderer>(true); } bool flag2 = (Object)(object)body.denizen == (Object)(object)bug.Prey || num2 <= 1.6f; Renderer[] renderers = body.renderers; foreach (Renderer renderer in renderers) { if (CanDraw(renderer)) { DrawShifted(renderer, flag2 ? inReach : edible, worldToCameraMatrix, projectionMatrix, pixel); flag = true; } } } } } if (!flag) { Detach(); return; } buffer.SetViewProjectionMatrices(worldToCameraMatrix, projectionMatrix); if (!attached) { camera.AddCommandBuffer((CameraEvent)12, buffer); attached = true; } } private void DrawShifted(Renderer renderer, Material material, Matrix4x4 view, Matrix4x4 projection, Vector2 pixel) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = renderer.bounds; float num = Mathf.Max(Vector3.Dot(((Bounds)(ref bounds)).center - ((Component)camera).transform.position, ((Component)camera).transform.forward), camera.nearClipPlane * 2f); float depth = 0.12f * camera.nearClipPlane / (num * num); Vector2[] offsets = Offsets; foreach (Vector2 val in offsets) { buffer.SetViewProjectionMatrices(view, Shift(projection, val.x * pixel.x, val.y * pixel.y, depth)); for (int j = 0; j < renderer.sharedMaterials.Length; j++) { buffer.DrawRenderer(renderer, material, j); } } } private static bool CanDraw(Renderer renderer) { if ((Object)(object)renderer != (Object)null && renderer.enabled && ((Component)renderer).gameObject.activeInHierarchy) { if (!(renderer is SkinnedMeshRenderer)) { return renderer is MeshRenderer; } return true; } return false; } private void Detach() { if (attached && (Object)(object)camera != (Object)null) { camera.RemoveCommandBuffer((CameraEvent)12, buffer); } attached = false; } private static Matrix4x4 Shift(Matrix4x4 projection, float x, float y, float depth) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0030: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Vector4 row = ((Matrix4x4)(ref projection)).GetRow(3); ((Matrix4x4)(ref projection)).SetRow(0, ((Matrix4x4)(ref projection)).GetRow(0) + row * x); ((Matrix4x4)(ref projection)).SetRow(1, ((Matrix4x4)(ref projection)).GetRow(1) + row * y); ((Matrix4x4)(ref projection)).SetRow(2, ((Matrix4x4)(ref projection)).GetRow(2) + row * depth); return projection; } private static Material FlatMaterial(Shader shader, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown Material val = new Material(shader) { hideFlags = (HideFlags)61, color = color }; val.SetInt("_SrcBlend", 1); val.SetInt("_DstBlend", 0); val.SetInt("_Cull", 0); val.SetInt("_ZWrite", 0); val.SetInt("_ZTest", 4); return val; } } internal class FlightMeter { private const float Width = 190f; private const float Height = 24f; private const float IconSize = 24f; private const float BarHeight = 14f; private const float Border = 2f; private static readonly Color Backing = new Color(0f, 0f, 0f, 0.75f); private static readonly Color Flying = Color32.op_Implicit(new Color32((byte)193, (byte)48, (byte)48, byte.MaxValue)); private static readonly Color Recovering = Color32.op_Implicit(new Color32((byte)240, (byte)97, (byte)97, byte.MaxValue)); private static readonly Color Spent = Color32.op_Implicit(new Color32((byte)107, (byte)107, (byte)107, byte.MaxValue)); private static readonly Color Pilled = new Color(0f, 0.48f, 1f); private GameObject root; private RectTransform fill; private Image fillImage; private float punch; public static FlightMeter Create(Transform parent) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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) FlightMeter flightMeter = new FlightMeter(); flightMeter.root = NewElement("BloodbugFlightMeter", parent, out var rect); rect.sizeDelta = new Vector2(190f, 24f); RectTransform rect2; Image obj = NewImage("Icon", (Transform)(object)rect, BloodbugContent.Icon, Color.white, out rect2); RectTransform obj2 = rect2; RectTransform obj3 = rect2; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 0.5f); obj3.anchorMax = val; obj2.anchorMin = val; rect2.pivot = new Vector2(0f, 0.5f); rect2.anchoredPosition = Vector2.zero; rect2.sizeDelta = new Vector2(24f, 24f); obj.preserveAspect = true; NewImage("Backing", (Transform)(object)rect, BloodbugContent.Pixel, Backing, out var rect3); rect3.anchorMin = new Vector2(0f, 0.5f); rect3.anchorMax = new Vector2(1f, 0.5f); rect3.pivot = new Vector2(0.5f, 0.5f); rect3.offsetMin = new Vector2(30f, -7f); rect3.offsetMax = new Vector2(0f, 7f); flightMeter.fillImage = NewImage("Fill", (Transform)(object)rect3, BloodbugContent.Pixel, Flying, out flightMeter.fill); flightMeter.fill.anchorMin = Vector2.zero; flightMeter.fill.anchorMax = Vector2.one; flightMeter.fill.offsetMin = new Vector2(2f, 2f); flightMeter.fill.offsetMax = new Vector2(-2f, -2f); return flightMeter; } public void Set(float fraction, BloodbugController.FlightState state, bool tooLowToFly, bool onPills, bool feeding) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) fraction = Mathf.Clamp01(fraction); fill.anchorMax = new Vector2(fraction, 1f); fill.offsetMax = new Vector2(-2f * fraction, -2f); ((Graphic)fillImage).color = ColorFor(fraction, state, tooLowToFly, onPills, feeding); punch = Mathf.Lerp(punch, 0f, Time.unscaledDeltaTime * 8f); root.transform.localScale = Vector3.one * (1f + punch); } public void Punch() { punch = 0.25f; } public void SetVisible(bool visible) { root.SetActive(visible); } public void Destroy() { Object.Destroy((Object)(object)root); } private static Color ColorFor(float fraction, BloodbugController.FlightState state, bool tooLowToFly, bool onPills, bool feeding) { //IL_0003: 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_001c: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (onPills) { return Pulse(Pilled, 1.5f, 0.25f); } if (feeding) { return Pulse(Recovering, 3f, 0.4f); } if (tooLowToFly) { return Spent; } if (state != BloodbugController.FlightState.Flying) { return Recovering; } if (!(fraction < 0.25f)) { return Flying; } return Pulse(Flying, 4f, 0.6f); } private static Color Pulse(Color color, float rate, float amount) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) return Color.Lerp(color, Color.white, Mathf.PingPong(Time.unscaledTime * rate, 1f) * amount); } private static GameObject NewElement(string name, Transform parent, out RectTransform rect) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.layer = ((Component)parent).gameObject.layer; rect = (RectTransform)val.transform; ((Transform)rect).SetParent(parent, false); return val; } private static Image NewImage(string name, Transform parent, Sprite sprite, Color color, out RectTransform rect) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Image obj = NewElement(name, parent, out rect).AddComponent<Image>(); obj.sprite = sprite; ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } } internal class FlyCamera { private const string FinalCameraName = "FXCam"; private const int LensLayer = 31; private const int BlurLayer = 30; private const float Priority = 1000f; private const float MaxDistortion = 85f; private const float MaxDistortionScale = 1.25f; private const float MaxVignette = 0.3f; private const float MaxExtraView = 1.3f; private const float MaxFieldOfView = 150f; private const float FocalLength = 50f; private const float MinAperture = 0.7f; private const float MaxAperture = 12f; private static readonly Vector3 ProtanRed = new Vector3(56.7f, 43.3f, 0f); private static readonly Vector3 ProtanGreen = new Vector3(55.8f, 44.2f, 0f); private static readonly Vector3 ProtanBlue = new Vector3(0f, 24.2f, 75.8f); private readonly PostProcessLayer finalLayer; private readonly PostProcessLayer worldLayer; private readonly LayerMask finalMask; private readonly LayerMask worldMask; private readonly bool worldWasEnabled; private PostProcessVolume lensVolume; private PostProcessVolume blurVolume; private LensDistortion distortion; private ColorGrading grading; private Vignette vignette; private DepthOfField depthOfField; private bool shown; private FlyCamera(PostProcessLayer finalLayer, PostProcessLayer worldLayer) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0030: Unknown result type (might be due to invalid IL or missing references) this.finalLayer = finalLayer; this.worldLayer = worldLayer; finalMask = finalLayer.volumeLayer; if ((Object)(object)worldLayer != (Object)null) { worldMask = worldLayer.volumeLayer; worldWasEnabled = ((Behaviour)worldLayer).enabled; } } public static FlyCamera Create(ENT_Player player) { Camera val = FindFinalCamera(player); PostProcessLayer val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PostProcessLayer>() : null); if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).enabled) { Plugin.Log.LogWarning((object)"could not apply post-processing on the final camera"); return null; } PostProcessLayer val3 = null; if ((Object)(object)player.cam != (Object)(object)val) { val3 = ((Component)player.cam).GetComponent<PostProcessLayer>(); } if ((Object)(object)val3 == (Object)null) { Plugin.Log.LogWarning((object)"could not apply post-processing on the final camera"); } FlyCamera flyCamera = new FlyCamera(val2, val3); flyCamera.CreateVolumes(); Plugin.Log.LogInfo((object)("bug view: lens on " + ((Object)val).name + ", blur on " + (((Object)(object)val3 != (Object)null) ? ((Object)val3).name : "nothing"))); return flyCamera; } public void Show(bool wanted) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)lensVolume == (Object)null || (Object)(object)finalLayer == (Object)null) { return; } if (wanted) { ApplyConfig(); } if (wanted != shown) { shown = wanted; ((Behaviour)lensVolume).enabled = wanted; finalLayer.volumeLayer = (wanted ? LayerMask.op_Implicit(LayerMask.op_Implicit(finalMask) & -1073741825) : finalMask); if (!wanted) { SetBlur(on: false); } } } public float Widen(float fieldOfView) { float value = Plugin.BugViewFisheye.Value; if (!shown || value <= 0f) { return fieldOfView; } float num = MathF.PI / 180f * Mathf.Min(160f, 1.6f * Mathf.Max(value * 85f, 1f)); float num2 = 2f * Mathf.Tan(num * 0.5f); float num3 = Mathf.Lerp(1f, 1.25f, value); float num4 = 0.5f / num3; float num5 = Mathf.Tan(num4 * num) / (num4 * num2) / num3; num5 /= Mathf.Lerp(1f, 1.3f, value); return Mathf.Min(2f * Mathf.Atan(Mathf.Tan(fieldOfView * 0.5f * (MathF.PI / 180f)) / num5) * 57.29578f, 150f); } public void Destroy() { Show(wanted: false); if ((Object)(object)lensVolume != (Object)null) { RuntimeUtilities.DestroyVolume(lensVolume, true, true); lensVolume = null; } if ((Object)(object)blurVolume != (Object)null) { RuntimeUtilities.DestroyVolume(blurVolume, true, true); blurVolume = null; } } private static Camera FindFinalCamera(ENT_Player player) { Camera[] componentsInChildren = ((Component)((Component)player).transform.root).GetComponentsInChildren<Camera>(true); foreach (Camera val in componentsInChildren) { if (((Object)val).name == "FXCam" && (Object)(object)val.targetTexture == (Object)null) { return val; } } componentsInChildren = Camera.allCameras; foreach (Camera val2 in componentsInChildren) { if (((Object)val2).name == "FXCam" && (Object)(object)val2.targetTexture == (Object)null) { return val2; } } return null; } private void CreateVolumes() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) distortion = ScriptableObject.CreateInstance<LensDistortion>(); ((ParameterOverride<bool>)(object)((PostProcessEffectSettings)distortion).enabled).Override(true); grading = ScriptableObject.CreateInstance<ColorGrading>(); ((ParameterOverride<bool>)(object)((PostProcessEffectSettings)grading).enabled).Override(true); ((ParameterOverride<GradingMode>)(object)grading.gradingMode).Override((GradingMode)0); vignette = ScriptableObject.CreateInstance<Vignette>(); ((ParameterOverride<bool>)(object)((PostProcessEffectSettings)vignette).enabled).Override(true); ((ParameterOverride<VignetteMode>)(object)vignette.mode).Override((VignetteMode)0); ((ParameterOverride<Color>)(object)vignette.color).Override(Color.black); ((ParameterOverride<float>)(object)vignette.smoothness).Override(0.45f); ((ParameterOverride<float>)(object)vignette.roundness).Override(1f); lensVolume = PostProcessManager.instance.QuickVolume(31, 1000f, (PostProcessEffectSettings[])(object)new PostProcessEffectSettings[3] { (PostProcessEffectSettings)distortion, (PostProcessEffectSettings)grading, (PostProcessEffectSettings)vignette }); ((Object)lensVolume).name = "Bloodbug lens"; ((Behaviour)lensVolume).enabled = false; if (!((Object)(object)worldLayer == (Object)null)) { depthOfField = ScriptableObject.CreateInstance<DepthOfField>(); ((ParameterOverride<bool>)(object)((PostProcessEffectSettings)depthOfField).enabled).Override(true); ((ParameterOverride<float>)(object)depthOfField.focalLength).Override(50f); blurVolume = PostProcessManager.instance.QuickVolume(30, 1000f, (PostProcessEffectSettings[])(object)new PostProcessEffectSettings[1] { (PostProcessEffectSettings)depthOfField }); ((Object)blurVolume).name = "Bloodbug blur"; ((Behaviour)blurVolume).enabled = false; } } private void ApplyConfig() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) float value = Plugin.BugViewFisheye.Value; ((ParameterOverride<bool>)(object)((PostProcessEffectSettings)distortion).enabled).Override(value > 0f); ((ParameterOverride<float>)(object)distortion.intensity).Override(value * 85f); ((ParameterOverride<float>)(object)distortion.scale).Override(Mathf.Lerp(1f, 1.25f, value)); ((ParameterOverride<bool>)(object)((PostProcessEffectSettings)vignette).enabled).Override(value > 0f); ((ParameterOverride<float>)(object)vignette.intensity).Override(value * 0.3f); float value2 = Plugin.BugViewNoRed.Value; Vector3 val = Vector3.Lerp(new Vector3(100f, 0f, 0f), ProtanRed, value2); Vector3 val2 = Vector3.Lerp(new Vector3(0f, 100f, 0f), ProtanGreen, value2); Vector3 val3 = Vector3.Lerp(new Vector3(0f, 0f, 100f), ProtanBlue, value2); ((ParameterOverride<bool>)(object)((PostProcessEffectSettings)grading).enabled).Override(value2 > 0f); ((ParameterOverride<float>)(object)grading.mixerRedOutRedIn).Override(val.x); ((ParameterOverride<float>)(object)grading.mixerRedOutGreenIn).Override(val.y); ((ParameterOverride<float>)(object)grading.mixerRedOutBlueIn).Override(val.z); ((ParameterOverride<float>)(object)grading.mixerGreenOutRedIn).Override(val2.x); ((ParameterOverride<float>)(object)grading.mixerGreenOutGreenIn).Override(val2.y); ((ParameterOverride<float>)(object)grading.mixerGreenOutBlueIn).Override(val2.z); ((ParameterOverride<float>)(object)grading.mixerBlueOutRedIn).Override(val3.x); ((ParameterOverride<float>)(object)grading.mixerBlueOutGreenIn).Override(val3.y); ((ParameterOverride<float>)(object)grading.mixerBlueOutBlueIn).Override(val3.z); float value3 = Plugin.BugViewBlur.Value; SetBlur(value3 > 0f); if ((Object)(object)depthOfField != (Object)null && value3 > 0f) { ((ParameterOverride<float>)(object)depthOfField.focusDistance).Override(10f); ((ParameterOverride<float>)(object)depthOfField.aperture).Override(Mathf.Lerp(12f, 0.7f, value3)); ((ParameterOverride<KernelSize>)(object)depthOfField.kernelSize).Override((KernelSize)((value3 > 0.66f) ? 3 : ((!(value3 > 0.33f)) ? 1 : 2))); } } private void SetBlur(bool on) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)blurVolume == (Object)null) && !((Object)(object)worldLayer == (Object)null) && ((Behaviour)blurVolume).enabled != on) { ((Behaviour)blurVolume).enabled = on; worldLayer.volumeLayer = (on ? LayerMask.op_Implicit(1073741824) : worldMask); ((Behaviour)worldLayer).enabled = on || worldWasEnabled; } } } internal static class NearHearing { private struct Saved { public AudioSource source; public AudioRolloffMode mode; public float min; public float max; public AudioLowPassFilter muffle; } private const float OwnSoundRadius = 0.75f; private static readonly List<Saved> changed = new List<Saved>(); private static readonly Dictionary<AudioSource, AudioLowPassFilter> pooled = new Dictionary<AudioSource, AudioLowPassFilter>(); public static bool On { get; private set; } public static void Turn(bool on) { if (on != On) { On = on; if (on) { Adjust(Object.FindObjectsByType<AudioSource>((FindObjectsSortMode)0)); } else { Restore(); } } } public static void Pooled(AudioSource source) { if (!pooled.ContainsKey(source)) { pooled.Add(source, Muffle(source, on: false)); } } public static void Played(AudioSource source, Vector3 position, Transform from, float spatial) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && pooled.TryGetValue(source, out var value)) { ((Behaviour)value).enabled = On && spatial > 0f && !IsOwn(position, from); } } public static float Fade(Vector3 position) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Vector3 position2 = ((Component)ENT_Player.playerObject.cam).transform.position; return 1f - Mathf.InverseLerp(4f, 16f, Vector3.Distance(position, position2)); } public static bool IsOwn(Vector3 position, Transform from) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)ENT_Player.playerObject).transform; if ((Object)(object)from != (Object)null) { if (!((Object)(object)from == (Object)(object)transform)) { return from.IsChildOf(transform); } return true; } return Vector3.Distance(position, transform.position) < 0.75f; } public static void Adjust(IEnumerable<AudioSource> sources) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)ENT_Player.playerObject).transform; foreach (AudioSource source in sources) { if (!pooled.ContainsKey(source) && !(source.spatialBlend <= 0f) && !((Component)source).transform.IsChildOf(transform)) { changed.Add(new Saved { source = source, mode = source.rolloffMode, min = source.minDistance, max = source.maxDistance, muffle = Muffle(source, on: true) }); source.rolloffMode = (AudioRolloffMode)1; source.minDistance = Mathf.Min(source.minDistance, 4f); source.maxDistance = Mathf.Min(source.maxDistance, 16f); } } } private static AudioLowPassFilter Muffle(AudioSource source, bool on) { AudioLowPassFilter val = ((Component)source).GetComponent<AudioLowPassFilter>(); if ((Object)(object)val == (Object)null) { val = ((Component)source).gameObject.AddComponent<AudioLowPassFilter>(); } val.cutoffFrequency = 1200f; val.lowpassResonanceQ = 1.5f; ((Behaviour)val).enabled = on; return val; } public static void Forget() { changed.Clear(); pooled.Clear(); On = false; } private static void Restore() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) for (int num = changed.Count - 1; num >= 0; num--) { Saved saved = changed[num]; if (!((Object)(object)saved.source == (Object)null)) { saved.source.rolloffMode = saved.mode; saved.source.minDistance = saved.min; saved.source.maxDistance = saved.max; if ((Object)(object)saved.muffle != (Object)null) { ((Behaviour)saved.muffle).enabled = false; } } } changed.Clear(); foreach (AudioLowPassFilter value in pooled.Values) { if ((Object)(object)value != (Object)null) { ((Behaviour)value).enabled = false; } } } } [HarmonyPatch(typeof(DEN_BasicDenizen), "Start")] internal static class DenizenStartPatch { private static void Postfix(DEN_BasicDenizen __instance) { if (BloodbugKin.IsBloodbug((GameEntity)(object)__instance)) { BloodbugKin.IgnorePlayer(__instance.targetComponent); } if (NearHearing.On) { NearHearing.Adjust(((Component)__instance).GetComponentsInChildren<AudioSource>(true)); } } } [HarmonyPatch] internal static class DenizenDeathPatch { private static IEnumerable<MethodBase> TargetMethods() { Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(Denizen).Assembly); foreach (Type type in typesFromAssembly) { if (!typeof(Denizen).IsAssignableFrom(type)) { continue; } foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if ((declaredMethod.Name == "Damage" || (declaredMethod.Name == "Kill" && declaredMethod.GetParameters().Length == 2)) && !declaredMethod.IsAbstract && !declaredMethod.IsStatic) { yield return declaredMethod; } } } } private static void Postfix(Denizen __instance) { if (((GameEntity)__instance).dead && BloodbugController.Exists) { BodyOutline.Track(__instance); } } } [HarmonyPatch(typeof(DEN_Roach), "AI")] internal static class RoachCrushPatch { private static void Prefix(DEN_Roach __instance, out bool __state) { __state = __instance.canSquish && BloodbugController.IsBloodbug(ENT_Player.playerObject); if (__state) { __instance.canSquish = false; } } private static void Finalizer(DEN_Roach __instance, bool __state) { if (__state) { __instance.canSquish = true; } } } internal static class BloodbugKin { public const string Tag = "Senkodev_BloodbugKin"; public static bool IsBloodbug(GameEntity entity) { if (!((Object)entity).name.StartsWith("Denizen_Bloodbug", StringComparison.OrdinalIgnoreCase)) { if (entity.objectType != null) { return entity.objectType.IndexOf("bloodbug", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } return true; } public static void Provoke(GameEntity entity) { DEN_BasicDenizen val = (DEN_BasicDenizen)(object)((entity is DEN_BasicDenizen) ? entity : null); if (val != null && IsBloodbug((GameEntity)(object)val)) { List<string> list = new List<string>(val.targetComponent.targetIgnoreTags); if (list.Remove("Senkodev_BloodbugKin")) { val.targetComponent.targetIgnoreTags = list.ToArray(); } } } public static void IgnorePlayer(AITargetComponent targeting) { List<string> list = new List<string>(targeting.targetIgnoreTags); if (!list.Contains("Senkodev_BloodbugKin")) { list.Add("Senkodev_BloodbugKin"); targeting.targetIgnoreTags = list.ToArray(); } } } [HarmonyPatch] internal static class BlockedShotPatch { private static readonly string[] Methods = new string[3] { "Use", "StartShoot", "Shoot" }; private static IEnumerable<MethodBase> TargetMethods() { Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(HandItem_Shoot).Assembly); foreach (Type type in typesFromAssembly) { if (!typeof(HandItem_Shoot).IsAssignableFrom(type)) { continue; } string[] methods = Methods; foreach (string text in methods) { MethodInfo methodInfo = AccessTools.DeclaredMethod(type, text, Type.EmptyTypes, (Type[])null); if (methodInfo != null && !methodInfo.IsAbstract) { yield return methodInfo; } } } } private static bool Prefix(HandItem_Shoot __instance) { int num; if (BloodbugItems.IsRebar(((HandItem)__instance).item) || BloodbugItems.IsPiton(((HandItem)__instance).item)) { num = (BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer()) ? 1 : 0); if (num != 0) { BloodbugItems.Refuse((HandItem)(object)__instance); } } else { num = 0; } return num == 0; } } [HarmonyPatch(typeof(HandItem_Piton), "Use")] internal static class PitonUsePatch { private static bool Prefix(HandItem_Piton __instance) { bool num = BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer()); if (num) { BloodbugItems.Refuse((HandItem)(object)__instance); } return !num; } } [HarmonyPatch(typeof(HandItem_Piton), "PitonHit")] internal static class PitonHitPatch { private static bool Prefix(HandItem_Piton __instance) { return !BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer()); } } [HarmonyPatch(typeof(Inventory), "DropItemIntoWorld")] internal static class ItemDropPatch { private static void Prefix(Item item, out float? __state) { __state = null; if (BloodbugController.IsBloodbug(ENT_Player.playerObject)) { float scale = (BloodbugItems.IsRebar(item) ? 0f : 0.5f); __state = item.dropVel; item.dropVel = BloodbugItems.ScaledDropVel(item.dropVel, scale); } } private static void Finalizer(Item item, float? __state) { if (__state.HasValue) { item.dropVel = __state.Value; } } } [HarmonyPatch(typeof(HandItem_Shoot), "CreateProjectile")] internal static class ThrowStrengthPatch { private static void Prefix(HandItem_Shoot __instance, out float? __state) { __state = null; if (BloodbugItems.IsThrown(__instance) && BloodbugController.IsBloodbug(((Hand_Base)__instance).hand.GetPlayer())) { __state = __instance.shootSpeed; __instance.shootSpeed *= 0.5f; } } private static void Finalizer(HandItem_Shoot __instance, float? __state) { if (__state.HasValue) { __instance.shootSpeed = __state.Value; } } } [HarmonyPatch(typeof(Item_Object), "CanPickup")] internal static class HammerPickupPatch { private static void Postfix(Item_Object __instance, ref bool __result) { if (__result && __instance.itemData != null && BloodbugItems.IsBanned(__instance.itemData) && BloodbugController.IsBloodbug(ENT_Player.playerObject)) { __result = false; } } } [HarmonyPatch(typeof(Inventory), "AddItemToInventoryScreen")] internal static class HammerBagPatch { private static bool Prefix(Item item) { if (!BloodbugItems.IsHammer(item) || !BloodbugController.IsBloodbug(ENT_Player.playerObject)) { return true; } if (ConsoleSpawnPatch.Spawning) { BloodbugItems.Allow(item); return true; } item.ClearDropObject(); return false; } } [HarmonyPatch(typeof(CL_GameManager), "SpawnItem")] internal static class ConsoleSpawnPatch { internal static bool Spawning; private static void Prefix() { Spawning = true; } private static void Finalizer() { Spawning = false; } } [HarmonyPatch(typeof(HandItem_Melee), "Use")] internal static class HammerUsePatch { private static bool Prefix(HandItem_Melee __instance) { bool num = BloodbugItems.BlocksSwing(__instance); if (num) { BloodbugItems.Refuse((HandItem)(object)__instance); } return !num; } } [HarmonyPatch(typeof(HandItem_Melee), "StartUse")] internal static class HammerSwingPatch { private static bool Prefix(HandItem_Melee __instance) { return !BloodbugItems.BlocksSwing(__instance); } } [HarmonyPatch(typeof(HandItem_Melee), "Hit")] internal static class HammerHitPatch { private static bool Prefix(HandItem_Melee __instance) { return !BloodbugItems.BlocksSwing(__instance); } } [HarmonyPatch(typeof(HandItem), "Use")] internal static class RoachEatPatch { private static void Prefix(HandItem __instance) { if (__instance.used || !BloodbugItems.IsEdibleRoach(__instance)) { return; } ENT_Player player = ((Hand_Base)__instance).hand.GetPlayer(); if (!BloodbugController.IsBloodbug(player)) { return; } Animator val = (((Object)(object)__instance.anim != (Object)null) ? __instance.anim : ((Component)__instance).GetComponent<Animator>()); if (!((Object)(object)val == (Object)null)) { __instance.used = true; val.SetTrigger("Use"); if ((Object)(object)GameAssets.RoachEatClip != (Object)null) { AudioManager.PlaySound(GameAssets.RoachEatClip, ((Component)player).transform, GameAssets.RoachEatVolume, 1f, 0f, false, 1f, (AudioMixerGroup)null, ""); } } } } [HarmonyPatch(typeof(HandItem), "Activate")] internal static class RoachSwallowPatch { private static void Postfix(HandItem __instance) { if (__instance.used && BloodbugItems.IsEdibleRoach(__instance)) { BloodbugController.For(((Hand_Base)__instance).hand.GetPlayer())?.EatRoach(__instance.item); } } } [HarmonyPatch(typeof(HandItem_Buff), "Activate")] internal static class BuffItemActivatePatch { private static void Postfix(HandItem_Buff __instance) { ENT_Player localPlayer = CL_GameManager.gMan.localPlayer; BloodbugItems.MarkBuff(__instance, localPlayer); if (__instance.onEatType != "food") { BloodbugController.For(localPlayer)?.Eat(BloodbugItems.Meals(__instance)); } } } [HarmonyPatch(typeof(M_Gamemode), "Finish")] internal static class GamemodeFinishPatch { private static void Prefix(M_Gamemode __instance, out bool? __state) { __state = null; if (Leaderboards.IsBloodbugRun && !AlreadySkipsScoring(__instance)) { __state = WK_Leaderboard_Core.disableLeaderboards; WK_Leaderboard_Core.disableLeaderboards = true; Plugin.Log.LogInfo((object)"bloodbug run, not submitting to leaderboards"); } } private static void Postfix(M_Gamemode __instance, bool hasFinished, bool? __state) { //IL_0050: 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) if (__state.HasValue && hasFinished && __instance.winCredits > 0 && CL_GameManager.GetRoaches(true) < __instance.winCreditMaximum && !__instance.IsCompetitive()) { CL_ProgressionManager.ShowUnlockPopup(__instance.roachEndSprite, "WIN BONUS", $"{__instance.winCredits} Facility Credits Added", DarkMachineCrayons.gold * 0.5f, (AudioClip)null, false); CL_GameManager.AddRoaches(__instance.winCredits, true); } } private static void Finalizer(bool? __state) { if (__state.HasValue) { WK_Leaderboard_Core.disableLeaderboards = __state.Value; } } private static bool AlreadySkipsScoring(M_Gamemode gamemode) { if ((gamemode.allowCheatedScores || !CommandConsole.hasCheated) && (gamemode.allowCheatedScores || CL_GameManager.AreAchievementsAllowed()) && !WorldLoader.customSeed && CL_GameManager.gMan.allowScores) { return !gamemode.allowLeaderboardScoring; } return true; } } [HarmonyPatch(typeof(SteamManager), "UploadGamemodeResults")] internal static class SteamUploadPatch { private static bool Prefix() { return !Leaderboards.IsBloodbugRun; } } internal static class Leaderboards { private static bool flown; public static bool IsBloodbugRun { get { ENT_Player playerObject = ENT_Player.playerObject; if (!flown) { if ((Object)(object)playerObject != (Object)null) { return playerObject.HasPerk("Perk_Senkodev_BloodbugForm"); } return false; } return true; } } public static void MarkRun() { flown = true; } public static void NewRun() { flown = false; } } [HarmonyPatch(typeof(ENT_Player), "Start")] internal static class PlayerStartPatch { private static void Postfix() { Leaderboards.NewRun(); } } [HarmonyPatch(typeof(ENT_Player), "Movement")] internal static class PlayerMovementPatch { private static void Prefix(ENT_Player __instance) { BloodbugController.For(__instance)?.BeforeMovement(); } private static void Postfix(ENT_Player __instance) { BloodbugController.For(__instance)?.AfterMovement(); } } [HarmonyPatch(typeof(ENT_Player), "OnControllerColliderHit")] internal static class PlayerColliderHitPatch { private static void Prefix(ENT_Player __instance, ControllerColliderHit hit) { BloodbugController.For(__instance)?.OnSurfaceHit(hit); } } [HarmonyPatch(typeof(ENT_Player), "AddForce", new Type[] { typeof(Vector3), typeof(string) })] internal static class PlayerAddForcePatch { private static void Prefix(ENT_Player __instance, ref Vector3 v, string source) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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) v *= BloodbugController.KnockbackMultiplier(__instance, source); } } [HarmonyPatch(typeof(UT_ForceZone), "FixedUpdate")] internal static class ForceZonePatch { private static void Prefix() { BloodbugController.activeForceZones++; } private static void Finalizer() { BloodbugController.activeForceZones--; } } [HarmonyPatch(typeof(ENT_Player), "GetCurrentMaxFallDistance")] internal static class FallDistancePatch { private static void Postfix(ENT_Player __instance, ref float __result) { if (BloodbugController.IsBloodbug(__instance)) { __result *= 2f; } } } [HarmonyPatch(typeof(ENT_Player), "GrabPropUpdate")] internal static class PropCarryPatch { private static void Prefix(ENT_Player __instance, int hand, out (Rigidbody body, float mass) __state) { __state = default((Rigidbody, float)); CL_Prop grabTarget = __instance.hands[hand].grabTarget; if (!((Object)(object)grabTarget == (Object)null) && !grabTarget.stuck && !BloodbugItems.IsPlank(grabTarget) && BloodbugController.IsBloodbug(__instance)) { Rigidbody rigidbody = grabTarget.GetRigidbody(); __state = (body: rigidbody, mass: rigidbody.mass); rigidbody.mass /= 0.5f; } } private static void Finalizer((Rigidbody body, float mass) __state) { if ((Object)(object)__state.body != (Object)null) { __state.body.mass = __state.mass; } } } [HarmonyPatch(typeof(Cosmetic_HandItem), "SpriteSwap")] internal static class BugHandsPalettePatch { private static void Postfix(Cosmetic_HandItem __instance, GameObject root) { if ((Object)(object)__instance != (Object)(object)BugHands.Cosmetic) { return; } SpriteRenderer[] componentsInChildren = root.GetComponentsInChildren<SpriteRenderer>(); for (int i = 0; i < componentsInChildren.Length; i++) { Material sharedMaterial = ((Renderer)componentsInChildren[i]).sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasFloat("_PaletteBaseBlend")) { sharedMaterial.SetFloat("_PaletteBaseBlend", 0f); } } } } [HarmonyPatch(typeof(ENT_Player), "SetCameraFov")] internal static class CameraFovPatch { private static void Postfix(ENT_Player __instance) { BloodbugController bloodbugController = BloodbugController.For(__instance); if (!((Object)(object)bloodbugController == (Object)null)) { float fieldOfView = bloodbugController.WidenView(__instance.cam.fieldOfView); __instance.cam.fieldOfView = fieldOfView; __instance.inventoryCam.fieldOfView = fieldOfView; } } } [HarmonyPatch(typeof(AudioManager), "GetPooledAudioSource")] internal static class PooledSoundPatch { internal static AudioSource Last; private static void Postfix(AudioSource __result) { Last = __result; if ((Object)(object)__result != (Object)null) { NearHearing.Pooled(__result); } } } [HarmonyPatch(typeof(AudioManager), "PlaySound", new Type[] { typeof(AudioClip), typeof(Vector3), typeof(float), typeof(float), typeof(float), typeof(bool), typeof(float), typeof(AudioMixerGroup), typeof(string) })] internal static class SoundAtPlacePatch { private static void Prefix(Vector3 position, ref float volume, float spatial) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (NearHearing.On && spatial > 0f) { volume *= NearHearing.Fade(position); } } private static void Postfix(Vector3 position, float spatial) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) NearHearing.Played(PooledSoundPatch.Last, position, null, spatial); } } [HarmonyPatch(typeof(AudioManager), "PlaySound", new Type[] { typeof(AudioClip), typeof(Transform), typeof(float), typeof(float), typeof(float), typeof(bool), typeof(float), typeof(AudioMixerGroup), typeof(string) })] internal static class SoundOnThingPatch { private static void Prefix(Transform from, ref float volume, float spatial) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (NearHearing.On && spatial > 0f) { volume *= NearHearing.Fade(from.position); } } private static void Postfix(Transform from, float spatial) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) NearHearing.Played(PooledSoundPatch.Last, from.position, from, spatial); } } [HarmonyPatch(typeof(M_Level), "Awake")] internal static class LevelAwakePatch { private static void Postfix(M_Level __instance) { MotherKin.ScanLevel(__instance); if (BloodbugController.Exists) { BodyOutline.TrackDead(((Component)__instance).GetComponentsInChildren<Denizen>(true)); } if (NearHearing.On) { NearHearing.Adjust(((Component)__instance).GetComponentsInChildren<AudioSource>(true)); } } } [HarmonyPatch(typeof(SSM_PerkChecker), "Check")] internal static class MotherPerkCheckPatch { private static void Postfix(SSM_PerkChecker __instance, ref float __result) { if (MotherKin.IsMotherCheck(__instance) && MotherKin.AppliesTo(ENT_Player.GetPlayer())) { __result = __instance.trueValue; } } } [HarmonyPatch(typeof(Localization), "GetLine")] internal static class MotherLinePatch { private static void Postfix(string group, string key, ref string __result) { if (MotherKin.TryGetLine(group, key, out var line) && MotherKin.AppliesToRun) { __result = line; } } } [HarmonyPatch(typeof(CL_AchievementManager), "SetAchievementValue", new Type[] { typeof(string), typeof(bool) })] internal static class RoachAchievementPatch { private static bool Prefix(string name) { if (!(name != "ACH_ROACHMODE")) { return !MotherKin.AppliesToRun; } return true; } } [HarmonyPatch(typeof(UT_LocationDataCollector), "LogData")] internal static class EndingVisitPatch { private static void Prefix(UT_LocationDataCollector __instance, out bool __state) { __state = __instance.locationName == "roachending" && MotherKin.AppliesToRun; if (__state) { __instance.locationName = "senkodev-bloodbugending"; } } private static void Finalizer(UT_LocationDataCollector __instance, bool __state) { if (__state) { __instance.locationName = "roachending"; } } } [HarmonyPatch(typeof(UT_GameStateController), "SetGamemode")] internal static class EndingSetGamemodePatch { private static void Prefix(ref M_Gamemode gamemode) { if (MotherKin.IsGameRoachEnding(gamemode) && MotherKin.AppliesToRun) { gamemode = MotherKin.EndingFor(gamemode); } } } [HarmonyPatch(typeof(UT_GameStateController), "LoadGamemode")] internal static class EndingLoadGamemodePatch { private static void Prefix(ref M_Gamemode gm) { if (MotherKin.IsGameRoachEnding(gm) && MotherKin.AppliesToRun) { gm = MotherKin.EndingFor(gm); } } } [HarmonyPatch(typeof(CL_AssetManager), "InitializeAssetManager")] internal static class AssetManagerReadyPatch { private static void Postfix() { BloodbugContent.Register(); } } [HarmonyPatch(typeof(CL_Handhold), "CanInteract")] internal static class HandholdCanInteractPatch { private static void Postfix(CL_Handhold __instance, Interaction info, ref bool __result) { if (__result && BloodbugController.BlocksClimbing(info.player, __instance)) { __result = false; } } } [HarmonyPatch(typeof(Hand), "GrabHold")] internal static class HandGrabHoldPatch { private static bool Prefix(Hand __instance, Transform target) { return !BloodbugController.BlocksClimbing(__instance.GetPlayer(), ((Component)target).GetComponent<CL_Handhold>()); } } [HarmonyPatch(typeof(OS_Computer_Interface), "ActivateComputer")] internal static class ComputerUsePatch { private static bool Prefix() { return !BloodbugController.IsBloodbug(ENT_Player.playerObject); } } public class BloodbugController : MonoBehaviour { private enum Charge { None, WindingUp, Dashing } public enum FlightState { Inactive, Grounded, Flying, Perched, Falling, Resting } internal const float FeedReach = 1.6f; private const float ChargeWindup = 0.5f; private const float ChargeSpeed = 20f; private const float ChargeDuration = 0.45f; private const float ChargeKnockback = 3f; private const float FeedDamageRate = 0.5f; private const float StrikeReach = 0.6f; private const float StrikeRadius = 0.7f; private const float ReboundSpeed = 4f; private const float FeedTickSeconds = 0.5f; internal static Func<bool> BiteOverride; private static readonly Collider[] overlaps = (Collider[])(object)new Collider[48]; private static KeyCode lastCheckedKey = (KeyCode)0; private readonly Dictionary<int, float> bloodLeft = new Dictionary<int, float>(); private Charge charge; private float chargeTimer; private float chargeCooldown; private Vector3 dashDirection; private bool biteHeld; private bool bitePressed; private GameEntity prey; private float feedTick; private PerkModule_HungerMeter hunger; private static BloodbugController current; private ENT_Player player; private bool active; private bool leaving; private int surfaceMask; internal const string FoodEatType = "food"; private const float MaxInjuryLoss = 0.9f; private const float MinTakeoffStamina = 10f; private const float RecoverStamina = 25f; internal static int activeForceZones; private float wetTimer; private float injuryTimer; private Perk wetWings; private Perk injury; private Perk moonRocks; private const float SputterBelow = 0.2f; private const float BankSpeed = 6f; private const float BankAngle = 10f; private const float HealedVolume = 0.6f; private readonly HandCosmeticSwap bugHands = new HandCosmeticSwap(); private FlightMeter meter; private AudioSource buzz; private BodyOutline outline; private FlyCamera eye; private bool hasVoice; private bool outlineFailed; private bool eyeFailed; private float bank; private float climberNearClip; private const float AutoTakeoffDelay = 0.2f; private const float JumpTakeoffDelay = 0.04f; private const float HoverBrake = 2.5f; private const float AirRegen = 3f; private const float InjectorSpeedBonus = 0.5f; private bool jumpPressed; private float airborneTime; private float thrust; private bool touchedFloor; private Vector3 velocityBeforeMove; private Vector3 wobbleSeed; private const float CrashCooldown = 0.6f; private const float CrashStun = 0.4f; private const float CrashBounce = 0.4f; private const float CrashStaminaLoss = 15f; private float stunTimer; private float crashCooldown; private float pendingCrashDamage; private const float PerchIntent = 0.3f; private const float PerchReach = 0.5f; private const float PerchSkin = 0.05f; private const float PerchSettleSpeed = 1f; private const float PerchCooldown = 0.4f; private const float KnockOffSpeed = 5f; private const float CrawlSpeed = 0.75f; private const float PushOffSpeed = 4f; private float perchCooldown; private Vector3 perchNormal; private Transform perchSurface; private const float ClingGrip = 12f; private const float WaterEscapeSeconds = 0.6f; private const float RideDepth = 0.04f; private const float HeadUnderMargin = 0.05f; private const float SurfacingSpeed = 1.6f; private const float SinkingSpeed = 0.6f; private const float FloatStiffness = 5f; private const float FloatDamping = 8f; private const float BobHeight = 0.015f; private const float BobRate = 2.2f; private const float MaxSoak = 3f; private float soakedSeconds; private float waterEscape; public bool IsCharging => charge != Charge.None; public bool IsFeeding => (Object)(object)prey != (Object)null; internal GameEntity Prey => prey; public FlightState State { get; private set; } public static bool Exists => (Object)(object)current != (Object)null; public float Stamina { get; private set; } public bool OnPills { get; private set; } public float MaxStamina { get { float num = Mathf.Min(0.25f * (float)Injuries, 0.9f); return 75f * (1f - num); } } public int Injuries { get; private set; } public bool HasWetWings => wetTimer > 0f; public bool IsStunned => stunTimer > 0f; public Vector3 PerchNormal => perchNormal; public bool IsClinging { get; private set; } public bool IsAfloat { get; private set; } internal float BloodLeft(GameEntity entity) { if (entity is DEN_Drone || entity is DEN_Turret || entity is DEN_GantryTurret) { return 0f; } if (!bloodLeft.TryGetValue(((Object)entity).GetInstanceID(), out var value)) { return 70f; } return value; } internal unsafe static string GameBindingFor(KeyCode key) { //IL_0000: 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_005c: Unknown result type (might be due to invalid IL or missing references) if ((int)key == 0) { return null; } foreach (ControllerMap allMap in ReInput.players.GetPlayer(0).controllers.maps.GetAllMaps((ControllerType)0)) { foreach (ActionElementMap allMap2 in allMap.AllMaps) { InputAction action = ReInput.mapping.GetAction(allMap2.actionId); if (((object)allMap2.keyCode/*cast due to .constrained prefix*/).ToString() == ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString() && action != null && action.name != "Fly") { return action.name; } } } return null; } private void ReadBiteKey() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) bool flag = ((BiteOverride != null) ? BiteOverride() : Input.GetKey(Plugin.BiteKey.Value)) && !player.IsInputLocked(); if (flag && !biteHeld) { bitePressed = true; } biteHeld = flag; } private void WarnIfBiteKeyTaken() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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) //IL_004e: Unknown result type (might be due to invalid IL or missing references) KeyCode value = Plugin.BiteKey.Value; if (value != lastCheckedKey) { lastCheckedKey = value; string text = GameBindingFor(value); if (text != null) { Plugin.Log.LogWarning((object)$"bite key {value} is also the game's {text} key"); CL_UIManager.instance.highscoreHeader.ShowText($"Bloodbug bite key {value} is also the game's {text} key. Change BiteKey in the mod's config."); } } } private void UpdateBite(ref Vector3 vel, float dt) { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) chargeCooldown -= dt; bool flag = bitePressed; bitePressed = false; GameEntity previousPrey = prey; prey = null; if (IsStunned || State == FlightState.Resting) { EndCharge(0f); return; } if (PlayerAccess.Grappled(player)) { EndCharge(0f); if (flag) { Sting(); } return; } if (biteHeld && charge == Charge.None) { GameEntity val = FindPrey(); if ((Object)(object)val != (Object)null) { Feed(val, previousPrey, dt); return; } } switch (charge) { case Charge.None: { bool flag2 = OnPills || Stamina >= 20f; if (flag && State == FlightState.Flying && chargeCooldown <= 0f && flag2) { charge = Charge.WindingUp; chargeTimer = 0f; PlayBloodbugSound("attack-start", 0.5f); } break; } case Charge.WindingUp: chargeTimer += dt; if (State != FlightState.Flying) { EndCharge(0f); } else if (chargeTimer >= 0.5f) { charge = Charge.Dashing; chargeTimer = 0.45f; dashDirection = ((Component)player.cam).transform.forward; if (!OnPills) { Stamina = Mathf.Max(Stamina - 20f, 0f); } PlayBloodbugSound("attack-activate", 0.6f); } break; case Charge.Dashing: { chargeTimer -= dt; Damageable val2 = ((State == FlightState.Flying) ? FindChargeTarget() : null); if (val2 != null) { Strike(ref vel, val2); } else if (State != FlightState.Flying || chargeTimer <= 0f) { vel = Vector3.ClampMagnitude(vel, 8f / 175f); EndCharge(2.5f); } break; } } } private void Sting() { ((GameEntity)player).ClearGrapple(); chargeCooldown = 2.5f; PlayBloodbugSound("attack-activate", 0.6f); CL_CameraControl.Shake(0.05f); player.SplatterScreenBlood(1); } private void EndCharge(float cooldown) { if (charge != Charge.None) { charge = Charge.None; chargeCooldown = cooldown; } } private void Strike(ref Vector3 vel, Damageable target) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) DamageInfo val = DamageInfo.CreateDamageInfo(3f, (GameEntity)(object)player, "bloodbug"); val.position = player.GetControllerPosition(); val.direction = dashDirection; DamageInfo val2 = val; if (val2.tags == null) { val2.tags = new List<string>(); } GameEntity val3 = (GameEntity)(object)((target is GameEntity) ? target : null); if (val3 != null) { BloodbugKin.Provoke(val3); val3.AddForce((dashDirection + Vector3.up * 0.3f) * 3f, "denizen"); } target.Damage(val); vel = -dashDirection * (4f / 175f); crashCooldown = 0.6f; perchCooldown = 0.4f; PlayBloodbugSound("hurt-impact", 0.5f); CL_CameraControl.Shake(0.08f); player.SplatterScreenBlood(1); EndCharge(2.5f); } private void Feed(GameEntity target, GameEntity previousPrey, float dt) { float num = BloodLeft(target); if (num <= 0f) { return; } prey = target; if ((Object)(object)previousPrey != (Object)(object)target) { feedTick = 0f; PlayBloodbugSound("attack-start", 0.35f); player.SplatterScreenBlood(1); } float num2 = Mathf.Min(30f * dt, num); bloodLeft[((Object)target).GetInstanceID()] = num - num2; Stamina = Mathf.Min(Stamina + num2, MaxStamina); ((GameEntity)player).Heal(0.3f * dt); FillHunger(num2 / 70f); feedTick -= dt; if (!(feedTick > 0f)) { feedTick = 0.5f; CL_CameraControl.Shake(0.01f); if (!target.dead) { BloodbugKin.Provoke(target); target.Damage(DamageInfo.CreateDamageInfo(0.25f, (GameEntity)(object)player, "bloodbug")); } } } internal void EatRoach(Item roach) { float num = BloodbugItems.RoachStamina(roach); Stamina = Mathf.Min(Stamina + num, MaxStamina); FillHunger(num / 70f); } private void FillHunger(float share) { if (hunger != null) { hunger.hungerMeter = Mathf.Min(hunger.hungerMeter + share * hunger.hungerMax, hunger.hungerMax); } } private float HungerSpeed() { if (hunger == null) { return 1f; } float num = hunger.hungerMeter / hunger.hungerMax; return Mathf.Lerp(0.75f, 1f, num / 0.3f); } private PerkModule_HungerMeter FindHunger() { foreach (Perk perk in player.perks) { foreach (PerkModule module in perk.modules) { PerkModule_HungerMeter val = (PerkModule_HungerMeter)(object)((module is PerkModule_HungerMeter) ? module : null); if (val != null) { return val; } } } return null; } private GameEntity FindPrey() { //IL_0012: 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_0022: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)player.cam).transform; int num = Physics.OverlapSphereNonAlloc(transform.position + transform.forward * 0.8f, 1f, overlaps, -1, (QueryTriggerInteraction)2); GameEntity result = null; float num2 = float.MaxValue; for (int i = 0; i < num; i++) { GameEntity obj = EntityOf(overlaps[i]); Denizen val = (Denizen)(object)((obj is Denizen) ? obj : null); if (val != null) { Vector3 val2 = overlaps[i].ClosestPoint(transform.position) - transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num2) { result = (GameEntity)(object)val; num2 = sqrMagnitude; } } } return result; } private Damageable FindChargeTarget() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(player.GetControllerPosition() + dashDirection * 0.6f, 0.7f, overlaps, -1, (QueryTriggerInteraction)2); for (int i = 0; i < num; i++) { GameEntity val = EntityOf(overlaps[i]); if ((Object)(object)val != (Object)null && !val.dead && val.damageable) { return (Damageable)(object)val; } } for (int j = 0; j < num; j++) { UT_Damage componentInParent = ((Component)overlaps[j]).GetComponentInParent<UT_Damage>(); if ((Object)(object)componentInParent != (Object)null && componentInParent.canDamage && !((Component)componentInParent).transform.IsChildOf(((Component)player).transform)) { return (Damageable)(object)componentInParent; } } return null; } private GameEntity EntityOf(Collider collider) { GameEntity val = GameEntity.GetGameEntity(((Component)collider).gameObject); if ((Object)(object)val == (Object)null) { val = ((Component)collider).GetComponentInParent<GameEntity>(); } if (!((Object)(object)val == (Object)(object)player)) { return val; } return null; } public static BloodbugController For(ENT_Player player) { if (!((Object)(object)current != (Object)null) || !((Object)(object)current.player == (Object)(object)player)) { return null; } return current; } public static bool IsBloodbug(ENT_Player player) { BloodbugController bloodbugController = For(player); if ((Object)(object)bloodbugController != (Object)null) { return bloodbugController.active; } return false; } public static bool BlocksClimbing(ENT_Player player, CL_Handhold handhold) { if (IsBloodbug(player) && !Plugin.AllowClimbing.Value) { return !BloodbugItems.IsRemoteMarker((Component)(object)handhold); } return false; } internal void Leave() { leaving = true; } private void Awake() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) current = this; player = ((Component)this).GetComponent<ENT_Player>(); wobbleSeed = new Vector3(Random.Range(0f, 100f), Random.Range(0f, 100f), Random.Range(0f, 100f)); for (int i = 0; i < 32; i++) { if (i != ((Component)this).gameObject.layer && !Physics.GetIgnoreLayerCollision(((Component)this).gameObject.layer, i)) { surfaceMask |= 1 << i; } } } private void Update() { if (leaving) { if (active) { Deactivate(keepDebuffs: false); } else { RemoveDebuffs(); } Object.Destroy((Object)(object)this); return; } if (!((GameEntity)player).dead && !active) { Activate(); } else if (((GameEntity)player).dead && active) { Deactivate(keepDebuffs: true); } if (active) { if (InputManager.GetButton("Jump").Down) { jumpPressed = true;