using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using ImpactfulSkills.common; using ImpactfulSkills.compatibility; using ImpactfulSkills.modules.Multiplant; using ImpactfulSkills.patches; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ImpactfulSkills")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ImpactfulSkills")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.9.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.9.0.0")] namespace ImpactfulSkills { internal class ValConfig { public static ConfigFile cfg; public static ConfigEntry EnableDebugMode; public static ConfigEntry EnableWoodcutting; public static ConfigEntry WoodCuttingDmgMod; public static ConfigEntry WoodCuttingLootFactor; public static ConfigEntry EnableMining; public static ConfigEntry MiningDmgMod; public static ConfigEntry MiningLootFactor; public static ConfigEntry MiningAOERange; public static ConfigEntry MiningAOELevel; public static ConfigEntry EnableMiningAOE; public static ConfigEntry EnableMiningRockBreaker; public static ConfigEntry RockBreakerMaxChance; public static ConfigEntry RockBreakerRequiredLevel; public static ConfigEntry RockBreakerDamage; public static ConfigEntry MinehitsPerInterval; public static ConfigEntry ChanceForAOEOnHit; public static ConfigEntry SkillLevelBonusEnabledForMiningDropChance; public static ConfigEntry ChanceForAOEOnHitScalesWithSkill; public static ConfigEntry EnableMiningCritHit; public static ConfigEntry RequiredLevelForMiningCrit; public static ConfigEntry ChanceForMiningCritHit; public static ConfigEntry CriticalHitDmgMult; public static ConfigEntry SkipNonRockDropIncreases; public static ConfigEntry ReducedChanceDropsForLowAmountDrops; public static ConfigEntry DistanceMiningDropMultiplierChecks; public static ConfigEntry RockbreakerSafetyResetTimeout; public static ConfigEntry SkipNonRockDropPrefabs; public static ConfigEntry FractionalDropsAsChance; public static ConfigEntry EnableStealth; public static ConfigEntry SneakSpeedFactor; public static ConfigEntry SneakNoiseReductionLevel; public static ConfigEntry SneakNoiseReductionFactor; public static ConfigEntry EnableSneakBonusDamage; public static ConfigEntry SneakBackstabBonusLevel; public static ConfigEntry SneakBackstabBonusFactor; public static ConfigEntry EnableRun; public static ConfigEntry RunSpeedFactor; public static ConfigEntry EnableJump; public static ConfigEntry JumpHeightFactor; public static ConfigEntry JumpHeightRequiredLevel; public static ConfigEntry EnableFallDamageReduction; public static ConfigEntry FallDamageReductionFactor; public static ConfigEntry FallDamageReductionRequiredLevel; public static ConfigEntry FallDamageHeightBonus; public static ConfigEntry FallDamageHeightRequiredLevel; public static ConfigEntry EnableFallDamageHeightBonus; public static ConfigEntry EnableAnimalWhisper; public static ConfigEntry AnimalTamingSpeedFactor; public static ConfigEntry TamedAnimalLootIncreaseFactor; public static ConfigEntry BetterBeesLevel; public static ConfigEntry EnableBeeBonuses; public static ConfigEntry BeeBiomeUnrestrictedLevel; public static ConfigEntry EnableBeeBiomeUnrestricted; public static ConfigEntry BeeHoneyOutputIncreaseBySkill; public static ConfigEntry BeeHarvestXP; public static ConfigEntry EnableGathering; public static ConfigEntry EnableGatheringAOE; public static ConfigEntry GatheringLuckFactor; public static ConfigEntry GatheringRangeFactor; public static ConfigEntry FarmingRangeRequiredLevel; public static ConfigEntry GatheringLuckLevels; public static ConfigEntry GatheringDisallowedItems; public static ConfigEntry EnableFarmingMultiPlant; public static ConfigEntry FarmingMultiplantRequiredLevel; public static ConfigEntry FarmingMultiplantMaxPlantedAtOnce; public static ConfigEntry FarmingMultiplantColumnCount; public static ConfigEntry FarmingMultiPlantSnapToExisting; public static ConfigEntry FarmingMultiPlantBufferSpace; public static ConfigEntry PlantingCostStaminaReduction; public static ConfigEntry PlantingSnapDistance; public static ConfigEntry PlantingAOEHarvestResetSafety; public static ConfigEntry PreferOtherPlantGrid; public static ConfigEntry FarmingSnapStyle; public static ConfigEntry FarmingSnapPreferCardinal; public static ConfigEntry EnableSnappingToOtherPlants; public static ConfigEntry FarmingMultiPlantDistanceBufferModifier; public static ConfigEntry EnableVoyager; public static ConfigEntry VoyagerSkillXPCheckFrequency; public static ConfigEntry VoyagerReduceCuttingStart; public static ConfigEntry VoyagerSailingSpeedFactor; public static ConfigEntry VoyagerIncreaseExplorationRadius; public static ConfigEntry VoyagerPaddleSpeedBonus; public static ConfigEntry VoyagerPaddleSpeedBonusLevel; public static ConfigEntry EnableBoatDamageReduction; public static ConfigEntry BoatDamageReductionLevel; public static ConfigEntry VoyagerDamageReductionAmount; public static ConfigEntry VoyagerImpactResistance; public static ConfigEntry VoyagerImpactResistanceLevel; public static ConfigEntry EnableFriendsRowSpeedBonus; public static ConfigEntry MaxFriendsRowSpeedBonus; public static ConfigEntry EnableWeaponSkill; public static ConfigEntry WeaponSkillStaminaReduction; public static ConfigEntry WeaponSkillBowDrawStaminaCostReduction; public static ConfigEntry WeaponSkillParryBonus; public static ConfigEntry WeaponSkillEquipSpeedFactor; public static ConfigEntry WeaponSkillEquipRequiredLevel; public static ConfigEntry EnableCooking; public static ConfigEntry EnableCookingBonusItems; public static ConfigEntry ChanceForCookingBonusItems; public static ConfigEntry RequiredLevelForBonusCookingItems; public static ConfigEntry CookingBonusItemMaxAmount; public static ConfigEntry CookingBurnReduction; public static ConfigEntry EnableHauling; public static ConfigEntry EnableCarryWeightBonus; public static ConfigEntry HaulingMaxWeightBonus; public static ConfigEntry EnableHaulingCartMassReduction; public static ConfigEntry HaulingCartMassReduction; public static ConfigEntry HaulingXPRate; public static ConfigEntry HaulingXPCheckInterval; public static ConfigEntry EnableBloodMagic; public static ConfigEntry BloodMagicXPForShieldDamageRatio; public static ConfigEntry BloodMagicXP; public static ConfigEntry EnableKnowledgeSharing; public static ConfigEntry AnimalTamingSkillGainRate; public static ConfigEntry VoyagerSkillGainRate; public static ConfigEntry SharedKnowledgeSkillBonusRate; public static ConfigEntry SharedKnowledgeCap; public static ConfigEntry SharedKnowledgeIgnoreList; public static ConfigEntry EnableCrafting; public static ConfigEntry EnableDurabilitySaves; public static ConfigEntry ScaleDurabilitySaveBySkillLevel; public static ConfigEntry EnableDurabilityLossPrevention; public static ConfigEntry DurabilitySaveLevel; public static ConfigEntry ChanceForDurabilityLossPrevention; public static ConfigEntry CraftingMaxBonus; public static ConfigEntry CraftingBonusChance; public static ConfigEntry EnableBonusItemCrafting; public static ConfigEntry EnableCraftBonusAsFraction; public static ConfigEntry CraftBonusFractionOfCraftNumber; public static ConfigEntry CraftingBonusCraftsLevel; public static ConfigEntry EnableMaterialReturns; public static ConfigEntry CraftingMaterialReturnsLevel; public static ConfigEntry MaxCraftingMaterialReturnPercent; public static ConfigEntry ChanceForMaterialReturn; public static ConfigEntry EnableSwimming; public static ConfigEntry SwimSpeedRequiredLevel; public static ConfigEntry SwimmingSpeedFactor; public static ConfigEntry EnableSwimStaminaCostReduction; public static ConfigEntry SwimStaminaReductionLevel; public static ConfigEntry SwimStaminaCostReductionFactor; public static ConfigEntry EnableBlocking; public static ConfigEntry BlockPowerRequiredLevel; public static ConfigEntry BlockPowerFactor; public static ConfigEntry BlockStaminaGainRequiredLevel; public static ConfigEntry BlockStaminaGainFactor; public static ConfigEntry EnableParryStaminaGain; public ValConfig(ConfigFile cf) { cfg = cf; cfg.SaveOnConfigSet = true; CreateConfigValues(cf); Logger.setDebugLogging(EnableDebugMode.Value); SetupMainFileWatcher(); } private void CreateConfigValues(ConfigFile Config) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown EnableDebugMode = Config.Bind("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); EnableDebugMode.SettingChanged += Logger.enableDebugLogging; EnableWoodcutting = BindServerConfig("Woodcutting", "EnableWoodcutting", value: true, "Enable woodcutting skill changes."); WoodCuttingDmgMod = BindServerConfig("Woodcutting", "WoodCuttingDmgMod", 1.2f, "How much skill levels impact your chop damage."); WoodCuttingLootFactor = BindServerConfig("Woodcutting", "WoodCuttingLootFactor", 3f, "How much the woodcutting skill provides additional loot. 2 is 2x the loot at level 100.", advanced: false, 1f, 10f); EnableMining = BindServerConfig("Mining", "EnableMining", value: true, "Enable mining skill changes."); MiningDmgMod = BindServerConfig("Mining", "MiningDmgMod", 1.2f, "How much your skill levels impact mining damage."); EnableMiningCritHit = BindServerConfig("Mining", "EnableMiningCritHit", value: true, "Enables mining critial hit strikes, must hit the required level for it to be active."); RequiredLevelForMiningCrit = BindServerConfig("Mining", "RequiredLevelForMiningCrit", 25, "Level the player must be for critical mining hits to activate", advanced: false, 0, 100); ChanceForMiningCritHit = BindServerConfig("Mining", "ChanceForMiningCritHit", 0.1f, "Chance for a critical hit when mining", advanced: false, 0f, 1f); CriticalHitDmgMult = BindServerConfig("Mining", "CriticalHitDmgMult", 3f, "Multipler for damage from a critical hit", advanced: false, 1f, 20f); MiningLootFactor = BindServerConfig("Mining", "MiningLootFactor", 2f, "How much the mining skill provides additional loot. 2 is 2x the loot at level 100."); EnableMiningAOE = BindServerConfig("Mining", "EnableMiningAOE", value: true, "Enable AOE mining skill changes."); ChanceForAOEOnHit = BindServerConfig("Mining", "ChanceForAOEOnHit", 0.3f, "Once AOE Mining is enabled, this is the chance for it to activate on any hit", advanced: false, 0f, 1f); ChanceForAOEOnHitScalesWithSkill = BindServerConfig("Mining", "ChanceForAOEOnHitScalesWithSkill", value: true, "Increases your chance for an AOE strike based on player skill"); MiningAOERange = BindServerConfig("Mining", "MiningAOERange", 2f, "How far away the mining AOE is applied. How far away an AOE hit is applied.", advanced: false, 0.5f, 10f); MiningAOELevel = BindServerConfig("Mining", "MiningAOELevel", 50f, "The level that AOE mining requires to activate. What skill level Mining AOE is enabled at.", advanced: false, 0f, 100f); EnableMiningRockBreaker = BindServerConfig("Mining", "EnableMiningRockBreaker", value: true, "Enable mining whole veins, by a (small) chance."); RockBreakerMaxChance = BindServerConfig("Mining", "RockBreakerMaxChance", 0.05f, "The maximum chance to break a whole vein. 0.05 is 5% chance to break a whole vein at level 100. This is checked on each hit.", advanced: false, 0f, 1f); RockBreakerRequiredLevel = BindServerConfig("Mining", "RockBreakerRequiredLevel", 75, "The level that vein breaking requires to activate. What skill level whole rocks breaking is enabled at.", advanced: false, 0, 100); RockBreakerDamage = BindServerConfig("Mining", "RockBreakerDamage", 300f, "Veinbreakers damage, small damage numbers will mean triggering this will not destroy a whole vein, but massively weaken it. Large numbers will ensure the whole vein is destroyed.", advanced: false, 0f, 10000f); MinehitsPerInterval = BindServerConfig("Mining", "MinehitsPerInterval", 2, "The number of pieces per interval to break when mining large rocks.", advanced: true, 1, 100); SkillLevelBonusEnabledForMiningDropChance = BindServerConfig("Mining", "SkillLevelBonusEnabledForMiningDropChance", value: false, "Pickaxes skill level provides a bonus to drop chance for drops that are not gaurenteed (This can significantly increase muddy scrap-pile drops)."); SkipNonRockDropIncreases = BindServerConfig("Mining", "SkipNonRockDropIncreases", value: true, "When enabled, only ores/rocks will get the increased drops, this primarily impacts muddy scrap piles in vanilla."); SkipNonRockDropPrefabs = BindServerConfig("Mining", "SkipNonRockDropPrefabs", "LeatherScraps,WitheredBone", "List of prefabs which will not recieve increased mining drops. Should be comma seperated without spaces."); ReducedChanceDropsForLowAmountDrops = BindServerConfig("Mining", "ReducedChanceDropsForLowAmountDrops", value: false, "When Enabled, drops that have an amount increase below 1 will only have a chance to happen instead of being rounded up to 1, and always happening."); FractionalDropsAsChance = BindServerConfig("Mining", "FractionalDropsAsChance", value: true, "When enabled, drops that are less than 1 become a chance to drop one. When disabled drops below 1 will never result in drops."); DistanceMiningDropMultiplierChecks = BindServerConfig("Mining", "DistanceMiningDropMultiplierChecks", 20f, "How far away the loot multiplier will check when rocks are destroyed. Increasing this significantly can cause a performance impact.", advanced: true, 10f, 100f); RockbreakerSafetyResetTimeout = BindServerConfig("Mining", "RockbreakerSafetyResetTimeout", 30f, "How long to wait before re-enabling rock breaker after its last activation.", advanced: true, 10f, 120f); EnableRun = BindServerConfig("Run", "EnableRun", value: true, "Enable run skill changes."); RunSpeedFactor = BindServerConfig("Run", "RunSpeedFactor", 0.005f, "How much the run speed is increased based on your run level. Amount applied per level, 0.005 will make level 100 run give 50% faster running.", advanced: false, 0.001f, 0.06f); EnableJump = BindServerConfig("Jump", "EnableJump", value: true, "Enable jump skill changes."); JumpHeightFactor = BindServerConfig("Jump", "JumpHeightFactor", 125f, "Percentage of original jump height at skill level 100. 100 = no change, 50 = half height, 200 = double height.", advanced: false, 50f, 300f); JumpHeightRequiredLevel = BindServerConfig("Jump", "JumpHeightRequiredLevel", 10f, "Minimum jump skill level required to gain jump height bonuses.", advanced: false, 0f, 100f); EnableFallDamageReduction = BindServerConfig("Jump", "EnableFallDamageReduction", value: true, "Enable fall damage reduction based on jump skill."); FallDamageReductionFactor = BindServerConfig("Jump", "FallDamageReductionFactor", 0.5f, "How much fall damage is reduced at skill level 100. 0.5 means 50% reduction at max level.", advanced: false, 0f, 1f); FallDamageReductionRequiredLevel = BindServerConfig("Jump", "FallDamageReductionRequiredLevel", 15f, "Minimum jump skill level required to gain fall damage reduction.", advanced: false, 0f, 100f); EnableFallDamageHeightBonus = BindServerConfig("Jump", "EnableFallDamageHeightBonus", value: true, "Enables Jump skill impacting the distance you can fall without recieving any fall damage."); FallDamageHeightRequiredLevel = BindServerConfig("Jump", "FallDamageHeightRequiredLevel", 25f, "The required level to start getting an increase to the height at which you will not recieve any fall damage.", advanced: false, 0f, 100f); FallDamageHeightBonus = BindServerConfig("Jump", "FallDamageHeightBonus", 3f, "Bonus to max fall height before taking damage at skill level 100 (meters). Scales with skill level (default is 4, and this is added to that).", advanced: false, 0f, 50f); EnableCooking = BindServerConfig("Cooking", "EnableCooking", value: true, "Enable cooking skill changes."); CookingBurnReduction = BindServerConfig("Cooking", "CookingBurnReduction", 0.5f, "How much offset is applied to diminishing returns for food, scaled by the players cooking skill. At 1 and cooking 100 food never degrades.", advanced: false, 0.1f, 1f); EnableHauling = BindServerConfig("Hauling", "EnableHauling", value: true, "Enables the hauling skill."); EnableCarryWeightBonus = BindServerConfig("Hauling", "EnableCarryWeightBonus", value: true, "Enables the carry weight bonus from the hauling skill."); HaulingMaxWeightBonus = BindServerConfig("Hauling", "HaulingMaxWeightBonus", 50f, "The maximum carry weight bonus from the hauling skill (the value you get at skill level 100).", advanced: false, 0f, 300f); EnableHaulingCartMassReduction = BindServerConfig("Hauling", "EnableHaulingCartMassReduction", value: true, "Enables mass reduction for the cart (this makes the cart easier to move when heavily loaded)."); HaulingCartMassReduction = BindServerConfig("Hauling", "HaulingCartMassReduction", 0.8f, "The maximum reduction that a carts weight will recieve based on your hauling skill.", advanced: false, 0.01f, 1f); HaulingXPRate = BindServerConfig("Hauling", "HaulingXPRate", 0.1f, "The amount of XP that is gained each time with Hauling", advanced: false, 0.01f, 10f); HaulingXPCheckInterval = BindServerConfig("Hauling", "HaulingXPCheckInterval", 5, "The frequency that you can gain hauling skill while moving goods."); EnableBloodMagic = BindServerConfig("BloodMagic", "EnableBloodMagic", value: true, "Enable blood magic skill changes."); BloodMagicXPForShieldDamageRatio = BindServerConfig("BloodMagic", "BloodMagicXPForShieldDamageRatio", 50f, "How much XP is gained for shield damage. 50 is once every 50 damage.", advanced: false, 1f, 200f); BloodMagicXP = BindServerConfig("BloodMagic", "BloodMagicXP", 1f, "How much XP is gained, used by other blood magic skill settings.", advanced: false, 0.1f, 10f); EnableStealth = BindServerConfig("Sneak", "EnableStealth", value: true, "Enable sneak skill changes."); SneakSpeedFactor = BindServerConfig("Sneak", "SneakSpeedFactor", 0.03f, "How much sneak speed is increased based on your sneak level. Amount applied per level, 0.03 will make level 100 sneak give normal walkspeed while sneaking.", advanced: false, 0.001f, 0.06f); SneakNoiseReductionLevel = BindServerConfig("Sneak", "SneakNoiseReductionLevel", 50f, "The level at which noise reduction starts being applied based on your skill", advanced: false, 0f, 100f); SneakNoiseReductionFactor = BindServerConfig("Sneak", "SneakNoiseReductionFactor", 0.5f, "How much noise is reduced based on your sneak level. Amount applied per level, 0.5 will make level 100 sneak give 50% less noise.", advanced: false, 0.1f, 1f); EnableSneakBonusDamage = BindServerConfig("Sneak", "EnableSneakBonusDamage", value: true, "Enable sneak bonus damage changes."); SneakBackstabBonusLevel = BindServerConfig("Sneak", "SneakBackstabBonusLevel", 25, "The level at which backstab damage starts being applied based on your skill", advanced: false, 0, 100); SneakBackstabBonusFactor = BindServerConfig("Sneak", "SneakBackstabBonusFactor", 2f, "How much backstab damage is increased based on your sneak level. 1 is a 100% bonus backstab damage at skill level 100.", advanced: false, 0.1f, 10f); EnableAnimalWhisper = BindServerConfig("AnimalHandling", "EnableAnimalWhisper", value: true, "Enable animal handling skill changes."); AnimalTamingSpeedFactor = BindServerConfig("AnimalHandling", "AnimalTamingSpeedFactor", 6f, "How much your animal handling skill impacts taming speed. 6 is 6x taming speed at level 100 (5 minutes vs 30 minutes default)", advanced: false, 1f, 10f); TamedAnimalLootIncreaseFactor = BindServerConfig("AnimalHandling", "TamedAnimalLootIncreaseFactor", 3f, "How much the animal handling skill improves your loot from tamed creatures. 3 is 3x the loot at level 100", advanced: false, 1f, 10f); EnableBeeBonuses = BindServerConfig("AnimalHandling", "EnableBeeBonuses", value: true, "Enables Animal Handling bonuses related to Bees."); BetterBeesLevel = BindServerConfig("AnimalHandling", "BetterBeesLevel", 15, "The level at which Bee productivity traits kick in", advanced: false, 0, 100); BeeHoneyOutputIncreaseBySkill = BindServerConfig("AnimalHandling", "BeeHoneyOutputIncreaseBySkill", 1f, "At level 100 skill, and 1.0 this results in a 100% increase in honey gathered."); EnableBeeBiomeUnrestricted = BindServerConfig("AnimalHandling", "EnableBeeBiomeUnrestricted", value: true, "At the specified level, beeshives built by you can produce honey in any biome."); BeeBiomeUnrestrictedLevel = BindServerConfig("AnimalHandling", "BeeBiomeUnrestrictedLevel", 25, "At this level, if enabled, beehives built by you can produce honey in any biome.", advanced: false, 0, 100); BeeHarvestXP = BindServerConfig("AnimalHandling", "BeeHarvestXP", 2f, "The amount of xp for Animal handling provided by harvesting a single honey from a beehive", advanced: false, 0f, 20f); EnableGathering = BindServerConfig("Farming", "EnableGathering", value: true, "Enable gathering skill changes."); GatheringLuckFactor = BindServerConfig("Farming", "GatheringLuckFactor", 0.5f, "How much luck impacts gathering. Each level gives you a small chance to get better loot.", advanced: false, 0.1f, 5f); EnableGatheringAOE = BindServerConfig("Farming", "EnableGatheringAOE", value: true, "Enable AOE gathering skill changes."); GatheringRangeFactor = BindServerConfig("Farming", "GatheringRangeFactor", 5f, "AOE gathering range you have at level 100.", advanced: false, 3f, 25f); FarmingRangeRequiredLevel = BindServerConfig("Farming", "GatheringRangeRequiredLevel", 50, "The level that AOE gathering requires to activate.", advanced: false, 0, 100); GatheringLuckLevels = BindServerConfig("Farming", "GatheringLuckLevels", "30,50,70,90,100", "Higher values have a lower chance of dropping. Each comma seperated number entry (0-100) is a chance at an additional drop."); GatheringDisallowedItems = BindServerConfig("Farming", "GatheringDisallowedItems", "SurtlingCore,Flint,Wood,Branch,Stone,Amber,AmberPearl,Coins,Ruby,CryptRemains,Obsidian,Crystal,Pot_Shard,DragonEgg,DvergrLantern,DvergrMineTreasure,SulfurRock,VoltureEgg,Swordpiece,MoltenCore,Hairstrands,Tar,BlackCore", "Items which can be picked, but do not get a luck roll for multiple loot and will not be auto-picked."); EnableFarmingMultiPlant = BindServerConfig("Farming", "EnableFarmingMultiPlant", value: true, "Enables farming multi-planting"); FarmingMultiplantRequiredLevel = BindServerConfig("Farming", "FarmingMultiplantRequiredLevel", 25, "The level that Multiplant is enabled.", advanced: false, 0, 100); FarmingMultiplantMaxPlantedAtOnce = BindServerConfig("Farming", "FarmingMultiplantMaxPlantedAtOnce", 12, "The total number of plants that can be planted at once at maximum gathering."); FarmingMultiplantColumnCount = BindServerConfig("Farming", "FarmingMultiplantColumnCount", 4, "Maximum number of columns in the planting grid. The grid will form the closest square shape possible without exceeding this limit.", advanced: true, 1, 12); FarmingMultiPlantSnapToExisting = BindServerConfig("Farming", "FarmingMultiPlantSnapToExisting", value: true, "Automatically align new grid to nearby existing plants"); FarmingMultiPlantDistanceBufferModifier = BindServerConfig("Farming", "FarmingMultiPlantDistanceBufferModifier", 1.1f, "The increased distance that is applied to all plants requirements to ensure that they do not become unhealthy."); FarmingMultiPlantBufferSpace = BindServerConfig("Farming", "FarmingMultiPlantBufferSpace", 0.2f, "Additional space for all multiplanted plants to ensure they are healthy.", advanced: true, 0f, 5f); PlantingCostStaminaReduction = BindServerConfig("Farming", "PlantingCostStaminaReduction", 0.5f, "At max level, the percentage reduction in stamina cost when placing.", advanced: true, 0f, 1f); PlantingSnapDistance = BindServerConfig("Farming", "PlantingSnapDistance", 1f, "The distance that is checked for other plants to attempt to snap to.", advanced: true, 0f, 10f); PlantingAOEHarvestResetSafety = BindServerConfig("Farming", "PlantingAOEHarvestResetSafety", 10f, "The number of seconds after an AOE harvest that harvesting will be re-enabled, even if it failed to reset."); FarmingSnapStyle = BindServerConfig("Farming", "FarmingSnapStyle", "Grid", "'Grid' detects the existing grid pattern and aligns to it; 'Legacy' snaps to the nearest plant position only.", new AcceptableValueList(new string[2] { "Grid", "Legacy" }), advanced: true); FarmingSnapPreferCardinal = BindServerConfig("Farming", "FarmingSnapPreferCardinal", value: true, "When using Grid snapping, prefer axis-aligned (N/S/E/W) snap candidates over diagonal ones.", null, advanced: true); EnableSnappingToOtherPlants = BindServerConfig("Farming", "EnableSnappingToOtherPlants", value: true, "When enabled, allows plant grid snapping to plants which are not the same kind as the currently planting one"); EnableVoyager = BindServerConfig("Voyager", "EnableVoyager", value: true, "Enable voyager skill changes."); VoyagerSkillXPCheckFrequency = BindServerConfig("Voyager", "VoyagerSkillXPCheckFrequency", 5, "How often Voyager skill can be increased while sailing. Rate varies based on your game physics engine speed.", advanced: false, 5, 200); VoyagerReduceCuttingStart = BindServerConfig("Voyager", "VoyagerReduceCuttingStart", 50f, "The level that the player starts to reduce the penalty of not having the wind at your back.", advanced: false, 0f, 100f); VoyagerSailingSpeedFactor = BindServerConfig("Voyager", "VoyagerSailingSpeedFactor", 1.5f, "How much the sailing speed is increased based on your voyager level. Amount applied per level, 2 will make level 100 voyager give 100% faster sailing.", advanced: false, 1f, 20f); VoyagerIncreaseExplorationRadius = BindServerConfig("Voyager", "VoyagerIncreaseExplorationRadius", 3f, "How much the exploration radius is increased based on your voyager level. Amount applied per level, 1 will make level 100 voyager give 100% more exploration radius.", advanced: false, 0f, 20f); VoyagerPaddleSpeedBonus = BindServerConfig("Voyager", "VoyagerPaddleSpeedBonus", 2f, "How much the paddle speed is increased based on your voyager level. 1 is a 100% bonus at level 100", advanced: false, 0.01f, 5f); VoyagerPaddleSpeedBonusLevel = BindServerConfig("Voyager", "VoyagerPaddleSpeedBonusLevel", 25f, "The level that the player starts to get a bonus to paddle speed.", advanced: false, 0f, 100f); EnableFriendsRowSpeedBonus = BindServerConfig("Voyager", "EnableFriendsRowSpeedBonus", value: true, "Whether or not friends attached to the ship will provide a 'rowing' speed bonus."); MaxFriendsRowSpeedBonus = BindServerConfig("Voyager", "MaxFriendsRowSpeedBonus", 0.25f, "The maximum speed bonus percent that each player can contribute. Players contribution is based on their own Voyager skill level.", advanced: false, 0f, 2f); EnableBoatDamageReduction = BindServerConfig("Voyager", "EnableBoatDamageReduction", value: true, "Enable to reduce damage to your boat as Voyager skill level increases."); VoyagerDamageReductionAmount = BindServerConfig("Voyager", "VoyagerDamageReductionAmount", 0.9f, "The maximum percentage of damage reduction, at level 100 skill. Scaled to skill. 1 is 100% damage reduction at player skill level 100.", advanced: false, 0f, 1f); BoatDamageReductionLevel = BindServerConfig("Voyager", "BoatDamageReductionLevel", 35, "The level at which you start to recieve a damage reduction from damage taken while on the boat"); VoyagerImpactResistance = BindServerConfig("Voyager", "VoyagerImpactResistance", value: true, "Whether or not impact resistance is enabled."); VoyagerImpactResistanceLevel = BindServerConfig("Voyager", "VoyagerImpactResistanceLevel", 75, "The level at which impact resistance is enabled. This prevents the ship from taking damage when it bumps into something."); EnableWeaponSkill = BindServerConfig("WeaponSkills", "EnableWeaponSkill", value: true, "Enable weapon skill changes."); WeaponSkillStaminaReduction = BindServerConfig("WeaponSkills", "WeaponSkillStaminaReduction", 0.5f, "How much stamina is reduced based on your weapon skill level at level 100. 0.5 will make level 100 weapon skill give 50% less stamina cost.", advanced: false, 0f, 1f); WeaponSkillParryBonus = BindServerConfig("WeaponSkills", "WeaponSkillParryBonus", 1f, "How much extra XP you get for parrying an attack", advanced: false, 0f, 10f); WeaponSkillBowDrawStaminaCostReduction = BindServerConfig("WeaponSkills", "WeaponSkillBowDrawStaminaCostReduction", 0.5f, "How much stamina is reduced based on your weapon skill level at level 100. 0.5 will make level 100 weapon skill give 50% less stamina cost. Vanilla is .33", advanced: false, 0f, 1f); WeaponSkillEquipRequiredLevel = BindServerConfig("WeaponSkills", "WeaponSkillEquipRequiredLevel", 45, "The level that equip speed bonuses start being applied based on your skill", advanced: true, 0, 100); WeaponSkillEquipSpeedFactor = BindServerConfig("WeaponSkills", "WeaponSkillEquipSpeedFactor", 2f, "How much faster your equipment is equipped based on your weapon skill.", advanced: true, 0f, 20f); EnableBlocking = BindServerConfig("Blocking", "EnableBlocking", value: true, "Enable blocking skill changes."); BlockPowerRequiredLevel = BindServerConfig("Blocking", "BlockPowerRequiredLevel", 25, "The level that BlockPowerFactor start being applied based on your skill", advanced: true, 0, 100); BlockPowerFactor = BindServerConfig("Blocking", "BlockPowerFactor", 0.75f, "The factor that blocking power increases after reaching the BlockRequiredLevel. Vanilla is .5f", advanced: true, 0.5f, 2f); BlockStaminaGainRequiredLevel = BindServerConfig("Blocking", "BlockStaminaGainRequiredLevel", 40, "The level that BlockStaminaGainFactor starts being applied base on your skill", advanced: true, 0, 100); BlockStaminaGainFactor = BindServerConfig("Blocking", "BlockStaminaGainFactor", 0.5f, "How much block stamina is returned based on your blocking level. This is modified by your characters blocking level. At level 100 you gain twice your block stamina use's stamina", advanced: true, 0.5f, 2f); EnableParryStaminaGain = BindServerConfig("Blocking", "EnableParryStaminaGain", value: false, "Enable stamina gain on parry. Value based off BlockStaminaGainFactor"); EnableCrafting = BindServerConfig("Crafting", "EnableCrafting", value: true, "Enable crafting skill changes."); EnableDurabilityLossPrevention = BindServerConfig("Crafting", "EnableDurabilityLossPrevention", value: true, "Enables durability reduction prevention that can scale with player skill."); EnableDurabilitySaves = BindServerConfig("Crafting", "EnableDurabilitySaves", value: true, "Enables reducing how often you use durability for your items."); DurabilitySaveLevel = BindServerConfig("Crafting", "DurabilitySaveLevel", 25, "Level requirement to enable durability saves."); ChanceForDurabilityLossPrevention = BindServerConfig("Crafting", "ChanceForDurabilityLossPrevention", 0.25f, "Chance that you will not use durability on use.", advanced: false, 0f, 1f); ScaleDurabilitySaveBySkillLevel = BindServerConfig("Crafting", "ScaleDurabilitySaveBySkillLevel", value: true, "Reduces MaxChanceForDurabilityPreserveOnUse based on level, at lvl 50 crafting MaxChanceForDurabilityPreserveOnUse is 50% of its value."); EnableBonusItemCrafting = BindServerConfig("Crafting", "EnableBonusItemCrafting", value: true, "Enables crafting bonus items."); CraftingBonusCraftsLevel = BindServerConfig("Crafting", "CraftingBonusCraftsLevel", 50, "The level at which you can start getting bonus crafts.", advanced: false, 0, 100); CraftingMaxBonus = BindServerConfig("Crafting", "CraftingMaxBonus", 3, "The maximum number of additional bonus crafts you can get from crafting an item"); CraftingBonusChance = BindServerConfig("Crafting", "CraftingBonusChance", 0.3f, "The chance to get a bonus craft when crafting an item. 0.5 is a 50% chance to get a bonus craft at level 100. Bonus crafting success can stack up to the CraftingMaxBonus times.", advanced: false, 0f, 1f); EnableCraftBonusAsFraction = BindServerConfig("Crafting", "EnableCraftBonusAsFraction", value: true, "Enable crafting bonus as a fraction of the number crafted (for recipes where the result is more than 1). If disabled, the bonus is always 1 item."); CraftBonusFractionOfCraftNumber = BindServerConfig("Crafting", "CraftBonusFractionOfCraftNumber", 0.25f, "If the number of items crafted by the recipe is greater than 1, a percentage of the number crafted is used for the bonus. This determines that percentage. Eg: craft 20 arrows (1 craft) a .25 value would give you 5 arrows for 1 bonus craft."); EnableMaterialReturns = BindServerConfig("Crafting", "EnableMaterialReturns", value: true, "Enable material returns from crafting."); CraftingMaterialReturnsLevel = BindServerConfig("Crafting", "CraftingMaterialReturnsLevel", 75, "The level at which material returns start being applied based on your skill", advanced: false, 0, 100); MaxCraftingMaterialReturnPercent = BindServerConfig("Crafting", "MaxCraftingMaterialReturnPercent", 0.3f, "The maximum percentage of materials that can be returned from crafting. 0.5 is 50% at level 100.", advanced: false, 0f, 1f); ChanceForMaterialReturn = BindServerConfig("Crafting", "ChanceForMaterialReturn", 0.15f, "The chance to return materials when crafting an item. 0.25 is a 25% chance to return materials at level 100.", advanced: false, 0f, 1f); EnableCooking = BindServerConfig("Cooking", "EnableCooking", value: true, "Enable cooking skill changes."); EnableCookingBonusItems = BindServerConfig("Cooking", "EnableCookingBonusItems", value: true, "Enables or disables getting bonuse food items."); RequiredLevelForBonusCookingItems = BindServerConfig("Cooking", "RequiredLevelForBonusCookingItems", 10, "Minimum level to start crafting bonus food items.", advanced: false, 0, 100); ChanceForCookingBonusItems = BindServerConfig("Cooking", "ChanceForCookingBonusItems", 0.4f, "The chance to craft bonus food items at level 100. 0.4 is a 40% chance.", advanced: false, 0f, 1f); CookingBonusItemMaxAmount = BindServerConfig("Cooking", "CookingBonusItemMaxAmount", 3, "The maximum number of cooked items you can recieve as a bonus, each item is an additional chance roll", advanced: true, 0, 10); CookingBurnReduction = BindServerConfig("Cooking", "CookingBurnReduction", 0.5f, "How much offset is applied to diminishing returns for food, scaled by the players cooking skill. At 1 and cooking 100 food never degrades.", advanced: false, 0.1f, 1f); EnableKnowledgeSharing = BindServerConfig("SkillRates", "EnableKnowledgeSharing", value: true, "Enable shared knowledge, this allows you to gain faster experiance in low skills if you already have other high skills (eg switching primary weapon skill)."); AnimalTamingSkillGainRate = BindServerConfig("SkillRates", "AnimalTamingSkillGainRate", 1f, "How fast the skill is gained.", advanced: false, 1f, 50f); VoyagerSkillGainRate = BindServerConfig("SkillRates", "VoyagerSkillGainRate", 4f, "How fast the skill is gained.", advanced: false, 1f, 50f); SharedKnowledgeSkillBonusRate = BindServerConfig("SkillRates", "SharedKnowledgeSkillBonusRate", 1.5f, "How strong at maximum the xp bonus from shared knowledge will be when catching up skills lower than your highest.", advanced: false, 0f, 10f); SharedKnowledgeCap = BindServerConfig("SkillRates", "SharedKnowledgeCap", 5f, "The number of levels below your maximum skill that shared knowledge stops providing a bonus at. Eg: max skill 90, at 5 any skills 85+ will not recieve an xp bonus.", advanced: true, 0f, 50f); SharedKnowledgeIgnoreList = BindServerConfig("SkillRates", "SharedKnowledgeIgnoreList", "", "Comma separated list of skills to ignore when calculating shared knowledge. This is useful for skills that have vastly different XP curves or that you simply do not want an accelerated growth rate in. Invalid skill names will be ignored."); SharedKnowledgeIgnoreList.SettingChanged += SharedKnowledge.UnallowedSharedXPSkillTypesChanged; EnableSwimming = BindServerConfig("Swimming", "EnableSwimming", value: true, "Enable swimming skill changes."); EnableSwimStaminaCostReduction = BindServerConfig("Swimming", "EnableSwimStaminaCostReduction", value: true, "Enables swim stamina cost reduction, at the level specified by SwimStaminaReductionLevel."); SwimSpeedRequiredLevel = BindServerConfig("Swimming", "SwimSpeedRequiredLevel", 25, "The level that swimming speed increases start being applied based on your skill", advanced: false, 0, 100); SwimmingSpeedFactor = BindServerConfig("Swimming", "SwimmingSpeedFactor", 3f, "How much swimming speed is increased based on your swimming level. This is modified by your characters swimming level. At skill level 100 the full value is in effect.", advanced: false, 0.1f, 10f); SwimStaminaReductionLevel = BindServerConfig("Swimming", "SwimStaminaReductionLevel", 50, "The level that swim stamina cost reductions start being applied based on your skill", advanced: false, 0, 100); SwimStaminaCostReductionFactor = BindServerConfig("Swimming", "SwimStaminaCostReductionFactor", 0.5f, "How much swim stamina cost is reduced based on your swimming level. This is modified by your characters swimming level. At skill level 100 the full value is in effect.", advanced: false, 0.1f, 1f); PreferOtherPlantGrid = BindServerConfig("Mod Compatibility", "PreferOtherPlantGrid", value: true, "When enabled, and an other planting grid mod is enabled (), Impactful skills planting grid will be disabled."); } internal static void SetupMainFileWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher.Path = Path.GetDirectoryName(cfg.ConfigFilePath); fileSystemWatcher.Filter = "MidnightsFX.ImpactfulSkills.cfg"; fileSystemWatcher.Changed += OnConfigFileChanged; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { if (ZNet.instance.IsServer()) { Logger.LogInfo("Configuration file has been changed, reloading settings."); cfg.Reload(); } } public static ConfigEntry BindServerConfig(string catagory, string key, float[] value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry BindServerConfig(string catagory, string key, bool value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry BindServerConfig(string catagory, string key, int value, string description, bool advanced = false, int valmin = 0, int valmax = 150) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry BindServerConfig(string catagory, string key, float value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry BindServerConfig(string catagory, string key, string value, string description, AcceptableValueList acceptableValues = null, bool advanced = false) { //IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } } internal class Logger { public static LogLevel Level = (LogLevel)16; public static void enableDebugLogging(object sender, EventArgs e) { //IL_0016: 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) if (ValConfig.EnableDebugMode.Value) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void setDebugLogging(bool state) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (state) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void LogDebug(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { ImpactfulSkills.Log.LogInfo((object)message); } } public static void LogInfo(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { ImpactfulSkills.Log.LogInfo((object)message); } } public static void LogWarning(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { ImpactfulSkills.Log.LogWarning((object)message); } } public static void LogError(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 2) { ImpactfulSkills.Log.LogError((object)message); } } } [BepInPlugin("MidnightsFX.ImpactfulSkills", "ImpactfulSkills", "0.9.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class ImpactfulSkills : BaseUnityPlugin { public const string PluginGUID = "MidnightsFX.ImpactfulSkills"; public const string PluginName = "ImpactfulSkills"; public const string PluginVersion = "0.9.0"; public ValConfig cfg; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); internal static AssetBundle EmbeddedResourceBundle; public static ManualLogSource Log; public void Awake() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; cfg = new ValConfig(((BaseUnityPlugin)this).Config); EmbeddedResourceBundle = AssetUtils.LoadAssetBundleFromResources("ImpactfulSkills.AssetsEmbedded.impactfulskills", typeof(ImpactfulSkills).Assembly); AddLocalizations(); Gathering.SetupGatherables(); Mining.SetupMining(); AnimalWhisper.SetupAnimalSkill(); Voyaging.SetupSailingSkill(); Hauling.SetupHaulingSkill(); Modcheck.CheckModCompat(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); new Harmony("MidnightsFX.ImpactfulSkills").PatchAll(executingAssembly); } private void AddLocalizations() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading Localizations."); string[] manifestResourceNames = typeof(ImpactfulSkills).Assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.Contains("Localizations")) { string text2 = Regex.Replace(ReadEmbeddedResourceFile(text), "\\/\\/.*", ""); string[] array = text.Split(new char[1] { '.' }); ((BaseUnityPlugin)this).Logger.LogDebug((object)("Adding localization: " + array[2])); localization.AddJsonFile(array[2], text2); } } } internal static string ReadEmbeddedResourceFile(string filename) { using Stream stream = typeof(ImpactfulSkills).Assembly.GetManifestResourceStream(filename); using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } } } namespace ImpactfulSkills.modules.Multiplant { internal class Plantable { public float GrowRadius { get; set; } public GameObject Refgo { get; set; } public List Seeds { get; set; } } internal static class PlantDefinitions { [HarmonyPriority(100)] [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class Patch_ZNetScene_Awake { private static void Postfix() { BuildPlantRequirements(); } } internal static Dictionary PlantableDefinitions = new Dictionary(); internal static int plantSpaceMask = 0; internal static int GhostLayer = 0; internal static void BuildPlantRequirements() { PlantableDefinitions.Clear(); if ((Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null) { Logger.LogWarning("ZNetScene not ready for plant definitions"); return; } foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { Plant component = prefab.GetComponent(); if ((Object)(object)component == (Object)null || PlantableDefinitions.ContainsKey(((Object)prefab).name)) { continue; } List list = new List(); Piece component2 = prefab.GetComponent(); if ((Object)(object)component2 != (Object)null) { Requirement[] resources = component2.m_resources; foreach (Requirement item in resources) { list.Add(item); } } PlantableDefinitions.Add(((Object)prefab).name, new Plantable { GrowRadius = component.m_growRadius, Refgo = prefab, Seeds = list }); GameObject[] grownPrefabs = component.m_grownPrefabs; foreach (GameObject val in grownPrefabs) { if (!PlantableDefinitions.ContainsKey(((Object)val).name)) { PlantableDefinitions.Add(((Object)val).name, new Plantable { Refgo = val, GrowRadius = component.m_growRadius }); } } Logger.LogDebug("Added plant cache entry: " + ((Object)prefab).name); } plantSpaceMask = LayerMask.GetMask(new string[4] { "static_solid", "Default_small", "piece", "piece_nonsolid" }); GhostLayer = LayerMask.NameToLayer("ghost"); Logger.LogInfo($"Loaded {PlantableDefinitions.Count} plantable definitions"); } } internal static class PlantGhostController { internal static readonly List ExtraGhosts = new List(); internal static readonly List GhostValid = new List(); private static readonly int _ghostLayer = LayerMask.NameToLayer("ghost"); private static string _lastPlantName = ""; private static bool _preservePool; private static int MaxActiveGhosts => PlantGrid.MaxToPlantAtOnce() - 1; private static int TotalCells => 1 + MaxActiveGhosts; private static int Columns => Mathf.Clamp(Mathf.CeilToInt(Mathf.Sqrt((float)TotalCells)), 1, ValConfig.FarmingMultiplantColumnCount.Value); internal static void Prepare(GameObject rootGhost) { if ((Object)(object)rootGhost == (Object)null) { DestroyPool(); return; } DetectPlantChange(rootGhost); if (!ShouldPreservePool()) { DestroyPool(); } } internal static void BuildGrid(GameObject rootGhost) { GrowPoolIfNeeded(rootGhost); InitializeGhosts(rootGhost); DeactivateExcess(); PlantGrid.GridPlantingActive = true; } internal static void DestroyPool() { foreach (GameObject extraGhost in ExtraGhosts) { if ((Object)(object)extraGhost != (Object)null) { Object.Destroy((Object)(object)extraGhost); } } ExtraGhosts.Clear(); GhostValid.Clear(); PlantGrid.GridPlantingActive = false; SnapSystem.ResetSnap(); PlantGridState.ResetSavedOrientation(); } internal static void Update() { UpdateVisibility(); if (!((Object)(object)PlantGridState.PlacementGhost == (Object)null)) { int columns = Columns; UpdateGhost(0, 0, 0); for (int i = 1; i < TotalCells && i - 1 < ExtraGhosts.Count; i++) { UpdateGhost(i / columns, i % columns, i); } } } private static void GrowPoolIfNeeded(GameObject rootGhost) { string name = ((Object)rootGhost).name; while (ExtraGhosts.Count < MaxActiveGhosts) { ZNetView.m_forceDisableInit = true; GameObject val = Object.Instantiate(rootGhost); ZNetView.m_forceDisableInit = false; ((Object)val).name = name; Transform[] componentsInChildren = val.GetComponentsInChildren(); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.layer = _ghostLayer; } ExtraGhosts.Add(val); } } private static void InitializeGhosts(GameObject rootGhost) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) GhostValid.Clear(); GhostValid.Add(item: true); Transform transform = rootGhost.transform; for (int i = 0; i < MaxActiveGhosts && i < ExtraGhosts.Count; i++) { GameObject obj = ExtraGhosts[i]; obj.SetActive(true); obj.transform.position = transform.position; obj.transform.localScale = transform.localScale; GhostValid.Add(item: true); } } private static void DeactivateExcess() { for (int i = MaxActiveGhosts; i < ExtraGhosts.Count; i++) { ExtraGhosts[i].SetActive(false); } } private static void UpdateVisibility() { bool flag = (Object)(object)PlantGridState.PlacementGhost != (Object)null && PlantGridState.PlacementGhost.activeSelf; for (int i = 0; i < ExtraGhosts.Count; i++) { bool flag2 = flag && i < MaxActiveGhosts; if (ExtraGhosts[i].activeSelf != flag2) { ExtraGhosts[i].SetActive(flag2); } } } private static void UpdateGhost(int row, int col, int index) { //IL_003d: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0074: 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) GameObject ghost = GetGhost(index); if (!((Object)(object)ghost == (Object)null)) { Vector3 val = ((index == 0) ? PlantGridState.BasePosition : (PlantGridState.BasePosition + PlantGridState.RowDirection * (float)row + PlantGridState.ColumnDirection * (float)col)); float y = default(float); Heightmap.GetHeight(val, ref y); val.y = y; ghost.transform.position = val; if (index > 0) { ghost.transform.rotation = Quaternion.identity; } bool flag = IsValidPosition(val); Piece component = ghost.GetComponent(); if (component != null) { component.SetInvalidPlacementHeightlight(!flag); } if (index < GhostValid.Count) { GhostValid[index] = flag; } } } private static GameObject GetGhost(int index) { if (index == 0) { return PlantGridState.PlacementGhost; } int num = index - 1; if (num >= ExtraGhosts.Count) { return null; } return ExtraGhosts[num]; } internal static bool IsValidPosition(Vector3 pos) { //IL_0000: 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) //IL_002c: Unknown result type (might be due to invalid IL or missing references) Heightmap val = Heightmap.FindHeightmap(pos); if ((Object)(object)val == (Object)null || (Object)(object)PlantGridState.Plant == (Object)null) { return false; } if (PlantGridState.Plant.m_needCultivatedGround && !val.IsCultivated(pos)) { return false; } return Physics.OverlapSphere(pos, PlantGridState.Plant.m_growRadius, Plant.m_spaceMask).Length == 0; } private static void DetectPlantChange(GameObject rootGhost) { string name = ((Object)rootGhost).name; if (name == _lastPlantName) { _preservePool = true; return; } _lastPlantName = name; _preservePool = false; } private static bool ShouldPreservePool() { if (!_preservePool || !PlantGrid.GridPlantingActive) { return false; } _preservePool = false; return true; } } internal static class PlantGrid { [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] private static class PlayerSetupPlacementGhost { private static void Postfix(Player __instance) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) Quaternion? pendingGhostRotation = _pendingGhostRotation; _pendingGhostRotation = null; if (!ValConfig.EnableFarmingMultiPlant.Value || UseOtherPlantGridSystem || (Object)(object)__instance.m_placementGhost == (Object)null || !HoldingCultivator()) { PlantGhostController.DestroyPool(); PlantGridState.Clear(); return; } if (((Character)__instance).GetSkillLevel((SkillType)106) < (float)ValConfig.FarmingMultiplantRequiredLevel.Value) { PlantGhostController.DestroyPool(); PlantGridState.Clear(); return; } if (!IsPlantable(__instance.m_placementGhost)) { PlantGhostController.DestroyPool(); PlantGridState.Clear(); return; } Plant component = __instance.m_placementGhost.GetComponent(); if ((Object)(object)component != (Object)null) { Spacing = component.m_growRadius * ValConfig.FarmingMultiPlantDistanceBufferModifier.Value + ValConfig.FarmingMultiPlantBufferSpace.Value; } PlantGridState.SetReferences(__instance.m_placementGhost); PlantGhostController.Prepare(__instance.m_placementGhost); PlantGhostController.BuildGrid(__instance.m_placementGhost); if (pendingGhostRotation.HasValue) { RestorePlaceRotation(__instance, pendingGhostRotation.Value); } } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static class AdjustPlacementGhosts { private static void Postfix() { if (!GridPlantingActive || UseOtherPlantGridSystem || !HoldingCultivator()) { return; } if ((Object)(object)Player.m_localPlayer != (Object)null && ZInput.GetButtonDown("Crouch")) { MultiplantDisabled = !MultiplantDisabled; string text = (MultiplantDisabled ? Localization.instance.Localize("$multi_plant_disabled") : Localization.instance.Localize("$multi_plant_enabled")); ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null); } PlantGridState.Update(); if (MultiplantDisabled) { foreach (GameObject extraGhost in PlantGhostController.ExtraGhosts) { if ((Object)(object)extraGhost != (Object)null) { extraGhost.SetActive(false); } } return; } PlantGhostController.Update(); } } [HarmonyPatch(typeof(Player), "PlacePiece")] public static class PlaceMultiPlantPieces { private static void Postfix(Player __instance, Piece piece) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (GridPlantingActive && !UseOtherPlantGridSystem && IsPlantable(((Component)piece).gameObject)) { _pendingGhostRotation = PlantGridState.BaseRotation; PlantGhostsWithCosts(__instance, ((Component)piece).gameObject); } } } internal static bool GridPlantingActive = false; internal static bool MultiplantDisabled = false; internal static float Spacing = 0f; internal static int UserDefinedMax = ValConfig.FarmingMultiplantMaxPlantedAtOnce.Value; internal static bool UseOtherPlantGridSystem = IsOtherPlantGridSystemAvailable(); private static Quaternion? _pendingGhostRotation; public static bool IsOtherPlantGridSystemAvailable() { if (ValConfig.PreferOtherPlantGrid.Value && Modcheck.OtherFarmingGridModPresent()) { return true; } return false; } internal static int MaxToPlantAtOnce() { int num = Mathf.RoundToInt((float)ValConfig.FarmingMultiplantMaxPlantedAtOnce.Value * ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)106)); if (num <= 1) { return 1; } return num; } internal static bool HoldingCultivator() { if ((Object)(object)Player.m_localPlayer == (Object)null || ((Humanoid)Player.m_localPlayer).GetRightItem() == null) { return false; } return ((Humanoid)Player.m_localPlayer).GetRightItem().m_shared.m_name == "$item_cultivator"; } internal static bool IsPlantable(GameObject go) { return (Object)(object)go.GetComponent() != (Object)null; } internal static void PlantGhostsWithCosts(Player player, GameObject primaryPlantablePrefab) { //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) if (!GridPlantingActive || PlantGhostController.ExtraGhosts.Count == 0) { return; } Logger.LogDebug("Placing plants in grid"); int num = 0; string prefabName = Utils.GetPrefabName(primaryPlantablePrefab); Plantable plantable = PlantDefinitions.PlantableDefinitions[prefabName]; int num2 = 100; if (plantable.Seeds.Count > 0) { foreach (Requirement seed in plantable.Seeds) { int num3 = ((Humanoid)player).m_inventory.CountItems(seed.m_resItem.m_itemData.m_shared.m_name, -1, true) / seed.m_amount; if (num3 < num2) { num2 = num3; } } } Logger.LogDebug($"Resources support planting up to {num2}"); float num4 = 10f * (ValConfig.PlantingCostStaminaReduction.Value * ((Character)player).GetSkillFactor((SkillType)106) - 1f); float num5 = 0f; for (int i = 0; i < PlantGhostController.ExtraGhosts.Count; i++) { GameObject val = PlantGhostController.ExtraGhosts[i]; if (!val.activeSelf) { continue; } int num6 = i + 1; if (num6 < PlantGhostController.GhostValid.Count && PlantGhostController.GhostValid[num6]) { if (!((Character)player).HaveStamina(num5 + num4)) { Logger.LogDebug($"Not enough stamina to plant more (cost so far: {num5})"); break; } if (!player.NoCostCheat() && num2 == num + 1) { Logger.LogDebug($"Not enough resources for plant {num + 1}"); break; } num5 += num4; Object.Instantiate(primaryPlantablePrefab, val.transform.position, primaryPlantablePrefab.transform.rotation); num++; } } if (plantable.Seeds.Count > 0) { Logger.LogDebug("Removing seed costs"); foreach (Requirement seed2 in plantable.Seeds) { ((Humanoid)player).m_inventory.RemoveItem(seed2.m_resItem.m_itemData.m_shared.m_name, seed2.m_amount * num, -1, true); } } Logger.LogDebug("Applying stamina cost and XP."); ((Character)player).UseStamina(num5); ((Character)player).RaiseSkill((SkillType)106, (float)num); } private static void RestorePlaceRotation(Player player, Quaternion rotation) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) player.m_placeRotation = Mathf.RoundToInt(((Quaternion)(ref rotation)).eulerAngles.y / player.m_placeRotationDegrees); } } internal static class PlantGridState { internal static GameObject PlacementGhost; internal static Plant Plant; internal static Vector3 BasePosition; internal static Quaternion BaseRotation; internal static Quaternion FixedRotation; internal static Vector3 RowDirection; internal static Vector3 ColumnDirection; internal static bool AltPlacement; internal static Quaternion? SavedBaseRotation; internal static Vector3 SavedRowDirection; internal static Vector3 SavedColumnDirection; internal static void SetReferences(GameObject rootGhost) { PlacementGhost = rootGhost; Plant = rootGhost.GetComponent(); } internal static void Clear() { PlacementGhost = null; Plant = null; } internal static void Update() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)PlacementGhost == (Object)null)) { AltPlacement = ZInput.GetButton("AltPlace"); BasePosition = PlacementGhost.transform.position; BaseRotation = PlacementGhost.transform.rotation; Vector3 eulerAngles = ((Quaternion)(ref BaseRotation)).eulerAngles; eulerAngles.y = Mathf.Round(eulerAngles.y / 90f) * 90f; FixedRotation = Quaternion.Euler(eulerAngles); UpdateDirectionsAndSnap(); } } private static void UpdateDirectionsAndSnap() { //IL_0011: 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_0020: 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) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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) float spacing = PlantGrid.Spacing; string prefabName = Utils.GetPrefabName(PlacementGhost); RowDirection = BaseRotation * Vector3.forward; ColumnDirection = BaseRotation * Vector3.right; if (!ValConfig.FarmingMultiPlantSnapToExisting.Value || AltPlacement || !SnapSystem.FindSnapPoints(prefabName, spacing)) { if (SnapSystem.HasRotationChangedSinceSnap()) { ResetSavedOrientation(); } if (SavedRowDirection != Vector3.zero) { RowDirection = SavedRowDirection * spacing; ColumnDirection = SavedColumnDirection * spacing; } else { RowDirection *= spacing; ColumnDirection *= spacing; } } } internal static void ResetSavedOrientation() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) SavedBaseRotation = null; SavedRowDirection = Vector3.zero; SavedColumnDirection = Vector3.zero; } } internal class SnapPoint { internal Vector3 pos; internal Vector3 rowDir; internal Vector3 colDir; internal Vector3 origin; internal SnapPoint() { } internal SnapPoint(Vector3 pos, Vector3 rowDir, Vector3 colDir, Vector3 origin) { //IL_0007: 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_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_0016: 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_001e: Unknown result type (might be due to invalid IL or missing references) this.pos = pos; this.rowDir = rowDir; this.colDir = colDir; this.origin = origin; } } internal static class SnapSystem { private static readonly int _scanMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" }); private const int MaxPrimaries = 8; private static bool _hasLastSnap; private static Quaternion _lastGhostRotation; internal static void ResetSnap() { _hasLastSnap = false; } internal static bool HasRotationChangedSinceSnap() { //IL_0009: 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) if (!_hasLastSnap) { return false; } return Quaternion.Angle(PlantGridState.FixedRotation, _lastGhostRotation) > 11f; } internal static bool FindSnapPoints(string plantName, float pieceSpacing) { return TryFreeSnap(plantName, pieceSpacing); } private static bool TryFreeSnap(string plantName, float pieceSpacing) { //IL_0000: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) List list = ScanForPlants(PlantGridState.BasePosition, ValConfig.PlantingSnapDistance.Value, plantName); if (list.Count == 0) { return false; } Transform val = SortByDistance(list, PlantGridState.BasePosition); ComputeFreeDirections(val.position, pieceSpacing); List list2 = new List(); if (!GenerateCandidates(list2, val.position)) { return false; } SnapPoint snapPoint = FindNearestEuclidean(list2); CommitSnap(snapPoint); PlantGridState.RowDirection = ChooseDirection(snapPoint.pos, PlantGridState.RowDirection); PlantGridState.ColumnDirection = ChooseDirection(snapPoint.pos, PlantGridState.ColumnDirection); return true; } private static void ComputeFreeDirections(Vector3 target, float pieceSpacing) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_009e: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_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) Vector3 val = PlantGridState.BasePosition - target; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.001f) { val = Vector3.forward; } else { ((Vector3)(ref val)).Normalize(); if (!PlantGridState.AltPlacement) { float num = Vector3.SignedAngle(Vector3.forward, val, Vector3.up); val = Quaternion.Euler(0f, Mathf.Round(num / 90f) * 90f, 0f) * Vector3.forward; } } PlantGridState.RowDirection = PlantGridState.FixedRotation * val * pieceSpacing; PlantGridState.ColumnDirection = Vector3.Cross(Vector3.up, PlantGridState.RowDirection); } private static bool GenerateCandidates(List snapPoints, Vector3 fromPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_000b: 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_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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0029: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0076: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) Vector3 rowDirection = PlantGridState.RowDirection; Vector3 columnDirection = PlantGridState.ColumnDirection; Vector3[] obj = new Vector3[4] { fromPos + rowDirection, fromPos - rowDirection, fromPos + columnDirection, fromPos - columnDirection }; float magnitude = ((Vector3)(ref rowDirection)).magnitude; bool flag = false; List<(Vector3, bool)> list = new List<(Vector3, bool)>(); Vector3[] array = (Vector3[])(object)obj; foreach (Vector3 val in array) { if (!PositionHasCollisions(val)) { Vector3 val2 = val - fromPos; bool flag2 = Mathf.Abs(Vector3.Dot(val2, ((Vector3)(ref rowDirection)).normalized)) < magnitude * 0.25f || Mathf.Abs(Vector3.Dot(val2, ((Vector3)(ref columnDirection)).normalized)) < magnitude * 0.25f; list.Add((val, flag2)); if (flag2) { flag = true; } } } if (list.Count == 0) { return false; } bool flag3 = ValConfig.FarmingSnapPreferCardinal?.Value ?? true; foreach (var (pos, flag4) in list) { if (!flag3 || !flag || flag4) { snapPoints.Add(new SnapPoint(pos, rowDirection, columnDirection, fromPos)); } } return snapPoints.Count > 0; } private static void CommitSnap(SnapPoint snap) { //IL_0010: 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_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) //IL_0046: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) _hasLastSnap = true; _lastGhostRotation = PlantGridState.PlacementGhost.transform.rotation; if (!PlantGridState.SavedBaseRotation.HasValue) { PlantGridState.SavedBaseRotation = _lastGhostRotation; } Vector3 basePosition = (PlantGridState.PlacementGhost.transform.position = snap.pos); PlantGridState.BasePosition = basePosition; } private static SnapPoint FindNearestEuclidean(List snaps) { //IL_0009: 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) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) SnapPoint snapPoint = snaps[0]; Vector3 val = snapPoint.pos - PlantGridState.BasePosition; float num = ((Vector3)(ref val)).sqrMagnitude; for (int i = 1; i < snaps.Count; i++) { val = snaps[i].pos - PlantGridState.BasePosition; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; snapPoint = snaps[i]; } } return snapPoint; } private static bool PositionHasCollisions(Vector3 pos) { //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_0002: 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_0011: Unknown result type (might be due to invalid IL or missing references) return Physics.CheckCapsule(pos, pos + Vector3.up * 0.1f, Mathf.Epsilon, _scanMask); } private static Vector3 ChooseDirection(Vector3 origin, Vector3 direction) { //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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_000e: 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) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!PositionHasCollisions(origin + direction)) { return direction; } if (!PositionHasCollisions(origin - direction)) { return -direction; } return direction; } private static List ScanForPlants(Vector3 origin, float radius, string plantName) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(origin, radius, _scanMask); List list = new List(); HashSet hashSet = new HashSet(); Collider[] array2 = array; foreach (Collider val in array2) { if (((Component)val).gameObject.layer == PlantDefinitions.GhostLayer || (Object)(object)((Component)val).GetComponent() == (Object)null || (!ValConfig.EnableSnappingToOtherPlants.Value && Utils.GetPrefabName(((Component)val).gameObject) != plantName)) { continue; } Transform root = ((Component)val).transform.root; if (hashSet.Add(root)) { list.Add(root); if (list.Count >= 8) { break; } } } return list; } private static Transform SortByDistance(List list, Vector3 origin) { //IL_0020: 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) Transform result = list[0]; float num = 9999f; foreach (Transform item in list) { float num2 = VectorExtensions.DistanceTo(item.localPosition, origin); if (num2 < num) { result = item; num = num2; } } return result; } } } namespace ImpactfulSkills.patches { public static class AnimalWhisper { [HarmonyPatch(typeof(Tameable), "DecreaseRemainingTime")] public static class IncreaseTamingSpeed { private static void Prefix(Tameable __instance, ref float time) { //IL_0029: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableAnimalWhisper.Value && (Object)(object)Player.m_localPlayer != (Object)null && Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)__instance).transform.position) <= 30f) { float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor(AnimalHandling); float num = time * (skillFactor * ValConfig.AnimalTamingSpeedFactor.Value + 1f); Logger.LogDebug($"animal taming remaining time {time}, modified: {num}"); time = num; ((Character)Player.m_localPlayer).RaiseSkill(AnimalHandling, ValConfig.AnimalTamingSkillGainRate.Value); } } } [HarmonyPatch(typeof(Beehive), "RPC_Extract")] public static class BetterBeeProduction { public static void Prefix(Beehive __instance) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableBeeBonuses.Value && (Object)(object)Player.m_localPlayer != (Object)null) { int honeyLevel = __instance.GetHoneyLevel(); if (honeyLevel > 0) { ((Character)Player.m_localPlayer).RaiseSkill(AnimalHandling, (float)honeyLevel * ValConfig.BeeHarvestXP.Value); } } } } [HarmonyPatch(typeof(Beehive), "GetHoneyLevel")] public static class BeeHivesMoreProductionBySkill { public static void Postfix(ref int __result) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer != (Object)null && __result > 0 && ValConfig.EnableBeeBonuses.Value) { float num = ValConfig.BeeHoneyOutputIncreaseBySkill.Value * ((Character)Player.m_localPlayer).GetSkillFactor(AnimalHandling); __result = Mathf.RoundToInt((float)__result + num * (float)__result); } } } [HarmonyPatch(typeof(Beehive), "CheckBiome")] public static class BehivesInAnyBiome { public static bool Prefix(Beehive __instance, ref bool __result) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || !ValConfig.EnableBeeBiomeUnrestricted.Value) { return true; } if (__instance.m_nview.GetZDO() != null && __instance.m_nview.GetZDO().GetBool("IS_BHIVE", false)) { __result = true; return false; } if (__instance.m_nview.GetZDO() != null && ((Character)Player.m_localPlayer).GetSkillLevel(AnimalHandling) >= (float)ValConfig.BeeBiomeUnrestrictedLevel.Value) { __instance.m_nview.GetZDO().Set("IS_BHIVE", true); __result = true; return false; } return true; } } [HarmonyPatch(typeof(Tameable), "OnDeath")] public static class IncreaseTamedAnimalYield { private static void Postfix(Tameable __instance) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) if (!ValConfig.EnableAnimalWhisper.Value || !((Object)(object)Player.m_localPlayer != (Object)null) || !((Object)(object)__instance != (Object)null) || !(Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)__instance).transform.position) <= 20f)) { return; } Character component = ((Component)__instance).gameObject.GetComponent(); if (component == null || !component.m_tamed) { return; } ((Character)Player.m_localPlayer).RaiseSkill(AnimalHandling, 1f * ValConfig.AnimalTamingSkillGainRate.Value); CharacterDrop component2 = ((Component)__instance).gameObject.GetComponent(); if (!((Object)(object)component2 != (Object)null)) { return; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor(AnimalHandling); foreach (Drop drop in component2.m_drops) { int num = 0; float num2 = (float)drop.m_amountMin * (ValConfig.TamedAnimalLootIncreaseFactor.Value * (skillFactor * 100f)) / 100f; float num3 = (float)drop.m_amountMax * (ValConfig.TamedAnimalLootIncreaseFactor.Value * (skillFactor * 100f)) / 100f; if (num2 > 0f && num3 > 0f && num2 != num3) { num = Random.Range((int)num2, (int)num3); } else if (num2 == num3) { num = (int)Math.Round(num2, 0); } if (drop.m_chance == 1f || !(Random.value > drop.m_chance)) { Logger.LogDebug($"AnimalWhisper extra drops {num} {((Object)drop.m_prefab).name}"); Quaternion val = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f); for (int i = 0; i < num; i++) { Object.Instantiate(drop.m_prefab, ((Component)__instance).transform.position, val); } } } } } public static SkillType AnimalHandling; public static void SetupAnimalSkill() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_004d: 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) SkillConfig val = new SkillConfig(); val.Name = "$skill_AnimalHandling"; val.Description = "$skill_AnimalHandling_description"; val.Icon = ImpactfulSkills.EmbeddedResourceBundle.LoadAsset("Assets/Custom/Icons/skill_icons/animalWhisper.png"); val.Identifier = "midnightsfx.animalwhisper"; val.IncreaseStep = 0.1f; AnimalHandling = SkillManager.Instance.AddSkill(val); } } public static class Blocking { [HarmonyPatch(typeof(ItemData), "GetBlockPower", new Type[] { typeof(int), typeof(float) })] internal class BlockPower_Patch { [HarmonyPostfix] private static void Postfix(float skillFactor, ref float __result) { if (ValConfig.EnableBlocking.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && ((Character)Player.m_localPlayer).GetSkillLevel((SkillType)6) >= (float)ValConfig.BlockPowerRequiredLevel.Value) { float num = __result / (1f + skillFactor * 0.5f); __result = num + num * skillFactor * ValConfig.BlockPowerFactor.Value; } } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] internal class BlockStaminaGain_Patch { [HarmonyPostfix] private static void Postfix(Humanoid __instance, bool __result) { if (ValConfig.EnableBlocking.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && __result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { float skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel((SkillType)6); float blockTimer = __instance.m_blockTimer; bool flag = __instance.GetCurrentBlocker().m_shared.m_timedBlockBonus > 1f && blockTimer != -1f && blockTimer < 0.25f; if ((ValConfig.EnableParryStaminaGain.Value || !flag) && skillLevel >= (float)ValConfig.BlockStaminaGainRequiredLevel.Value) { float num = skillLevel / 100f * ValConfig.BlockStaminaGainFactor.Value * __instance.m_blockStaminaDrain; Logger.LogDebug($"Blocking returning stamina {num}, full cost: {__instance.m_blockStaminaDrain}"); ((Character)__instance).AddStamina(num); } } } } } public static class BloodMagic { [HarmonyPatch(typeof(SE_Shield), "OnDamaged")] public static class VoyagerSpeedPatch { private static void Prefix(HitData hit, Character attacker, SE_Shield __instance) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableBloodMagic.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && (friendly_factions.Contains(((StatusEffect)__instance).m_character.m_faction) || ((StatusEffect)__instance).m_character.m_tamed)) { shield_damage += hit.GetTotalDamage(); if (shield_damage > ValConfig.BloodMagicXPForShieldDamageRatio.Value) { float num = shield_damage / ValConfig.BloodMagicXPForShieldDamageRatio.Value; shield_damage = 0f; Logger.LogDebug("BloodMagic adding XP from shield damage: " + num); ((Character)Player.m_localPlayer).RaiseSkill((SkillType)10, num); } } } } private static float shield_damage = 0f; private static List friendly_factions = new List { (Faction)0, (Faction)11 }; } public static class Cooking { [HarmonyPatch(typeof(Player))] public static class CookEnjoysFoodLongerPatch { [HarmonyTranspiler] [HarmonyPatch("UpdateFood")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Div, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Mathf), "Clamp01", (Type[])null, (Type[])null), (string)null) }).RemoveInstructions(2).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)ClampFoodWithBonus) }) .ThrowIfNotMatch("Unable to patch Food degrading improvement.", Array.Empty()); return val.Instructions(); } public static float ClampFoodWithBonus(float food_time_remaining, float food_burn_time) { if (ValConfig.EnableCooking.Value && (Object)(object)Player.m_localPlayer != (Object)null) { float num = ValConfig.CookingBurnReduction.Value * ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)105); return Mathf.Clamp01(food_time_remaining / food_burn_time + num); } return Mathf.Clamp01(food_time_remaining / food_burn_time); } } } internal class Crafting { [HarmonyPatch(typeof(Humanoid))] public static class BlockDurabilityReduction { [HarmonyTranspiler] [HarmonyPatch("BlockAttack")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(SharedData), "m_useDurabilityDrain"), (string)null) }).Advance(1).RemoveInstructions(4) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)CheckAndReduceDurabilityCost) }) .ThrowIfNotMatch("Unable to patch Block Durability reduction.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(Attack))] public static class RangedAttackReduceDurabilityCost { [HarmonyTranspiler] [HarmonyPatch("ProjectileAttackTriggered")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(SharedData), "m_useDurabilityDrain"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)CheckAndReduceDurabilityCost) }) .ThrowIfNotMatch("Unable to patch Ranged attack durability reduction.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(Attack))] public static class MeleeAttackReduceDurabilityCost { [HarmonyTranspiler] [HarmonyPatch("DoMeleeAttack")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(SharedData), "m_useDurabilityDrain"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)CheckAndReduceDurabilityCost) }) .ThrowIfNotMatch("Unable to patch Melee attack durability reduction.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(Attack))] public static class DoNonAttackReduceDurabilityCost { [HarmonyTranspiler] [HarmonyPatch("DoNonAttack")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(SharedData), "m_useDurabilityDrain"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)CheckAndReduceDurabilityCost) }) .ThrowIfNotMatch("Unable to patch DoNonAttack durability reduction.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(InventoryGui))] public static class CraftingItemBonusDropsPatch { [HarmonyTranspiler] [HarmonyPatch("DoCrafting")] private static IEnumerable ConstructorTranspiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, generator); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[5] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_S, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldnull, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)null, (string)null) }).Advance(2).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_2, (object)null), Transpilers.EmitDelegate>((Func)CraftableBonus), new CodeInstruction(OpCodes.Stloc_2, (object)null) }) .CreateLabelOffset(out var label, 45) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Br, (object)label) }) .ThrowIfNotMatch("Unable to patch Crafting bonus.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(InventoryGui))] public static class CraftingItemRefundPatch { [HarmonyTranspiler] [HarmonyPatch("DoCrafting")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Player), "ConsumeResources", (Type[])null, (Type[])null), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_S, (object)14), Transpilers.EmitDelegate>((Action)DetermineCraftingRefund) }) .ThrowIfNotMatch("Unable to patch Crafting Refunds.", Array.Empty()); return val.Instructions(); } } public static float CheckAndReduceDurabilityCost(float item_durability_drain) { if (ValConfig.EnableDurabilityLossPrevention.Value && (Object)(object)Player.m_localPlayer != (Object)null) { float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)107); float value = Random.value; float num = ValConfig.ChanceForDurabilityLossPrevention.Value; if (ValConfig.ScaleDurabilitySaveBySkillLevel.Value) { num *= skillFactor; } if ((double)ValConfig.DurabilitySaveLevel.Value <= (double)skillFactor * 100.0 && value < num) { Logger.LogDebug($"Skipping durability usage {value} < {num}"); return 0f; } } return item_durability_drain; } private static int CraftableBonus(InventoryGui instance, int base_amount_crafted) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if (!ValConfig.EnableCrafting.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return base_amount_crafted; } int num = base_amount_crafted; CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation(); float skillFactor; float skillLevel; if ((Object)(object)instance.m_craftRecipe.m_craftingStation != (Object)null && (int)instance.m_craftRecipe.m_craftingStation.m_craftingSkill == 105) { skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)105); skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel((SkillType)105); } else { skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)107); skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel((SkillType)107); } if ((Object)(object)currentCraftingStation != (Object)null && (Object)(object)instance.m_craftRecipe.m_craftingStation != (Object)null && instance.m_craftUpgradeItem == null) { Logger.LogDebug("Determining crafting recipe bonus amount"); num += GetCraftingItemBonusAmount(instance, base_amount_crafted, skillFactor, skillLevel, instance.m_craftRecipe.m_craftingStation.m_craftingSkill); } if (num != base_amount_crafted) { Vector3 val = ((Component)Player.m_localPlayer).transform.position + Vector3.up; DamageText.instance.ShowText((TextType)7, val, $"+{num - base_amount_crafted}", true); instance.m_craftBonusEffect.Create(val, Quaternion.identity, (Transform)null, 1f, -1); } return num; } private static void DetermineCraftingRefund(InventoryGui instance, int num_recipe_crafted) { //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) float skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel((SkillType)107); float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)107); if (!ValConfig.EnableMaterialReturns.Value || skillLevel < (float)ValConfig.CraftingMaterialReturnsLevel.Value) { return; } Dictionary dictionary = new Dictionary(); if (instance.m_craftRecipe.m_requireOnlyOneIngredient) { Logger.LogDebug("Require any resource recipes do not get a refund."); return; } Requirement[] resources = instance.m_craftRecipe.m_resources; foreach (Requirement val in resources) { float value = Random.value; float num = ValConfig.ChanceForMaterialReturn.Value * skillFactor; Logger.LogDebug($"Checking refund chance for {((Object)val.m_resItem).name} {value} < {num}"); if (value <= num) { if (val.m_amount > 1) { int value2 = Mathf.RoundToInt((float)val.m_amount * (ValConfig.MaxCraftingMaterialReturnPercent.Value * skillFactor)); dictionary.Add(val.m_resItem, value2); } else if ((double)value < (double)num / 2.0) { dictionary.Add(val.m_resItem, 1); } } } if (dictionary.Count == 0) { return; } Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + Vector3.up; DamageText.instance.ShowText((TextType)7, val2, LocalizationManager.Instance.TryTranslate("$craft_refund"), true); instance.m_craftBonusEffect.Create(val2, Quaternion.identity, (Transform)null, 1f, -1); foreach (KeyValuePair item in dictionary) { bool flag = ((Humanoid)Player.m_localPlayer).GetInventory().AddItem(((Component)item.Key).gameObject, item.Value); Logger.LogDebug($"Refund to add: {((Object)item.Key).name} {item.Value} | refunded? {flag}"); } } private static int GetCraftingItemBonusAmount(InventoryGui instance, int base_amount_crafted, float skill_factor, float player_skill_level, SkillType craftingSkill) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Invalid comparison between Unknown and I4 //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Invalid comparison between Unknown and I4 int num = 0; if ((int)craftingSkill == 105 && (!ValConfig.EnableCookingBonusItems.Value || (float)ValConfig.RequiredLevelForBonusCookingItems.Value > player_skill_level)) { return num; } if (!ValConfig.EnableBonusItemCrafting.Value || player_skill_level < (float)ValConfig.CraftingBonusCraftsLevel.Value) { return num; } float num2 = (((int)craftingSkill != 105) ? (ValConfig.CraftingBonusChance.Value * skill_factor) : (ValConfig.ChanceForCookingBonusItems.Value * skill_factor)); int num3 = 1; if ((int)craftingSkill != 105 && instance.m_craftRecipe.m_amount > 1 && ValConfig.EnableCraftBonusAsFraction.Value) { num3 = Mathf.RoundToInt((float)instance.m_craftRecipe.m_amount * ValConfig.CraftBonusFractionOfCraftNumber.Value); Logger.LogDebug($"Bonus updated now {num3}, using fraction of result."); } int num4 = (((int)craftingSkill != 105) ? ValConfig.CraftingMaxBonus.Value : ValConfig.CookingBonusItemMaxAmount.Value); for (int i = 1; i <= num4; i++) { float num5 = Random.Range(0f, 1f); Logger.LogDebug($"Bonus crafting roll {i}: {num2} >= {num5}"); if (!(num2 >= num5)) { break; } num += num3; } Logger.LogDebug($"Crafting {instance.m_craftRecipe.m_item.m_itemData.m_shared.m_name} with new total {base_amount_crafted} + (bonus) {num}."); return num; } } public static class Gathering { [HarmonyPatch(typeof(Pickable))] public static class DisableVanillaGatheringLuck { [HarmonyTranspiler] [HarmonyPatch("Interact")] private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, generator); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Pickable), "m_picked"), (string)null) }).Advance(2).Insert((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Func)DetermineExtraDrops), new CodeInstruction(OpCodes.Stloc_0, (object)null) }) .Advance(3) .CreateLabelOffset(out var label, 59) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Br, (object)label) }) .ThrowIfNotMatch("Unable remove vanilla pickable luckydrop.", Array.Empty()); return val.Instructions(); } private static int DetermineExtraDrops(Pickable __instance) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || __instance.m_picked) { return 0; } if (UnallowedPickables.Contains(((Object)__instance.m_itemPrefab).name)) { Logger.LogDebug("Pickable is not an allowed gathering item."); return 0; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)106); float num = ValConfig.GatheringLuckFactor.Value * skillFactor * 100f / 100f; float num2 = Random.Range(0f, 50f) + num; int num3 = 0; foreach (float luck_level in luck_levels) { Logger.LogDebug($"Gathering Luck roll: {num2} > {luck_level}"); if (num2 > luck_level) { num3++; continue; } break; } Logger.LogDebug($"Gathering Luck, drop total: {num3}"); if (num3 > 0) { Vector3 val = ((Component)__instance).transform.position + Vector3.up * __instance.m_spawnOffset; Logger.LogDebug($"Spawning extra drops {num3}"); DamageText.instance.ShowText((TextType)7, ((Component)__instance).transform.position + Vector3.up * __instance.m_spawnOffset, $"+{num3}", true); __instance.m_bonusEffect.Create(val, Quaternion.identity, (Transform)null, 1f, -1); } ((Character)Player.m_localPlayer).RaiseSkill((SkillType)106, (float)(1 + num3)); return num3; } } [HarmonyPatch(typeof(Attack))] public static class HarvestRangeIncreasesScythe { [HarmonyTranspiler] [HarmonyPatch("DoMeleeAttack")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Attack), "m_harvestRadiusMaxLevel"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)IncreaseHarvestWeaponRange) }) .ThrowIfNotMatch("Unable to increase vanilla harvest max range.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(Pickable), "Interact")] public static class GatheringLuckPatch { [CompilerGenerated] private sealed class d__1 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Collider[] targets; private int 5__2; private Collider[] <>7__wrap2; private int <>7__wrap3; private Collider 5__5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap2 = null; 5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0084; } <>1__state = -1; 5__2 = 0; <>7__wrap2 = targets; <>7__wrap3 = 0; goto IL_0111; IL_0084: if (!((Object)(object)5__5 == (Object)null)) { Pickable val = ((Component)5__5).GetComponent() ?? ((Component)5__5).GetComponentInParent(); if ((Object)(object)val != (Object)null && (Object)(object)val.m_itemPrefab != (Object)null && !UnallowedPickables.Contains(((Object)val.m_itemPrefab).name) && val.CanBePicked()) { val.m_nview.ClaimOwnership(); val.Interact((Humanoid)(object)Player.m_localPlayer, false, false); } 5__5 = null; } <>7__wrap3++; goto IL_0111; IL_0111: if (<>7__wrap3 < <>7__wrap2.Length) { 5__5 = <>7__wrap2[<>7__wrap3]; 5__2++; if (5__2 % 10 == 0) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } goto IL_0084; } <>7__wrap2 = null; enabled_aoe_gathering = true; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static void Postfix(ref bool __result, Pickable __instance, Humanoid character) { //IL_0103: Unknown result type (might be due to invalid IL or missing references) if (!ValConfig.EnableGathering.Value || !ValConfig.EnableGatheringAOE.Value || !((Object)(object)Player.m_localPlayer != (Object)null) || !((Object)(object)character == (Object)(object)Player.m_localPlayer) || !((Object)(object)__instance != (Object)null)) { return; } if (UnallowedPickables.Contains(((Object)__instance.m_itemPrefab).name)) { Logger.LogDebug("Pickable is not a gathering item."); return; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)106); if (!enabled_aoe_gathering && aoe_gathering_activated_at + ValConfig.PlantingAOEHarvestResetSafety.Value < Time.realtimeSinceStartup) { enabled_aoe_gathering = true; } Logger.LogDebug($"Checking for AOE gathering {skillFactor * 100f > (float)ValConfig.FarmingRangeRequiredLevel.Value} && {enabled_aoe_gathering}"); if (!(skillFactor * 100f > (float)ValConfig.FarmingRangeRequiredLevel.Value) || !enabled_aoe_gathering) { return; } float num = ValConfig.GatheringRangeFactor.Value * skillFactor; Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, num, pickableMask); Logger.LogDebug($"AOE Picking {array.Count()} in harvest range {num}."); aoe_gathering_activated_at = Time.realtimeSinceStartup; enabled_aoe_gathering = false; if (array.Length <= 5) { Collider[] array2 = array; foreach (Collider val in array2) { Pickable val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent(); if ((Object)(object)val2 != (Object)null) { Logger.LogDebug("Checking " + ((Object)((Component)val2).gameObject).name + " in harvest range."); if (!UnallowedPickables.Contains(((Object)val2.m_itemPrefab).name) && val2.CanBePicked()) { val2.m_nview.ClaimOwnership(); val2.Interact((Humanoid)(object)Player.m_localPlayer, false, false); } } } enabled_aoe_gathering = true; } else { ((MonoBehaviour)Player.m_localPlayer).StartCoroutine(PickAOE(array)); } } [IteratorStateMachine(typeof(d__1))] private static IEnumerator PickAOE(Collider[] targets) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(0) { targets = targets }; } } private static readonly int pickableMask = LayerMask.GetMask(new string[3] { "piece_nonsolid", "item", "Default_small" }); private static readonly List UnallowedPickables = new List(); private static List luck_levels = new List(); private static bool enabled_aoe_gathering = true; private static float aoe_gathering_activated_at = 0f; private static void PickableLuckLevelsChanged(object s, EventArgs e) { try { List list = new List(); string[] array = ValConfig.GatheringLuckLevels.Value.Split(new char[1] { ',' }); foreach (string s2 in array) { list.Add(float.Parse(s2)); } if (list.Count > 0) { luck_levels = list; } } catch (Exception arg) { Logger.LogWarning($"Error parsing GatheringLuckLevels: {arg}"); } } private static void UnallowedPickablesChanged(object s, EventArgs e) { try { List list = new List(); string[] array = ValConfig.GatheringDisallowedItems.Value.Split(new char[1] { ',' }); foreach (string item in array) { list.Add(item); } if (list.Count > 0) { UnallowedPickables.Clear(); UnallowedPickables.AddRange(list); } } catch (Exception arg) { Logger.LogWarning($"Error parsing GatheringDisallowedItems: {arg}"); } } public static void SetupGatherables() { try { string[] array = ValConfig.GatheringLuckLevels.Value.Split(new char[1] { ',' }); foreach (string s in array) { luck_levels.Add(float.Parse(s)); } } catch (Exception arg) { Logger.LogWarning($"Error parsing GatheringLuckLevels, defaults will be used: {arg}"); luck_levels.AddRange(new List { 30f, 50f, 70f, 90f, 100f }); } ValConfig.GatheringLuckLevels.SettingChanged += PickableLuckLevelsChanged; try { string[] array = ValConfig.GatheringDisallowedItems.Value.Split(new char[1] { ',' }); foreach (string item in array) { UnallowedPickables.Add(item); } } catch (Exception arg2) { Logger.LogWarning($"Error parsing GatheringDisallowedItems, defaults will be used.: {arg2}"); UnallowedPickables.AddRange(new List { "SurtlingCore", "Flint", "Wood", "Branch", "Stone", "Amber", "AmberPearl", "Coins", "Ruby", "CryptRemains", "Obsidian", "Crystal", "Pot_Shard", "DragonEgg", "DvergrLantern", "DvergrMineTreasure", "SulfurRock", "VoltureEgg", "Swordpiece", "MoltenCore", "Hairstrands", "Tar", "BlackCore" }); } ValConfig.GatheringDisallowedItems.SettingChanged += UnallowedPickablesChanged; } private static float IncreaseHarvestWeaponRange(float max_harvest_range) { if (ValConfig.EnableGathering.Value) { return ValConfig.GatheringRangeFactor.Value + max_harvest_range; } return max_harvest_range; } } internal class Hauling { [HarmonyPatch(typeof(Player))] private static class PlayerCarryWeightPatch { [HarmonyPatch("GetMaxCarryWeight")] private static void Postfix(Player __instance, ref float __result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableHauling.Value && ValConfig.EnableCarryWeightBonus.Value) { __result += ((Character)__instance).GetSkillFactor(HaulingSkill) * ValConfig.HaulingMaxWeightBonus.Value; } } } [HarmonyPatch(typeof(Vagon))] private static class VagonMassPatch { [HarmonyPatch("SetMass")] private static void Prefix(ref float mass) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableHauling.Value && ValConfig.EnableHaulingCartMassReduction.Value && !((Object)(object)Player.m_localPlayer == (Object)null)) { mass *= 1f - ((Character)Player.m_localPlayer).GetSkillFactor(HaulingSkill) * ValConfig.HaulingCartMassReduction.Value; } } } [HarmonyPatch(typeof(Vagon))] private static class VagonXPPatch { private static Vector3 lastPosition = Vector3.zero; private static float lastTimer = 0f; [HarmonyPatch("LateUpdate")] private static void Postfix(Vagon __instance) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) if (!ValConfig.EnableHauling.Value || (Object)(object)Player.m_localPlayer == (Object)null || !__instance.IsAttached((Character)(object)Player.m_localPlayer)) { return; } if (lastPosition == Vector3.zero || lastTimer == 0f) { lastPosition = ((Component)__instance).transform.position; lastTimer = Time.realtimeSinceStartup; } if (!(Time.realtimeSinceStartup > lastTimer + (float)ValConfig.HaulingXPCheckInterval.Value)) { return; } lastTimer = Time.realtimeSinceStartup; float num = Vector3.Distance(lastPosition, ((Component)__instance).transform.position); Logger.LogDebug($"Checking distanced traveled: {num}"); if (num > 1f) { float num2 = 0f; Rigidbody[] bodies = __instance.m_bodies; foreach (Rigidbody val in bodies) { num2 += val.mass; } Logger.LogDebug($"Raising hauling skill: {ValConfig.HaulingXPRate.Value * (num2 * 0.3f)} = {num2} * 0.3 * {ValConfig.HaulingXPRate.Value}"); ((Character)Player.m_localPlayer).RaiseSkill(HaulingSkill, ValConfig.HaulingXPRate.Value * (num2 * 0.3f)); lastPosition = ((Component)__instance).transform.position; } } } public static SkillType HaulingSkill; public static void SetupHaulingSkill() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_004d: 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) SkillConfig val = new SkillConfig(); val.Name = "$skill_Hauling"; val.Description = "$skill_Hauling_description"; val.Icon = ImpactfulSkills.EmbeddedResourceBundle.LoadAsset("Assets/Custom/Icons/skill_icons/hauling_skill.png"); val.Identifier = "midnightsfx.hauling"; val.IncreaseStep = 0.1f; HaulingSkill = SkillManager.Instance.AddSkill(val); } } public static class Jumping { [HarmonyPatch(typeof(Character))] public static class JumpForcePatch { [HarmonyTranspiler] [HarmonyPatch("Jump")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Character), "m_jumpForce"), (string)null) }).RemoveInstruction().InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)ModifyJumpForceBySkill) }) .ThrowIfNotMatch("Unable to patch jump force modification.", Array.Empty()); return val.Instructions(); } private static float ModifyJumpForceBySkill(Character character) { if (!ValConfig.EnableJump.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)character != (Object)(object)Player.m_localPlayer) { return character.m_jumpForce; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)100); float num = skillFactor * 100f; if (ValConfig.JumpHeightRequiredLevel.Value > num) { return character.m_jumpForce; } float num2 = ValConfig.JumpHeightFactor.Value / 100f; float num3 = 1f + (num2 - 1f) * skillFactor; float num4 = character.m_jumpForce * num3; Logger.LogDebug($"Jump force modified: {character.m_jumpForce} -> {num4} (skill: {num}, multiplier: {num3})"); return num4; } } [HarmonyPatch(typeof(Character))] public static class FallDamagePatch { internal static float MinFallDamageHeight = 4f; [HarmonyTranspiler] [HarmonyPatch("UpdateGroundContact")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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 //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Character), "IsPlayer", (Type[])null, (Type[])null), (string)null) }).Advance(2).MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Character), "IsPlayer", (Type[])null, (Type[])null), (string)null) }) .MatchForward(true, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)null, (string)null) }) .RemoveInstruction() .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Func)ModifyMinFallHeightForDamageBySkill) }) .ThrowIfNotMatch("Unable to patch min damage height increase.", Array.Empty()) .MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(SEMan), "ModifyFallDamage", (Type[])null, (Type[])null), (string)null) }) .Advance(1) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldloc_2, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Func)ModifyFallDamageBySkill), new CodeInstruction(OpCodes.Stloc_2, (object)null) }) .ThrowIfNotMatch("Unable to patch Fall damage reduction.", Array.Empty()); return val.Instructions(); } private static float ModifyFallDamageBySkill(float falldmg, Character chara) { if (!ValConfig.EnableJump.Value || !ValConfig.EnableFallDamageReduction.Value) { return falldmg; } float skillFactor = chara.GetSkillFactor((SkillType)100); float num = skillFactor * 100f; if (ValConfig.FallDamageReductionRequiredLevel.Value > num) { return falldmg; } float num2 = 1f - ValConfig.FallDamageReductionFactor.Value * skillFactor; float num3 = falldmg * num2; Logger.LogDebug($"Fall damage reduced: {falldmg} -> {num3} (reduction: {num2})"); return num3; } private static float ModifyMinFallHeightForDamageBySkill(Character character) { if (!ValConfig.EnableJump.Value || !ValConfig.EnableFallDamageHeightBonus.Value) { return MinFallDamageHeight; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)100); float num = skillFactor * 100f; if (ValConfig.FallDamageHeightRequiredLevel.Value > num) { return MinFallDamageHeight; } return MinFallDamageHeight + ValConfig.FallDamageHeightBonus.Value * skillFactor; } } } public static class Mining { [HarmonyPatch(typeof(MineRock), "Damage")] public static class MinerockDmgPatch { public static void Prefix(HitData hit, MineRock __instance) { ModifyPickaxeDmg(hit, __instance); } } [HarmonyPatch(typeof(MineRock5), "Damage")] public static class Minerock5DmgPatch { public static void Prefix(HitData hit, MineRock5 __instance) { ModifyPickaxeDmg(hit, null, __instance); } } [HarmonyPatch(typeof(MineRock5), "RPC_SetAreaHealth")] public static class Minerock5DestroyPatch { public static void Postfix(MineRock5 __instance, long sender, int index, float health) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableMining.Value && (Object)(object)Player.m_localPlayer != (Object)null && !((double)health > 0.0)) { IncreaseMiningDrops(__instance.m_dropItems, ((Component)__instance).gameObject.transform.position); } } } [HarmonyPatch(typeof(Destructible), "Destroy")] public static class IncreaseDropsFromDestructibleRock { public static void Prefix(Destructible __instance, HitData hit) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_002f: 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) if (ValConfig.EnableMining.Value && (int)__instance.m_destructibleType == 1 && (int)__instance.m_destructibleType != 2 && hit != null && (Object)(object)Player.m_localPlayer != (Object)null && !(hit.m_attacker != ((Character)Player.m_localPlayer).GetZDOID())) { IncreaseDestructibleMineDrops(__instance); } } } [CompilerGenerated] private sealed class d__12 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Dictionary drops; public Vector3 centerPos; private int 5__2; private Dictionary.Enumerator <>7__wrap2; private bool 5__4; private int 5__5; private GameObject 5__6; private int 5__7; private int 5__8; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap2 = default(Dictionary.Enumerator); 5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_00ea: 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_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: 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_00cd: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -3; goto IL_00e3; } <>1__state = -1; 5__2 = 0; <>7__wrap2 = drops.GetEnumerator(); <>1__state = -3; goto IL_0240; IL_0240: if (<>7__wrap2.MoveNext()) { KeyValuePair current = <>7__wrap2.Current; 5__4 = false; 5__5 = 0; 5__6 = current.Key; 5__7 = current.Value; Logger.LogDebug($"Dropping {((Object)5__6).name} {5__7}"); 5__8 = 0; goto IL_0221; } <>m__Finally1(); <>7__wrap2 = default(Dictionary.Enumerator); return false; IL_0221: if (5__8 < 5__7) { if (5__2 > 0 && 5__2 % 10 == 0) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } goto IL_00e3; } 5__6 = null; 5__6 = null; goto IL_0240; IL_00e3: GameObject obj = Object.Instantiate(5__6, centerPos, Quaternion.identity); int num2 = 5__2 + 1; 5__2 = num2; ItemDrop component = obj.GetComponent(); if (!5__4) { 5__4 = true; if (Object.op_Implicit((Object)(object)component)) { 5__5 = component.m_itemData.m_shared.m_maxStackSize; } } if ((Object)(object)component != (Object)null) { int num3 = 5__7 - 5__8; if (num3 > 0) { if (5__7 > 5__5) { component.m_itemData.m_stack = 5__5; 5__8 += 5__5; } else { component.m_itemData.m_stack = num3; 5__8 += num3; } } component.m_itemData.m_worldLevel = (byte)Game.m_worldLevel; } Rigidbody component2 = obj.GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { Vector3 insideUnitSphere = Random.insideUnitSphere; if ((double)insideUnitSphere.y < 0.0) { insideUnitSphere.y = 0f - insideUnitSphere.y; } component2.AddForce(insideUnitSphere * 5f, (ForceMode)2); } num2 = 5__8 + 1; 5__8 = num2; goto IL_0221; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap2).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__9 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Collider[] mine_targets; public HitData aoedmg; private MineRock5 5__2; private MineRock 5__3; private int 5__4; private Collider[] 5__5; private int 5__6; private Collider 5__7; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; 5__5 = null; 5__7 = null; <>1__state = -2; } private bool MoveNext() { //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Expected O, but got Unknown int areaIndex; Bounds bounds; int i; switch (<>1__state) { default: return false; case 0: { <>1__state = -1; 5__2 = null; 5__3 = null; bool flag = true; 5__4 = 0; try { Collider[] array = mine_targets; foreach (Collider val in array) { MineRock componentInParent = ((Component)val).gameObject.GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { 5__3 = componentInParent; flag = true; break; } MineRock5 componentInParent2 = ((Component)val).gameObject.GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null) { 5__2 = componentInParent2; flag = false; break; } } } catch (Exception ex) { Logger.LogWarning("Exception trying to get minerock parent object, AOE mining skipped: " + ex.Message); rockbreaker_running = false; current_aoe_strike = null; return false; } if (!((Object)(object)5__3 != (Object)null) && !((Object)(object)5__2 != (Object)null)) { break; } if (mine_targets != null) { if (flag) { 5__5 = mine_targets; 5__6 = 0; goto IL_020a; } 5__5 = mine_targets; 5__6 = 0; goto IL_033e; } goto IL_0351; } case 1: <>1__state = -1; goto IL_0195; case 2: { <>1__state = -1; goto IL_02ba; } IL_0351: 5__5 = null; 5__7 = null; break; IL_02ba: areaIndex = 5__2.GetAreaIndex(5__7); if (areaIndex >= 0) { Logger.LogDebug($"AOE Damage applying to minerock5 index: {areaIndex}"); HitData obj = aoedmg; bounds = 5__7.bounds; obj.m_point = ((Bounds)(ref bounds)).center; aoedmg.m_hitCollider = 5__7; 5__2.DamageArea(areaIndex, aoedmg); } goto IL_032c; IL_0195: if (ArrayContains(5__3.m_hitAreas, 5__7)) { Logger.LogDebug("AOE Damage applying to minerock"); HitData obj2 = aoedmg; bounds = 5__7.bounds; obj2.m_point = ((Bounds)(ref bounds)).center; aoedmg.m_hitCollider = 5__7; 5__3.Damage(aoedmg); } goto IL_01f8; IL_032c: i = 5__6 + 1; 5__6 = i; goto IL_033e; IL_020a: if (5__6 < 5__5.Length && 5__5 != null && !((Object)(object)5__3 == (Object)null)) { 5__7 = 5__5[5__6]; if (!((Object)(object)5__7 == (Object)null)) { i = 5__4 + 1; 5__4 = i; if (5__4 % ValConfig.MinehitsPerInterval.Value == 0) { <>2__current = (object)new WaitForFixedUpdate(); <>1__state = 1; return true; } goto IL_0195; } goto IL_01f8; } goto IL_0351; IL_01f8: i = 5__6 + 1; 5__6 = i; goto IL_020a; IL_033e: if (5__6 < 5__5.Length && 5__5 != null && !((Object)(object)5__2 == (Object)null)) { 5__7 = 5__5[5__6]; if (!((Object)(object)5__7 == (Object)null)) { i = 5__4 + 1; 5__4 = i; if (5__4 % ValConfig.MinehitsPerInterval.Value == 0) { <>2__current = (object)new WaitForFixedUpdate(); <>1__state = 2; return true; } goto IL_02ba; } goto IL_032c; } goto IL_0351; } rockbreaker_running = false; current_aoe_strike = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly int rockmask = LayerMask.GetMask(new string[3] { "static_solid", "Default_small", "Default" }); private static Collider[] current_aoe_strike = null; private static bool rockbreaker_running = false; private static readonly List skipIncreaseDrops = new List { "LeatherScraps", "WitheredBone" }; private static float rockbreakerActivatedAt = 0f; private static void UnallowedMinablesChanged(object s, EventArgs e) { try { List list = new List(); string[] array = ValConfig.SkipNonRockDropPrefabs.Value.Split(new char[1] { ',' }); foreach (string item in array) { list.Add(item); } if (list.Count > 0) { skipIncreaseDrops.Clear(); skipIncreaseDrops.AddRange(list); } } catch (Exception arg) { Logger.LogWarning($"Error parsing SkipNonRockDropPrefabs: {arg}"); } } public static void SetupMining() { try { string[] array = ValConfig.SkipNonRockDropPrefabs.Value.Split(new char[1] { ',' }); foreach (string item in array) { skipIncreaseDrops.Add(item); } } catch (Exception arg) { Logger.LogWarning($"Error parsing SkipNonRockDropPrefabs, defaults will be used.: {arg}"); skipIncreaseDrops.AddRange(new List { "LeatherScraps", "WitheredBone" }); } ValConfig.GatheringDisallowedItems.SettingChanged += UnallowedMinablesChanged; } public static void ModifyPickaxeDmg(HitData hit, MineRock instance = null, MineRock5 instance5 = null) { //IL_001d: 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_0375: Unknown result type (might be due to invalid IL or missing references) if (!ValConfig.EnableMining.Value || hit == null || (Object)(object)Player.m_localPlayer == (Object)null || hit.m_attacker != ((Character)Player.m_localPlayer).GetZDOID()) { return; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)12); float num = (float)(1.0 + (double)ValConfig.MiningDmgMod.Value * ((double)skillFactor * 100.0) / 100.0); Logger.LogDebug($"Player mining dmg multiplier: {num}"); hit.m_damage.m_pickaxe *= num; if (ValConfig.EnableMiningCritHit.Value && (double)skillFactor * 100.0 >= (double)ValConfig.RequiredLevelForMiningCrit.Value && (double)Random.value <= (double)ValConfig.ChanceForMiningCritHit.Value) { Logger.LogDebug("Mining Critical hit activated"); hit.m_damage.m_pickaxe *= ValConfig.CriticalHitDmgMult.Value; } if ((double)hit.m_damage.m_pickaxe <= 0.0) { return; } if (rockbreaker_running && rockbreakerActivatedAt + ValConfig.RockbreakerSafetyResetTimeout.Value < Time.realtimeSinceStartup) { rockbreaker_running = false; current_aoe_strike = null; } if (!rockbreaker_running && current_aoe_strike == null) { float value = Random.value; float num2 = skillFactor * ValConfig.RockBreakerMaxChance.Value; Logger.LogDebug($"Rock breaker roll: {value} <= {num2}"); if (ValConfig.EnableMiningRockBreaker.Value && (double)skillFactor * 100.0 >= (double)ValConfig.RockBreakerRequiredLevel.Value && (double)value <= (double)num2) { Logger.LogDebug("Rock breaker activated!"); hit.m_damage.m_pickaxe = ValConfig.RockBreakerDamage.Value; rockbreaker_running = true; rockbreakerActivatedAt = Time.realtimeSinceStartup; if ((Object)(object)instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { Logger.LogDebug("Rock breaker activated on minerock"); current_aoe_strike = instance.m_hitAreas; ((MonoBehaviour)Player.m_localPlayer).StartCoroutine(MineAoeDamage(instance.m_hitAreas, hit)); } else { rockbreaker_running = false; current_aoe_strike = null; } if (!((Object)(object)instance5 != (Object)null)) { return; } if ((Object)(object)Player.m_localPlayer != (Object)null) { Logger.LogDebug("Rock breaker activated on minerock5"); List list = new List(); foreach (HitArea hitArea in instance5.m_hitAreas) { list.Add(hitArea.m_collider); } current_aoe_strike = list.ToArray(); ((MonoBehaviour)Player.m_localPlayer).StartCoroutine(MineAoeDamage(list.ToArray(), hit)); } else { rockbreaker_running = false; current_aoe_strike = null; } return; } } if (!ValConfig.EnableMiningAOE.Value || (double)skillFactor * 100.0 < (double)ValConfig.MiningAOELevel.Value || current_aoe_strike != null) { return; } float num3 = ValConfig.ChanceForAOEOnHit.Value; if (ValConfig.ChanceForAOEOnHitScalesWithSkill.Value) { num3 -= 1f * skillFactor; } if (num3 < 0f) { num3 = 0f; } float value2 = Random.value; if (value2 < num3) { Logger.LogDebug(string.Format($"AOE Mining failed roll: {value2} < {num3}")); return; } Logger.LogDebug($"Player mining aoe activated: {value2} > {num3}"); Vector3 point = hit.m_point; double num4 = (double)ValConfig.MiningAOERange.Value * (double)skillFactor; int num5 = rockmask; Collider[] mine_targets = (current_aoe_strike = Physics.OverlapSphere(point, (float)num4, num5)); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((MonoBehaviour)Player.m_localPlayer).StartCoroutine(MineAoeDamage(mine_targets, hit)); return; } current_aoe_strike = null; rockbreaker_running = false; } public static bool ArrayContains(Collider[] group, Collider target) { for (int i = 0; i < group.Length; i++) { if ((Object)(object)group[i] == (Object)(object)target) { return true; } } return false; } [IteratorStateMachine(typeof(d__9))] private static IEnumerator MineAoeDamage(Collider[] mine_targets, HitData aoedmg) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__9(0) { mine_targets = mine_targets, aoedmg = aoedmg }; } public static void IncreaseDestructibleMineDrops(Destructible dmine) { //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_003a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)dmine.m_spawnWhenDestroyed != (Object)null)) { Vector3 position = ((Component)dmine).transform.position; DropOnDestroyed component = ((Component)dmine).GetComponent(); if (!((Object)(object)component == (Object)null) && component.m_dropWhenDestroyed != null) { IncreaseMiningDrops(component.m_dropWhenDestroyed, position); } } } public static void IncreaseMiningDrops(DropTable drops, Vector3 position, HitData hitdata = null) { //IL_000a: 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_0338: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) float num = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, position); if (num > ValConfig.DistanceMiningDropMultiplierChecks.Value) { Logger.LogDebug($"Player too far away from rock to get increased loot: {num}"); return; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)12); float num2 = ValConfig.MiningLootFactor.Value * (skillFactor * 100f); Dictionary dictionary = new Dictionary(); if (drops.m_drops != null) { foreach (DropData drop in drops.m_drops) { if (ValConfig.SkipNonRockDropIncreases.Value && skipIncreaseDrops.Contains(((Object)drop.m_item).name)) { continue; } float value = Random.value; float num3 = drops.m_dropChance; if (ValConfig.SkillLevelBonusEnabledForMiningDropChance.Value) { num3 = (float)((double)(num2 * drops.m_dropChance) / 100.0); } if ((double)num3 > 1.0) { num3 = 1f; } Logger.LogDebug($"Mining rock check roll: {num3} <= {value}"); if (num3 <= value) { Logger.LogDebug("Mining rock drop increase: " + ((Object)drop.m_item).name + " failed drop roll"); continue; } int num4 = 0; Logger.LogDebug($"Mining rock drop current: {drops.m_dropMin}, max_drop: {drops.m_dropMax}"); float num5 = (float)((double)((float)drops.m_dropMin * num2) / 100.0); float num6 = (float)((double)((float)drops.m_dropMax * num2) / 100.0); if (ValConfig.ReducedChanceDropsForLowAmountDrops.Value && (double)num5 > 0.0 && (double)num6 > 0.0 && num5 != 1f) { float num7 = Random.Range(num5, num6); float value2 = Random.value; if (num7 <= value2) { Logger.LogDebug($"Mining rock drop increase: {((Object)drop.m_item).name} failed amount roll {num7} <= {value2}"); continue; } } num4 = (((double)num5 != (double)num6) ? Mathf.RoundToInt(Random.Range(num5, num6)) : Mathf.RoundToInt(num5)); if (num4 < 1) { float value3 = Random.value; if (ValConfig.FractionalDropsAsChance.Value && value3 <= num5) { Logger.LogDebug($"Mining rock drop bonus result is less than 1. Roll success ({value3} <= {num5}) for dropping 1."); num4 = 1; } else { Logger.LogDebug($"Mining rock drop bonus result is less than 1. No bonus. ({value3} <= {num5})"); num4 = 0; } } Logger.LogDebug($"Mining rock drop increase {((Object)drop.m_item).name} min_drop: {num5}, max_drop: {num6} drop amount: {num4}"); if (dictionary.ContainsKey(drop.m_item)) { dictionary[drop.m_item] += num4; } else { dictionary.Add(drop.m_item, num4); } } } if (dictionary.Count != 0) { ((MonoBehaviour)Player.m_localPlayer).StartCoroutine(DropItemsAsync(dictionary, position, 1f)); } } [IteratorStateMachine(typeof(d__12))] private static IEnumerator DropItemsAsync(Dictionary drops, Vector3 centerPos, float dropArea) { //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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__12(0) { drops = drops, centerPos = centerPos }; } [HarmonyTranspiler] [HarmonyPatch(typeof(MineRock), "RPC_Hit")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchEndForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(MineRock), "m_destroyedEffect"), (string)null) }).MatchEndForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Pop, (object)null, (string)null) }).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Action)ApplyIncreasedMiningDrops) }) .ThrowIfNotMatch("Unable to patch Minerock Drop increase.", Array.Empty()); return val.Instructions(); } private static void ApplyIncreasedMiningDrops(MineRock __instance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableMining.Value && (Object)(object)Player.m_localPlayer != (Object)null) { IncreaseMiningDrops(__instance.m_dropItems, ((Component)__instance).gameObject.transform.position); } } } public static class Running { [HarmonyPatch(typeof(Character))] public static class RunningSpeedPatch { [HarmonyTranspiler] [HarmonyPatch("UpdateWalking")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Character), "m_runSpeed"), (string)null) }).RemoveInstruction().InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)ModifyRunSpeedBySkill) }) .ThrowIfNotMatch("Unable to patch Run skill movement increase.", Array.Empty()); return val.Instructions(); } public static float ModifyRunSpeedBySkill(Character __instance) { if (ValConfig.EnableRun.Value && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)102); float num = ValConfig.RunSpeedFactor.Value * (skillFactor * 100f); return __instance.m_runSpeed + num; } return __instance.m_runSpeed; } } } public static class SharedKnowledge { [HarmonyPatch(typeof(Player), "RaiseSkill")] public static class PatchSkillIncreaseHigherGainsForLowerSkills { private static void Prefix(SkillType skill, ref float value) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) time_since_start += Time.deltaTime; if (!ValConfig.EnableKnowledgeSharing.Value || !((Object)(object)Player.m_localPlayer != (Object)null) || skill_types_to_avoid_shared_xp.Contains(skill)) { return; } if (time_since_start > last_skill_level_check || highest_skill_level == 0f) { if (!setup_avoid_skills) { SetupUnallowedSharedXPSkills(); setup_avoid_skills = true; } highest_skill_level = UpdateHighestSkillLevel(Player.m_localPlayer); last_skill_level_check = time_since_start + Time.deltaTime * 100f; Logger.LogDebug($"Setting highest skill level {highest_skill_level} factor {highest_skill_factor}"); } float skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel(skill); if (skillLevel < highest_skill_level) { float num = Mathf.Lerp(0f, highest_skill_level, highest_skill_factor) / 100f; float num2 = ValConfig.SharedKnowledgeSkillBonusRate.Value * num; if (highest_skill_level <= skillLevel + ValConfig.SharedKnowledgeCap.Value) { num2 = 0f; } Logger.LogDebug($"Bonus skill gain from Knowledge {num2} for {((object)(SkillType)(ref skill)).ToString()}"); value += num2; } } } private static float highest_skill_level = 0f; private static float highest_skill_factor = 0f; private static float time_since_start = 0f; private static float last_skill_level_check = 0f; private static bool setup_avoid_skills = false; private static List skill_types_to_avoid_shared_xp = new List(); public static void UnallowedSharedXPSkillTypesChanged(object s, EventArgs e) { SetupUnallowedSharedXPSkills(); } public static void SetupUnallowedSharedXPSkills() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00d5: 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) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } List list = new List(); List list2 = ((Character)Player.m_localPlayer).GetSkills().m_skillData.Keys.ToList(); bool flag = false; if (ValConfig.SharedKnowledgeIgnoreList.Value != "") { string[] array = ValConfig.SharedKnowledgeIgnoreList.Value.Split(new char[1] { ',' }); foreach (string text in array) { Logger.LogDebug("Checking " + text + " as skill enum"); SkillDef skill = SkillManager.Instance.GetSkill(text); if (skill != null) { list.Add(skill.m_skill); continue; } try { foreach (SkillType item in list2) { SkillType current = item; if (((object)(SkillType)(ref current)).ToString().Equals(text, StringComparison.OrdinalIgnoreCase)) { if (!list.Contains(current)) { list.Add(current); } break; } } } catch (Exception arg) { Logger.LogError($"Error parsing {text} as skill enum: {arg}"); } } } if (list.Count > 0) { skill_types_to_avoid_shared_xp.Clear(); skill_types_to_avoid_shared_xp.AddRange(list); } if (flag) { Logger.LogWarning("Some of the skills you provided in the config are not valid skill types. Invalid skill types will be ignored. A comma seperated of valid skill names is recommended."); Logger.LogWarning("Valid skill types are: " + string.Join(", ", Skills.s_allSkills)); } Logger.LogDebug("Unallowed shared xp skills: " + string.Join(", ", skill_types_to_avoid_shared_xp)); } private static float UpdateHighestSkillLevel(Player player) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) float num = 0f; foreach (Skill skill in ((Character)player).GetSkills().GetSkillList()) { if (skill != null && skill.m_level > num) { num = skill.m_level; highest_skill_factor = ((Character)player).GetSkillFactor(skill.m_info.m_skill); } } return num; } } public static class Sneaking { [HarmonyPatch(typeof(Character))] public static class SneakSpeedPatch { [HarmonyTranspiler] [HarmonyPatch("UpdateWalking")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); if (Modcheck.IsSNEAKerEnabled) { Logger.LogDebug("SNEAKer detected, using compatibility patch."); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Character), "IsEncumbered", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)null, (string)null) }).Advance(4).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Func)ModifySneakSpeedBonusOnly), new CodeInstruction(OpCodes.Add, (object)null) }) .ThrowIfNotMatch("Unable to patch Sneak skill movement increase with SNEAKer.", Array.Empty()); } else { val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Character), "m_crouchSpeed"), (string)null) }).RemoveInstruction().InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)ModifyMovementSpeedBySkill) }) .ThrowIfNotMatch("Unable to patch Sneak skill movement increase.", Array.Empty()); } return val.Instructions(); } public static float ModifySneakSpeedBonusOnly(Character __instance) { if (!ValConfig.EnableStealth.Value || __instance.IsEncumbered()) { return 0f; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)101); return ValConfig.SneakSpeedFactor.Value * (skillFactor * 100f); } public static float ModifyMovementSpeedBySkill(Character __instance) { if (!ValConfig.EnableStealth.Value || __instance.IsEncumbered()) { return __instance.m_crouchSpeed; } float skillFactor = __instance.GetSkillFactor((SkillType)101); float num = ValConfig.SneakSpeedFactor.Value * (skillFactor * 100f); return __instance.m_crouchSpeed + num; } } public static class SneakingReducedNoisePatch { [HarmonyPatch(typeof(Character), "AddNoise")] public static class AddNoisePatch { public static void Prefix(Character __instance, ref float range) { if (ValConfig.EnableStealth.Value && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { float skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel((SkillType)101); if (!((double)skillLevel < (double)ValConfig.SneakNoiseReductionLevel.Value)) { float num = (float)((100.0 - (double)(ValConfig.SneakNoiseReductionFactor.Value * skillLevel)) / 100.0) * range; range = num; } } } } } public static class SneakingBackstabBonusDmg { [HarmonyPatch(typeof(Attack))] public static class AddMeleeBonusBackstab { [HarmonyTranspiler] [HarmonyPatch("DoMeleeAttack")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(SharedData), "m_backstabBonus"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Func)ModifyBackstab) }) .ThrowIfNotMatch("Unable to patch Melee Backstab.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(Attack))] public static class AddRangedBonusBackstab { [HarmonyTranspiler] [HarmonyPatch("FireProjectileBurst")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(SharedData), "m_backstabBonus"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Func)ModifyBackstab) }) .ThrowIfNotMatch("Unable to patch Ranged Backstab.", Array.Empty()); return val.Instructions(); } } public static float ModifyBackstab(float backstab_base, Attack attack_instance) { if (!ValConfig.EnableSneakBonusDamage.Value || !((Character)attack_instance.m_character).IsPlayer() || (double)ValConfig.SneakBackstabBonusLevel.Value > (double)((Character)attack_instance.m_character).GetSkillLevel((SkillType)101)) { return backstab_base; } float skillFactor = ((Character)attack_instance.m_character).GetSkillFactor((SkillType)101); float num = backstab_base * (ValConfig.SneakBackstabBonusFactor.Value * skillFactor); float num2 = backstab_base + num; Logger.LogDebug(string.Format($"Adding bonus backstab {num} = total ({num2})")); return num2; } } } public static class Swimming { [HarmonyPatch(typeof(Character))] public static class SwimmingSpeedPatch { [HarmonyTranspiler] [HarmonyPatch("UpdateSwimming")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Character), "m_swimSpeed"), (string)null) }).RemoveInstruction().InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)ModifySwimSpeedbySkill) }) .ThrowIfNotMatch("Unable to patch Swim skill movement increase.", Array.Empty()); return val.Instructions(); } public static float ModifySwimSpeedbySkill(Character __instance) { if (!ValConfig.EnableSwimming.Value) { return __instance.m_swimSpeed; } float skillFactor = __instance.GetSkillFactor((SkillType)103); if ((float)ValConfig.SwimSpeedRequiredLevel.Value > skillFactor * 100f) { return __instance.m_swimSpeed; } float num = 1f + ValConfig.SwimmingSpeedFactor.Value * skillFactor; return __instance.m_swimSpeed + num; } } [HarmonyPatch(typeof(Player))] public static class SwimmingReduceStaminaCostPatch { [HarmonyTranspiler] [HarmonyPatch("OnSwimming")] public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Mul, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Character), "UseStamina", (Type[])null, (Type[])null), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)ModifySwimCost) }) .ThrowIfNotMatch("Unable to patch Swim Stamina cost reduction.", Array.Empty()); return val.Instructions(); } public static float ModifySwimCost(float swimCost) { if (!ValConfig.EnableSwimming.Value || !ValConfig.EnableSwimStaminaCostReduction.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return swimCost; } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)103); if ((float)ValConfig.SwimStaminaReductionLevel.Value > skillFactor * 100f) { return swimCost; } return (1f - ValConfig.SwimStaminaCostReductionFactor.Value * skillFactor) * swimCost; } } } public static class Voyaging { [HarmonyPatch(typeof(Ship), "GetSailForce")] public static class VoyagerSpeedPatch { private static void Postfix(Ship __instance, ref Vector3 __result, float dt) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0066: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) if (!ValConfig.EnableVoyager.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return; } current_update_time += dt; if (__instance.IsPlayerInBoat(Player.m_localPlayer) && update_timer <= current_update_time) { update_timer = current_update_time + (float)ValConfig.VoyagerSkillXPCheckFrequency.Value; Vector3 velocity = ((Character)Player.m_localPlayer).GetVelocity(); bool flag = Mathf.Abs(velocity.x) > 1.5f || Mathf.Abs(velocity.z) > 1.5f; Logger.LogDebug($"Checking to raise voyager: x-vel: {velocity.x}, z-vel: {velocity.z} | skill gain speed? {flag}"); if (flag) { Logger.LogDebug("Raising player voyager skill."); ((Character)Player.m_localPlayer).RaiseSkill(VoyagingSkill, ValConfig.VoyagerSkillGainRate.Value * 1f); } } float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor(VoyagingSkill); if (skillFactor > 0f) { float num = 1f + skillFactor * ValConfig.VoyagerSailingSpeedFactor.Value; __result *= num; } if (!ValConfig.EnableFriendsRowSpeedBonus.Value || __instance.m_players.Count <= 1) { return; } float num2 = 1f; foreach (Player player in __instance.m_players) { if (!((Object)(object)player == (Object)(object)Player.m_localPlayer)) { num2 += ((Character)player).GetSkillFactor(VoyagingSkill) * ValConfig.MaxFriendsRowSpeedBonus.Value; } } __result *= num2; } } [HarmonyPatch(typeof(WearNTear))] public static class ShipDamageReduction { [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] private static void Prefix(WearNTear __instance, ref HitData hit) { //IL_0001: 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_0067: Unknown result type (might be due to invalid IL or missing references) if ((int)__instance.m_materialType == 0 && ValConfig.EnableBoatDamageReduction.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && !(((Character)Player.m_localPlayer).GetSkillLevel(VoyagingSkill) < (float)ValConfig.BoatDamageReductionLevel.Value)) { Ship component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null) && component.m_players.Contains(Player.m_localPlayer)) { float num = ((Character)Player.m_localPlayer).GetSkillFactor(VoyagingSkill) * ValConfig.VoyagerDamageReductionAmount.Value; Logger.LogDebug($"Reducing Ship damage by {num * 100f}%"); ((DamageTypes)(ref hit.m_damage)).Modify(1f - num); } } } } [HarmonyPatch(typeof(ImpactEffect))] public static class ShipDamageImpactReduction { [HarmonyPatch(typeof(ImpactEffect), "Awake")] private static void Postfix(ImpactEffect __instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Player.m_localPlayer == (Object)null) && !(((Character)Player.m_localPlayer).GetSkillLevel(VoyagingSkill) < (float)ValConfig.VoyagerImpactResistanceLevel.Value)) { __instance.m_damageToSelf = false; } } } [HarmonyPatch(typeof(Ship))] public static class PaddlingIsFasterPatch { [HarmonyTranspiler] [HarmonyPatch("CustomFixedUpdate")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[7] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Ship), "m_body"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Ship), "m_body"), (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_1, (object)null, (string)null) }).Advance(3).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)PaddleSpeedImprovement) }) .ThrowIfNotMatch("Unable to patch paddle speed improvement.", Array.Empty()); return val.Instructions(); } public static Vector3 PaddleSpeedImprovement(Vector3 ship_motion) { //IL_0055: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableVoyager.Value && (Object)(object)Player.m_localPlayer != (Object)null) { float skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel(VoyagingSkill); if (skillLevel >= ValConfig.VoyagerPaddleSpeedBonusLevel.Value) { return ship_motion * (1f + ValConfig.VoyagerPaddleSpeedBonus.Value * (skillLevel / 100f)); } } return ship_motion; } } [HarmonyPatch(typeof(Ship), "GetWindAngleFactor")] public static class VoyagerAnglePatch { private static void Postfix(ref float __result) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableVoyager.Value && !((Object)(object)Player.m_localPlayer == (Object)null)) { float skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel(VoyagingSkill); if (skillLevel >= ValConfig.VoyagerReduceCuttingStart.Value && __result < 1f) { float num = skillLevel * 0.02f; float num2 = Mathf.Clamp(__result + num, __result, 1f); __result = num2; } } } } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(Vector3), typeof(float) })] private class VoyagerNotSoBlindWhileSailingPatch { private static void Prefix(ref float radius) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableVoyager.Value && (Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.m_attachedToShip && ((Character)Player.m_localPlayer).IsAttached()) { radius *= ((Character)Player.m_localPlayer).GetSkillFactor(VoyagingSkill) * ValConfig.VoyagerIncreaseExplorationRadius.Value + 1f; } } } public static SkillType VoyagingSkill; private static float update_timer; private static float current_update_time; public static void SetupSailingSkill() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_004d: 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) SkillConfig val = new SkillConfig(); val.Name = "$skill_Voyager"; val.Description = "$skill_Voyager_description"; val.Icon = ImpactfulSkills.EmbeddedResourceBundle.LoadAsset("Assets/Custom/Icons/skill_icons/voyager.png"); val.Identifier = "midnightsfx.voyager"; val.IncreaseStep = 0.15f; VoyagingSkill = SkillManager.Instance.AddSkill(val); } } internal class WeaponSkill { [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] public static class ItemDisplay { public static void Postfix(ItemData item, ref string __result) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (!ValConfig.EnableWeaponSkill.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return; } List list = __result.Split(new char[1] { '\n' }).ToList(); List list2 = new List(list); for (int i = 0; i < list.Count; i++) { if (list[i].Contains("item_staminause")) { float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor(item.m_shared.m_skillType); list2[i] = "$item_staminause: " + item.m_shared.m_attack.m_attackStamina + " (" + Mathf.RoundToInt(ModifyWeaponStaminaCostBySkillLevelInheritFactor(item.m_shared.m_attack.m_attackStamina, 0.33f, skillFactor)) + ")"; } else if (list[i].Contains("item_staminahold")) { float skillFactor2 = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)8); list2[i] = "$item_staminahold: " + item.m_shared.m_attack.m_drawStaminaDrain + " (" + Mathf.RoundToInt(item.m_shared.m_attack.m_drawStaminaDrain - item.m_shared.m_attack.m_drawStaminaDrain * ValConfig.WeaponSkillBowDrawStaminaCostReduction.Value * skillFactor2) + ")/s"; } } __result = string.Join("\n", list2); } } [HarmonyPatch(typeof(ItemData))] public static class ModifyStaimaDrainBows { [HarmonyTranspiler] [HarmonyPatch("GetDrawStaminaDrain")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Dup, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)null, (string)null) }).Advance(1).RemoveInstructions(1) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate>((Func)ModifyStaminaDrainCostForBow) }) .ThrowIfNotMatch("Unable to patch Stamina reduction for bows compatibility.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(Humanoid))] public static class ParryGivesBonusXP { [HarmonyTranspiler] [HarmonyPatch("BlockAttack")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(Humanoid), "m_perfectBlockEffect"), (string)null) }).Advance(2).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate((Action)ExtraXPForParryBlock) }) .ThrowIfNotMatch("Unable to patch extra XP for Parry block.", Array.Empty()); return val.Instructions(); } } [HarmonyPatch(typeof(Attack))] public static class ModifyStaimaDrainWeapons { [HarmonyTranspiler] [HarmonyPatch("GetAttackStamina")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[8] { new CodeMatch((OpCode?)OpCodes.Ldloc_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Mul, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Mul, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Sub, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Stloc_0, (object)null, (string)null) }).RemoveInstruction().Advance(2) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldloc_1, (object)null), Transpilers.EmitDelegate>((Func)ModifyWeaponStaminaCostBySkillLevelInheritFactor) }) .RemoveInstructions(4) .ThrowIfNotMatch("Unable to patch stamina cost reduction modification, inherit modifier compatibility.", Array.Empty()); return val.Instructions(); } } private static class EquipSpeedHelper { public static float Apply(float duration, ItemData item) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return duration; } float num = ((Character)Player.m_localPlayer).GetSkillFactor(item.m_shared.m_skillType) * 100f; float num2 = 1f + num / 100f * ValConfig.WeaponSkillEquipSpeedFactor.Value; if (num > (float)ValConfig.WeaponSkillEquipRequiredLevel.Value) { return duration / num2; } return duration; } } [HarmonyPatch(typeof(Player), "QueueEquipAction")] public static class ModifyEquipSpeed_On { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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 //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(SharedData), "m_equipDuration"); CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo, (string)null) }); val.Advance(1); val.Insert((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(EquipSpeedHelper), "Apply", (Type[])null, (Type[])null)) }); return val.InstructionEnumeration(); } } [HarmonyPatch(typeof(Player), "QueueUnequipAction")] public static class ModifyEquipSpeed_Off { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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 //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(SharedData), "m_equipDuration"); CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo, (string)null) }); val.Advance(1); val.Insert((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(EquipSpeedHelper), "Apply", (Type[])null, (Type[])null)) }); return val.InstructionEnumeration(); } } private static float ModifyStaminaDrainCostForBow() { if (!ValConfig.EnableWeaponSkill.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return 0.33f; } float num = 0.33f - ValConfig.WeaponSkillBowDrawStaminaCostReduction.Value * 0.33f * ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)8); if (num < 0.01f) { num = 0.01f; } return num; } private static float ModifyWeaponStaminaCostBySkillLevelInheritFactor(float stam_cost, float reduce_factor, float skillfactor) { if (!ValConfig.EnableWeaponSkill.Value) { float num = stam_cost * reduce_factor * skillfactor; return stam_cost - num; } float num2 = stam_cost * ValConfig.WeaponSkillStaminaReduction.Value * skillfactor; num2 *= 1f + reduce_factor; return stam_cost - num2; } private static void ExtraXPForParryBlock() { if (ValConfig.EnableWeaponSkill.Value && (Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).RaiseSkill((SkillType)6, ValConfig.WeaponSkillParryBonus.Value); } } } public static class Woodcutting { [HarmonyPatch(typeof(TreeLog), "Damage")] public static class IncreaseTreeLogDamage { private static void Prefix(HitData hit) { ModifyChop(hit); } } [HarmonyPatch(typeof(TreeBase), "Damage")] public static class IncreaseTreeBaseDamage { private static void Prefix(HitData hit) { ModifyChop(hit); } } [HarmonyPatch(typeof(Destructible), "Damage")] public static class DestructibleIncreaseChopDamage { private static void Prefix(Destructible __instance, HitData hit) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 if ((ValConfig.EnableWoodcutting.Value && (int)__instance.m_destructibleType == 2) || ((int)__instance.m_destructibleType == 1 && ((Object)((Component)__instance).gameObject).name == "shrub_2")) { ModifyChop(hit); } } } [HarmonyPatch(typeof(TreeLog), "Destroy")] public static class IncreaseDropsFromTree { private static void Postfix(TreeLog __instance, HitData hitData) { //IL_001d: 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) if (ValConfig.EnableWoodcutting.Value && hitData != null && (Object)(object)Player.m_localPlayer != (Object)null && hitData.m_attacker == ((Character)Player.m_localPlayer).GetZDOID()) { IncreaseTreeLogDrops(__instance); } } } [HarmonyPatch(typeof(Destructible), "Destroy")] public static class IncreaseDropsFromDestructibleTree { private static void Prefix(Destructible __instance, HitData hit) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0026: 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) if (ValConfig.EnableWoodcutting.Value && (int)__instance.m_destructibleType == 2 && hit != null && (Object)(object)Player.m_localPlayer != (Object)null && hit.m_attacker == ((Character)Player.m_localPlayer).GetZDOID()) { IncreaseDestructibleTreeDrops(__instance); } } } [HarmonyPatch(typeof(TreeBase))] public static class DamageHandler_Apply_Patch { [HarmonyTranspiler] [HarmonyPatch("RPC_Damage")] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldloc_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)null, (string)null) }).Advance(3).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), Transpilers.EmitDelegate>((Action)IncreaseTreeDrops) }) .ThrowIfNotMatch("Unable to patch drop increase for trees.", Array.Empty()); return val.Instructions(); } } public static void ModifyChop(HitData hit) { //IL_0023: 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) if (ValConfig.EnableWoodcutting.Value && hit != null && (Object)(object)Player.m_localPlayer != (Object)null && hit.m_attacker == ((Character)Player.m_localPlayer).GetZDOID()) { float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)13); Logger.LogDebug($"Player skillfactor: {skillFactor}"); float num = 1f + ValConfig.WoodCuttingDmgMod.Value * (skillFactor * 100f) / 100f; Logger.LogDebug($"Player woodcutting dmg multiplier: {num}"); hit.m_damage.m_chop *= num; } } public static void IncreaseDestructibleTreeDrops(Destructible dtree) { //IL_0006: 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_0024: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)dtree).transform.position; DropTable val = ((Component)dtree).GetComponent()?.m_dropWhenDestroyed; if (val != null) { IncreaseWoodDrops(val, position); } } public static void IncreaseTreeLogDrops(TreeLog tree) { //IL_0006: 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_0012: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)tree).transform.position; IncreaseWoodDrops(tree.m_dropWhenDestroyed, position); } public static void IncreaseTreeDrops(TreeBase tree) { //IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableWoodcutting.Value) { Vector3 position = ((Component)tree).transform.position; IncreaseWoodDrops(tree.m_dropWhenDestroyed, position); } } public static void IncreaseWoodDrops(DropTable drops, Vector3 position) { //IL_0017: 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_001f: 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_005d: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (DropData drop in drops.m_drops) { if (dictionary.ContainsKey(drop.m_item)) { dictionary[drop.m_item] += drop.m_stackMin; } else { dictionary.Add(drop.m_item, drop.m_stackMin); } } int num = 0; float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor((SkillType)13); float num2 = (float)drops.m_dropMin * (ValConfig.WoodCuttingLootFactor.Value * (skillFactor * 100f)) / 100f; float num3 = (float)drops.m_dropMax * (ValConfig.WoodCuttingLootFactor.Value * (skillFactor * 100f)) / 100f; if (num2 <= 1f || num3 <= 1f) { return; } if (num2 > 0f && num3 > 0f && num2 != num3) { num = Random.Range((int)num2, (int)num3); } else if (num2 == num3) { num = (int)Math.Round(num2, 0); } Logger.LogDebug($"Tree drop increase min_drop: ({drops.m_dropMin}) {num2}, max_drop: ({drops.m_dropMax}) {num3} drop amount: {num}"); if (dictionary.Count <= 0) { return; } foreach (KeyValuePair item in dictionary) { Quaternion val = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f); int maxStackSize = item.Key.GetComponent().m_itemData.m_shared.m_maxStackSize; if (num > maxStackSize) { int num4 = num / maxStackSize; for (int i = 0; i < num4; i++) { Object.Instantiate(item.Key, position, val).GetComponent().m_itemData.m_stack = maxStackSize; Logger.LogDebug($"Dropping {maxStackSize} of {((Object)item.Key).name} to the world."); } num -= maxStackSize * num4; } else { Object.Instantiate(item.Key, position, val).GetComponent().m_itemData.m_stack = num; Logger.LogDebug($"Dropping {num} of {((Object)item.Key).name} to the world."); } } } } } namespace ImpactfulSkills.compatibility { internal static class Modcheck { public static bool IsSNEAKerEnabled; public static bool IsMagicPluginEnabled; public static bool IsCrystalMagicalEnabled; public static bool IsPlantEasilyEnabled; public static bool IsGathilFarmGridEnabled; public static bool IsVentureFarmGridEnabled; public static bool IsXeioMassFarmingEnabled; public static bool IsComfyMassFarmingEnabled; internal static void CheckModCompat() { try { Dictionary plugins = BepInExUtils.GetPlugins(false); if (plugins != null) { if (plugins.Keys.Contains("blacks7ar.SNEAKer")) { IsSNEAKerEnabled = true; } if (plugins.Keys.Contains("blacks7ar.MagicPlugin")) { IsMagicPluginEnabled = true; } if (plugins.Keys.Contains("dev.crystal.magical")) { IsCrystalMagicalEnabled = true; } if (plugins.Keys.Contains("advize.PlantEasily")) { IsPlantEasilyEnabled = true; } if (plugins.Keys.Contains("fr.galathil.FarmGrid")) { IsGathilFarmGridEnabled = true; } if (plugins.Keys.Contains("com.orianaventure.mod.VentureFarmGrid")) { IsVentureFarmGridEnabled = true; } if (plugins.Keys.Contains("xeio.MassFarming")) { IsXeioMassFarmingEnabled = true; } if (plugins.Keys.Contains("EardwulfDoesMods.Comfy.MassFarming")) { IsComfyMassFarmingEnabled = true; } } } catch { Logger.LogWarning("Unable to check mod compatibility. Ensure that Bepinex can load."); } } internal static bool OtherFarmingGridModPresent() { if (IsPlantEasilyEnabled || IsGathilFarmGridEnabled || IsVentureFarmGridEnabled || IsXeioMassFarmingEnabled || IsComfyMassFarmingEnabled) { return true; } return false; } } internal static class PlantEasily { internal static class API { private static Type apiType = AccessTools.TypeByName("PlantEasily.GhostLimitAPI"); private static MethodInfo register = apiType.GetMethod("RegisterGhostLimitProvider", BindingFlags.Static | BindingFlags.Public); public static bool IsAvailable => apiType != null; internal static void RegisterPlantEasilyLimit() { register.Invoke(null, new object[2] { "ImpactfulSkills.modules.Multiplant.PlantGrid", (Func)(() => PlantGrid.MaxToPlantAtOnce()) }); } } } } namespace ImpactfulSkills.common { internal static class Util { public static CodeMatcher CreateLabelOffset(this CodeMatcher matcher, out Label label, int offset = 0) { return matcher.CreateLabelAt(matcher.Pos + offset, ref label); } public static CodeMatcher ExtractLabels(this CodeMatcher matcher, out List