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 GaS QuestSpawner v1.0.7
plugins/GaS-QuestSpawner/GaS-QuestSpawner.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; 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 BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GaS; using GaSQuestSpawner.Core; using GearAndStorage; using GearAndStorage.Core; using HarmonyLib; using Newtonsoft.Json; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("GaS-QuestSpawner")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.7.0")] [assembly: AssemblyInformationalVersion("1.0.7")] [assembly: AssemblyProduct("GaS-QuestSpawner")] [assembly: AssemblyTitle("GaS-QuestSpawner")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.7.0")] [module: UnverifiableCode] namespace GaS { internal static class L { internal static Func<string> Language = () => "English"; internal static readonly Dictionary<string, string[]> Catalog = Load(); internal static string Code { get { switch (Language()?.ToLowerInvariant() ?? "") { default: return "en"; case "german": case "deutsch": case "de": return "de"; case "czech": case "čeština": case "cs": return "cs"; } } } private static Dictionary<string, string[]> Load() { Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>(StringComparer.Ordinal); using StreamReader streamReader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("GaS.Translations.tsv")); string text; while ((text = streamReader.ReadLine()) != null) { if (text.Length != 0 && !text.StartsWith("#")) { string[] array = text.Split('\t'); if (array.Length != 4) { throw new InvalidDataException("Invalid localization row: " + array[0]); } dictionary.Add(array[0], new string[3] { array[1], array[2], array[3] }); } } return dictionary; } internal static string T(string source) { if (source == null) { return ""; } if (!Catalog.TryGetValue(source, out var value)) { return source; } return value[(Code == "cs") ? 1 : ((Code == "de") ? 2 : 0)]; } internal static string F(string source, params object[] args) { return string.Format(CultureInfo.CurrentCulture, T(source), args); } internal static string Notice(string text) { if (string.IsNullOrEmpty(text)) { return text; } foreach (KeyValuePair<string, string[]> item in Catalog) { string[] value = item.Value; foreach (string text2 in value) { if (text == text2) { return T(item.Key); } if (item.Key.EndsWith(": ", StringComparison.Ordinal) && text.StartsWith(text2, StringComparison.Ordinal)) { return T(item.Key) + text.Substring(text2.Length); } } } return text; } } internal static class LanguageRuntime { private sealed class ConfigurationManagerAttributes { public string DispName; public string Category; public string Description; public Action<ConfigEntryBase> CustomDrawer; private bool expanded; public ConfigurationManagerAttributes(ConfigEntryBase entry) { DispName = Label(entry.Definition.Key); Category = Label(entry.Definition.Section); Description = Describe(entry.Description.Description); if (entry.SettingType.IsEnum && entry.Definition.Key == "Difficulty") { CustomDrawer = DrawDifficulty; } } private void DrawDifficulty(ConfigEntryBase entry) { GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(L.T(entry.BoxedValue.ToString()) + " ▾", Array.Empty<GUILayoutOption>())) { expanded = !expanded; } if (expanded) { foreach (object value in Enum.GetValues(entry.SettingType)) { if (GUILayout.Button(L.T(value.ToString()), Array.Empty<GUILayoutOption>())) { entry.BoxedValue = value; expanded = false; } } } GUILayout.EndVertical(); } } private static string language; private static readonly List<ConfigFile> files = new List<ConfigFile>(); internal static void Register(ConfigFile file) { if (!files.Contains(file)) { files.Add(file); } } internal static void Tick() { L.Language = () => (Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English"; if (language == L.Code) { return; } language = L.Code; foreach (ConfigFile file in files) { foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in file) { Attach(item.Value); } } foreach (PluginInfo value in Chainloader.PluginInfos.Values) { BaseUnityPlugin instance = value.Instance; if (!((Object)(object)instance == (Object)null) && !(((object)instance).GetType().FullName != "ConfigurationManager.ConfigurationManager")) { ((object)instance).GetType().GetMethod("BuildSettingList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(instance, null); } } } private static void Attach(ConfigEntryBase entry) { object[] tags = entry.Description.Tags; tags = tags.Where((object t) => !(t is ConfigurationManagerAttributes)).ToArray(); typeof(ConfigDescription).GetField("<Tags>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(entry.Description, tags.Concat(new object[1] { new ConfigurationManagerAttributes(entry) }).ToArray()); } internal static string Label(string key) { if (key.StartsWith("Storage.")) { return L.T("Storage") + ": " + L.T(key.Substring(8)); } if (key.StartsWith("Allow") && key.Length > 5) { return L.T("Allow") + ": " + L.T(key.Substring(5)); } if (key.StartsWith("Hotkey")) { return L.T("Hotkey") + " " + key.Substring(6); } return L.T(key); } internal static string Describe(string source) { if (source.StartsWith("Additionally allow restricted items of ") && source.EndsWith(" even before the trophy unlock. False does not revoke an altar unlock.")) { return L.F("portal.allow.description", L.T(source.Substring("Additionally allow restricted items of ".Length, source.Length - "Additionally allow restricted items of ".Length - " even before the trophy unlock. False does not revoke an altar unlock.".Length))); } return L.T(source); } internal static string Creature(string prefab) { ZNetScene instance = ZNetScene.instance; object obj; if (instance == null) { obj = null; } else { GameObject prefab2 = instance.GetPrefab(prefab); obj = ((prefab2 == null) ? null : prefab2.GetComponent<Character>()?.m_name); } if (obj == null) { obj = prefab; } string text = (string)obj; if (Localization.instance != null) { return Localization.instance.Localize(text); } return text; } } } namespace GaSQuestSpawner { internal static class Network { [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class Connection { private static void Prefix(ZNetPeer peer) { peer.m_rpc.Register<string>("GaSQuestSpawner.PolicyRequest", (Action<ZRpc, string>)delegate(ZRpc rpc, string version) { if (ZNet.instance.IsServer() && version == "1.0.7") { rpc.Invoke("GaSQuestSpawner.Policy", new object[1] { JsonConvert.SerializeObject((object)Settings.Local()) }); } }); peer.m_rpc.Register<string>("GaSQuestSpawner.Policy", (Action<ZRpc, string>)delegate(ZRpc rpc, string json) { if (ZNet.instance.IsServer() || rpc != ZNet.instance.GetServerRPC()) { return; } try { if (json.Length <= 100000) { Settings settings = JsonConvert.DeserializeObject<Settings>(json); if (settings != null && settings.Valid()) { settings.Families = new Dictionary<string, Family>(settings.Families, StringComparer.OrdinalIgnoreCase); settings.BiomeOverrides = new Dictionary<string, string>(settings.BiomeOverrides, StringComparer.OrdinalIgnoreCase); settings.LargeCreatures = new HashSet<string>(settings.LargeCreatures, StringComparer.OrdinalIgnoreCase); settings.AquaticCreatures = new HashSet<string>(settings.AquaticCreatures, StringComparer.OrdinalIgnoreCase); Remote = settings; Settings.ApplyServerView(settings); Plugin.Log.LogInfo((object)$"Quest zone server policy received: difficulty={settings.Difficulty}, radius={settings.Radius}, distance={settings.MinDistance}-{settings.MaxDistance}."); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Zone policy rejected: " + ex.Message)); } }); } } private const string Request = "GaSQuestSpawner.PolicyRequest"; private const string Response = "GaSQuestSpawner.Policy"; internal static Settings Remote; private static ZRpc server; private static float nextRequest; private static string lastPolicyLog; internal static Settings Current { get { if ((Object)(object)ZNet.instance == (Object)null) { return null; } if (ZNet.instance.IsServer()) { return Settings.Local(); } ZRpc serverRPC = ZNet.instance.GetServerRPC(); if (serverRPC != server) { Remote = null; server = serverRPC; nextRequest = 0f; } if (serverRPC != null && Time.realtimeSinceStartup >= nextRequest) { nextRequest = Time.realtimeSinceStartup + 5f; serverRPC.Invoke("GaSQuestSpawner.PolicyRequest", new object[1] { "1.0.7" }); } if (Remote == null) { return null; } Settings.ApplyServerView(Remote); string text = $"server-authoritative difficulty={Remote.Difficulty}, radius={Remote.Radius}, distance={Remote.MinDistance}-{Remote.MaxDistance}"; if (text != lastPolicyLog) { lastPolicyLog = text; Plugin.Log.LogInfo((object)("Quest zone policy: " + text + ".")); } return new Settings { Enabled = Remote.Enabled, Difficulty = Rules.EffectiveDifficulty(Remote.Difficulty, Settings.DifficultyEntry.Value), Radius = Remote.Radius, MinDistance = Remote.MinDistance, MaxDistance = Remote.MaxDistance, Families = Remote.Families, BiomeOverrides = Remote.BiomeOverrides, LargeCreatures = Remote.LargeCreatures, AquaticCreatures = Remote.AquaticCreatures }; } } } [BepInPlugin("mkova.GaSQuestSpawner", "GaS-QuestSpawner", "1.0.7")] [BepInDependency("mkova.GearAndStorage", "0.5.17")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "Save")] private static class Persist { private static void Prefix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { Save(); } } } public const string Id = "mkova.GaSQuestSpawner"; public const string Version = "1.0.7"; private const string SaveKey = "GaSQuestSpawner.state.v1"; internal static ManualLogSource Log; internal static HuntState State; internal static Plugin Instance; private Harmony harmony; private Player loaded; private long world; private IEnumerator search; private float nextTick; private float nextSave; private string policyNotice; private void Awake() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Settings.Bind(((BaseUnityPlugin)this).Config); LanguageRuntime.Register(((BaseUnityPlugin)this).Config); LanguageRuntime.Tick(); harmony = new Harmony("mkova.GaSQuestSpawner"); harmony.PatchAll(); QuestIntegration.ResolveKill += TaggedCreature.ResolveKill; ((BaseUnityPlugin)this).Logger.LogInfo((object)"GaS-QuestSpawner 1.0.7 loaded."); } private void Update() { LanguageRuntime.Tick(); if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || WorldGenerator.instance == null) { loaded = null; State = null; search = null; ZoneMap.Clear(); return; } try { Player localPlayer = Player.m_localPlayer; if (localPlayer.m_isLoading || !QuestIntegration.IsLoaded) { return; } if ((Object)(object)loaded != (Object)(object)localPlayer || world != ZNet.World.m_uid) { loaded = localPlayer; world = ZNet.World.m_uid; State = null; search = null; ZoneMap.Clear(); if (localPlayer.m_customData.TryGetValue("GaSQuestSpawner.state.v1", out var value)) { try { HuntState huntState = JsonConvert.DeserializeObject<HuntState>(value); if (huntState?.World == world && huntState.Owner == localPlayer.GetPlayerID() && huntState.Zones != null) { State = huntState; } } catch (Exception ex) { Log.LogWarning((object)("Cannot restore hunt zones: " + ex.Message)); } } } if (search != null && !search.MoveNext()) { search = null; } if (!(Time.realtimeSinceStartup < nextTick)) { nextTick = Time.realtimeSinceStartup + 1f; Tick(localPlayer); } } catch (Exception ex2) { search = null; nextTick = Time.realtimeSinceStartup + 5f; Log.LogError((object)("Hunt zone update: " + ex2)); } } private void Tick(Player player) { //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Invalid comparison between I4 and Unknown //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Expected I4, but got Unknown QuestDefinition active = QuestIntegration.Active; Settings current = Network.Current; if (active == null) { ClearState(); return; } if (State != null && (State.Quest != active.ID || State.Attempt != QuestIntegration.AttemptID)) { ClearState(); } if (current == null) { if (policyNotice != active.ID) { Notice(L.F("zone.wait", "1.0.7")); policyNotice = active.ID; } ZoneMap.Clear(); return; } if (!current.Enabled || ((Character)player).IsDead()) { search = null; ZoneMap.Clear(); ZNetView nview = ((Character)player).m_nview; if (nview != null) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("gqs.activeUntil", 0L); } } return; } if (active.KillReqs.Count == 0 || active.KillReqs.Any((QuestObjective o) => IsBoss(o.Prefab))) { ClearState(); return; } if (State == null) { State = new HuntState { World = world, Owner = player.GetPlayerID(), Quest = active.ID, Attempt = QuestIntegration.AttemptID, OriginX = ((Component)player).transform.position.x, OriginZ = ((Component)player).transform.position.z }; Save(); } HuntZone[] array = State.Zones.ToArray(); foreach (HuntZone zone in array) { QuestObjective val = ((IEnumerable<QuestObjective>)active.KillReqs).FirstOrDefault((Func<QuestObjective, bool>)((QuestObjective o) => o.Prefab == zone.Target)); if (val == null || QuestIntegration.Count(val) >= val.Amount) { State.Zones.Remove(zone); Save(); continue; } List<SpawnData> rules = SpawnRules(zone.Target); Biome val2 = AllowedBiomes(zone.Target, current, rules); Biome biome = WorldGenerator.instance.GetBiome(zone.Center); if ((int)val2 == 0 || (val2 & biome) == 0) { State.Zones.Remove(zone); State.RetryAt.Remove(zone.Target); Save(); Notice(L.F("zone.relocated", LanguageRuntime.Creature(zone.Target))); } else if (zone.Biomes != (int)val2) { zone.Biomes = (int)val2; Save(); } } if (search == null) { float value; QuestObjective val3 = ((IEnumerable<QuestObjective>)active.KillReqs).FirstOrDefault((Func<QuestObjective, bool>)((QuestObjective o) => QuestIntegration.Count(o) < o.Amount && !State.Zones.Any((HuntZone z) => z.Target == o.Prefab) && (!State.RetryAt.TryGetValue(o.Prefab, out value) || Time.realtimeSinceStartup >= value))); if (val3 != null) { search = FindZone(State, val3.Prefab, current, current.Radius, current.MinDistance, current.MaxDistance); } } ((Character)player).m_nview.GetZDO().Set("gqs.activeZones", string.Join("|", State.Zones.Select((HuntZone z) => z.ID))); ((Character)player).m_nview.GetZDO().Set("gqs.activeUntil", 0L); foreach (HuntZone zone2 in State.Zones) { SpawnController.Tick(player, zone2, current); } ZoneMap.Update(State.Zones, (active.ID == "gearandstorage_first_supplies" && active.Title == "První zásoby") ? L.T(active.Title) : active.Title); if (Time.realtimeSinceStartup >= nextSave) { nextSave = Time.realtimeSinceStartup + 5f; Save(); } } internal static bool IsBoss(string prefab) { GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if (prefab2 == null) { return false; } return prefab2.GetComponent<Character>()?.m_boss == true; } internal static List<SpawnData> SpawnRules(string prefab) { return (from s in (from s in SpawnSystem.m_instances.SelectMany((SpawnSystem s) => s.m_spawnLists) where (Object)(object)s != (Object)null select s).SelectMany((SpawnSystemList s) => s.m_spawners) where s.m_enabled && !s.m_devDisabled && (Object)(object)s.m_prefab != (Object)null && ((Object)s.m_prefab).name == prefab select s).ToList(); } internal static Biome AllowedBiomes(string prefab, Settings policy, List<SpawnData> rules) { //IL_0018: 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_002a: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (policy.BiomeOverrides.TryGetValue(prefab, out var value)) { return Settings.ParseBiomes(value); } Biome val = (Biome)0; foreach (SpawnData rule in rules) { val |= rule.m_biome; } return val; } private IEnumerator FindZone(HuntState state, string target, Settings policy, float radius, float minDistance, float maxDistance) { List<SpawnData> rules = SpawnRules(target); if (rules.Count == 0) { state.RetryAt[target] = Time.realtimeSinceStartup + 60f; Notice(L.F("zone.rules", LanguageRuntime.Creature(target))); yield break; } Biome allowedBiomes = AllowedBiomes(target, policy, rules); if ((int)allowedBiomes == 0) { state.RetryAt[target] = Time.realtimeSinceStartup + 60f; Notice(L.F("zone.rules", LanguageRuntime.Creature(target))); yield break; } bool aquatic = policy.AquaticCreatures.Contains(target) || rules.Any(IsWaterRule); Log.LogInfo((object)$"Quest zone search: target={target}, distance={minDistance:0.#}-{maxDistance:0.#}m, biomes={allowedBiomes}, aquatic={aquatic}."); int budget = 0; double phase = (double)(uint)StringExtensionMethods.GetStableHashCode(target) / 4294967295.0 * Math.PI * 2.0; Vector3 val = default(Vector3); foreach (var item in Rules.Candidates(minDistance, maxDistance, phase)) { if (state != State || QuestIntegration.AttemptID != state.Attempt) { yield break; } ((Vector3)(ref val))..ctor(state.OriginX + item.x, 0f, state.OriginZ + item.z); if (SuitableSeed(val, rules, allowedBiomes, aquatic)) { val.y = WorldGenerator.instance.GetHeight(val); int num = 0; for (int i = 0; i < 8; i++) { float num2 = (float)i * (float)Math.PI / 4f; if (SuitableSeed(val + new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * radius * 0.6f, rules, allowedBiomes, aquatic)) { num++; } } if (num >= (aquatic ? 2 : 5)) { state.Zones.Add(new HuntZone { ID = Guid.NewGuid().ToString("N"), Target = target, X = val.x, Y = val.y, Z = val.z, Radius = radius, Biomes = (int)allowedBiomes }); Save(); Notice(L.F("zone.found", LanguageRuntime.Creature(target))); yield break; } } int num3 = budget + 1; budget = num3; if (num3 >= 48) { budget = 0; yield return null; } } state.RetryAt[target] = Time.realtimeSinceStartup + 60f; Notice(L.F("zone.missing", LanguageRuntime.Creature(target), Mathf.RoundToInt(minDistance), Mathf.RoundToInt(maxDistance))); } internal static bool IsWaterRule(SpawnData rule) { if (rule != null && Math.Abs(rule.m_minOceanDepth - rule.m_maxOceanDepth) > 0.001f) { return rule.m_maxOceanDepth > 0f; } return false; } private static bool SuitableSeed(Vector3 pos, List<SpawnData> rules, Biome allowedBiomes, bool aquatic) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) WorldGenerator instance = WorldGenerator.instance; Biome biome = instance.GetBiome(pos); float height = instance.GetHeight(pos); float altitude = height - ZoneSystem.instance.m_waterLevel; float waterDepth = Mathf.Max(0f, ZoneSystem.instance.m_waterLevel - height); Vector2 val = new Vector2(pos.x, pos.z); float distance = ((Vector2)(ref val)).magnitude; bool forest = WorldGenerator.InForest(pos); BiomeArea area = instance.GetBiomeArea(pos); if ((allowedBiomes & biome) == 0 || !rules.Any(delegate(SpawnData r) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if ((r.m_biome & biome) != 0 && (r.m_biomeArea & area) != 0 && altitude >= r.m_minAltitude && altitude <= r.m_maxAltitude && (forest ? r.m_inForest : r.m_outsideForest) && (r.m_minDistanceFromCenter <= 0f || distance >= r.m_minDistanceFromCenter) && (r.m_maxDistanceFromCenter <= 0f || distance <= r.m_maxDistanceFromCenter)) { if (!aquatic) { return altitude >= 0.5f; } if (altitude < 0.5f) { if (IsWaterRule(r)) { if (waterDepth >= r.m_minOceanDepth) { return waterDepth <= r.m_maxOceanDepth; } return false; } return true; } return false; } return false; })) { return false; } if ((Object)(object)EffectArea.IsPointInsideArea(new Vector3(pos.x, height, pos.z), (Type)4, 30f) != (Object)null) { return false; } if (Mathf.Abs(instance.GetHeight(pos + Vector3.right * 8f) - height) < 7f) { return Mathf.Abs(instance.GetHeight(pos + Vector3.forward * 8f) - height) < 7f; } return false; } internal static void Notice(string text) { Log.LogInfo((object)text); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } internal static void Save() { if ((Object)(object)Instance?.loaded != (Object)null && State != null) { Instance.loaded.m_customData["GaSQuestSpawner.state.v1"] = JsonConvert.SerializeObject((object)State); } } private void ClearState() { search = null; State = null; loaded?.m_customData.Remove("GaSQuestSpawner.state.v1"); Player obj = loaded; if (obj != null) { ZNetView nview = ((Character)obj).m_nview; if (nview != null) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("gqs.activeUntil", 0L); } } } ZoneMap.Clear(); } private void OnDestroy() { QuestIntegration.ResolveKill -= TaggedCreature.ResolveKill; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ZoneMap.Clear(); Instance = null; } } internal sealed class HuntState { public long World; public long Owner; public string Quest; public string Attempt; public float OriginX; public float OriginZ; public List<HuntZone> Zones = new List<HuntZone>(); [JsonIgnore] public Dictionary<string, float> RetryAt = new Dictionary<string, float>(); } internal sealed class HuntZone { public string ID; public string Target; public float X; public float Y; public float Z; public float Radius; public int Biomes; public bool BossSpawned; public List<SpawnRecord> Creatures = new List<SpawnRecord>(); [JsonIgnore] public float NextSpawn; [JsonIgnore] public float EnteredAt; [JsonIgnore] public float LastBlockedNotice; [JsonIgnore] public bool Inside; [JsonIgnore] public Vector3 Center => new Vector3(X, Y, Z); internal bool Contains(Vector3 p) { //IL_0000: 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) return Rules.Inside(p.x, p.z, X, Z, Radius); } } internal sealed class SpawnRecord { public string Token; public long Expires; public bool Boss; public bool Large; } internal sealed class Settings { private static bool applyingServerView; public bool Enabled = true; public Difficulty Difficulty = Difficulty.Normal; public float Radius = 70f; public float MinDistance = 500f; public float MaxDistance = 1000f; public Dictionary<string, Family> Families = new Dictionary<string, Family>(StringComparer.OrdinalIgnoreCase); public Dictionary<string, string> BiomeOverrides = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); public HashSet<string> LargeCreatures = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public HashSet<string> AquaticCreatures = new HashSet<string>(StringComparer.OrdinalIgnoreCase); internal static ConfigEntry<bool> EnabledEntry; internal static ConfigEntry<Difficulty> DifficultyEntry; internal static ConfigEntry<float> RadiusEntry; internal static ConfigEntry<float> MinDistanceEntry; internal static ConfigEntry<float> MaxDistanceEntry; internal static ConfigEntry<string> FamiliesEntry; internal static ConfigEntry<string> BiomeOverridesEntry; internal static ConfigEntry<string> LargeCreaturesEntry; internal static ConfigEntry<string> AquaticCreaturesEntry; internal static void Bind(ConfigFile file) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown EnabledEntry = file.Bind<bool>("General", "Enabled", true, "Enable personal quest hunting zones. Server controls this setting in multiplayer."); DifficultyEntry = file.Bind<Difficulty>("General", "Difficulty", Difficulty.Normal, "Easy: basic mobs with 0 stars. Normal: 0-1 stars. Hard: 1-2 stars. VeryHard: 2-4 stars, mostly elites and one miniboss per zone. In multiplayer every gameplay setting is controlled by the server. Quest rewards never change."); RadiusEntry = file.Bind<float>("General", "ZoneRadius", 70f, new ConfigDescription("Hunting circle radius in metres. New zones only. Configure the search distance separately.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(40f, 100f), Array.Empty<object>())); MinDistanceEntry = file.Bind<float>("General", "SpawnDistanceMin", 500f, new ConfigDescription("Minimum distance in metres from quest acceptance to a newly selected hunting zone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 5000f), Array.Empty<object>())); MaxDistanceEntry = file.Bind<float>("General", "SpawnDistanceMax", 1000f, new ConfigDescription("Maximum distance in metres from quest acceptance to a newly selected hunting zone. Must be at least SpawnDistanceMin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 10000f), Array.Empty<object>())); Dictionary<string, Family> dictionary = new Dictionary<string, Family> { ["Greyling"] = new Family("Greydwarf_Shaman", "Greydwarf_Elite", "Greydwarf_Elite"), ["Greydwarf"] = new Family("Greydwarf_Shaman", "Greydwarf_Elite", "Greydwarf_Elite"), ["Greydwarf_Shaman"] = new Family("Greydwarf_Elite", "Troll", "Greydwarf_Elite"), ["Greydwarf_Elite"] = new Family("Greydwarf_Shaman", "Troll", "Greydwarf_Elite"), ["Skeleton"] = new Family("Skeleton_Poison", "Skeleton_Poison", "Skeleton_Poison"), ["Draugr"] = new Family("Draugr_Ranged", "Draugr_Elite", "Draugr_Elite"), ["Goblin"] = new Family("GoblinShaman", "GoblinBrute", "GoblinBrute"), ["Wolf"] = new Family("Wolf", "Fenring", "Fenring"), ["Seeker"] = new Family("Seeker", "SeekerBrute", "SeekerBrute") }; FamiliesEntry = file.Bind<string>("Creatures", "FamiliesJson", JsonConvert.SerializeObject((object)dictionary), "Target prefab -> Strong, Large and Boss prefab. Missing family uses stronger target variants. Boss means a named ordinary creature; true game bosses are always rejected. Stars follow difficulty. Restart after editing configuration files."); BiomeOverridesEntry = file.Bind<string>("Creatures", "BiomeOverridesJson", JsonConvert.SerializeObject((object)BiomeCatalog.Defaults()), "Target prefab -> allowed Valheim biome names. Vanilla defaults are strict. Separate multiple legitimate biomes with commas. Creatures not listed use their loaded natural SpawnSystem rules. Existing zones are checked and relocated after a change. Restart after editing configuration files."); LargeCreaturesEntry = file.Bind<string>("Creatures", "LargeCreatures", "Troll,Abomination,StoneGolem,Lox,SeekerBrute,Gjall,Morgen_NonSleeping,FallenValkyrie,TrollFrost,JotunWarrior", "Comma-separated prefab names that use reduced spawn caps, smaller batches and longer intervals. Applies both to quest targets and stronger family variants."); AquaticCreaturesEntry = file.Bind<string>("Creatures", "AquaticCreatures", string.Join(",", BiomeCatalog.AquaticDefaults()), "Comma-separated aquatic target prefabs. Their zones search water inside the allowed biome instead of rejecting submerged terrain. Native water-depth rules still apply."); file.SettingChanged += delegate { if (!applyingServerView && Network.Remote != null && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { ApplyServerView(Network.Remote); } }; } internal static void ApplyServerView(Settings server) { if (server == null || applyingServerView) { return; } applyingServerView = true; try { EnabledEntry.Value = server.Enabled; DifficultyEntry.Value = server.Difficulty; RadiusEntry.Value = server.Radius; MinDistanceEntry.Value = server.MinDistance; MaxDistanceEntry.Value = server.MaxDistance; FamiliesEntry.Value = JsonConvert.SerializeObject((object)server.Families); BiomeOverridesEntry.Value = JsonConvert.SerializeObject((object)server.BiomeOverrides); LargeCreaturesEntry.Value = string.Join(",", server.LargeCreatures.OrderBy<string, string>((string x) => x, StringComparer.OrdinalIgnoreCase)); AquaticCreaturesEntry.Value = string.Join(",", server.AquaticCreatures.OrderBy<string, string>((string x) => x, StringComparer.OrdinalIgnoreCase)); } finally { applyingServerView = false; } } internal static Settings Local() { Dictionary<string, Family> dictionary = JsonConvert.DeserializeObject<Dictionary<string, Family>>(FamiliesEntry.Value); Dictionary<string, string> dictionary2 = JsonConvert.DeserializeObject<Dictionary<string, string>>(BiomeOverridesEntry.Value); HashSet<string> largeCreatures = new HashSet<string>(from x in (LargeCreaturesEntry.Value ?? "").Split(',') select x.Trim() into x where x.Length > 0 select x, StringComparer.OrdinalIgnoreCase); HashSet<string> aquaticCreatures = new HashSet<string>(from x in (AquaticCreaturesEntry.Value ?? "").Split(',') select x.Trim() into x where x.Length > 0 select x, StringComparer.OrdinalIgnoreCase); float value = MinDistanceEntry.Value; float value2 = MaxDistanceEntry.Value; return new Settings { Enabled = EnabledEntry.Value, Difficulty = DifficultyEntry.Value, Radius = RadiusEntry.Value, MinDistance = Math.Min(value, value2), MaxDistance = Math.Max(value, value2), Families = new Dictionary<string, Family>(dictionary ?? new Dictionary<string, Family>(), StringComparer.OrdinalIgnoreCase), BiomeOverrides = new Dictionary<string, string>(dictionary2 ?? new Dictionary<string, string>(), StringComparer.OrdinalIgnoreCase), LargeCreatures = largeCreatures, AquaticCreatures = aquaticCreatures }; } internal bool Valid() { if (Enum.IsDefined(typeof(Difficulty), Difficulty) && Radius >= 40f && Radius <= 100f && MinDistance >= 50f && MaxDistance >= MinDistance && MaxDistance <= 10000f && Families != null && Families.Count <= 500 && BiomeOverrides != null && BiomeOverrides.Count <= 1000 && BiomeOverrides.All((KeyValuePair<string, string> x) => !string.IsNullOrWhiteSpace(x.Key) && (int)ParseBiomes(x.Value) > 0) && LargeCreatures != null && LargeCreatures.Count <= 500 && AquaticCreatures != null) { return AquaticCreatures.Count <= 500; } return false; } internal static Biome ParseBiomes(string text) { //IL_0001: 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_0035: 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_0046: 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) Biome val = (Biome)0; string[] array = (text ?? "").Split(','); for (int i = 0; i < array.Length; i++) { if (!Enum.TryParse<Biome>(array[i].Trim(), ignoreCase: true, out Biome result) || !Enum.IsDefined(typeof(Biome), result)) { return (Biome)0; } val |= result; } return val; } } internal sealed class Family { public string Strong; public string Large; public string Boss; public Family() { } public Family(string strong, string large, string boss) { Strong = strong; Large = large; Boss = boss; } } internal static class SpawnController { internal static void Tick(Player player, HuntZone zone, Settings policy) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_059e: Unknown result type (might be due to invalid IL or missing references) //IL_05a3: Unknown result type (might be due to invalid IL or missing references) //IL_05be: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_069b: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0528: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0537: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) bool flag = zone.Contains(((Component)player).transform.position) && !((Character)player).IsTeleporting() && !((Character)player).InCutscene(); if (flag && !zone.Inside) { zone.EnteredAt = Time.realtimeSinceStartup; } zone.Inside = flag; if (!flag || Time.realtimeSinceStartup - zone.EnteredAt < 5f) { return; } long now = ZNet.instance.GetTime().Ticks; foreach (Character allCharacter in Character.GetAllCharacters()) { ZNetView nview = allCharacter.m_nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val != null && !(val.GetString("gqs.zone", "") != zone.ID) && !allCharacter.IsDead()) { string token = val.GetString("gqs.token", ""); SpawnRecord spawnRecord = zone.Creatures.FirstOrDefault((SpawnRecord r) => r.Token == token); if (spawnRecord != null) { spawnRecord.Expires = now + TimeSpan.FromSeconds(90.0).Ticks; } if (allCharacter.m_nview.IsOwner()) { val.Set("gqs.expires", now + TimeSpan.FromSeconds(60.0).Ticks); } } } zone.Creatures.RemoveAll((SpawnRecord r) => r.Expires < now); ((Character)player).m_nview.GetZDO().Set("gqs.activeAttempt", Plugin.State.Attempt); ((Character)player).m_nview.GetZDO().Set("gqs.activeUntil", now + TimeSpan.FromSeconds(4.0).Ticks); if (Time.realtimeSinceStartup < zone.NextSpawn) { return; } bool large = policy.LargeCreatures.Contains(zone.Target); zone.NextSpawn = Time.realtimeSinceStartup + Rules.Interval(policy.Difficulty, large); List<SpawnData> list = Plugin.SpawnRules(zone.Target); if (list.Count == 0) { return; } bool flag2 = policy.AquaticCreatures.Contains(zone.Target) || list.Any(Plugin.IsWaterRule); Biome val2 = (Biome)zone.Biomes; if ((int)val2 == 0) { return; } SpawnSystem spawnSystem = SpawnSystem.m_instances.FirstOrDefault(); if ((Object)(object)spawnSystem == (Object)null) { return; } MethodInfo clone = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); list = ((IEnumerable<SpawnData>)list).Select((Func<SpawnData, SpawnData>)((SpawnData r) => (SpawnData)clone.Invoke(r, null))).ToList(); foreach (SpawnData item in list) { item.m_canSpawnCloseToPlayer = true; } int num = Rules.Limit(policy.Difficulty, large); int num2 = Math.Max(0, Math.Min(Rules.Batch(policy.Difficulty, large), num - zone.Creatures.Count)); int num3 = zone.Creatures.Count((SpawnRecord r) => r.Large); int num4 = 0; int num5 = 0; for (int num6 = 0; num6 < num2; num6++) { Role role = ((policy.Difficulty == Difficulty.VeryHard && !zone.BossSpawned) ? Role.Boss : Rules.Pick(policy.Difficulty, Random.value)); GameObject val3 = SelectPrefab(zone.Target, role, policy); if ((Object)(object)val3 == (Object)null) { continue; } bool flag3 = policy.LargeCreatures.Contains(((Object)val3).name); if (flag3 && (num3 + num4 >= Rules.Limit(policy.Difficulty, large: true) || num4 >= Rules.Batch(policy.Difficulty, large: true))) { continue; } bool flag4 = false; Vector3 position = default(Vector3); for (int num7 = 0; num7 < 32; num7++) { Vector2 val4 = Random.insideUnitCircle * (zone.Radius - 5f); position = zone.Center + new Vector3(val4.x, 0f, val4.y); if (!Player.IsPlayerInRange(position, 15f) && (WorldGenerator.instance.GetBiome(position) & val2) != 0 && !((Object)(object)Heightmap.FindHeightmap(position) == (Object)null) && list.Any((SpawnData rule) => spawnSystem.IsSpawnPointGood(rule, ref position)) && zone.Contains(position) && (flag2 || !(position.y < ZoneSystem.instance.m_waterLevel + 0.5f)) && !((Object)(object)EffectArea.IsPointInsideArea(position, (Type)4, 30f) != (Object)null) && !Physics.CheckSphere(position + Vector3.up * 1.5f, 1f, LayerMask.GetMask(new string[3] { "piece", "static_solid", "Default" }))) { flag4 = true; break; } } if (!flag4) { continue; } GameObject val5 = Object.Instantiate<GameObject>(val3, position + Vector3.up * 0.3f, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f)); Character component = val5.GetComponent<Character>(); ZNetView component2 = val5.GetComponent<ZNetView>(); if ((Object)(object)component2 == (Object)null || !component2.IsValid() || (Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val5); continue; } string text = Guid.NewGuid().ToString("N"); ZDO zDO = component2.GetZDO(); zDO.Set("gqs.zone", zone.ID); zDO.Set("gqs.token", text); zDO.Set("gqs.owner", player.GetPlayerID()); zDO.Set("gqs.quest", Plugin.State.Quest); zDO.Set("gqs.attempt", Plugin.State.Attempt); zDO.Set("gqs.target", zone.Target); zDO.Set("gqs.center", zone.Center); zDO.Set("gqs.radius", zone.Radius); zDO.Set("gqs.expires", now + TimeSpan.FromSeconds(60.0).Ticks); zDO.Set("gqs.boss", role == Role.Boss); component.SetLevel(Rules.Stars(policy.Difficulty, Random.value) + 1); if (role == Role.Boss) { zone.BossSpawned = true; zDO.Set("gqs.name", "Vůdce loviště: " + zone.Target); } BaseAI component3 = val5.GetComponent<BaseAI>(); if (component3 != null) { component3.Alert(); } zone.Creatures.Add(new SpawnRecord { Token = text, Expires = now + TimeSpan.FromSeconds(90.0).Ticks, Boss = (role == Role.Boss), Large = flag3 }); if (flag3) { num4++; } num5++; } if (num5 > 0) { Plugin.Save(); } else if (num2 > 0 && Time.realtimeSinceStartup > zone.LastBlockedNotice + 60f) { zone.LastBlockedNotice = Time.realtimeSinceStartup; Plugin.Notice(L.F("zone.blocked", LanguageRuntime.Creature(zone.Target))); } } private static GameObject SelectPrefab(string target, Role role, Settings settings) { settings.Families.TryGetValue(target, out var value); string text = role switch { Role.Boss => value?.Boss, Role.Large => value?.Large, Role.Strong => value?.Strong, _ => target, }; if (string.IsNullOrWhiteSpace(text)) { text = target; } GameObject prefab = ZNetScene.instance.GetPrefab(text); if ((Object)(object)((prefab != null) ? prefab.GetComponent<Character>() : null) == (Object)null || prefab.GetComponent<Character>().m_boss) { text = target; prefab = ZNetScene.instance.GetPrefab(target); } if (prefab == null || prefab.GetComponent<Character>()?.m_boss != false) { return null; } return prefab; } } internal sealed class TaggedCreature : MonoBehaviour { [HarmonyPatch(typeof(Character), "Awake")] private static class Attach { private static void Postfix(Character __instance) { if (!(__instance is Player)) { ((Component)__instance).gameObject.AddComponent<TaggedCreature>(); } } } [HarmonyPatch(typeof(Character), "OnDeath")] private static class Death { private static void Prefix(Character __instance) { ZNetView nview = __instance.m_nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val == null || Plugin.State == null) { return; } string zoneID = val.GetString("gqs.zone", ""); string token = val.GetString("gqs.token", ""); HuntZone huntZone = Plugin.State.Zones.FirstOrDefault((HuntZone z) => z.ID == zoneID); if (huntZone != null) { huntZone.Creatures.RemoveAll((SpawnRecord c) => c.Token == token); Plugin.Save(); } } } internal const string Zone = "gqs.zone"; internal const string Token = "gqs.token"; internal const string Owner = "gqs.owner"; internal const string Quest = "gqs.quest"; internal const string Attempt = "gqs.attempt"; internal const string Target = "gqs.target"; internal const string Center = "gqs.center"; internal const string Radius = "gqs.radius"; internal const string Expires = "gqs.expires"; internal const string Boss = "gqs.boss"; internal const string Name = "gqs.name"; internal const string ActiveAttempt = "gqs.activeAttempt"; internal const string ActiveUntil = "gqs.activeUntil"; internal const string ActiveZones = "gqs.activeZones"; private Character character; private void Awake() { character = ((Component)this).GetComponent<Character>(); ((MonoBehaviour)this).InvokeRepeating("Check", 1f, 1f); } private void Check() { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) ZNetView val = character?.m_nview; if ((Object)(object)val == (Object)null || !val.IsValid() || (Object)(object)ZNet.instance == (Object)null) { return; } ZDO zDO = val.GetZDO(); if (string.IsNullOrEmpty(zDO.GetString("gqs.zone", ""))) { return; } string text = zDO.GetString("gqs.name", ""); if (!string.IsNullOrEmpty(text)) { character.m_name = (zDO.GetBool("gqs.boss", false) ? L.F("zone.boss", LanguageRuntime.Creature(zDO.GetString("gqs.target", ""))) : text); } if (val.IsOwner() && !character.IsDead()) { long ticks = ZNet.instance.GetTime().Ticks; Player player = Player.GetPlayer(zDO.GetLong("gqs.owner", 0L)); object obj; if (player == null) { obj = null; } else { ZNetView nview = ((Character)player).m_nview; obj = ((nview != null) ? nview.GetZDO() : null); } ZDO val2 = (ZDO)obj; Vector3 vec = zDO.GetVec3("gqs.center", Vector3.zero); float num = zDO.GetFloat("gqs.radius", 0f); if ((Object)(object)player != (Object)null && !((Character)player).IsDead() && val2 != null && val2.GetString("gqs.activeAttempt", "") == zDO.GetString("gqs.attempt", "") && val2.GetLong("gqs.activeUntil", 0L) >= ticks && val2.GetString("gqs.activeZones", "").Split('|').Contains(zDO.GetString("gqs.zone", "")) && Rules.Inside(((Component)player).transform.position.x, ((Component)player).transform.position.z, vec.x, vec.z, num)) { zDO.Set("gqs.expires", ticks + TimeSpan.FromSeconds(60.0).Ticks); } if (zDO.GetLong("gqs.expires", 0L) < ticks || !Rules.Inside(((Component)this).transform.position.x, ((Component)this).transform.position.z, vec.x, vec.z, num + 25f)) { ZNetScene.instance.Destroy(((Component)this).gameObject); } } } internal static KillCredit ResolveKill(ZDO victim, ZDOID attacker) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_002b: 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_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) //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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown if (string.IsNullOrEmpty(victim.GetString("gqs.zone", ""))) { return null; } KillCredit result = new KillCredit { Suppress = true }; ZDO zDO = ZDOMan.instance.GetZDO(attacker); if (zDO == null) { return result; } Vector3 vec = victim.GetVec3("gqs.center", Vector3.zero); float radius = victim.GetFloat("gqs.radius", 0f); Vector3 position = victim.GetPosition(); Vector3 position2 = zDO.GetPosition(); if (!Rules.CanCredit(victim.GetLong("gqs.owner", 0L), zDO.GetLong(ZDOVars.s_playerID, 0L), Rules.Inside(position.x, position.z, vec.x, vec.z, radius), Rules.Inside(position2.x, position2.z, vec.x, vec.z, radius))) { return result; } return new KillCredit { QuestID = victim.GetString("gqs.quest", ""), AttemptID = victim.GetString("gqs.attempt", ""), Prefab = victim.GetString("gqs.target", ""), RecipientPlayerID = victim.GetLong("gqs.owner", 0L), CreditKiller = true }; } } internal static class ZoneMap { private static readonly Dictionary<string, PinData> pins = new Dictionary<string, PinData>(); private static Minimap map; private static Sprite circle; internal static void Update(List<HuntZone> zones, string title) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Minimap.instance == (Object)null) { return; } if ((Object)(object)map != (Object)(object)Minimap.instance) { Clear(); map = Minimap.instance; } if ((Object)(object)circle == (Object)null) { Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { float num = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(64f, 64f)); float num2 = ((num > 63f) ? 0f : ((num > 59f) ? 0.9f : 0.12f)); val.SetPixel(j, i, new Color(1f, 0.08f, 0.04f, num2)); } } val.Apply(); circle = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f)); } string[] array = pins.Keys.Where((string k) => !zones.Any((HuntZone z) => z.ID == k)).ToArray(); foreach (string key in array) { map.RemovePin(pins[key]); pins.Remove(key); } foreach (HuntZone zone in zones) { string text = L.F("zone.pin", title, LanguageRuntime.Creature(zone.Target)); if (pins.TryGetValue(zone.ID, out var value)) { value.m_name = text; continue; } PinData val2 = map.AddPin(zone.Center, (PinType)13, text, false, false, 0L, default(PlatformUserID)); val2.m_icon = circle; val2.m_worldSize = zone.Radius * 2f; pins.Add(zone.ID, val2); } } internal static void Clear() { if ((Object)(object)map != (Object)null) { foreach (PinData value in pins.Values) { map.RemovePin(value); } } pins.Clear(); map = null; } } } namespace GaSQuestSpawner.Core { public static class BiomeCatalog { public static string[] AquaticDefaults() { return new string[3] { "Leech", "Serpent", "BonemawSerpent" }; } public static Dictionary<string, string> Defaults() { return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["Greyling"] = "Meadows", ["Boar"] = "Meadows", ["Deer"] = "Meadows", ["Neck"] = "Meadows", ["Greydwarf"] = "BlackForest", ["Greydwarf_Elite"] = "BlackForest", ["Greydwarf_Shaman"] = "BlackForest", ["Troll"] = "BlackForest", ["Ghost"] = "BlackForest", ["Bjorn"] = "BlackForest", ["Draugr"] = "Swamp", ["Draugr_Ranged"] = "Swamp", ["Draugr_Elite"] = "Swamp", ["Blob"] = "Swamp", ["BlobElite"] = "Swamp", ["Leech"] = "Swamp", ["Wraith"] = "Swamp", ["Abomination"] = "Swamp", ["Surtling"] = "Swamp", ["Skeleton"] = "BlackForest, Swamp", ["Wolf"] = "Mountain", ["Fenring"] = "Mountain", ["Fenring_Cultist"] = "Mountain", ["Hatchling"] = "Mountain", ["StoneGolem"] = "Mountain", ["Ulv"] = "Mountain", ["Goblin"] = "Plains", ["GoblinArcher"] = "Plains", ["GoblinBrute"] = "Plains", ["GoblinShaman"] = "Plains", ["Lox"] = "Plains", ["Deathquito"] = "Plains", ["BlobTar"] = "Plains", ["Unbjorn"] = "Plains", ["Seeker"] = "Mistlands", ["SeekerBrute"] = "Mistlands", ["Tick"] = "Mistlands", ["Gjall"] = "Mistlands", ["Hare"] = "Mistlands", ["Charred_Melee"] = "AshLands", ["Charred_Archer"] = "AshLands", ["Charred_Mage"] = "AshLands", ["Morgen"] = "AshLands", ["Morgen_NonSleeping"] = "AshLands", ["FallenValkyrie"] = "AshLands", ["Asksvin"] = "AshLands", ["Volture"] = "AshLands", ["Greydwarf_Frozen"] = "DeepNorth", ["Skeleton_DeepNorth"] = "DeepNorth", ["TrollFrost"] = "DeepNorth", ["JotunWarrior"] = "DeepNorth", ["JotunWitch"] = "DeepNorth", ["Serpent"] = "Ocean", ["BonemawSerpent"] = "Ocean" }; } } public enum Difficulty { Easy, Normal, Hard, VeryHard } public enum Role { Basic, Strong, Large, Elite, Boss } public static class Rules { public static Difficulty EffectiveDifficulty(Difficulty server, Difficulty owner) { return server; } public static int Limit(Difficulty d, bool large = false) { return ((!large) ? new int[4] { 12, 14, 16, 18 } : new int[4] { 3, 4, 5, 6 })[(int)d]; } public static int Batch(Difficulty d, bool large = false) { return ((!large) ? new int[4] { 3, 3, 4, 5 } : new int[4] { 1, 1, 1, 2 })[(int)d]; } public static float Interval(Difficulty d, bool large = false) { return ((!large) ? new float[4] { 12f, 11f, 10f, 9f } : new float[4] { 18f, 16f, 14f, 12f })[(int)d]; } public static int Stars(Difficulty d, double roll) { int num = (new int[4] { 0, 0, 1, 2 })[(int)d]; int num2 = (new int[4] { 0, 1, 2, 4 })[(int)d]; if (roll < 0.0) { roll = 0.0; } if (roll >= 1.0) { roll = 0.999999999; } return num + (int)(roll * (double)(num2 - num + 1)); } public static int MaxStars(Difficulty d) { return (new int[4] { 0, 1, 2, 4 })[(int)d]; } public static Role Pick(Difficulty d, double roll) { switch (d) { case Difficulty.Easy: return Role.Basic; case Difficulty.Normal: if (!(roll < 0.8)) { return Role.Strong; } return Role.Basic; case Difficulty.Hard: if (!(roll < 0.4)) { if (!(roll < 0.6)) { if (!(roll < 0.75)) { return Role.Elite; } return Role.Large; } return Role.Strong; } return Role.Basic; default: if (!(roll < 0.8)) { return Role.Basic; } return Role.Elite; } } public static bool Inside(float x, float z, float cx, float cz, float radius) { return (x - cx) * (x - cx) + (z - cz) * (z - cz) <= radius * radius; } public static bool CanCredit(long owner, long killer, bool victimInside, bool killerInside) { return owner != 0L && killer != 0 && victimInside && killerInside; } public static IEnumerable<(float x, float z)> Candidates(float min, float max, double phase) { for (float r = min; r <= max; r += 25f) { int count = (int)Math.Ceiling(Math.PI * 2.0 * (double)r / 25.0); for (int i = 0; i < count; i++) { double num = phase + Math.PI * 2.0 * (double)i / (double)count; yield return (x: (float)Math.Cos(num) * r, z: (float)Math.Sin(num) * r); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }