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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FehuAssets.Airships; using FehuAssets.Parrots; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FehuAssets")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FehuAssets")] [assembly: AssemblyTitle("FehuAssets")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } } public sealed class AirshipConfigHolder : MonoBehaviour { } namespace FehuAssets { [BepInPlugin("fehu.assets", "FehuAssets", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class FehuAssetsPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "RemovePiece")] private static class PlayerRemovePiecePatch { private static readonly FieldInfo? HoveringPieceField = AccessTools.Field(typeof(Player), "m_hoveringPiece"); private static bool Prefix(Player __instance) { object? obj = HoveringPieceField?.GetValue(__instance); Piece val = (Piece)((obj is Piece) ? obj : null); if ((Object)(object)val == (Object)null || !IsFehuPiece(val)) { return true; } DestroyFehuPiece(val); return false; } private static bool IsFehuPiece(Piece piece) { return FehuAssetsPlugin.IsFehuPiece(piece); } } private readonly struct DancerPrefabSpec { public string SourcePath { get; } public string SourceName { get; } public string ExposedPrefabName { get; } public string DisplayName { get; } public string Description { get; } public DancerGroup Group { get; } public DancerPrefabSpec(string sourcePath, string sourceName, string exposedPrefabName, string displayName, string description, DancerGroup group) { SourcePath = sourcePath; SourceName = sourceName; ExposedPrefabName = exposedPrefabName; DisplayName = displayName; Description = description; Group = group; } } private readonly struct RequirementSpec { public string Item { get; } public int Amount { get; } public bool Recover { get; } public RequirementSpec(string item, int amount, bool recover) { Item = item; Amount = amount; Recover = recover; } } private enum DancerGroup { Standing, Sitting, Laying } private readonly struct StructurePrefabSpec { public string PrefabName { get; } public string DisplayName { get; } public string Description { get; } public StructureKind Kind { get; } public RequirementSpec[] Requirements { get; } public StructurePrefabSpec(string prefabName, string displayName, string description, StructureKind kind, RequirementSpec[] requirements) { PrefabName = prefabName; DisplayName = displayName; Description = description; Kind = kind; Requirements = requirements; } } private enum StructureKind { Sigil, Monument, Totem } public const string ModGuid = "fehu.assets"; public const string ModName = "FehuAssets"; public const string ModVersion = "1.0.0"; public const string JotunnGuid = "com.jotunn.jotunn"; private const string BundleResourceName = "FehuAssets.Resources.fehu_dancers.bundle"; private const string WhoreHousePrefabName = "GlitnirWhoreHouse"; private const string WhoreHousePrefabPath = "assets/bagual/glitnirlocations/whorehouse/glitnirwhorehouse.prefab"; private static readonly Harmony Harmony = new Harmony("fehu.assets"); private static readonly DancerPrefabSpec[] DancerPrefabs = new DancerPrefabSpec[11] { Dancer("Interior/Decor_1Andar/Diane_Dancer", "Diane_Dancer", "Fehu_DianeDancer", "Astrid Firebraid"), Dancer("Interior/Mulheres/Emily_Dancing", "Emily_Dancing", "Fehu_EmilyDancer", "Freydis Goldhair"), Dancer("Interior/Mulheres/Freya_RedHair_Dancing", "Freya_RedHair_Dancing", "Fehu_FreyaDancer", "Runa Moonveil"), Dancer("Interior/Mulheres/Martha_Dancing", "Martha_Dancing", "Fehu_MarthaDancer", "Thyra Silkstep"), Dancer("Interior/Mulheres/ElficGirl_Blond_Dancer", "ElficGirl_Blond_Dancer", "Fehu_BlondElfDancer", "Eira Silvermist"), Dancer("Interior/Mulheres/ElficGirl_RedHair_Dancer", "ElficGirl_RedHair_Dancer", "Fehu_RedElfDancer", "Ylva Ravenhair"), Dancer("Interior/Mulheres/ElficGirl_Brunette_Dancer", "ElficGirl_Brunette_Dancer", "Fehu_BrunetteElfDancer", "Solveig Honeywine"), Dancer("Interior/Mulheres/ElficGirl_Brunette_Idle", "ElficGirl_Brunette_Idle", "Fehu_BrunetteIdle", "Ingrid Shadowstep"), Sitting("Interior/Mulheres/FreyaSentada01", "FreyaSentada01", "Fehu_FreyaSitting01", "Runa Sitting I"), Sitting("Interior/Mulheres/FreyaSentada02", "FreyaSentada02", "Fehu_FreyaSitting02", "Runa Sitting II"), Laying("Interior/Mulheres/FreyaDeitada01", "FreyaDeitada01", "Fehu_FreyaLaying", "Runa Laying") }; private static readonly StructurePrefabSpec[] StructurePrefabs = new StructurePrefabSpec[3] { new StructurePrefabSpec("piece_fehu_sigil", "Fehu Sigil", "A sacred Fehu rune marker.", StructureKind.Sigil, new RequirementSpec[4] { new RequirementSpec("Stone", 60, recover: true), new RequirementSpec("FineWood", 25, recover: true), new RequirementSpec("SurtlingCore", 5, recover: true), new RequirementSpec("Bronze", 5, recover: true) }), new StructurePrefabSpec("piece_fehu_monument", "Fehu Monument", "A heavy stone monument bearing the Fehu rune.", StructureKind.Monument, new RequirementSpec[4] { new RequirementSpec("Stone", 100, recover: true), new RequirementSpec("BlackMarble", 30, recover: true), new RequirementSpec("SurtlingCore", 8, recover: true), new RequirementSpec("Bronze", 10, recover: true) }), new StructurePrefabSpec("piece_fehu_totem", "Fehu Totem", "A small ritual marker for camps and gathering places.", StructureKind.Totem, new RequirementSpec[4] { new RequirementSpec("Wood", 30, recover: true), new RequirementSpec("RoundLog", 10, recover: true), new RequirementSpec("BoneFragments", 10, recover: true), new RequirementSpec("SurtlingCore", 1, recover: true) }) }; private static AssetBundle? _bundle; private static GameObject? _whoreHousePrefab; private static readonly List RegisteredPrefabs = new List(); private static readonly Dictionary Icons = new Dictionary(); private static ConfigEntry? _enableBuildPieces; private static ConfigEntry? _enableStandingDancers; private static ConfigEntry? _enableSittingDancers; private static ConfigEntry? _enableLayingDancers; private static ConfigEntry? _pieceTable; private static ConfigEntry? _pieceCategory; private static ConfigEntry? _requiredCraftingStation; private static ConfigEntry? _colliderSizeMultiplier; private static ConfigEntry? _recipeCostMultiplier; private static ConfigEntry? _recoverResources; private static ConfigEntry? _enableDancerDebugLogs; private static ConfigEntry? _standingItem1; private static ConfigEntry? _standingItem1Amount; private static ConfigEntry? _standingItem2; private static ConfigEntry? _standingItem2Amount; private static ConfigEntry? _standingItem3; private static ConfigEntry? _standingItem3Amount; private static ConfigEntry? _standingItem4; private static ConfigEntry? _standingItem4Amount; private static ConfigEntry? _sittingItem1; private static ConfigEntry? _sittingItem1Amount; private static ConfigEntry? _sittingItem2; private static ConfigEntry? _sittingItem2Amount; private static ConfigEntry? _sittingItem3; private static ConfigEntry? _sittingItem3Amount; private static ConfigEntry? _sittingItem4; private static ConfigEntry? _sittingItem4Amount; private static ConfigEntry? _layingItem1; private static ConfigEntry? _layingItem1Amount; private static ConfigEntry? _layingItem2; private static ConfigEntry? _layingItem2Amount; private static ConfigEntry? _layingItem3; private static ConfigEntry? _layingItem3Amount; private static ConfigEntry? _layingItem4; private static ConfigEntry? _layingItem4Amount; private ManualLogSource Log => ((BaseUnityPlugin)this).Logger; public ManualLogSource AirshipLog => ((BaseUnityPlugin)this).Logger; public ManualLogSource ParrotLog => ((BaseUnityPlugin)this).Logger; private void Awake() { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Expected O, but got Unknown //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Expected O, but got Unknown //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Expected O, but got Unknown //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Expected O, but got Unknown //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Expected O, but got Unknown //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c5: Expected O, but got Unknown //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Expected O, but got Unknown //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Expected O, but got Unknown //IL_05c7: Unknown result type (might be due to invalid IL or missing references) //IL_05d1: Expected O, but got Unknown try { _enableBuildPieces = ((BaseUnityPlugin)this).Config.Bind("General", "Enable build pieces", true, "Register the Fehu dancer build pieces in the Hammer Fehu tab."); _enableStandingDancers = ((BaseUnityPlugin)this).Config.Bind("General", "Enable standing dancers", true, "Register standing and dancing Fehu build pieces."); _enableSittingDancers = ((BaseUnityPlugin)this).Config.Bind("General", "Enable sitting dancers", true, "Register seated Fehu build pieces."); _enableLayingDancers = ((BaseUnityPlugin)this).Config.Bind("General", "Enable laying dancers", true, "Register laying Fehu build pieces."); _pieceTable = ((BaseUnityPlugin)this).Config.Bind("Build", "Piece table", "Hammer", "Jotunn piece table used for Fehu pieces. Default: Hammer."); _pieceCategory = ((BaseUnityPlugin)this).Config.Bind("Build", "Piece category", "Fehu", "Hammer tab/category name for Fehu pieces."); _requiredCraftingStation = ((BaseUnityPlugin)this).Config.Bind("Build", "Required crafting station", string.Empty, "Required station prefab name. Empty means no station requirement. Example: piece_workbench."); _colliderSizeMultiplier = ((BaseUnityPlugin)this).Config.Bind("Build", "Collider size multiplier", 1f, new ConfigDescription("Multiplier for Fehu dancer removal/selection collider size.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 4f), Array.Empty())); _recipeCostMultiplier = ((BaseUnityPlugin)this).Config.Bind("Recipes", "Recipe cost multiplier", 1f, new ConfigDescription("Multiplier applied to all Fehu dancer recipe costs.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); _recoverResources = ((BaseUnityPlugin)this).Config.Bind("Recipes", "Recover resources", true, "Recover materials when a Fehu dancer build piece is removed."); _enableDancerDebugLogs = ((BaseUnityPlugin)this).Config.Bind("Debug", "EnableDancerDebugLogs", false, "Enable verbose Fehu dancer registration/loading logs."); _standingItem1 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 1", "FineWood", "First recipe item for standing dancer pieces."); _standingItem1Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 1 amount", 10, new ConfigDescription("Amount of item 1 for standing dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _standingItem2 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 2", "LinenThread", "Second recipe item for standing dancer pieces."); _standingItem2Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 2 amount", 4, new ConfigDescription("Amount of item 2 for standing dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _standingItem3 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 3", "Coins", "Third recipe item for standing dancer pieces."); _standingItem3Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 3 amount", 25, new ConfigDescription("Amount of item 3 for standing dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _standingItem4 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 4", "SurtlingCore", "Fourth recipe item for standing dancer pieces."); _standingItem4Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Standing dancers", "Item 4 amount", 3, new ConfigDescription("Amount of item 4 for standing dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _sittingItem1 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 1", "FineWood", "First recipe item for sitting dancer pieces."); _sittingItem1Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 1 amount", 8, new ConfigDescription("Amount of item 1 for sitting dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _sittingItem2 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 2", "DeerHide", "Second recipe item for sitting dancer pieces."); _sittingItem2Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 2 amount", 4, new ConfigDescription("Amount of item 2 for sitting dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _sittingItem3 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 3", "Coins", "Third recipe item for sitting dancer pieces."); _sittingItem3Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 3 amount", 20, new ConfigDescription("Amount of item 3 for sitting dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _sittingItem4 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 4", "SurtlingCore", "Fourth recipe item for sitting dancer pieces."); _sittingItem4Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Sitting dancers", "Item 4 amount", 3, new ConfigDescription("Amount of item 4 for sitting dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _layingItem1 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 1", "FineWood", "First recipe item for laying dancer pieces."); _layingItem1Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 1 amount", 8, new ConfigDescription("Amount of item 1 for laying dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _layingItem2 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 2", "DeerHide", "Second recipe item for laying dancer pieces."); _layingItem2Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 2 amount", 6, new ConfigDescription("Amount of item 2 for laying dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _layingItem3 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 3", "Coins", "Third recipe item for laying dancer pieces."); _layingItem3Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 3 amount", 20, new ConfigDescription("Amount of item 3 for laying dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); _layingItem4 = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 4", "SurtlingCore", "Fourth recipe item for laying dancer pieces."); _layingItem4Amount = ((BaseUnityPlugin)this).Config.Bind("Recipes - Laying dancers", "Item 4 amount", 3, new ConfigDescription("Amount of item 4 for laying dancer pieces.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); if (!_enableBuildPieces.Value) { DancerLogInfo("Fehu dancer build pieces are disabled in config."); return; } _bundle = LoadEmbeddedDancerBundle(); _whoreHousePrefab = LoadWhoreHousePrefab(_bundle); Harmony.PatchAll(typeof(FehuAssetsPlugin).Assembly); new FehuAirshipRegistry(this).Register(); new ParrotRegistry(this).Register(); EnsurePieceCategory(); RegisterDancerPrefabs(_whoreHousePrefab); } catch (Exception arg) { Log.LogError((object)string.Format("Failed to initialize {0}: {1}", "FehuAssets", arg)); } } private void OnDestroy() { Harmony.UnpatchSelf(); } private void DancerLogInfo(string message) { ConfigEntry? enableDancerDebugLogs = _enableDancerDebugLogs; if (enableDancerDebugLogs != null && enableDancerDebugLogs.Value) { Log.LogInfo((object)message); } } private AssetBundle LoadEmbeddedDancerBundle() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("FehuAssets.Resources.fehu_dancers.bundle"); if (stream == null) { string text = string.Join(", ", executingAssembly.GetManifestResourceNames()); throw new InvalidOperationException("Embedded dancer bundle resource 'FehuAssets.Resources.fehu_dancers.bundle' was not found. Available resources: " + text); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); AssetBundle obj = AssetBundle.LoadFromMemory(memoryStream.ToArray()); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("Unity failed to load embedded Fehu dancers AssetBundle."); } DancerLogInfo("Loaded embedded Fehu dancers AssetBundle."); return obj; } private GameObject LoadWhoreHousePrefab(AssetBundle bundle) { GameObject val = bundle.LoadAsset("GlitnirWhoreHouse"); if ((Object)(object)val == (Object)null) { val = bundle.LoadAsset("assets/bagual/glitnirlocations/whorehouse/glitnirwhorehouse.prefab"); } if ((Object)(object)val == (Object)null) { string text = string.Join(", ", from name in bundle.GetAllAssetNames() where name.IndexOf("whorehouse", StringComparison.OrdinalIgnoreCase) >= 0 select name); throw new InvalidOperationException("Could not load 'GlitnirWhoreHouse'. Matching bundle assets: " + text); } return val; } private static int RemoveFehuPieces(float? radius) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) Vector3 val = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero); int num = 0; Piece[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Piece val2 in array) { if (IsFehuPiece(val2) && (!radius.HasValue || !(Vector3.Distance(val, ((Component)val2).transform.position) > radius.Value))) { DestroyFehuPiece(val2); num++; } } return num; } private static void DestroyFehuPiece(Piece piece) { ZNetView component = ((Component)piece).GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { if (!component.IsOwner()) { component.ClaimOwnership(); } component.Destroy(); } else { Object.Destroy((Object)(object)((Component)piece).gameObject); } } private static bool IsFehuPiece(Piece piece) { return ((Object)((Component)piece).gameObject).name.StartsWith("Fehu_", StringComparison.Ordinal); } private void RegisterDancerPrefabs(GameObject whoreHousePrefab) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) DancerPrefabSpec[] dancerPrefabs = DancerPrefabs; for (int i = 0; i < dancerPrefabs.Length; i++) { DancerPrefabSpec spec = dancerPrefabs[i]; if (!IsGroupEnabled(spec.Group)) { DancerLogInfo("Skipped disabled Fehu build piece '" + spec.ExposedPrefabName + "'."); continue; } Transform val = whoreHousePrefab.transform.Find(spec.SourcePath); if ((Object)(object)val == (Object)null) { val = FindDeepChild(whoreHousePrefab.transform, spec.SourceName); } if ((Object)(object)val == (Object)null) { Log.LogError((object)("Missing dancer GameObject '" + spec.SourceName + "' at '" + spec.SourcePath + "'.")); continue; } GameObject val2 = CreateDancerPiecePrefab(((Component)val).gameObject, spec); Sprite orCreateIcon = GetOrCreateIcon(spec); PrepareBuildPiece(val2, spec, orCreateIcon); val2.SetActive(true); val2.transform.position = new Vector3(0f, -10000f, 0f); Object.DontDestroyOnLoad((Object)(object)val2); RegisterWithJotunn(val2, spec, orCreateIcon); RegisteredPrefabs.Add(val2); DancerLogInfo("Registered Fehu build piece '" + spec.ExposedPrefabName + "' from '" + spec.SourceName + "'."); } DancerLogInfo($"Registered {RegisteredPrefabs.Count}/{DancerPrefabs.Length} Fehu dancer build pieces in the Fehu tab."); } private void RegisterStructurePrefabs() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) int num = 0; StructurePrefabSpec[] structurePrefabs = StructurePrefabs; for (int i = 0; i < structurePrefabs.Length; i++) { StructurePrefabSpec spec = structurePrefabs[i]; try { GameObject val = CreateStructurePrefab(spec); Sprite icon = CreateStructureIcon(spec); PrepareBuildPiece(val, spec.DisplayName, spec.Description, icon); val.SetActive(true); val.transform.position = new Vector3(0f, -10000f, 0f); Object.DontDestroyOnLoad((Object)(object)val); RegisterWithJotunn(val, spec.DisplayName, spec.Description, spec.Requirements, icon); RegisteredPrefabs.Add(val); num++; DancerLogInfo("Registered Fehu structure piece '" + spec.PrefabName + "'."); } catch (Exception arg) { Log.LogError((object)$"Failed to register Fehu structure '{spec.PrefabName}': {arg}"); } } DancerLogInfo($"Registered {num}/{StructurePrefabs.Length} Fehu structure pieces in the Fehu tab."); } private IEnumerator RegisterStructurePrefabsWhenReady() { for (int i = 0; i < 300; i++) { if ((Object)(object)ZNetScene.instance != (Object)null && (Object)(object)ZNetScene.instance.GetPrefab("piece_stonestair") != (Object)null) { RegisterStructurePrefabs(); yield break; } yield return null; } Log.LogError((object)"Timed out waiting for vanilla Valheim prefabs. Fehu Sigil/Monument/Totem were not registered."); } private static DancerPrefabSpec Dancer(string sourcePath, string sourceName, string exposedPrefabName, string displayName) { return new DancerPrefabSpec(sourcePath, sourceName, exposedPrefabName, displayName, DescriptionFor(exposedPrefabName), DancerGroup.Standing); } private static DancerPrefabSpec Sitting(string sourcePath, string sourceName, string exposedPrefabName, string displayName) { return new DancerPrefabSpec(sourcePath, sourceName, exposedPrefabName, displayName, DescriptionFor(exposedPrefabName), DancerGroup.Sitting); } private static DancerPrefabSpec Laying(string sourcePath, string sourceName, string exposedPrefabName, string displayName) { return new DancerPrefabSpec(sourcePath, sourceName, exposedPrefabName, displayName, DescriptionFor(exposedPrefabName), DancerGroup.Laying); } private static string DescriptionFor(string exposedPrefabName) { return exposedPrefabName switch { "Fehu_DianeDancer" => "Ognistowłosa tancerka Fehu, która wnosi do sali ciepło, rytm i odrobinę niebezpiecznego blasku.", "Fehu_EmilyDancer" => "Złotowłosa ozdoba długiego domu, lekka jak pieśń przy miodzie i jasna jak poranny skarb.", "Fehu_FreyaDancer" => "Runa Moonveil tańczy jak srebrny cień pod księżycem, spokojna i hipnotyczna.", "Fehu_MarthaDancer" => "Thyra Silkstep trzyma rytm z gracją dworskiej artystki i pewnością kogoś, kto zna swoją scenę.", "Fehu_BlondElfDancer" => "Elficka tancerka o jasnych włosach, stworzona do komnat pełnych światła, złota i cichej magii.", "Fehu_RedElfDancer" => "Rudowłosa elfka Fehu, żywa iskra wśród lamp, run i nocnych opowieści.", "Fehu_BrunetteElfDancer" => "Solveig Honeywine porusza się miękko i pewnie, jakby każdy krok był częścią starego rytuału.", "Fehu_BrunetteIdle" => "Ingrid Shadowstep czeka w ciszy, chłodna, elegancka i gotowa do ozdobienia mrocznej sali.", "Fehu_FreyaSitting01" => "Siedząca Runa, spokojna dekoracja do komnat, łaźni i prywatnych zakątków.", "Fehu_FreyaSitting02" => "Druga poza siedzącej Runy, bardziej dworska, idealna przy tronie albo palenisku.", "Fehu_FreyaLaying" => "Leżąca Runa, leniwa ozdoba komnaty odpoczynku, łóżka albo zacisznej alkowy.", _ => "Dekoracyjna tancerka Fehu.", }; } private static void PrepareBuildPiece(GameObject prefab, DancerPrefabSpec spec, Sprite icon) { PrepareBuildPiece(prefab, spec.DisplayName, spec.Description, icon); } private static GameObject CreateDancerPiecePrefab(GameObject source, DancerPrefabSpec spec) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateBuildPieceRoot(spec.ExposedPrefabName); val.SetActive(false); GameObject val2 = Object.Instantiate(source); ((Object)val2).name = spec.SourceName + "_Visual"; SanitizeDancerPrefab(val2); val2.transform.SetParent(val.transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; Bounds val3 = CalculateRendererBounds(val); if (((Bounds)(ref val3)).size != Vector3.zero) { Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(((Bounds)(ref val3)).center.x, ((Bounds)(ref val3)).min.y, ((Bounds)(ref val3)).center.z); Transform transform = val2.transform; transform.localPosition -= val4; } return val; } private static GameObject CreateBuildPieceRoot(string prefabName) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.GetPrefab("piece_woodpole") : null); if ((Object)(object)val == (Object)null && (Object)(object)instance != (Object)null) { val = instance.GetPrefab("piece_stonefloor2x2"); } GameObject val2 = (GameObject)(((Object)(object)val != (Object)null) ? ((object)Object.Instantiate(val)) : ((object)new GameObject(prefabName))); ((Object)val2).name = prefabName; Transform[] array = ((IEnumerable)val2.transform).Cast().ToArray(); for (int i = 0; i < array.Length; i++) { Object.DestroyImmediate((Object)(object)((Component)array[i]).gameObject); } Renderer[] componentsInChildren = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Collider[] componentsInChildren2 = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } Rigidbody[] componentsInChildren3 = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { DestroyRigidbodyIfSafe(componentsInChildren3[i]); } return val2; } private static Bounds CalculateRendererBounds(GameObject target) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_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_002e: 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) Renderer[] componentsInChildren = target.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return new Bounds(Vector3.zero, Vector3.zero); } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return bounds; } private static void PrepareBuildPiece(GameObject prefab, string displayName, string description, Sprite icon) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) SetLayerRecursive(prefab, LayerMask.NameToLayer("piece")); ZNetView obj = prefab.GetComponent() ?? prefab.AddComponent(); obj.m_persistent = true; obj.m_type = (ObjectType)0; Piece obj2 = prefab.GetComponent() ?? prefab.AddComponent(); obj2.m_name = displayName; obj2.m_description = description; obj2.m_icon = icon; obj2.m_enabled = true; obj2.m_category = (PieceCategory)0; obj2.m_craftingStation = null; obj2.m_resources = Array.Empty(); MakePlacementPermissive(obj2); EnsureRemovalTarget(prefab); RemoveProblematicWearNTear(prefab); } private static void EnsureRemovalTarget(GameObject prefab) { //IL_003e: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_0081: 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) BoxCollider val = prefab.GetComponent() ?? prefab.AddComponent(); ((Collider)val).isTrigger = false; float num = Mathf.Clamp(_colliderSizeMultiplier?.Value ?? 1f, 0.25f, 4f); Bounds val2 = CalculateRendererBounds(prefab); if (((Bounds)(ref val2)).size == Vector3.zero) { val.center = new Vector3(0f, 1f, 0f); val.size = new Vector3(0.8f, 2f, 0.8f) * num; } else { Vector3 center = prefab.transform.InverseTransformPoint(((Bounds)(ref val2)).center); val.center = center; val.size = new Vector3(Mathf.Max(0.8f, ((Bounds)(ref val2)).size.x + 0.25f), Mathf.Max(0.8f, ((Bounds)(ref val2)).size.y + 0.25f), Mathf.Max(0.8f, ((Bounds)(ref val2)).size.z + 0.25f)) * num; } } private static void SanitizeDancerPrefab(GameObject prefab) { RemoveComponentsByTypeName(prefab, "Character", "Humanoid", "MonsterAI", "BaseAI", "AnimalAI", "Tameable", "Procreation", "Growup", "Ragdoll", "ZSyncAnimation"); Collider[] componentsInChildren = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Rigidbody[] componentsInChildren2 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { DestroyRigidbodyIfSafe(componentsInChildren2[i]); } ZNetView[] componentsInChildren3 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } Piece[] componentsInChildren4 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } WearNTear[] componentsInChildren5 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren5.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren5[i]); } } private static void RemoveComponentsByTypeName(GameObject prefab, params string[] typeNames) { HashSet hashSet = new HashSet(typeNames, StringComparer.Ordinal); Component[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val != (Object)null && hashSet.Contains(((object)val).GetType().Name)) { Object.DestroyImmediate((Object)(object)val); } } } private static void SetLayerRecursive(GameObject target, int layer) { if (layer >= 0) { target.layer = layer; Transform[] componentsInChildren = target.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.layer = layer; } } } private static GameObject CreateStructurePrefab(StructurePrefabSpec spec) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01df: 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) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_046e: 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_0499: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_0516: 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) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0546: Unknown result type (might be due to invalid IL or missing references) //IL_056c: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_059c: Unknown result type (might be due to invalid IL or missing references) //IL_05b0: Unknown result type (might be due to invalid IL or missing references) //IL_05c4: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Unknown result type (might be due to invalid IL or missing references) //IL_05ef: Unknown result type (might be due to invalid IL or missing references) //IL_0603: Unknown result type (might be due to invalid IL or missing references) //IL_0629: Unknown result type (might be due to invalid IL or missing references) //IL_062e: Unknown result type (might be due to invalid IL or missing references) //IL_0642: Unknown result type (might be due to invalid IL or missing references) //IL_0663: Unknown result type (might be due to invalid IL or missing references) GameObject val = CreateBuildPieceRoot(spec.PrefabName); val.layer = LayerMask.NameToLayer("piece"); Material material = CreateMaterial("FehuAssets_RuneGold", new Color(1f, 0.62f, 0.08f, 1f)); switch (spec.Kind) { case StructureKind.Sigil: AddPrefabChild(val, "piece_stonefloor2x2", "stone_plinth", new Vector3(0f, 0f, 0f), Vector3.zero, new Vector3(1.15f, 0.35f, 0.85f)); AddPrefabChild(val, "piece_darkwoodpole4", "left_post", new Vector3(-0.62f, 0.95f, -0.08f), Vector3.zero, new Vector3(0.85f, 0.85f, 0.85f)); AddPrefabChild(val, "piece_darkwoodpole4", "right_post", new Vector3(0.62f, 0.95f, -0.08f), Vector3.zero, new Vector3(0.85f, 0.85f, 0.85f)); AddPrefabChild(val, "piece_stonewall1x1", "dark_stone_face", new Vector3(0f, 0.92f, -0.16f), Vector3.zero, new Vector3(0.9f, 0.95f, 0.25f)); AddFehuRuneFromBeams(val, "sigil", new Vector3(0f, 1.02f, -0.36f), 0.78f, material); AddPrefabChild(val, "piece_dvergr_lantern", "low_lantern", new Vector3(0.1f, 0.42f, -0.18f), Vector3.zero, new Vector3(0.55f, 0.55f, 0.55f)); break; case StructureKind.Monument: AddPrefabChild(val, "piece_stonefloor4x4", "main_base", new Vector3(0f, 0f, 0f), Vector3.zero, new Vector3(1f, 0.35f, 0.75f)); AddPrefabChild(val, "piece_stonestair", "stair_1", new Vector3(0f, 0.12f, -1.05f), Vector3.zero, new Vector3(0.95f, 0.8f, 0.95f)); AddPrefabChild(val, "piece_stonestair", "stair_2", new Vector3(0f, 0.34f, -0.75f), Vector3.zero, new Vector3(0.75f, 0.7f, 0.75f)); AddPrefabChild(val, "piece_stonewall2x1", "left_wall", new Vector3(-0.42f, 1.25f, 0.1f), Vector3.zero, new Vector3(0.65f, 1.2f, 0.65f)); AddPrefabChild(val, "piece_stonewall2x1", "right_wall", new Vector3(0.42f, 1.25f, 0.1f), Vector3.zero, new Vector3(0.65f, 1.2f, 0.65f)); AddPrefabChild(val, "piece_stonewall1x1", "cap", new Vector3(0f, 2.35f, 0.1f), Vector3.zero, new Vector3(1.2f, 0.35f, 0.55f)); AddPrefabChild(val, "piece_darkwoodpole4", "left_pillar", new Vector3(-1.15f, 1.4f, 0f), Vector3.zero, new Vector3(0.9f, 0.9f, 0.9f)); AddPrefabChild(val, "piece_darkwoodpole4", "right_pillar", new Vector3(1.15f, 1.4f, 0f), Vector3.zero, new Vector3(0.9f, 0.9f, 0.9f)); AddPrefabChild(val, "piece_banner01", "left_banner", new Vector3(-1.45f, 1.25f, -0.12f), Vector3.zero, new Vector3(0.8f, 0.8f, 0.8f)); AddPrefabChild(val, "piece_banner01", "right_banner", new Vector3(1.45f, 1.25f, -0.12f), Vector3.zero, new Vector3(0.8f, 0.8f, 0.8f)); AddPrefabChild(val, "piece_groundtorch", "left_torch", new Vector3(-0.75f, 0.35f, -0.65f), Vector3.zero, new Vector3(0.8f, 0.8f, 0.8f)); AddPrefabChild(val, "piece_groundtorch", "right_torch", new Vector3(0.75f, 0.35f, -0.65f), Vector3.zero, new Vector3(0.8f, 0.8f, 0.8f)); AddFehuRuneFromBeams(val, "monument", new Vector3(0f, 1.48f, -0.36f), 0.95f, material); break; case StructureKind.Totem: AddPrefabChild(val, "piece_stonefloor2x2", "rock_base", new Vector3(0f, 0f, 0f), Vector3.zero, new Vector3(0.85f, 0.35f, 0.85f)); AddPrefabChild(val, "piece_woodpole2", "core_a", new Vector3(-0.12f, 1.05f, 0f), Vector3.zero, Vector3.one); AddPrefabChild(val, "piece_woodpole2", "core_b", new Vector3(0.12f, 1.05f, 0f), Vector3.zero, Vector3.one); AddPrefabChild(val, "piece_darkwoodbeam", "crossbar", new Vector3(0f, 1.62f, 0f), new Vector3(0f, 90f, 0f), new Vector3(0.95f, 0.95f, 0.95f)); AddPrefabChild(val, "piece_dvergr_lantern", "left_lantern", new Vector3(-0.95f, 1.05f, 0f), Vector3.zero, new Vector3(0.55f, 0.55f, 0.55f)); AddPrefabChild(val, "piece_dvergr_lantern", "right_lantern", new Vector3(0.95f, 1.05f, 0f), Vector3.zero, new Vector3(0.55f, 0.55f, 0.55f)); AddFehuRuneFromBeams(val, "totem", new Vector3(0f, 1.28f, -0.18f), 0.62f, material); break; } return val; } private static void AddFehuRuneFromBeams(GameObject root, string prefix, Vector3 center, float scale, Material? material) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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) AddPrefabChild(root, "piece_darkwoodbeam", prefix + "_fehu_stave", center + new Vector3(-0.12f * scale, 0f, 0f), new Vector3(0f, 0f, 90f), new Vector3(0.42f * scale, 0.42f * scale, 0.42f * scale), material); AddPrefabChild(root, "piece_darkwoodbeam", prefix + "_fehu_top_branch", center + new Vector3(0.16f * scale, 0.22f * scale, -0.01f), new Vector3(0f, 0f, 32f), new Vector3(0.36f * scale, 0.36f * scale, 0.36f * scale), material); AddPrefabChild(root, "piece_darkwoodbeam", prefix + "_fehu_mid_branch", center + new Vector3(0.13f * scale, -0.02f * scale, -0.01f), new Vector3(0f, 0f, 32f), new Vector3(0.31f * scale, 0.31f * scale, 0.31f * scale), material); } private static GameObject AddPrefabChild(GameObject parent, string prefabName, string childName, Vector3 localPosition, Vector3 localEuler, Vector3 localScale, Material? material = null) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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) GameObject val = Object.Instantiate(ZNetScene.instance.GetPrefab(prefabName) ?? throw new InvalidOperationException("Vanilla Valheim prefab '" + prefabName + "' was not found.")); ((Object)val).name = childName; StripBuildComponents(val); if ((Object)(object)material != (Object)null) { ApplyMaterial(val, material); } val.transform.SetParent(parent.transform, false); val.transform.localPosition = localPosition; val.transform.localRotation = Quaternion.Euler(localEuler); val.transform.localScale = localScale; SetLayerRecursive(val, parent.layer); return val; } private static void ApplyMaterial(GameObject target, Material material) { Renderer[] componentsInChildren = target.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { sharedMaterials[j] = material; } val.sharedMaterials = sharedMaterials; } } private static void StripBuildComponents(GameObject prefab) { ZNetView[] componentsInChildren = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Piece[] componentsInChildren2 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } WearNTear[] componentsInChildren3 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } Collider[] componentsInChildren4 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } } private static void AddFehuRune(GameObject parent, Material? main, Material? accent, float width, float height, float z) { //IL_0018: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00d6: Unknown result type (might be due to invalid IL or missing references) AddBox(parent, "fehu_stave", new Vector3((0f - width) * 0.35f, height * 0.55f, z), new Vector3(0.14f, height, 0.12f), main); AddBox(parent, "fehu_branch_top", new Vector3(width * 0.08f, height * 0.85f, z - 0.01f), new Vector3(width, 0.12f, 0.13f), accent, (Vector3?)new Vector3(0f, 0f, -35f)); AddBox(parent, "fehu_branch_mid", new Vector3(width * 0.05f, height * 0.58f, z - 0.01f), new Vector3(width * 0.82f, 0.12f, 0.13f), accent, (Vector3?)new Vector3(0f, 0f, -35f)); } private static void AddBox(GameObject parent, string name, Vector3 localPosition, Vector3 localScale, Material? material, Vector3? localEuler = null) { //IL_0031: 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_0049: 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_0067: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj).name = name; obj.layer = parent.layer; obj.transform.SetParent(parent.transform, false); obj.transform.localPosition = localPosition; obj.transform.localRotation = Quaternion.Euler((Vector3)(((??)localEuler) ?? Vector3.zero)); obj.transform.localScale = localScale; Renderer component = obj.GetComponent(); if ((Object)(object)material != (Object)null) { component.material = material; } Collider component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } } private static Material? CreateMaterial(string name, Color color) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_005d: 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) Shader val = Shader.Find("Legacy Shaders/Diffuse") ?? Shader.Find("Diffuse") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { name = name }; val2.color = color; if (val2.HasProperty("_Color")) { val2.SetColor("_Color", color); } Object.DontDestroyOnLoad((Object)(object)val2); return val2; } private static void MakePlacementPermissive(Piece piece) { Type? typeFromHandle = typeof(Piece); SetPieceField(typeFromHandle, piece, "m_groundOnly", value: false); SetPieceField(typeFromHandle, piece, "m_groundPiece", value: false); SetPieceField(typeFromHandle, piece, "m_cultivatedGroundOnly", value: false); SetPieceField(typeFromHandle, piece, "m_waterPiece", value: false); SetPieceField(typeFromHandle, piece, "m_noInWater", value: false); SetPieceField(typeFromHandle, piece, "m_notOnWood", value: false); SetPieceField(typeFromHandle, piece, "m_notOnFloor", value: false); SetPieceField(typeFromHandle, piece, "m_notOnTiltingSurface", value: false); SetPieceField(typeFromHandle, piece, "m_inCeilingOnly", value: false); SetPieceField(typeFromHandle, piece, "m_onlyInTeleportArea", value: false); SetPieceField(typeFromHandle, piece, "m_allowedInDungeons", value: true); SetPieceField(typeFromHandle, piece, "m_canBeRemoved", value: true); SetPieceField(typeFromHandle, piece, "m_clipGround", value: false); SetPieceField(typeFromHandle, piece, "m_clipEverything", value: false); } private static void SetPieceField(Type pieceType, Piece piece, string fieldName, bool value) { FieldInfo field = pieceType.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public); if (field?.FieldType == typeof(bool)) { field.SetValue(piece, value); } } private static void SetBoolField(Type type, object instance, string fieldName, bool value) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public); if (field?.FieldType == typeof(bool)) { field.SetValue(instance, value); } } private static void SetFloatField(Type type, object instance, string fieldName, float value) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public); if (field?.FieldType == typeof(float)) { field.SetValue(instance, value); } } private static void SetEnumField(Type type, object instance, string fieldName, string value) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public); if ((object)field != null && field.FieldType.IsEnum) { field.SetValue(instance, Enum.Parse(field.FieldType, value)); } } private static bool IsGroupEnabled(DancerGroup group) { return group switch { DancerGroup.Standing => _enableStandingDancers?.Value ?? true, DancerGroup.Sitting => _enableSittingDancers?.Value ?? true, DancerGroup.Laying => _enableLayingDancers?.Value ?? true, _ => true, }; } private static int ScaleAmount(int amount) { float num = _recipeCostMultiplier?.Value ?? 1f; return Mathf.Max(0, Mathf.CeilToInt((float)amount * num)); } private static void RemoveProblematicWearNTear(GameObject prefab) { WearNTear[] componentsInChildren = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } private static void DestroyRigidbodyIfSafe(Rigidbody rigidbody) { if (!((Object)(object)rigidbody == (Object)null)) { Debug.Log((object)("[FehuAirships] Rigidbody removal attempt object=" + GetHierarchyPath(((Component)rigidbody).transform) + " prefab=" + ((Object)((Component)rigidbody).transform.root).name + " components=" + DescribeComponents(((Component)rigidbody).gameObject))); if (!ShouldPreserveRigidbody(((Component)rigidbody).gameObject)) { Object.DestroyImmediate((Object)(object)rigidbody); } } } private static bool ShouldPreserveRigidbody(GameObject go) { if ((Object)(object)go.GetComponent() != (Object)null || (Object)(object)go.GetComponent() != (Object)null || (Object)(object)go.GetComponent() != (Object)null || (Object)(object)go.GetComponent() != (Object)null || (Object)(object)go.GetComponent() != (Object)null) { return true; } Component[] components = go.GetComponents(); foreach (Component val in components) { if ((Object)(object)val == (Object)null) { continue; } foreach (RequireComponent item in Attribute.GetCustomAttributes(((object)val).GetType(), typeof(RequireComponent), inherit: true).OfType()) { if (item.m_Type0 == typeof(Rigidbody) || item.m_Type1 == typeof(Rigidbody) || item.m_Type2 == typeof(Rigidbody)) { return true; } } } return false; } private static string DescribeComponents(GameObject go) { return string.Join(",", from component in go.GetComponents() where (Object)(object)component != (Object)null select ((object)component).GetType().Name); } private static string GetHierarchyPath(Transform transform) { List list = new List(); Transform val = transform; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } private static Sprite GetOrCreateIcon(DancerPrefabSpec spec) { if (Icons.TryGetValue(spec.ExposedPrefabName, out Sprite value)) { return value; } Sprite val = LoadEmbeddedIcon(spec) ?? CreateFallbackIcon(spec); Icons[spec.ExposedPrefabName] = val; return val; } private static Sprite? LoadEmbeddedIcon(DancerPrefabSpec spec) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_008c: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) string name = "FehuAssets.Resources.Icons." + spec.ExposedPrefabName + ".rgba"; using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); byte[] array = memoryStream.ToArray(); if (array.Length != 65536) { return null; } Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false) { name = spec.ExposedPrefabName + "_IconTexture", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; byte[] array2 = FlipRawRgbaVertically(array, 128, 128); val.LoadRawTextureData(array2); val.Apply(false, true); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width); ((Object)obj).name = spec.ExposedPrefabName + "_Icon"; Object.DontDestroyOnLoad((Object)(object)val); Object.DontDestroyOnLoad((Object)(object)obj); return obj; } private static byte[] FlipRawRgbaVertically(byte[] source, int width, int height) { int num = width * 4; byte[] array = new byte[source.Length]; for (int i = 0; i < height; i++) { Buffer.BlockCopy(source, i * num, array, (height - 1 - i) * num, num); } return array; } private static Sprite CreateFallbackIcon(DancerPrefabSpec spec) { //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_0028: 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_0037: Expected O, but got Unknown //IL_003e: 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_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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_0391: 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_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false) { name = spec.ExposedPrefabName + "_IconTexture", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; Color32 val2 = ColorFromName(spec.ExposedPrefabName); Color32 val3 = HairColorFor(spec.ExposedPrefabName); Color32 val4 = default(Color32); ((Color32)(ref val4))..ctor((byte)(val2.r / 3), (byte)(val2.g / 3), (byte)(val2.b / 3), byte.MaxValue); Color32 val5 = default(Color32); ((Color32)(ref val5))..ctor((byte)Mathf.Min(255, val2.r + 70), (byte)Mathf.Min(255, val2.g + 70), (byte)Mathf.Min(255, val2.b + 70), byte.MaxValue); Color32[] array = (Color32[])(object)new Color32[16384]; for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { bool flag = j < 5 || i < 5 || j >= 123 || i >= 123; bool num = InEllipse(j, i, 64, 34, 21, 23); bool flag2 = InEllipse(j, i, 64, 29, 28, 22) && !InEllipse(j, i, 64, 43, 18, 14); bool flag3 = j >= 56 && j <= 72 && i >= 52 && i <= 67; bool num2 = InEllipse(j, i, 64, 83, 31, 36); bool num3 = InEllipse(j, i, 64, 98, 38, 25); bool flag4 = i >= 70 && i <= 82 && Mathf.Abs(j - 64) < 18; bool flag5 = Mathf.Abs((float)(j - 39) + (float)(i - 74) * 0.35f) < 6f && i >= 58 && i <= 100; bool flag6 = Mathf.Abs((float)(j - 89) - (float)(i - 74) * 0.35f) < 6f && i >= 58 && i <= 100; bool flag7 = Mathf.Abs(j - 26) + Mathf.Abs(i - 28) < 9 || Mathf.Abs(j - 101) + Mathf.Abs(i - 92) < 8; array[i * 128 + j] = (flag ? val5 : val4); if (num3) { array[i * 128 + j] = val4; } if (num2) { array[i * 128 + j] = val2; } if (flag5 || flag6 || flag3) { array[i * 128 + j] = new Color32((byte)236, (byte)188, (byte)150, byte.MaxValue); } if (flag4) { array[i * 128 + j] = val5; } if (num) { array[i * 128 + j] = new Color32((byte)236, (byte)188, (byte)150, byte.MaxValue); } if (flag2) { array[i * 128 + j] = val3; } if (flag7) { array[i * 128 + j] = new Color32(byte.MaxValue, (byte)236, (byte)154, byte.MaxValue); } } } val.SetPixels32(array); val.Apply(false, true); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 128f); ((Object)obj).name = spec.ExposedPrefabName + "_Icon"; Object.DontDestroyOnLoad((Object)(object)val); Object.DontDestroyOnLoad((Object)(object)obj); return obj; } private static Sprite CreateStructureIcon(StructurePrefabSpec spec) { //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_0028: 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_0037: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: 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_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false) { name = spec.PrefabName + "_IconTexture", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; Color32 element = ((spec.Kind == StructureKind.Monument) ? new Color32((byte)54, (byte)62, (byte)66, byte.MaxValue) : new Color32((byte)45, (byte)38, (byte)31, byte.MaxValue)); Color32 color = default(Color32); ((Color32)(ref color))..ctor((byte)55, (byte)235, (byte)190, byte.MaxValue); Color32 color2 = default(Color32); ((Color32)(ref color2))..ctor((byte)145, (byte)151, (byte)145, byte.MaxValue); Color32 color3 = default(Color32); ((Color32)(ref color3))..ctor((byte)95, (byte)65, (byte)39, byte.MaxValue); Color32[] array = Enumerable.Repeat(element, 16384).ToArray(); DrawRect(array, 128, 12, 108, 104, 8, color2); switch (spec.Kind) { case StructureKind.Sigil: DrawRect(array, 128, 54, 24, 10, 76, color3); DrawRotatedRect(array, 128, 69, 41, 58, 9, -32f, color); DrawRotatedRect(array, 128, 67, 63, 48, 9, -32f, color); break; case StructureKind.Monument: DrawRect(array, 128, 38, 20, 52, 88, color2); DrawRect(array, 128, 56, 34, 8, 60, color); DrawRotatedRect(array, 128, 72, 48, 43, 7, -32f, color); DrawRotatedRect(array, 128, 70, 66, 35, 7, -32f, color); break; case StructureKind.Totem: DrawRect(array, 128, 59, 24, 10, 82, color3); DrawRotatedRect(array, 128, 70, 45, 55, 9, -22f, color3); DrawRotatedRect(array, 128, 68, 66, 42, 8, -22f, color3); DrawRect(array, 128, 54, 84, 20, 20, color); break; } val.SetPixels32(array); val.Apply(false, true); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 128f); ((Object)obj).name = spec.PrefabName + "_Icon"; Object.DontDestroyOnLoad((Object)(object)val); Object.DontDestroyOnLoad((Object)(object)obj); return obj; } private static void DrawRect(Color32[] pixels, int size, int x, int y, int w, int h, Color32 color) { //IL_001a: 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) for (int i = Mathf.Max(0, y); i < Mathf.Min(size, y + h); i++) { for (int j = Mathf.Max(0, x); j < Mathf.Min(size, x + w); j++) { pixels[i * size + j] = color; } } } private static void DrawRotatedRect(Color32[] pixels, int size, int cx, int cy, int w, int h, float degrees, Color32 color) { //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) float num = degrees * ((float)Math.PI / 180f); float num2 = Mathf.Cos(num); float num3 = Mathf.Sin(num); int num4 = Mathf.CeilToInt((float)Mathf.Max(w, h) * 0.75f); for (int i = Mathf.Max(0, cy - num4); i < Mathf.Min(size, cy + num4); i++) { for (int j = Mathf.Max(0, cx - num4); j < Mathf.Min(size, cx + num4); j++) { float num5 = j - cx; float num6 = i - cy; float num7 = num5 * num2 + num6 * num3; float num8 = (0f - num5) * num3 + num6 * num2; if (Mathf.Abs(num7) <= (float)w * 0.5f && Mathf.Abs(num8) <= (float)h * 0.5f) { pixels[i * size + j] = color; } } } } private static bool InEllipse(int x, int y, int cx, int cy, int rx, int ry) { float num = (float)(x - cx) / (float)rx; float num2 = (float)(y - cy) / (float)ry; return num * num + num2 * num2 <= 1f; } private static Color32 HairColorFor(string prefabName) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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 (prefabName.Contains("Blond") || prefabName.Contains("Emily")) { return new Color32((byte)238, (byte)194, (byte)83, byte.MaxValue); } if (prefabName.Contains("Red") || prefabName.Contains("Diane") || prefabName.Contains("Freya")) { return new Color32((byte)165, (byte)62, (byte)42, byte.MaxValue); } if (prefabName.Contains("Brunette") || prefabName.Contains("Martha")) { return new Color32((byte)78, (byte)45, (byte)33, byte.MaxValue); } return new Color32((byte)170, (byte)148, (byte)118, byte.MaxValue); } private static Color32 ColorFromName(string name) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) uint num = 2166136261u; foreach (char c in name) { num ^= c; num *= 16777619; } return new Color32((byte)(90 + (num & 0x7F)), (byte)(70 + ((num >> 8) & 0x7F)), (byte)(80 + ((num >> 16) & 0x7F)), byte.MaxValue); } private static Transform? FindDeepChild(Transform parent, string name) { for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (((Object)child).name == name) { return child; } Transform val = FindDeepChild(child, name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private void RegisterWithJotunn(GameObject prefab, DancerPrefabSpec spec, Sprite icon) { RequirementConfig[] requirements = (from requirement in ((IEnumerable)GetRequirements(spec.Group)).Select((Func)((RequirementSpec requirement) => new RequirementConfig(requirement.Item, ScaleAmount(requirement.Amount), 0, _recoverResources?.Value ?? requirement.Recover))) where !string.IsNullOrWhiteSpace(requirement.Item) && requirement.Amount > 0 select requirement).ToArray(); RegisterWithJotunn(prefab, spec.DisplayName, spec.Description, requirements, icon); } private void RegisterWithJotunn(GameObject prefab, string displayName, string description, RequirementSpec[] requirementSpecs, Sprite icon) { RequirementConfig[] requirements = (from requirement in ((IEnumerable)requirementSpecs).Select((Func)((RequirementSpec requirement) => new RequirementConfig(requirement.Item, ScaleAmount(requirement.Amount), 0, _recoverResources?.Value ?? requirement.Recover))) where !string.IsNullOrWhiteSpace(requirement.Item) && requirement.Amount > 0 select requirement).ToArray(); RegisterWithJotunn(prefab, displayName, description, requirements, icon); } private void RegisterWithJotunn(GameObject prefab, string displayName, string description, RequirementConfig[] requirements, Sprite icon) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_006f: 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_0080: Expected O, but got Unknown //IL_0083: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown if (requirements.Length > 4) { requirements = requirements.Take(4).ToArray(); } PieceConfig val = new PieceConfig { Name = displayName, Description = description, Enabled = true, PieceTable = CleanConfigString(_pieceTable, "Hammer"), Category = CleanConfigString(_pieceCategory, "Fehu"), CraftingStation = CleanConfigString(_requiredCraftingStation, string.Empty), Icon = icon, Requirements = requirements }; CustomPiece val2 = new CustomPiece(prefab, true, val) { PieceTable = val.PieceTable, Category = val.Category }; PieceManager.Instance.AddPiece(val2); DancerLogInfo("Prepared recipe for '" + displayName + "': " + string.Join(", ", requirements.Select((RequirementConfig requirement) => $"{requirement.Item} x{requirement.Amount}"))); } private void EnsurePieceCategory() { string text = CleanConfigString(_pieceTable, "Hammer"); string text2 = CleanConfigString(_pieceCategory, "Fehu"); object instance = PieceManager.Instance; foreach (MethodInfo item in from method in instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public) where method.Name == "AddPieceCategory" select method) { ParameterInfo[] parameters = item.GetParameters(); try { if (parameters.Length == 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string)) { item.Invoke(instance, new object[2] { text, text2 }); DancerLogInfo("Ensured Fehu hammer category '" + text2 + "' in table '" + text + "'."); return; } if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string)) { item.Invoke(instance, new object[1] { text2 }); DancerLogInfo("Ensured Fehu hammer category '" + text2 + "'."); return; } } catch (Exception ex) { Log.LogWarning((object)("Could not add Fehu category using " + item.Name + ": " + ex.Message)); } } Log.LogWarning((object)("Could not find Jotunn AddPieceCategory overload. Fehu pieces will fall back to category '" + text2 + "' only.")); } private static RequirementSpec[] GetRequirements(DancerGroup group) { return group switch { DancerGroup.Standing => new RequirementSpec[4] { Requirement(_standingItem1, _standingItem1Amount), Requirement(_standingItem2, _standingItem2Amount), Requirement(_standingItem3, _standingItem3Amount), Requirement(_standingItem4, _standingItem4Amount) }, DancerGroup.Sitting => new RequirementSpec[4] { Requirement(_sittingItem1, _sittingItem1Amount), Requirement(_sittingItem2, _sittingItem2Amount), Requirement(_sittingItem3, _sittingItem3Amount), Requirement(_sittingItem4, _sittingItem4Amount) }, DancerGroup.Laying => new RequirementSpec[4] { Requirement(_layingItem1, _layingItem1Amount), Requirement(_layingItem2, _layingItem2Amount), Requirement(_layingItem3, _layingItem3Amount), Requirement(_layingItem4, _layingItem4Amount) }, _ => Array.Empty(), }; } private static RequirementSpec Requirement(ConfigEntry? item, ConfigEntry? amount) { return new RequirementSpec(CleanConfigString(item, string.Empty), amount?.Value ?? 0, recover: true); } private static string CleanConfigString(ConfigEntry? entry, string fallback) { string text = entry?.Value?.Trim() ?? string.Empty; if (!string.IsNullOrWhiteSpace(text)) { return text; } return fallback; } } } namespace FehuAssets.Parrots { [HarmonyPatch(typeof(CharacterDrop), "Start")] internal static class CharacterDrop_Start_ParrotDrops { private static void Postfix(CharacterDrop __instance) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0076: 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_0082: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00ae: Expected O, but got Unknown if (((Object)((Component)__instance).gameObject).name.StartsWith("PR_Parrot1") && (__instance.m_drops == null || __instance.m_drops.Count <= 0)) { ZNetScene instance = ZNetScene.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.GetPrefab("Feathers") : null); if ((Object)val == (Object)null) { ParrotsPlugin.ParrotsLogger.LogWarning((object)"Feathers prefab not found in ZNetScene"); return; } __instance.m_drops = new List { new Drop { m_prefab = val, m_amountMin = 2, m_amountMax = 4, m_chance = 1f, m_onePerPlayer = false, m_levelMultiplier = true } }; ParrotsPlugin.ParrotsLogger.LogDebug((object)"Parrot drops configured: 2-4 Feathers"); } } } [HarmonyPatch(typeof(Character), "Start")] internal static class Character_Start_ParrotColors { private static readonly int ColorProp = Shader.PropertyToID("_Color"); private static readonly Color StarOneColor = new Color(0.4f, 0.85f, 0.3f, 1f); private static readonly Color StarTwoColor = new Color(0.9f, 0.15f, 0.1f, 1f); private static void Postfix(Character __instance) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)((Component)__instance).gameObject).name.StartsWith("PR_Parrot1")) { return; } int level = __instance.GetLevel(); if (level <= 1) { return; } Transform val = ((Component)__instance).transform.Find("Visual"); if ((Object)val == (Object)null) { return; } SkinnedMeshRenderer componentInChildren = ((Component)val).GetComponentInChildren(); if (!((Object)componentInChildren == (Object)null)) { MaterialPropertyBlock val2 = new MaterialPropertyBlock(); ((Renderer)componentInChildren).GetPropertyBlock(val2); if (level == 2) { val2.SetColor(ColorProp, StarOneColor); ((Renderer)componentInChildren).SetPropertyBlock(val2); ParrotsPlugin.ParrotsLogger.LogDebug((object)"1-star parrot: green variant"); } else if (level >= 3) { val2.SetColor(ColorProp, StarTwoColor); ((Renderer)componentInChildren).SetPropertyBlock(val2); ParrotsPlugin.ParrotsLogger.LogDebug((object)"2-star parrot: scarlet variant"); } } } } [HarmonyPatch(typeof(Character), "UpdateMotion")] internal static class Character_UpdateMotion_ParrotFixes { private static bool Prefix(Character __instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (ParrotFlightBehavior.IsInFollowFlight(__instance)) { ZNetView component = ((Component)__instance).GetComponent(); if ((Object)component != (Object)null && component.IsOwner()) { return false; } } return true; } } [HarmonyPatch(typeof(FejdStartup), "Awake")] internal static class FejdStartup_Awake_DeferredLocalizations { private static void Postfix() { if (ParrotsPlugin.s_localizationsRegistered) { return; } try { ParrotsPlugin.RegisterLocalizations(); } catch (Exception ex) { ParrotsPlugin.ParrotsLogger.LogError((object)("Deferred RegisterLocalizations() failed: " + ex.Message)); } } } [HarmonyPatch(typeof(Humanoid), "Awake")] internal static class Humanoid_Awake_ParrotFaction { private static void Postfix(Humanoid __instance) { //IL_001c: 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_003e: Expected O, but got Unknown if (((Object)((Component)__instance).gameObject).name.StartsWith("PR_Parrot1")) { ((Character)__instance).m_faction = (Faction)1; __instance.m_defaultItems = Array.Empty(); ZNetScene instance = ZNetScene.instance; if (!((Object)instance == (Object)null)) { GameObject prefab = instance.GetPrefab("PR_SFX_Hit"); GameObject val = instance.GetPrefab("vfx_HitSparks") ?? instance.GetPrefab("vfx_clubhit"); ((Character)__instance).m_hitEffects = MakeEffects(prefab, val); GameObject prefab2 = instance.GetPrefab("PR_SFX_Death"); GameObject prefab3 = instance.GetPrefab("Boar"); GameObject val2 = FindVisualEffect(((Object)(object)prefab3 == (Object)null) ? null : ((Character)(prefab3.GetComponent()?)).m_deathEffects); ((Character)__instance).m_deathEffects = MakeEffects(prefab2, val2); ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "Parrot VFX: hit=" + ((((Object)(object)val != (Object)null) ? ((Object)val).name : null) ?? "none") + ", death=" + ((((Object)(object)val2 != (Object)null) ? ((Object)val2).name : null) ?? "none")); } } } private static GameObject FindVisualEffect(EffectList effects) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown if (effects?.m_effectPrefabs == null) { return null; } EffectData[] effectPrefabs = effects.m_effectPrefabs; foreach (EffectData val in effectPrefabs) { if (!((Object)val.m_prefab == (Object)null) && (Object)val.m_prefab.GetComponent() == (Object)null) { return val.m_prefab; } } return null; } private static EffectList MakeEffects(params GameObject[] prefabs) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0041: 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_0053: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown List list = new List(); foreach (GameObject val in prefabs) { if ((Object)val != (Object)null) { list.Add(new EffectData { m_prefab = val, m_enabled = true }); } } return new EffectList { m_effectPrefabs = list.ToArray() }; } } [HarmonyPatch(typeof(ItemDrop), "Awake")] internal static class ItemDrop_Awake_ParrotEgg { private static void Postfix(ItemDrop __instance) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (ParrotRegistry.IsParrotEggItem(__instance.m_itemData) && (Object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } [HarmonyPatch(typeof(ItemDrop), "GetHoverText")] internal static class ItemDrop_GetHoverText_EggProgress { private static void Postfix(ItemDrop __instance, ref string __result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!ParrotRegistry.IsParrotEggItem(__instance.m_itemData)) { return; } ZNetView component = ((Component)__instance).GetComponent(); if (!((Object)component == (Object)null) && component.IsValid()) { float num = component.GetZDO().GetFloat("PR_HatchTimer", 0f); float hatchTime = ParrotEggHatch.HatchTime; if (num >= 0f) { float num2 = Mathf.Clamp01(num / hatchTime) * 100f; string arg = Localization.instance.Localize("$parrot_hatching"); __result += $"\n{arg}: {num2:F0}%"; } } } } [HarmonyPatch(typeof(MonsterAI), "Awake")] internal static class MonsterAI_Awake_ParrotSetup { private static void Postfix(MonsterAI __instance) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (((Object)((Component)__instance).gameObject).name.StartsWith("PR_Parrot1")) { SetupParrotAI(__instance); SetupParrotCharacter(__instance); FixAnimatorController(__instance); if ((Object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } private static void FixAnimatorController(MonsterAI ai) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown Transform val = ((Component)ai).transform.Find("Visual"); if ((Object)val == (Object)null) { return; } Animator component = ((Component)val).GetComponent(); if (!((Object)component == (Object)null)) { if ((Object)component.runtimeAnimatorController == (Object)null && (Object)ParrotsPlugin.CachedAnimatorController != (Object)null) { component.runtimeAnimatorController = ParrotsPlugin.CachedAnimatorController; ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotPatches] Fixed missing AnimatorController: assigned '" + ((Object)ParrotsPlugin.CachedAnimatorController).name + "' " + $"({ParrotsPlugin.CachedAnimatorController.animationClips.Length} clips)"); } else if ((Object)component.runtimeAnimatorController == (Object)null) { ParrotsPlugin.ParrotsLogger.LogWarning((object)"[ParrotPatches] Animator has no controller AND no cached controller available!"); } } } private static void SetupParrotAI(MonsterAI ai) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown ai.m_consumeRange = 2f; ai.m_consumeSearchInterval = 2f; ai.m_enableHuntPlayer = false; ai.m_attackPlayerObjects = false; ai.m_interceptTimeMax = 0f; ai.m_interceptTimeMin = 0f; ai.m_maxChaseDistance = 1f; ai.m_fleeIfNotAlerted = true; ai.m_fleeIfLowHealth = 1f; ((BaseAI)ai).m_viewRange = 10f; ((BaseAI)ai).m_viewAngle = 90f; ((BaseAI)ai).m_hearRange = 6f; ai.m_alertRange = 5f; ZNetScene instance = ZNetScene.instance; if ((Object)instance != (Object)null) { GameObject prefab = instance.GetPrefab("PR_SFX_Chirp"); if ((Object)prefab != (Object)null) { EffectList val = new EffectList(); val.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = prefab, m_enabled = true } }; ((BaseAI)ai).m_idleSound = val; ((BaseAI)ai).m_idleSoundInterval = 8f; ((BaseAI)ai).m_idleSoundChance = 0.5f; ParrotsPlugin.ParrotsLogger.LogDebug((object)"Parrot SFX: idle chirp wired (every 8s, 50% chance)"); } GameObject prefab2 = instance.GetPrefab("PR_SFX_Squawk"); if ((Object)prefab2 != (Object)null) { EffectList val2 = new EffectList(); val2.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = prefab2, m_enabled = true } }; ((BaseAI)ai).m_alertedEffects = val2; ParrotsPlugin.ParrotsLogger.LogDebug((object)"Parrot SFX: alerted squawk wired"); } } ParrotsPlugin.ParrotsLogger.LogDebug((object)"Parrot AI configured: randomFly=true, range=60, airDuration=45, altitude=prefab(5/15/3), consumeSearchInterval=2, fleeIfNotAlerted=true, viewRange=10"); } private static void SetupParrotCharacter(MonsterAI ai) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown Character component = ((Component)ai).GetComponent(); if (!((Object)component == (Object)null)) { ParrotsPlugin.ParrotsLogger.LogDebug((object)$"Parrot Character: keeping prefab fly speeds (slow={component.m_flySlowSpeed}, fast={component.m_flyFastSpeed}, turn={component.m_flyTurnSpeed}, accel={component.m_acceleration})"); } } } [HarmonyPatch(typeof(MonsterAI), "FindClosestConsumableItem")] internal static class MonsterAI_FindClosestConsumableItem_ParrotFix { private static bool Prefix(MonsterAI __instance, float maxRange, ref ItemDrop __result) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)((Component)__instance).gameObject).name.StartsWith("PR_Parrot1")) { return true; } Character component = ((Component)__instance).GetComponent(); if ((Object)component != (Object)null && component.m_flying) { __result = null; return false; } int mask = LayerMask.GetMask(new string[1] { "item" }); Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, maxRange, mask); ItemDrop val = null; float num = 999999f; Collider[] array2 = array; foreach (Collider val2 in array2) { if ((Object)val2.attachedRigidbody == (Object)null) { continue; } ItemDrop component2 = ((Component)val2.attachedRigidbody).GetComponent(); if ((Object)component2 == (Object)null) { continue; } ZNetView component3 = ((Component)component2).GetComponent(); if ((Object)component3 == (Object)null || !component3.IsValid()) { continue; } bool flag = false; foreach (ItemDrop consumeItem in __instance.m_consumeItems) { if ((Object)consumeItem != (Object)null && component2.m_itemData.m_shared.m_name == consumeItem.m_itemData.m_shared.m_name) { flag = true; break; } } if (flag) { float num2 = Vector3.Distance(((Component)component2).transform.position, ((Component)__instance).transform.position); if (num2 < num) { val = component2; num = num2; } } } __result = val; return false; } } public sealed class ParrotAssetLoader { private readonly ManualLogSource _log; private AssetBundle? _bundle; public ParrotAssetLoader(ManualLogSource log) { _log = log; } public AssetBundle LoadBundle() { if ((Object)(object)_bundle != (Object)null) { return _bundle; } Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("FehuAssets.Parrots.Resources.mar_parrots"); if (stream == null) { string text = string.Join(", ", executingAssembly.GetManifestResourceNames()); throw new InvalidOperationException("Embedded Parrots AssetBundle resource 'FehuAssets.Parrots.Resources.mar_parrots' was not found. Available resources: " + text); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); _bundle = AssetBundle.LoadFromMemory(memoryStream.ToArray()); if ((Object)(object)_bundle == (Object)null) { throw new InvalidOperationException("Unity failed to load embedded Parrots AssetBundle."); } ParrotDebugLog.Info(_log, "[FehuParrots] Loaded embedded AssetBundle 'mar_parrots' resource='FehuAssets.Parrots.Resources.mar_parrots'."); return _bundle; } public GameObject LoadPrefab(string prefabName) { AssetBundle val = LoadBundle(); GameObject obj = val.LoadAsset(prefabName); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException(string.Concat(str3: string.Join(", ", from name in val.GetAllAssetNames() where name.IndexOf(prefabName, StringComparison.OrdinalIgnoreCase) >= 0 select name), str0: "Parrots prefab '", str1: prefabName, str2: "' was not found in 'mar_parrots'. Matching assets: ")); } return obj; } public T? LoadAsset(string assetName) where T : Object { return LoadBundle().LoadAsset(assetName); } public void LogBundleInventory() { AssetBundle val = LoadBundle(); string[] allAssetNames = val.GetAllAssetNames(); foreach (string text in allAssetNames) { ParrotDebugLog.Info(_log, "[FehuParrots] Bundle asset: " + text); } LogTypedAssets(val, "prefabs/gameobjects"); LogTypedAssets(val, "meshes"); LogTypedAssets(val, "textures"); LogTypedAssets(val, "materials"); LogTypedAssets(val, "icons/sprites"); LogTypedAssets(val, "animations"); LogTypedAssets(val, "audio"); } private void LogTypedAssets(AssetBundle bundle, string label) where T : Object { T[] array = bundle.LoadAllAssets(); string arg = ((array.Length == 0) ? "" : string.Join(", ", array.Select((T asset) => (!((Object)(object)asset != (Object)null)) ? "" : ((Object)asset).name))); ParrotDebugLog.Info(_log, $"[FehuParrots] {label}: count={array.Length} names={arg}"); } } public static class ParrotAssets { public const string BundleName = "mar_parrots"; public const string BundleResourceName = "FehuAssets.Parrots.Resources.mar_parrots"; public static readonly string[] Phase1RegisteredPrefabs = new string[2] { "PR_Parrot1", "PR_ParrotEgg" }; public static readonly string[] Phase2BackendPrefabs = new string[6] { "PR_SFX_Squawk", "PR_SFX_Chirp", "PR_SFX_Death", "PR_SFX_Hit", "PR_SFX_Whistle", "PR_Parrot1_Rag" }; } internal static class ParrotBreedingAudit { private static readonly HashSet LoggedParrots = new HashSet(); internal static void LogConfig(ManualLogSource log, ParrotConfig config) { ParrotDebugLog.Info(log, "[FehuParrots][BreedingAudit] BreedingEnabled=" + (ParrotsPlugin.BreedingEnabled?.Value.ToString() ?? "NULL") + " " + $"EnableParrotBreeding={config.EnableParrotBreeding.Value} " + "MaxParrotsNearby=" + (ParrotsPlugin.MaxParrotsNearby?.Value.ToString() ?? "NULL") + " PregnancyDuration=" + (ParrotsPlugin.PregnancyDuration?.Value.ToString() ?? "NULL") + " FoodList=" + string.Join(",", ParrotsPlugin.FoodItemNames)); LogFoodResolution(log); } internal static void LogParrot(Tameable tameable) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if ((Object)tameable == (Object)null) { return; } GameObject gameObject = ((Component)tameable).gameObject; if ((Object)gameObject == (Object)null || !((Object)gameObject).name.StartsWith("PR_Parrot1", StringComparison.Ordinal)) { return; } int instanceID = ((Object)gameObject).GetInstanceID(); if (LoggedParrots.Add(instanceID)) { ManualLogSource parrotsLogger = ParrotsPlugin.ParrotsLogger; Character component = gameObject.GetComponent(); Humanoid component2 = gameObject.GetComponent(); MonsterAI component3 = gameObject.GetComponent(); Procreation component4 = gameObject.GetComponent(); bool flag = false; bool flag2 = false; int num = 0; try { flag = (Object)(object)component != (Object)null && component.IsTamed(); num = (((Object)(object)component != (Object)null) ? component.GetLevel() : 0); } catch (Exception ex) { parrotsLogger.LogWarning((object)("[FehuParrots][BreedingAudit] Character state read failed name=" + ((Object)gameObject).name + " error=" + ex.Message)); } try { flag2 = !tameable.IsHungry(); } catch (Exception ex2) { parrotsLogger.LogWarning((object)("[FehuParrots][BreedingAudit] Tameable fed state read failed name=" + ((Object)gameObject).name + " error=" + ex2.Message)); } ParrotDebugLog.Info(parrotsLogger, "[FehuParrots][BreedingAudit] " + $"name={((Object)gameObject).name} level={num} tamed={flag} fed={flag2} " + $"hasTameable={true} hasProcreation={(Object)(object)component4 != (Object)null} hasMonsterAI={(Object)(object)component3 != (Object)null} " + $"hasHumanoid={(Object)(object)component2 != (Object)null} hasCharacter={(Object)(object)component != (Object)null}"); if ((Object)(object)component4 == (Object)null) { string text = ((ParrotsPlugin.BreedingEnabled == null) ? "BreedingEnabled config entry is NULL" : ((!ParrotsPlugin.BreedingEnabled.Value) ? "BreedingEnabled=false at Tameable.Awake" : "BreedingEnabled=true but Procreation was not added")); parrotsLogger.LogWarning((object)("[FehuParrots][BreedingAudit] hasProcreation=false reason=" + text)); return; } string arg = (((Object)(object)component4.m_offspring != (Object)null) ? ((Object)component4.m_offspring).name : "NULL"); ParrotDebugLog.Info(parrotsLogger, "[FehuParrots][BreedingAudit] " + $"Procreation m_offspring={arg} m_maxCreatures={component4.m_maxCreatures} " + $"m_totalCheckRange={component4.m_totalCheckRange} m_partnerCheckRange={component4.m_partnerCheckRange} " + $"m_pregnancyChance={component4.m_pregnancyChance} m_pregnancyDuration={component4.m_pregnancyDuration} " + $"m_requiredLovePoints={component4.m_requiredLovePoints} m_updateInterval={component4.m_updateInterval}"); LogPartnerDetection(parrotsLogger, gameObject, component, tameable, component4); } } private static void LogFoodResolution(ManualLogSource log) { ObjectDB instance = ObjectDB.instance; string[] foodItemNames = ParrotsPlugin.FoodItemNames; foreach (string text in foodItemNames) { bool flag = (Object)(object)instance != (Object)null && (Object)(object)instance.GetItemPrefab(text) != (Object)null; ParrotDebugLog.Info(log, $"[FehuParrots][BreedingAudit] food={text} prefabExists={flag}"); } } private static void LogPartnerDetection(ManualLogSource log, GameObject go, Character character, Tameable tameable, Procreation procreation) { //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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_007c: 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) Vector3 position = go.transform.position; int num = 0; int num2 = 0; bool flag = false; string arg = "none"; foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null) { continue; } GameObject gameObject = ((Component)allCharacter).gameObject; if ((Object)gameObject == (Object)null || (Object)(object)gameObject == (Object)(object)go || !((Object)gameObject).name.StartsWith("PR_Parrot1", StringComparison.Ordinal)) { continue; } float num3 = Vector3.Distance(position, gameObject.transform.position); if (num3 <= procreation.m_totalCheckRange) { num2++; } if (num3 <= procreation.m_partnerCheckRange) { num++; Tameable component = gameObject.GetComponent(); bool flag2 = false; bool flag3 = false; try { flag2 = allCharacter.IsTamed(); flag3 = (Object)(object)component != (Object)null && !component.IsHungry(); } catch { } if (flag2 && flag3) { flag = true; } } } bool flag4 = (Object)(object)character != (Object)null && SafeIsTamed(character); bool flag5 = SafeIsFed(tameable); if (ParrotsPlugin.BreedingEnabled == null || !ParrotsPlugin.BreedingEnabled.Value) { arg = "config disabled"; } else if ((Object)(object)procreation == (Object)null) { arg = "no Procreation"; } else if ((Object)(object)procreation.m_offspring == (Object)null) { arg = "no offspring prefab"; } else if (!flag4) { arg = "not tamed"; } else if (!flag5) { arg = "not fed"; } else if (num2 >= procreation.m_maxCreatures) { arg = "too many nearby"; } else if (!flag) { arg = "partner not found/fed/tamed/in range"; } ParrotDebugLog.Info(log, "[FehuParrots][BreedingAudit] " + $"name={((Object)go).name} nearbyPartnerRange={num} nearbyTotalRange={num2} " + $"partnerFound={flag} blockedReason={arg}"); } private static bool SafeIsTamed(Character character) { try { return (Object)(object)character != (Object)null && character.IsTamed(); } catch { return false; } } private static bool SafeIsFed(Tameable tameable) { try { return (Object)(object)tameable != (Object)null && !tameable.IsHungry(); } catch { return false; } } } internal sealed class Localization { internal static readonly Localization instance = new Localization(); internal string Localize(string key) { string result; switch (key) { case "$parrot_dismount": return "Return to Flight"; case "$parrot_call_down": return "Call Down"; case "$parrot_hold": return "Hold"; case "$parrot_shoulder": return "Perch on Shoulder"; case "$parrot_hatching": return "Hatching"; case "$item_parrotegg": return "Parrot Egg"; case "$enemy_parrot1": return "Macaw"; default: if (key.StartsWith("$")) { result = key.Substring(1); break; } goto case null; case null: result = key; break; } return result; } } internal static class ParrotCompat { private static readonly MethodInfo TameMethod = typeof(Tameable).GetMethod("Tame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); private static readonly MethodInfo GetTamenessMethod = typeof(Tameable).GetMethod("GetTameness", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); private static readonly MethodInfo SetFollowTargetMethod = typeof(MonsterAI).GetMethod("SetFollowTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(GameObject) }, null); private static readonly FieldInfo FollowField = typeof(MonsterAI).GetField("m_follow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static void TameSafe(Tameable tameable) { TameMethod?.Invoke(tameable, null); } internal static float GetTamenessSafe(Tameable tameable) { if ((Object)(object)tameable == (Object)null || GetTamenessMethod == null) { return 0f; } object obj = GetTamenessMethod.Invoke(tameable, null); if (obj is float) { return (float)obj; } return 0f; } internal static void SetFollowTargetSafe(MonsterAI ai, GameObject target) { if (!((Object)(object)ai == (Object)null)) { if (SetFollowTargetMethod != null) { SetFollowTargetMethod.Invoke(ai, new object[1] { target }); } else { FollowField?.SetValue(ai, target); } } } internal static GameObject GetFollowTargetSafe(MonsterAI ai) { if ((Object)(object)ai == (Object)null || FollowField == null) { return null; } object? value = FollowField.GetValue(ai); return (GameObject)((value is GameObject) ? value : null); } } internal static class ParrotStringExtensions { internal static int GetStableHashCode(this string text) { int num = 5381; if (text == null) { return num; } foreach (char c in text) { num = ((num << 5) + num) ^ c; } return num; } } public sealed class ParrotConfig { public ConfigEntry EnableParrots { get; } public ConfigEntry EnableParrotEgg { get; } public ConfigEntry EnableParrotGameplay { get; } public ConfigEntry EnableParrotEggHatching { get; } public ConfigEntry EnableParrotTaming { get; } public ConfigEntry EnableParrotBreeding { get; } public ConfigEntry EnableShoulderParrot { get; } public ConfigEntry EnableParrotWorldSpawns { get; } public ConfigEntry EggHatchSeconds { get; } public ConfigEntry ParrotTamingTime { get; } public ConfigEntry AllowedParrotFoods { get; } public ConfigEntry ShoulderHotkey { get; } public ConfigEntry ParrotFollowHotkey { get; } public ConfigEntry ParrotGroundVisualYOffset { get; } public ConfigEntry ParrotShoulderOffsetX { get; } public ConfigEntry ParrotShoulderOffsetY { get; } public ConfigEntry ParrotShoulderOffsetZ { get; } public ConfigEntry ParrotShoulderRotX { get; } public ConfigEntry ParrotShoulderRotY { get; } public ConfigEntry ParrotShoulderRotZ { get; } public ConfigEntry ParrotReturnDistance { get; } public ConfigEntry ParrotTeleportDistance { get; } public ConfigEntry EnableParrotDebugLogs { get; } public ParrotConfig(ConfigFile config) { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Expected O, but got Unknown //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Expected O, but got Unknown //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Expected O, but got Unknown //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Expected O, but got Unknown //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Expected O, but got Unknown EnableParrots = config.Bind("Parrots", "EnableParrots", true, "Register Fehu Parrots prefabs."); EnableParrotEgg = config.Bind("Parrots", "EnableParrotEgg", true, "Register PR_ParrotEgg as a safe ItemDrop."); EnableParrotGameplay = config.Bind("Parrots", "EnableParrotGameplay", true, "Enable live PR_Parrot1 gameplay systems."); EnableParrotEggHatching = config.Bind("Parrots", "EnableParrotEggHatching", true, "Allow dropped PR_ParrotEgg items to hatch. When gameplay is disabled, hatching uses a safe visual PR_Parrot1 placeholder."); EnableParrotTaming = config.Bind("Parrots", "EnableParrotTaming", true, "Enable safe Fehu parrot taming. Vanilla Tameable is only used when live gameplay is enabled and stable."); EnableParrotBreeding = config.Bind("Parrots", "EnableParrotBreeding", true, "Enable vanilla Procreation breeding for tamed parrots when fed and near a partner."); EnableShoulderParrot = config.Bind("Parrots", "EnableShoulderParrot", true, "Enable tamed parrot shoulder perch using the ShoulderHotkey."); EnableParrotWorldSpawns = config.Bind("Parrots", "EnableParrotWorldSpawns", false, "Phase 3 placeholder. World spawning is intentionally not implemented in Phase 2."); EggHatchSeconds = config.Bind("Parrots", "EggHatchSeconds", 120f, new ConfigDescription("Seconds a dropped PR_ParrotEgg must rest before hatching.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 3600f), Array.Empty())); ParrotTamingTime = config.Bind("Parrots", "ParrotTamingTime", 120f, new ConfigDescription("Seconds required for Fehu parrot tame progress.", (AcceptableValueBase)(object)new AcceptableValueRange(30f, 3600f), Array.Empty())); AllowedParrotFoods = config.Bind("Parrots", "AllowedParrotFoods", "Blueberries,Raspberry,Carrot,Turnip", "Comma-separated internal prefab names accepted by parrots as taming food."); ShoulderHotkey = config.Bind("Parrots", "ShoulderHotkey", "G", "Keyboard key used to perch/release your tamed parrot."); ParrotFollowHotkey = config.Bind("Parrots", "ParrotFollowHotkey", "H", "Keyboard key used to toggle Follow/Stay for your tamed parrot."); ParrotGroundVisualYOffset = config.Bind("Parrots", "ParrotGroundVisualYOffset", 0.18f, new ConfigDescription("Visual-only Y offset applied to the PR_Parrot1 Visual child while not perched.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); ParrotShoulderOffsetX = config.Bind("Parrots", "ParrotShoulderOffsetX", 0.18f, new ConfigDescription("Local shoulder X offset for perched parrots.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); ParrotShoulderOffsetY = config.Bind("Parrots", "ParrotShoulderOffsetY", 0.18f, new ConfigDescription("Local shoulder Y offset for perched parrots.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); ParrotShoulderOffsetZ = config.Bind("Parrots", "ParrotShoulderOffsetZ", -0.08f, new ConfigDescription("Local shoulder Z offset for perched parrots.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); ParrotShoulderRotX = config.Bind("Parrots", "ParrotShoulderRotX", 0f, new ConfigDescription("Local shoulder X rotation for perched parrots.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty())); ParrotShoulderRotY = config.Bind("Parrots", "ParrotShoulderRotY", 85f, new ConfigDescription("Local shoulder Y rotation for perched parrots.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty())); ParrotShoulderRotZ = config.Bind("Parrots", "ParrotShoulderRotZ", -8f, new ConfigDescription("Local shoulder Z rotation for perched parrots.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty())); ParrotReturnDistance = config.Bind("Parrots", "ParrotReturnDistance", 25f, new ConfigDescription("Distance where an owned parrot forcefully resumes follow/catch-up.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 200f), Array.Empty())); ParrotTeleportDistance = config.Bind("Parrots", "ParrotTeleportDistance", 100f, new ConfigDescription("Distance where an owned parrot teleports safely near its owner.", (AcceptableValueBase)(object)new AcceptableValueRange(20f, 500f), Array.Empty())); EnableParrotDebugLogs = config.Bind("Parrots", "EnableParrotDebugLogs", false, "Enable verbose Fehu parrot diagnostics."); EnableShoulderParrot.Value = true; EnableParrotWorldSpawns.Value = false; EnableParrotGameplay.Value = true; EnableParrotEggHatching.Value = true; EnableParrotTaming.Value = true; } public string[] FoodPrefabs() { return (from food in (AllowedParrotFoods.Value ?? string.Empty).Split(new char[1] { ',' }) select food.Trim() into food where !string.IsNullOrWhiteSpace(food) select food).ToArray(); } public void LogAndMigrate(ManualLogSource log) { bool flag = false; if (EggHatchSeconds.Value == 300f) { EggHatchSeconds.Value = 120f; flag = true; ParrotDebugLog.Info(log, "[FehuParrots] Migrated old default EggHatchSeconds=300 to new default 120."); } if (ParrotTamingTime.Value == 600f || ParrotTamingTime.Value == 300f) { float value = ParrotTamingTime.Value; ParrotTamingTime.Value = 120f; flag = true; ParrotDebugLog.Info(log, $"[FehuParrots] Migrated old default ParrotTamingTime={value} to new default 120."); } if (flag) { ParrotDebugLog.Info(log, "[FehuParrots] Old Parrots config defaults were updated once. If you want custom timings, edit the config file after this launch."); } if (EnableParrotDebugLogs.Value) { ParrotDebugLog.Info(log, $"[FehuParrots] Config EggHatchSeconds={EggHatchSeconds.Value} ParrotTamingTime={ParrotTamingTime.Value}"); ParrotDebugLog.Info(log, $"[FehuParrots] Using config value EggHatchSeconds={EggHatchSeconds.Value} from config file."); ParrotDebugLog.Info(log, $"[FehuParrots] Using ParrotTamingTime={ParrotTamingTime.Value}"); } } } internal static class ParrotDebugLog { public static bool Enabled => ParrotRuntimeUtil.Config?.EnableParrotDebugLogs.Value ?? false; public static void Info(ManualLogSource? log, object message) { if (Enabled && log != null) { log.LogInfo(message); } } public static void Unity(object message) { if (Enabled) { Debug.Log(message); } } } public class ParrotEggHatch : MonoBehaviour { internal const string ZdoKey = "PR_HatchTimer"; private ZNetView m_nview; private ItemDrop m_itemDrop; private float m_updateTimer; internal static float HatchTime => ParrotsPlugin.HatchTime?.Value ?? 120f; private void Awake() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown m_nview = ((Component)this).GetComponent(); m_itemDrop = ((Component)this).GetComponent(); if ((Object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.GetZDO().Set("PR_HatchTimer", m_nview.GetZDO().GetFloat("PR_HatchTimer", 0f)); } } private void FixedUpdate() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown if ((Object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner()) { return; } ItemDrop itemDrop = m_itemDrop; Rigidbody val = (((Object)(object)itemDrop != (Object)null) ? ((Component)itemDrop).GetComponent() : null); if ((Object)val == (Object)null || !val.IsSleeping()) { return; } m_updateTimer += Time.fixedDeltaTime; if (!(m_updateTimer < 1f)) { m_updateTimer = 0f; float num = m_nview.GetZDO().GetFloat("PR_HatchTimer", 0f); num += 1f; m_nview.GetZDO().Set("PR_HatchTimer", num); if (num >= HatchTime) { Hatch(); } } } private unsafe void Hatch() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0087: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "Parrot egg hatching!"); Vector3 position = ((Component)this).transform.position; ZNetScene instance = ZNetScene.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.GetPrefab("vfx_spawn") : null); if ((Object)val != (Object)null) { Object.Instantiate(val, position, Quaternion.identity); } ZNetScene instance2 = ZNetScene.instance; GameObject val2 = (((Object)(object)instance2 != (Object)null) ? instance2.GetPrefab("PR_Parrot1") : null); if ((Object)val2 != (Object)null) { Tameable component = Object.Instantiate(val2, position + Vector3.up * 0.5f, Quaternion.identity).GetComponent(); if ((Object)component != (Object)null) { ParrotCompat.TameSafe(component); Player closestPlayer = Player.GetClosestPlayer(position, 30f); if ((Object)closestPlayer != (Object)null) { component.Command((Humanoid)closestPlayer, false); } } ManualLogSource parrotsLogger = ParrotsPlugin.ParrotsLogger; Vector3 val3 = position; ParrotDebugLog.Info(parrotsLogger, "Blue-and-Yellow Macaw hatched (tamed) at " + ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString()); } else { ParrotsPlugin.ParrotsLogger.LogError((object)"PR_Parrot1 prefab not found in ZNetScene!"); } if (m_nview.IsOwner()) { m_nview.Destroy(); } } } public class ParrotFlightBehavior : MonoBehaviour { private enum FollowFlightState { Grounded, Approaching, Orbiting, Landing } private static readonly HashSet s_followFlightCharacters = new HashSet(); private const string ZDO_FLIGHT_MODE = "PR_flightMode"; private Character m_character; private MonsterAI m_monsterAI; private Rigidbody m_body; private Animator m_animator; private ZNetView m_nview; private float m_debugLogTimer; private const float DebugLogInterval = 5f; private float m_lastActualSpeed; private float m_smoothNormalizedSpeed; private float m_smoothTurnSpeed; private float m_smoothAnimSpeed = 1f; private float m_maxFlightSpeed = 8.75f; private bool m_flightSuppressed; private float m_flightSuppressionCheckTimer; private const float FlightSuppressionCheckInterval = 1f; private bool m_tamedSettingsApplied; private FollowFlightState m_followState; private bool m_isInFollowFlight; private RigidbodyInterpolation m_savedInterpolation; private float m_followFlightTimer; private float m_orbitAngle; private float m_playerStillTimer; private float m_landingSpiral; private bool m_summonedLanding; private bool m_nonOwnerFollowFlight; private const float OrbitRadius = 6f; private const float OrbitSpeed = 0.9f; private const float OrbitAltitudeBase = 7f; private const float OrbitAltitudeRipple = 1f; private const float OrbitAltitudeSweep = 2.5f; private const float OrbitAltitudeSweepSpeed = 0.18f; private const float PlayerStillThreshold = 12f; private const float LandingSpiralDuration = 4f; private const float PhysicsTurnFactor = 5f; private Vector3 m_prevForward; private float m_swoopTimer; private float m_swoopPhase; private const float SwoopInterval = 18f; private const float SwoopDuration = 4f; private const float SwoopDepth = 4f; private float m_consumeFixTimer = 5f; private bool m_consumeItemsFixed; private float m_followFlightDiagTimer; private static string[] RequiredFoodItems => ParrotsPlugin.FoodItemNames; public static bool IsInFollowFlight(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)character != (Object)null) { return s_followFlightCharacters.Contains(character); } return false; } private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Expected O, but got Unknown //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Expected O, but got Unknown //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Expected O, but got Unknown //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Expected O, but got Unknown //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Expected O, but got Unknown CacheReferences(); if ((Object)m_nview != (Object)null) { m_nview.Register("RPC_CommandLand", (Action)RPC_CommandLand); m_nview.Register("RPC_CommandTakeoff", (Action)RPC_CommandTakeoff); m_nview.Register("RPC_PlayWhistleSFX", (Action)RPC_PlayWhistleSFX); } if ((Object)m_animator != (Object)null) { m_animator.SetFloat("anim_speed", 1f); } if ((Object)m_animator != (Object)null) { RuntimeAnimatorController runtimeAnimatorController = m_animator.runtimeAnimatorController; ParrotsPlugin.ParrotsLogger.LogDebug((object)("[ParrotFlight] Animator DIAG: " + $"enabled={((Behaviour)m_animator).enabled}, " + "controller=" + (((Object)runtimeAnimatorController != (Object)null) ? ((Object)runtimeAnimatorController).name : "NULL") + ", " + $"paramCount={m_animator.parameterCount}, " + $"layerCount={m_animator.layerCount}, " + $"isHuman={m_animator.isHuman}, " + $"hasAvatar={(Object)m_animator.avatar != (Object)null}, " + "avatarName=" + (((Object)m_animator.avatar != (Object)null) ? ((Object)m_animator.avatar).name : "NULL") + ", " + $"clipCount={(((Object)runtimeAnimatorController != (Object)null) ? runtimeAnimatorController.animationClips.Length : 0)}")); if ((Object)runtimeAnimatorController != (Object)null && runtimeAnimatorController.animationClips.Length != 0) { AnimationClip[] animationClips = runtimeAnimatorController.animationClips; foreach (AnimationClip val in animationClips) { ParrotsPlugin.ParrotsLogger.LogDebug((object)("[ParrotFlight] Clip: " + (((Object)val != (Object)null) ? ((Object)val).name : "NULL") + " " + $"length={(((Object)val != (Object)null) ? val.length : 0f):F2}s loop={(Object)val != (Object)null && ((Motion)val).isLooping}")); } } else { ParrotsPlugin.ParrotsLogger.LogWarning((object)"[ParrotFlight] Animator has NO controller or NO clips!"); } AnimatorStateInfo currentAnimatorStateInfo = m_animator.GetCurrentAnimatorStateInfo(0); ParrotsPlugin.ParrotsLogger.LogDebug((object)("[ParrotFlight] Animator state: " + $"hash={((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash}, length={((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length:F2}, " + $"normalizedTime={((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime:F2}, speed={((AnimatorStateInfo)(ref currentAnimatorStateInfo)).speed:F2}")); } else { ParrotsPlugin.ParrotsLogger.LogWarning((object)"[ParrotFlight] NO Animator found on Visual child!"); } ParrotsPlugin.ParrotsLogger.LogDebug((object)("[ParrotFlight] Awake on " + ((Object)((Component)this).gameObject).name + " - " + $"character={(Object)m_character != (Object)null}, monsterAI={(Object)m_monsterAI != (Object)null}, " + $"body={(Object)m_body != (Object)null}, animator={(Object)m_animator != (Object)null}")); } private void OnEnable() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if ((Object)m_character == (Object)null) { CacheReferences(); } m_smoothNormalizedSpeed = 0f; } private void OnDisable() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown if ((Object)m_character != (Object)null) { s_followFlightCharacters.Remove(m_character); } if (m_isInFollowFlight && (Object)m_monsterAI != (Object)null) { m_isInFollowFlight = false; ((Behaviour)m_monsterAI).enabled = true; } if (m_nonOwnerFollowFlight) { m_nonOwnerFollowFlight = false; if ((Object)m_monsterAI != (Object)null) { ((Behaviour)m_monsterAI).enabled = true; } if ((Object)m_body != (Object)null) { m_body.useGravity = true; } } } private void CacheReferences() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown m_character = ((Component)this).GetComponent(); m_monsterAI = ((Component)this).GetComponent(); m_body = ((Component)this).GetComponent(); m_nview = ((Component)this).GetComponent(); Transform val = ((Component)this).transform.Find("Visual"); if ((Object)val != (Object)null) { m_animator = ((Component)val).GetComponent(); } if ((Object)m_character != (Object)null && m_character.m_flySlowSpeed > 0f) { m_maxFlightSpeed = Mathf.Lerp(m_character.m_flySlowSpeed, m_character.m_flyFastSpeed, 0.25f); } } private void TryFixConsumeItems() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Expected O, but got Unknown //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Expected O, but got Unknown if (m_consumeItemsFixed) { return; } m_consumeFixTimer -= Time.deltaTime; if (m_consumeFixTimer > 0f) { return; } m_consumeItemsFixed = true; if ((Object)m_monsterAI == (Object)null) { return; } ObjectDB instance = ObjectDB.instance; if ((Object)instance == (Object)null) { ParrotsPlugin.ParrotsLogger.LogError((object)"[ParrotFlight] ObjectDB not available yet!"); m_consumeItemsFixed = false; m_consumeFixTimer = 3f; return; } if (m_monsterAI.m_consumeItems == null) { m_monsterAI.m_consumeItems = new List(); } string text = ""; foreach (ItemDrop consumeItem in m_monsterAI.m_consumeItems) { text = text + (((Object)consumeItem != (Object)null) ? ((Object)consumeItem).name : "null") + ", "; } ParrotsPlugin.ParrotsLogger.LogDebug((object)$"[ParrotFlight] ConsumeItems before fix ({m_monsterAI.m_consumeItems.Count}): [{text}]"); HashSet hashSet = new HashSet(); foreach (ItemDrop consumeItem2 in m_monsterAI.m_consumeItems) { if ((Object)consumeItem2 != (Object)null) { hashSet.Add(((Object)consumeItem2).name); } } int num = 0; string[] requiredFoodItems = RequiredFoodItems; foreach (string text2 in requiredFoodItems) { if (hashSet.Contains(text2)) { continue; } GameObject itemPrefab = instance.GetItemPrefab(text2); if ((Object)itemPrefab == (Object)null) { int stableHashCode = text2.GetStableHashCode(); itemPrefab = instance.GetItemPrefab(stableHashCode); if ((Object)itemPrefab != (Object)null) { ParrotsPlugin.ParrotsLogger.LogDebug((object)("[ParrotFlight] Found '" + text2 + "' via hash lookup (actual name: " + ((Object)itemPrefab).name + ")")); } } if ((Object)itemPrefab != (Object)null) { ItemDrop component = itemPrefab.GetComponent(); if ((Object)component != (Object)null) { m_monsterAI.m_consumeItems.Add(component); num++; ParrotsPlugin.ParrotsLogger.LogDebug((object)("[ParrotFlight] Added missing consume item: " + text2 + " (prefab=" + ((Object)itemPrefab).name + ")")); } else { ParrotsPlugin.ParrotsLogger.LogWarning((object)("[ParrotFlight] No ItemDrop on prefab: " + text2)); } } else { ParrotsPlugin.ParrotsLogger.LogWarning((object)("[ParrotFlight] Food prefab NOT FOUND: '" + text2 + "'")); } } string text3 = ""; foreach (ItemDrop consumeItem3 in m_monsterAI.m_consumeItems) { text3 = text3 + (((Object)consumeItem3 != (Object)null) ? ((Object)consumeItem3).name : "null") + ", "; } ParrotsPlugin.ParrotsLogger.LogDebug((object)$"[ParrotFlight] ConsumeItems after fix ({m_monsterAI.m_consumeItems.Count}, added {num}): [{text3}]"); } private void PeriodicDebugLog() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_041e: 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_044c: Expected O, but got Unknown //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Expected O, but got Unknown m_debugLogTimer -= Time.deltaTime; if (m_debugLogTimer > 0f) { return; } m_debugLogTimer = 5f; string text = (IsCharacterFlying() ? "FLYING" : "GROUND"); float num; if (!m_isInFollowFlight) { if (!((Object)m_body != (Object)null)) { num = 0f; } else { Vector3 linearVelocity = m_body.linearVelocity; num = ((Vector3)(ref linearVelocity)).magnitude; } } else { num = m_lastActualSpeed; } float num2 = num; string text2 = "no AI"; if ((Object)m_monsterAI != (Object)null) { Tameable component = ((Component)this).GetComponent(); bool flag = (Object)component != (Object)null && (Object)((Component)component).GetComponent() != (Object)null && ((Component)component).GetComponent().IsTamed(); bool flag2 = (Object)component != (Object)null && component.IsHungry(); int num3 = ((m_monsterAI.m_consumeItems != null) ? m_monsterAI.m_consumeItems.Count : (-1)); string text3 = "none"; if (m_monsterAI.m_consumeItems != null && m_monsterAI.m_consumeItems.Count > 0) { int mask = LayerMask.GetMask(new string[1] { "item" }); Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, m_monsterAI.m_consumeSearchRange, mask); float num4 = float.MaxValue; string arg = ""; Collider[] array2 = array; foreach (Collider val in array2) { if ((Object)val.attachedRigidbody == (Object)null) { continue; } ItemDrop component2 = ((Component)val.attachedRigidbody).GetComponent(); if ((Object)component2 == (Object)null) { continue; } float num5 = Vector3.Distance(((Component)this).transform.position, ((Component)component2).transform.position); if (!(num5 < num4)) { continue; } foreach (ItemDrop consumeItem in m_monsterAI.m_consumeItems) { if ((Object)consumeItem != (Object)null && component2.m_itemData.m_shared.m_name == consumeItem.m_itemData.m_shared.m_name) { num4 = num5; arg = ((Object)component2).name; break; } } } if (num4 < float.MaxValue) { text3 = $"{arg} at {num4:F1}m"; } } float num6 = -1f; if ((Object)Player.m_localPlayer != (Object)null) { num6 = Vector3.Distance(((Component)this).transform.position, ((Component)Player.m_localPlayer).transform.position); } string text4 = "idle"; string text5 = (flag ? $", followFlight={m_followState}" : ""); text2 = $"alerted={((BaseAI)m_monsterAI).IsAlerted()}, " + $"playerDist={num6:F1}m, " + $"consumeItems={num3}, " + "consume=" + text4 + ", " + $"tamed={flag}, hungry={flag2}, " + "nearbyFood=" + text3 + text5; } string text6 = ""; if ((Object)m_body != (Object)null) { float num7 = (((Object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.GetGroundHeight(((Component)this).transform.position) : 0f); float num8 = ((Component)this).transform.position.y - num7; text6 = $", alt={((Component)this).transform.position.y:F1} (ground+{num8:F1}), velY={m_body.linearVelocity.y:F2}"; if (m_isInFollowFlight && (Object)Player.m_localPlayer != (Object)null) { float num9 = ((Component)this).transform.position.y - ((Component)Player.m_localPlayer).transform.position.y; text6 += $", player+{num9:F1}"; } } ParrotsPlugin.ParrotsLogger.LogDebug((object)("[ParrotFlight] " + ((Object)((Component)this).gameObject).name + ": state=" + text + ", " + $"speed={num2:F1}m/s{text6}, " + "AI[" + text2 + "]")); } private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (!((Object)m_character == (Object)null) && (!((Object)m_nview != (Object)null) || m_nview.IsValid())) { if ((Object)m_nview != (Object)null && !m_nview.IsOwner()) { SyncNonOwnerFlightMode(); return; } ManageFlightSuppression(); ManageConsumeForFlight(); ManageTamedFollowFlight(); UpdateFollowFlightAngle(); OrientTowardOwner(); TryFixConsumeItems(); PeriodicDebugLog(); } } private void LateUpdate() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)m_character == (Object)null) && (!((Object)m_nview != (Object)null) || m_nview.IsValid()) && (!((Object)m_nview != (Object)null) || m_nview.IsOwner())) { ApplyFollowFlightPhysics(); UpdateTurnSpeed(); UpdateNormalizedSpeed(); UpdateAnimSpeed(); if ((Object)m_body != (Object)null) { Vector3 linearVelocity = m_body.linearVelocity; m_lastActualSpeed = ((Vector3)(ref linearVelocity)).magnitude; } } } private void UpdateTurnSpeed() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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)m_animator == (Object)null) { return; } Vector3 forward = ((Component)this).transform.forward; float deltaTime = Time.deltaTime; if (IsCharacterFlying()) { if (((Vector3)(ref m_prevForward)).sqrMagnitude > 0.01f && deltaTime > 0.001f) { float num = Vector3.SignedAngle(m_prevForward, forward, Vector3.up) / deltaTime; if (Mathf.Abs(num) < 2f) { num = 0f; } float num2 = Mathf.Clamp(num / m_character.m_flyTurnSpeed, -1f, 1f); m_smoothTurnSpeed = Mathf.Lerp(m_smoothTurnSpeed, num2, 3f * deltaTime); } else { m_smoothTurnSpeed = Mathf.Lerp(m_smoothTurnSpeed, 0f, 3f * deltaTime); } m_animator.SetFloat("turn_speed", m_smoothTurnSpeed); } else { m_smoothTurnSpeed = Mathf.Lerp(m_smoothTurnSpeed, 0f, 4f * deltaTime); m_animator.SetFloat("turn_speed", m_smoothTurnSpeed); } m_prevForward = forward; } private void UpdateNormalizedSpeed() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //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) if ((Object)m_animator == (Object)null) { return; } if (IsCharacterFlying()) { float num; if (!((Object)m_body != (Object)null)) { num = 0f; } else { Vector3 linearVelocity = m_body.linearVelocity; num = ((Vector3)(ref linearVelocity)).magnitude; } float num2 = Mathf.Clamp01(num / m_maxFlightSpeed); float num3 = (m_isInFollowFlight ? 0.35f : 0.25f); num2 = Mathf.Max(num2, num3); m_smoothNormalizedSpeed = Mathf.Lerp(m_smoothNormalizedSpeed, num2, 5f * Time.deltaTime); } else { m_smoothNormalizedSpeed = Mathf.Lerp(m_smoothNormalizedSpeed, 0f, 3f * Time.deltaTime); } m_animator.SetFloat("normalized_speed", m_smoothNormalizedSpeed); } private void UpdateAnimSpeed() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if ((Object)m_animator == (Object)null) { return; } float num; if (IsCharacterFlying()) { num = Mathf.Lerp(1.5f, 3f, m_smoothNormalizedSpeed); } else { float num2; if (!((Object)m_body != (Object)null)) { num2 = 0f; } else { Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(m_body.linearVelocity.x, m_body.linearVelocity.z); num2 = ((Vector2)(ref val)).magnitude; } float num3 = num2; float num4 = (((Object)m_character != (Object)null) ? m_character.m_runSpeed : 4f); num = Mathf.Lerp(1f, 1.5f, Mathf.Clamp01(num3 / num4)); } m_smoothAnimSpeed = Mathf.Lerp(m_smoothAnimSpeed, num, 3f * Time.deltaTime); m_animator.SetFloat("anim_speed", m_smoothAnimSpeed); } private void ApplyFollowFlightPhysics() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_005e: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) if (!m_isInFollowFlight || !IsCharacterFlying() || (Object)m_body == (Object)null || (Object)m_character == (Object)null) { return; } Player followPlayer = GetFollowPlayer(); if ((Object)followPlayer == (Object)null) { return; } float deltaTime = Time.deltaTime; if (deltaTime < 0.0001f) { return; } Vector3 val = ComputeDesiredVelocity(followPlayer); Vector3 linearVelocity = m_body.linearVelocity; float num = 20f * deltaTime; float num2 = 15f * deltaTime; Vector3 linearVelocity2 = new Vector3 { x = Mathf.MoveTowards(linearVelocity.x, val.x, num), z = Mathf.MoveTowards(linearVelocity.z, val.z, num), y = Mathf.MoveTowards(linearVelocity.y, val.y, num2) }; m_body.linearVelocity = linearVelocity2; Vector3 linearVelocity3 = m_body.linearVelocity; if (((Vector3)(ref linearVelocity3)).sqrMagnitude > 0.25f) { Vector3 val2 = linearVelocity3; val2.y *= 0.3f; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { Quaternion val3 = Quaternion.LookRotation(((Vector3)(ref val2)).normalized); m_body.MoveRotation(Quaternion.Slerp(m_body.rotation, val3, 5f * deltaTime)); } } if ((Object)m_animator != (Object)null) { Vector3 linearVelocity4 = m_body.linearVelocity; float magnitude = ((Vector3)(ref linearVelocity4)).magnitude; m_animator.SetFloat("forward_speed", magnitude); m_animator.SetBool("flying", true); } } private Vector3 ComputeDesiredVelocity(Player player) { //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_0062: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Expected O, but got Unknown //IL_00da: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position; float flyFastSpeed = m_character.m_flyFastSpeed; float flySlowSpeed = m_character.m_flySlowSpeed; switch (m_followState) { case FollowFlightState.Approaching: { float num12 = 7f + Mathf.Sin(Time.time * 0.18f) * 2.5f; Vector3 val7 = position + new Vector3(Mathf.Sin(m_orbitAngle) * 6f, num12, Mathf.Cos(m_orbitAngle) * 6f) - ((Component)this).transform.position; float magnitude3 = ((Vector3)(ref val7)).magnitude; float num13 = Mathf.Lerp(flySlowSpeed, flyFastSpeed, Mathf.Clamp01(magnitude3 / 10f)); if (!(magnitude3 > 0.5f)) { return val7 * 2f; } return ((Vector3)(ref val7)).normalized * num13; } case FollowFlightState.Orbiting: { Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(((Component)this).transform.position.x - position.x, 0f, ((Component)this).transform.position.z - position.z); float magnitude2 = ((Vector3)(ref val3)).magnitude; Vector3 val4 = ((magnitude2 > 0.1f) ? (val3 / magnitude2) : Vector3.forward); Vector3 val5 = new Vector3(0f - val4.z, 0f, val4.x); float num5 = 1f + 0.3f * Mathf.Sin(m_orbitAngle * 2f); float num6 = 5.3999996f * num5; Vector3 val6 = val5 * num6; float num7 = magnitude2 - 6f; val6 -= val4 * Mathf.Clamp(num7 * 2f, 0f - flyFastSpeed, flyFastSpeed); float num8 = Mathf.Sin(m_orbitAngle * 0.5f) * 1f; float num9 = Mathf.Sin(Time.time * 0.18f) * 2.5f; float num10 = 0f; if (m_swoopPhase > 0f) { num10 = -4f * Mathf.Sin(m_swoopPhase * (float)Math.PI); } float num11 = position.y + 7f + num8 + num9 + num10 - ((Component)this).transform.position.y; val6.y = Mathf.Clamp(num11 * 3f, 0f - flySlowSpeed, flySlowSpeed); return val6; } case FollowFlightState.Landing: { float num = Mathf.Lerp(4.8f, 2f, m_landingSpiral); float num2 = Mathf.Lerp(7f + Mathf.Sin(Time.time * 0.18f) * 2.5f, 1.5f, m_landingSpiral * m_landingSpiral); Vector3 val = position + new Vector3(Mathf.Sin(m_orbitAngle) * num, num2, Mathf.Cos(m_orbitAngle) * num); float num3 = (((Object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.GetGroundHeight(val) : 0f); val.y = Mathf.Max(val.y, num3 + 1.5f); Vector3 val2 = val - ((Component)this).transform.position; float magnitude = ((Vector3)(ref val2)).magnitude; float num4 = Mathf.Lerp(1f, flySlowSpeed, Mathf.Clamp01(magnitude / 4f)); if (!(magnitude > 0.1f)) { return Vector3.zero; } return ((Vector3)(ref val2)).normalized * num4; } default: return Vector3.zero; } } private void UpdateFollowFlightAngle() { if (!m_isInFollowFlight) { return; } switch (m_followState) { case FollowFlightState.Orbiting: m_orbitAngle += 0.9f * Time.deltaTime; if (m_swoopPhase > 0f) { m_swoopPhase += Time.deltaTime / 4f; if (m_swoopPhase >= 1f) { m_swoopPhase = 0f; } break; } m_swoopTimer -= Time.deltaTime; if (m_swoopTimer <= 0f) { m_swoopPhase = 0.01f; m_swoopTimer = 18f + Random.Range(-4f, 6f); } break; case FollowFlightState.Landing: { float num = 1f - m_landingSpiral * m_landingSpiral; m_orbitAngle += 1.17f * num * Time.deltaTime; break; } } } private void ManageFlightSuppression() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Expected O, but got Unknown //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Expected O, but got Unknown //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Expected O, but got Unknown if ((Object)m_monsterAI == (Object)null) { return; } m_flightSuppressionCheckTimer -= Time.deltaTime; if (m_flightSuppressionCheckTimer > 0f) { return; } m_flightSuppressionCheckTimer = 1f; Character val = m_character ?? ((Component)this).GetComponent(); if ((Object)val != (Object)null && val.IsTamed()) { if (!m_tamedSettingsApplied) { m_tamedSettingsApplied = true; m_monsterAI.m_fleeIfNotAlerted = false; m_monsterAI.m_fleeIfLowHealth = 0f; m_flightSuppressed = false; m_character.m_speed = 4f; m_character.m_runSpeed = 6f; m_character.m_flySlowSpeed = 7f; m_character.m_flyFastSpeed = 14f; m_character.m_flyTurnSpeed = 12f; m_character.m_acceleration = 3f; m_maxFlightSpeed = Mathf.Lerp(m_character.m_flySlowSpeed, m_character.m_flyFastSpeed, 0.25f); ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, $"[ParrotFlight] {((Object)((Component)this).gameObject).name}: TAMED! Speeds boosted (ground=4/6, fly=7/14, turn=12, accel=3, maxFlight={m_maxFlightSpeed:F1})"); } if (m_isInFollowFlight) { return; } if ((Object)ParrotCompat.GetFollowTargetSafe(m_monsterAI) == (Object)null) { ((BaseAI)m_monsterAI).m_randomFly = false; ((BaseAI)m_monsterAI).m_randomMoveRange = 0f; if (IsCharacterFlying()) { m_character.m_flying = false; } } else { ((BaseAI)m_monsterAI).m_randomFly = true; } return; } if (m_tamedSettingsApplied || m_character.m_flyFastSpeed > 10.5f) { m_tamedSettingsApplied = false; m_character.m_speed = 1.5f; m_character.m_runSpeed = 3f; m_character.m_flySlowSpeed = 5f; m_character.m_flyFastSpeed = 10f; m_character.m_flyTurnSpeed = 6f; m_character.m_acceleration = 0.6f; m_maxFlightSpeed = Mathf.Lerp(5f, 10f, 0.25f); ParrotsPlugin.ParrotsLogger.LogWarning((object)$"[ParrotFlight] {((Object)((Component)this).gameObject).name}: wild parrot had tamed speeds (flyFast={m_character.m_flyFastSpeed})! Reset to prefab values."); } bool flag = false; string text = ""; Tameable component = ((Component)this).GetComponent(); if ((Object)component != (Object)null) { float num = Mathf.Clamp01(ParrotCompat.GetTamenessSafe(component)); if (num > 0f) { flag = true; text = $"taming in progress ({num * 100f:F0}%)"; } } if (!flag && m_monsterAI.m_consumeItems != null && m_monsterAI.m_consumeItems.Count > 0) { float num2 = m_monsterAI.m_consumeRange * 2f; int mask = LayerMask.GetMask(new string[1] { "item" }); Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, num2, mask); foreach (Collider val2 in array) { if ((Object)val2.attachedRigidbody == (Object)null) { continue; } ItemDrop component2 = ((Component)val2.attachedRigidbody).GetComponent(); if ((Object)component2 == (Object)null) { continue; } foreach (ItemDrop consumeItem in m_monsterAI.m_consumeItems) { if ((Object)consumeItem != (Object)null && component2.m_itemData.m_shared.m_name == consumeItem.m_itemData.m_shared.m_name) { flag = true; text = "food nearby (" + ((Object)component2).name + ")"; break; } } if (flag) { break; } } } if (flag && !m_flightSuppressed) { ((BaseAI)m_monsterAI).m_randomFly = false; m_flightSuppressed = true; ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] " + ((Object)((Component)this).gameObject).name + ": Flight SUPPRESSED (" + text + ") - staying grounded"); } else if (!flag && m_flightSuppressed) { ((BaseAI)m_monsterAI).m_randomFly = true; m_flightSuppressed = false; ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] " + ((Object)((Component)this).gameObject).name + ": Flight RESTORED - no food nearby, not fleeing"); } } private void ManageConsumeForFlight() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (!((Object)m_monsterAI == (Object)null) && !((Object)m_character == (Object)null) && !m_character.IsTamed()) { if (IsCharacterFlying()) { m_monsterAI.m_consumeSearchInterval = 999f; } else { m_monsterAI.m_consumeSearchInterval = 2f; } } } private void ManageTamedFollowFlight() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Expected O, but got Unknown if ((Object)m_character == (Object)null || (Object)m_monsterAI == (Object)null || !m_character.IsTamed()) { return; } m_followFlightDiagTimer -= Time.deltaTime; if (m_followFlightDiagTimer <= 0f) { m_followFlightDiagTimer = 5f; ShoulderParrot component = ((Component)this).GetComponent(); bool flag = (Object)component != (Object)null && component.IsOnShoulder; ParrotsPlugin.ParrotsLogger.LogDebug((object)($"[FollowFlight] DIAG {((Object)((Component)this).gameObject).name}: state={m_followState}, " + $"isInFollowFlight={m_isInFollowFlight}, flying={IsCharacterFlying()}, " + "follow=" + (((Object)ParrotCompat.GetFollowTargetSafe(m_monsterAI) != (Object)null) ? ((Object)ParrotCompat.GetFollowTargetSafe(m_monsterAI)).name : "NULL") + ", " + $"onShoulder={flag}, " + $"monsterAI.enabled={((Behaviour)m_monsterAI).enabled}, " + $"Y={((Component)this).transform.position.y:F1}")); } if ((Object)ParrotCompat.GetFollowTargetSafe(m_monsterAI) == (Object)null) { m_summonedLanding = false; if (m_followState != FollowFlightState.Grounded) { TransitionTo(FollowFlightState.Grounded); if (IsCharacterFlying()) { m_character.m_flying = false; } } return; } ShoulderParrot component2 = ((Component)this).GetComponent(); if ((Object)component2 != (Object)null && component2.IsOnShoulder) { return; } if (!m_isInFollowFlight && m_followState != FollowFlightState.Grounded) { ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, $"[ParrotFlight] Ownership recovery: state={m_followState} but not in follow-flight. Resetting to Grounded."); m_followState = FollowFlightState.Grounded; m_followFlightTimer = 0f; } if (!m_isInFollowFlight && (Object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner() && m_nview.GetZDO().GetInt("PR_flightMode", 0) == 1 && IsCharacterFlying()) { Player followPlayer = GetFollowPlayer(); if ((Object)followPlayer != (Object)null) { ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] Ownership recovery: ZDO flightMode=1, re-entering follow-flight orbit."); m_followState = FollowFlightState.Grounded; m_isInFollowFlight = false; TransitionTo(FollowFlightState.Orbiting); InitOrbit(followPlayer); } else { ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] Ownership recovery: ZDO flightMode=1 but no follow player. Landing."); m_nview.GetZDO().Set("PR_flightMode", 0); } } Player followPlayer2 = GetFollowPlayer(); if ((Object)followPlayer2 == (Object)null) { return; } float num = Vector3.Distance(((Component)this).transform.position, ((Component)followPlayer2).transform.position); Vector3 velocity = ((Character)followPlayer2).GetVelocity(); float magnitude = ((Vector3)(ref velocity)).magnitude; if (magnitude < 0.3f) { m_playerStillTimer += Time.deltaTime; } else { m_playerStillTimer = 0f; } switch (m_followState) { case FollowFlightState.Grounded: if (m_followFlightTimer > 0f) { if (IsCharacterFlying()) { m_character.m_flying = false; ((BaseAI)m_monsterAI).m_randomFly = false; } m_followFlightTimer -= Time.deltaTime; if (!(m_followFlightTimer <= 0f)) { break; } if (m_playerStillTimer > 2f) { m_followFlightTimer = 1f; break; } ((BaseAI)m_monsterAI).m_randomFly = true; m_followFlightTimer = Random.Range(3f, 6f); float num2 = ((num > 8f) ? 0.7f : 0.5f); if (Random.value < num2) { TransitionTo(FollowFlightState.Orbiting); m_character.m_flying = true; InitOrbit(followPlayer2); } break; } if (IsCharacterFlying()) { TransitionTo(FollowFlightState.Orbiting); InitOrbit(followPlayer2); break; } if (num > 12f) { TransitionTo(FollowFlightState.Approaching); m_character.m_flying = true; break; } m_followFlightTimer -= Time.deltaTime; if (m_followFlightTimer <= 0f) { m_followFlightTimer = Random.Range(3f, 6f); float num3 = ((num > 8f) ? 0.7f : 0.5f); if (Random.value < num3) { TransitionTo(FollowFlightState.Orbiting); m_character.m_flying = true; InitOrbit(followPlayer2); } } break; case FollowFlightState.Approaching: if (num < 15f) { TransitionTo(FollowFlightState.Orbiting); InitOrbit(followPlayer2); } break; case FollowFlightState.Orbiting: if (m_playerStillTimer > 12f) { TransitionTo(FollowFlightState.Landing); m_landingSpiral = 0f; } else if (num > 25f) { TransitionTo(FollowFlightState.Approaching); } break; case FollowFlightState.Landing: m_landingSpiral += Time.deltaTime / 4f; if (m_landingSpiral >= 1f || !IsCharacterFlying()) { TransitionTo(FollowFlightState.Grounded); if (IsCharacterFlying()) { m_character.m_flying = false; } ((BaseAI)m_monsterAI).m_randomFly = false; m_followFlightTimer = Random.Range(3f, 6f); m_summonedLanding = false; } else if (magnitude > 1f && !m_summonedLanding) { TransitionTo(FollowFlightState.Orbiting); InitOrbit(followPlayer2); } break; } } private void TransitionTo(FollowFlightState newState) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //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) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) if (m_followState == newState) { return; } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, $"[ParrotFlight] Follow state: {m_followState} -> {newState}"); bool num = m_followState == FollowFlightState.Grounded; bool flag = newState == FollowFlightState.Grounded; m_followState = newState; if ((Object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner()) { int num2 = ((!flag) ? 1 : 0); m_nview.GetZDO().Set("PR_flightMode", num2); } if (num && !flag && (Object)m_monsterAI != (Object)null) { m_isInFollowFlight = true; ((Behaviour)m_monsterAI).enabled = false; if ((Object)m_character != (Object)null) { s_followFlightCharacters.Add(m_character); } if ((Object)m_body != (Object)null) { m_body.useGravity = false; m_savedInterpolation = m_body.interpolation; m_body.interpolation = (RigidbodyInterpolation)1; } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] MonsterAI DISABLED for follow-flight, gravity OFF"); } if (!flag) { return; } if ((Object)m_character != (Object)null) { m_character.m_flyTurnSpeed = 12f; s_followFlightCharacters.Remove(m_character); } if ((Object)m_monsterAI != (Object)null && m_isInFollowFlight) { m_isInFollowFlight = false; ((Behaviour)m_monsterAI).enabled = true; if ((Object)m_body != (Object)null) { m_body.useGravity = true; m_body.interpolation = m_savedInterpolation; } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] MonsterAI RE-ENABLED (grounded), gravity ON"); } } private void InitOrbit(Player player) { //IL_0007: 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_0028: 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) m_orbitAngle = Mathf.Atan2(((Component)this).transform.position.x - ((Component)player).transform.position.x, ((Component)this).transform.position.z - ((Component)player).transform.position.z); m_swoopTimer = 9f + Random.Range(0f, 9f); m_swoopPhase = 0f; } public void SuppressTakeoff(float duration) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown m_followState = FollowFlightState.Grounded; m_isInFollowFlight = false; m_followFlightTimer = duration; if ((Object)m_monsterAI != (Object)null) { ((BaseAI)m_monsterAI).m_randomFly = false; } } public void CommandLandNearby(bool toShoulder) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if ((Object)m_nview != (Object)null && m_nview.IsValid() && !m_nview.IsOwner()) { m_nview.InvokeRPC("RPC_CommandLand", new object[1] { toShoulder }); } else { CommandLandNearbyInternal(toShoulder); } } private void CommandLandNearbyInternal(bool toShoulder) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown m_summonedLanding = true; if (m_followState == FollowFlightState.Grounded || m_followState == FollowFlightState.Landing) { return; } if (!m_isInFollowFlight) { if ((Object)m_character != (Object)null) { m_character.m_flying = true; } TransitionTo(FollowFlightState.Orbiting); Player followPlayer = GetFollowPlayer(); if ((Object)followPlayer != (Object)null) { InitOrbit(followPlayer); } } TransitionTo(FollowFlightState.Landing); m_landingSpiral = 0f; ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, $"[ParrotFlight] CommandLandNearby(toShoulder={toShoulder}): forcing Landing"); } public void CommandTakeoff() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if ((Object)m_nview != (Object)null && m_nview.IsValid() && !m_nview.IsOwner()) { m_nview.InvokeRPC("RPC_CommandTakeoff", Array.Empty()); } else { CommandTakeoffInternal(); } } private void CommandTakeoffInternal() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if (!((Object)m_character == (Object)null)) { Player followPlayer = GetFollowPlayer(); if (!((Object)followPlayer == (Object)null)) { m_character.m_flying = true; m_followFlightTimer = 0f; m_followState = FollowFlightState.Grounded; m_isInFollowFlight = false; TransitionTo(FollowFlightState.Orbiting); InitOrbit(followPlayer); ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] CommandTakeoff: forced orbit entry from dismount"); } } } private void OrientTowardOwner() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) if ((Object)m_character == (Object)null || (Object)m_monsterAI == (Object)null || !m_character.IsTamed() || IsCharacterFlying() || (Object)ParrotCompat.GetFollowTargetSafe(m_monsterAI) == (Object)null) { return; } ShoulderParrot component = ((Component)this).GetComponent(); if ((Object)component != (Object)null && component.IsOnShoulder) { return; } Player followPlayer = GetFollowPlayer(); if ((Object)followPlayer == (Object)null) { return; } float num = Vector3.Distance(((Component)this).transform.position, ((Component)followPlayer).transform.position); if (num > 5f || num < 0.5f) { return; } Vector3 val = ((Component)followPlayer).transform.position - ((Component)this).transform.position; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f)) { if (!((Object)m_body != (Object)null)) { float num2 = 0f; } else { Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(m_body.linearVelocity.x, m_body.linearVelocity.z); float num2 = ((Vector2)(ref val2)).magnitude; } _ = 1f; } } private void SyncNonOwnerFlightMode() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown if ((Object)m_nview == (Object)null || !m_nview.IsValid()) { return; } bool flag = m_nview.GetZDO().GetInt("PR_flightMode", 0) == 1; if (flag && !m_nonOwnerFollowFlight) { m_nonOwnerFollowFlight = true; if ((Object)m_monsterAI != (Object)null) { ((Behaviour)m_monsterAI).enabled = false; } if ((Object)m_body != (Object)null) { m_body.useGravity = false; } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] Non-owner: follow-flight mode ON (AI disabled)"); } else if (!flag && m_nonOwnerFollowFlight) { m_nonOwnerFollowFlight = false; if ((Object)m_monsterAI != (Object)null) { ((Behaviour)m_monsterAI).enabled = true; } if ((Object)m_body != (Object)null) { m_body.useGravity = true; } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[ParrotFlight] Non-owner: follow-flight mode OFF (AI restored)"); } } private void RPC_CommandLand(long sender, bool toShoulder) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if (!((Object)m_nview == (Object)null) && m_nview.IsOwner() && IsAuthorizedCommander(sender)) { CommandLandNearbyInternal(toShoulder); } } private void RPC_CommandTakeoff(long sender) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if (!((Object)m_nview == (Object)null) && m_nview.IsOwner() && IsAuthorizedCommander(sender)) { CommandTakeoffInternal(); } } private bool IsAuthorizedCommander(long senderSessionId) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Player followPlayer = GetFollowPlayer(); if ((Object)followPlayer == (Object)null) { return true; } ZNetView component = ((Component)followPlayer).GetComponent(); if ((Object)component == (Object)null || !component.IsValid()) { return true; } return component.GetZDO().GetOwner() == senderSessionId; } private void RPC_PlayWhistleSFX(long sender, int sfxType) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (sender == ZDOMan.GetSessionID()) { return; } ZNetScene instance = ZNetScene.instance; if ((Object)instance == (Object)null) { return; } GameObject prefab = instance.GetPrefab("PR_SFX_Whistle"); if ((Object)prefab != (Object)null) { Object.Instantiate(prefab, ((Component)this).transform.position, Quaternion.identity); } if (sfxType == 1) { GameObject prefab2 = instance.GetPrefab("PR_SFX_Chirp"); if ((Object)prefab2 != (Object)null) { ((MonoBehaviour)this).StartCoroutine(DelayedRemoteSFX(prefab2, ((Component)this).transform.position, 0.4f)); } } } private static IEnumerator DelayedRemoteSFX(GameObject prefab, Vector3 position, float delay) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForSeconds(delay); Object.Instantiate(prefab, position, Quaternion.identity); } private bool IsCharacterFlying() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if ((Object)m_character != (Object)null) { return m_character.m_flying; } return false; } private Player GetFollowPlayer() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if ((Object)m_monsterAI == (Object)null || (Object)ParrotCompat.GetFollowTargetSafe(m_monsterAI) == (Object)null) { return null; } return ParrotCompat.GetFollowTargetSafe(m_monsterAI).GetComponent(); } } internal static class ParrotOriginalLocalization { private static bool s_registered; private static readonly Dictionary English = new Dictionary { ["$enemy_parrot1"] = "Blue-and-Yellow Macaw", ["enemy_parrot1"] = "Blue-and-Yellow Macaw", ["$item_parrotegg"] = "Parrot Egg", ["item_parrotegg"] = "Parrot Egg", ["$item_parrotegg_desc"] = "A warm parrot egg.", ["item_parrotegg_desc"] = "A warm parrot egg.", ["$parrot_hatching"] = "Hatching", ["parrot_hatching"] = "Hatching", ["$parrot_whistle"] = "You whistle for your parrot", ["parrot_whistle"] = "You whistle for your parrot", ["$parrot_call_shoulder"] = "You call your parrot to your shoulder", ["parrot_call_shoulder"] = "You call your parrot to your shoulder", ["$parrot_perched"] = "Parrot perched on shoulder", ["parrot_perched"] = "Parrot perched on shoulder", ["$parrot_dismount"] = "Dismount", ["parrot_dismount"] = "Dismount", ["$parrot_call_down"] = "Call down", ["parrot_call_down"] = "Call down", ["$parrot_shoulder"] = "Shoulder", ["parrot_shoulder"] = "Shoulder", ["$parrot_hold"] = "Hold", ["parrot_hold"] = "Hold" }; internal static void Register() { if (!s_registered && (TryRegisterJotunn() | TryRegisterValheimLocalization())) { s_registered = true; ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[FehuParrots] Parrot egg localization registered."); } } private static bool TryRegisterJotunn() { try { Type type = Type.GetType("Jotunn.Managers.LocalizationManager, Jotunn"); if (type == null) { return false; } object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return false; } foreach (MethodInfo item in from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public) where m.Name == "AddTranslation" select m) { ParameterInfo[] parameters = item.GetParameters(); try { if (parameters.Length == 2 && parameters[0].ParameterType == typeof(string) && typeof(IDictionary).IsAssignableFrom(parameters[1].ParameterType)) { item.Invoke(obj, new object[2] { "English", English }); return true; } if (parameters.Length == 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(Dictionary)) { item.Invoke(obj, new object[2] { "English", English }); return true; } if (parameters.Length != 3 || !(parameters[0].ParameterType == typeof(string)) || !(parameters[1].ParameterType == typeof(string)) || !(parameters[2].ParameterType == typeof(string))) { continue; } foreach (KeyValuePair item2 in English) { item.Invoke(obj, new object[3] { "English", item2.Key, item2.Value }); } return true; } catch { } } } catch (Exception ex) { ManualLogSource parrotsLogger = ParrotsPlugin.ParrotsLogger; if (parrotsLogger != null) { parrotsLogger.LogWarning((object)("[FehuParrots] Jotunn localization registration failed: " + ex.Message)); } } return false; } private static bool TryRegisterValheimLocalization() { try { Type type = AccessTools.TypeByName("Localization") ?? Type.GetType("Localization, assembly_valheim"); object obj = type?.GetField("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? type?.GetProperty("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (type == null || obj == null) { return false; } MethodInfo method = type.GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { foreach (KeyValuePair item in English) { string text = (item.Key.StartsWith("$") ? item.Key.Substring(1) : item.Key); method.Invoke(obj, new object[2] { text, item.Value }); } return true; } } catch (Exception ex) { ManualLogSource parrotsLogger = ParrotsPlugin.ParrotsLogger; if (parrotsLogger != null) { parrotsLogger.LogWarning((object)("[FehuParrots] Valheim localization registration failed: " + ex.Message)); } } return false; } } [HarmonyPatch] internal static class ParrotLocalizationRuntimePatch { private static IEnumerable TargetMethods() { Type localization = AccessTools.TypeByName("Localization"); if (!(localization == null)) { MethodInfo methodInfo = AccessTools.Method(localization, "SetupLanguage", (Type[])null, (Type[])null); if (methodInfo != null) { yield return methodInfo; } MethodInfo methodInfo2 = AccessTools.Method(localization, "LoadLanguages", (Type[])null, (Type[])null); if (methodInfo2 != null) { yield return methodInfo2; } } } private static void Postfix() { ParrotOriginalLocalization.Register(); } } internal static class ParrotRuntimeUtil { internal static ParrotConfig Config { get; private set; } internal static void Configure(ParrotConfig config) { Config = config; } } public sealed class ParrotRegistry { private readonly ManualLogSource _log; private readonly ParrotConfig _config; private readonly ParrotAssetLoader _loader; private readonly FehuAssetsPlugin _plugin; public static RuntimeAnimatorController? CachedAnimatorController { get; private set; } public ParrotRegistry(FehuAssetsPlugin plugin) { _plugin = plugin; _log = plugin.ParrotLog; _config = new ParrotConfig(((BaseUnityPlugin)plugin).Config); _loader = new ParrotAssetLoader(_log); } public void Register() { if (!_config.EnableParrots.Value) { ParrotDebugLog.Info(_log, "[FehuParrots] Disabled by config. No Parrots assets registered."); return; } ParrotRuntimeUtil.Configure(_config); _config.LogAndMigrate(_log); if (_config.EnableParrotDebugLogs.Value) { _loader.LogBundleInventory(); } CachedAnimatorController = _loader.LoadAsset("Assets/Animations/PR_ParrotAnimator.controller") ?? _loader.LoadAsset("PR_ParrotAnimator"); ParrotsPlugin.Configure(_plugin, _config, CachedAnimatorController); ParrotBreedingAudit.LogConfig(_log, _config); RegisterBackendPrefabs(); if (_config.EnableParrotEgg.Value) { RegisterParrotEgg(); } if (_config.EnableParrotGameplay.Value) { RegisterParrotCreature(); ParrotDebugLog.Info(_log, "[FehuParrots] Live PR_Parrot1 registered through Jotunn CreatureManager. Original Character/Humanoid/MonsterAI/Tameable stack preserved."); } else { ParrotDebugLog.Info(_log, "[FehuParrots] EnableParrotGameplay=false. PR_Parrot1 creature was not registered; no placeholder/hybrid creature is created."); } } private void RegisterBackendPrefabs() { string[] phase2BackendPrefabs = ParrotAssets.Phase2BackendPrefabs; foreach (string text in phase2BackendPrefabs) { GameObject val = _loader.LoadPrefab(text); PrefabManager.Instance.AddPrefab(val); if (_config.EnableParrotDebugLogs.Value) { ParrotDebugLog.Info(_log, "[FehuParrots] Registered backend prefab through Jotunn PrefabManager: " + text); } } } private void RegisterParrotEgg() { //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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown ItemConfig val = new ItemConfig { Name = "$item_parrotegg", Description = "$item_parrotegg_desc", Amount = 1, Enabled = false }; bool flag = ItemManager.Instance.AddItem(new CustomItem(_loader.LoadBundle(), "PR_ParrotEgg", true, val)); ParrotDebugLog.Info(_log, $"[FehuParrots] PR_ParrotEgg Jotunn ItemManager registration registered={flag}."); } private void RegisterParrotCreature() { //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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown CreatureConfig val = new CreatureConfig { Name = "Macaw", Faction = (Faction)2 }; bool flag = CreatureManager.Instance.AddCreature(new CustomCreature(_loader.LoadBundle(), "PR_Parrot1", true, val)); ParrotDebugLog.Info(_log, $"[FehuParrots] PR_Parrot1 Jotunn CreatureManager registration registered={flag}."); } internal static bool IsParrotEggItem(ItemData? itemData) { if (itemData == null) { return false; } string text = itemData.m_shared?.m_name ?? string.Empty; string text2 = (((Object)(object)itemData.m_dropPrefab != (Object)null) ? ((Object)itemData.m_dropPrefab).name : string.Empty); switch (text) { default: if (text.IndexOf("parrotegg", StringComparison.OrdinalIgnoreCase) < 0) { return text2 == "PR_ParrotEgg"; } break; case "$item_parrotegg": case "Parrot Egg": case "PR_ParrotEgg": break; } return true; } } [HarmonyPatch] internal static class ParrotServerDevcommandsComponentInfoInstrumentation { private static bool _logged; private static bool Prepare() { ParrotConfig config = ParrotRuntimeUtil.Config; if (config != null && config.EnableParrotDebugLogs.Value) { return AccessTools.TypeByName("ServerDevcommands.ComponentInfo") != null; } return false; } private static MethodBase? TargetMethod() { Type type = AccessTools.TypeByName("ServerDevcommands.ComponentInfo"); if (!(type != null)) { return null; } return AccessTools.Method(type, "SearchComponents", (Type[])null, (Type[])null); } private static bool Prefix() { if (_logged) { return true; } _logged = true; int num = 0; foreach (GameObject item in EnumeratePrefabs()) { if ((Object)(object)item == (Object)null) { continue; } Component[] componentsInChildren = item.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Component val = componentsInChildren[i]; if ((Object)(object)val == (Object)null) { num++; Debug.LogWarning((object)$"[FehuParrots] ComponentInfo diagnostic prefab='{((Object)item).name}' componentIndex={i} component=NULL missingMonoBehaviour=True registeredBy='{GuessRegistrant(((Object)item).name)}'"); continue; } Type type = ((object)val).GetType(); MonoBehaviour val2 = (MonoBehaviour)(object)((val is MonoBehaviour) ? val : null); if (val2 != null && (Object)(object)val2 == (Object)null) { num++; Debug.LogWarning((object)$"[FehuParrots] ComponentInfo diagnostic prefab='{((Object)item).name}' componentIndex={i} componentType='{type.FullName}' unityNull=True registeredBy='{GuessRegistrant(((Object)item).name)}'"); } } } ParrotDebugLog.Unity($"[FehuParrots] ComponentInfo diagnostic completed suspiciousComponents={num}. Original ServerDevcommands.SearchComponents will continue normally."); return true; } private static IEnumerable EnumeratePrefabs() { HashSet seen = new HashSet(); if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null) { foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if ((Object)(object)prefab != (Object)null && seen.Add(prefab)) { yield return prefab; } } } if (!((Object)(object)ObjectDB.instance != (Object)null) || ObjectDB.instance.m_items == null) { yield break; } foreach (GameObject item in ObjectDB.instance.m_items) { if ((Object)(object)item != (Object)null && seen.Add(item)) { yield return item; } } } private static string GuessRegistrant(string prefabName) { if (prefabName.StartsWith("PR_", StringComparison.OrdinalIgnoreCase)) { return "FehuAssets.Parrots"; } if (prefabName.StartsWith("Fehu_", StringComparison.OrdinalIgnoreCase) || prefabName.StartsWith("Floating", StringComparison.OrdinalIgnoreCase) || prefabName.StartsWith("DS_AirShip", StringComparison.OrdinalIgnoreCase) || prefabName == "DS_MagicBroom") { return "FehuAssets"; } return "unknown"; } } internal static class ParrotsPlugin { internal static ManualLogSource ParrotsLogger; internal static readonly string[] FoodItemNames = new string[4] { "Blueberries", "Raspberry", "Carrot", "Turnip" }; internal static RuntimeAnimatorController CachedAnimatorController; internal static bool s_localizationsRegistered; public static ConfigEntry ShoulderKey; public static ConfigEntry ShoulderHoldTime; public static ConfigEntry TamingTime; public static ConfigEntry HatchTime; public static ConfigEntry BreedingEnabled; public static ConfigEntry MaxParrotsNearby; public static ConfigEntry PregnancyDuration; internal static void Configure(FehuAssetsPlugin plugin, ParrotConfig config, RuntimeAnimatorController animatorController) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Expected O, but got Unknown ParrotsLogger = plugin.ParrotLog; CachedAnimatorController = animatorController; if (ShoulderKey == null) { ShoulderKey = ((BaseUnityPlugin)plugin).Config.Bind("2 - Shoulder Parrot", "Mount Key", (KeyCode)103, "Key to mount/dismount parrot on your shoulder"); } if (ShoulderHoldTime == null) { ShoulderHoldTime = ((BaseUnityPlugin)plugin).Config.Bind("2 - Shoulder Parrot", "Hold Threshold", 0.4f, new ConfigDescription("Seconds to hold mount key for shoulder perch (short press = call to land nearby)", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 1f), Array.Empty())); } if (TamingTime == null) { TamingTime = ((BaseUnityPlugin)plugin).Config.Bind("3 - Taming", "Taming Time", config.ParrotTamingTime.Value, new ConfigDescription("Seconds to tame a parrot while fed", (AcceptableValueBase)(object)new AcceptableValueRange(30f, 600f), Array.Empty())); } if (HatchTime == null) { HatchTime = ((BaseUnityPlugin)plugin).Config.Bind("4 - Egg", "Hatch Time", config.EggHatchSeconds.Value, new ConfigDescription("Seconds for a dropped parrot egg to hatch", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 600f), Array.Empty())); } if (BreedingEnabled == null) { BreedingEnabled = ((BaseUnityPlugin)plugin).Config.Bind("5 - Breeding", "Enabled", config.EnableParrotBreeding.Value, "Allow tamed parrots to breed when fed and near a partner"); } if (MaxParrotsNearby == null) { MaxParrotsNearby = ((BaseUnityPlugin)plugin).Config.Bind("5 - Breeding", "Max Nearby", 4, new ConfigDescription("Max parrots within range before breeding stops", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20), Array.Empty())); } if (PregnancyDuration == null) { PregnancyDuration = ((BaseUnityPlugin)plugin).Config.Bind("5 - Breeding", "Pregnancy Duration", 600f, new ConfigDescription("Seconds of pregnancy before offspring spawns", (AcceptableValueBase)(object)new AcceptableValueRange(60f, 3600f), Array.Empty())); } } internal static void RegisterLocalizations() { s_localizationsRegistered = true; } } public class ShoulderParrot : MonoBehaviour { private enum KeyState { Idle, Pressed, HeldTriggered } internal const string ZInputButtonName = "ParrotCall"; private const bool s_zinputRegistered = false; private static readonly HashSet s_instances = new HashSet(); private Character m_parrot; private MonsterAI m_ai; private Rigidbody m_body; private CapsuleCollider m_collider; private ZNetView m_nview; private GameObject m_savedFollowTarget; private bool m_onShoulder; private int m_savedLayer; private const string ZDO_ON_SHOULDER = "PR_shoulder"; private const string ZDO_SHOULDER_OWNER = "PR_shoulder_owner"; private bool m_remoteOnShoulder; private Player m_remoteOwnerPlayer; private Transform m_remoteShoulderBone; private float m_autoMountTimer; private const float AutoMountMinInterval = 45f; private const float AutoMountChance = 0.25f; private const float AutoMountMaxDist = 2.5f; private const float MountRange = 5f; private float m_dismountCooldown; private bool m_loggedKinematicReset; private bool m_loggedCharacterReset; private Transform m_shoulderBone; private static readonly Vector3 ShoulderLocalOffset = new Vector3(0.05f, 0.25f, -0.03f); private const float ShoulderHeight = 1.62f; private const float ShoulderRight = 0.27f; private const float ShoulderForward = -0.03f; private static int s_lastKeyFrame = -1; private bool m_mountTransition; private float m_mountTransitionTimer; private float m_mountTransitionDuration; private Vector3 m_mountStartOffset; private const float MountTransitionMinDuration = 0.3f; private const float MountTransitionMaxDuration = 1.2f; private const float MountArcHeight = 0.5f; private bool m_dismountTransition; private float m_dismountTransitionTimer; private Vector3 m_dismountStartPos; private Vector3 m_dismountTargetPos; private Quaternion m_dismountStartRot; private bool m_dismountToFlight; private const float DismountHopDuration = 0.6f; private const float DismountHopArcHeight = 0.4f; private const float DismountTakeoffDuration = 0.4f; private const float DismountTakeoffArcHeight = 0.5f; private KeyState m_keyState; private float m_keyDownTime; private bool m_summonedToShoulder; private bool m_buttonWasDown; public static ShoulderParrot MountedParrot { get; private set; } public bool IsOnShoulder => m_onShoulder; internal static void RegisterZInputButton(object zinput) { } internal static string GetKeyDisplayName() { //IL_000a: 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) ConfigEntry shoulderKey = ParrotsPlugin.ShoulderKey; return ((object)(KeyCode)((shoulderKey == null) ? 103 : ((int)shoulderKey.Value))/*cast due to .constrained prefix*/).ToString(); } private static bool GetButtonDown() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) ConfigEntry shoulderKey = ParrotsPlugin.ShoulderKey; return Input.GetKeyDown((KeyCode)((shoulderKey == null) ? 103 : ((int)shoulderKey.Value))); } private static bool GetButton() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) ConfigEntry shoulderKey = ParrotsPlugin.ShoulderKey; return Input.GetKey((KeyCode)((shoulderKey == null) ? 103 : ((int)shoulderKey.Value))); } private void Awake() { m_parrot = ((Component)this).GetComponent(); m_ai = ((Component)this).GetComponent(); m_body = ((Component)this).GetComponent(); m_collider = ((Component)this).GetComponent(); m_nview = ((Component)this).GetComponent(); m_autoMountTimer = Random.Range(20f, 60f); } private void OnEnable() { s_instances.Add(this); } private void OnDisable() { s_instances.Remove(this); } private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown if ((Object)m_nview != (Object)null && m_nview.IsValid() && !m_nview.IsOwner()) { SyncRemoteShoulder(); } else { if (m_dismountTransition) { return; } if (m_onShoulder) { Player localPlayer = Player.m_localPlayer; if ((Object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { Dismount(); } else if (GetButtonDown() && Time.frameCount != s_lastKeyFrame) { s_lastKeyFrame = Time.frameCount; ParrotsPlugin.ParrotsLogger.LogDebug((object)"[Shoulder] Dismount key pressed"); Dismount(); } } else { if ((Object)m_parrot == (Object)null || m_parrot.IsDead() || !m_parrot.IsTamed()) { return; } if (m_dismountCooldown > 0f) { m_dismountCooldown -= Time.deltaTime; } Player localPlayer2 = Player.m_localPlayer; if ((Object)localPlayer2 == (Object)null) { return; } float num = ParrotsPlugin.ShoulderHoldTime?.Value ?? 0.4f; bool button = GetButton(); bool buttonDown = GetButtonDown(); bool flag = m_buttonWasDown && !button; m_buttonWasDown = button; if (true) { if (buttonDown && Time.frameCount != s_lastKeyFrame) { m_keyState = KeyState.Pressed; m_keyDownTime = Time.time; } if (m_keyState == KeyState.Pressed && button && Time.time - m_keyDownTime >= num) { m_keyState = KeyState.HeldTriggered; s_lastKeyFrame = Time.frameCount; HandleLongPress(localPlayer2); } if (flag) { if (m_keyState == KeyState.Pressed) { s_lastKeyFrame = Time.frameCount; HandleShortPress(localPlayer2); } m_keyState = KeyState.Idle; } } else if (m_keyState != KeyState.Idle) { m_keyState = KeyState.Idle; } CheckSummonedArrival(localPlayer2); CheckAutoMount(localPlayer2); } } } private void LateUpdate() { if (m_onShoulder) { UpdateShoulderPosition(); } else if (m_dismountTransition) { UpdateDismountTransition(); } else if (m_remoteOnShoulder) { UpdateRemoteShoulderPosition(); } } private static ShoulderParrot FindClosestMountable(Player player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00c1: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_00b9: Expected O, but got Unknown ShoulderParrot result = null; float num = 5f; foreach (ShoulderParrot s_instance in s_instances) { if (!((Object)s_instance.m_parrot == (Object)null) && s_instance.m_parrot.IsTamed() && !s_instance.m_parrot.IsDead() && !s_instance.m_onShoulder && !(s_instance.m_dismountCooldown > 0f) && (!((Object)s_instance.m_ai != (Object)null) || !((Object)ParrotCompat.GetFollowTargetSafe(s_instance.m_ai) != (Object)null) || !((Object)ParrotCompat.GetFollowTargetSafe(s_instance.m_ai) != (Object)((Component)player).gameObject))) { float num2 = Vector3.Distance(((Component)s_instance).transform.position, ((Component)player).transform.position); if (num2 < num) { num = num2; result = s_instance; } } } return result; } private static ShoulderParrot FindClosestCallable(Player player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00c1: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_00b9: Expected O, but got Unknown ShoulderParrot result = null; float num = float.MaxValue; foreach (ShoulderParrot s_instance in s_instances) { if (!((Object)s_instance.m_parrot == (Object)null) && s_instance.m_parrot.IsTamed() && !s_instance.m_parrot.IsDead() && !s_instance.m_onShoulder && !(s_instance.m_dismountCooldown > 0f) && !((Object)s_instance.m_ai == (Object)null) && (!((Object)ParrotCompat.GetFollowTargetSafe(s_instance.m_ai) != (Object)null) || !((Object)ParrotCompat.GetFollowTargetSafe(s_instance.m_ai) != (Object)((Component)player).gameObject))) { float num2 = Vector3.Distance(((Component)s_instance).transform.position, ((Component)player).transform.position); if (num2 < num) { num = num2; result = s_instance; } } } return result; } private static void EnsureFollow(ShoulderParrot target, Player player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if ((Object)target.m_ai != (Object)null && (Object)ParrotCompat.GetFollowTargetSafe(target.m_ai) == (Object)null) { Tameable component = ((Component)target).GetComponent(); if ((Object)component != (Object)null) { component.Command((Humanoid)player, false); ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[Shoulder] Whistle overrides STAY → Follow (via Tameable.Command RPC)"); } else { ParrotCompat.SetFollowTargetSafe(target.m_ai, ((Component)player).gameObject); ParrotsPlugin.ParrotsLogger.LogWarning((object)"[Shoulder] Whistle follow: no Tameable found, direct set (not synced)"); } } } private void HandleShortPress(Player player) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) ShoulderParrot shoulderParrot = FindClosestCallable(player); if ((Object)shoulderParrot == (Object)null) { return; } EnsureFollow(shoulderParrot, player); if (Vector3.Distance(((Component)shoulderParrot).transform.position, ((Component)player).transform.position) < 5f && (Object)MountedParrot == (Object)null) { shoulderParrot.Mount(); return; } ParrotFlightBehavior component = ((Component)shoulderParrot).GetComponent(); if ((Object)component != (Object)null) { component.CommandLandNearby(toShoulder: false); PlayCallSFX(((Component)shoulderParrot).transform.position); ((Character)player).Message((MessageType)1, Localization.instance.Localize("$parrot_whistle"), 0, (Sprite)null); } } private void HandleLongPress(Player player) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)MountedParrot != (Object)null) { return; } ShoulderParrot shoulderParrot = FindClosestCallable(player); if ((Object)shoulderParrot == (Object)null) { return; } EnsureFollow(shoulderParrot, player); if (Vector3.Distance(((Component)shoulderParrot).transform.position, ((Component)player).transform.position) < 5f) { shoulderParrot.Mount(); } else { ParrotFlightBehavior component = ((Component)shoulderParrot).GetComponent(); if ((Object)component != (Object)null) { component.CommandLandNearby(toShoulder: true); } shoulderParrot.m_summonedToShoulder = true; } PlayCallSFX(((Component)shoulderParrot).transform.position); ((Character)player).Message((MessageType)1, Localization.instance.Localize("$parrot_call_shoulder"), 0, (Sprite)null); } private void CheckSummonedArrival(Player player) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0031: 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) if (m_summonedToShoulder && !m_onShoulder) { if ((Object)MountedParrot != (Object)null) { m_summonedToShoulder = false; } else if (Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) < 10f) { m_summonedToShoulder = false; Mount(); ((Character)player).Message((MessageType)1, Localization.instance.Localize("$parrot_perched"), 0, (Sprite)null); } } } private void PlayCallSFX(Vector3 parrotPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_005b: 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_007d: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; if ((Object)instance == (Object)null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)localPlayer != (Object)null) { GameObject prefab = instance.GetPrefab("PR_SFX_Whistle"); if ((Object)prefab != (Object)null) { Object.Instantiate(prefab, ((Component)localPlayer).transform.position, Quaternion.identity); } } ((MonoBehaviour)this).StartCoroutine(DelayedChirpResponse(parrotPosition, 0.4f)); if ((Object)m_nview != (Object)null && m_nview.IsValid()) { m_nview.InvokeRPC(ZNetView.Everybody, "RPC_PlayWhistleSFX", new object[1] { 1 }); } } private static IEnumerator DelayedChirpResponse(Vector3 position, float delay) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForSeconds(delay); ZNetScene instance = ZNetScene.instance; if (!((Object)instance == (Object)null)) { GameObject prefab = instance.GetPrefab("PR_SFX_Chirp"); if ((Object)prefab != (Object)null) { Object.Instantiate(prefab, position, Quaternion.identity); } } } private void CheckAutoMount(Player player) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_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) if ((Object)MountedParrot != (Object)null) { return; } m_autoMountTimer -= Time.deltaTime; if (m_autoMountTimer > 0f) { return; } m_autoMountTimer = Random.Range(45f, 67.5f); if (Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) > 2.5f) { return; } Vector3 val; if ((Object)m_body != (Object)null) { val = m_body.linearVelocity; if (((Vector3)(ref val)).magnitude > 0.5f) { return; } } val = ((Character)player).GetVelocity(); if (!(((Vector3)(ref val)).magnitude > 1f) && Random.value < 0.25f) { Mount(); string keyDisplayName = GetKeyDisplayName(); ((Character)player).Message((MessageType)1, "[" + keyDisplayName + "] " + Localization.instance.Localize("$parrot_perched"), 0, (Sprite)null); } } private void Mount() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Expected O, but got Unknown //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Expected O, but got Unknown //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if ((Object)localPlayer == (Object)null) { return; } ManualLogSource parrotsLogger = ParrotsPlugin.ParrotsLogger; object arg = ((Component)this).transform.position; Rigidbody body = m_body; object arg2 = (((Object)(object)body != (Object)null) ? new bool?(body.isKinematic) : ((bool?)null)); Rigidbody body2 = m_body; parrotsLogger.LogDebug((object)$"[Shoulder] Mount START - pos={arg}, isKinematic={arg2}, useGravity={(((Object)(object)body2 != (Object)null) ? new bool?(body2.useGravity) : ((bool?)null))}"); m_onShoulder = true; MountedParrot = this; m_loggedKinematicReset = false; m_loggedCharacterReset = false; if ((Object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner()) { m_nview.GetZDO().Set("PR_shoulder", true); ZNetView component = ((Component)localPlayer).GetComponent(); if ((Object)component != (Object)null && component.IsValid()) { m_nview.GetZDO().Set("PR_shoulder_owner", component.GetZDO().m_uid); } } m_shoulderBone = null; Animator componentInChildren = ((Component)localPlayer).GetComponentInChildren(); if ((Object)componentInChildren != (Object)null) { m_shoulderBone = componentInChildren.GetBoneTransform((HumanBodyBones)12); ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[Shoulder] Bone tracking: " + (((Object)m_shoulderBone != (Object)null) ? ((Object)m_shoulderBone).name : "NOT FOUND, using fallback")); } if ((Object)m_ai != (Object)null) { m_savedFollowTarget = ParrotCompat.GetFollowTargetSafe(m_ai); ((Behaviour)m_ai).enabled = false; ManualLogSource parrotsLogger2 = ParrotsPlugin.ParrotsLogger; GameObject savedFollowTarget = m_savedFollowTarget; parrotsLogger2.LogDebug((object)("[Shoulder] MonsterAI disabled (was following: " + ((((Object)(object)savedFollowTarget != (Object)null) ? ((Object)savedFollowTarget).name : null) ?? "null") + ")")); } if ((Object)m_parrot != (Object)null) { m_parrot.m_flying = false; ((Behaviour)m_parrot).enabled = false; ParrotsPlugin.ParrotsLogger.LogDebug((object)"[Shoulder] Character component disabled"); } if ((Object)m_body != (Object)null) { m_body.linearVelocity = Vector3.zero; m_body.angularVelocity = Vector3.zero; m_body.isKinematic = true; m_body.useGravity = false; ParrotsPlugin.ParrotsLogger.LogDebug((object)$"[Shoulder] Rigidbody set kinematic - isKinematic={m_body.isKinematic}, useGravity={m_body.useGravity}"); } if ((Object)m_collider != (Object)null) { ((Collider)m_collider).enabled = false; ParrotsPlugin.ParrotsLogger.LogDebug((object)"[Shoulder] CapsuleCollider disabled"); } m_savedLayer = ((Component)this).gameObject.layer; SetLayerRecursive(((Component)this).gameObject, LayerMask.NameToLayer("Ignore Raycast")); ParrotsPlugin.ParrotsLogger.LogDebug((object)$"[Shoulder] Layer changed from {m_savedLayer} to Ignore Raycast"); ParrotFlightBehavior component2 = ((Component)this).GetComponent(); if ((Object)component2 != (Object)null) { ((Behaviour)component2).enabled = false; } m_mountStartOffset = ((Component)this).transform.position - ((Component)localPlayer).transform.position; m_mountTransitionTimer = 0f; float magnitude = ((Vector3)(ref m_mountStartOffset)).magnitude; m_mountTransitionDuration = Mathf.Lerp(0.3f, 1.2f, Mathf.Clamp01(magnitude / 10f)); m_mountTransition = true; Transform val = ((Component)this).transform.Find("Visual"); if ((Object)val != (Object)null) { Animator component3 = ((Component)val).GetComponent(); if ((Object)component3 != (Object)null) { component3.SetBool("flying", true); component3.SetFloat("forward_speed", 2f); } } ManualLogSource parrotsLogger3 = ParrotsPlugin.ParrotsLogger; object arg3 = ((Component)this).transform.position; Rigidbody body3 = m_body; object arg4 = (((Object)(object)body3 != (Object)null) ? new bool?(body3.isKinematic) : ((bool?)null)); Character parrot = m_parrot; parrotsLogger3.LogDebug((object)$"[Shoulder] Mount COMPLETE - pos={arg3}, isKinematic={arg4}, Character.enabled={(((Object)(object)parrot != (Object)null) ? new bool?(((Behaviour)parrot).enabled) : ((bool?)null))}"); } private void Dismount() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0041: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Expected O, but got Unknown ParrotsPlugin.ParrotsLogger.LogDebug((object)$"[Shoulder] Dismount START - pos={((Component)this).transform.position}"); Player localPlayer = Player.m_localPlayer; float num; if (!((Object)localPlayer != (Object)null)) { num = 0f; } else { Vector3 velocity = ((Character)localPlayer).GetVelocity(); num = ((Vector3)(ref velocity)).magnitude; } float num2 = num; m_dismountToFlight = num2 > 1f; m_onShoulder = false; MountedParrot = null; m_dismountCooldown = 1f; m_summonedToShoulder = false; if ((Object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner()) { m_nview.GetZDO().Set("PR_shoulder", false); m_nview.GetZDO().Set("PR_shoulder_owner", ZDOID.None); } m_dismountStartPos = ((Component)this).transform.position; m_dismountStartRot = ((Component)this).transform.rotation; if (m_dismountToFlight) { m_dismountTargetPos = (((Object)localPlayer != (Object)null) ? (m_dismountStartPos + Vector3.up * 1.5f + ((Component)localPlayer).transform.right * 1.5f + ((Component)localPlayer).transform.forward * 0.5f) : (m_dismountStartPos + Vector3.up * 1.5f)); } else { Vector3 val = (((Object)localPlayer != (Object)null) ? (((Component)localPlayer).transform.position + ((Component)localPlayer).transform.right * 1.5f) : (((Component)this).transform.position + Vector3.right * 1.5f)); float y = (((Object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.GetGroundHeight(val) : 0f); val.y = y; m_dismountTargetPos = val; } m_dismountTransitionTimer = 0f; m_dismountTransition = true; Transform val2 = ((Component)this).transform.Find("Visual"); if ((Object)val2 != (Object)null) { Animator component = ((Component)val2).GetComponent(); if ((Object)component != (Object)null) { component.SetBool("flying", true); component.SetFloat("forward_speed", m_dismountToFlight ? 3f : 1f); } } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[Shoulder] Dismount transition: " + (m_dismountToFlight ? "TAKEOFF" : "HOP")); } private void UpdateDismountTransition() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || (Object)m_parrot == (Object)null || m_parrot.IsDead()) { FinalizeDismount(); return; } float num = (m_dismountToFlight ? 0.4f : 0.6f); float num2 = (m_dismountToFlight ? 0.5f : 0.4f); m_dismountTransitionTimer += Time.deltaTime; float num3 = Mathf.Clamp01(m_dismountTransitionTimer / num); float num4 = num3 * num3 * (3f - 2f * num3); float num5 = 4f * num3 * (1f - num3) * num2; Vector3 position = Vector3.Lerp(m_dismountStartPos, m_dismountTargetPos, num4); position.y += num5; ((Component)this).transform.position = position; Vector3 val = m_dismountTargetPos - m_dismountStartPos; if (m_dismountToFlight) { val.y *= 0.3f; } if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized); ((Component)this).transform.rotation = Quaternion.Slerp(m_dismountStartRot, val2, num4); } if (num3 >= 1f) { FinalizeDismount(); } } private void FinalizeDismount() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) m_dismountTransition = false; m_shoulderBone = null; if ((Object)m_parrot != (Object)null) { ((Behaviour)m_parrot).enabled = true; } if ((Object)m_ai != (Object)null) { ((Behaviour)m_ai).enabled = true; ParrotCompat.SetFollowTargetSafe(m_ai, m_savedFollowTarget); } if ((Object)m_body != (Object)null) { m_body.isKinematic = false; m_body.useGravity = true; } if ((Object)m_collider != (Object)null) { ((Collider)m_collider).enabled = true; } SetLayerRecursive(((Component)this).gameObject, m_savedLayer); ParrotFlightBehavior component = ((Component)this).GetComponent(); if ((Object)component != (Object)null) { ((Behaviour)component).enabled = true; } if (m_dismountToFlight) { if ((Object)m_parrot != (Object)null) { m_parrot.m_flying = true; } if ((Object)m_body != (Object)null) { Player localPlayer = Player.m_localPlayer; Vector3 val; if (!((Object)localPlayer != (Object)null)) { val = Vector3.up; } else { Vector3 val2 = ((Component)localPlayer).transform.forward * 0.5f + Vector3.up + ((Component)localPlayer).transform.right * 0.3f; val = ((Vector3)(ref val2)).normalized; } Vector3 val3 = val; float num = (((Object)m_parrot != (Object)null) ? m_parrot.m_flySlowSpeed : 7f); m_body.linearVelocity = val3 * num; } if ((Object)component != (Object)null) { component.CommandTakeoff(); } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[Shoulder] Dismount TAKEOFF complete — entering orbit"); return; } if ((Object)m_parrot != (Object)null) { m_parrot.m_flying = false; } Transform val4 = ((Component)this).transform.Find("Visual"); if ((Object)val4 != (Object)null) { Animator component2 = ((Component)val4).GetComponent(); if ((Object)component2 != (Object)null) { component2.SetBool("flying", false); component2.SetFloat("forward_speed", 0f); } } if ((Object)component != (Object)null) { component.SuppressTakeoff(Random.Range(3f, 6f)); } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[Shoulder] Dismount HOP complete — grounded"); } private void UpdateShoulderPosition() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019a: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if ((Object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { Dismount(); return; } if ((Object)m_body != (Object)null && !m_body.isKinematic) { if (!m_loggedKinematicReset) { ParrotsPlugin.ParrotsLogger.LogWarning((object)"[Shoulder] Kinematic was reset by external system, re-applying."); m_loggedKinematicReset = true; } m_body.linearVelocity = Vector3.zero; m_body.angularVelocity = Vector3.zero; m_body.isKinematic = true; m_body.useGravity = false; } if ((Object)m_parrot != (Object)null && ((Behaviour)m_parrot).enabled) { if (!m_loggedCharacterReset) { ParrotsPlugin.ParrotsLogger.LogWarning((object)"[Shoulder] Character was re-enabled by external system, disabling."); m_loggedCharacterReset = true; } ((Behaviour)m_parrot).enabled = false; } Vector3 val = ComputeShoulderPos(localPlayer); if (m_mountTransition) { m_mountTransitionTimer += Time.deltaTime; float num = Mathf.Clamp01(m_mountTransitionTimer / m_mountTransitionDuration); float num2 = num * num * (3f - 2f * num); float num3 = 4f * num * (1f - num) * 0.5f; Vector3 position = Vector3.Lerp(((Component)localPlayer).transform.position + m_mountStartOffset, val, num2); position.y += num3; ((Component)this).transform.position = position; ((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, ((Component)localPlayer).transform.rotation, num2); if (!(num >= 1f)) { return; } m_mountTransition = false; Transform val2 = ((Component)this).transform.Find("Visual"); if ((Object)val2 != (Object)null) { Animator component = ((Component)val2).GetComponent(); if ((Object)component != (Object)null) { component.SetFloat("forward_speed", 0f); component.SetBool("flying", false); } } } else { ((Component)this).transform.position = val; ((Component)this).transform.rotation = ((Component)localPlayer).transform.rotation; } } private Vector3 ComputeShoulderPos(Player player) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return ComputeShoulderPosForPlayer(player, m_shoulderBone); } private Vector3 ComputeShoulderPosForPlayer(Player player, Transform shoulderBone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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 ((Object)shoulderBone != (Object)null) { return shoulderBone.position + shoulderBone.right * ShoulderLocalOffset.x + shoulderBone.up * ShoulderLocalOffset.y + shoulderBone.forward * ShoulderLocalOffset.z; } return ((Component)player).transform.position + ((Component)player).transform.up * 1.62f + ((Component)player).transform.right * 0.27f + ((Component)player).transform.forward * -0.03f; } private static Player FindPlayerByZDOID(ZDOID playerZDOID) { //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_0022: 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_0035: Expected O, but got Unknown if (playerZDOID == ZDOID.None) { return null; } ZNetScene instance = ZNetScene.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.FindInstance(playerZDOID) : null); if ((Object)val != (Object)null) { return val.GetComponent(); } return null; } private void SyncRemoteShoulder() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0048: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown if ((Object)m_nview == (Object)null || !m_nview.IsValid()) { return; } bool flag = m_nview.GetZDO().GetBool("PR_shoulder", false); ZDOID zDOID = m_nview.GetZDO().GetZDOID("PR_shoulder_owner"); if (flag && !m_remoteOnShoulder) { m_remoteOwnerPlayer = FindPlayerByZDOID(zDOID); if (!((Object)m_remoteOwnerPlayer != (Object)null)) { return; } m_remoteOnShoulder = true; m_remoteShoulderBone = null; Animator componentInChildren = ((Component)m_remoteOwnerPlayer).GetComponentInChildren(); if ((Object)componentInChildren != (Object)null) { m_remoteShoulderBone = componentInChildren.GetBoneTransform((HumanBodyBones)12); } if ((Object)m_collider != (Object)null) { ((Collider)m_collider).enabled = false; } m_savedLayer = ((Component)this).gameObject.layer; SetLayerRecursive(((Component)this).gameObject, LayerMask.NameToLayer("Ignore Raycast")); if ((Object)m_body != (Object)null) { m_body.linearVelocity = Vector3.zero; m_body.angularVelocity = Vector3.zero; m_body.isKinematic = true; m_body.useGravity = false; } Transform val = ((Component)this).transform.Find("Visual"); if ((Object)val != (Object)null) { Animator component = ((Component)val).GetComponent(); if ((Object)component != (Object)null) { component.SetBool("flying", false); component.SetFloat("forward_speed", 0f); } } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[Shoulder] Remote mount: parrot on " + m_remoteOwnerPlayer.GetPlayerName() + "'s shoulder"); } else if (!flag && m_remoteOnShoulder) { ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[Shoulder] Remote dismount"); RemoteUnmount(); } } private void UpdateRemoteShoulderPosition() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)m_remoteOwnerPlayer == (Object)null || ((Character)m_remoteOwnerPlayer).IsDead()) { RemoteUnmount(); return; } ((Component)this).transform.position = ComputeShoulderPosForPlayer(m_remoteOwnerPlayer, m_remoteShoulderBone); ((Component)this).transform.rotation = ((Component)m_remoteOwnerPlayer).transform.rotation; if ((Object)m_body != (Object)null && !m_body.isKinematic) { m_body.linearVelocity = Vector3.zero; m_body.isKinematic = true; m_body.useGravity = false; } } private void RemoteUnmount() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown m_remoteOnShoulder = false; m_remoteOwnerPlayer = null; m_remoteShoulderBone = null; if ((Object)m_collider != (Object)null) { ((Collider)m_collider).enabled = true; } SetLayerRecursive(((Component)this).gameObject, m_savedLayer); if ((Object)m_body != (Object)null) { m_body.isKinematic = false; m_body.useGravity = true; } } private static void SetLayerRecursive(GameObject go, int layer) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) go.layer = layer; foreach (Transform item in go.transform) { SetLayerRecursive(((Component)item).gameObject, layer); } } private void OnDestroy() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00af: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown if (m_remoteOnShoulder) { RemoteUnmount(); } if (m_onShoulder) { if ((Object)m_parrot != (Object)null) { ((Behaviour)m_parrot).enabled = true; } if ((Object)m_collider != (Object)null) { ((Collider)m_collider).enabled = true; } if ((Object)m_body != (Object)null) { m_body.isKinematic = false; m_body.useGravity = true; } SetLayerRecursive(((Component)this).gameObject, m_savedLayer); m_onShoulder = false; if ((Object)MountedParrot == (Object)this) { MountedParrot = null; } } else if (m_dismountTransition) { m_dismountTransition = false; if ((Object)m_parrot != (Object)null) { ((Behaviour)m_parrot).enabled = true; } if ((Object)m_ai != (Object)null) { ((Behaviour)m_ai).enabled = true; } if ((Object)m_collider != (Object)null) { ((Collider)m_collider).enabled = true; } if ((Object)m_body != (Object)null) { m_body.isKinematic = false; m_body.useGravity = true; } SetLayerRecursive(((Component)this).gameObject, m_savedLayer); } } } [HarmonyPatch(typeof(Tameable), "Awake")] internal static class Tameable_Awake_ParrotTaming { private static EffectList MakeEffects(params GameObject[] prefabs) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0041: 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_0053: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown List list = new List(); foreach (GameObject val in prefabs) { if ((Object)val != (Object)null) { list.Add(new EffectData { m_prefab = val, m_enabled = true }); } } return new EffectList { m_effectPrefabs = list.ToArray() }; } private static void Postfix(Tameable __instance) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Expected O, but got Unknown //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Expected O, but got Unknown //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Expected O, but got Unknown //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Expected O, but got Unknown if (!((Object)((Component)__instance).gameObject).name.StartsWith("PR_Parrot1")) { return; } __instance.m_tamingTime = ParrotsPlugin.TamingTime?.Value ?? 120f; __instance.m_fedDuration = 600f; __instance.m_commandable = true; ZNetScene instance = ZNetScene.instance; if ((Object)instance != (Object)null) { GameObject prefab = instance.GetPrefab("PR_SFX_Squawk"); GameObject prefab2 = instance.GetPrefab("PR_SFX_Chirp"); GameObject prefab3 = instance.GetPrefab("fx_creature_tamed"); GameObject prefab4 = instance.GetPrefab("vfx_boar_love"); __instance.m_tamedEffect = MakeEffects(prefab3, prefab); __instance.m_sootheEffect = MakeEffects(prefab3, prefab2); __instance.m_petEffect = MakeEffects(prefab4, prefab2); ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "Parrot Tameable VFX: tamed=" + ((((Object)(object)prefab3 != (Object)null) ? ((Object)prefab3).name : null) ?? "none") + ", pet=" + ((((Object)(object)prefab4 != (Object)null) ? ((Object)prefab4).name : null) ?? "none") + ", SFX=squawk+chirp"); } ConfigEntry breedingEnabled = ParrotsPlugin.BreedingEnabled; bool flag = false; Procreation val = ((Component)__instance).GetComponent(); if (breedingEnabled != null && breedingEnabled.Value) { if ((Object)val == (Object)null) { val = ((Component)__instance).gameObject.AddComponent(); flag = true; ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, "[FehuParrots] Added vanilla Procreation component."); } val.m_updateInterval = 10f; val.m_totalCheckRange = 20f; val.m_maxCreatures = ParrotsPlugin.MaxParrotsNearby?.Value ?? 4; val.m_partnerCheckRange = 10f; val.m_pregnancyChance = 0.33f; val.m_pregnancyDuration = ParrotsPlugin.PregnancyDuration?.Value ?? 600f; val.m_requiredLovePoints = 2; val.m_spawnOffset = 1f; val.m_minOffspringLevel = 1; GameObject val2 = (((Object)(object)instance != (Object)null) ? instance.GetPrefab("PR_Parrot1") : null); if ((Object)val2 != (Object)null) { val.m_offspring = val2; } GameObject val3 = (((Object)(object)instance != (Object)null) ? instance.GetPrefab("vfx_boar_love") : null); if ((Object)val3 != (Object)null) { Procreation val4 = val; EffectList val5 = new EffectList(); val5.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = val3, m_enabled = true } }; val4.m_loveEffects = val5; } } ParrotDebugLog.Info(ParrotsPlugin.ParrotsLogger, string.Format("[FehuParrots] PR_Parrot1 hasTameable={0} hasProcreation={1} ProcreationAdded={2} FoodItems={3} PregnancyDuration={4}", (Object)__instance != (Object)null, (Object)val != (Object)null, flag, string.Join(",", ParrotsPlugin.FoodItemNames), ParrotsPlugin.PregnancyDuration?.Value.ToString() ?? "NULL")); if ((Object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } ParrotBreedingAudit.LogParrot(__instance); ParrotsPlugin.ParrotsLogger.LogDebug((object)$"Parrot Tameable: taming={__instance.m_tamingTime}s, breeding={ParrotsPlugin.BreedingEnabled?.Value}, shoulder-ready"); } } [HarmonyPatch(typeof(Tameable), "GetHoverText")] internal static class Tameable_GetHoverText_ShoulderHint { private static void Postfix(Tameable __instance, ref string __result) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown if (!((Object)((Component)__instance).gameObject).name.StartsWith("PR_Parrot1")) { return; } Character component = ((Component)__instance).GetComponent(); if (!((Object)component == (Object)null) && component.IsTamed()) { string keyDisplayName = ShoulderParrot.GetKeyDisplayName(); ShoulderParrot component2 = ((Component)__instance).GetComponent(); if ((Object)component2 != (Object)null && component2.IsOnShoulder) { __result = __result + "\n[" + keyDisplayName + "] " + Localization.instance.Localize("$parrot_dismount"); return; } __result = __result + "\n[" + keyDisplayName + "] " + Localization.instance.Localize("$parrot_call_down") + " | " + Localization.instance.Localize("$parrot_hold") + " [" + keyDisplayName + "] " + Localization.instance.Localize("$parrot_shoulder"); } } } internal static class ZInput_Load_RegisterParrotButton { } } namespace FehuAssets.Airships { public sealed class FehuAirshipAssetLoader { private const string ResourceName = "FehuAssets.Airships.Resources.airshipplus"; private const string CompatibilityAssemblyName = "AirShipPlus"; private const string CompatibilityResourceName = "FehuAssets.Airships.Compatibility.AirShipPlus.dll"; private static bool _compatibilityAssemblyLoaded; private AssetBundle? _bundle; public AssetBundle Bundle { get { if ((Object)(object)_bundle != (Object)null) { return _bundle; } EnsureCompatibilityAssemblyLoaded(); using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FehuAssets.Airships.Resources.airshipplus"); if (stream == null) { throw new InvalidOperationException("Missing embedded AirShipPlus resource 'FehuAssets.Airships.Resources.airshipplus'."); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); _bundle = AssetBundle.LoadFromMemory(memoryStream.ToArray()) ?? throw new InvalidOperationException("Unity could not load the embedded airshipplus AssetBundle."); return _bundle; } } public GameObject LoadPrefab(string assetPath) { return Bundle.LoadAsset(assetPath) ?? throw new InvalidOperationException("Airship bundle prefab not found: " + assetPath); } private static void EnsureCompatibilityAssemblyLoaded() { if (_compatibilityAssemblyLoaded) { return; } if (AppDomain.CurrentDomain.GetAssemblies().Any((Assembly assembly) => string.Equals(assembly.GetName().Name, "AirShipPlus", StringComparison.Ordinal))) { _compatibilityAssemblyLoaded = true; return; } using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FehuAssets.Airships.Compatibility.AirShipPlus.dll"); if (stream == null) { throw new InvalidOperationException("Missing embedded AirShipPlus compatibility assembly resource 'FehuAssets.Airships.Compatibility.AirShipPlus.dll'."); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Assembly.Load(memoryStream.ToArray()); _compatibilityAssemblyLoaded = true; } public void LogGameObjectAssets(ManualLogSource log) { if (!FehuAirshipDebug.Enabled) { return; } string[] allAssetNames = Bundle.GetAllAssetNames(); foreach (string text in allAssetNames) { GameObject val = Bundle.LoadAsset(text); if (!((Object)(object)val == (Object)null)) { FehuAirshipDebug.LogInfo(log, "[FehuAirships] Asset='" + text + "' GameObject='" + ((Object)val).name + "' " + $"ZNetView={(Object)(object)val.GetComponentInChildren(true) != (Object)null} " + $"Piece={(Object)(object)val.GetComponentInChildren(true) != (Object)null} " + $"ItemDrop={(Object)(object)val.GetComponentInChildren(true) != (Object)null} " + $"WearNTear={(Object)(object)val.GetComponentInChildren(true) != (Object)null} " + $"Rigidbody={(Object)(object)val.GetComponentInChildren(true) != (Object)null}"); } } } } public sealed class FehuAirshipConfigHolder { public ConfigEntry Enabled { get; } public ConfigEntry EnableFehuBalloon { get; } public ConfigEntry EnableFehuAirship { get; } public ConfigEntry EnableFehuSkyCaravel { get; } public ConfigEntry EnableFehuRunebroom { get; } public ConfigEntry EnableCoreRecipes { get; } public ConfigEntry EnableAirshipDebugLogs { get; } public ConfigEntry FuelInterval { get; } public ConfigEntry LiftForce { get; } public ConfigEntry CruiseForce { get; } public ConfigEntry TurnSpeed { get; } public FehuAirshipConfigHolder(ConfigFile config) { //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Expected O, but got Unknown Enabled = config.Bind("Airships", "Enabled", true, "Register Fehu airships and Ancient Core fuel."); EnableFehuBalloon = config.Bind("Airships", "EnableFehuBalloon", true, "Expose Fehu Balloon build recipe. Safe prefab registration remains enabled for existing worlds."); EnableFehuAirship = config.Bind("Airships", "EnableFehuAirship", true, "Expose Fehu Airship build recipe. Safe prefab registration remains enabled for existing worlds."); EnableFehuSkyCaravel = config.Bind("Airships", "EnableFehuSkyCaravel", true, "Expose Fehu Sky Caravel build recipe. Safe prefab registration remains enabled for existing worlds."); EnableFehuRunebroom = config.Bind("Airships", "EnableFehuRunebroom", true, "Expose Fehu Runebroom build recipe. Safe prefab registration remains enabled for existing worlds."); EnableCoreRecipes = config.Bind("Airships", "EnableCoreRecipes", true, "Expose Ancient/Warpstone/Mithril/Meteorite Core crafting recipes."); EnableAirshipDebugLogs = config.Bind("Debug", "EnableAirshipDebugLogs", false, "Enable verbose Fehu airship startup/runtime diagnostic logs."); FehuAirshipDebug.Configure(EnableAirshipDebugLogs); FuelInterval = config.Bind("Airships", "Fuel consumption interval", 30f, new ConfigDescription("Seconds of piloted flight per Ancient Core.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 300f), Array.Empty())); LiftForce = config.Bind("Airships", "Lift force", 18f, new ConfigDescription("Vertical force while piloting a fueled airship.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); CruiseForce = config.Bind("Airships", "Cruise force", 10f, new ConfigDescription("Forward and reverse force while piloting.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); TurnSpeed = config.Bind("Airships", "Turn speed", 55f, new ConfigDescription("Yaw speed while piloting.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 180f), Array.Empty())); } public bool IsVehicleRecipeEnabled(string prefabName) { return prefabName switch { "Fehu_AirShipOne" => EnableFehuBalloon.Value, "Fehu_AirShipTwo" => EnableFehuAirship.Value, "Fehu_AirShipThree" => EnableFehuSkyCaravel.Value, "Fehu_MagicBroom" => EnableFehuRunebroom.Value, _ => true, }; } public int FuelCapacity(string prefabName) { return prefabName switch { "Fehu_AirShipOne" => 300, "Fehu_AirShipTwo" => 500, "Fehu_AirShipThree" => 500, "Fehu_MagicBroom" => 200, _ => 300, }; } } public sealed class FehuAirshipControlsPilot : MonoBehaviour, Hoverable, Interactable, IDoodadController { private const string PilotKey = "fehu_airship_pilot"; private const string RunebroomSeatName = "Fehu_Runebroom_RiderSeat"; private const string RunebroomAttachAnimation = "attach_chair"; private static readonly Vector3 RunebroomSeatLocalPosition = new Vector3(0f, -0.26f, 0.25f); private static readonly Vector3 RunebroomSeatLocalRotation = new Vector3(0f, 0f, 0f); private static readonly Vector3 RunebroomDetachOffset = new Vector3(0f, 0.5f, 0f); private ZNetView? _nview; private FehuAirshipFuelSystem? _fuel; private Player? _pilot; private Transform? _runebroomSeat; private bool _runebroomSeatFallbackCreated; private Vector3 _controlMove; private bool _controlRun; private bool _controlBlock; public bool IsLocalPilot { get { if ((Object)(object)_pilot != (Object)null) { return (Object)(object)_pilot == (Object)(object)Player.m_localPlayer; } return false; } } public float ForwardInput => Mathf.Clamp(_controlMove.z, -1f, 1f); public float TurnInput => Mathf.Clamp(_controlMove.x, -1f, 1f); public bool RunInput => _controlRun; public bool BlockInput => _controlBlock; public void Configure(FehuAirshipFuelSystem fuel) { _fuel = fuel; } private void Awake() { _nview = ((Component)this).GetComponent(); if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } } private void Start() { if (_nview == null) { _nview = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } } public bool Interact(Humanoid user, bool hold, bool alt) { if (_nview == null) { _nview = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } Player val = (Player)(object)((user is Player) ? user : null); string text = ((val != null) ? val.GetPlayerName() : (((Object)(object)user != (Object)null) ? ((Object)user).name : "NULL")); Player val2 = (Player)(object)((user is Player) ? user : null); long num = ((val2 != null) ? val2.GetPlayerID() : 0); bool key = Input.GetKey((KeyCode)304); bool key2 = Input.GetKey((KeyCode)303); bool flag = alt || key || key2; FehuAirshipDebug.Log($"[FehuAirships] Interact vehicle={((Object)((Component)this).gameObject).name} user={text}/{num} hold={hold} alt={alt} leftShift={key} rightShift={key2} shiftHeld={flag} fuel={(Object)(object)_fuel != (Object)null} nview={(Object)(object)_nview != (Object)null}"); if (!hold) { Player val3 = (Player)(object)((user is Player) ? user : null); if (val3 != null) { if (flag) { FehuAirshipDebug.Log($"[FehuAirships] Interact chose fuel vehicle={((Object)((Component)this).gameObject).name} player={val3.GetPlayerName()}/{val3.GetPlayerID()}"); if ((Object)(object)_fuel != (Object)null) { return _fuel.AddFuel(val3); } return false; } FehuAirshipDebug.Log($"[FehuAirships] Interact chose pilot vehicle={((Object)((Component)this).gameObject).name} player={val3.GetPlayerName()}/{val3.GetPlayerID()}"); return StartPilot(val3); } } return false; } public string GetHoverText() { if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } string text = _fuel?.StatusText() ?? "Ancient Core: 0/300"; return "Fehu Airship Controls\n" + text + "\n[E] Pilot\n[Shift+E] Fill fuel tank"; } public string GetHoverName() { return "Fehu Airship Controls"; } public Component GetControlledComponent() { return (Component)(object)this; } public bool IsValid() { if ((Object)(object)this != (Object)null && (Object)(object)((Component)this).gameObject != (Object)null) { return ((Behaviour)this).isActiveAndEnabled; } return false; } public Vector3 GetPosition() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!IsRunebroom()) { return ((Component)this).transform.position; } return EnsureRunebroomSeat().position; } public void ApplyControlls(Vector3 moveDir, Vector3 lookDir, bool run, bool autoRun, bool block) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _controlMove = moveDir; _controlRun = run; _controlBlock = block; } public void OnUseStop(Player player) { if ((Object)(object)_pilot == (Object)(object)player) { DetachRunebroomPilot(player); FehuAirshipDebug.Log($"[FehuAirships] Pilot stopped vehicle={((Object)((Component)this).gameObject).name} player={player.GetPlayerName()}/{player.GetPlayerID()}"); _pilot = null; if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null && _nview.IsOwner()) { _nview.GetZDO().Set("fehu_airship_pilot", 0L); } } } public bool UseItem(Humanoid user, ItemData item) { if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } string text = ((item?.m_shared != null) ? item.m_shared.m_name : "NULL"); string text2 = (((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : "NULL"); bool flag = FehuAirshipFuelSystem.IsFuelItem(item); FehuAirshipDebug.Log($"[FehuAirships] UseItem vehicle={((Object)((Component)this).gameObject).name} item={text} prefab={text2} isFuel={flag} fuel={(Object)(object)_fuel != (Object)null}"); Player val = (Player)(object)((user is Player) ? user : null); if (val == null || !flag) { return false; } if ((Object)(object)_fuel == (Object)null) { return true; } return _fuel.AddFuel(val); } private bool StartPilot(Player player) { if (_nview == null) { _nview = ((Component)this).GetComponent(); } if ((Object)(object)_nview != (Object)null && _nview.IsValid() && !_nview.IsOwner()) { _nview.ClaimOwnership(); } _pilot = player; bool flag = false; try { player.StartDoodadControl((IDoodadController)(object)this); flag = true; } catch (Exception ex) { Debug.LogWarning((object)$"[FehuAirships] StartDoodadControl failed vehicle={((Object)((Component)this).gameObject).name} player={player.GetPlayerName()}/{player.GetPlayerID()} error={ex.GetType().Name}: {ex.Message}"); } bool flag2 = false; if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null && _nview.IsOwner()) { _nview.GetZDO().Set("fehu_airship_pilot", player.GetPlayerID()); flag2 = true; } AttachRunebroomPilot(player); FehuAirshipDebug.Log($"[FehuAirships] Pilot started vehicle={((Object)((Component)this).gameObject).name} player={player.GetPlayerName()}/{player.GetPlayerID()} doodadControl={flag} zdoPilotSet={flag2}"); return true; } private bool IsRunebroom() { string name = ((Object)((Component)this).gameObject).name; if (name.IndexOf("MagicBroom", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Runebroom", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private Transform EnsureRunebroomSeat() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if ((Object)(object)_runebroomSeat != (Object)null) { return _runebroomSeat; } _runebroomSeat = FindExistingRunebroomSeat(); if ((Object)(object)_runebroomSeat == (Object)null) { GameObject val = new GameObject("Fehu_Runebroom_RiderSeat"); val.transform.SetParent(((Component)this).transform, false); _runebroomSeat = val.transform; _runebroomSeatFallbackCreated = true; } Vector3 localPosition = _runebroomSeat.localPosition; Vector3 localEulerAngles = _runebroomSeat.localEulerAngles; _runebroomSeat.localPosition = RunebroomSeatLocalPosition; _runebroomSeat.localEulerAngles = RunebroomSeatLocalRotation; Debug.Log((object)$"[FehuAirships] Runebroom seat path={GetTransformPath(_runebroomSeat)} previousLocalPosition={localPosition} previousLocalRotation={localEulerAngles} localPosition={_runebroomSeat.localPosition} localRotation={_runebroomSeat.localEulerAngles}"); return _runebroomSeat; } private Transform? FindExistingRunebroomSeat() { string[] array = new string[9] { "Fehu_Runebroom_RiderSeat", "attach", "rider", "seat", "chair", "sit", "pilot", "saddle", "vassoura" }; _ = new string[2] { "broom", "controls" }; Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); string[] array2 = array; foreach (string value in array2) { Transform[] array3 = componentsInChildren; foreach (Transform val in array3) { if (!((Object)(object)val == (Object)(object)((Component)this).transform) && ((Object)val).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return val; } } } return null; } private void AttachRunebroomPilot(Player player) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) if (!IsRunebroom()) { return; } Transform val = EnsureRunebroomSeat(); try { ((Character)player).AttachStart(val, ((Component)this).gameObject, true, false, true, "attach_chair", RunebroomDetachOffset, (Transform)null); Vector3 val2 = val.InverseTransformPoint(((Component)player).transform.position); FehuAirshipDebug.Log($"[FehuAirships] Runebroom pilot attach success vehicle={((Object)((Component)this).gameObject).name} player={player.GetPlayerName()}/{player.GetPlayerID()} seatPath={GetTransformPath(val)} fallbackSeat={_runebroomSeatFallbackCreated} playerRelativeToSeat={val2}"); } catch (Exception ex) { Debug.LogWarning((object)$"[FehuAirships] Runebroom pilot attach failed vehicle={((Object)((Component)this).gameObject).name} player={player.GetPlayerName()}/{player.GetPlayerID()} seatPath={GetTransformPath(val)} error={ex.GetType().Name}: {ex.Message}"); } } private void DetachRunebroomPilot(Player player) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!IsRunebroom()) { return; } try { ((Character)player).AttachStop(); Vector3 val = ((Component)this).transform.TransformPoint(new Vector3(0.8f, 0.6f, 0f)); ((Component)player).transform.position = val; FehuAirshipDebug.Log($"[FehuAirships] Runebroom pilot detach success vehicle={((Object)((Component)this).gameObject).name} player={player.GetPlayerName()}/{player.GetPlayerID()} safePosition={val}"); } catch (Exception ex) { Debug.LogWarning((object)$"[FehuAirships] Runebroom pilot detach failed vehicle={((Object)((Component)this).gameObject).name} player={player.GetPlayerName()}/{player.GetPlayerID()} error={ex.GetType().Name}: {ex.Message}"); } } private static string GetTransformPath(Transform target) { if ((Object)(object)target == (Object)null) { return "NULL"; } string text = ((Object)target).name; Transform parent = target.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } } internal static class FehuAirshipDebug { private static ConfigEntry? _enabled; public static bool Enabled => _enabled?.Value ?? false; public static void Configure(ConfigEntry enabled) { _enabled = enabled; } public static void Log(string message) { if (Enabled) { Debug.Log((object)message); } } public static void LogInfo(ManualLogSource log, string message) { if (Enabled) { log.LogInfo((object)message); } } } public sealed class FehuAirshipFuelSystem : MonoBehaviour { private const string FuelKey = "fehu_airship_fuel"; private const string FuelPrefabName = "FloatingYellowOrb"; private const string FuelDisplayName = "Ancient Core"; private const float DefaultFuelInterval = 30f; private ZNetView? _nview; private FehuAirshipConfigHolder? _config; private FehuAirshipControlsPilot? _pilot; private int _capacity; private float _fuel; private float _timer; private ManualLogSource? _log; public bool HasFuel => _fuel > 0.01f; public int CurrentFuel => Mathf.FloorToInt(_fuel); public int Capacity => EnsureCapacity(); public void Configure(FehuAirshipConfigHolder config, FehuAirshipControlsPilot pilot, int capacity, ManualLogSource log) { _config = config; _pilot = pilot; _capacity = ((capacity > 0) ? capacity : DefaultCapacityFor(((Object)((Component)this).gameObject).name)); _log = log; } private void Awake() { _nview = ((Component)this).GetComponent(); if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } EnsureCapacity(); } private void Start() { EnsureCapacity(); if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null) { _fuel = _nview.GetZDO().GetFloat("fehu_airship_fuel", 0f); } FehuAirshipDebug.Log($"[FehuAirships] FuelSystem init prefab='{((Object)((Component)this).gameObject).name}' maxFuel={_capacity} current={CurrentFuel} nview={(Object)(object)_nview != (Object)null} pilot={(Object)(object)_pilot != (Object)null}"); } private void Update() { if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } if (!((Object)(object)_pilot == (Object)null) && _pilot.IsLocalPilot && HasFuel) { _timer += Time.deltaTime; float num = _config?.FuelInterval.Value ?? 30f; if (_timer >= num) { _timer = 0f; SetFuel(_fuel - 1f); } } } public bool AddFuel(Player player) { int num = EnsureCapacity(); bool key = Input.GetKey((KeyCode)304); bool key2 = Input.GetKey((KeyCode)303); Inventory inventory = ((Humanoid)player).GetInventory(); ItemData val = ((IEnumerable)inventory.GetAllItems()).FirstOrDefault((Func)IsFuelItem); int num2 = inventory.GetAllItems().Count((ItemData item) => (Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == "FloatingYellowOrb"); int num3 = inventory.GetAllItems().Count((ItemData item) => IsFuelDisplayName(item, "Ancient Core")); int num4 = inventory.GetAllItems().Count((ItemData item) => IsFuelDisplayName(item, "Ancient Orb")); int num5 = inventory.GetAllItems().Count((ItemData item) => IsFuelDisplayName(item, "Golden Core")); string text = ((val == null) ? "none" : DescribeFuelItem(val)); LogInventoryFuelDebug(inventory); FehuAirshipDebug.Log(string.Format("[FehuAirships] Fuel interact prefab='{0}' player='{1}' id={2} leftShift={3} rightShift={4} expectedPrefab='{5}' prefabCount={6} ancientCoreCount={7} ancientOrbCount={8} goldenCoreCount={9} matched='{10}' current={11} max={12}", ((Object)((Component)this).gameObject).name, player.GetPlayerName(), player.GetPlayerID(), key, key2, "FloatingYellowOrb", num2, num3, num4, num5, text, CurrentFuel, num)); if (num <= 0) { Debug.LogWarning((object)"[FehuAirships] Fuel result=blocked reason=invalid-capacity."); return true; } if (CurrentFuel >= num) { ((Character)player).Message((MessageType)2, "Fehu fuel tank is full.", 0, (Sprite)null); FehuAirshipDebug.Log("[FehuAirships] Fuel result=tank-full."); return true; } if (val == null) { ((Character)player).Message((MessageType)2, "You need Ancient Core.", 0, (Sprite)null); FehuAirshipDebug.Log("[FehuAirships] Fuel result=no-fuel-item."); return true; } if ((Object)(object)_nview != (Object)null && _nview.IsValid() && !_nview.IsOwner()) { _nview.ClaimOwnership(); } int currentFuel = CurrentFuel; inventory.RemoveOneItem(val); SetFuel(Mathf.Min((float)num, _fuel + 1f)); ((Character)player).Message((MessageType)2, "Added Ancient Core fuel.", 0, (Sprite)null); FehuAirshipDebug.Log($"[FehuAirships] Fuel result=added amount=1 item='{text}' oldFuel={currentFuel} newFuel={CurrentFuel} max={num}."); return true; } public string StatusText() { int num = EnsureCapacity(); return string.Format("{0}: {1}/{2}", "Ancient Core", CurrentFuel, num); } public static bool IsFuelItem(ItemData? item) { if (item == null) { return false; } if ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == "FloatingYellowOrb") { return true; } return IsYellowFuelName(item.m_shared?.m_name); } private static bool IsYellowFuelName(string? name) { if (!(name == "Ancient Core") && !(name == "Ancient Orb")) { return name == "Golden Core"; } return true; } private static void LogInventoryFuelDebug(Inventory inventory) { int num = 0; foreach (ItemData allItem in inventory.GetAllItems()) { bool flag = IsFuelItem(allItem); if (flag) { num += allItem.m_stack; } string text = ((allItem.m_shared != null) ? allItem.m_shared.m_name : "NULL"); string text2 = text; string text3 = (((Object)(object)allItem.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : "NULL"); FehuAirshipDebug.Log($"[FehuAirships] Fuel inventory item shared='{text}' localized='{text2}' dropPrefab='{text3}' stack={allItem.m_stack} match={flag}"); } FehuAirshipDebug.Log($"[FehuAirships] Fuel inventory valid Ancient Core count={num}"); } private int EnsureCapacity() { if (_capacity <= 0) { _capacity = DefaultCapacityFor(((Object)((Component)this).gameObject).name); } return _capacity; } private static int DefaultCapacityFor(string prefabName) { if (prefabName != null) { int length = prefabName.Length; if (length <= 12) { if (length != 10) { if (length == 12 && prefabName == "AirShipThree") { goto IL_00fc; } } else { char c = prefabName[7]; if (c != 'O') { if (c != 'T') { if (c == 'o' && prefabName == "MagicBroom") { goto IL_0104; } } else if (prefabName == "AirShipTwo") { goto IL_00f4; } } else if (prefabName == "AirShipOne") { goto IL_00ec; } } } else if (length != 15) { if (length == 17 && prefabName == "Fehu_AirShipThree") { goto IL_00fc; } } else { char c = prefabName[12]; if (c != 'O') { if (c != 'T') { if (c == 'o' && prefabName == "Fehu_MagicBroom") { goto IL_0104; } } else if (prefabName == "Fehu_AirShipTwo") { goto IL_00f4; } } else if (prefabName == "Fehu_AirShipOne") { goto IL_00ec; } } } if (prefabName.IndexOf("AirShipOne", StringComparison.OrdinalIgnoreCase) >= 0) { return 300; } if (prefabName.IndexOf("AirShipTwo", StringComparison.OrdinalIgnoreCase) >= 0) { return 500; } if (prefabName.IndexOf("AirShipThree", StringComparison.OrdinalIgnoreCase) >= 0) { return 500; } if (prefabName.IndexOf("MagicBroom", StringComparison.OrdinalIgnoreCase) >= 0) { return 200; } return 300; IL_00fc: return 500; IL_0104: return 200; IL_00ec: return 300; IL_00f4: return 500; } private static bool IsFuelDisplayName(ItemData? item, string displayName) { if (item?.m_shared != null) { return string.Equals(item.m_shared.m_name, displayName, StringComparison.Ordinal); } return false; } private static string DescribeFuelItem(ItemData item) { string arg = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : "null"); string arg2 = ((item.m_shared != null) ? item.m_shared.m_name : "null"); return $"prefab={arg},name={arg2},stack={item.m_stack}"; } private void SetFuel(float value) { int num = EnsureCapacity(); _fuel = Mathf.Clamp(value, 0f, (float)num); if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null && _nview.IsOwner()) { _nview.GetZDO().Set("fehu_airship_fuel", _fuel); } } } internal static class FehuAirshipHammerBuildPath { private sealed class Entry { public GameObject Prefab { get; } public string PrefabName { get; } public string DisplayName { get; } public RequirementConfig[] Requirements { get; } public ManualLogSource Log { get; } public Entry(GameObject prefab, string prefabName, string displayName, RequirementConfig[] requirements, ManualLogSource log) { Prefab = prefab; PrefabName = prefabName; DisplayName = displayName; Requirements = requirements; Log = log; } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDBAwakePatch { private static void Postfix(ObjectDB __instance) { Apply(__instance); } } private static readonly List Entries = new List(); public static void Register(GameObject prefab, string prefabName, string displayName, RequirementConfig[] requirements, ManualLogSource log) { if (!((Object)(object)prefab == (Object)null)) { Piece val = prefab.GetComponent() ?? prefab.AddComponent(); val.m_name = displayName; val.m_description = displayName; val.m_enabled = true; val.m_craftingStation = null; if ((Object)(object)val.m_icon == (Object)null) { log.LogWarning((object)("[FehuAirships] Direct Hammer piece '" + prefabName + "' has no icon; existing fallback should have been assigned.")); } Entries.RemoveAll((Entry entry) => string.Equals(entry.PrefabName, prefabName, StringComparison.Ordinal)); Entries.Add(new Entry(prefab, prefabName, displayName, requirements ?? Array.Empty(), log)); FehuAirshipDebug.LogInfo(log, $"[FehuAirships] Direct Hammer build path queued prefab='{prefabName}' znet={(Object)(object)prefab.GetComponent() != (Object)null} piece={(Object)(object)val != (Object)null} requirements={((requirements != null) ? requirements.Length : 0)}"); if ((Object)(object)ObjectDB.instance != (Object)null) { Apply(ObjectDB.instance); } } } private static void Apply(ObjectDB objectDb) { if ((Object)(object)objectDb == (Object)null || Entries.Count == 0) { return; } GameObject itemPrefab = objectDb.GetItemPrefab("Hammer"); PieceTable val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null)?.m_itemData?.m_shared?.m_buildPieces; if ((Object)(object)val == (Object)null) { FehuAirshipDebug.LogInfo(Entries[0].Log, "[FehuAirships] Direct Hammer build path waiting: Hammer PieceTable not ready."); return; } foreach (Entry entry in Entries) { GameObject val2 = ResolveRegisteredPrefab(entry); if (!((Object)(object)val2 == (Object)null)) { Piece obj = val2.GetComponent() ?? val2.AddComponent(); obj.m_name = entry.DisplayName; obj.m_description = entry.DisplayName; obj.m_enabled = true; obj.m_craftingStation = null; obj.m_resources = ResolveRequirements(objectDb, entry); ZNetView val3 = EnsureNetworkRoot(val2); val.m_pieces.RemoveAll((GameObject existing) => (Object)(object)existing == (Object)null || string.Equals(NormalizeCloneName(((Object)existing).name), entry.PrefabName, StringComparison.Ordinal)); val.m_pieces.Add(val2); FehuAirshipDebug.LogInfo(entry.Log, string.Format("[FehuAirships] Direct Hammer build path applied prefab='{0}' znet={1} persistent={2} registeredSource={3} tablePieces={4}", entry.PrefabName, (Object)(object)val3 != (Object)null, (Object)(object)val3 != (Object)null && val3.m_persistent, (val2 == entry.Prefab) ? "queued" : "ZNetScene", val.m_pieces.Count)); } } } private static GameObject ResolveRegisteredPrefab(Entry entry) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(entry.PrefabName) : null); if ((Object)(object)val != (Object)null) { return val; } return entry.Prefab; } private static ZNetView EnsureNetworkRoot(GameObject prefab) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) ZNetView val = prefab.GetComponent(); if ((Object)(object)val == (Object)null) { val = prefab.AddComponent(); } val.m_persistent = true; val.m_type = (ObjectType)0; return val; } private static Requirement[] ResolveRequirements(ObjectDB objectDb, Entry entry) { //IL_00a5: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown List list = new List(); RequirementConfig[] requirements = entry.Requirements; foreach (RequirementConfig val in requirements) { if (!string.IsNullOrWhiteSpace(val.Item) && val.Amount > 0) { GameObject itemPrefab = objectDb.GetItemPrefab(val.Item); ItemDrop val2 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { entry.Log.LogWarning((object)("[FehuAirships] Direct Hammer requirement missing prefab='" + entry.PrefabName + "' item='" + val.Item + "'.")); } else { list.Add(new Requirement { m_resItem = val2, m_amount = val.Amount, m_amountPerLevel = val.AmountPerLevel, m_recover = true }); } } } return list.ToArray(); } private static string NormalizeCloneName(string name) { if (!name.EndsWith("(Clone)", StringComparison.Ordinal)) { return name; } return name.Substring(0, name.Length - "(Clone)".Length); } } public sealed class FehuAirshipPersistence : MonoBehaviour { private const string HasTransformKey = "fehu_airship_has_transform"; private const string EngineKey = "fehu_airship_engine"; private const float SaveInterval = 5f; private ZNetView? _nview; private FehuAirshipFuelSystem? _fuel; private FehuAirshipControlsPilot? _pilot; private float _saveTimer; private bool _restored; private bool _validationStarted; private void Awake() { //IL_0045: 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) _nview = ((Component)this).GetComponent(); _fuel = ((Component)this).GetComponent(); _pilot = ((Component)this).GetComponent(); if ((Object)(object)_nview != (Object)null) { _nview.m_persistent = true; _nview.m_type = (ObjectType)0; } FehuAirshipDebug.Log($"[FehuAirships] Persistence Awake prefab='{((Object)((Component)this).gameObject).name}' znet={(Object)(object)_nview != (Object)null} persistent={(Object)(object)_nview != (Object)null && _nview.m_persistent} pos={((Component)this).transform.position}"); } private void Start() { if (_nview == null) { _nview = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } RestoreTransformIfSaved(); LogState("Start/reload"); if (!_validationStarted) { _validationStarted = true; ((MonoBehaviour)this).StartCoroutine(ValidateRuntimeInstanceDeferred()); } SaveState(force: true); } private void Update() { _saveTimer += Time.deltaTime; if (!(_saveTimer < 5f)) { _saveTimer = 0f; SaveState(force: false); } } private void OnDestroy() { SaveState(force: true); LogState("OnDestroy/save-last"); } private void RestoreTransformIfSaved() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_00b9: 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_007f: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (_restored || (Object)(object)_nview == (Object)null || !_nview.IsValid() || _nview.GetZDO() == null) { return; } ZDO zDO = _nview.GetZDO(); if (!zDO.GetBool("fehu_airship_has_transform", false)) { _restored = true; return; } Vector3 position = zDO.GetPosition(); Quaternion rotation = zDO.GetRotation(); ((Component)this).transform.SetPositionAndRotation(position, rotation); Rigidbody component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { component.position = position; component.rotation = rotation; component.linearVelocity = Vector3.zero; component.angularVelocity = Vector3.zero; } _restored = true; FehuAirshipDebug.Log($"[FehuAirships] Persistence restored prefab='{((Object)((Component)this).gameObject).name}' zdoPos={position} zdoRot={((Quaternion)(ref rotation)).eulerAngles}"); } private void SaveState(bool force) { //IL_0054: 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) if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.GetZDO() != null && _nview.IsOwner()) { ZDO zDO = _nview.GetZDO(); zDO.Set("fehu_airship_has_transform", true); zDO.SetPosition(((Component)this).transform.position); zDO.SetRotation(((Component)this).transform.rotation); zDO.Set("fehu_airship_engine", (Object)(object)_pilot != (Object)null && _pilot.IsLocalPilot); if (force) { LogState("Save/force"); } } } private IEnumerator ValidateRuntimeInstanceDeferred() { yield return null; yield return null; for (float elapsed = 0f; elapsed <= 2f; elapsed += 0.2f) { if (_nview == null) { _nview = ((Component)this).GetComponent(); } if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null) { bool flag = _nview.IsOwner(); FehuAirshipDebug.Log($"[FehuAirships] Vehicle persistence OK prefab='{((Object)((Component)this).gameObject).name}' owner={flag}"); yield break; } yield return (object)new WaitForSeconds(0.2f); } bool flag2 = (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null; Debug.LogError((object)$"[FehuAirships] INVALID VEHICLE INSTANCE - NO ZDO - WILL NOT PERSIST prefab='{((Object)((Component)this).gameObject).name}' root='{((Object)((Component)this).transform.root).name}' znet={(Object)(object)_nview != (Object)null} zdo={flag2} persistent={(Object)(object)_nview != (Object)null && _nview.m_persistent} pos={((Component)this).transform.position}"); } private void LogState(string reason) { //IL_007f: 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_008c: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) bool flag = (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null; bool flag2 = (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner(); bool flag3 = (Object)(object)_nview != (Object)null && _nview.m_persistent; bool flag4 = false; bool flag5 = false; Vector3 position = ((Component)this).transform.position; Quaternion rotation = ((Component)this).transform.rotation; if (flag) { ZDO zDO = _nview.GetZDO(); flag4 = zDO.GetBool("fehu_airship_engine", false); flag5 = zDO.GetBool("fehu_airship_has_transform", false); position = zDO.GetPosition(); rotation = zDO.GetRotation(); } FehuAirshipDebug.Log($"[FehuAirships] Persistence {reason} prefab='{((Object)((Component)this).gameObject).name}' znet={(Object)(object)_nview != (Object)null} zdo={flag} persistent={flag3} owner={flag2} pos={((Component)this).transform.position} zdoPos={position} zdoRot={((Quaternion)(ref rotation)).eulerAngles} savedTransform={flag5} fuel={(((Object)(object)_fuel != (Object)null) ? _fuel.CurrentFuel : (-1))}/{(((Object)(object)_fuel != (Object)null) ? _fuel.Capacity : (-1))} engine={flag4}"); } } [HarmonyPatch(typeof(Piece), "Awake")] internal static class FehuAirshipPieceAwakePatch { private static readonly string[] AirshipPrefabNames = new string[4] { "Fehu_AirShipOne", "Fehu_AirShipTwo", "Fehu_AirShipThree", "Fehu_MagicBroom" }; private static readonly FieldRef PieceNviewRef = AccessTools.FieldRefAccess("m_nview"); private static void Postfix(Piece __instance) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return; } GameObject gameObject = ((Component)__instance).gameObject; string text = NormalizeCloneName(((Object)gameObject).name); if (IsFehuAirship(text)) { ZNetView component = gameObject.GetComponent(); if ((Object)(object)component == (Object)null) { Debug.LogError((object)$"[FehuAirships] INVALID VEHICLE BUILD PATH - missing root ZNetView root='{((Object)gameObject).name}' prefab='{text}' pos={gameObject.transform.position}"); return; } component.m_persistent = true; component.m_type = (ObjectType)0; PieceNviewRef.Invoke(__instance) = component; bool flag = component.IsValid() && component.GetZDO() != null; FehuAirshipDebug.Log($"[FehuAirships] Build path network root='{((Object)gameObject).name}' prefab='{text}' addedZNetView=False znet=True zdo={flag} persistent={component.m_persistent} type={component.m_type} pos={gameObject.transform.position}"); } } private static bool IsFehuAirship(string name) { string[] airshipPrefabNames = AirshipPrefabNames; foreach (string text in airshipPrefabNames) { if (name == text) { return true; } } return false; } private static string NormalizeCloneName(string name) { if (!name.EndsWith("(Clone)")) { return name; } return name.Substring(0, name.Length - "(Clone)".Length); } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class FehuAirshipPlayerSetControlsPatch { private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool jump, ref bool dodge) { if (!((Object)(object)__instance == (Object)null) && __instance.GetDoodadController() is FehuAirshipControlsPilot) { attack = false; attackHold = false; secondaryAttack = false; secondaryAttackHold = false; jump = false; dodge = false; } } } public sealed class FehuAirshipRegistry { private readonly struct VehicleSpec { public string AssetPath { get; } public string SourceName { get; } public string ExposedName { get; } public string DisplayName { get; } public VehicleSpec(string assetPath, string sourceName, string exposedName, string displayName) { AssetPath = assetPath; SourceName = sourceName; ExposedName = exposedName; DisplayName = displayName; } } private readonly struct AssetSpec { public string AssetPath { get; } public string SourceName { get; } public string DisplayName { get; } public AssetSpec(string assetPath, string sourceName, string displayName) { AssetPath = assetPath; SourceName = sourceName; DisplayName = displayName; } } private readonly ManualLogSource _log; private readonly FehuAirshipConfigHolder _config; private readonly FehuAirshipAssetLoader _loader = new FehuAirshipAssetLoader(); private readonly HashSet _registered = new HashSet(StringComparer.Ordinal); private int _registeredVehicles; private int _registeredCores; private int _registeredDestruction; private static readonly VehicleSpec[] Vehicles = new VehicleSpec[4] { new VehicleSpec("assets/bagual/airshipplus/airship 01/airshipone.prefab", "AirShipOne", "Fehu_AirShipOne", "Fehu Balloon"), new VehicleSpec("assets/bagual/airshipplus/airship 02/airshiptwo.prefab", "AirShipTwo", "Fehu_AirShipTwo", "Fehu Airship"), new VehicleSpec("assets/bagual/airshipplus/airship 03/airshipthree.prefab", "AirShipThree", "Fehu_AirShipThree", "Fehu Sky Caravel"), new VehicleSpec("assets/bagual/airshipplus/vassouramágica/magicbroom.prefab", "MagicBroom", "Fehu_MagicBroom", "Fehu Runebroom") }; private static readonly AssetSpec[] Cores = new AssetSpec[4] { new AssetSpec("assets/bagual/airshipplus/magicalorbs/floatingyelloworb.prefab", "FloatingYellowOrb", "Ancient Core"), new AssetSpec("assets/bagual/airshipplus/magicalorbs/floatinggreenorb.prefab", "FloatingGreenOrb", "Warpstone Core"), new AssetSpec("assets/bagual/airshipplus/magicalorbs/floatingblueorb.prefab", "FloatingBlueOrb", "Mithril Core"), new AssetSpec("assets/bagual/airshipplus/magicalorbs/floatingredorb.prefab", "FloatingRedOrb", "Meteorite Core") }; private static readonly string[] DestructionAssets = new string[4] { "assets/bagual/airshipplus/airship 01/ds_airshipone.prefab", "assets/bagual/airshipplus/airship 02/ds_airshiptwo.prefab", "assets/bagual/airshipplus/airship 03/ds_airshipthree.prefab", "assets/bagual/airshipplus/vassouramágica/ds_magicbroom.prefab" }; public FehuAirshipRegistry(FehuAssetsPlugin plugin) { _log = plugin.AirshipLog; _config = new FehuAirshipConfigHolder(((BaseUnityPlugin)plugin).Config); FehuAirshipRuntimeBootstrap.ConfigureShared(_config); } public void Register() { if (!_config.Enabled.Value) { FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Disabled by config."); return; } try { _loader.LogGameObjectAssets(_log); VehicleSpec[] vehicles = Vehicles; foreach (VehicleSpec spec in vehicles) { RegisterVehicle(spec); } AssetSpec[] cores = Cores; foreach (AssetSpec spec2 in cores) { RegisterItem(spec2); } string[] destructionAssets = DestructionAssets; foreach (string assetPath in destructionAssets) { if (RegisterRawPrefab(assetPath)) { _registeredDestruction++; } } FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Registered vehicles: {_registeredVehicles}/4"); FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Registered core items: {_registeredCores}/4"); FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Registered item drops: 0/3 (ItemDrop_AirShipOne/Two/Three intentionally excluded from V1)."); FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Registered destruction prefabs: {_registeredDestruction}/4"); FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Vehicles registered as spawnable prefabs only; not craftable yet."); } catch (Exception arg) { _log.LogError((object)$"[FehuAirships] Registration failed: {arg}"); } } private void RegisterVehicle(VehicleSpec spec) { //IL_00ea: 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) GameObject val = _loader.LoadPrefab(spec.AssetPath); VerifyVehicleSource(val, spec); bool activeSelf = val.activeSelf; val.SetActive(false); GameObject val2 = Object.Instantiate(val); val.SetActive(activeSelf); ((Object)val2).name = spec.ExposedName; val2.SetActive(false); Floating[] componentsInChildren = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } InspectAndRemoveImpactEffects(val2, spec.ExposedName); InspectAndRemoveContainers(val2, spec.ExposedName); InspectAndRemoveWearNTear(val2, spec.ExposedName); RemoveVehicleOnlyItemAndCreatureComponents(val2, spec.ExposedName); int num = RemoveAllZSyncTransforms(val2); FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Removed ZSyncTransform count={num} vehicle={spec.ExposedName}"); ZNetView obj = val2.GetComponent() ?? val2.AddComponent(); obj.m_persistent = true; obj.m_type = (ObjectType)0; ZNetView[] componentsInChildren2 = val2.GetComponentsInChildren(true); foreach (ZNetView obj2 in componentsInChildren2) { obj2.m_persistent = true; obj2.m_type = (ObjectType)0; } Rigidbody obj3 = val2.GetComponent() ?? val2.AddComponent(); obj3.mass = ((spec.ExposedName == "Fehu_MagicBroom") ? 40f : 600f); obj3.interpolation = (RigidbodyInterpolation)1; ConfigureVehiclePresentation(val2, spec.DisplayName); if (val2.GetComponentsInChildren(true).Length == 0) { AddSelectionCollider(val2); } FehuAirshipControlsPilot fehuAirshipControlsPilot = val2.AddComponent(); FehuAirshipFuelSystem fehuAirshipFuelSystem = val2.AddComponent(); FehuAirshipRuntimeBootstrap fehuAirshipRuntimeBootstrap = val2.AddComponent(); val2.AddComponent(); fehuAirshipFuelSystem.Configure(_config, fehuAirshipControlsPilot, _config.FuelCapacity(spec.ExposedName), _log); fehuAirshipControlsPilot.Configure(fehuAirshipFuelSystem); fehuAirshipRuntimeBootstrap.Configure(_config, fehuAirshipControlsPilot, fehuAirshipFuelSystem); val2.SetActive(true); bool flag = _config.IsVehicleRecipeEnabled(spec.ExposedName); bool flag2 = RegisterPrefab(val2); if (flag2) { RegisterVehicleBuildPiece(val2, spec); } if (flag2) { _registeredVehicles++; } LogRegisteredVehicle(spec, val2, flag2); FehuAirshipDebug.LogInfo(_log, flag ? ("[FehuAirships] Vehicle direct Hammer build recipe enabled '" + spec.DisplayName + "' (" + spec.ExposedName + ").") : ("[FehuAirships] Vehicle direct Hammer build path forced for persistence '" + spec.DisplayName + "' (" + spec.ExposedName + "); config recipe flag is disabled.")); } private void RegisterItem(AssetSpec spec) { if (RegisterCoreItemRecipe(spec)) { _registeredCores++; FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Registered Jotunn item '" + spec.SourceName + "' from AssetBundle as '" + spec.DisplayName + "'."); } } private bool RegisterCoreItemRecipe(AssetSpec spec) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown ItemConfig val = new ItemConfig { Name = spec.DisplayName, Description = CoreDescription(spec.SourceName), Amount = 1, Enabled = _config.EnableCoreRecipes.Value, CraftingStation = "Workbench", MinStationLevel = 1, Requirements = CoreRequirements(spec.SourceName) }; if (ItemManager.Instance.AddItem(new CustomItem(_loader.Bundle, spec.AssetPath, true, val))) { FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Core recipe '" + spec.DisplayName + "': " + DescribeRequirements(val.Requirements)); return true; } _log.LogWarning((object)("[FehuAirships] Jotunn CustomItem registration failed for '" + spec.SourceName + "'.")); return false; } private bool RegisterVehicleBuildPiece(GameObject vehicle, VehicleSpec spec) { Piece val = vehicle.GetComponent() ?? vehicle.AddComponent(); val.m_name = spec.DisplayName; val.m_description = spec.DisplayName; if ((Object)(object)val.m_icon == (Object)null) { val.m_icon = CreateFallbackIcon(spec.ExposedName); } RequirementConfig[] requirements = VehicleRequirements(spec.ExposedName); FehuAirshipHammerBuildPath.Register(vehicle, spec.ExposedName, spec.DisplayName, requirements, _log); FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Airship direct Hammer recipe '" + spec.DisplayName + "': " + DescribeRequirements(requirements)); return true; } private bool RegisterRawPrefab(string assetPath) { GameObject prefab = Object.Instantiate(_loader.LoadPrefab(assetPath)); return RegisterPrefab(prefab); } private bool RegisterPrefab(GameObject prefab) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!_registered.Add(((Object)prefab).name)) { Object.DestroyImmediate((Object)(object)prefab); return false; } prefab.transform.position = new Vector3(0f, -10000f, 0f); Object.DontDestroyOnLoad((Object)(object)prefab); PrefabManager.Instance.AddPrefab(prefab); return true; } private static int RemoveAllZSyncTransforms(GameObject vehicle) { ZSyncTransform[] componentsInChildren = vehicle.GetComponentsInChildren(true); ZSyncTransform[] array = componentsInChildren; for (int i = 0; i < array.Length; i++) { Object.DestroyImmediate((Object)(object)array[i]); } return componentsInChildren.Length; } private void VerifyVehicleSource(GameObject source, VehicleSpec spec) { bool flag = ((Object)source).name == spec.SourceName; bool flag2 = (Object)(object)source.GetComponentInChildren(true) != (Object)null; bool flag3 = (Object)(object)source.GetComponentInChildren(true) != (Object)null; bool flag4 = (Object)(object)source.GetComponentInChildren(true) != (Object)null; bool flag5 = (Object)(object)source.GetComponentInChildren(true) != (Object)null; bool flag6 = (Object)(object)source.GetComponentInChildren(true) != (Object)null; FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Vehicle asset='{spec.AssetPath}' GameObject='{((Object)source).name}' expected='{spec.SourceName}' nameMatch={flag} ZNetView={flag2} Piece={flag3} ItemDrop={flag4} WearNTear={flag5} Rigidbody={flag6}"); } private static void ConfigureVehiclePresentation(GameObject vehicle, string displayName) { Piece component = vehicle.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_name = displayName; component.m_description = displayName; } } private void LogRegisteredVehicle(VehicleSpec spec, GameObject vehicle, bool registered) { //IL_01ec: Unknown result type (might be due to invalid IL or missing references) ZNetView component = vehicle.GetComponent(); bool flag = (Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null; FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Vehicle validation assetFound=true registered={registered} registeredName='{((Object)vehicle).name}' " + $"ZNetView={(Object)(object)vehicle.GetComponent() != (Object)null} " + $"ZSyncTransform={(Object)(object)vehicle.GetComponent() != (Object)null} " + $"Rigidbody={(Object)(object)vehicle.GetComponent() != (Object)null} " + $"Floating={(Object)(object)vehicle.GetComponentInChildren(true) != (Object)null} " + $"Piece={(Object)(object)vehicle.GetComponentInChildren(true) != (Object)null} " + $"WearNTear={(Object)(object)vehicle.GetComponentInChildren(true) != (Object)null} " + $"Container={(Object)(object)vehicle.GetComponentInChildren(true) != (Object)null} " + $"FehuAirshipFuelSystem={(Object)(object)vehicle.GetComponent() != (Object)null} " + $"FehuAirshipControlsPilot={(Object)(object)vehicle.GetComponent() != (Object)null} " + $"FehuAirshipRigidbody={(Object)(object)vehicle.GetComponent() != (Object)null} " + $"RuntimeBootstrap={(Object)(object)vehicle.GetComponent() != (Object)null}"); FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Persistence prefab={spec.ExposedName} persistent={(Object)(object)component != (Object)null && component.m_persistent} hasZDO={flag} fuel=registration-template pos={vehicle.transform.position}"); } private void InspectAndRemoveImpactEffects(GameObject vehicle, string registeredName) { ImpactEffect[] componentsInChildren = vehicle.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { FehuAirshipDebug.LogInfo(_log, "[FehuAirships] ImpactEffect scan vehicle='" + registeredName + "' found=0."); return; } ImpactEffect[] array = componentsInChildren; foreach (ImpactEffect val in array) { string objectPath = GetObjectPath(((Component)val).transform, vehicle.transform); string text = DescribeInstanceFields(val); FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] ImpactEffect vehicle='{registeredName}' path='{objectPath}' enabled={((Behaviour)val).enabled} fields={text}"); Object.DestroyImmediate((Object)(object)val); FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Removed unsafe ImpactEffect vehicle='" + registeredName + "' path='" + objectPath + "'."); } } private void InspectAndRemoveContainers(GameObject vehicle, string registeredName) { Container[] componentsInChildren = vehicle.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Container scan vehicle='" + registeredName + "' found=0."); return; } Container[] array = componentsInChildren; foreach (Container val in array) { string objectPath = GetObjectPath(((Component)val).transform, vehicle.transform); string text = ReadInstanceField(val, "m_name"); string text2 = ReadInstanceField(val, "m_width"); string text3 = ReadInstanceField(val, "m_height"); string text4 = ReadInstanceField(val, "m_inventory"); string text5 = ReadInstanceField(val, "m_checkGuardStone"); bool flag = (Object)(object)((Component)val).GetComponent() != (Object)null || (Object)(object)((Component)val).GetComponentInParent() != (Object)null; string text6 = DescribeInstanceFields(val); FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] Container vehicle='{registeredName}' path='{objectPath}' enabled={((Behaviour)val).enabled} " + $"m_name={text} m_width={text2} m_height={text3} inventory={text4} hasZNetView={flag} " + "privateAccess=" + text5 + " fields=" + text6); Object.DestroyImmediate((Object)(object)val); FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Removed V1 cargo Container vehicle='" + registeredName + "' path='" + objectPath + "'."); } } private void InspectAndRemoveWearNTear(GameObject vehicle, string registeredName) { WearNTear[] componentsInChildren = vehicle.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { FehuAirshipDebug.LogInfo(_log, "[FehuAirships] WearNTear scan vehicle='" + registeredName + "' found=0."); return; } WearNTear[] array = componentsInChildren; foreach (WearNTear val in array) { string objectPath = GetObjectPath(((Component)val).transform, vehicle.transform); string text = DescribeInstanceFields(val); FehuAirshipDebug.LogInfo(_log, $"[FehuAirships] WearNTear vehicle='{registeredName}' path='{objectPath}' enabled={((Behaviour)val).enabled} fields={text}"); Object.DestroyImmediate((Object)(object)val); FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Removed V1 unsafe WearNTear vehicle='" + registeredName + "' path='" + objectPath + "'."); } } private void RemoveVehicleOnlyItemAndCreatureComponents(GameObject vehicle, string registeredName) { ItemDrop[] componentsInChildren = vehicle.GetComponentsInChildren(true); foreach (ItemDrop val in componentsInChildren) { string objectPath = GetObjectPath(((Component)val).transform, vehicle.transform); FehuAirshipDebug.LogInfo(_log, "[FehuAirships] Removed vehicle-only ItemDrop vehicle='" + registeredName + "' path='" + objectPath + "' prefab='" + ((Object)((Component)val).gameObject).name + "'."); Object.DestroyImmediate((Object)(object)val); } MonoBehaviour[] componentsInChildren2 = vehicle.GetComponentsInChildren(true); foreach (MonoBehaviour val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null)) { string text = ((object)val2).GetType().FullName ?? ((object)val2).GetType().Name; if (text.IndexOf("CreatureLevelControl", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("OriginalItemData", StringComparison.OrdinalIgnoreCase) >= 0) { string objectPath2 = GetObjectPath(((Component)val2).transform, vehicle.transform); _log.LogWarning((object)("[FehuAirships] Removed creature-level component vehicle='" + registeredName + "' path='" + objectPath2 + "' type='" + text + "'.")); Object.DestroyImmediate((Object)(object)val2); } } } } private static string GetObjectPath(Transform transform, Transform root) { List list = new List(); Transform val = transform; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } list.Reverse(); return string.Join("/", list); } private static string DescribeInstanceFields(object instance) { List list = new List(); FieldInfo[] fields = instance.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { try { list.Add(fieldInfo.Name + "=" + DescribeValue(fieldInfo.GetValue(instance))); } catch (Exception ex) { list.Add(fieldInfo.Name + "="); } } return string.Join(", ", list); } private static string ReadInstanceField(object instance, string fieldName) { FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return ""; } try { return DescribeValue(field.GetValue(instance)); } catch (Exception ex) { return ""; } } private static string DescribeValue(object? value) { if (value == null) { return "null"; } Object val = (Object)((value is Object) ? value : null); if (val != null) { if (!(val == (Object)null)) { return ((object)val).GetType().Name + "('" + val.name + "')"; } return ""; } if (value is IEnumerable enumerable && !(value is string)) { List list = new List(); foreach (object item in enumerable) { list.Add(DescribeValue(item)); } return "[" + string.Join("; ", list) + "]"; } return value.ToString() ?? ""; } private static string CoreDescription(string prefabName) { return prefabName switch { "FloatingYellowOrb" => "An ancient magical power core recovered from forgotten ruins. It stores stable primordial energy capable of powering advanced Fehu technology.", "FloatingGreenOrb" => "A rare core infused with spatial and arcane energies. Used in advanced magical technologies and teleportation research.", "FloatingBlueOrb" => "A powerful energy core forged from enchanted Mithril. Known for exceptional stability and efficiency.", "FloatingRedOrb" => "An extremely rare core containing fragments of celestial matter. Holds immense power and is considered legendary technology.", _ => "A Fehu airship core.", }; } private static RequirementConfig[] CoreRequirements(string prefabName) { return prefabName switch { "FloatingYellowOrb" => Requirements(("SurtlingCore", 1), ("Resin", 10), ("Coins", 100)), "FloatingGreenOrb" => Requirements(("SurtlingCore", 2), ("BMM_WarpstoneCoins", 20), ("Coins", 250)), "FloatingBlueOrb" => Requirements(("SurtlingCore", 2), ("BMM_MithrilCoins", 20), ("Coins", 250)), "FloatingRedOrb" => Requirements(("SurtlingCore", 2), ("BMM_MeteoriteCoins", 20), ("Coins", 250)), _ => Array.Empty(), }; } private static RequirementConfig[] VehicleRequirements(string prefabName) { return prefabName switch { "Fehu_AirShipOne" => Requirements(("FineWood", 40), ("Resin", 40), ("FloatingYellowOrb", 5), ("Coins", 1000)), "Fehu_AirShipTwo" => Requirements(("FineWood", 80), ("Iron", 30), ("FloatingYellowOrb", 10), ("Coins", 2500)), "Fehu_AirShipThree" => Requirements(("FineWood", 120), ("Silver", 30), ("FloatingYellowOrb", 15), ("Coins", 10000)), "Fehu_MagicBroom" => Requirements(("FineWood", 20), ("Resin", 10), ("FloatingYellowOrb", 3), ("Coins", 1000)), _ => Array.Empty(), }; } private static RequirementConfig[] Requirements(params (string Item, int Amount)[] requirements) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown RequirementConfig[] array = (RequirementConfig[])(object)new RequirementConfig[requirements.Length]; for (int i = 0; i < requirements.Length; i++) { array[i] = new RequirementConfig(requirements[i].Item, requirements[i].Amount, 0, true); } return array; } private static string DescribeRequirements(IEnumerable requirements) { List list = new List(); foreach (RequirementConfig requirement in requirements) { list.Add($"{requirement.Item} x{requirement.Amount}"); } return string.Join(", ", list); } private static Sprite CreateFallbackIcon(string prefabName) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_027b: 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_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { name = prefabName + "_RecipeIconTexture", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; Color32 val2 = (Color32)(prefabName switch { "Fehu_MagicBroom" => new Color32((byte)128, (byte)86, (byte)42, byte.MaxValue), "Fehu_AirShipThree" => new Color32((byte)118, (byte)152, (byte)185, byte.MaxValue), "Fehu_AirShipTwo" => new Color32((byte)140, (byte)108, (byte)82, byte.MaxValue), _ => new Color32((byte)202, (byte)174, (byte)91, byte.MaxValue), }); Color32 val3 = default(Color32); ((Color32)(ref val3))..ctor((byte)(val2.r / 3), (byte)(val2.g / 3), (byte)(val2.b / 3), byte.MaxValue); Color32 val4 = default(Color32); ((Color32)(ref val4))..ctor((byte)Mathf.Min(255, val2.r + 55), (byte)Mathf.Min(255, val2.g + 55), (byte)Mathf.Min(255, val2.b + 55), byte.MaxValue); Color32[] array = (Color32[])(object)new Color32[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { bool flag = j < 3 || i < 3 || j >= 61 || i >= 61; bool flag2 = Mathf.Abs(i - 39) < 7 && j > 10 && j < 54; bool flag3 = prefabName == "Fehu_AirShipOne" && (float)((j - 32) * (j - 32)) / 360f + (float)((i - 22) * (i - 22)) / 190f <= 1f; bool flag4 = Mathf.Abs(j - 32) < 3 && i > 12 && i < 48; bool flag5 = prefabName == "Fehu_MagicBroom" && Mathf.Abs((float)(j - 13) - (float)(i - 48) * 1.1f) < 3f && i > 16 && i < 55; bool num = Mathf.Abs(j - 49) + Mathf.Abs(i - 15) < 6 || Mathf.Abs(j - 17) + Mathf.Abs(i - 18) < 5; array[i * 64 + j] = (flag ? val4 : val3); if (flag3 || flag2 || flag4 || flag5) { array[i * 64 + j] = val2; } if (num) { array[i * 64 + j] = new Color32(byte.MaxValue, (byte)231, (byte)124, byte.MaxValue); } } } val.SetPixels32(array); val.Apply(false, true); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); ((Object)obj).name = prefabName + "_RecipeIcon"; Object.DontDestroyOnLoad((Object)(object)val); Object.DontDestroyOnLoad((Object)(object)obj); return obj; } private static void AddSelectionCollider(GameObject target) { //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_0023: 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_005a: 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_007c: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = target.GetComponentsInChildren(true); BoxCollider val = target.AddComponent(); if (componentsInChildren.Length == 0) { val.center = new Vector3(0f, 1f, 0f); val.size = new Vector3(3f, 2f, 6f); return; } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } val.center = target.transform.InverseTransformPoint(((Bounds)(ref bounds)).center); val.size = ((Bounds)(ref bounds)).size + Vector3.one * 0.5f; } } [RequireComponent(typeof(Rigidbody))] public sealed class FehuAirshipRigidbody : MonoBehaviour { private const float DefaultLiftForce = 18f; private const float DefaultCruiseForce = 10f; private const float DefaultTurnSpeed = 55f; private Rigidbody? _body; private FehuAirshipControlsPilot? _pilot; private FehuAirshipFuelSystem? _fuel; private FehuAirshipConfigHolder? _config; private ZNetView? _nview; public void Configure(FehuAirshipConfigHolder config, FehuAirshipControlsPilot pilot, FehuAirshipFuelSystem fuel) { _config = config; _pilot = pilot; _fuel = fuel; } private void Awake() { _body = ((Component)this).GetComponent(); if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } _nview = ((Component)this).GetComponent(); _body.useGravity = true; _body.linearDamping = 0.35f; _body.angularDamping = 1.5f; _body.constraints = (RigidbodyConstraints)80; } private void Start() { if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } if (_nview == null) { _nview = ((Component)this).GetComponent(); } FehuAirshipDebug.Log($"[FehuAirships] Rigidbody init vehicle={((Object)((Component)this).gameObject).name} pilot={(Object)(object)_pilot != (Object)null} fuel={(Object)(object)_fuel != (Object)null} config={_config != null} nview={(Object)(object)_nview != (Object)null}"); } private void FixedUpdate() { //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0221: 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_023f: Unknown result type (might be due to invalid IL or missing references) if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } if (!((Object)(object)_body == (Object)null) && !((Object)(object)_pilot == (Object)null) && !((Object)(object)_fuel == (Object)null) && _pilot.IsLocalPilot && _fuel.HasFuel) { if ((Object)(object)_nview != (Object)null && _nview.IsValid() && !_nview.IsOwner()) { _nview.ClaimOwnership(); } float num = ((Mathf.Abs(_pilot.ForwardInput) > 0.01f) ? _pilot.ForwardInput : (Input.GetKey((KeyCode)119) ? 1f : (Input.GetKey((KeyCode)115) ? (-1f) : 0f))); float num2 = ((Mathf.Abs(_pilot.TurnInput) > 0.01f) ? _pilot.TurnInput : (Input.GetKey((KeyCode)100) ? 1f : (Input.GetKey((KeyCode)97) ? (-1f) : 0f))); bool key = Input.GetKey((KeyCode)32); bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305) || Input.GetKey((KeyCode)99); float num3 = (key ? 1f : (flag ? (-1f) : 0f)); float num4 = _config?.CruiseForce.Value ?? 10f; float num5 = _config?.LiftForce.Value ?? 18f; float num6 = _config?.TurnSpeed.Value ?? 55f; _body.AddForce(((Component)this).transform.forward * num * num4, (ForceMode)5); _body.AddForce(Vector3.up * (num3 * num5 + num5 * 0.35f), (ForceMode)5); _body.MoveRotation(_body.rotation * Quaternion.Euler(0f, num2 * num6 * Time.fixedDeltaTime, 0f)); } } } public sealed class FehuAirshipRuntimeBootstrap : MonoBehaviour { private static FehuAirshipConfigHolder? s_config; private FehuAirshipConfigHolder? _config; private FehuAirshipControlsPilot? _pilot; private FehuAirshipFuelSystem? _fuel; private bool _started; public static void ConfigureShared(FehuAirshipConfigHolder config) { s_config = config; } public void Configure(FehuAirshipConfigHolder config, FehuAirshipControlsPilot pilot, FehuAirshipFuelSystem fuel) { _config = config; _pilot = pilot; _fuel = fuel; } private void Awake() { if (_config == null) { _config = s_config; } if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } } private void Start() { if (!_started) { _started = true; ((MonoBehaviour)this).StartCoroutine(EnsureFlightPhysicsDeferred()); } } private IEnumerator EnsureFlightPhysicsDeferred() { yield return null; yield return null; if (_config == null) { _config = s_config; } if (_pilot == null) { _pilot = ((Component)this).GetComponent(); } if (_fuel == null) { _fuel = ((Component)this).GetComponent(); } if (_config == null || (Object)(object)_pilot == (Object)null || (Object)(object)_fuel == (Object)null) { Debug.LogError((object)$"[FehuAirships] Runtime physics bootstrap failed prefab={((Object)((Component)this).gameObject).name} config={_config != null} pilot={(Object)(object)_pilot != (Object)null} fuel={(Object)(object)_fuel != (Object)null}"); } else { Rigidbody obj = ((Component)this).GetComponent() ?? ((Component)this).gameObject.AddComponent(); obj.mass = (((Object)((Component)this).gameObject).name.StartsWith("Fehu_MagicBroom") ? 40f : 600f); obj.interpolation = (RigidbodyInterpolation)1; (((Component)this).GetComponent() ?? ((Component)this).gameObject.AddComponent()).Configure(_config, _pilot, _fuel); Debug.Log((object)$"[FehuAirships] Runtime physics bootstrap OK prefab={((Object)((Component)this).gameObject).name} config={_config != null} pilot={(Object)(object)_pilot != (Object)null} fuel={(Object)(object)_fuel != (Object)null}"); } } } } namespace AirShipsPlus { public sealed class Airship : MonoBehaviour { } public sealed class AirshipControlls : MonoBehaviour { } public sealed class AirshipFuelSystem : MonoBehaviour { } public sealed class AirshipPort : MonoBehaviour { } }