Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Afrek Expanded Skills v1.0.0
plugins/Afrek.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using Afrek.Core; using Afrek.Dev; using Afrek.Feats; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Afrek { public static class Cfg { public static ConfigEntry<float> GainRate; private static readonly Dictionary<SkillId, ConfigEntry<bool>> s_enabled = new Dictionary<SkillId, ConfigEntry<bool>>(); public static void Bind(ConfigFile c) { //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_000d: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; GainRate = c.Bind<float>("1 - General", "SkillGainRate", 1f, new ConfigDescription("How fast all Afrek skills grow (1 = as designed, 0 = not at all). The world's own skill gain setting applies on top.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), new object[1] { val })); SkillDef[] all = SkillTable.All; foreach (SkillDef skillDef in all) { s_enabled[skillDef.Id] = c.Bind<bool>("2 - Skills", skillDef.Id.ToString(), true, new ConfigDescription("The " + skillDef.NameEn + " skill. Off: it neither grows nor helps (the level stays in the save). Switch it off if another mod already adds such a skill.", (AcceptableValueBase)null, new object[1] { val })); } } public static bool Enabled(SkillId id) { if (s_enabled.TryGetValue(id, out var value)) { return value.Value; } return false; } internal static void SetEnabledForTest(SkillId id, bool on) { if (s_enabled.TryGetValue(id, out var value)) { value.Value = on; } } } public static class Lang { private static readonly (string key, string en, string de)[] Texts = new(string, string, string)[21] { ("afrek_msg_thread_saved", "Cut thriftily: {0} {1} left over", "Sparsam zugeschnitten: {0} {1} übrig"), ("afrek_weather_turns", "The weather is turning", "Das Wetter schlägt um"), ("afrek_weather_soon", "Soon: {0}", "Bald: {0}"), ("afrek_weather_stays", "Stays: {0}", "Bleibt: {0}"), ("afrek_weather_then", "then {0}", "dann {0}"), ("afrek_minutes", "{0} min", "{0} Min."), ("afrek_weather_clear", "clear", "klar"), ("afrek_weather_rain", "rain", "Regen"), ("afrek_weather_lightrain", "drizzle", "Nieselregen"), ("afrek_weather_swamprain", "swamp rain", "Sumpfregen"), ("afrek_weather_mist", "mist", "Nebel"), ("afrek_weather_forestmist", "forest mist", "Waldnebel"), ("afrek_weather_haze", "haze", "Dunst"), ("afrek_weather_thunder", "thunderstorm", "Gewitter"), ("afrek_weather_snow", "snow", "Schnee"), ("afrek_weather_snowstorm", "blizzard", "Schneesturm"), ("afrek_weather_ashrain", "ash rain", "Ascheregen"), ("afrek_weather_cinderrain", "cinder rain", "Glutregen"), ("afrek_weather_ashstorm", "ash storm", "Aschesturm"), ("afrek_weather_seastorm", "sea storm", "Seesturm"), ("afrek_home", "Home: {0}", "Heimweg: {0}") }; public static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); Dictionary<string, string> dictionary2 = new Dictionary<string, string>(); (string, string, string)[] texts = Texts; for (int i = 0; i < texts.Length; i++) { (string, string, string) tuple = texts[i]; string item = tuple.Item1; string item2 = tuple.Item2; string item3 = tuple.Item3; dictionary[item] = item2; dictionary2[item] = item3; } SkillDef[] all = SkillTable.All; foreach (SkillDef skillDef in all) { dictionary[skillDef.Token] = skillDef.NameEn; dictionary2[skillDef.Token] = skillDef.NameDe; dictionary[skillDef.Token + "_desc"] = skillDef.DescEn; dictionary2[skillDef.Token + "_desc"] = skillDef.DescDe; } string text = "English"; localization.AddTranslation(ref text, dictionary); text = "German"; localization.AddTranslation(ref text, dictionary2); } public static string T(string token, params object[] args) { string text = ((Localization.instance != null) ? Localization.instance.Localize("$" + token) : token); if (args == null || args.Length == 0) { return text; } try { return string.Format(text, args); } catch (FormatException) { return text; } } } [BepInPlugin("zap.afrek", "Afrek", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class AfrekPlugin : BaseUnityPlugin { public const string PluginGuid = "zap.afrek"; public const string PluginName = "Afrek"; public const string PluginVersion = "1.0.0"; private Harmony _harmony; public static AfrekPlugin Instance { get; private set; } public static string PluginDir { get; private set; } public static ManualLogSource Log { get; private set; } public static string AssetPath(string fileName) { return Path.Combine(PluginDir ?? "", "Assets", fileName); } private void Awake() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); Cfg.Bind(((BaseUnityPlugin)this).Config); Lang.Register(); AfrekSkills.Register(); Insight.Register(); _harmony = new Harmony("zap.afrek"); _harmony.PatchAll(typeof(AfrekPlugin).Assembly); SelfTest.TryStart(((Component)this).gameObject); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } } namespace Afrek.Feats { public static class AfrekSkills { private static readonly Dictionary<SkillId, SkillType> s_types = new Dictionary<SkillId, SkillType>(); private static readonly Dictionary<SkillId, SkillConfig> s_configs = new Dictionary<SkillId, SkillConfig>(); public static void Register() { //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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) SkillDef[] all = SkillTable.All; foreach (SkillDef skillDef in all) { SkillConfig val = new SkillConfig { Identifier = skillDef.Identifier, Name = "$" + skillDef.Token, Description = "$" + skillDef.Token + "_desc", IncreaseStep = 1f }; s_types[skillDef.Id] = SkillManager.Instance.AddSkill(val); s_configs[skillDef.Id] = val; } PrefabManager.OnVanillaPrefabsAvailable += SetIcons; } private static void SetIcons() { SkillDef[] all = SkillTable.All; foreach (SkillDef skillDef in all) { Sprite val = null; string[] icon = skillDef.Icon; foreach (string text in icon) { GameObject prefab = PrefabManager.Instance.GetPrefab(text); if (!((Object)(object)prefab == (Object)null)) { ItemDrop component = prefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData.m_shared.m_icons != null && component.m_itemData.m_shared.m_icons.Length != 0) { val = component.m_itemData.m_shared.m_icons[0]; } else if ((Object)(object)prefab.GetComponent<Piece>() != (Object)null) { val = prefab.GetComponent<Piece>().m_icon; } if ((Object)(object)val != (Object)null) { break; } } } if ((Object)(object)val == (Object)null) { AfrekPlugin.Log.LogWarning((object)("no icon for skill " + skillDef.Key + " (" + string.Join(", ", skillDef.Icon) + ")")); } s_configs[skillDef.Id].Icon = val; } } public static Sprite Icon(SkillId id) { if (!s_configs.TryGetValue(id, out var value)) { return null; } return value.Icon; } public static SkillType Type(SkillId id) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (!s_types.TryGetValue(id, out var value)) { return (SkillType)0; } return value; } public static bool Enabled(SkillId id) { return Cfg.Enabled(id); } public static float Factor(Player p, SkillId id) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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) if ((Object)(object)p == (Object)null || !Enabled(id)) { return 0f; } SkillType val = Type(id); if ((int)val != 0) { return ((Character)p).GetSkillFactor(val); } return 0f; } public static float LocalFactor(SkillId id) { return Factor(Player.m_localPlayer, id); } public static void Raise(Player p, SkillId id, float points) { //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_0026: 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) if ((Object)(object)p == (Object)null || !Enabled(id)) { return; } SkillType val = Type(id); float num = points * Cfg.GainRate.Value; if ((int)val != 0 && !(num <= 0f)) { int num2 = 0; while (num > 0f && num2 < 1000) { float num3 = Mathf.Min(num, 0.5f); ((Character)p).RaiseSkill(val, num3); num -= num3; num2++; } } } public static void RaiseLocal(SkillId id, float points) { Raise(Player.m_localPlayer, id, points); } public static float Level(Player p, SkillId id) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) SkillType val = Type(id); if (!((Object)(object)p == (Object)null) && (int)val != 0) { return ((Character)p).GetSkills().GetSkillLevel(val); } return 0f; } } internal static class Animals { [HarmonyPatch(typeof(Tameable), "DecreaseRemainingTime")] private static class TameFaster { private static void Prefix(Tameable __instance, ref float time) { //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_003d: 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) if (Cfg.Enabled(SkillId.AnimalHandling) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsOwner()) { Vector3 position = ((Component)__instance).transform.position; time *= 1f + 1f * Shared.Best(position, 60f, SkillId.AnimalHandling); Shared.RaiseNearby(position, 60f, SkillId.AnimalHandling, 0.15f); } } } [HarmonyPatch(typeof(Tameable), "Tame")] private static class TameDone { private static void Prefix(Tameable __instance, out bool __state) { __state = (Object)(object)__instance.m_character != (Object)null && !__instance.m_character.IsTamed(); } private static void Postfix(Tameable __instance, bool __state) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (__state && !((Object)(object)__instance.m_character == (Object)null) && __instance.m_character.IsTamed()) { Shared.Raise(Player.GetClosestPlayer(((Component)__instance).transform.position, 30f), SkillId.AnimalHandling, 10f); } } } [HarmonyPatch(typeof(Tameable), "Interact")] private static class Pet { private static void Postfix(Tameable __instance, Humanoid user, bool hold, bool alt) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) if (hold || alt || (Object)(object)user != (Object)(object)Player.m_localPlayer || (Object)(object)__instance.m_character == (Object)null || !__instance.m_character.IsTamed()) { return; } ZDOID zDOID = __instance.m_character.GetZDOID(); if (!s_lastPet.TryGetValue(zDOID, out var value) || !(Time.time - value < 60f)) { s_lastPet[zDOID] = Time.time; if (Time.time - s_lastPetPoints >= 30f) { s_lastPetPoints = Time.time; AfrekSkills.Raise(Player.m_localPlayer, SkillId.AnimalHandling, 0.5f); } float num = __instance.m_character.GetMaxHealth() * Tuning.Chance(0.1f, AfrekSkills.LocalFactor(SkillId.AnimalHandling)); Character character = __instance.m_character; if (num >= 1f && character.GetHealth() < character.GetMaxHealth()) { character.Heal(num, true); } } } } [HarmonyPatch(typeof(Procreation), "Procreate")] private static class Breed { private struct State { public float Chance; public float Duration; public float Skill; public bool Due; } private static void Prefix(Procreation __instance, out State __state) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) __state = new State { Chance = __instance.m_pregnancyChance, Duration = __instance.m_pregnancyDuration }; if (!((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner() && Cfg.Enabled(SkillId.Breeding)) { float num = (__state.Skill = Shared.Best(((Component)__instance).transform.position, 30f, SkillId.Breeding)); __instance.m_pregnancyChance = __state.Chance * (1f - 0.5f * num); __instance.m_pregnancyDuration = Tuning.Shorter(__state.Duration, 0.4f, num); __state.Due = __instance.IsPregnant() && __instance.IsDue(); } } private static void Postfix(Procreation __instance, State __state) { //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_003e: 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_00a8: Unknown result type (might be due to invalid IL or missing references) if (__state.Due && !__instance.IsPregnant()) { Vector3 position = ((Component)__instance).transform.position; if ((Object)(object)__instance.m_offspring != (Object)null && (Object)(object)__instance.m_offspring.GetComponent<Character>() != (Object)null) { Shared.RaiseNearby(position, 30f, SkillId.Breeding, 5f); } ZDO zDO = __instance.m_nview.GetZDO(); if (zDO.GetBool(KeyTwin, false)) { zDO.Set(KeyTwin, false); } else if (!(Random.value >= Tuning.Chance(0.15f, __state.Skill)) && SpawnSystem.GetNrOfInstances(__instance.m_myPrefab, position, __instance.m_totalCheckRange, false, false) + SpawnSystem.GetNrOfInstances(__instance.m_offspringPrefab, position, __instance.m_totalCheckRange, false, false) < __instance.m_maxCreatures) { zDO.Set(KeyTwin, true); long ticks = ZNet.instance.GetTime().AddSeconds(0f - __state.Duration - 1f).Ticks; zDO.Set(ZDOVars.s_pregnant, ticks); } } } private static void Finalizer(Procreation __instance, State __state) { __instance.m_pregnancyChance = __state.Chance; __instance.m_pregnancyDuration = __state.Duration; } } [HarmonyPatch(typeof(Growup), "GrowUpdate")] private static class GrowFaster { private static void Prefix(Growup __instance, out float __state) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_008f: Unknown result type (might be due to invalid IL or missing references) __state = __instance.m_growTime; if (Cfg.Enabled(SkillId.Breeding) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { Vector3 position = ((Component)__instance).transform.position; float f = Shared.Best(position, 30f, SkillId.Breeding); __instance.m_growTime = Tuning.Shorter(__state, 0.3f, f); if ((Object)(object)__instance.m_baseAI != (Object)null && __instance.m_baseAI.GetTimeSinceSpawned().TotalSeconds > (double)__instance.m_growTime) { Shared.RaiseNearby(position, 30f, SkillId.Breeding, 2f); } } } private static void Finalizer(Growup __instance, float __state) { __instance.m_growTime = __state; } } [HarmonyPatch(typeof(EggGrow), "GrowUpdate")] private static class HatchFaster { private static void Prefix(EggGrow __instance, out float __state) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_00c6: Unknown result type (might be due to invalid IL or missing references) __state = __instance.m_growTime; if (Cfg.Enabled(SkillId.Breeding) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { Vector3 position = ((Component)__instance).transform.position; float f = Shared.Best(position, 30f, SkillId.Breeding); __instance.m_growTime = Tuning.Shorter(__state, 0.3f, f); float num = __instance.m_nview.GetZDO().GetFloat(ZDOVars.s_growStart, 0f); if (num > 0f && ZNet.instance.GetTimeSeconds() > (double)(num + __instance.m_growTime) && __instance.CanGrow() && (Object)(object)__instance.m_item != (Object)null && __instance.m_item.m_itemData.m_stack == 1) { Shared.RaiseNearby(position, 30f, SkillId.Breeding, 3f); } } } private static void Finalizer(EggGrow __instance, float __state) { __instance.m_growTime = __state; } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] private static class MoreMeat { private static void Postfix(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> __result) { Character character = __instance.m_character; if (__result == null || (Object)(object)character == (Object)null || !Cfg.Enabled(SkillId.Butchery) || character.m_lastHit == null) { return; } Character attacker = character.m_lastHit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val == (Object)null) { return; } float f = Shared.Factor(val, SkillId.Butchery); bool flag = false; for (int i = 0; i < __result.Count; i++) { KeyValuePair<GameObject, int> keyValuePair = __result[i]; if (!((Object)(object)keyValuePair.Key == (Object)null) && IsButcherable(((Object)keyValuePair.Key).name)) { flag = true; int num = Tuning.MoreAmount(keyValuePair.Value, 0.3f, f, Random.value); if (num != keyValuePair.Value) { __result[i] = new KeyValuePair<GameObject, int>(keyValuePair.Key, num); } } } if (flag) { Shared.Raise(val, SkillId.Butchery, 2f * (float)Mathf.Max(1, character.GetLevel())); } } } private const float TameRange = 60f; private static readonly Dictionary<ZDOID, float> s_lastPet = new Dictionary<ZDOID, float>(); private static float s_lastPetPoints = -1000f; private static readonly int KeyTwin = StringExtensionMethods.GetStableHashCode("afrek_twin"); private static readonly HashSet<string> Butcherable = new HashSet<string> { "RawMeat", "DeerMeat", "NeckTail", "WolfMeat", "LoxMeat", "HareMeat", "ChickenMeat", "SerpentMeat", "BugMeat", "AsksvinMeat", "VoltureMeat", "BjornMeat", "MooseMeat", "SealBlubber", "BoneMawSerpentMeat", "LeatherScraps", "DeerHide", "TrollHide", "WolfPelt", "LoxPelt", "ScaleHide", "AskHide", "BjornHide", "MooseHide", "SealHide", "SerpentScale", "Feathers" }; internal static bool IsButcherable(string prefab) { if (prefab != null) { return Butcherable.Contains(prefab); } return false; } } internal static class Crafting { [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] private static class Craft { private static void Prefix(InventoryGui __instance) { s_recipe = __instance.m_craftRecipe; s_multi = ((!__instance.m_multiCrafting) ? 1 : __instance.m_multiCraftAmount); s_consumed = false; } private static void Postfix(Player player) { Recipe s_recipe = Crafting.s_recipe; if (!((Object)(object)s_recipe == (Object)null) && !((Object)(object)s_recipe.m_item == (Object)null) && s_consumed && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && IsMeadBase(((Object)s_recipe.m_item).name)) { AfrekSkills.Raise(player, SkillId.Brewing, 3f * (float)s_multi); } } private static void Finalizer() { s_recipe = null; } } [HarmonyPatch(typeof(Player), "ConsumeResources")] private static class Thrifty { private static void Postfix(Player __instance, Requirement[] requirements, int qualityLevel, int multiplier) { if ((Object)(object)s_recipe == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } s_consumed = true; float f = AfrekSkills.Factor(__instance, SkillId.Spinning); bool flag = false; foreach (Requirement val in requirements) { if ((Object)(object)val.m_resItem == (Object)null || !IsCloth(((Object)val.m_resItem).name)) { continue; } int num = val.GetAmount(qualityLevel) * Mathf.Max(1, multiplier); if (num > 0) { flag = true; int num2 = Tuning.MoreAmount(num, 0.25f, f, Random.value) - num; if (num2 > 0) { ((Humanoid)__instance).GetInventory().AddItem(((Component)val.m_resItem).gameObject, num2); ((Character)__instance).Message((MessageType)1, Lang.T("afrek_msg_thread_saved", num2, Localization.instance.Localize(val.m_resItem.m_itemData.m_shared.m_name)), 0, (Sprite)null, false); } } } if (flag) { AfrekSkills.Raise(__instance, SkillId.Spinning, 3f * (float)Mathf.Max(1, multiplier)); } } } private static Recipe s_recipe; private static int s_multi; private static bool s_consumed; internal static bool IsMeadBase(string prefab) { if (prefab != null) { if (!prefab.StartsWith("MeadBase")) { return prefab == "BarleyWineBase"; } return true; } return false; } internal static bool IsCloth(string prefab) { if (!(prefab == "LinenThread")) { return prefab?.StartsWith("Jute") ?? false; } return true; } } internal static class Insight { public enum Kind { Weather, Home } public class SE_AfrekInsight : StatusEffect { public Kind m_kind; public override void UpdateStatusEffect(float dt) { ((StatusEffect)this).UpdateStatusEffect(dt); base.m_name = Label(m_kind); } public override string GetIconText() { return Detail(m_kind); } } [HarmonyPatch(typeof(Player), "Update")] private static class Keep { private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)s_weather == (Object)null)) { Insight.s_timer += Time.deltaTime; if (!(Insight.s_timer < 1f)) { float s_timer = Insight.s_timer; Insight.s_timer = 0f; UpdateWeather(__instance, AfrekSkills.Factor(__instance, SkillId.WeatherLore), s_timer); UpdateHome(__instance, AfrekSkills.Factor(__instance, SkillId.Navigation)); Show(__instance, s_weather, s_weatherLabel.Length > 0, SkillId.WeatherLore); Show(__instance, s_home, s_homeLabel.Length > 0, SkillId.Navigation); } } } } private static SE_AfrekInsight s_weather; private static SE_AfrekInsight s_home; private static string s_weatherLabel = ""; private static string s_weatherDetail = ""; private static string s_homeLabel = ""; private static string s_homeDetail = ""; private static readonly Dictionary<string, string> WeatherTokens = new Dictionary<string, string> { { "Clear", "clear" }, { "Heath clear", "clear" }, { "Mistlands_clear", "clear" }, { "Twilight_Clear", "clear" }, { "Rain", "rain" }, { "Mistlands_rain", "rain" }, { "LightRain", "lightrain" }, { "SwampRain", "swamprain" }, { "Misty", "mist" }, { "DeepForest Mist", "forestmist" }, { "Ashlands_misty", "haze" }, { "ThunderStorm", "thunder" }, { "Mistlands_thunder", "thunder" }, { "Snow", "snow" }, { "Twilight_Snow", "snow" }, { "SnowStorm", "snowstorm" }, { "Twilight_SnowStorm", "snowstorm" }, { "Ashlands_ashrain", "ashrain" }, { "Ashlands_CinderRain", "cinderrain" }, { "Ashlands_storm", "ashstorm" }, { "Ashlands_SeaStorm", "seastorm" } }; private static long s_lastPeriod = -1L; private static string s_lastEnv; private static readonly string[] CompassEn = new string[8] { "N", "NE", "E", "SE", "S", "SW", "W", "NW" }; private static readonly string[] CompassDe = new string[8] { "N", "NO", "O", "SO", "S", "SW", "W", "NW" }; private static float s_timer; public static void Register() { s_weather = Make(Kind.Weather, "AfrekWeatherSense"); s_home = Make(Kind.Home, "AfrekHomeSense"); } private static SE_AfrekInsight Make(Kind kind, string name) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown SE_AfrekInsight sE_AfrekInsight = ScriptableObject.CreateInstance<SE_AfrekInsight>(); ((Object)sE_AfrekInsight).name = name; sE_AfrekInsight.m_kind = kind; ((StatusEffect)sE_AfrekInsight).m_name = name; ((StatusEffect)sE_AfrekInsight).m_ttl = 0f; ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)sE_AfrekInsight, false)); return sE_AfrekInsight; } private static string Label(Kind k) { if (k != Kind.Weather) { return s_homeLabel; } return s_weatherLabel; } private static string Detail(Kind k) { if (k != Kind.Weather) { return s_homeDetail; } return s_weatherDetail; } internal static EnvSetup Predict(long period, BiomeSector biome, Vector3 at) { //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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0050: 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) EnvMan instance = EnvMan.instance; State state = Random.state; try { Random.InitState((int)period); List<EnvEntry> availableEnvironments = instance.GetAvailableEnvironments(biome); if (availableEnvironments == null || availableEnvironments.Count == 0) { return null; } availableEnvironments = new List<EnvEntry>(availableEnvironments); EnvSetup result = instance.SelectWeightedEnvironment(availableEnvironments); bool flag = WorldGenerator.IsAshlands(at.x, at.z); bool flag2 = WorldGenerator.IsDeepnorth(at.x, at.y); foreach (EnvEntry item in availableEnvironments) { if (item.m_ashlandsOverride && flag) { result = item.m_env; } if (item.m_deepnorthOverride && flag2) { result = item.m_env; } } return result; } finally { Random.state = state; } } internal static string WeatherName(EnvSetup e) { if (e == null) { return "?"; } if (!WeatherTokens.TryGetValue(e.m_name, out var value)) { return e.m_name.Replace('_', ' '); } return Lang.T("afrek_weather_" + value); } private static void UpdateWeather(Player p, float f, float dt) { //IL_0076: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) s_weatherLabel = (s_weatherDetail = ""); EnvMan instance = EnvMan.instance; if ((Object)(object)instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || instance.GetEnvironmentOverride() != null) { return; } long num = (long)ZNet.instance.GetTimeSeconds(); long environmentDuration = instance.m_environmentDuration; if (environmentDuration <= 0) { return; } long num2 = num / environmentDuration; Vector3 at = (((Object)(object)Utils.GetMainCamera() != (Object)null) ? ((Component)Utils.GetMainCamera()).transform.position : ((Component)p).transform.position); BiomeSector currentBiome = instance.m_currentBiome; EnvSetup val = Predict(num2, currentBiome, at); EnvSetup val2 = Predict(num2 + 1, currentBiome, at); bool flag = !p.InShelter() && !((Character)p).InInterior(); if (flag) { AfrekSkills.Raise(p, SkillId.WeatherLore, 0.025f * dt); } if (s_lastPeriod >= 0 && num2 != s_lastPeriod && flag && val != null && val.m_name != s_lastEnv) { AfrekSkills.Raise(p, SkillId.WeatherLore, 3f); } s_lastPeriod = num2; s_lastEnv = val?.m_name; float num3 = (num2 + 1) * environmentDuration - num; if (f <= 0f || val2 == null || num3 > Tuning.ForecastLead(f)) { return; } bool flag2 = val == null || val.m_name != val2.m_name; int num4 = Mathf.Max(1, Mathf.CeilToInt(num3 / 60f)); if (f < 0.2f) { if (flag2) { s_weatherLabel = Lang.T("afrek_weather_turns"); } return; } s_weatherLabel = Lang.T(flag2 ? "afrek_weather_soon" : "afrek_weather_stays", WeatherName(val2)); s_weatherDetail = Lang.T("afrek_minutes", num4); if (f >= 0.75f) { EnvSetup val3 = Predict(num2 + 2, currentBiome, at); if (val3 != null && val3.m_name != val2.m_name) { s_weatherLabel = s_weatherLabel + " · " + Lang.T("afrek_weather_then", WeatherName(val3)); } } } internal static bool Home(out Vector3 home) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) home = Vector3.zero; PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (val != null && val.HaveCustomSpawnPoint()) { home = val.GetCustomSpawnPoint(); return true; } if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.GetLocationIcon(Game.instance.m_StartLocation, ref home); } return false; } private static void UpdateHome(Player p, float f) { //IL_002f: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) s_homeLabel = (s_homeDetail = ""); if (f <= 0f || (Object)(object)Ship.GetLocalShip() == (Object)null || !Home(out var home)) { return; } Vector3 val = home - ((Component)p).transform.position; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; if (!(magnitude < 50f)) { float num = (Mathf.Atan2(val.x, val.z) * 57.29578f + 360f) % 360f; string text = ((Localization.instance != null && Localization.instance.GetSelectedLanguage() == "German") ? CompassDe : CompassEn)[Mathf.RoundToInt(num / 45f) % 8]; if (f >= 0.75f) { s_homeLabel = Lang.T("afrek_home", $"{text} {Mathf.RoundToInt(num)}°"); } else { s_homeLabel = Lang.T("afrek_home", text); } if (f >= 0.75f) { s_homeDetail = (magnitude / 1000f).ToString("0.0") + " km"; } else if (f >= 0.4f) { s_homeDetail = "~" + Mathf.Max(1, Mathf.RoundToInt(magnitude / 1000f)) + " km"; } } } private static void Show(Player p, SE_AfrekInsight se, bool on, SkillId icon) { SEMan sEMan = ((Character)p).GetSEMan(); bool flag = sEMan.HaveStatusEffect(((StatusEffect)se).NameHash()); if (on && !flag) { ((StatusEffect)se).m_icon = AfrekSkills.Icon(icon); sEMan.AddStatusEffect((StatusEffect)(object)se, false, 0, 0f, (short)(-1)); } else if (!on && flag) { sEMan.RemoveStatusEffect(((StatusEffect)se).NameHash(), true); } } } internal static class Living { [HarmonyPatch(typeof(Player), "AddKnownText")] private static class NewLore { private static void Prefix(Player __instance, string label, out bool __state) { __state = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && !__instance.m_knownTexts.ContainsKey(label); } private static void Postfix(Player __instance, bool __state) { if (__state) { AfrekSkills.Raise(__instance, SkillId.RuneLore, 15f); } } } [HarmonyPatch(typeof(RuneStone), "Interact")] private static class ReadStone { private static void Postfix(RuneStone __instance, Humanoid character, bool hold) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0085: Unknown result type (might be due to invalid IL or missing references) Player val = (Player)(object)((character is Player) ? character : null); if (!hold && !((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !string.IsNullOrEmpty(__instance.m_label)) { Vector3 position = ((Component)__instance).transform.position; Vector3Int key = default(Vector3Int); ((Vector3Int)(ref key))..ctor(Mathf.RoundToInt(position.x), Mathf.RoundToInt(position.y), Mathf.RoundToInt(position.z)); if (!s_lastRead.TryGetValue(key, out var value) || !(Time.time - value < 600f)) { s_lastRead[key] = Time.time; AfrekSkills.Raise(val, SkillId.RuneLore, 2f); } } } } [HarmonyPatch(typeof(Vegvisir), "Interact")] private static class ReadVegvisir { private static void Postfix(Vegvisir __instance, Humanoid character, bool hold) { //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_002d: 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) Player val = (Player)(object)((character is Player) ? character : null); if (!hold && !((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { Vector3 position = ((Component)__instance).transform.position; string text = Mathf.RoundToInt(position.x) + "," + Mathf.RoundToInt(position.z); val.m_customData.TryGetValue("afrek_vegvisirs", out var value); value = value ?? ""; if (!value.Split(new char[1] { ';' }).Contains(text)) { val.m_customData["afrek_vegvisirs"] = ((value.Length == 0) ? text : (value + ";" + text)); AfrekSkills.Raise(val, SkillId.RuneLore, 10f); } } } } [HarmonyPatch(typeof(SleepText), "ShowDreamText")] private static class Dream { private static void Postfix(SleepText __instance) { if ((Object)(object)__instance.m_dreamField != (Object)null && ((Behaviour)__instance.m_dreamField).enabled && !string.IsNullOrEmpty(__instance.m_dreamField.text)) { AfrekSkills.RaiseLocal(SkillId.RuneLore, 5f); } } } [HarmonyPatch(typeof(Player), "RaiseSkill")] private static class LearnFaster { private static void Prefix(Player __instance, ref float value) { if (s_raising || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } s_raising = true; try { value *= 1f + 0.1f * AfrekSkills.Factor(__instance, SkillId.RuneLore); } finally { s_raising = false; } } } [HarmonyPatch(typeof(SE_Rested), "UpdateTTL")] private static class LongerRested { private static void Prefix(SE_Rested __instance, out float __state) { __state = ((StatusEffect)__instance).m_ttl; } private static void Postfix(SE_Rested __instance, float __state) { if (!((Object)(object)((StatusEffect)__instance).m_character != (Object)(object)Player.m_localPlayer) && !Mathf.Approximately(((StatusEffect)__instance).m_ttl, __state)) { ((StatusEffect)__instance).m_ttl = ((StatusEffect)__instance).m_ttl * (1f + 0.4f * AfrekSkills.LocalFactor(SkillId.CampLife)); } } } [HarmonyPatch(typeof(Player), "SetSleeping")] private static class Slept { private static void Prefix(Player __instance, bool sleep, out bool __state) { __state = __instance.m_sleeping && !sleep; } private static void Postfix(Player __instance, bool __state) { if (__state && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { AfrekSkills.Raise(__instance, SkillId.CampLife, 5f); } } } [HarmonyPatch(typeof(Player), "Update")] private static class Resting { private static void Postfix(Player __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Living.s_restTimer += Time.deltaTime; if (!(Living.s_restTimer < 5f)) { float s_restTimer = Living.s_restTimer; Living.s_restTimer = 0f; if (((Character)__instance).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectResting)) { AfrekSkills.Raise(__instance, SkillId.CampLife, 1f / 60f * s_restTimer); } } } } [HarmonyPatch(typeof(Player), "ConsumeItem")] private static class Drink { private static void Prefix(Player __instance, ItemData item, out int __state) { __state = -1; if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && item != null) { if ((Object)(object)item.m_shared.m_consumeStatusEffect != (Object)null && item.m_shared.m_food <= 0f && IsMead(item)) { s_drinking = item; } __state = ((Humanoid)__instance).GetInventory().CountItems(item.m_shared.m_name, -1, true); } } private static void Postfix(Player __instance, ItemData item, bool __result, int __state) { bool flag = s_drinking == item; s_drinking = null; if (__result && __state >= 0 && item != null && flag && item.m_shared.m_consumeStatusEffect.m_ttl >= 60f) { AfrekSkills.Raise(__instance, SkillId.Drinking, 3f); } } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(StatusEffect), typeof(bool), typeof(int), typeof(float), typeof(short) })] private static class MeadTime { private static void Postfix(SEMan __instance, StatusEffect __result) { if (s_drinking == null || (Object)(object)__result == (Object)null || (Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer || __result.m_ttl < 60f) { return; } float num = AfrekSkills.LocalFactor(SkillId.Drinking); if (!(num <= 0f)) { if (IsDraught(__result)) { __result.m_ttl *= 1f - 0.3f * num; } else { __result.m_ttl *= 1f + 0.3f * num; } } } } [HarmonyPatch(typeof(Player), "EatFood")] private static class Eat { private static void Postfix(Player __instance, ItemData item, bool __result) { if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || item == null) { return; } FoodKind foodKind = KindOf(item); if (foodKind == FoodKind.None) { return; } float num = LoverFactor(__instance, foodKind); foreach (Food food in __instance.m_foods) { if (food.m_item != null && food.m_item.m_shared.m_name == item.m_shared.m_name && num > 0f) { food.m_time = item.m_shared.m_foodBurnTime * (1f + 0.25f * num); } } SharedData shared = item.m_shared; float points = Tuning.MealPoints(shared.m_food, shared.m_foodStamina, shared.m_foodEitr, FoodKinds.Count(foodKind)); FoodKind[] singles = Singles; foreach (FoodKind foodKind2 in singles) { if ((foodKind & foodKind2) != FoodKind.None) { AfrekSkills.Raise(__instance, SkillOf(foodKind2), points); } } } } [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] private static class MoreFromFood { private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } foreach (Food food in __instance.m_foods) { if (food.m_item != null) { float num = 0.1f * LoverFactor(__instance, KindOf(food.m_item)); if (!(num <= 0f)) { hp += food.m_health * num; stamina += food.m_stamina * num; eitr += food.m_eitr * num; } } } } } private static readonly Dictionary<Vector3Int, float> s_lastRead = new Dictionary<Vector3Int, float>(); private const string VegvisirKey = "afrek_vegvisirs"; private static bool s_raising; private static float s_restTimer; private static ItemData s_drinking; private static readonly Dictionary<string, FoodKind> s_kinds = new Dictionary<string, FoodKind>(); private static readonly FoodKind[] Singles = new FoodKind[5] { FoodKind.Meat, FoodKind.Fish, FoodKind.Greens, FoodKind.Bread, FoodKind.Stew }; internal static bool IsMead(ItemData item) { string text = (((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : ""); if (!text.StartsWith("Mead")) { return text.StartsWith("BarleyWine"); } return true; } internal static bool IsDraught(StatusEffect se) { SE_Stats val = (SE_Stats)(object)((se is SE_Stats) ? se : null); if (val != null && !string.IsNullOrEmpty(se.m_category)) { if (!(val.m_healthOverTime > 0f) && !(val.m_staminaOverTime > 0f)) { return val.m_eitrOverTime > 0f; } return true; } return false; } internal static FoodKind KindOf(ItemData item) { if (item == null) { return FoodKind.None; } string token = item.m_shared.m_name; if (s_kinds.TryGetValue(token, out var value)) { return value; } string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : null); if (text == null && (Object)(object)ObjectDB.instance != (Object)null) { GameObject? obj = ((IEnumerable<GameObject>)ObjectDB.instance.m_items).FirstOrDefault((Func<GameObject, bool>)((GameObject g) => (Object)(object)g != (Object)null && g.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_name == token)); text = ((obj != null) ? ((Object)obj).name : null); } if (text == null) { return FoodKind.None; } value = FoodKinds.Of(text, (from q in (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetRecipe(item) : null)?.m_resources where (Object)(object)q.m_resItem != (Object)null select ((Object)q.m_resItem).name)); s_kinds[token] = value; return value; } internal static SkillId SkillOf(FoodKind single) { return single switch { FoodKind.Meat => SkillId.MeatLover, FoodKind.Fish => SkillId.FishLover, FoodKind.Bread => SkillId.BreadLover, FoodKind.Stew => SkillId.StewLover, _ => SkillId.GreensLover, }; } internal static float LoverFactor(Player p, FoodKind kind) { float num = 0f; FoodKind[] singles = Singles; foreach (FoodKind foodKind in singles) { if ((kind & foodKind) != FoodKind.None) { num = Mathf.Max(num, AfrekSkills.Factor(p, SkillOf(foodKind))); } } return num; } } internal static class Sea { [HarmonyPatch(typeof(Ship), "GetSailForce")] private static class SailForce { private static void Postfix(Ship __instance, ref Vector3 __result) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) float num = Shared.Factor(Captain(__instance), SkillId.Seamanship); if (num > 0f) { __result *= 1f + 0.15f * num; } } } [HarmonyPatch(typeof(Ship), "CustomFixedUpdate")] private static class Oars { private static void Prefix(Ship __instance, out float __state) { __state = __instance.m_backwardForce; if (!((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsOwner()) { float num = Shared.Factor(Captain(__instance), SkillId.Seamanship); if (num > 0f) { __instance.m_backwardForce = __state * (1f + 0.25f * num); } } } private static void Finalizer(Ship __instance, float __state) { __instance.m_backwardForce = __state; } } [HarmonyPatch(typeof(Ship), "ApplyControlls")] private static class Rudder { private static void Prefix(Ship __instance, out float __state) { __state = __instance.m_rudderSpeed; float num = AfrekSkills.LocalFactor(SkillId.Seamanship); if (num > 0f) { __instance.m_rudderSpeed = __state * (1f + 0.3f * num); } } private static void Finalizer(Ship __instance, float __state) { __instance.m_rudderSpeed = __state; } } [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] private static class Hull { private static void Prefix(WearNTear __instance, HitData hit) { if (hit == null || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsOwner()) { return; } Ship component = ((Component)__instance).GetComponent<Ship>(); if (!((Object)(object)component == (Object)null)) { float num = Shared.Factor(Captain(component), SkillId.Seamanship); if (num > 0f) { ((DamageTypes)(ref hit.m_damage)).Modify(1f - 0.35f * num); } } } } [HarmonyPatch(typeof(Ship), "GetWindAngleFactor")] private static class WindAngle { private static bool Prefix(Ship __instance, ref float __result) { //IL_0042: 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) if ((Object)(object)EnvMan.instance == (Object)null) { return true; } Player val = Captain(__instance); float num = (((Object)(object)val == (Object)(object)Player.m_localPlayer) ? AfrekSkills.LocalFactor(SkillId.Navigation) : Shared.Factor(val, SkillId.Navigation)); if (num <= 0f) { return true; } float dotWindBow = Vector3.Dot(EnvMan.instance.GetWindDir(), -((Component)__instance).transform.forward); __result = Tuning.WindAngleFactor(dotWindBow, num); return false; } } [HarmonyPatch(typeof(Player), "Update")] private static class Helm { private static void Postfix(Player __instance) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Ship controlledShip = __instance.GetControlledShip(); if ((Object)(object)controlledShip == (Object)null) { Sea.s_helmTimer = 0f; return; } Sea.s_helmTimer += Time.deltaTime; if (Sea.s_helmTimer < 1f) { return; } float s_helmTimer = Sea.s_helmTimer; Sea.s_helmTimer = 0f; float num = Mathf.Abs(controlledShip.GetSpeed()); if (controlledShip.IsSailUp() && num > 1f) { AfrekSkills.Raise(__instance, SkillId.Seamanship, 0.08f * Mathf.Min(1f, num / 6f) * s_helmTimer); if (Vector3.Dot(EnvMan.instance.GetWindDir(), -((Component)controlledShip).transform.forward) > 0.5f && controlledShip.GetWindAngleFactor() > 0.05f) { AfrekSkills.Raise(__instance, SkillId.Navigation, 0.05f * s_helmTimer); } } else if (num > 0.5f) { AfrekSkills.Raise(__instance, SkillId.Seamanship, 0.04f * s_helmTimer); } } } [HarmonyPatch(typeof(Minimap), "UpdateExplore")] private static class Sight { private static void Prefix(Minimap __instance, Player player, out float __state) { __state = __instance.m_exploreRadius; s_newPixels = 0; s_exploring = (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer; if (s_exploring) { bool flag = (Object)(object)Ship.GetLocalShip() != (Object)null; float num = AfrekSkills.Factor(player, flag ? SkillId.Navigation : SkillId.Cartography); if (num > 0f) { __instance.m_exploreRadius = __state * (1f + (flag ? 0.5f : 0.5f) * num); } } } private static void Finalizer(Minimap __instance, float __state) { __instance.m_exploreRadius = __state; } private static void Postfix(Minimap __instance, Player player, float __state) { bool s_exploring = Sea.s_exploring; Sea.s_exploring = false; if (s_exploring && s_newPixels != 0) { bool flag = (Object)(object)Ship.GetLocalShip() != (Object)null; AfrekSkills.Raise(player, flag ? SkillId.Navigation : SkillId.Cartography, (float)s_newPixels * (flag ? 0.01f : 0.03f)); s_newPixels = 0; } } } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(int), typeof(int) })] private static class NewPixel { private static void Postfix(bool __result) { if (__result && s_exploring) { s_newPixels++; } } } private static float s_helmTimer; private static int s_newPixels; private static bool s_exploring; internal static Player Captain(Ship s) { ShipControlls val = (((Object)(object)s != (Object)null) ? s.m_shipControlls : null); if (!((Object)(object)val != (Object)null) || !val.HaveValidUser()) { return null; } return Player.GetPlayer(val.GetUser()); } } public static class Shared { [HarmonyPatch(typeof(ZNet), "Awake")] private static class RegisterRpc { private static void Postfix() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.Register<int, float>("Afrek_Raise", (Action<long, int, float>)RPC_Raise); } } } [HarmonyPatch(typeof(Player), "Update")] private static class PublishSkills { private static void Postfix(Player __instance) { Publish(__instance, force: false); } } [HarmonyPatch(typeof(Player), "OnSpawned")] private static class PublishOnSpawn { private static void Postfix(Player __instance) { Publish(__instance, force: true); } } public const string RaiseRpc = "Afrek_Raise"; private static int[] s_keys; private static readonly float[] s_sent = new float[SkillTable.All.Length]; private static float s_nextPublish; private static int Key(SkillId id) { if (s_keys == null) { s_keys = new int[SkillTable.All.Length]; SkillDef[] all = SkillTable.All; foreach (SkillDef skillDef in all) { s_keys[(int)skillDef.Id] = StringExtensionMethods.GetStableHashCode("afrek_" + skillDef.Key); } } return s_keys[(int)id]; } public static float Factor(Player p, SkillId id) { if ((Object)(object)p == (Object)null || !Cfg.Enabled(id)) { return 0f; } if ((Object)(object)p == (Object)(object)Player.m_localPlayer) { return AfrekSkills.Factor(p, id); } ZDO val = (((Object)(object)((Character)p).m_nview != (Object)null && ((Character)p).m_nview.IsValid()) ? ((Character)p).m_nview.GetZDO() : null); if (val == null) { return 0f; } return Mathf.Clamp01(val.GetFloat(Key(id), 0f)); } public static float Best(Vector3 at, float range, SkillId id, out Player who) { //IL_0035: 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) who = null; float num = 0f; foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && !((Character)allPlayer).IsDead() && !(Vector3.Distance(((Component)allPlayer).transform.position, at) > range)) { float num2 = Factor(allPlayer, id); if ((Object)(object)who == (Object)null || num2 > num) { num = num2; who = allPlayer; } } } return num; } public static float Best(Vector3 at, float range, SkillId id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Player who; return Best(at, range, id, out who); } public static Player PlayerOf(long peer) { foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null && (Object)(object)((Character)allPlayer).m_nview != (Object)null && ((Character)allPlayer).m_nview.IsValid() && ((Character)allPlayer).m_nview.GetZDO().GetOwner() == peer) { return allPlayer; } } return null; } public static void Raise(Player p, SkillId id, float points) { if ((Object)(object)p == (Object)null || points <= 0f || !Cfg.Enabled(id)) { return; } if ((Object)(object)p == (Object)(object)Player.m_localPlayer) { AfrekSkills.Raise(p, id, points); return; } long num = (((Object)(object)((Character)p).m_nview != (Object)null && ((Character)p).m_nview.IsValid()) ? ((Character)p).m_nview.GetZDO().GetOwner() : 0); if (num != 0L) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(num, "Afrek_Raise", new object[2] { (int)id, points }); } } } public static void RaiseNearby(Vector3 at, float range, SkillId id, float points) { //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) foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null && !((Character)allPlayer).IsDead() && Vector3.Distance(((Component)allPlayer).transform.position, at) <= range) { Raise(allPlayer, id, points); } } } private static void RPC_Raise(long sender, int id, float points) { if (id >= 0 && id < SkillTable.All.Length && !(points <= 0f) && !(points > 50f)) { AfrekSkills.Raise(Player.m_localPlayer, (SkillId)id, points); } } internal static void Publish(Player p, bool force) { if ((Object)(object)p == (Object)null || (Object)(object)p != (Object)(object)Player.m_localPlayer || (Object)(object)((Character)p).m_nview == (Object)null || !((Character)p).m_nview.IsValid() || (!force && Time.time < s_nextPublish)) { return; } s_nextPublish = Time.time + 5f; ZDO zDO = ((Character)p).m_nview.GetZDO(); SkillDef[] all = SkillTable.All; foreach (SkillDef skillDef in all) { float num = AfrekSkills.Factor(p, skillDef.Id); if (force || !Mathf.Approximately(num, s_sent[(int)skillDef.Id])) { s_sent[(int)skillDef.Id] = num; zDO.Set(Key(skillDef.Id), num); } } } } public enum SkillId { Brewing, Smelting, Spinning, AnimalHandling, Breeding, Beekeeping, Butchery, Seamanship, Navigation, Cartography, WeatherLore, Trading, RuneLore, CampLife, Drinking, MeatLover, FishLover, GreensLover, BreadLover, StewLover } public sealed class SkillDef { public SkillId Id; public string Key; public string NameEn; public string NameDe; public string DescEn; public string DescDe; public string[] Icon; public string Identifier => "zap.afrek." + Key; public string Token => "afrek_skill_" + Key; } public static class SkillTable { public static readonly SkillDef[] All = new SkillDef[20] { new SkillDef { Id = SkillId.Brewing, Key = "brewing", NameEn = "Brewing", NameDe = "Brauen", DescEn = "Mead bases at the cauldron, barrels in the fermenter. Faster fermenting, now and then a bottle more.", DescDe = "Metgrundlagen am Kessel, Fässer im Gärbottich. Schneller gären, ab und zu eine Flasche mehr.", Icon = new string[2] { "fermenter", "MeadTasty" } }, new SkillDef { Id = SkillId.Smelting, Key = "smelting", NameEn = "Smelting", NameDe = "Hüttenkunde", DescEn = "Smelter, charcoal kiln, blast furnace and eitr refinery. Faster work, less fuel, now and then a bar more.", DescDe = "Schmelzofen, Meiler, Hochofen und Eitr-Raffinerie. Schneller, weniger Brennstoff, ab und zu ein Barren mehr.", Icon = new string[2] { "Iron", "Copper" } }, new SkillDef { Id = SkillId.Spinning, Key = "spinning", NameEn = "Spinning & Weaving", NameDe = "Spinnen & Weben", DescEn = "The spinning wheel and everything sewn from linen and jute. Faster spinning, a thread more now and then, thrifty weaving.", DescDe = "Das Spinnrad und alles aus Leinen und Jute. Schneller spinnen, ab und zu ein Faden mehr, sparsam weben.", Icon = new string[2] { "LinenThread", "piece_spinningwheel" } }, new SkillDef { Id = SkillId.AnimalHandling, Key = "animalhandling", NameEn = "Animal Handling", NameDe = "Tierkunde", DescEn = "Taming wild beasts and keeping tame ones. Faster taming, and a pat soothes their wounds.", DescDe = "Wilde Tiere zähmen und zahme halten. Schneller zähmen, und Streicheln lindert ihre Wunden.", Icon = new string[1] { "TrophyBoar" } }, new SkillDef { Id = SkillId.Breeding, Key = "breeding", NameEn = "Breeding", NameDe = "Züchter", DescEn = "Raising young from your tame animals. More matings, shorter pregnancies, quicker growth, now and then twins.", DescDe = "Nachwuchs von deinen zahmen Tieren. Mehr Paarungen, kürzere Trächtigkeit, schnelleres Wachsen, ab und zu Zwillinge.", Icon = new string[2] { "ChickenEgg", "TrophyHare" } }, new SkillDef { Id = SkillId.Beekeeping, Key = "beekeeping", NameEn = "Beekeeping", NameDe = "Imkerei", DescEn = "Keeping bees. Busier hives and now and then a honey more at the harvest.", DescDe = "Bienen halten. Fleißigere Stöcke und bei der Ernte ab und zu ein Honig mehr.", Icon = new string[2] { "QueenBee", "Honey" } }, new SkillDef { Id = SkillId.Butchery, Key = "butchery", NameEn = "Butchery & Tanning", NameDe = "Schlachten & Gerben", DescEn = "Cutting up game and taking its hide. More meat, hides and pelts from what you kill.", DescDe = "Wild zerlegen und das Fell nehmen. Mehr Fleisch, Häute und Felle von deiner Beute.", Icon = new string[2] { "DeerHide", "LeatherScraps" } }, new SkillDef { Id = SkillId.Seamanship, Key = "seamanship", NameEn = "Seamanship", NameDe = "Seemannschaft", DescEn = "Handling a ship at the helm. More speed under sail and oar, a quicker rudder, a hull that takes less damage.", DescDe = "Ein Schiff am Ruder führen. Mehr Fahrt unter Segel und Ruder, ein schnelleres Ruder, ein Rumpf, der weniger Schaden nimmt.", Icon = new string[2] { "Karve", "VikingShip" } }, new SkillDef { Id = SkillId.Navigation, Key = "navigation", NameEn = "Navigation", NameDe = "Navigation", DescEn = "Reading wind and sea. Sail closer to the wind, see further at sea, and feel the way home.", DescDe = "Wind und See lesen. Höher am Wind segeln, auf See weiter sehen und den Weg nach Hause spüren.", Icon = new string[2] { "Wishbone", "YagluthDrop" } }, new SkillDef { Id = SkillId.Cartography, Key = "cartography", NameEn = "Cartography", NameDe = "Kartografie", DescEn = "Mapping the land as you walk it. The map uncovers more around you.", DescDe = "Das Land kartieren, während du es durchwanderst. Die Karte deckt mehr um dich herum auf.", Icon = new string[1] { "piece_cartographytable" } }, new SkillDef { Id = SkillId.WeatherLore, Key = "weatherlore", NameEn = "Weather Lore", NameDe = "Wetterkunde", DescEn = "Reading the sky. You sense what weather comes next, earlier and more surely.", DescDe = "Den Himmel lesen. Du ahnst, welches Wetter kommt, früher und sicherer.", Icon = new string[2] { "Feathers", "FeatherCape" } }, new SkillDef { Id = SkillId.Trading, Key = "trading", NameEn = "Trading", NameDe = "Handel", DescEn = "Bargaining with traders. Lower prices when you buy, more coins when you sell.", DescDe = "Mit Händlern feilschen. Niedrigere Preise beim Kaufen, mehr Münzen beim Verkaufen.", Icon = new string[1] { "Coins" } }, new SkillDef { Id = SkillId.RuneLore, Key = "runelore", NameEn = "Rune Lore", NameDe = "Runenkunde", DescEn = "Reading runestones, ravens and dreams. Whoever knows the old lore learns everything a little faster.", DescDe = "Runensteine, Raben und Träume lesen. Wer die alte Kunde kennt, lernt alles etwas schneller.", Icon = new string[3] { "Vegvisir", "TrophyDraugr", "BoneFragments" } }, new SkillDef { Id = SkillId.CampLife, Key = "camplife", NameEn = "Camp Life", NameDe = "Lagerleben", DescEn = "Resting by the fire and sleeping well. Longer rested, fires that burn longer on your wood.", DescDe = "Am Feuer rasten und gut schlafen. Länger ausgeruht, Feuer brennen mit deinem Holz länger.", Icon = new string[2] { "fire_pit", "piece_campfire" } }, new SkillDef { Id = SkillId.Drinking, Key = "drinking", NameEn = "Hard Drinking", NameDe = "Trinkfestigkeit", DescEn = "Drinking mead. Lasting meads work longer, healing draughts come back sooner.", DescDe = "Met trinken. Anhaltende Mete wirken länger, heilende Tränke sind früher wieder bereit.", Icon = new string[2] { "MeadTasty", "MeadHealthMinor" } }, new SkillDef { Id = SkillId.MeatLover, Key = "meatlover", NameEn = "Meat Gourmet", NameDe = "Fleischgourmet", DescEn = "Eating meat dishes. They keep you going longer and give a little more.", DescDe = "Fleischgerichte essen. Sie halten länger vor und geben etwas mehr.", Icon = new string[1] { "CookedMeat" } }, new SkillDef { Id = SkillId.FishLover, Key = "fishlover", NameEn = "Fish Lover", NameDe = "Fischliebhaber", DescEn = "Eating fish and seafood. They keep you going longer and give a little more.", DescDe = "Fisch und Meeresfrüchte essen. Sie halten länger vor und geben etwas mehr.", Icon = new string[1] { "FishCooked" } }, new SkillDef { Id = SkillId.GreensLover, Key = "greenslover", NameEn = "Fruit & Greens Lover", NameDe = "Früchte- & Kräuterfreund", DescEn = "Eating berries, mushrooms, roots and salads. They keep you going longer and give a little more.", DescDe = "Beeren, Pilze, Wurzeln und Salate essen. Sie halten länger vor und geben etwas mehr.", Icon = new string[2] { "Raspberry", "Blueberries" } }, new SkillDef { Id = SkillId.BreadLover, Key = "breadlover", NameEn = "Bread & Pastry Lover", NameDe = "Brot- & Backwarenliebhaber", DescEn = "Eating bread, flatbread, pies and cakes. They keep you going longer and give a little more.", DescDe = "Brot, Fladenbrot, Pasteten und Kuchen essen. Sie halten länger vor und geben etwas mehr.", Icon = new string[1] { "Bread" } }, new SkillDef { Id = SkillId.StewLover, Key = "stewlover", NameEn = "Soup & Stew Lover", NameDe = "Suppen- & Eintopfliebhaber", DescEn = "Eating soups, stews and porridges. They keep you going longer and give a little more.", DescDe = "Suppen, Eintöpfe und Breie essen. Sie halten länger vor und geben etwas mehr.", Icon = new string[2] { "TurnipStew", "CarrotSoup" } } }; public static SkillDef Get(SkillId id) { return All[(int)id]; } } internal static class Stations { [HarmonyPatch(typeof(Fermenter), "RPC_AddItem")] private static class BrewFill { private static void Prefix(Fermenter __instance, out bool __state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 __state = (int)__instance.GetStatus() == 0; } private static void Postfix(Fermenter __instance, long sender, bool __state) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (__state && __instance.m_nview.IsOwner() && (int)__instance.GetStatus() != 0) { Player p = Shared.PlayerOf(sender); SetStationSkill(__instance.m_nview, Shared.Factor(p, SkillId.Brewing)); } } } [HarmonyPatch(typeof(Fermenter), "GetFermentationTime")] private static class BrewFaster { private static void Postfix(Fermenter __instance, ref double __result) { if (!(__result <= 0.0) && Cfg.Enabled(SkillId.Brewing)) { float num = StationSkill(__instance.m_nview); if (num > 0f) { __result /= Tuning.Shorter(1f, 0.3f, num); } } } } [HarmonyPatch(typeof(Fermenter), "RPC_Tap")] private static class BrewTap { private static void Prefix(Fermenter __instance, out bool __state) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 __state = __instance.m_nview.IsOwner() && (int)__instance.GetStatus() == 3; } private static void Postfix(Fermenter __instance, long sender, bool __state) { if (__state) { Player p = Shared.PlayerOf(sender); float f = Shared.Factor(p, SkillId.Brewing); s_extraBottles[__instance] = ((Random.value < Tuning.Chance(0.5f, f)) ? 1 : 0); ExtraPlanned += s_extraBottles[__instance]; SetStationSkill(__instance.m_nview, 0f); Shared.Raise(p, SkillId.Brewing, 7f); } } } [HarmonyPatch(typeof(Fermenter), "DelayedTap")] private static class BrewExtraBottle { private static void Postfix(Fermenter __instance) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!s_extraBottles.TryGetValue(__instance, out var value)) { return; } s_extraBottles.Remove(__instance); ItemConversion itemConversion = __instance.GetItemConversion(__instance.m_delayedTapItem); if (itemConversion != null && !((Object)(object)itemConversion.m_to == (Object)null)) { for (int i = 0; i < value; i++) { ItemDrop.OnCreateNew(Object.Instantiate<ItemDrop>(itemConversion.m_to, __instance.m_outputPoint.position + Vector3.up * 0.5f, Quaternion.identity), false); ExtraSpawned++; } } } } [HarmonyPatch(typeof(Smelter), "RPC_AddOre")] private static class SmeltAddOre { private static void Prefix(Smelter __instance, out int __state) { __state = (__instance.m_nview.IsOwner() ? __instance.GetQueueSize() : (-1)); } private static void Postfix(Smelter __instance, long sender, int __state) { if (__state >= 0 && __instance.GetQueueSize() > __state) { SkillId? skillId = SkillOf(__instance); if (skillId.HasValue) { Player p = Shared.PlayerOf(sender); SetStationSkill(__instance.m_nview, Shared.Factor(p, skillId.Value)); SetFiller(__instance.m_nview, p); } } } } [HarmonyPatch(typeof(Smelter), "RPC_AddFuel")] private static class SmeltAddFuel { private static void Prefix(Smelter __instance, out float __state) { __state = (__instance.m_nview.IsOwner() ? __instance.GetFuel() : float.MaxValue); } private static void Postfix(Smelter __instance, long sender, float __state) { if (!(__instance.GetFuel() <= __state) && SkillOf(__instance) == SkillId.Smelting && __instance.m_maxOre <= 0) { Player p = Shared.PlayerOf(sender); SetStationSkill(__instance.m_nview, Shared.Factor(p, SkillId.Smelting)); SetFiller(__instance.m_nview, p); } } } [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] private static class SmeltFaster { private static void Prefix(Smelter __instance, out Vector3 __state) { //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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) __state = new Vector3(__instance.m_secPerProduct, 0f, 0f); if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid() || !__instance.m_nview.IsOwner()) { return; } SkillId? skillId = SkillOf(__instance); if (skillId.HasValue && Cfg.Enabled(skillId.Value)) { float num = StationSkill(__instance.m_nview); if (!(num <= 0f)) { __state = new Vector3(__state.x, __instance.GetFuel(), num); float cutAt = ((skillId == SkillId.Spinning) ? 0.3f : 0.3f); __instance.m_secPerProduct = Tuning.Shorter(__state.x, cutAt, num); } } } private static void Postfix(Smelter __instance, Vector3 __state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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) if (!(__state.z <= 0f) && __instance.m_maxFuel > 0) { float num = __state.y - __instance.GetFuel(); if (num > 0f) { __instance.SetFuel(__instance.GetFuel() + num * 0.25f * __state.z); } } } private static void Finalizer(Smelter __instance, Vector3 __state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) __instance.m_secPerProduct = __state.x; } } [HarmonyPatch(typeof(Smelter), "QueueProcessed")] private static class SmeltExtra { private static void Postfix(Smelter __instance, string ore) { if (s_inExtra) { return; } SkillId? skillId = SkillOf(__instance); if (!skillId.HasValue || !Cfg.Enabled(skillId.Value)) { return; } long num = __instance.m_nview.GetZDO().GetLong(KeyFiller, 0L); if (num != 0L) { Shared.Raise(Player.GetPlayer(num), skillId.Value, PointsPerProduct(__instance)); } float num2 = Tuning.Chance((skillId == SkillId.Spinning) ? 0.2f : 0.15f, StationSkill(__instance.m_nview)); if (Random.value >= num2) { return; } s_inExtra = true; try { __instance.QueueProcessed(ore); } finally { s_inExtra = false; } } } [HarmonyPatch(typeof(Beehive), "RPC_Extract")] private static class BeeHarvest { private static void Prefix(Beehive __instance, out int __state) { __state = ((__instance.m_nview.IsOwner() && IsHive(__instance)) ? __instance.GetHoneyLevel() : 0); } private static void Postfix(Beehive __instance, long caller, int __state) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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) if (__state <= 0) { return; } Player p = Shared.PlayerOf(caller); float f = Shared.Factor(p, SkillId.Beekeeping); SetStationSkill(__instance.m_nview, f); Shared.Raise(p, SkillId.Beekeeping, 2f * (float)__state); int num = 0; for (int i = 0; i < __state; i++) { if (Random.value < Tuning.Chance(0.4f, f)) { num++; } } for (int j = 0; j < num; j++) { Vector2 val = Random.insideUnitCircle * 0.5f; ItemDrop component = ((Component)Object.Instantiate<ItemDrop>(__instance.m_honeyItem, __instance.m_spawnPoint.position + new Vector3(val.x, 0.25f * (float)(__state + j), val.y), Quaternion.identity)).GetComponent<ItemDrop>(); if (component != null) { component.SetStack(Game.instance.ScaleDrops(__instance.m_honeyItem.m_itemData, 1)); } } } } [HarmonyPatch(typeof(Beehive), "UpdateBees")] private static class BeesFaster { private static void Prefix(Beehive __instance, out float __state) { __state = __instance.m_secPerUnit; if (Cfg.Enabled(SkillId.Beekeeping) && IsHive(__instance)) { float num = StationSkill(__instance.m_nview); if (num > 0f) { __instance.m_secPerUnit = Tuning.Shorter(__state, 0.3f, num); } } } private static void Finalizer(Beehive __instance, float __state) { __instance.m_secPerUnit = __state; } } [HarmonyPatch(typeof(Fireplace), "RPC_AddFuel")] private static class FireFuel { private static void Prefix(Fireplace __instance, out float __state) { __state = (__instance.m_nview.IsOwner() ? __instance.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f) : float.MaxValue); } private static void Postfix(Fireplace __instance, long sender, float __state) { ZDO zDO = __instance.m_nview.GetZDO(); if (zDO != null && !(zDO.GetFloat(ZDOVars.s_fuel, 0f) <= __state)) { Player p = Shared.PlayerOf(sender); Shared.Raise(p, SkillId.CampLife, 0.1f); float num = 0.5f * Shared.Factor(p, SkillId.CampLife); if (num > 0f) { zDO.Set(ZDOVars.s_fuel, Mathf.Min(zDO.GetFloat(ZDOVars.s_fuel, 0f) + num, __instance.m_maxFuel)); } } } } private static readonly int KeySkill = StringExtensionMethods.GetStableHashCode("afrek_station_skill"); private static readonly Dictionary<Fermenter, int> s_extraBottles = new Dictionary<Fermenter, int>(); internal static int ExtraPlanned; internal static int ExtraSpawned; private static readonly int KeyFiller = StringExtensionMethods.GetStableHashCode("afrek_station_filler"); private static bool s_inExtra; private static float StationSkill(ZNetView nview) { if (!((Object)(object)nview != (Object)null) || !nview.IsValid()) { return 0f; } return Mathf.Clamp01(nview.GetZDO().GetFloat(KeySkill, 0f)); } private static void SetStationSkill(ZNetView nview, float f) { if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner() && !Mathf.Approximately(nview.GetZDO().GetFloat(KeySkill, 0f), f)) { nview.GetZDO().Set(KeySkill, f); } } internal static SkillId? SkillOf(Smelter s) { switch (Utils.GetPrefabName(((Component)s).gameObject)) { case "piece_spinningwheel": return SkillId.Spinning; case "smelter": case "charcoal_kiln": case "blastfurnace": case "eitrrefinery": case "piece_FrostKiln": return SkillId.Smelting; default: return null; } } private static void SetFiller(ZNetView nview, Player p) { if ((Object)(object)p != (Object)null && (Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner()) { nview.GetZDO().Set(KeyFiller, p.GetPlayerID()); } } internal static float PointsPerProduct(Smelter s) { return Utils.GetPrefabName(((Component)s).gameObject) switch { "piece_spinningwheel" => 0.4f, "charcoal_kiln" => 0.3f, "piece_FrostKiln" => 0.5f, _ => 0.8f, }; } internal static bool IsHive(Beehive b) { return Utils.GetPrefabName(((Component)b).gameObject) != "piece_birdnest"; } } internal static class Trade { [HarmonyPatch(typeof(StoreGui), "FillList")] private static class PricesInList { private static void Prefix(StoreGui __instance) { Enter(__instance); } private static void Finalizer() { Exit(); } } [HarmonyPatch(typeof(StoreGui), "UpdateBuyButton")] private static class PricesForButton { private static void Prefix(StoreGui __instance) { Enter(__instance); } private static void Finalizer() { Exit(); } } [HarmonyPatch(typeof(StoreGui), "BuySelectedItem")] private static class Buy { private static void Prefix(StoreGui __instance, out int __state) { __state = __instance.GetPlayerCoins(); Enter(__instance); } private static void Finalizer() { Exit(); } private static void Postfix(StoreGui __instance, int __state) { int num = __state - __instance.GetPlayerCoins(); if (num > 0) { AfrekSkills.RaiseLocal(SkillId.Trading, (float)num * 0.1f); } } } [HarmonyPatch(typeof(StoreGui), "SellItem")] private static class Sell { private static void Prefix(StoreGui __instance, out int __state) { __state = __instance.GetPlayerCoins(); } private static void Postfix(StoreGui __instance, int __state) { Player localPlayer = Player.m_localPlayer; int num = __instance.GetPlayerCoins() - __state; if (!((Object)(object)localPlayer == (Object)null) && num > 0) { int num2 = Tuning.MoreAmount(num, 0.15f, AfrekSkills.LocalFactor(SkillId.Trading), Random.value) - num; if (num2 > 0 && (Object)(object)__instance.m_coinPrefab != (Object)null) { ((Humanoid)localPlayer).GetInventory().AddItem(((Component)__instance.m_coinPrefab).gameObject, num2); } AfrekSkills.RaiseLocal(SkillId.Trading, (float)(num + num2) * 0.1f); } } } private static int s_depth; private static readonly List<int> s_prices = new List<int>(); private static Trader s_trader; internal static int Discounted(int price, float f) { if (price > 1) { return Mathf.Max(1, Mathf.RoundToInt((float)price * (1f - 0.15f * Mathf.Clamp01(f)))); } return price; } private static void Enter(StoreGui gui) { if (s_depth++ > 0 || (Object)(object)gui == (Object)null || (Object)(object)gui.m_trader == (Object)null) { return; } float num = AfrekSkills.LocalFactor(SkillId.Trading); if (num <= 0f) { return; } s_trader = gui.m_trader; s_prices.Clear(); foreach (TradeItem item in s_trader.m_items) { s_prices.Add(item.m_price); item.m_price = Discounted(item.m_price, num); } } private static void Exit() { if (--s_depth <= 0 && !((Object)(object)s_trader == (Object)null)) { for (int i = 0; i < s_trader.m_items.Count && i < s_prices.Count; i++) { s_trader.m_items[i].m_price = s_prices[i]; } s_trader = null; s_prices.Clear(); } } } } namespace Afrek.Dev { public class SelfTest : MonoBehaviour { private string _out; private readonly List<string> _report = new List<string>(); private int _pass; private int _fail; private Vector3 _home; public static void TryStart(GameObject host) { string environmentVariable = Environment.GetEnvironmentVariable("AFREK_SELFTEST"); if (string.IsNullOrEmpty(environmentVariable)) { return; } Application.runInBackground = true; string[] commandLineArgs = Environment.GetCommandLineArgs(); bool flag = false; for (int i = 0; i < commandLineArgs.Length - 1; i++) { if (commandLineArgs[i] == "-savedir" && !string.IsNullOrEmpty(commandLineArgs[i + 1])) { Directory.CreateDirectory(commandLineArgs[i + 1]); Utils.SetSaveDataPath(commandLineArgs[i + 1]); flag = true; } } if (!flag) { AfrekPlugin.Log.LogError((object)"Self test needs -savedir <scratch folder>; not starting it."); } else { host.AddComponent<SelfTest>()._out = environmentVariable; } } private static bool Flag(string name) { return (Environment.GetEnvironmentVariable("AFREK_SELFTEST_" + name) ?? "") == "1"; } private static string Var(string name) { return Environment.GetEnvironmentVariable("AFREK_SELFTEST_" + name) ?? ""; } private void Start() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown Directory.CreateDirectory(_out); Application.logMessageReceived += new LogCallback(OnLog); ((MonoBehaviour)this).StartCoroutine(Run()); } private void OnLog(string condition, string stackTrace, LogType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) if ((int)type == 4 || (int)type == 0) { _report.Add($"[{type}] {condition}\n{stackTrace}"); } } private IEnumerator Run() { float timeout = Time.realtimeSinceStartup + 600f; while (((Object)(object)FejdStartup.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) && Time.realtimeSinceStartup < timeout) { yield return null; } yield return (object)new WaitForSecondsRealtime(4f); string text = Var("JOIN"); if (!string.IsNullOrEmpty(text)) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(EnterServer(text))); if ((Object)(object)Player.m_localPlayer != (Object)null) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(Multiplayer())); } } else if (Flag("WORLD")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(EnterWorld())); if ((Object)(object)Player.m_localPlayer != (Object)null) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(WorldTest())); } } _report.Add($"RESULT pass {_pass} fail {_fail}"); Flush(); Application.logMessageReceived -= new LogCallback(OnLog); yield return (object)new WaitForSecondsRealtime(0.5f); Application.Quit(); } private IEnumerator Safe(IEnumerator inner) { while (true) { object current; try { if (!inner.MoveNext()) { break; } current = inner.Current; } catch (Exception ex) { _report.Add("step failed: " + ex); _fail++; break; } yield return current; } } private void Flush() { Directory.CreateDirectory(_out); File.WriteAllLines(Path.Combine(_out, "report.txt"), _report); } private void Check(bool ok, string what) { if (ok) { _pass++; } else { _fail++; } _report.Add((ok ? "PASS " : "FAIL ") + what); } private IEnumerator EnterWorld() { FejdStartup instance = FejdStartup.instance; if ((Object)(object)instance == (Object)null) { _report.Add("world: no FejdStartup"); yield break; } PlayerProfile val = new PlayerProfile("afrektester", (FileSource)2); val.SetName("Afreker"); val.m_firstSpawn = false; val.Save(); Game.SetProfile("afrektester", (FileSource)2); World val2 = new World("AfrekTest", "HQ7GnTiegh") { m_fileSource = (FileSource)2 }; val2.SaveWorldFWLData(DateTime.Now); instance.m_world = val2; instance.m_startingWorld = true; ZNet.SetServer(true, false, false, val2.m_name, "", val2); ZNet.ResetServerHost(); instance.TransitionToMainScene(); _report.Add("world: loading " + val2.m_name + " seed " + val2.m_seedName); float timeout = Time.realtimeSinceStartup + 300f; while (((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting()) && Time.realtimeSinceStartup < timeout) { yield return null; } if ((Object)(object)Player.m_localPlayer == (Object)null) { _report.Add("world: player never spawned"); yield break; } yield return (object)new WaitForSecondsRealtime(6f); _report.Add("world: spawned at " + ((object)((Component)Player.m_localPlayer).transform.position/*cast due to .constrained prefix*/).ToString()); } private IEnumerator EnterServer(string address) { FejdStartup instance = FejdStartup.instance; if ((Object)(object)instance == (Object)null) { _report.Add("join: no FejdStartup"); yield break; } PlayerProfile val = new PlayerProfile("afrekmp", (FileSource)2); val.SetName("AfrekerMP"); val.m_firstSpawn = false; val.Save(); Game.SetProfile("afrekmp", (FileSource)2); instance.SetServerToJoin(new ServerJoinData(new ServerJoinDataDedicated(address))); instance.JoinServer(); _report.Add("join: connecting to " + address); float timeout = Time.realtimeSinceStartup + 240f; while (((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting()) && Time.realtimeSinceStartup < timeout) { yield return null; } if ((Object)(object)Player.m_localPlayer == (Object)null) { _report.Add("join: player never spawned"); yield break; } yield return (object)new WaitForSecondsRealtime(8f); _report.Add($"join: spawned at {((Component)Player.m_localPlayer).transform.position}, server {ZNet.instance.IsServer()}, peers {ZNet.instance.GetPeers().Count}"); } private IEnumerator Multiplayer() { yield return ((MonoBehaviour)this).StartCoroutine(Safe(MpScenes())); } private IEnumerator WorldTest() { if (Flag("RESEARCH")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(Research())); } else { yield return ((MonoBehaviour)this).StartCoroutine(Safe(Scenes())); } } private static void Stand(Player p, Vector3 at) { //IL_0007: 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_002a: 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) at.y = ZoneSystem.instance.GetGroundHeight(at) + 0.1f; ((Component)p).transform.position = at; ((Character)p).m_body.position = at; ((Character)p).m_body.linearVelocity = Vector3.zero; } private IEnumerator Travel(Player p, Vector3 at) { //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) ((Character)p).TeleportTo(at + Vector3.up * 2f, ((Component)p).transform.rotation, true); float limit = Time.realtimeSinceStartup + 90f; while ((((Character)p).IsTeleporting() || !ZoneSystem.instance.IsZoneLoaded(at)) && Time.realtimeSinceStartup < limit) { yield return null; } yield return (object)new WaitForSecondsRealtime(3f); Stand(p, at); yield return (object)new WaitForSecondsRealtime(1f); } private void ClearArea(Vector3 c, float r) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) int num = 0; ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0); foreach (ZNetView val in array) { if (!((Object)(object)val == (Object)null) && val.IsValid() && !((Object)(object)((Component)val).GetComponent<Player>() != (Object)null) && !(Utils.DistanceXZ(((Component)val).transform.position, c) > r) && (Object.op_Implicit((Object)(object)((Component)val).GetComponent<TreeBase>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<TreeLog>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<Destructible>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<MineRock>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<MineRock5>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<Pickable>()) || (Object.op_Implicit((Object)(object)((Component)val).GetComponent<Character>()) && !((Component)val).GetComponent<Character>().IsTamed()))) { val.Destroy(); num++; } } _report.Add("scene: cleared " + num + " objects"); } private static Pose Look(Vector3 target, float bearing, float dist, float height) { //IL_0000: 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) //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_0021: 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_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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target + Quaternion.Euler(0f, bearing, 0f) * Vector3.forward * dist + Vector3.up * height; return new Pose(val, Quaternion.LookRotation(target - val)); } private IEnumerator MainShot(string name, Pose pose) { //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) Camera main = Utils.GetMainCamera(); GameCamera gc = GameCamera.instance; if ((Object)(object)main == (Object)null) { _report.Add("mainshot: no camera"); yield break; } if ((Object)(object)gc != (Object)null) { ((Behaviour)gc).enabled = false; } if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.m_userHidden = true; } ((Component)main).transform.SetPositionAndRotation(pose.position, pose.rotation); float fov = main.fieldOfView; main.fieldOfView = 50f; yield return null; yield return null; yield return (object)new WaitForEndOfFrame(); Directory.CreateDirectory(_out); ScreenCapture.CaptureScreenshot(Path.Combine(_out, name + ".png")); yield return null; yield return null; main.fieldOfView = fov; if ((Object)(object)gc != (Object)null) { ((Behaviour)gc).enabled = true; } if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.m_userHidden = false; } } private IEnumerator Shot(string name) { yield return (object)new WaitForEndOfFrame(); Directory.CreateDirectory(_out); ScreenCapture.CaptureScreenshot(Path.Combine(_out, name + ".png")); yield return null; yield return null; } private static string Flat(string s) { if (s != null) { return s.Replace('\n', '|'); } return "null"; } private static Bounds RendererBounds(GameObject go) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) Bounds result = default(Bounds); bool flag = false; Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if (!(val is ParticleSystemRenderer) && val.enabled) { if (!flag) { result = val.bounds; flag = true; } else { ((Bounds)(ref result)).Encapsulate(val.bounds); } } } return result; } private static Skill Data(Player p, SkillId id) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return ((Character)p).GetSkills().GetSkill(AfrekSkills.Type(id)); } private static void SetLevel(Player p, SkillId id, float level) { Skill obj = Data(p, id); obj.m_level = level; obj.m_accumulator = 0f; Shared.Publish(p, force: true); } private static void ResetAll(Player p) { SkillDef[] all = SkillTable.All; foreach (SkillDef skillDef in all) { SetLevel(p, skillDef.Id, 0f); } } private static float Points(Player p, SkillId id) { Skill val = Data(p, id); float num = 0f; for (int i = 0; i < (int)val.m_level; i++) { num += (float)(Math.Pow(i + 1, 1.5) * 0.5 + 0.5); } return num + val.m_accumulator; } private static GameObject SpawnAt(string prefab, Vector3 at, float yaw = 0f) { //IL_0018: 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) GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if ((Object)(object)prefab2 == (Object)null) { return null; } GameObject obj = Object.Instantiate<GameObject>(prefab2, at, Quaternion.Euler(0f, yaw, 0f)); long playerID = Game.instance.GetPlayerProfile().GetPlayerID(); ZNetView component = obj.GetComponent<ZNetView>(); if (component != null) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.Set(ZDOVars.s_creator, playerID); } } Piece component2 = obj.GetComponent<Piece>(); if ((Object)(object)component2 != (Object)null) { component2.m_creator = playerID; } return obj; } private static void Remove(Component c) { if (!((Object)(object)c == (Object)null)) { ZNetView component = c.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.Destroy(); } } } private static int CountDrops(string prefab, Vector3 at, float r) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) int num = 0; ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0); foreach (ItemDrop val in array) { if ((Object)(object)val != (Object)null && Utils.GetPrefabName(((Component)val).gameObject) == prefab && Vector3.Distance(((Component)val).transform.position, at) < r) { num += val.m_itemData.m_stack; } } return num; } private static void ClearDrops(Vector3 at, float r) { //IL_001e: 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) ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0); foreach (ItemDrop val in array) { if ((Object)(object)val != (Object)null && Vector3.Distance(((Component)val).transform.position, at) < r) { ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (component != null) { component.Destroy(); } } } } private static Vector3 FlatSpot(Vector3 c, float r) { //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_0120: 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_0028: 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_0056: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or