using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.Json; using System.Text.Json.Serialization; using BepInEx; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using Nosebleed.Pancake.Achievements; using Nosebleed.Pancake.DungeonEnvironment; using Nosebleed.Pancake.GameCommands; using Nosebleed.Pancake.GameConfig; using Nosebleed.Pancake.GameConfig.Accessors; using Nosebleed.Pancake.GameConfig.ShopConfigs.Arcana; using Nosebleed.Pancake.GameLogic; using Nosebleed.Pancake.GameLogic.GameStates; using Nosebleed.Pancake.Models; using Nosebleed.Pancake.ProceduralGeneration; using Nosebleed.Pancake.RuntimeData; using Nosebleed.Pancake.View; using Nosebleed.Pancake.Weapons; using Nosebleed.Util; using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Tables; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("VampireMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("My first plugin")] [assembly: AssemblyTitle("VampireMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VampireMod { public class DataSender { private long LastUpdateTimestamp = 0L; public void SendUpdate(List floorCards, List gameCards, bool forceUpdate = false) { Plugin.Instance.Log.LogInfo((object)"Sending update to statsly"); if (forceUpdate || IsUpdateNeeded()) { object data = new { floorCards, gameCards }; var value = new { Event = "runUpdate", Data = data }; Plugin.Instance.LogToStatsly(JsonSerializer.Serialize(value)); } } private bool IsUpdateNeeded() { long num = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); long num2 = num - LastUpdateTimestamp; if (num2 > 5000) { LastUpdateTimestamp = num; return true; } return false; } } public static class Dicts { public static Dictionary CardDevNameToId = new Dictionary { ["Card_A_0_Bone"] = 0, ["Card_A_0_CherryBomb"] = 1, ["Card_A_0_Cross"] = 2, ["Card_A_0_Garlic"] = 3, ["Card_A_0_GorgeousMoon"] = 4, ["Card_A_0_Knife"] = 5, ["Card_A_0_Whip"] = 6, ["Card_A_1_FireWand"] = 7, ["Card_A_1_GattiAmari"] = 8, ["Card_A_1_KingBible"] = 9, ["Card_A_1_MagicWand"] = 10, ["Card_A_1_Runetracer"] = 11, ["Card_A_1_SoulEater"] = 12, ["Card_A_2_BloodyTear"] = 13, ["Card_A_2_Carrello"] = 14, ["Card_A_2_CelestialDusting"] = 15, ["Card_A_2_EightTheSparrow"] = 16, ["Card_A_2_HolyWand"] = 17, ["Card_A_2_LightningRing"] = 18, ["Card_A_2_UnholyVespers"] = 19, ["Card_A_2_ValkyrieTurner"] = 20, ["Card_A_2_ViciousHunger"] = 21, ["Card_A_3_Axe"] = 22, ["Card_A_3_DeathSpiral"] = 23, ["Card_A_3_HeavenSword"] = 24, ["Card_A_3_HellFire"] = 25, ["Card_A_3_NoFuture"] = 26, ["Card_A_3_SantaWater"] = 27, ["Card_A_3_ShadowPinion"] = 28, ["Card_A_3_ThousandEdge"] = 29, ["Card_A_4_LaBorra"] = 30, ["Card_A_4_Pentagram"] = 31, ["Card_A_4_PhieraDerTuphello"] = 32, ["Card_A_4_Phieraggi"] = 33, ["Card_A_4_Thunderloop"] = 34, ["Card_A_5_Peachone"] = 35, ["Card_A_5_Vandalier"] = 36, ["Card_A_6_EbonyWings"] = 37, ["Card_AngeloSpietato"] = 38, ["Card_B_0_EmptyTome"] = 39, ["Card_B_0_RawMana"] = 40, ["Card_B_1_EmptyTome"] = 41, ["Card_B_2_EmptyTome"] = 42, ["Card_B_3_EmptyTome"] = 43, ["Card_Confuse"] = 44, ["Card_CursedLancet"] = 45, ["Card_D_0_Armor"] = 46, ["Card_D_1_Armor"] = 47, ["Card_D_2_Armor"] = 48, ["Card_D_3_ClockLancet"] = 49, ["Card_E_BagOfCoins"] = 50, ["Card_E_CloverPetal"] = 51, ["Card_E_CoinPurse"] = 52, ["Card_E_LargeBagOfCoins"] = 53, ["Card_E_LittleClover"] = 54, ["Card_E_LittleHeart"] = 55, ["Card_E_Orologion"] = 56, ["Card_E_Rosary"] = 57, ["Card_E_Vacuum"] = 58, ["Card_M_0_Wings"] = 59, ["Card_M_3_SongOfMana"] = 60, ["Card_M_5_Mannajja"] = 61, ["Card_ManaBomb"] = 62, ["Card_Muddle"] = 63, ["Card_S_0_Candelabrador"] = 64, ["Card_S_0_SkullOManic"] = 65, ["Card_S_1_Attractorb"] = 66, ["Card_S_1_Candelabrador"] = 67, ["Card_S_1_Crown"] = 68, ["Card_S_1_Duplicator"] = 69, ["Card_S_1_HollowHeart"] = 70, ["Card_S_1_Pummarola"] = 71, ["Card_S_1_SpellBinder"] = 72, ["Card_S_1_Spinach"] = 73, ["Card_S_1_StoneMask"] = 74, ["Card_S_2_Bracer"] = 75, ["Card_S_2_Candelabrador"] = 76, ["Card_S_2_Clover"] = 77, ["Card_S_2_Crown"] = 78, ["Card_S_2_Duplicator"] = 79, ["Card_S_2_HollowHeart"] = 80, ["Card_S_2_Pummarola"] = 81, ["Card_S_2_Spinach"] = 82, ["Card_S_2_Tiramisu"] = 83, ["Card_Shatter"] = 84, ["Card_W_Bracelet"] = 85, ["Card_W_Combo"] = 86, ["Card_W_WildDefence"] = 87, ["FCC_Antonio"] = 88, ["FCC_Arca"] = 89, ["FCC_Cavallo"] = 90, ["FCC_Christine"] = 91, ["FCC_Clerici"] = 92, ["FCC_Concetta"] = 93, ["FCC_Divano"] = 94, ["FCC_Dommario"] = 95, ["FCC_Gallo"] = 96, ["FCC_Gennaro"] = 97, ["FCC_Giovanna"] = 98, ["FCC_Imelda"] = 99, ["FCC_Krochi"] = 100, ["FCC_Lama"] = 101, ["FCC_MissingNo"] = 102, ["FCC_Mortaccio"] = 103, ["FCC_OSole"] = 104, ["FCC_Pasqualina"] = 105, ["FCC_Poe"] = 106, ["FCC_Poppea"] = 107, ["FCC_Porta"] = 108, ["FCC_Pugnala"] = 109, ["FCC_Ramba"] = 110 }; public static Dictionary ArcanaDevNameToId = new Dictionary { ["ArcanaConfig_AndAnother"] = 0, ["ArcanaConfig_ChainLink"] = 1, ["ArcanaConfig_ExperimentalMedicine"] = 2, ["ArcanaConfig_JestersHat"] = 3, ["ArcanaConfig_MakeAScene"] = 4, ["ArcanaConfig_ManaSyphon"] = 5, ["ArcanaConfig_OverTheTop"] = 6, ["ArcanaConfig_SharpMind"] = 7, ["ArcanaConfig_ShieldBash"] = 8, ["ArcanaConfig_SwollenFist"] = 9, ["ArcanaConfig_WildStrength"] = 10, ["ArcanaConfig_YourShield"] = 11 }; public static Dictionary DungeonDevNameToId = new Dictionary { ["Dungeon_CappellaMagna_01"] = 0, ["Dungeon_CappellaMagna_02"] = 1, ["Dungeon_DairyPlant_01"] = 2, ["Dungeon_DairyPlant_02"] = 3, ["Dungeon_DairyPlant_03"] = 4, ["Dungeon_GalloTower_01"] = 5, ["Dungeon_InlaidLibrary_01"] = 6, ["Dungeon_InlaidLibrary_02"] = 7, ["Dungeon_InlaidLibrary_03"] = 8, ["Dungeon_Madforest_01"] = 9, ["Dungeon_Madforest_02"] = 10, ["Dungeon_Madforest_03"] = 11, ["Dungeon_TinyBridge_01"] = 12, ["Dungeon_TinyBridge_02"] = 13, ["Dungeon_TinyBridge_03"] = 14, ["Dungeon_Tutorial"] = 15 }; public static Dictionary EnemyDevNameToId = new Dictionary { ["EnemyConfig_1000Health_Test"] = 0, ["EnemyConfig_1HealthBoss_Test"] = 1, ["EnemyConfig_AmbushMantisElite"] = 2, ["EnemyConfig_ApprenticeWitch"] = 3, ["EnemyConfig_ArchDemon"] = 4, ["EnemyConfig_ArchDemonElite"] = 5, ["EnemyConfig_ArchonOro"] = 6, ["EnemyConfig_ArchonSpada"] = 7, ["EnemyConfig_ArconAscia"] = 8, ["EnemyConfig_Bat"] = 9, ["EnemyConfig_Bat_COWARD"] = 10, ["EnemyConfig_Bat_Elite"] = 11, ["EnemyConfig_Bat_Glowing"] = 12, ["EnemyConfig_Bat_Glowing-T2"] = 13, ["EnemyConfig_Bat_Glowing-T3"] = 14, ["EnemyConfig_Bat_Glowing-T4"] = 15, ["EnemyConfig_Bat_Tutorial00"] = 16, ["EnemyConfig_Bat_Tutorial01"] = 17, ["EnemyConfig_Bat_Tutorial01_NoXP"] = 18, ["EnemyConfig_Bat_Tutorial02"] = 19, ["EnemyConfig_Bat_Tutorial03"] = 20, ["EnemyConfig_Bat_Tutorial03_FullXP"] = 21, ["EnemyConfig_Bat_Tutorial04"] = 22, ["EnemyConfig_Bat_Tutorial05"] = 23, ["EnemyConfig_Bat_Tutorial06"] = 24, ["EnemyConfig_Bat_Weak"] = 25, ["EnemyConfig_BeastDemon"] = 26, ["EnemyConfig_BeastDemonElite"] = 27, ["EnemyConfig_BeastDemonElite_Ambush"] = 28, ["EnemyConfig_Brazier_Weak"] = 29, ["EnemyConfig_BridgeGuardian"] = 30, ["EnemyConfig_CollosalFlameElite"] = 31, ["EnemyConfig_DevilElite"] = 32, ["EnemyConfig_Dragonshrimp"] = 33, ["EnemyConfig_Drowner"] = 34, ["EnemyConfig_Durga"] = 35, ["EnemyConfig_Ecto"] = 36, ["EnemyConfig_EctoElite"] = 37, ["EnemyConfig_EnderEliteP1"] = 38, ["EnemyConfig_EnderEliteP2"] = 39, ["EnemyConfig_EyeBallElite"] = 40, ["EnemyConfig_EyeBallElite_Ambush"] = 41, ["EnemyConfig_FallenAngel"] = 42, ["EnemyConfig_FallenAngelElite"] = 43, ["EnemyConfig_FallenArchangel"] = 44, ["EnemyConfig_FallenThrone"] = 45, ["EnemyConfig_FishmanElite"] = 46, ["EnemyConfig_FlowerWall"] = 47, ["EnemyConfig_FlowerWallThorny"] = 48, ["EnemyConfig_GalloElite"] = 49, ["EnemyConfig_Gallotrice"] = 50, ["EnemyConfig_GallotriceElite"] = 51, ["EnemyConfig_Ghiavolo"] = 52, ["EnemyConfig_Ghost"] = 53, ["EnemyConfig_GhostElite"] = 54, ["EnemyConfig_GhostElite_Ambush"] = 55, ["EnemyConfig_Ghoul"] = 56, ["EnemyConfig_GiantArmouredKnightElite"] = 57, ["EnemyConfig_GiantArmouredKnightElite_Ambush"] = 58, ["EnemyConfig_GiantBat"] = 59, ["EnemyConfig_GiantCrabElite"] = 60, ["EnemyConfig_GiantCrabElite_Ambush"] = 61, ["EnemyConfig_GiantMummy"] = 62, ["EnemyConfig_GiantMummy_Elite"] = 63, ["EnemyConfig_GiantSkulloneElite"] = 64, ["EnemyConfig_GiantSkulloneElite_Ambush"] = 65, ["EnemyConfig_GlowingBat_Elite"] = 66, ["EnemyConfig_GlowingBat_Elite-Mid"] = 67, ["EnemyConfig_GlowingBat_Elite-T3"] = 68, ["EnemyConfig_GlowingBat_Elite-T4"] = 69, ["EnemyConfig_Golem"] = 70, ["EnemyConfig_GolemElite"] = 71, ["EnemyConfig_GreenKnight"] = 72, ["EnemyConfig_GreenKnightElite"] = 73, ["EnemyConfig_Guardian1"] = 74, ["EnemyConfig_Guardian2"] = 75, ["EnemyConfig_Guardian3"] = 76, ["EnemyConfig_Guardian4"] = 77, ["EnemyConfig_Guardian5"] = 78, ["EnemyConfig_HagElite"] = 79, ["EnemyConfig_HarpyElite"] = 80, ["EnemyConfig_Harpy_Weak"] = 81, ["EnemyConfig_Impefinger"] = 82, ["EnemyConfig_Kali"] = 83, ["EnemyConfig_LionHead"] = 84, ["EnemyConfig_LionHeadElite"] = 85, ["EnemyConfig_LizardElite"] = 86, ["EnemyConfig_LizardPawn"] = 87, ["EnemyConfig_LostTwinElite"] = 88, ["EnemyConfig_ManitcoreElite"] = 89, ["EnemyConfig_MantisElite"] = 90, ["EnemyConfig_MasterWitchElite"] = 91, ["EnemyConfig_Merman"] = 92, ["EnemyConfig_MermanElite_Ambush"] = 93, ["EnemyConfig_MilkElemental"] = 94, ["EnemyConfig_MilkElementalElite"] = 95, ["EnemyConfig_Minotaur"] = 96, ["EnemyConfig_MinotaurElite"] = 97, ["EnemyConfig_MinotaurElite_Ambush"] = 98, ["EnemyConfig_MoonAtlantean"] = 99, ["EnemyConfig_MudMan"] = 100, ["EnemyConfig_MudMan_Weak"] = 101, ["EnemyConfig_MudmanElite"] = 102, ["EnemyConfig_NesuferitElite"] = 103, ["EnemyConfig_QueenMedusaElite"] = 104, ["EnemyConfig_QueenMedusaElite_Ambush"] = 105, ["EnemyConfig_Raiju"] = 106, ["EnemyConfig_RedDeath"] = 107, ["EnemyConfig_Scarleton"] = 108, ["EnemyConfig_ShadeBomb"] = 109, ["EnemyConfig_Skeleton2"] = 110, ["EnemyConfig_Skeleton3"] = 111, ["EnemyConfig_Skeleton3_Elite"] = 112, ["EnemyConfig_Skullino"] = 113, ["EnemyConfig_SneakyHead"] = 114, ["EnemyConfig_Succubus"] = 115, ["EnemyConfig_SuccubusElite"] = 116, ["EnemyConfig_SunAtlantean"] = 117, ["EnemyConfig_SwordRussel"] = 118, ["EnemyConfig_SwordiLee"] = 119, ["EnemyConfig_Swordian"] = 120, ["EnemyConfig_TestArmorAction"] = 121, ["EnemyConfig_TestDamageAction"] = 122, ["EnemyConfig_TestDebuffEnemy"] = 123, ["EnemyConfig_TestKnockbackResist"] = 124, ["EnemyConfig_TraineeRedReaper"] = 125, ["EnemyConfig_TreasureBat_Elite"] = 126, ["EnemyConfig_Trickster"] = 127, ["EnemyConfig_TrinacriaElite"] = 128, ["EnemyConfig_TritontElite"] = 129, ["EnemyConfig_TwinDemon"] = 130, ["EnemyConfig_Venus"] = 131, ["EnemyConfig_Werewolf"] = 132, ["EnemyConfig_WerewolfElite"] = 133, ["EnemyConfig_Werewolf_Weak"] = 134, ["EnemyConfig_Zombie"] = 135, ["EnemyConfig_Zombie_Elite"] = 136, ["EnemyConfig_Zombie_Test"] = 137, ["EnemyConfig_Zombie_Test_NoXP"] = 138, ["EnemyConfig_Zombie_Weak"] = 139 }; public static int GetOrCreateId(string value, Dictionary knownValues) { if (knownValues.TryGetValue(value, out var value2)) { return value2; } int num = -2128831035; foreach (char c in value) { num = (num ^ c) * 16777619; } return Math.Abs(num); } } public class FloorTransitionStatePatch { [HarmonyPatch(typeof(FloorTransitionState), "OnDungeonGenerated")] public static class OnDungeonGenerated { public static void Prefix(FloorTransitionState __instance, TiledMapData _) { Plugin.Instance.rm.OnFloorLoaded(_); } } } public class RunStartStatePatch { [HarmonyPatch(typeof(RunStartState), "OnDungeonLoaded")] public static class OnDungeonLoaded { public static void Prefix(TiledMapData _) { Plugin.Instance.rm.ClearCurrentRunFile(); Plugin.Instance.rm.OnFloorLoaded(_); } } } public class DungeonModelPatch { [HarmonyPatch(typeof(DestructibleBehaviour), "SetDestroyed")] public static class SetDestroyed { public static void Prefix(DestructibleBehaviour __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) ManualLogSource log = Plugin.Instance.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("SetDestroyed "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(__instance.Type); } log.LogInfo(val); Plugin.Instance.rm.AddDestructible(__instance.Type); } } } public class Dungeon3DMapModelPatch { [HarmonyPatch(typeof(Dungeon3DMapModel), "OnDungeonLoaded")] public static class OnDungeonLoaded { public static void Prefix(Dungeon3DMapModel __instance, DungeonConfig dungeonConfig) { TiledMapData mapData = __instance.MapData; Plugin.Instance.rm.OnFloorLoaded(mapData); Plugin.Instance.rm.TryLoadCurrentRun(); } } } public class GameModelPatch { [HarmonyPatch(typeof(GameModel), "OnDungeonComplete")] public static class OnDungeonComplete { public static void Postfix(GameModel __instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown ManualLogSource log = Plugin.Instance.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(17, 0, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Dungeon Completed"); } log.LogInfo(val); double currentTimeInRun = __instance.CurrentTimeInRun; int difficultyRating = __instance.Dungeon.DungeonConfig.DifficultyRating; int playerLevel = __instance.PlayerModel.PlayerLevel; List activeArcanas = Globals.PlayerRunSettings._activeArcanas; List list = new List(); Enumerator enumerator = activeArcanas.GetEnumerator(); while (enumerator.MoveNext()) { ArcanaConfig current = enumerator.Current; ManualLogSource log2 = Plugin.Instance.Log; val = new BepInExInfoLogInterpolatedStringHandler(7, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("arcana "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((LocalizedReference)current.LocalizedName).TableReference); } log2.LogInfo(val); list.Add(Dicts.GetOrCreateId(current.AssetId, Dicts.ArcanaDevNameToId)); } Plugin.Instance.rm.RunEnded(isCompleted: true, currentTimeInRun, difficultyRating, playerLevel, list); } } [HarmonyPatch(typeof(GameModel), "OnGameOver")] public static class OnGameOver { public static void Postfix(GameModel __instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown ManualLogSource log = Plugin.Instance.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(14, 0, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Dungeon failed"); } log.LogInfo(val); double currentTimeInRun = __instance.CurrentTimeInRun; int difficultyRating = __instance.Dungeon.DungeonConfig.DifficultyRating; int playerLevel = __instance.PlayerModel.PlayerLevel; List activeArcanas = Globals.PlayerRunSettings._activeArcanas; List list = new List(); Enumerator enumerator = activeArcanas.GetEnumerator(); while (enumerator.MoveNext()) { ArcanaConfig current = enumerator.Current; list.Add(Dicts.GetOrCreateId(current.AssetId, Dicts.ArcanaDevNameToId)); } Plugin.Instance.rm.RunEnded(isCompleted: false, __instance.CurrentTimeInRun, difficultyRating, playerLevel, list); int num = SingletonMonoBehaviour.Instance.NumberOfVisibleAchievementsUnlocked(); int num2 = SingletonMonoBehaviour.Instance.NumberOfVisibleAchievements(true); ManualLogSource log2 = Plugin.Instance.Log; val = new BepInExInfoLogInterpolatedStringHandler(17, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Achievements: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" / "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num2); } log2.LogInfo(val); } } } public class DamageEffectPatch { [HarmonyPatch(typeof(DamageEffect), "ApplyDamage", new Type[] { typeof(PlayerModel), typeof(CardModel), typeof(CardConfig), typeof(IEncounterModel), typeof(StatSnapshot), typeof(List), typeof(List), typeof(List), typeof(List), typeof(CritEffectType), typeof(Il2CppReferenceArray), typeof(bool) })] public static class ApplyDamage { public static void Postfix(PlayerModel playerModel, CardModel cardModel, CardConfig cardConfig, IEncounterModel encounterModel, StatSnapshot playerStats, List enemyModels, List enemyDamages, List enemiesPiercedPerAmount, List areaHitCounts, CritEffectType critEffectType, Il2CppReferenceArray criticalEffects, bool isInCombo) { //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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) int orCreateId = Dicts.GetOrCreateId(cardConfig.AssetId, Dicts.CardDevNameToId); double num = 0.0; Enumerator enumerator = enemyDamages.GetEnumerator(); while (enumerator.MoveNext()) { EnemyDamageInfo current = enumerator.Current; num += current.healthDamage + current.armorDamage; } Plugin.Instance.rm.PlayerDealDamages(orCreateId, num); } } } public class CardModelPatch { [HarmonyPatch(typeof(CardModel), "OnPlayCard")] public static class OnPlayCard { public static void Postfix(CardModel __instance, PlayerModel playerModel, StatSnapshot playerStats, bool wasTriggeredByCardEffect, bool useCommandQueue, bool isCardInCombo) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown string assetId = __instance.CardConfig.AssetId; int orCreateId = Dicts.GetOrCreateId(assetId, Dicts.CardDevNameToId); bool flag = playerModel.ComboMultiplier - Plugin.Instance.rm.PreviousComboCount >= 0; ManualLogSource log = Plugin.Instance.Log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(8, 4, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("card "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(orCreateId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(isCardInCombo); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(flag); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(playerModel.ComboMultiplier); } log.LogInfo(val); Plugin.Instance.rm.CardPlayed(orCreateId, flag, playerModel.ComboMultiplier); Plugin.Instance.rm.PreviousComboCount = playerModel.ComboMultiplier; } } [HarmonyPatch(typeof(CardModel), "TryAddGemToEmptySlot")] public static class TryAddGemToEmptySlot { public static void Postfix(CardModel __instance, ref bool __result, GemConfig gemConfig) { if (__result) { Plugin.Instance.Log.LogInfo((object)"GEM INSERTED"); Plugin.Instance.rm.OnGemInserted(); } } } } public class BreakableCardPatch { [HarmonyPatch(typeof(BreakableCard), "SetCrackState")] public static class SetCrackState { public static void Postfix(CardCrackState crackState) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Plugin.Instance.rm.CardCracked(crackState); } } } public class Dungeon3DMapViewPatch { [HarmonyPatch(typeof(Dungeon3DMapView), "MoveToMapCoords")] public static class MoveToMapCoords { public static void Postfix(Vector2Int fromCoords, Vector2Int toCoords, TileExitDirections fromDir) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Plugin.Instance.rm.TileVisited(toCoords); } } } public class PlayerModelPatch { [HarmonyPatch(typeof(PlayerModel), "ResolveDamage")] public static class ResolveDamage { public static void Prefix(PlayerModel __instance, int amount) { if (amount <= 160) { float value = __instance._playerStats.Armor.Value; int num = (int)Math.Max(0f, (float)amount - value); int armored = amount - num; Plugin.Instance.rm.EnemyDamagesHit(num, armored); } } } [HarmonyPatch(typeof(PlayerModel), "OnStartTurn")] public static class OnStartTurn { public static void Prefix() { Plugin.Instance.rm.PreviousComboCount = 0; Plugin.Instance.rm.OnPlayerTurnEnded(); } } [HarmonyPatch(typeof(PlayerModel), "OnPlayerDeath")] public static class OnPlayerDeath { public static void Prefix() { Plugin.Instance.rm.TryAddTimelineEvent(0); } } } public class EnemyModelPatch { [HarmonyPatch(typeof(EnemyModel), "OnDied")] public static class OnDied { public static void Prefix(EnemyModel __instance, CardModel cardThatKilled) { int orCreateId = Dicts.GetOrCreateId(cardThatKilled.CardConfig.AssetId, Dicts.CardDevNameToId); int orCreateId2 = Dicts.GetOrCreateId(__instance.EnemyConfig.AssetId, Dicts.EnemyDevNameToId); Plugin.Instance.rm.MonsterKilled(orCreateId, orCreateId2); } } [HarmonyPatch(typeof(EnemyModel), "ResolveDamage")] public static class ResolveDamage { public static void Postfix(EnemyModel __instance, ref DamageResult __result, double damage) { string assetId = __instance.EnemyConfig.AssetId; int orCreateId = Dicts.GetOrCreateId(assetId, Dicts.EnemyDevNameToId); Plugin.Instance.rm.MonsterReceivesDamages(orCreateId, __result.ArmorDamage + __result.HealthDamage, __result.OverkillDamage); } } } public class EnemyEncounterModelPatch { [HarmonyPatch(typeof(EnemyEncounterModel), "OnEncounterDefeated")] public static class OnEncounterDefeated { public static void Prefix() { Plugin.Instance.rm.OnEncounterDefeated(); Plugin.Instance.rm.OnPlayerTurnEnded(); } } [HarmonyPatch(typeof(EnemyEncounterModel), "PopulateEnemies")] public static class PopulateEnemies { public static void Prefix() { Plugin.Instance.rm.TryAddTimelineEvent(1); } } } [BepInPlugin("VampireMod", "My first plugin", "1.0.0")] public class Plugin : BasePlugin { public struct LogEntry { public string Name; public string AssetId; } public class CardDataStatsly { public int Id { get; set; } public int PlayedCount { get; set; } public long Damages { get; set; } public int Kills { get; set; } public double DamagesPerUse { get; set; } } public ManualLogSource Log; public static Plugin Instance; public RunManager rm = new RunManager(); public override void Load() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown Instance = this; Log = ((BasePlugin)this).Log; ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("VampireMod"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!"); } log.LogInfo(val); Harmony val2 = new Harmony("VampireMod"); val2.PatchAll(); foreach (MethodBase patchedMethod in val2.GetPatchedMethods()) { ManualLogSource log2 = Log; val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Patched: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(patchedMethod.DeclaringType?.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(patchedMethod.Name); } log2.LogInfo(val); } } public void LogToStatsly(string message) { using StreamWriter streamWriter = File.AppendText(GetMegaBonkFilePath()); streamWriter.WriteLine(message); } private string GetMegaBonkFilePath() { string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); string text = Path.Combine(folderPath, "Statly"); string result = Path.Combine(text, "vampireCrawlers.txt"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } return result; } public void Localize(string lang) { string path = "B:\\DevProjects\\Python\\VampireCrawlersTranslations\\" + lang; Dictionary dictionary = new Dictionary(); Dictionary trsltArcanas = new Dictionary(); LocalizeArcana(Databases.ArcanaConfigs.AndAnother, dictionary, trsltArcanas, 0); LocalizeArcana(Databases.ArcanaConfigs.ChainLink, dictionary, trsltArcanas, 1); LocalizeArcana(Databases.ArcanaConfigs.ExperimentalMedicine, dictionary, trsltArcanas, 2); LocalizeArcana(Databases.ArcanaConfigs.JestersHat, dictionary, trsltArcanas, 3); LocalizeArcana(Databases.ArcanaConfigs.MakeAScene, dictionary, trsltArcanas, 4); LocalizeArcana(Databases.ArcanaConfigs.ManaSyphon, dictionary, trsltArcanas, 5); LocalizeArcana(Databases.ArcanaConfigs.OverTheTop, dictionary, trsltArcanas, 6); LocalizeArcana(Databases.ArcanaConfigs.SharpMind, dictionary, trsltArcanas, 7); LocalizeArcana(Databases.ArcanaConfigs.ShieldBash, dictionary, trsltArcanas, 8); LocalizeArcana(Databases.ArcanaConfigs.SwollenFist, dictionary, trsltArcanas, 9); LocalizeArcana(Databases.ArcanaConfigs.WildStrength, dictionary, trsltArcanas, 10); LocalizeArcana(Databases.ArcanaConfigs.YourShield, dictionary, trsltArcanas, 11); Dictionary dictionary2 = new Dictionary(); Dictionary trsltCards = new Dictionary(); LocalizeCards(dictionary2, trsltCards); Dictionary dictionary3 = new Dictionary(); Dictionary trsltDungeons = new Dictionary(); LocalizeDungeons(dictionary3, trsltDungeons); Dictionary monsters = new Dictionary(); Dictionary trsltMonsters = new Dictionary(); LocalizeMonsters(monsters, trsltMonsters); JsonSerializerOptions options = new JsonSerializerOptions { WriteIndented = true }; File.WriteAllText(Path.Combine(path, "dungeons.json"), JsonSerializer.Serialize(dictionary3, options)); File.WriteAllText(Path.Combine(path, "cards.json"), JsonSerializer.Serialize(dictionary2, options)); File.WriteAllText(Path.Combine(path, "arcanas.json"), JsonSerializer.Serialize(dictionary, options)); } public static string GetCleanEnemyName(string assetId) { if (string.IsNullOrEmpty(assetId)) { return string.Empty; } assetId = assetId.Replace("EnemyConfig_", ""); HashSet ignore = new HashSet(StringComparer.OrdinalIgnoreCase) { "Test", "Tutorial", "NoXP" }; List values = (from p in assetId.Split('_', StringSplitOptions.RemoveEmptyEntries) where !ignore.Contains(p) && !p.All(char.IsDigit) select p).ToList(); string text = string.Join(" ", values); return text.Replace("Elite", "(Elite)").Replace("Ambush", "(Ambush)"); } private void LocalizeMonsters(Dictionary monsters, Dictionary trsltMonsters) { ValueCollection values = ((AssetDatabase)(object)Databases.Enemies)._assetIdMap.Values; List list = new List(); Enumerator enumerator = values.GetEnumerator(); while (enumerator.MoveNext()) { EnemyConfig current = enumerator.Current; try { string assetId = current.AssetId; list.Add(new LogEntry { Name = GetCleanEnemyName(assetId), AssetId = assetId }); } catch { } } list.Sort((LogEntry a, LogEntry b) => string.CompareOrdinal(a.AssetId, b.AssetId)); int num = 0; foreach (LogEntry item in list) { monsters[num] = item.Name; trsltMonsters[item.AssetId] = num; num++; } } private void LocalizeDungeons(Dictionary dungeons, Dictionary trsltDungeons) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown List assetList = ((AssetGroup)(object)Databases.Dungeons)._assetList; List list = new List(); Enumerator enumerator = assetList.GetEnumerator(); bool flag = default(bool); while (enumerator.MoveNext()) { DungeonConfig current = enumerator.Current; try { if (current.Name != null && current.AssetId != null && !current.AssetId.Contains("TestDungeonConfig")) { ManualLogSource log = Instance.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(9, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("dungeon "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(current.AssetId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(current.Name); } log.LogInfo(val); list.Add(new LogEntry { Name = current.Name, AssetId = current.AssetId }); } } catch (Exception) { } } list.Sort((LogEntry a, LogEntry b) => string.CompareOrdinal(a.AssetId, b.AssetId)); int num = 0; foreach (LogEntry item in list) { dungeons[num] = item.Name; trsltDungeons[item.AssetId] = num; num++; } } private void LocalizeCards(Dictionary cards, Dictionary trsltCards) { Dictionary> cardGroupCardMap = Databases.CardConfigs._cardGroupCardMap; List list = new List(); Enumerator> enumerator = cardGroupCardMap.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair> current = enumerator.Current; string groupName = current.Key.groupName; if (groupName == "Test Card Group") { continue; } Enumerator enumerator2 = current.Value.GetEnumerator(); while (enumerator2.MoveNext()) { CardConfig current2 = enumerator2.Current; if ((!current2.IsDisabled || !(current2.Name != "Card_D_3_Armor")) && !current2.AssetId.Contains("Test")) { list.Add(new LogEntry { Name = current2.Name, AssetId = current2.AssetId }); } } } list.Sort((LogEntry a, LogEntry b) => string.CompareOrdinal(a.AssetId, b.AssetId)); int num = 0; foreach (LogEntry item in list) { cards[num] = item.Name; trsltCards[item.AssetId] = num; num++; } } private void LocalizeArcana(ArcanaConfig config, Dictionary arcanas, Dictionary trsltArcanas, int index) { string assetId = config.AssetId; string name = config.Name; arcanas[index] = name; trsltArcanas[assetId] = index; } } public class RunManager { private DataSender Sender { get; set; } = new DataSender(); private List Timeline { get; set; } = new List(); public int PreviousComboCount { get; set; } = 0; private double TotalDamagesDealt { get; set; } = 0.0; private int TotalDamagesTaken { get; set; } = 0; private int TotalDamagesTanked { get; set; } = 0; private int TotalEncountersDefeatedCount { get; set; } = 0; private int CurrentFloorIndex { get; set; } = 0; private int CurrentEncounterStart { get; set; } = 0; private Dictionary FloorsData { get; set; } = new Dictionary(); private int TotalMovementsCount { get; set; } = 0; private int TotalTilesVisited { get; set; } = 0; private int TotalCardsPlayedCount { get; set; } = 0; private int TotalCardsInComboCount { get; set; } = 0; private int MaxComboReached { get; set; } = 0; private Dictionary TotalCardsPlayed { get; set; } = new Dictionary(); private Dictionary TotalCardsKills { get; set; } = new Dictionary(); private Dictionary TotalCardsDamages { get; set; } = new Dictionary(); private int TotalBestDamageCardId { get; set; } = 0; private int TotalBestDamageCardDamages { get; set; } = 0; private int TotalMonstersKilledCount { get; set; } = 0; private int TotalMonstersKnockedCount { get; set; } = 0; private double TotalOverkillDamagesCount { get; set; } = 0.0; private Dictionary TotalMonstersDamages { get; set; } = new Dictionary(); private Dictionary TotalMonstersKills { get; set; } = new Dictionary(); private int? CrawlerId { get; set; } = null; private int? DungeonId { get; set; } = null; private int BreakingCardCount { get; set; } = 0; private int FullyBrokenCardCount { get; set; } = 0; private int EvolutionsCount { get; set; } = 0; private List Arcanas { get; set; } = new List(); private Dictionary Destructibles { get; set; } = new Dictionary(); private int TotalGemsInserted { get; set; } = 0; public RunManager() { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) foreach (DestructibleType value in Enum.GetValues(typeof(DestructibleType))) { Destructibles[value] = 0; } } public void TryAddTimelineEvent(int eventId) { try { int timestamp = (int)SingletonMonoBehaviour.Instance.CurrentTimeInRun; TimelineEvent item = new TimelineEvent { EventId = eventId, Timestamp = timestamp }; Timeline.Add(item); } catch { } } private void clear() { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) PreviousComboCount = 0; TotalDamagesDealt = 0.0; TotalDamagesTaken = 0; TotalDamagesTanked = 0; TotalEncountersDefeatedCount = 0; CurrentFloorIndex = 0; FloorsData = new Dictionary(); TotalMovementsCount = 0; TotalTilesVisited = 0; TotalCardsPlayedCount = 0; TotalCardsInComboCount = 0; MaxComboReached = 0; TotalCardsPlayed = new Dictionary(); TotalCardsKills = new Dictionary(); TotalCardsDamages = new Dictionary(); TotalBestDamageCardId = 0; TotalBestDamageCardDamages = 0; TotalGemsInserted = 0; TotalMonstersKilledCount = 0; TotalMonstersKnockedCount = 0; TotalOverkillDamagesCount = 0.0; TotalMonstersDamages = new Dictionary(); TotalMonstersKills = new Dictionary(); CrawlerId = null; DungeonId = null; BreakingCardCount = 0; FullyBrokenCardCount = 0; EvolutionsCount = 0; Arcanas = new List(); Destructibles = new Dictionary(); foreach (DestructibleType value in Enum.GetValues(typeof(DestructibleType))) { Destructibles[value] = 0; } Timeline = new List(); } public void TileVisited(Vector2Int coords) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) FloorsData[CurrentFloorIndex].TilesVisited.Add(coords); TotalTilesVisited++; PlayerMoved(); } public void OnGemInserted() { TotalGemsInserted++; FloorsData[CurrentFloorIndex].OnGemInserted(); SaveCurrentRun(); } public void OnFloorLoaded(TiledMapData tiles, Vector2Int? oldCoord = null) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_00a7: 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_00d9: Invalid comparison between Unknown and I4 if (CurrentFloorIndex != 0) { FloorsData[CurrentFloorIndex].OnFloorFinished(); TryAddTimelineEvent(3); } CurrentFloorIndex++; FloorsData[CurrentFloorIndex] = new FloorData(); Vector2Int currentPlayerMapCoords = SingletonMonoBehaviour.Instance.Dungeon3DMapModel.CurrentPlayerMapCoords; FloorsData[CurrentFloorIndex].TilesVisited.Add(currentPlayerMapCoords); if (oldCoord.HasValue) { FloorsData[CurrentFloorIndex].TilesVisited.Add(oldCoord.Value); } foreach (MapTile item in tiles.MapTiles._gridArray) { if ((int)item.ValidExits > 0) { FloorsData[CurrentFloorIndex].FloorTilesCount++; } } } public void OnEncounterDefeated() { TotalEncountersDefeatedCount++; FloorsData[CurrentFloorIndex].EncountersDefeatedCount++; SaveCurrentRun(); (List, List) cardsForUpdate = GetCardsForUpdate(); Sender.SendUpdate(cardsForUpdate.Item2, cardsForUpdate.Item1); } public void AddDestructible(DestructibleType type) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_001d: 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_0052: Unknown result type (might be due to invalid IL or missing references) if (Destructibles.TryGetValue(type, out var _)) { Destructibles[type]++; } else { Destructibles[type] = 1; } FloorsData[CurrentFloorIndex].AddDestructible(type); SaveCurrentRun(); } public void CardPlayed(int id, bool isCardInCombo, int comboCount) { TotalCardsPlayed[id] = ((!TotalCardsPlayed.TryGetValue(id, out var value)) ? 1 : (value + 1)); TotalCardsPlayedCount++; if (isCardInCombo) { TotalCardsInComboCount++; } if (comboCount > MaxComboReached) { MaxComboReached = comboCount; } FloorsData[CurrentFloorIndex].CardPlayed(id, isCardInCombo, comboCount); SaveCurrentRun(); (List, List) cardsForUpdate = GetCardsForUpdate(); Sender.SendUpdate(cardsForUpdate.Item2, cardsForUpdate.Item1); } public void OnPlayerTurnEnded() { (List, List) cardsForUpdate = GetCardsForUpdate(); Sender.SendUpdate(cardsForUpdate.Item2, cardsForUpdate.Item1, forceUpdate: true); } public void PlayerMoved() { TotalMovementsCount++; FloorsData[CurrentFloorIndex].MovementsCount++; } public void PlayerDealDamages(int cardId, double damages) { TotalCardsDamages[cardId] = (TotalCardsDamages.TryGetValue(cardId, out var value) ? (value + damages) : damages); if (damages > (double)TotalBestDamageCardDamages) { TotalBestDamageCardDamages = (int)damages; TotalBestDamageCardId = cardId; } TotalDamagesDealt += damages; FloorsData[CurrentFloorIndex].PlayerDealDamages(cardId, damages); } public void MonsterReceivesDamages(int monsterId, double damages, double overKillDamages) { TotalOverkillDamagesCount += overKillDamages; TotalMonstersDamages[monsterId] = (TotalMonstersDamages.TryGetValue(monsterId, out var value) ? (value + damages) : damages); FloorsData[CurrentFloorIndex].MonsterReceivesDamages(monsterId, damages, overKillDamages); } public void EnemyDamagesHit(int damages, int armored) { TotalDamagesTaken += damages; TotalDamagesTanked += armored; FloorsData[CurrentFloorIndex].DamagesTaken += damages; FloorsData[CurrentFloorIndex].DamagesTanked += armored; } public void MonsterKilled(int cardId, int enemyId) { TotalMonstersKills[enemyId] = ((!TotalMonstersKills.TryGetValue(enemyId, out var value)) ? 1 : (value + 1)); TotalCardsKills[cardId] = ((!TotalCardsKills.TryGetValue(cardId, out var value2)) ? 1 : (value2 + 1)); TotalMonstersKilledCount++; FloorsData[CurrentFloorIndex].MonsterKilled(cardId, enemyId); } public void CardCracked(CardCrackState state) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 BreakingCardCount++; if ((int)state == 2) { FullyBrokenCardCount++; } } public void RunEnded(bool isCompleted, double runDuration, int diffRating, int level, List arcanas) { if (CurrentFloorIndex != 0) { FloorsData[CurrentFloorIndex].OnFloorFinished(); } Plugin.Instance.Log.LogInfo((object)JsonSerializer.Serialize(FloorsData)); int duration = (int)Math.Round(runDuration); long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long num2 = 0L; Dictionary dictionary = new Dictionary(TotalCardsDamages.Count); foreach (KeyValuePair totalCardsDamage in TotalCardsDamages) { num2 += (long)totalCardsDamage.Value; dictionary[totalCardsDamage.Key] = (long)totalCardsDamage.Value; } Dictionary dictionary2 = new Dictionary(TotalMonstersDamages.Count); foreach (KeyValuePair totalMonstersDamage in TotalMonstersDamages) { dictionary2[totalMonstersDamage.Key] = (long)totalMonstersDamage.Value; } Destructibles.TryGetValue((DestructibleType)3, out var value); Destructibles.TryGetValue((DestructibleType)0, out var value2); object obj = new { Duration = duration, CharacterId = GetCrawlerId(), DungeonId = GetDungeonId(), TotalCardsPlayedCount = TotalCardsPlayedCount, CardsPlayedDict = TotalCardsPlayed, DamagesDict = dictionary, TotalDamagesDealt = num2, IsWin = isCompleted, DiffRating = diffRating, TotalDamagesTaken = TotalDamagesTaken, TotalDamagesTanked = TotalDamagesTanked, Level = level, Arcanas = arcanas, TotalMonstersKills = TotalMonstersKills, TotalMonstersKilledCount = TotalMonstersKilledCount, MonstersDamages = dictionary2, TotalCardsKills = TotalCardsKills, ChestsOpened = value, CandlesDestroyed = value2, TotalBestDamageCardId = TotalBestDamageCardId, TotalBestDamageCardDamages = TotalBestDamageCardDamages, TotalCardsInComboCount = TotalCardsInComboCount, MaxComboReached = MaxComboReached, FloorsData = FloorsData, TotalEncountersDefeatedCount = TotalEncountersDefeatedCount, Timeline = Timeline, TotalGemsInserted = TotalGemsInserted }; Plugin.Instance.LogToStatsly(JsonSerializer.Serialize(obj)); var value3 = new { Event = "runEnd", Data = obj }; Plugin.Instance.LogToStatsly(JsonSerializer.Serialize(value3)); clear(); } private (List gameCards, List floorCards) GetCardsForUpdate() { List list = new List(); foreach (KeyValuePair item in TotalCardsPlayed) { int key = item.Key; TotalCardsDamages.TryGetValue(key, out var value); TotalCardsKills.TryGetValue(key, out var value2); list.Add(new Plugin.CardDataStatsly { Id = item.Key, PlayedCount = item.Value, Damages = (long)value, Kills = value2, DamagesPerUse = Math.Round(value / (double)item.Value) }); } return (list, FloorsData[CurrentFloorIndex].GetCardsForUpdate()); } private int GetDungeonId() { PlayerRunSettings playerRunSettings = Globals.PlayerRunSettings; DungeonConfig val = playerRunSettings.CurrentDungeonSetting(); return Dicts.GetOrCreateId(val.AssetId, Dicts.DungeonDevNameToId); } private int GetCrawlerId() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown PlayerRunSettings playerRunSettings = Globals.PlayerRunSettings; FccConfig mainFcc = playerRunSettings.MainFcc; if ((Object)(object)mainFcc != (Object)null) { string assetId = ((CardConfig)mainFcc).AssetId; return Dicts.GetOrCreateId(assetId, Dicts.CardDevNameToId); } List startingDeck = Globals.PlayerRunSettings._startingDeck; string value = string.Empty; Enumerator enumerator = startingDeck.GetEnumerator(); bool flag = default(bool); while (enumerator.MoveNext()) { DeckCardItem current = enumerator.Current; string assetId2 = current.cardConfig.AssetId; if (assetId2.Contains("FCC")) { ManualLogSource log = Plugin.Instance.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(0, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(assetId2); } log.LogInfo(val); value = assetId2; break; } } return Dicts.GetOrCreateId(value, Dicts.CardDevNameToId); } private static string GetFilePath() { string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); string path = Path.Combine(folderPath, "Statly"); return Path.Combine(path, "vampireCrawlersCurrentRun.txt"); } private void SaveCurrentRun() { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown try { var value = new { PreviousComboCount, TotalDamagesDealt, TotalDamagesTaken, TotalDamagesTanked, TotalEncountersDefeatedCount, CurrentFloorIndex, FloorsData, TotalMovementsCount, TotalTilesVisited, TotalCardsPlayedCount, TotalCardsInComboCount, MaxComboReached, TotalCardsPlayed, TotalCardsKills, TotalCardsDamages, TotalBestDamageCardId, TotalBestDamageCardDamages, TotalMonstersKilledCount, TotalMonstersKnockedCount, TotalOverkillDamagesCount, TotalMonstersDamages, TotalMonstersKills, CrawlerId, DungeonId, BreakingCardCount, FullyBrokenCardCount, EvolutionsCount, Arcanas, Destructibles, Timeline, TotalGemsInserted }; string contents = JsonSerializer.Serialize(value); string filePath = GetFilePath(); Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.WriteAllText(filePath, contents); } catch (Exception ex) { ManualLogSource log = Plugin.Instance.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to save current run: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogError(val); } } public bool TryLoadCurrentRun() { //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Expected O, but got Unknown try { string filePath = GetFilePath(); if (!File.Exists(filePath)) { return false; } string text = File.ReadAllText(filePath); if (string.IsNullOrWhiteSpace(text)) { return false; } JsonDocument jsonDocument = JsonDocument.Parse(text); JsonElement rootElement = jsonDocument.RootElement; PreviousComboCount = rootElement.GetProperty("PreviousComboCount").GetInt32(); TotalDamagesDealt = rootElement.GetProperty("TotalDamagesDealt").GetDouble(); TotalDamagesTaken = rootElement.GetProperty("TotalDamagesTaken").GetInt32(); TotalDamagesTanked = rootElement.GetProperty("TotalDamagesTanked").GetInt32(); TotalEncountersDefeatedCount = rootElement.GetProperty("TotalEncountersDefeatedCount").GetInt32(); CurrentFloorIndex = rootElement.GetProperty("CurrentFloorIndex").GetInt32(); TotalMovementsCount = rootElement.GetProperty("TotalMovementsCount").GetInt32(); TotalTilesVisited = rootElement.GetProperty("TotalTilesVisited").GetInt32(); TotalCardsPlayedCount = rootElement.GetProperty("TotalCardsPlayedCount").GetInt32(); TotalCardsInComboCount = rootElement.GetProperty("TotalCardsInComboCount").GetInt32(); MaxComboReached = rootElement.GetProperty("MaxComboReached").GetInt32(); TotalBestDamageCardId = rootElement.GetProperty("TotalBestDamageCardId").GetInt32(); TotalBestDamageCardDamages = rootElement.GetProperty("TotalBestDamageCardDamages").GetInt32(); TotalMonstersKilledCount = rootElement.GetProperty("TotalMonstersKilledCount").GetInt32(); TotalMonstersKnockedCount = rootElement.GetProperty("TotalMonstersKnockedCount").GetInt32(); TotalOverkillDamagesCount = rootElement.GetProperty("TotalOverkillDamagesCount").GetDouble(); CrawlerId = ((rootElement.GetProperty("CrawlerId").ValueKind == JsonValueKind.Null) ? null : new int?(rootElement.GetProperty("CrawlerId").GetInt32())); DungeonId = ((rootElement.GetProperty("DungeonId").ValueKind == JsonValueKind.Null) ? null : new int?(rootElement.GetProperty("DungeonId").GetInt32())); BreakingCardCount = rootElement.GetProperty("BreakingCardCount").GetInt32(); FullyBrokenCardCount = rootElement.GetProperty("FullyBrokenCardCount").GetInt32(); EvolutionsCount = rootElement.GetProperty("EvolutionsCount").GetInt32(); TotalGemsInserted = rootElement.GetProperty("TotalGemsInserted").GetInt32(); TotalCardsPlayed = JsonSerializer.Deserialize>(rootElement.GetProperty("TotalCardsPlayed").GetRawText()) ?? new Dictionary(); TotalCardsKills = JsonSerializer.Deserialize>(rootElement.GetProperty("TotalCardsKills").GetRawText()) ?? new Dictionary(); TotalCardsDamages = JsonSerializer.Deserialize>(rootElement.GetProperty("TotalCardsDamages").GetRawText()) ?? new Dictionary(); TotalMonstersDamages = JsonSerializer.Deserialize>(rootElement.GetProperty("TotalMonstersDamages").GetRawText()) ?? new Dictionary(); TotalMonstersKills = JsonSerializer.Deserialize>(rootElement.GetProperty("TotalMonstersKills").GetRawText()) ?? new Dictionary(); Arcanas = JsonSerializer.Deserialize>(rootElement.GetProperty("Arcanas").GetRawText()) ?? new List(); Destructibles = JsonSerializer.Deserialize>(rootElement.GetProperty("Destructibles").GetRawText()) ?? new Dictionary(); FloorsData = JsonSerializer.Deserialize>(rootElement.GetProperty("FloorsData").GetRawText()) ?? new Dictionary(); Timeline = JsonSerializer.Deserialize>(rootElement.GetProperty("Timeline").GetRawText()) ?? new List(); Plugin.Instance.Log.LogInfo((object)"Resumed run from saved file."); (List, List) cardsForUpdate = GetCardsForUpdate(); Sender.SendUpdate(cardsForUpdate.Item2, cardsForUpdate.Item1, forceUpdate: true); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Instance.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to load current run: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogError(val); return false; } } public void ClearCurrentRunFile() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown try { string filePath = GetFilePath(); if (File.Exists(filePath)) { File.Delete(filePath); } } catch (Exception ex) { ManualLogSource log = Plugin.Instance.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(34, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to clear current run file: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogError(val); } } } public class FloorData { public long TotalDamagesDealt { get; set; } = 0L; public int DamagesTaken { get; set; } = 0; public int DamagesTanked { get; set; } = 0; public int EncountersDefeatedCount { get; set; } = 0; [JsonIgnore] public HashSet TilesVisited { get; set; } = new HashSet(); public int FloorTilesCount { get; set; } = 0; public int TotalTilesVisited { get; set; } = 0; public int MovementsCount { get; set; } = 0; public int CardsPlayedCount { get; set; } = 0; public int CardsInComboCount { get; set; } = 0; public int MaxComboReached { get; set; } = 0; public Dictionary CardsPlayed { get; set; } = new Dictionary(); public Dictionary CardsKills { get; set; } = new Dictionary(); public Dictionary CardsDamagesRaw { get; set; } = new Dictionary(); public Dictionary CardsDamages { get; set; } = new Dictionary(); public int BestDamageCardId { get; set; } = 0; public int BestDamageCardDamages { get; set; } = 0; public int MonstersKilledCount { get; set; } = 0; public int MonstersKnockedCount { get; set; } = 0; public double OverkillDamagesCountRaw { get; set; } = 0.0; public long OverkillDamagesCount { get; set; } = 0L; public Dictionary MonstersDamagesRaw { get; set; } = new Dictionary(); public Dictionary MonstersDamages { get; set; } = new Dictionary(); public Dictionary MonstersKills { get; set; } = new Dictionary(); public Dictionary Destructibles { get; set; } = new Dictionary(); public int ChestsOpened { get; set; } = 0; public int CandlesDestroyed { get; set; } = 0; public int GemsInserted { get; set; } = 0; public void OnFloorFinished() { TotalTilesVisited = TilesVisited.Count; Destructibles.TryGetValue((DestructibleType)3, out var value); Destructibles.TryGetValue((DestructibleType)0, out var value2); ChestsOpened = value; CandlesDestroyed = value2; foreach (KeyValuePair item in CardsDamagesRaw) { TotalDamagesDealt += (long)item.Value; CardsDamages[item.Key] = (int)item.Value; } foreach (KeyValuePair item2 in MonstersDamagesRaw) { MonstersDamages[item2.Key] = (int)item2.Value; } OverkillDamagesCount = (long)OverkillDamagesCountRaw; } public void CardPlayed(int id, bool isCardInCombo, int comboCount) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown CardsPlayed[id] = ((!CardsPlayed.TryGetValue(id, out var value)) ? 1 : (value + 1)); CardsPlayedCount++; ManualLogSource log = Plugin.Instance.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("played "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CardsPlayedCount); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" this floor"); } log.LogInfo(val); if (isCardInCombo) { CardsInComboCount++; } if (comboCount > MaxComboReached) { MaxComboReached = comboCount; } } public void PlayerDealDamages(int cardId, double damages) { CardsDamagesRaw[cardId] = (CardsDamagesRaw.TryGetValue(cardId, out var value) ? (value + damages) : damages); if (damages > (double)BestDamageCardDamages) { BestDamageCardDamages = (int)damages; BestDamageCardId = cardId; } } public void MonsterReceivesDamages(int monsterId, double damages, double overKillDamages) { OverkillDamagesCountRaw += overKillDamages; MonstersDamagesRaw[monsterId] = (MonstersDamagesRaw.TryGetValue(monsterId, out var value) ? (value + damages) : damages); } public void MonsterKilled(int cardId, int enemyId) { MonstersKills[enemyId] = ((!MonstersKills.TryGetValue(enemyId, out var value)) ? 1 : (value + 1)); CardsKills[cardId] = ((!CardsKills.TryGetValue(cardId, out var value2)) ? 1 : (value2 + 1)); MonstersKilledCount++; } public void OnGemInserted() { GemsInserted++; } public void AddDestructible(DestructibleType type) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_001d: 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) if (Destructibles.TryGetValue(type, out var _)) { Destructibles[type]++; } else { Destructibles[type] = 1; } } public List GetCardsForUpdate() { List list = new List(); foreach (KeyValuePair item in CardsPlayed) { int key = item.Key; CardsDamagesRaw.TryGetValue(key, out var value); CardsKills.TryGetValue(key, out var value2); list.Add(new Plugin.CardDataStatsly { Id = item.Key, PlayedCount = item.Value, Damages = (long)value, DamagesPerUse = Math.Round(value / (double)item.Value), Kills = value2 }); } return list; } } public class TimelineEvent { public int Timestamp { get; set; } public int EventId { get; set; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "VampireMod"; public const string PLUGIN_NAME = "My first plugin"; public const string PLUGIN_VERSION = "1.0.0"; } }