Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Swamp Revival After Bonemass v1.0.3
BepInEx/plugins/PrimeForestSpirit/PrimeForestSpirit.dll
Decompiled 4 days agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PrimeForestSpirit")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.2.0")] [assembly: AssemblyInformationalVersion("0.4.2")] [assembly: AssemblyProduct("PrimeForestSpirit")] [assembly: AssemblyTitle("PrimeForestSpirit")] [assembly: AssemblyVersion("0.4.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BiomeRevival.PrimeForestSpirit { [BepInPlugin("com.prime.forestspirit", "Prime Forest Spirit", "0.4.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class PrimeForestSpiritPlugin : BaseUnityPlugin { public const string PluginId = "com.prime.forestspirit"; public const string PrefabName = "PrimeForestSpirit"; internal static PrimeForestSpiritPlugin Instance; internal static SpiritSettings Settings; public static Func<bool> RestorationGate; private SpiritVisuals visuals; private void Awake() { Instance = this; Settings = new SpiritSettings(((BaseUnityPlugin)this).Config); PrefabManager.OnVanillaPrefabsAvailable += Register; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Prime Forest Spirit 0.4.2: original visuals/movement/lifetime; nighttime restored visibility, sleeping offscreen/daytime visuals and lights."); } private void Register() { //IL_0108: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= Register; GameObject val = null; try { GameObject prefab = PrefabManager.Instance.GetPrefab("LuredWisp"); if (!Object.op_Implicit((Object)(object)prefab)) { throw new InvalidOperationException("Installed LuredWisp prefab was not available."); } if (Object.op_Implicit((Object)(object)PrefabManager.Instance.GetPrefab("PrimeForestSpirit"))) { throw new InvalidOperationException("Prefab name already registered: PrimeForestSpirit"); } val = PrefabManager.Instance.CreateEmptyPrefab("PrimeForestSpirit", false); if (!Object.op_Implicit((Object)(object)val) || val.activeInHierarchy) { throw new InvalidOperationException("Expected an inactive Jotunn prefab container; refusing unsafe construction."); } val.SetActive(false); Component[] components = val.GetComponents<Component>(); foreach (Component val2 in components) { if (!(val2 is Transform)) { Object.DestroyImmediate((Object)(object)val2); } } val.layer = LayerMask.NameToLayer("Default"); val.tag = "spawned"; visuals = new SpiritVisuals(Settings, ((BaseUnityPlugin)this).Logger); visuals.Build(prefab, val); ZNetView obj = val.AddComponent<ZNetView>(); obj.m_persistent = true; obj.m_distant = false; obj.m_type = (ObjectType)0; obj.m_syncInitialScale = false; ZSyncTransform obj2 = val.AddComponent<ZSyncTransform>(); obj2.m_syncPosition = true; obj2.m_syncRotation = false; obj2.m_syncScale = false; obj2.m_syncBodyVelocity = false; obj2.m_characterParentSync = false; val.AddComponent<SpiritWander>(); val.AddComponent<FireflyPulse>(); val.AddComponent<FireflyVisibility>(); val.AddComponent<SpiritLifetime>(); SpiritVisuals.Validate(val); val.SetActive(true); PrefabManager.Instance.AddPrefab(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)("REGISTERED PrimeForestSpirit: luminous point/halo at " + Settings.Scale + " scale, light=" + Settings.LightIntensity + "/" + Settings.LightRange + ", materials=" + visuals.MaterialCount + ", owner-controlled wandering. No interaction/combat/mist components.")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("PrimeForestSpirit registration failed; no spawning enabled: " + ex)); if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } } } internal void Diagnostic(string message) { if (Settings.Diagnostics) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= Register; if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } internal sealed class SpiritSettings { internal readonly float Scale; internal readonly float LightIntensity; internal readonly float LightRange; internal readonly float LightDistance; internal readonly Color FireflyColor; internal readonly float CoreDiameter; internal readonly float HaloDiameter; internal readonly float CoreBrightness; internal readonly float HaloBrightness; internal readonly float CoreOpacity; internal readonly float HaloOpacity; internal readonly float PulseMinSeconds; internal readonly float PulseMaxSeconds; internal readonly float PulseMinimum; internal readonly float VisualDistance; internal readonly float VisibilityInterval; internal readonly float VisibilityHysteresis; internal readonly float Radius; internal readonly float Speed; internal readonly float Steering; internal readonly float PauseChance; internal readonly float PauseMin; internal readonly float PauseMax; internal readonly float LegMin; internal readonly float LegMax; internal readonly float HoverHeight; internal readonly float BobAmplitude; internal readonly float BobPeriod; internal readonly float SurfaceInterval; internal readonly float ObstacleRadius; internal readonly float ObstacleDistance; internal readonly float CurveRate; internal readonly float SurfaceResponse; internal readonly float AvoidanceResponse; internal readonly float RenderResponse; internal readonly bool Diagnostics; internal SpiritSettings(ConfigFile config) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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: 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_008b: 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) Scale = Number(config, "Visuals", "VisualScale", 1f, 0.1f, 1f, "Scale relative to LuredWisp, including particles. Restart required for settings changes."); Color value = config.Bind<Color>("Firefly", "FireflyColor", new Color(1f, 0.68f, 0.18f, 1f), "Warm golden-yellow tint shared by core, halo and light. Replaces old GoldColor; restart required.").Value; FireflyColor = new Color(Mathf.Clamp01(value.r), Mathf.Clamp01(value.g), Mathf.Clamp01(value.b), 1f); LightIntensity = Number(config, "Visuals", "LightIntensity", 0.8f, 0f, 2f, "Point-light intensity; zero removes scene illumination but preserves the emissive glow."); LightRange = Number(config, "Visuals", "LightRange", 3f, 0.1f, 5f, "Point-light range in metres; no shadows."); LightDistance = Number(config, "Visuals", "LightCullDistance", 15f, 2f, 40f, "Vanilla LightLod distance in metres."); CoreDiameter = Number(config, "Firefly", "CoreDiameter", 0.055f, 0.01f, 0.2f, "Luminous billboard core diameter in metres at VisualScale=1; no solid mesh."); HaloDiameter = Number(config, "Firefly", "HaloDiameter", 0.45f, 0.1f, 1.5f, "Soft radial halo diameter in metres at VisualScale=1."); CoreBrightness = Number(config, "Firefly", "CoreBrightness", 2f, 0.1f, 5f, "Peak unlit core RGB multiplier; appearance depends on tone mapping/bloom."); HaloBrightness = Number(config, "Firefly", "HaloBrightness", 1f, 0.1f, 3f, "Peak unlit halo RGB multiplier."); CoreOpacity = Number(config, "Firefly", "CoreOpacity", 0.85f, 0.05f, 1f, "Core peak alpha before smooth pulse modulation."); HaloOpacity = Number(config, "Firefly", "HaloOpacity", 0.22f, 0.01f, 0.8f, "Halo peak alpha; procedural alpha fades smoothly to zero at its edge."); PulseMinSeconds = Number(config, "Firefly", "PulsePeriodMinSeconds", 2f, 0.5f, 20f, "Minimum individual pulse period; stable per-object randomization."); PulseMaxSeconds = Mathf.Max(PulseMinSeconds, Number(config, "Firefly", "PulsePeriodMaxSeconds", 4f, 0.5f, 30f, "Maximum individual pulse period.")); PulseMinimum = Number(config, "Firefly", "PulseMinimumBrightness", 0.08f, 0f, 0.5f, "Dim-phase fraction of peak; modulates core/halo alpha and point-light intensity together."); VisualDistance = Number(config, "Visibility", "VisualDistance", 80f, 20f, 120f, "Glow-only camera distance in metres, subject to native object loading/fog/occlusion. Does not expand illumination or global draw distances."); VisibilityInterval = Number(config, "Visibility", "CheckIntervalSeconds", 0.25f, 0.1f, 1f, "Local per-object camera-distance check interval; no scene scan."); VisibilityHysteresis = Number(config, "Visibility", "HysteresisMetres", 2f, 0f, 10f, "Extra distance before hiding a currently visible glow, preventing edge toggling."); Radius = Number(config, "Movement", "WanderRadius", 10f, 1f, 50f, "Horizontal roaming radius around the original network spawn position, with smooth edge steering."); Speed = Number(config, "Movement", "MoveSpeed", 1.05f, 0.05f, 2f, "Maximum horizontal speed in metres per second; v0.2 default is 1.75x the v0.1 default."); Steering = Number(config, "Movement", "SteeringRate", 1.2f, 0.1f, 5f, "Velocity easing rate; smaller values give gentler turns."); CurveRate = Number(config, "Movement", "CurveAngularRate", 0.18f, 0.02f, 0.6f, "Angular rate of the continuously moving two-orbit attractor; no waypoint arrivals."); SurfaceResponse = Number(config, "Movement", "SurfaceResponse", 2.5f, 0.2f, 10f, "Per-frame filtering of sampled surface heights and vertical speed response."); AvoidanceResponse = Number(config, "Movement", "AvoidanceResponse", 3f, 0.2f, 10f, "Per-frame filtering of occasional obstacle samples."); RenderResponse = Number(config, "Movement", "RenderResponse", 12f, 2f, 30f, "LateUpdate visual-position smoothing rate on all peers; root synchronization remains native."); PauseChance = Number(config, "Movement", "PauseChance", 0.4f, 0f, 1f, "Chance of pausing after a wander leg."); PauseMin = Number(config, "Movement", "PauseMinSeconds", 1.5f, 0.1f, 30f, "Minimum pause duration."); PauseMax = Mathf.Max(PauseMin, Number(config, "Movement", "PauseMaxSeconds", 4.5f, 0.1f, 60f, "Maximum pause duration.")); LegMin = Number(config, "Movement", "DirectionMinSeconds", 7f, 1f, 60f, "Minimum cruising time before a pause opportunity; no abrupt direction change occurs."); LegMax = Mathf.Max(LegMin, Number(config, "Movement", "DirectionMaxSeconds", 16f, 1f, 120f, "Maximum cruising time before a pause opportunity.")); BobAmplitude = Number(config, "Movement", "BobAmplitude", 0.1f, 0f, 0.4f, "Maximum child-visual vertical bob in metres."); BobPeriod = Number(config, "Movement", "BobPeriodSeconds", 4f, 1f, 15f, "Main bob period, combined with a second slower oscillation."); HoverHeight = Mathf.Max(BobAmplitude + 0.2f, Number(config, "Movement", "HoverHeight", 1.3f, 0.3f, 5f, "Root height above sampled terrain or water; at least bob amplitude plus 0.2m.")); SurfaceInterval = Number(config, "Movement", "SurfaceCheckSeconds", 0.25f, 0.1f, 2f, "Interval for terrain, water and obstacle samples; filtered every frame. No scene scans."); ObstacleRadius = Number(config, "Movement", "ObstacleRadius", 0.15f, 0.05f, 0.5f, "Sphere-cast clearance against terrain and structures."); ObstacleDistance = Number(config, "Movement", "ObstacleLookAhead", 0.9f, 0.3f, 3f, "Minimum obstacle look-ahead distance; automatically increased for speed/check interval."); Diagnostics = config.Bind<bool>("Diagnostics", "LogOwnership", false, "Log owner changes per spirit; no per-frame logging.").Value; } private static float Number(ConfigFile config, string section, string key, float value, float min, float max, string description) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())).Value; } } internal sealed class SpiritVisuals { private readonly SpiritSettings settings; private readonly ManualLogSource log; private Material glow; private Texture2D radial; internal int MaterialCount => Object.op_Implicit((Object)(object)glow) ? 1 : 0; internal SpiritVisuals(SpiritSettings settings, ManualLogSource log) { this.settings = settings; this.log = log; } internal void Build(GameObject donor, GameObject root) { //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_00a7: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_0198: 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_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020d: 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_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) Transform val = donor.transform.Find("effects/flare"); ParticleSystemRenderer val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ParticleSystemRenderer>() : null); Material val3 = (Object.op_Implicit((Object)(object)val2) ? ((Renderer)val2).sharedMaterial : null); if (!Object.op_Implicit((Object)(object)val3) || ((Object)val3.shader).name != "Legacy Shaders/Particles/Alpha Blended" || !val3.HasProperty("_TintColor") || !val3.HasProperty("_MainTex")) { throw new InvalidOperationException("Inspected LuredWisp transparent flare material is missing/changed; refusing a solid fallback."); } radial = CreateRadialTexture(); glow = new Material(val3) { name = "PrimeForestSpirit_FireflyGlow", renderQueue = 3000 }; glow.SetTexture("_MainTex", (Texture)(object)radial); Color val4 = settings.FireflyColor * 0.5f; val4.a = settings.CoreOpacity * settings.PulseMinimum * 0.5f; glow.SetColor("_TintColor", val4); if (glow.HasProperty("_ZWrite")) { glow.SetInt("_ZWrite", 0); } if (glow.HasProperty("_SrcBlend")) { glow.SetInt("_SrcBlend", 5); } if (glow.HasProperty("_DstBlend")) { glow.SetInt("_DstBlend", 10); } GameObject val5 = new GameObject("PrimeForestSpiritVisuals"); val5.transform.SetParent(root.transform, false); val5.transform.localScale = Vector3.one * settings.Scale; ParticleSystemRenderer val6 = CreatePoint(val5.transform, "PrimeFireflyCore", settings.CoreDiameter); ParticleSystemRenderer val7 = CreatePoint(val5.transform, "PrimeFireflyHalo", settings.HaloDiameter); GameObject val8 = new GameObject("PrimeFireflyLight"); val8.transform.SetParent(val5.transform, false); Light obj = val8.AddComponent<Light>(); obj.type = (LightType)2; obj.color = settings.FireflyColor; obj.intensity = settings.LightIntensity * settings.PulseMinimum; obj.range = settings.LightRange; obj.shadows = (LightShadows)0; LightLod obj2 = val8.AddComponent<LightLod>(); obj2.m_lightLod = true; obj2.m_lightDistance = settings.LightDistance; obj2.m_shadowLod = false; LODGroup component = donor.GetComponent<LODGroup>(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("LuredWisp LODGroup missing."); } LOD[] lODs = component.GetLODs(); if (lODs.Length != 1) { throw new InvalidOperationException("Unexpected LuredWisp LOD layout; review before registration."); } lODs[0].renderers = (Renderer[])(object)new Renderer[2] { (Renderer)val6, (Renderer)val7 }; lODs[0].screenRelativeTransitionHeight = 0f; LODGroup obj3 = root.AddComponent<LODGroup>(); obj3.SetLODs(lODs); obj3.fadeMode = component.fadeMode; obj3.animateCrossFading = component.animateCrossFading; obj3.localReferencePoint = component.localReferencePoint * settings.Scale; obj3.size = component.size * settings.Scale; obj3.enabled = component.enabled; log.LogInfo((object)("Firefly visuals: no solid mesh, sparks or trails; two stationary billboards, one owned material/radial texture. Shader=" + ((Object)glow.shader).name + "; core/halo=" + settings.CoreDiameter + "/" + settings.HaloDiameter + "m; screen-size cull removed, glow-only distance=" + settings.VisualDistance + "m; light range unchanged=" + settings.LightRange + "m.")); } private Texture2D CreateRadialTexture() { //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_00c9: 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_00d7: 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_00e7: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[16384]; for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { double num = 2.0 * (double)j / 127.0 - 1.0; double num2 = 2.0 * (double)i / 127.0 - 1.0; array[i * 128 + j] = new Color(1f, 1f, 1f, FireflyMath.RadialAlpha(Math.Sqrt(num * num + num2 * num2))); } } Texture2D val = new Texture2D(128, 128, (TextureFormat)4, true) { name = "PrimeForestSpirit_RadialGlow", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; val.SetPixels(array); val.Apply(true, true); return val; } private ParticleSystemRenderer CreatePoint(Transform parent, string name, float diameter) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0084: 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_00ac: 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_00cc: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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_010c: 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_011c: 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_012c: 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_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); ParticleSystem val2 = val.AddComponent<ParticleSystem>(); val2.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = val2.main; ((MainModule)(ref main)).duration = 1f; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).playOnAwake = true; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(float.PositiveInfinity); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).startSize3D = false; ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(diameter); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.white); ((MainModule)(ref main)).maxParticles = 1; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0; ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).enabled = false; EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f); ((EmissionModule)(ref emission)).rateOverDistance = MinMaxCurve.op_Implicit(0f); ((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1] { new Burst(0f, (short)1) }); TrailModule trails = val2.trails; ((TrailModule)(ref trails)).enabled = false; LightsModule lights = val2.lights; ((LightsModule)(ref lights)).enabled = false; CollisionModule collision = val2.collision; ((CollisionModule)(ref collision)).enabled = false; TriggerModule trigger = val2.trigger; ((TriggerModule)(ref trigger)).enabled = false; ExternalForcesModule externalForces = val2.externalForces; ((ExternalForcesModule)(ref externalForces)).enabled = false; ParticleSystemRenderer val3 = val.GetComponent<ParticleSystemRenderer>(); if (!Object.op_Implicit((Object)(object)val3)) { val3 = val.AddComponent<ParticleSystemRenderer>(); } val3.renderMode = (ParticleSystemRenderMode)0; val3.alignment = (ParticleSystemRenderSpace)0; ((Renderer)val3).sharedMaterial = glow; ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val3).receiveShadows = false; return val3; } internal static void Validate(GameObject root) { //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: 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_0219: 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_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Unresolved script in firefly prefab."); } bool num; if (!((Object)(object)val.gameObject == (Object)(object)root)) { if (val is Transform || val is ParticleSystem || val is ParticleSystemRenderer || val is Light) { continue; } num = val is LightLod; } else { if (val is Transform || val is ZNetView || val is ZSyncTransform || val is SpiritWander || val is FireflyPulse || val is FireflyVisibility || val is SpiritLifetime) { continue; } num = val is LODGroup; } if (!num) { throw new InvalidOperationException("Disallowed firefly component: " + ((object)val).GetType().FullName); } } if (root.GetComponentsInChildren<ParticleSystem>(true).Length != 2 || root.GetComponentsInChildren<ParticleSystemRenderer>(true).Length != 2 || root.GetComponentsInChildren<Light>(true).Length != 1) { throw new InvalidOperationException("Expected exactly two glow systems and one point light."); } LODGroup component = root.GetComponent<LODGroup>(); LOD[] array = (LOD[])(Object.op_Implicit((Object)(object)component) ? ((Array)component.GetLODs()) : ((Array)new LOD[0])); if (array.Length != 1 || array[0].renderers.Length != 2 || (Object)(object)array[0].renderers[0] == (Object)(object)array[0].renderers[1]) { throw new InvalidOperationException("Expected exactly two distinct firefly LOD renderers."); } if (array[0].screenRelativeTransitionHeight != 0f) { throw new InvalidOperationException("Unexpected screen-size cutoff on extended-visibility firefly."); } Renderer[] renderers = array[0].renderers; foreach (Renderer val2 in renderers) { if (!(val2 is ParticleSystemRenderer) || !((Component)val2).transform.IsChildOf(root.transform)) { throw new InvalidOperationException("Firefly LOD refers outside its billboard hierarchy."); } } ParticleSystem[] componentsInChildren2 = root.GetComponentsInChildren<ParticleSystem>(true); int i = 0; while (i < componentsInChildren2.Length) { ParticleSystem val3 = componentsInChildren2[i]; MainModule main = val3.main; if (((MainModule)(ref main)).maxParticles == 1) { main = val3.main; if ((int)((MainModule)(ref main)).simulationSpace == 0) { TrailModule trails = val3.trails; if (!((TrailModule)(ref trails)).enabled) { CollisionModule collision = val3.collision; if (!((CollisionModule)(ref collision)).enabled) { TriggerModule trigger = val3.trigger; if (!((TriggerModule)(ref trigger)).enabled) { LightsModule lights = val3.lights; if (!((LightsModule)(ref lights)).enabled) { i++; continue; } } } } } } throw new InvalidOperationException("Unexpected gameplay, trail or particle count in glow system."); } } } [DefaultExecutionOrder(200)] public sealed class FireflyPulse : MonoBehaviour { private ZNetView view; private ParticleSystemRenderer core; private ParticleSystemRenderer halo; private Light pointLight; private MaterialPropertyBlock properties; private SpiritSettings settings; private double period; private double cycle; private bool initialized; private FireflyVisibility visibility; private static readonly int TintId = Shader.PropertyToID("_TintColor"); private void Start() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown view = ((Component)this).GetComponent<ZNetView>(); settings = PrimeForestSpiritPlugin.Settings; visibility = ((Component)this).GetComponent<FireflyVisibility>(); Transform val = ((Component)this).transform.Find("PrimeForestSpiritVisuals"); if (!Object.op_Implicit((Object)(object)view) || !Object.op_Implicit((Object)(object)val) || settings == null) { ((Behaviour)this).enabled = false; return; } core = ((Component)val.Find("PrimeFireflyCore")).GetComponent<ParticleSystemRenderer>(); halo = ((Component)val.Find("PrimeFireflyHalo")).GetComponent<ParticleSystemRenderer>(); pointLight = ((Component)val.Find("PrimeFireflyLight")).GetComponent<Light>(); properties = new MaterialPropertyBlock(); Apply(settings.PulseMinimum); } private void LateUpdate() { if (settings != null && properties != null && Object.op_Implicit((Object)(object)view) && view.IsValid() && (!Object.op_Implicit((Object)(object)visibility) || visibility.Visible)) { if (!initialized) { FireflyMath.Parameters((uint)((object)Unsafe.As<ZDOID, ZDOID>(ref view.GetZDO().m_uid)/*cast due to .constrained prefix*/).GetHashCode(), settings.PulseMinSeconds, settings.PulseMaxSeconds, out period, out cycle); initialized = true; } cycle = (cycle + (double)Mathf.Min(Time.deltaTime, 0.1f) / period) % 1.0; Apply(FireflyMath.Pulse(cycle, settings.PulseMinimum)); } } private void Apply(float pulse) { SetTint((Renderer)(object)core, settings.CoreBrightness, settings.CoreOpacity * pulse); SetTint((Renderer)(object)halo, settings.HaloBrightness, settings.HaloOpacity * pulse); pointLight.intensity = settings.LightIntensity * pulse; } private void SetTint(Renderer renderer, float brightness, float alpha) { //IL_0006: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Color val = settings.FireflyColor * (brightness * 0.5f); val.a = alpha * 0.5f; properties.SetColor(TintId, val); renderer.SetPropertyBlock(properties); } } internal static class FireflyMath { internal static float RadialAlpha(double radius) { double num = Math.Max(0.0, 1.0 - radius * radius); if (!(radius >= 1.0)) { return (float)(num * num * num); } return 0f; } internal static float Pulse(double cycle, float minimum) { return minimum + (1f - minimum) * (float)(0.5 - 0.5 * Math.Cos(Math.PI * 2.0 * cycle)); } internal static void Parameters(uint identity, float min, float max, out double period, out double cycle) { uint num = identity ^ 0xF17EF17Eu; num ^= num >> 16; num *= 2146121005; num ^= num >> 15; num *= 2221713035u; num ^= num >> 16; period = (double)min + (double)(max - min) * SpiritMath.Next01(ref num); cycle = SpiritMath.Next01(ref num); } } public sealed class FireflyVisibility : MonoBehaviour { private Renderer core; private Renderer halo; private SpiritSettings settings; private float timer; private bool visible = true; private GameObject visualRoot; private static int conditionFrame = -1; private static bool night; private static bool restored; internal bool Visible => visible; private void Start() { settings = PrimeForestSpiritPlugin.Settings; Transform val = ((Component)this).transform.Find("PrimeForestSpiritVisuals"); if (!Object.op_Implicit((Object)(object)val) || settings == null) { ((Behaviour)this).enabled = false; return; } visualRoot = ((Component)val).gameObject; core = (Renderer)(object)((Component)val.Find("PrimeFireflyCore")).GetComponent<ParticleSystemRenderer>(); halo = (Renderer)(object)((Component)val.Find("PrimeFireflyHalo")).GetComponent<ParticleSystemRenderer>(); } private void Update() { //IL_00e1: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) if (settings == null || !Object.op_Implicit((Object)(object)core) || !Object.op_Implicit((Object)(object)halo)) { return; } timer -= Time.deltaTime; if (!(timer > 0f)) { timer = settings.VisibilityInterval; if (conditionFrame != Time.frameCount) { conditionFrame = Time.frameCount; night = Object.op_Implicit((Object)(object)EnvMan.instance) && EnvMan.IsNight(); restored = PrimeForestSpiritPlugin.RestorationGate?.Invoke() ?? (Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetGlobalKey("prime_swamp_restored")); } Camera mainCamera = Utils.GetMainCamera(); bool num = night; bool num2 = restored; bool camera = Object.op_Implicit((Object)(object)mainCamera); float squaredDistance; if (!Object.op_Implicit((Object)(object)mainCamera)) { squaredDistance = float.MaxValue; } else { Vector3 val = ((Component)mainCamera).transform.position - ((Component)this).transform.position; squaredDistance = ((Vector3)(ref val)).sqrMagnitude; } bool flag = FireflyActivityPolicy.Visible(num, num2, camera, squaredDistance, settings.VisualDistance, settings.VisibilityHysteresis, visible); if (flag != visible) { visible = flag; core.forceRenderingOff = !visible; halo.forceRenderingOff = !visible; visualRoot.SetActive(visible); } } } } internal static class FireflyActivityPolicy { internal static bool Visible(bool night, bool restored, bool camera, float squaredDistance, float distance, float hysteresis, bool wasVisible) { float num = distance + (wasVisible ? hysteresis : 0f); if (night && restored && camera) { return squaredDistance <= num * num; } return false; } } public sealed class SpiritWander : MonoBehaviour { private const string HomeKey = "PrimeForestSpirit_home"; private const string InitializedKey = "PrimeForestSpirit_initialized"; private const string RandomKey = "PrimeForestSpirit_random"; private const string PauseKey = "PrimeForestSpirit_paused"; private const string DeadlineKey = "PrimeForestSpirit_deadline"; private ZNetView view; private Transform visual; private SpiritSettings settings; private Vector3 home; private Vector3 velocity; private Vector3 avoidance; private Vector3 sampledAvoidance; private Vector3 renderPosition; private WaterVolume water; private uint random; private double phase; private float surfaceTimer; private float floorHeight; private float filteredFloor; private long deadline; private bool wasOwner; private bool initialized; private bool paused; private bool surfaceReady; private bool haveFloor; private int obstacleMask; private void Start() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) view = ((Component)this).GetComponent<ZNetView>(); visual = ((Component)this).transform.Find("PrimeForestSpiritVisuals"); settings = PrimeForestSpiritPlugin.Settings; renderPosition = ((Component)this).transform.position; obstacleMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" }); if (!Object.op_Implicit((Object)(object)view) || !Object.op_Implicit((Object)(object)visual) || settings == null) { ((Behaviour)this).enabled = false; } } private void Update() { //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_018c: 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_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_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view) || !view.IsValid() || settings == null || !Object.op_Implicit((Object)(object)ZNet.instance)) { return; } ZDO zDO = view.GetZDO(); phase = (double)((uint)((object)Unsafe.As<ZDOID, ZDOID>(ref zDO.m_uid)/*cast due to .constrained prefix*/).GetHashCode() % 65521u) * 9.589574803772205E-05; bool flag = view.IsOwner(); if (flag && !wasOwner) { ReadOwnerState(zDO); } if (flag != wasOwner && Object.op_Implicit((Object)(object)PrimeForestSpiritPlugin.Instance)) { PrimeForestSpiritPlugin.Instance.Diagnostic(((Object)this).name + " network owner=" + flag); } wasOwner = flag; if (!flag || !initialized) { return; } float num = Mathf.Min(Time.deltaTime, 0.1f); long ticks = ZNet.instance.GetTime().Ticks; surfaceTimer -= num; if (surfaceTimer <= 0f) { SampleSurfaceAndObstacle(); surfaceTimer = settings.SurfaceInterval; } if (!surfaceReady) { velocity = Vector3.zero; return; } if (ticks >= deadline) { ChooseNext(zDO, ticks); } filteredFloor = Mathf.Lerp(filteredFloor, floorHeight, SpiritMath.Ease(settings.SurfaceResponse, num)); avoidance = Vector3.Lerp(avoidance, sampledAvoidance, SpiritMath.Ease(settings.AvoidanceResponse, num)); Vector3 val = Vector3.zero; if (!paused) { SpiritMath.Curve(ZNet.instance.GetTimeSeconds(), phase, settings.Radius, settings.CurveRate, out var x, out var z); Vector3 val2 = home + new Vector3((float)x, 0f, (float)z) - ((Component)this).transform.position; val2.y = 0f; val = Vector3.ClampMagnitude(val2 / 1.5f + avoidance * settings.Speed, settings.Speed); Vector3 val3 = ((Component)this).transform.position - home; val3.y = 0f; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude > settings.Radius * 0.8f) { float num2 = Mathf.Clamp01((magnitude / settings.Radius - 0.8f) / 0.2f); val = Vector3.Lerp(val, -((Vector3)(ref val3)).normalized * settings.Speed, num2); } } float num3 = filteredFloor + settings.HoverHeight - ((Component)this).transform.position.y; val.y = Mathf.Clamp(num3 * settings.SurfaceResponse, (0f - settings.Speed) * 0.7f, settings.Speed * 0.7f); velocity = Vector3.Lerp(velocity, val, SpiritMath.Ease(settings.Steering, num)); Vector3 position = ((Component)this).transform.position; Vector3 val4 = velocity * num; float num4 = (float)SpiritMath.DiscStepFraction(position.x - home.x, position.z - home.z, val4.x, val4.z, settings.Radius); Vector3 position2 = position + val4 * num4; if (num4 < 1f) { velocity *= num4; } position2.y = position.y + val4.y; ((Component)this).transform.position = position2; } private void LateUpdate() { //IL_003e: 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_006d: 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_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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)visual) && settings != null && Object.op_Implicit((Object)(object)view) && view.IsValid() && Object.op_Implicit((Object)(object)ZNet.instance)) { renderPosition = Vector3.Lerp(renderPosition, ((Component)this).transform.position, SpiritMath.Ease(settings.RenderResponse, Mathf.Min(Time.deltaTime, 0.1f))); visual.position = renderPosition + Vector3.up * SpiritMath.Bob(ZNet.instance.GetTimeSeconds(), settings.BobAmplitude, settings.BobPeriod, phase); } } private void ReadOwnerState(ZDO zdo) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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_006b: Unknown result type (might be due to invalid IL or missing references) initialized = zdo.GetBool("PrimeForestSpirit_initialized", false); if (!initialized) { home = ((Component)this).transform.position; random = (uint)((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).GetHashCode(); if (random == 0) { random = 2654435769u; } paused = true; deadline = 0L; zdo.Set("PrimeForestSpirit_home", home); WriteLeg(zdo); zdo.Set("PrimeForestSpirit_initialized", true); initialized = true; } else { home = zdo.GetVec3("PrimeForestSpirit_home", ((Component)this).transform.position); random = (uint)zdo.GetInt("PrimeForestSpirit_random", 1); paused = zdo.GetBool("PrimeForestSpirit_paused", false); deadline = zdo.GetLong("PrimeForestSpirit_deadline", 0L); } velocity = Vector3.zero; surfaceTimer = 0f; haveFloor = false; } private void ChooseNext(ZDO zdo, long now) { bool flag = !paused && SpiritMath.Next01(ref random) < (double)settings.PauseChance; paused = flag; float num = ((!paused) ? Range(settings.LegMin, settings.LegMax) : Range(settings.PauseMin, settings.PauseMax)); deadline = now + (long)(num * 10000000f); WriteLeg(zdo); } private float Range(float min, float max) { return min + (max - min) * (float)SpiritMath.Next01(ref random); } private void WriteLeg(ZDO zdo) { zdo.Set("PrimeForestSpirit_random", (int)random); zdo.Set("PrimeForestSpirit_paused", paused); zdo.Set("PrimeForestSpirit_deadline", deadline); } private void SampleSurfaceAndObstacle() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_0133: 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_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) surfaceReady = Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetGroundHeight(((Component)this).transform.position, ref floorHeight); if (surfaceReady) { float waterLevel = Floating.GetWaterLevel(((Component)this).transform.position, ref water); floorHeight = Mathf.Max(floorHeight, waterLevel); floorHeight = Mathf.Max(floorHeight, ZoneSystem.instance.m_waterLevel); if (!haveFloor) { filteredFloor = floorHeight; haveFloor = true; } Vector3 val = velocity; val.y = 0f; float num = Mathf.Max(settings.ObstacleDistance, settings.Speed * settings.SurfaceInterval * 2f + settings.ObstacleRadius); sampledAvoidance = Vector3.zero; RaycastHit val2 = default(RaycastHit); if (((Vector3)(ref val)).sqrMagnitude > 0.01f && Physics.SphereCast(((Component)this).transform.position, settings.ObstacleRadius, ((Vector3)(ref val)).normalized, ref val2, num, obstacleMask, (QueryTriggerInteraction)1)) { Vector3 normal = ((RaycastHit)(ref val2)).normal; normal.y = 0f; sampledAvoidance = ((Vector3)(ref normal)).normalized * 2f; } } } } internal static class SpiritMath { internal static double Next01(ref uint state) { if (state == 0) { state = 2654435769u; } state ^= state << 13; state ^= state >> 17; state ^= state << 5; return (double)(state >> 8) / 16777216.0; } internal static void Disc(ref uint state, double radius, out double x, out double z) { double num = Next01(ref state) * Math.PI * 2.0; double num2 = Math.Sqrt(Next01(ref state)) * radius; x = Math.Cos(num) * num2; z = Math.Sin(num) * num2; } internal static float Ease(float rate, float dt) { return (float)(1.0 - Math.Exp((0f - Math.Max(0f, rate)) * Math.Max(0f, dt))); } internal static void Curve(double time, double phase, double radius, double rate, out double x, out double z) { double num = time * rate + phase + 0.16 * Math.Sin(time * rate * 0.43 + phase * 0.7); double num2 = (0.0 - time) * rate * 1.371 + phase * 1.731; x = radius * (0.55 * Math.Cos(num) + 0.2 * Math.Cos(num2)); z = radius * (0.55 * Math.Sin(num) + 0.2 * Math.Sin(num2)); } internal static double DiscStepFraction(double x, double z, double dx, double dz, double radius) { double num = x * x + z * z; double num2 = (x + dx) * (x + dx) + (z + dz) * (z + dz); double num3 = radius * radius; if (num > num3 + 1E-09) { return (num2 <= num) ? 1 : 0; } if (num2 <= num3) { return 1.0; } double num4 = dx * dx + dz * dz; if (num4 < 1E-16) { return 0.0; } double num5 = 2.0 * (x * dx + z * dz); double num6 = num - num3; return Math.Max(0.0, Math.Min(1.0, (0.0 - num5 + Math.Sqrt(Math.Max(0.0, num5 * num5 - 4.0 * num4 * num6))) / (2.0 * num4))); } internal static float Bob(double time, float amplitude, float period, double phase) { return amplitude * (float)((Math.Sin(time * Math.PI * 2.0 / (double)period + phase) + 0.23 * Math.Sin(time * Math.PI * 2.0 / ((double)period * 1.731) + phase * 1.37)) / 1.23); } } public sealed class SpiritLifetime : MonoBehaviour { private const string ExpiryKey = "PrimeForestSpirit_ambientExpiry"; private ZNetView view; private float checkTimer; private bool destroying; private void Start() { view = ((Component)this).GetComponent<ZNetView>(); } private void Update() { checkTimer -= Time.deltaTime; if (checkTimer > 0f || destroying) { return; } checkTimer = 1f; if (Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner() && Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)ZNetScene.instance)) { ZDO zDO = view.GetZDO(); long ticks = ZNet.instance.GetTime().Ticks; long num = zDO.GetLong("PrimeForestSpirit_ambientExpiry", 0L); if (num == 0L) { num = ticks + SpiritLifetimeMath.DurationTicks((uint)((object)Unsafe.As<ZDOID, ZDOID>(ref zDO.m_uid)/*cast due to .constrained prefix*/).GetHashCode()); zDO.Set("PrimeForestSpirit_ambientExpiry", num); } if (ticks >= num) { destroying = true; ZNetScene.instance.Destroy(((Component)this).gameObject); } } } } internal static class SpiritLifetimeMath { internal static long DurationTicks(uint identity) { FireflyMath.Parameters(identity ^ 0xA6B13C59u, 240f, 360f, out var period, out var _); return (long)(period * 10000000.0); } } }
BepInEx/plugins/PrimeSwampDecorations/PrimeSwampDecorations.dll
Decompiled 4 days agousing System; using System.Collections; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PrimeSwampDecorations")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyInformationalVersion("0.3.1")] [assembly: AssemblyProduct("PrimeSwampDecorations")] [assembly: AssemblyTitle("PrimeSwampDecorations")] [assembly: AssemblyVersion("0.3.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PrimeSwampDecorations { [BepInPlugin("com.primeswamp.decorations", "Prime Swamp Decorations", "0.3.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class PrimeSwampPlugin : BaseUnityPlugin { private static readonly string[,] Sources = new string[10, 3] { { "PrimeSwampCampfire", "fire_pit_haldor", "light" }, { "PrimeSwampIronFirepit", "fire_pit_hildir", "light" }, { "PrimeSwampStandingIronTorch", "piece_groundtorch", "light" }, { "PrimeSwampSconce", "piece_walltorch", "light" }, { "PrimeSwampBogWitchFirePit", "BogWitch_Fire_Pit", "light" }, { "PrimeSwampHearth", "hearth", "light" }, { "PrimeSwampCandle", "Candle_resin", "light" }, { "PrimeSwampBed", "bed", "utility" }, { "PrimeSwampWorkbench", "piece_workbench", "utility" }, { "PrimeSwampForge", "forge", "utility" } }; private void Awake() { PrefabManager.OnVanillaPrefabsAvailable += OnPrefabsAvailable; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Prime Swamp Decorations 0.3.1 loaded; native donors, no MVBP wait or build menus."); } private void OnPrefabsAvailable() { ((MonoBehaviour)this).StartCoroutine(RegisterPrefabs()); PrefabManager.OnVanillaPrefabsAvailable -= OnPrefabsAvailable; } private IEnumerator RegisterPrefabs() { InstallInteractionPatches(); for (int i = 0; i < Sources.GetLength(0); i++) { string text = Sources[i, 0]; string text2 = Sources[i, 1]; bool flag = Sources[i, 2] == "light"; try { GameObject val = PrefabManager.Instance.CreateClonedPrefab(text, text2); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Source not found: " + text2)); continue; } int num = 0; int num2 = 0; EffectArea[] componentsInChildren = val.GetComponentsInChildren<EffectArea>(true); foreach (EffectArea val2 in componentsInChildren) { if ((val2.m_type & 4) != 0) { val2.m_type = (Type)(val2.m_type & 0xFB); if ((int)val2.m_type == 0) { ((Behaviour)val2).enabled = false; } num++; } } if (flag) { Fireplace[] componentsInChildren2 = val.GetComponentsInChildren<Fireplace>(true); foreach (Fireplace instance in componentsInChildren2) { SetField(instance, "m_startFuel", 100f); SetField(instance, "m_maxFuel", 100f); SetField(instance, "m_secPerFuel", 1E+09f); num2++; } } PrefabManager.Instance.AddPrefab(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)("REGISTERED " + text + " <- " + text2 + " | suppression removed=" + num + " | fireplaces=" + num2)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("FAILED " + text + ": " + ex)); } } yield break; } private static void SetField(object instance, string name, float value) { FieldInfo field = instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(float)) { field.SetValue(instance, value); } } private void InstallInteractionPatches() { try { Type type = Type.GetType("HarmonyLib.Harmony, 0Harmony") ?? Type.GetType("HarmonyLib.Harmony, HarmonyX"); Type type2 = Type.GetType("HarmonyLib.HarmonyMethod, 0Harmony") ?? Type.GetType("HarmonyLib.HarmonyMethod, HarmonyX"); if (type == null || type2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Harmony unavailable: light prompts not hidden"); return; } object harmony = Activator.CreateInstance(type, "com.primeswamp.decorations.interactions"); ConstructorInfo constructor = type2.GetConstructor(new Type[1] { typeof(MethodInfo) }); MethodInfo methodInfo = null; MethodInfo[] methods = type.GetMethods(); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2.Name == "Patch" && methodInfo2.GetParameters().Length >= 2 && methodInfo2.GetParameters()[0].ParameterType == typeof(MethodBase)) { methodInfo = methodInfo2; break; } } if (constructor == null || methodInfo == null) { throw new Exception("Harmony patch API not found"); } PatchMethod(harmony, methodInfo, constructor, "GetHoverText", "HideHoverText"); PatchMethod(harmony, methodInfo, constructor, "GetHoverName", "HideHoverName"); PatchMethod(harmony, methodInfo, constructor, "Interact", "BlockInteraction"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom light interaction patches installed."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not hide light interactions: " + ex)); } } private static void PatchMethod(object harmony, MethodInfo patch, ConstructorInfo ctor, string original, string prefix) { MethodInfo methodInfo = null; MethodInfo[] methods = typeof(Fireplace).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2.Name == original) { methodInfo = methodInfo2; break; } } if (!(methodInfo == null)) { MethodInfo method = typeof(PrimeSwampPlugin).GetMethod(prefix, BindingFlags.Static | BindingFlags.NonPublic); object obj = ctor.Invoke(new object[1] { method }); object[] array = new object[patch.GetParameters().Length]; array[0] = methodInfo; array[1] = obj; patch.Invoke(harmony, array); } } private static bool IsOurLight(Fireplace fireplace) { if ((Object)(object)fireplace == (Object)null) { return false; } Transform val = ((Component)fireplace).transform; while ((Object)(object)val != (Object)null) { if (((Object)val).name.StartsWith("PrimeSwamp", StringComparison.Ordinal) && ((Object)val).name != "PrimeSwampBed" && ((Object)val).name != "PrimeSwampWorkbench" && ((Object)val).name != "PrimeSwampForge") { return true; } val = val.parent; } return false; } private static bool HideHoverText(Fireplace __instance, ref string __result) { if (!IsOurLight(__instance)) { return true; } __result = ""; return false; } private static bool HideHoverName(Fireplace __instance, ref string __result) { if (!IsOurLight(__instance)) { return true; } __result = ""; return false; } private static bool BlockInteraction(Fireplace __instance, ref bool __result) { if (!IsOurLight(__instance)) { return true; } __result = false; return false; } } }
BepInEx/plugins/PrimeSwampNPCs/PrimeSwampNPCs.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PrimeSwampNPCs")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.9.0")] [assembly: AssemblyInformationalVersion("0.1.9+clothing-dialogue.1")] [assembly: AssemblyProduct("PrimeSwampNPCs")] [assembly: AssemblyTitle("PrimeSwampNPCs")] [assembly: AssemblyVersion("0.1.9.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BiomeRevival.PrimeSwampNPCs { public sealed class NpcRuntime : MonoBehaviour { private static readonly FieldRef<VisEquipment, int> RenderedLegHash = AccessTools.FieldRefAccess<VisEquipment, int>("m_currentLegItemHash"); private float appearanceAudit = -1f; private static readonly FieldRef<MonsterAI, StaticTarget> StaticTargetField = AccessTools.FieldRefAccess<MonsterAI, StaticTarget>("m_targetStatic"); private static readonly Func<BaseAI, float, Vector3, float, bool, bool> MoveHome = AccessTools.MethodDelegate<Func<BaseAI, float, Vector3, float, bool, bool>>(AccessTools.Method(typeof(BaseAI), "MoveTo", new Type[4] { typeof(float), typeof(Vector3), typeof(float), typeof(bool) }, (Type[])null), (object)null, true); private static readonly Func<BaseAI, float, Vector3, bool> RunAway = AccessTools.MethodDelegate<Func<BaseAI, float, Vector3, bool>>(AccessTools.Method(typeof(BaseAI), "Flee", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<MonsterAI, bool> SetAlert = AccessTools.MethodDelegate<Action<MonsterAI, bool>>(AccessTools.Method(typeof(MonsterAI), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null), (object)null, true); private readonly List<Character> candidates = new List<Character>(); private float threatScan; private Character danger; private bool returning; private bool fleeing; private static readonly Func<BaseAI, Vector3, bool> FarmHavePath = AccessTools.MethodDelegate<Func<BaseAI, Vector3, bool>>(AccessTools.Method(typeof(BaseAI), "HavePath", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<BaseAI> FarmStop = AccessTools.MethodDelegate<Action<BaseAI>>(AccessTools.Method(typeof(BaseAI), "StopMoving", (Type[])null, (Type[])null), (object)null, true); private static readonly FieldRef<BaseAI, float> LastFarmPath = AccessTools.FieldRefAccess<BaseAI, float>("m_lastFindPathTime"); private readonly FarmerClock farmClock = new FarmerClock(); private Vector3 farmDestination; private float farmRetry; private float farmPoseTimer; private float farmPoseSafetyUntil; private bool farmAgentChanged; private AgentType originalFarmAgent; private Vector3 civilianWaterFacing; private bool civilianShore; private readonly CivilianActivity farmerSettings = new CivilianActivity { Mode = "Farming" }; private ZoneSystem priestAltarWorld; private readonly List<Vector3> priestAltars = new List<Vector3>(); private static readonly FieldRef<Humanoid, Attack> CurrentAttack = AccessTools.FieldRefAccess<Humanoid, Attack>("m_currentAttack"); private float playerContactWait; private static readonly int AggravatedKey = (int)AccessTools.Field(AccessTools.TypeByName("ZDOVars"), "s_aggravated").GetValue(null); private bool playerCombat; private long nextCombatReaction; private long nextWitnessRequest; private uint reactionRandom; public string Profession; internal static readonly List<NpcRuntime> Instances = new List<NpcRuntime>(); internal static readonly Action<MonsterAI, Character> SetTarget = AccessTools.MethodDelegate<Action<MonsterAI, Character>>(AccessTools.Method(typeof(MonsterAI), "SetTarget", (Type[])null, (Type[])null), (object)null, true); internal static readonly Action<BaseAI, Vector3> SetPatrol = AccessTools.MethodDelegate<Action<BaseAI, Vector3>>(AccessTools.Method(typeof(BaseAI), "SetPatrolPoint", new Type[1] { typeof(Vector3) }, (Type[])null), (object)null, true); private static readonly FieldRef<MonsterAI, Character> Target = AccessTools.FieldRefAccess<MonsterAI, Character>("m_targetCreature"); private static readonly Action<VisEquipment> RefreshBody = AccessTools.MethodDelegate<Action<VisEquipment>>(AccessTools.Method(typeof(VisEquipment), "UpdateBaseModel", (Type[])null, (Type[])null), (object)null, true); private static readonly int ModelIndexKey = (int)AccessTools.Field(AccessTools.TypeByName("ZDOVars"), "s_modelIndex").GetValue(null); private static readonly FieldRef<Humanoid, ItemData> HiddenRight = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenRightItem"); private static readonly FieldRef<Humanoid, ItemData> HiddenLeft = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenLeftItem"); internal ZNetView View; internal Humanoid Human; internal MonsterAI AI; internal NpcDefinition Definition; internal ItemData Weapon; internal ItemData Arrow; internal AppearanceRecord Look; private ItemData shield; private ItemData peace; private ItemData torch; private VisEquipment visuals; private ZSyncAnimation animationSync; private Animator animator; private uint random; private uint identity; private float timer; private float workTimer; private int equipmentMode = -1; private bool initialized; private bool wasOwner; private bool canWork; private bool inventoryBuilt; private string workTrigger; private bool hadDanger; private static readonly NpcSpeechGate SpeechGate = new NpcSpeechGate(); private static ZNet speechWorld; private static readonly Func<ZRoutedRpc, long> GetServer = AccessTools.MethodDelegate<Func<ZRoutedRpc, long>>(AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null), (object)null, true); private readonly FarmerClock bathClock = new FarmerClock(); private Vector3 bathDestination; private float bathRetry; private bool bathDanger; internal Vector3 Home => View.GetZDO().GetVec3("PrimeNPC_home", ((Component)this).transform.position); private CivilianActivity ActivitySettings { get { if (Profession != "PrimeFarmer") { return Definition?.Activity; } farmerSettings.Enabled = PrimeSwampNPCsPlugin.FarmerActivityEnabled.Value; farmerSettings.Radius = PrimeSwampNPCsPlugin.FarmerWorkRadius.Value; farmerSettings.MinimumTravelDistance = PrimeSwampNPCsPlugin.FarmerTravelMinimum.Value; farmerSettings.WalkTimeoutSeconds = PrimeSwampNPCsPlugin.FarmerWalkTimeout.Value; farmerSettings.IdleMinimumSeconds = PrimeSwampNPCsPlugin.FarmerIdleMinimum.Value; farmerSettings.IdleMaximumSeconds = PrimeSwampNPCsPlugin.FarmerIdleMaximum.Value; farmerSettings.WorkMinimumSeconds = PrimeSwampNPCsPlugin.FarmerWorkMinimum.Value; farmerSettings.WorkMaximumSeconds = PrimeSwampNPCsPlugin.FarmerWorkMaximum.Value; farmerSettings.WorkChance = PrimeSwampNPCsPlugin.FarmerWorkChance.Value; farmerSettings.MaximumWaterDepth = PrimeSwampNPCsPlugin.FarmerWaterDepth.Value; return farmerSettings; } } internal bool OwnsFarmerMovement { get { if (NpcCivilianPolicy.Supported(Profession) && initialized && Object.op_Implicit((Object)(object)View) && View.IsValid() && View.IsOwner() && ActivitySettings != null && ActivitySettings.Enabled && !((Character)Human).IsDead() && !InCombat && !fleeing) { return !returning; } return false; } } internal bool CosmeticFarmEvent { get { if (NpcCivilianPolicy.Supported(Profession) && !InCombat) { if (farmClock.Phase != FarmerPhase.Working) { return Time.time < farmPoseSafetyUntil; } return true; } return false; } } internal bool Angry { get { if (Object.op_Implicit((Object)(object)AI)) { return ((BaseAI)AI).IsAggravated(); } return false; } } internal static long Now { get { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return 0L; } return ZNet.instance.GetTime().Ticks; } } internal bool InCombat { get { if (Object.op_Implicit((Object)(object)View) && View.IsValid()) { if (!View.IsOwner()) { return View.GetZDO().GetBool("PrimeNPC_combat", false); } if (!fleeing && Object.op_Implicit((Object)(object)AI)) { return Object.op_Implicit((Object)(object)((BaseAI)AI).GetTargetCreature()); } return false; } return false; } } private static long ServerPeer => GetServer(ZRoutedRpc.instance); internal bool OwnsSwimmerMovement { get { if (Profession == "PrimeSwimmer" && initialized && Object.op_Implicit((Object)(object)View) && View.IsValid() && View.IsOwner()) { return !((Character)Human).IsDead(); } return false; } } private unsafe void AuditAppearance() { //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_054c: Unknown result type (might be due to invalid IL or missing references) //IL_0551: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0507: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) if (!initialized || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || !View.IsOwner()) { return; } if (PrimeSwampNPCsPlugin.AppearanceDiagnostics.Value) { PrimeSwampNPCsPlugin.Log("APPEARANCE_STATE " + Profession + " model=" + Look.Gender + " clothing=" + string.Join(",", Look.Armor) + " work=" + Look.Peace + " right=" + (Object.op_Implicit((Object)(object)Human.RightItem?.m_dropPrefab) ? ((Object)Human.RightItem.m_dropPrefab).name : "none")); } if (PrimeSwampNPCsPlugin.AppearanceDiagnostics.Value) { string text = Array.Find(Look.Armor, NpcClothingPolicy.LegItem) ?? ""; int num = ((!(text == "")) ? StringExtensionMethods.GetStableHashCode(text) : 0); PrimeSwampNPCsPlugin.Log("APPEARANCE_LEG_HASH " + Profession + " expected=" + num + " rendered=" + RenderedLegHash.Invoke(visuals) + " match=" + (num == RenderedLegHash.Invoke(visuals))); } Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if ((!(val is MeshRenderer) && !(val is SkinnedMeshRenderer)) || !val.enabled || !((Component)val).gameObject.activeInHierarchy) { continue; } string text2 = ((Object)val).name; Transform parent = ((Component)val).transform.parent; while (Object.op_Implicit((Object)(object)parent) && (Object)(object)parent != (Object)(object)((Component)this).transform) { text2 = ((Object)parent).name + "/" + text2; parent = parent.parent; } Bounds bounds; Vector3 val7; if (PrimeSwampNPCsPlugin.AppearanceDiagnostics.Value) { if (((Object)val).name == "body") { Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if (Object.op_Implicit((Object)(object)val2) && val2.HasProperty("_LegsTex")) { string text3 = Array.Find(Look.Armor, NpcClothingPolicy.LegItem) ?? ""; object obj2; if (!(text3 == "")) { GameObject obj = NpcFactory.Find(text3); obj2 = ((obj == null) ? null : obj.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_armorMaterial); } else { obj2 = null; } Material val3 = (Material)obj2; Texture val4 = ((Object.op_Implicit((Object)(object)val3) && val3.HasProperty("_LegsTex")) ? val3.GetTexture("_LegsTex") : null); Texture texture = val2.GetTexture("_LegsTex"); PrimeSwampNPCsPlugin.Log("APPEARANCE_LEG_TEXTURE " + Profession + " source=" + (Object.op_Implicit((Object)(object)val4) ? ((Object)val4).name : "none") + " body=" + (Object.op_Implicit((Object)(object)texture) ? ((Object)texture).name : "none") + " match=" + ((Object)(object)val4 == (Object)(object)texture)); } } } int num2 = 0; SkinnedMeshRenderer val5 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); if (val5 != null) { Transform[] bones = val5.bones; foreach (Transform val6 in bones) { if (Object.op_Implicit((Object)(object)val6) && !val6.IsChildOf(((Component)this).transform)) { num2++; } } } string[] obj3 = new string[10] { "APPEARANCE_MESH ", Profession, " mesh=", text2, " bounds=", null, null, null, null, null }; bounds = val.bounds; obj3[5] = ((object)(*(Bounds*)(&bounds))/*cast due to .constrained prefix*/).ToString(); obj3[6] = " scale="; val7 = ((Component)val).transform.lossyScale; obj3[7] = ((object)(*(Vector3*)(&val7))/*cast due to .constrained prefix*/).ToString(); obj3[8] = " foreignBones="; obj3[9] = num2.ToString(); PrimeSwampNPCsPlugin.Log(string.Concat(obj3)); } bounds = val.bounds; val7 = ((Bounds)(ref bounds)).extents; if (((Vector3)(ref val7)).magnitude <= 6f) { bounds = val.bounds; if (Vector3.Distance(((Bounds)(ref bounds)).center, ((Component)this).transform.position) <= 6f) { continue; } } string[] obj4 = new string[10] { "APPEARANCE_OUTLIER ", Profession, " mesh=", text2, " bounds=", null, null, null, null, null }; bounds = val.bounds; obj4[5] = ((object)(*(Bounds*)(&bounds))/*cast due to .constrained prefix*/).ToString(); obj4[6] = " work="; obj4[7] = Look.Peace; obj4[8] = " chest/legs="; obj4[9] = string.Join(",", Look.Armor); PrimeSwampNPCsPlugin.Warn(string.Concat(obj4)); } } internal bool RemembersOffender(Character other) { if (Object.op_Implicit((Object)(object)other) && other.IsPlayer() && Object.op_Implicit((Object)(object)AI)) { return ((BaseAI)AI).IsAggravated(); } return false; } internal bool IsAngryAt(Character other) { return RemembersOffender(other); } private bool Provoked(Character other) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)other) && View.GetZDO().GetZDOID("PrimeNPC_threat") == other.GetZDOID()) { return View.GetZDO().GetLong("PrimeNPC_threatUntil", 0L) > Now; } return false; } internal static bool Livestock(Character c) { if (Object.op_Implicit((Object)(object)c) && !c.IsPlayer() && !Object.op_Implicit((Object)(object)((Component)c).GetComponent<NpcRuntime>())) { return c.IsTamed(); } return false; } private bool ImmediateThreat(Character enemy) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) Character val = (Object.op_Implicit((Object)(object)enemy.GetBaseAI()) ? enemy.GetBaseAI().GetTargetCreature() : null); if (Object.op_Implicit((Object)(object)val) && !val.IsDead() && ((Object)(object)val == (Object)(object)Human || Object.op_Implicit((Object)(object)((Component)val).GetComponent<NpcRuntime>()) || Livestock(val))) { Vector3 val2 = ((Component)val).transform.position - ((Component)enemy).transform.position; return ((Vector3)(ref val2)).sqrMagnitude <= Definition.ThreatRadius * Definition.ThreatRadius; } return false; } private bool Allowed(Character target) { //IL_0032: 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_0081: Invalid comparison between Unknown and I4 //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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) if (!Object.op_Implicit((Object)(object)target) || target.IsDead() || target.GetHealth() <= 0f || (Object)(object)target == (Object)(object)Human || !PriestAltarSafe(((Component)this).transform.position) || !PriestTargetSafe(target)) { return false; } if ((NpcCivilianPolicy.Additional(Profession) || Profession == "PrimeWarrior" || Profession == "PrimeSwimmer") && (int)target.GetFaction() == 1 && !Provoked(target) && !ImmediateThreat(target)) { return false; } return NpcBehaviorPolicy.Defend(BaseAI.IsEnemy((Character)(object)Human, target), Provoked(target), ImmediateThreat(target), NpcBehaviorPolicy.Proactive(Profession), target.IsPlayer(), IsAngryAt(target), Vector3.Distance(((Component)this).transform.position, Home), Vector3.Distance(((Component)target).transform.position, Home), Definition.DefenseRadius); } internal void UpdateDefensiveTarget(float dt, out bool see, out bool hear) { //IL_0068: 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_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) see = (hear = false); if (!initialized || !View.IsOwner() || ((Character)Human).IsDead()) { Target.Invoke(AI) = null; return; } StaticTargetField.Invoke(AI) = null; if (Profession == "PrimePriest" && !PriestAltarSafe(((Component)this).transform.position)) { Target.Invoke(AI) = null; returning = true; } Character targetCreature = ((BaseAI)AI).GetTargetCreature(); if (Object.op_Implicit((Object)(object)targetCreature) && !Allowed(targetCreature)) { Target.Invoke(AI) = null; returning = true; } threatScan -= dt; if (!Object.op_Implicit((Object)(object)((BaseAI)AI).GetTargetCreature()) && threatScan <= 0f) { threatScan = 1f; candidates.Clear(); Character.GetCharactersInRange(Home, Definition.DefenseRadius, candidates); Character val = null; float num = float.MaxValue; foreach (Character candidate in candidates) { if (Allowed(candidate) && (((BaseAI)AI).CanSeeTarget(candidate) || ((BaseAI)AI).CanHearTarget(candidate))) { Vector3 val2 = ((Component)candidate).transform.position - ((Component)this).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; val = candidate; } } } if (Object.op_Implicit((Object)(object)val)) { SetTarget(AI, val); returning = false; if (ImmediateThreat(val) && !Provoked(val)) { View.GetZDO().Set("PrimeNPC_threat", val.GetZDOID()); View.GetZDO().Set("PrimeNPC_threatUntil", Now + 150000000); } } } targetCreature = ((BaseAI)AI).GetTargetCreature(); if (Weapon != null && NpcProfessionPolicy.ContactWeapon(Profession, Look.Weapon)) { Weapon.m_shared.m_aiAttackRange = ((Object.op_Implicit((Object)(object)targetCreature) && targetCreature.IsPlayer()) ? NpcCivilianPolicy.ContactRange(Look.Weapon, Weapon.m_shared.m_attack.m_attackRange) : 2f); } if (Object.op_Implicit((Object)(object)targetCreature)) { see = ((BaseAI)AI).CanSeeTarget(targetCreature); hear = ((BaseAI)AI).CanHearTarget(targetCreature); danger = targetCreature; if (see | hear) { SetAlert(AI, arg2: true); } } else if (!fleeing) { SetAlert(AI, arg2: false); } fleeing = NpcBehaviorPolicy.Flee(Profession, ((Character)Human).GetHealthPercentage(), Definition.RetreatHealthFraction, Object.op_Implicit((Object)(object)targetCreature) || (Object.op_Implicit((Object)(object)danger) && Provoked(danger))); if (fleeing) { Target.Invoke(AI) = null; see = (hear = false); } if (InCombat || fleeing || returning) { InterruptFarmerRoutine(); } Equip(InCombat); } internal void OverrideDefensiveMovement(float dt) { //IL_0056: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: 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_00df: 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) //IL_00fb: 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_0137: 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_018a: 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) if (!initialized || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || !View.IsOwner() || ((Character)Human).IsDead() || Profession == "PrimeSwimmer") { return; } Vector3 val = ((Component)this).transform.position - Home; if (((Vector3)(ref val)).sqrMagnitude > Definition.DefenseRadius * Definition.DefenseRadius) { Target.Invoke(AI) = null; returning = true; } if (fleeing && Object.op_Implicit((Object)(object)danger) && Provoked(danger)) { Equip(combat: false); if (Vector3.Distance(((Component)this).transform.position, Home) > 3f || Vector3.Distance(((Component)danger).transform.position, Home) > 5f) { MoveHome((BaseAI)(object)AI, dt, Home, 2f, arg5: true); } else if (Vector3.Distance(((Component)this).transform.position, Home) < Definition.DefenseRadius - 3f) { RunAway((BaseAI)(object)AI, dt, ((Component)danger).transform.position); } else { MoveHome((BaseAI)(object)AI, dt, Home, 2f, arg5: true); } } else if (returning && MoveHome((BaseAI)(object)AI, dt, Home, 2f, arg5: true)) { returning = false; } } internal void DamageAccepted(Character attacker) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)attacker) && Object.op_Implicit((Object)(object)View) && View.IsValid() && View.IsOwner() && !((Character)Human).IsDead() && !attacker.IsPlayer()) { AlertNearby(((Component)this).transform.position, attacker, View.GetZDO().GetString("PrimeNPC_settlement", "")); } } private void NativeDeath() { InterruptFarmerRoutine(broadcast: false); if (Object.op_Implicit((Object)(object)View) && View.IsValid() && View.IsOwner()) { View.GetZDO().Set("PrimeNPC_dead", true); } Instances.Remove(this); ((Behaviour)this).enabled = false; } private void ResetFarmerRoutine() { if (NpcCivilianPolicy.Supported(Profession)) { InterruptFarmerRoutine(); farmRetry = 0f; } } private void RestoreFarmAgent() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (farmAgentChanged && Object.op_Implicit((Object)(object)AI)) { ((BaseAI)AI).m_pathAgentType = originalFarmAgent; LastFarmPath.Invoke((BaseAI)(object)AI) = -1000f; farmAgentChanged = false; } } private void InterruptFarmerRoutine(bool broadcast = true) { if (NpcCivilianPolicy.Supported(Profession)) { bool num = farmClock.Phase == FarmerPhase.Working; farmClock.Advance(0f, danger: true, arrived: false, 0f, 0f, workOpportunity: false); RestoreFarmAgent(); if (num) { CancelFarmPose(broadcast); } } } private void CancelFarmPose(bool broadcast) { farmPoseSafetyUntil = Time.time + 2f; ClearFarmPose(); if (broadcast && Object.op_Implicit((Object)(object)View) && View.IsValid() && View.IsOwner()) { View.InvokeRPC(ZNetView.Everybody, "PrimeNPC_CancelFarmPose", Array.Empty<object>()); } } private void OnCancelFarmPose(long sender) { if (Object.op_Implicit((Object)(object)View) && View.IsValid() && sender == View.GetZDO().GetOwner()) { farmPoseSafetyUntil = Time.time + 2f; ClearFarmPose(); } } private void ClearFarmPose() { //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_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_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: 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_025a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)animator)) { return; } if (Profession == "PrimeFarmer") { animator.ResetTrigger("swing_hoe"); animator.ResetTrigger("scything"); } else { animator.ResetTrigger("swing_hammer"); animator.ResetTrigger("fishingrod_throw"); } AnimatorStateInfo currentAnimatorStateInfo; if (NpcCivilianPolicy.Additional(Profession)) { animator.ResetTrigger(workTrigger); if (Profession == "PrimeWitch") { currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Base Layer.fireball_to_idle")) { animator.Play("Base Layer.Movement", 0, 0f); } } string text = NpcProfessionPolicy.WorkState(Profession); if (!string.IsNullOrEmpty(text)) { currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName(text)) { animator.Play("Base Layer.Movement", 0, 0f); } } } if (Profession == "PrimeWarrior") { animator.ResetTrigger("emote_point"); currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Base Layer.Emotes.Emote_point")) { animator.Play("Base Layer.Movement", 0, 0f); } } if (CurrentAttack.Invoke(Human) != null && !CurrentAttack.Invoke(Human).IsDone()) { return; } currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Base Layer.Scything")) { animator.Play("Base Layer.Movement", 0, 0f); } int layerIndex = animator.GetLayerIndex("upperbody"); if (Profession != "PrimeFarmer") { currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Base Layer.Fishing throw")) { animator.Play("Base Layer.Movement", 0, 0f); } } if (layerIndex < 0) { return; } currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(layerIndex); if (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("upperbody.swing_hoe")) { if (!(Profession == "PrimeCommoner") && !(Profession == "PrimeSculptor")) { return; } currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(layerIndex); if (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("upperbody.swing_hammer")) { return; } } animator.Play("upperbody.None", layerIndex, 0f); } internal void UpdateFarmerActivity(float dt) { //IL_008b: 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_0096: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_0419: 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_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) if (!NpcCivilianPolicy.Supported(Profession)) { return; } if (!OwnsFarmerMovement) { InterruptFarmerRoutine(); return; } CivilianActivity activitySettings = ActivitySettings; if (!farmAgentChanged) { originalFarmAgent = ((BaseAI)AI).m_pathAgentType; ((BaseAI)AI).m_pathAgentType = (AgentType)5; LastFarmPath.Invoke((BaseAI)(object)AI) = -1000f; farmAgentChanged = true; } Equip(combat: false); float num = NpcFarmerPolicy.Radius(activitySettings.Radius, Definition.DefenseRadius); Vector3 val = ((Component)this).transform.position - Home; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > num * num) { CancelIfWorking(); farmClock.BeginWalk(activitySettings.WalkTimeoutSeconds); farmDestination = Home; } bool flag = false; if (farmClock.Phase == FarmerPhase.Walking) { flag = MoveHome((BaseAI)(object)AI, dt, farmDestination, 0.7f, arg5: false); } else { FarmStop((BaseAI)(object)AI); } if (flag && activitySettings.Mode == "Fishing") { civilianShore = FindCivilianShore(((Component)this).transform.position, activitySettings, out civilianWaterFacing); } FarmerPhase phase = farmClock.Phase; float pause = ((phase == FarmerPhase.Walking && flag) ? FarmDuration(activitySettings.IdleMinimumSeconds, activitySettings.IdleMaximumSeconds) : 0f); bool flag2 = phase == FarmerPhase.Pausing && farmClock.Remaining <= dt && canWork && Object.op_Implicit((Object)(object)animationSync) && NpcCivilianPolicy.CanWork(activitySettings.Mode, civilianShore) && ((Character)Human).IsOnGround() && !((Character)Human).IsSwimming() && NpcPolicy.Unit(ref random) < (double)activitySettings.WorkChance; farmClock.Advance(dt, danger: false, flag, pause, flag2 ? FarmDuration(activitySettings.WorkMinimumSeconds, activitySettings.WorkMaximumSeconds) : 0f, flag2); if (phase == FarmerPhase.Working && farmClock.Phase != phase) { CancelFarmPose(broadcast: true); } if (farmClock.Phase == FarmerPhase.Working) { if (activitySettings.Mode == "Fishing" && civilianShore) { ((Character)Human).SetLookDir(civilianWaterFacing, 0f); } farmPoseTimer -= dt; if (phase != FarmerPhase.Working) { farmPoseTimer = 0f; } if (farmPoseTimer <= 0f && canWork && Object.op_Implicit((Object)(object)animationSync) && NpcCivilianPolicy.CanWork(activitySettings.Mode, civilianShore) && ((Character)Human).IsOnGround() && !((Character)Human).IsSwimming() && !((Character)Human).InAttack()) { bool num2; if (!(Profession == "PrimeFarmer")) { num2 = workTrigger == NpcCivilianPolicy.WorkTrigger(activitySettings.Mode, Look.Peace); } else { if (workTrigger == "swing_hoe") { goto IL_0365; } num2 = workTrigger == "scything"; } if (num2) { goto IL_0365; } } } goto IL_0392; IL_0392: if (farmClock.Phase != FarmerPhase.Seeking) { return; } farmRetry -= dt; if (farmRetry > 0f) { return; } farmRetry = 3f; bool flag3 = activitySettings.Mode == "Fishing" && NpcPolicy.Unit(ref random) < (double)activitySettings.ShoreChance; for (int i = 0; i < 4; i++) { NpcFarmerPolicy.Destination(ref random, num, out var x, out var z); Vector3 point = Home + new Vector3(x, 0f, z); Vector3 val2 = point - ((Component)this).transform.position; val2.y = 0f; if (!(((Vector3)(ref val2)).magnitude < activitySettings.MinimumTravelDistance) && FarmDestinationSafe(ref point)) { bool flag4 = activitySettings.Mode == "Fishing" && FindCivilianShore(point, activitySettings, out civilianWaterFacing); if (!flag3 || flag4 || i >= 3) { civilianShore = flag4; farmDestination = point; farmClock.BeginWalk(activitySettings.WalkTimeoutSeconds); break; } } } return; IL_0365: farmPoseSafetyUntil = Time.time + 2f; animationSync.SetTrigger(workTrigger); farmPoseTimer = 3f; goto IL_0392; } private void CancelIfWorking() { if (farmClock.Phase == FarmerPhase.Working) { CancelFarmPose(broadcast: true); } } private float FarmDuration(float minimum, float maximum) { return minimum + (float)NpcPolicy.Unit(ref random) * Mathf.Max(0f, maximum - minimum); } private bool FarmDestinationSafe(ref Vector3 point) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_005e: 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_006d: 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_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_00b4: 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_00bf: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)Heightmap.FindHeightmap(point)) || !PriestAltarSafe(point)) { return false; } point.y = ZoneSystem.instance.GetGroundHeight(point); int mask = LayerMask.GetMask(new string[1] { "terrain" }); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(point + Vector3.up * 2f, Vector3.down, ref val, 4f, mask)) { return false; } int mask2 = LayerMask.GetMask(new string[2] { "static_solid", "piece" }); bool clear = !Physics.CheckCapsule(point + Vector3.up * 0.5f, point + Vector3.up * 1.5f, 0.3f, mask2, (QueryTriggerInteraction)1); if (!NpcFarmerPolicy.SafeGround(point.y, ZoneSystem.instance.m_waterLevel, ActivitySettings.MaximumWaterDepth, Vector3.Angle(((RaycastHit)(ref val)).normal, Vector3.up), clear, reachable: true)) { return false; } return FarmHavePath((BaseAI)(object)AI, point); } private bool PriestTargetSafe(Character target) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (Profession != "PrimePriest") { return true; } string name = ((Object)((Component)target).gameObject).name; if (target.m_boss && (name == "Bonemass" || name == "Bonemass(Clone)")) { return false; } return PriestAltarSafe(((Component)target).transform.position); } private bool PriestAltarSafe(Vector3 point) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00e6: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (Profession != "PrimePriest" || !Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return true; } if ((Object)(object)priestAltarWorld != (Object)(object)ZoneSystem.instance) { priestAltarWorld = ZoneSystem.instance; priestAltars.Clear(); foreach (LocationInstance value in ZoneSystem.instance.m_locationInstances.Values) { string text = value.m_location.m_prefabName; if (string.IsNullOrEmpty(text)) { text = value.m_location.m_name; } if (text == "Bonemass") { priestAltars.Add(value.m_position); } } } foreach (Vector3 priestAltar in priestAltars) { if (!NpcProfessionPolicy.AltarSafe(point.x - priestAltar.x, point.z - priestAltar.z)) { return false; } } return true; } private bool FindCivilianShore(Vector3 standing, CivilianActivity settings, out Vector3 facing) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0095: 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_00a1: 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_00bd: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) facing = Vector3.zero; if (!Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return false; } float waterLevel = ZoneSystem.instance.m_waterLevel; int mask = LayerMask.GetMask(new string[3] { "terrain", "static_solid", "piece" }); Vector3 val = default(Vector3); Vector3 val3 = default(Vector3); for (int i = 0; i < 8; i++) { float num = (float)i * MathF.PI / 4f; ((Vector3)(ref val))..ctor(Mathf.Cos(num), 0f, Mathf.Sin(num)); for (int j = 1; j <= 2; j++) { float num2 = settings.ShoreSearchDistance * (float)j / 2f; Vector3 val2 = standing + val * num2; if (Object.op_Implicit((Object)(object)Heightmap.FindHeightmap(val2))) { float groundHeight = ZoneSystem.instance.GetGroundHeight(val2); ((Vector3)(ref val3))..ctor(val2.x, waterLevel + 0.3f, val2.z); if (NpcCivilianPolicy.ShoreWater(clear: !Physics.Linecast(standing + Vector3.up * 1.4f, val3, mask, (QueryTriggerInteraction)1), ground: groundHeight, water: waterLevel, distance: num2, searchDistance: settings.ShoreSearchDistance, loaded: true)) { facing = val; return true; } } } } return false; } internal void EnsurePlayerMelee(float dt) { //IL_00eb: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) if (!initialized || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || !View.IsOwner() || !InCombat || ((Character)Human).IsDead() || !NpcProfessionPolicy.ContactWeapon(Profession, Look.Weapon)) { playerContactWait = 0f; return; } Character targetCreature = ((BaseAI)AI).GetTargetCreature(); if (!Object.op_Implicit((Object)(object)targetCreature) || !targetCreature.IsPlayer() || !Allowed(targetCreature)) { playerContactWait = 0f; return; } float reach = NpcMeleePolicy.ContactRange(Weapon.m_shared.m_attack.m_attackRange); Collider component = ((Component)targetCreature).GetComponent<Collider>(); float contactDistance = (Object.op_Implicit((Object)(object)component) ? Vector3.Distance(((Character)Human).GetCenterPoint(), component.ClosestPoint(((Character)Human).GetCenterPoint())) : Vector3.Distance(((Component)Human).transform.position, ((Component)targetCreature).transform.position)); Attack val = CurrentAttack.Invoke(Human); if (!NpcMeleePolicy.Ready(authorizedPlayer: true, ((Character)Human).InAttack() || (val != null && !val.IsDone()), ((BaseAI)AI).CanSeeTarget(targetCreature), contactDistance, reach, Time.time - Weapon.m_lastAttackTime, Weapon.m_shared.m_aiAttackInterval)) { playerContactWait = 0f; return; } playerContactWait += dt; if (!(playerContactWait < 1f)) { playerContactWait = 0f; ((BaseAI)AI).StopMoving(); Vector3 val2 = targetCreature.GetCenterPoint() - ((Character)Human).GetCenterPoint(); val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.001f) { ((Character)Human).SetLookDir(((Vector3)(ref val2)).normalized, 0f); } if (((Character)Human).StartAttack(targetCreature, false)) { PrimeSwampNPCsPlugin.Log(Profession + ": native player melee started at contact distance " + contactDistance.ToString("F2")); } } } private void RegisterReactions() { View.Register<ZDOID, ZDOID>("PrimeNPC_WitnessDamage", (Action<long, ZDOID, ZDOID>)OnWitnessDamage); View.Register<int, ZDOID, Vector3>("PrimeNPC_RequestReaction", (Action<long, int, ZDOID, Vector3>)OnReactionRequest); View.Register<int, string>("PrimeNPC_Reaction", (Action<long, int, string>)OnReaction); } private static Character ReactionActor(ZDOID id) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(id) : null); if (!Object.op_Implicit((Object)(object)val)) { return null; } return val.GetComponent<Character>(); } private void OnWitnessDamage(long sender, ZDOID playerId, ZDOID pieceId) { //IL_0067: 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_009a: 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_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_00bc: 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_0117: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)View) || !View.IsValid() || !View.IsOwner() || !initialized || ((Character)Human).IsDead() || InCombat || fleeing || Now < nextWitnessRequest) { return; } ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(pieceId) : null); Character val2 = ReactionActor(playerId); if (val != null && val.GetOwner() == sender && Object.op_Implicit((Object)(object)val2) && val2.IsPlayer() && !val2.IsDead() && SettlementWitness.Property(val.GetPosition())) { Vector3 val3 = val.GetPosition() - ((Component)this).transform.position; if (!(((Vector3)(ref val3)).sqrMagnitude > 400f) && ((BaseAI)AI).CanSeeTarget(val2)) { nextWitnessRequest = Now + 20000000; View.InvokeRPC(ServerPeer, "PrimeNPC_RequestReaction", new object[3] { 1, pieceId, val.GetPosition() }); } } } private void TryCombatReaction() { //IL_00f0: 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) Character targetCreature = ((BaseAI)AI).GetTargetCreature(); if (!NpcReactionPolicy.Combat(Object.op_Implicit((Object)(object)targetCreature) && targetCreature.IsPlayer(), ((BaseAI)AI).IsAggravated(), InCombat, fleeing)) { playerCombat = false; return; } bool flag = !playerCombat; playerCombat = true; if (flag || Now >= nextCombatReaction) { if (reactionRandom == 0) { reactionRandom = identity ^ 0xB5297A4Du; } nextCombatReaction = Now + (long)((18.0 + NpcPolicy.Unit(ref reactionRandom) * 12.0) * 10000000.0); if (flag || NpcPolicy.Unit(ref reactionRandom) < 0.45) { View.InvokeRPC(ServerPeer, "PrimeNPC_RequestReaction", new object[3] { 2, targetCreature.GetZDOID(), Vector3.zero }); } } } private void OnReactionRequest(long sender, int kind, ZDOID context, Vector3 point) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_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_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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || sender != View.GetZDO().GetOwner() || ((Character)Human).IsDead() || (kind != 1 && kind != 2)) { return; } ZDO zDO = View.GetZDO(); long now = Now; if (!NpcReactionPolicy.Cooldown(now, zDO.GetLong("PrimeNPC_nextReaction", 0L))) { return; } if (kind == 1) { if (InCombat || float.IsNaN(point.x) || float.IsNaN(point.y) || float.IsNaN(point.z)) { return; } Vector3 val = point - ((Component)this).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 400f || !SettlementWitness.Property(point)) { return; } } else { Character val2 = ReactionActor(context); if (!Object.op_Implicit((Object)(object)val2) || !val2.IsPlayer() || val2.IsDead() || !zDO.GetBool(AggravatedKey, false) || !InCombat) { return; } } if ((Object)(object)speechWorld != (Object)(object)ZNet.instance) { SpeechGate.Clear(); speechWorld = ZNet.instance; } if (SpeechGate.TryReserve(((Component)this).transform.position.x, ((Component)this).transform.position.z, (double)now / 10000000.0, 8.0, 20.0)) { uint seed = (uint)(((object)Unsafe.As<ZDOID, ZDOID>(ref zDO.m_uid)/*cast due to .constrained prefix*/).GetHashCode() ^ (int)(now / 10000000)); string text = NpcReactionPolicy.Choose(Profession, kind, zDO.GetString("PrimeNPC_lastReaction", ""), ref seed); zDO.Set("PrimeNPC_lastReaction", text); zDO.Set("PrimeNPC_nextReaction", now + 200000000); View.InvokeRPC(ZNetView.Everybody, "PrimeNPC_Reaction", new object[2] { kind, text }); } } private void OnReaction(long sender, int kind, string text) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_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_0098: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)View) && View.IsValid() && sender == ServerPeer && Object.op_Implicit((Object)(object)Chat.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && (kind == 1 || kind == 2) && !((Character)Human).IsDead()) { Vector3 val = ((Component)Player.m_localPlayer).transform.position - ((Component)this).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > 400f)) { Chat.instance.SetNpcText(((Component)this).gameObject, new Vector3(0f, 2.1f, 0f), 20f, 5f, Definition.DisplayName, text, false); } } } private void Start() { View = ((Component)this).GetComponent<ZNetView>(); Human = ((Component)this).GetComponent<Humanoid>(); AI = ((Component)this).GetComponent<MonsterAI>(); visuals = ((Component)this).GetComponent<VisEquipment>(); animationSync = ((Component)this).GetComponent<ZSyncAnimation>(); animator = ((Component)this).GetComponentInChildren<Animator>(); if (!PrimeSwampNPCsPlugin.Definitions.TryGetValue(Profession, out Definition) || !Object.op_Implicit((Object)(object)View) || !Object.op_Implicit((Object)(object)Human) || !Object.op_Implicit((Object)(object)AI)) { ((Behaviour)this).enabled = false; return; } View.Register<ZDOID>("PrimeNPC_Provoked", (Action<long, ZDOID>)OnProvoked); View.Register<string>("PrimeNPC_Speech", (Action<long, string>)OnSpeech); View.Register<string>("PrimeNPC_RequestSpeech", (Action<long, string>)OnSpeechRequest); if (NpcCivilianPolicy.Supported(Profession)) { View.Register("PrimeNPC_CancelFarmPose", (Action<long>)OnCancelFarmPose); } Humanoid human = Human; ((Character)human).m_onDeath = (Action)Delegate.Combine(((Character)human).m_onDeath, new Action(NativeDeath)); RegisterReactions(); Instances.Add(this); } private void Update() { timer -= Time.deltaTime; if (timer > 0f || !Object.op_Implicit((Object)(object)View) || !View.IsValid()) { return; } timer = 0.25f; if (!initialized && !Initialize()) { return; } bool flag = View.IsOwner(); if (flag && !inventoryBuilt) { initialized = false; if (!Initialize()) { return; } } if (flag && !wasOwner) { ApplyAppearance(); equipmentMode = -1; ResetFarmerRoutine(); ResetSwimmerRoutine(); } wasOwner = flag; if (!flag || ((Character)Human).IsDead() || ((Character)Human).GetHealth() <= 0f) { return; } Equip(InCombat); TryCombatReaction(); if (hadDanger && !InCombat && !fleeing) { View.GetZDO().Set("PrimeNPC_recentDanger", Now + 900000000); } hadDanger = InCombat || fleeing; if (!InCombat) { TrySpeech(); TryWork(); } if (appearanceAudit >= 0f) { appearanceAudit -= 0.25f; if (appearanceAudit < 0f) { AuditAppearance(); } } } private bool Initialize() { //IL_0419: 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_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Expected O, but got Unknown //IL_054d: Unknown result type (might be due to invalid IL or missing references) //IL_0552: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_0635: Unknown result type (might be due to invalid IL or missing references) //IL_063c: Invalid comparison between Unknown and I4 ZDO zDO = View.GetZDO(); identity = (uint)((object)Unsafe.As<ZDOID, ZDOID>(ref zDO.m_uid)/*cast due to .constrained prefix*/).GetHashCode(); random = NpcProfessionPolicy.AppearanceSeed(Profession, identity); string text = zDO.GetString("PrimeNPC_appearance", ""); int num = NpcCivilianPolicy.AppearanceVersion(Profession); if (string.IsNullOrEmpty(text) || zDO.GetInt("PrimeNPC_lookVersion", 0) < num) { if (!View.IsOwner()) { return false; } AppearanceRecord appearanceRecord = null; try { if (!string.IsNullOrEmpty(text)) { appearanceRecord = JsonConvert.DeserializeObject<AppearanceRecord>(text); } } catch (JsonException) { } Look = MakeAppearance(appearanceRecord?.Gender ?? zDO.GetInt("PrimeNPC_gender", Definition.Gender)); if (appearanceRecord != null) { NpcClothingPolicy.Migrate(Definition, appearanceRecord, Look); } Look.CombatArmor = ((appearanceRecord != null && appearanceRecord.CombatArmor >= 0f) ? appearanceRecord.CombatArmor : NpcCosmetics.Protection(Definition.BaseArmor, appearanceRecord?.ProtectionItems ?? appearanceRecord?.Armor ?? Look.ProtectionItems, SourceArmor)); zDO.Set("PrimeNPC_appearance", JsonConvert.SerializeObject((object)Look)); zDO.Set("PrimeNPC_lookVersion", num); } else { Look = JsonConvert.DeserializeObject<AppearanceRecord>(text); } if (NpcCivilianPolicy.Supported(Profession) && Look != null && Look.Gender == 1 && !string.IsNullOrEmpty(Look.Beard)) { Look.Beard = ""; if (View.IsOwner()) { zDO.Set("PrimeNPC_appearance", JsonConvert.SerializeObject((object)Look)); } } if (!NpcOutfitPolicy.RecordCompatible(Definition, Look) || Look.CombatArmor < 0f) { PrimeSwampNPCsPlugin.Warn(Profession + ": invalid saved outfit/protection; cannot initialize."); ((Behaviour)this).enabled = false; return false; } if (!View.IsOwner()) { initialized = true; return true; } Inventory inventory = Human.GetInventory(); Human.UnequipAllItems(); inventory.RemoveAll(); HiddenRight.Invoke(Human) = (HiddenLeft.Invoke(Human) = null); ApplyModel(); string[] armor = Look.Armor; foreach (string id in armor) { ItemData val = AddItem(id, cosmetic: true); if (val != null && View.IsOwner()) { Human.EquipItem(val, false); } } Weapon = AddItem(Look.Weapon); shield = AddItem(Look.Shield); peace = AddItem(Look.Peace); if (Definition.TorchEligible) { torch = AddItem("Torch"); } if (Look.Weapon == "BowHuntsman") { Arrow = AddItem("ArrowIron"); if (Arrow != null && View.IsOwner()) { Human.EquipItem(Arrow, false); } } List<Drop> list = new List<Drop>(); LootRule[] array = Definition.Drops ?? Array.Empty<LootRule>(); int num2 = ((Profession == "PrimeFarmer") ? NpcPolicy.Pick(ref random, array.Length) : (-1)); for (int j = 0; j < array.Length; j++) { if (num2 < 0 || j == num2) { LootRule lootRule = array[j]; GameObject val2 = NpcFactory.Find(lootRule.Prefab); if (Object.op_Implicit((Object)(object)val2)) { list.Add(new Drop { m_prefab = val2, m_amountMin = lootRule.Min, m_amountMax = lootRule.Max, m_chance = lootRule.Chance, m_levelMultiplier = false, m_onePerPlayer = false }); } else { PrimeSwampNPCsPlugin.Warn(Profession + ": missing drop " + lootRule.Prefab); } } } ((Component)this).GetComponent<CharacterDrop>().m_drops = list; if (View.IsOwner()) { if (!zDO.GetBool("PrimeNPC_healthV2", false)) { ((Character)Human).SetMaxHealth(Definition.Health * (float)((Character)Human).GetLevel()); if (string.IsNullOrEmpty(text)) { ((Character)Human).SetHealth(((Character)Human).GetMaxHealth()); } zDO.Set("PrimeNPC_healthV2", true); } if (!zDO.GetBool("PrimeNPC_homeSet", false)) { zDO.Set("PrimeNPC_home", ((Component)this).transform.position); zDO.Set("PrimeNPC_homeSet", true); } SetPatrol((BaseAI)(object)AI, zDO.GetVec3("PrimeNPC_home", ((Component)this).transform.position)); ApplyAppearance(); if (zDO.GetLong("PrimeNPC_nextSpeech", 0L) <= Now) { ScheduleSpeech(zDO); } } if ((peace != null || NpcCivilianPolicy.Additional(Profession) || Profession == "PrimeWarrior") && Object.op_Implicit((Object)(object)animator)) { canWork = false; workTrigger = ((NpcCivilianPolicy.Additional(Profession) || Profession == "PrimeWarrior") ? NpcCivilianPolicy.WorkTrigger(Definition.Activity.Mode, Look.Peace) : peace.m_shared.m_attack.m_attackAnimation); AnimatorControllerParameter[] parameters = animator.parameters; foreach (AnimatorControllerParameter val3 in parameters) { if ((int)val3.type == 9 && val3.name == workTrigger) { canWork = true; } } } workTimer = 10f + (float)NpcPolicy.Unit(ref random) * 15f; inventoryBuilt = true; initialized = true; appearanceAudit = 0.5f; return true; } private AppearanceRecord MakeAppearance(int requestedGender) { return NpcPolicy.CreateAppearance(Definition, PrimeSwampNPCsPlugin.Appearance, requestedGender, ref random, PrimeSwampNPCsPlugin.CultivatorChance.Value, PrimeSwampNPCsPlugin.FarmerFemaleChance.Value); } private static float SourceArmor(string id) { GameObject val = NpcFactory.Find(id); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.GetComponent<ItemDrop>())) { return 0f; } return val.GetComponent<ItemDrop>().m_itemData.GetArmor(); } private void ApplyModel() { View.GetZDO().Set(ModelIndexKey, Look.Gender, false); visuals.SetModel(Look.Gender); RefreshBody(visuals); } internal void PrepareRagdoll(VisEquipment target) { //IL_00a6: 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) if (Look != null && Object.op_Implicit((Object)(object)target)) { ZNetView component = ((Component)target).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner()) { component.GetZDO().Set(ModelIndexKey, Look.Gender, false); target.SetModel(Look.Gender); RefreshBody(target); AppearanceFile appearance = PrimeSwampNPCsPlugin.Appearance; Rgb rgb = appearance.Skin[Look.Skin]; Rgb rgb2 = appearance.Hair[Look.HairColor]; target.SetSkinColor(new Vector3(rgb.R, rgb.G, rgb.B)); target.SetHairColor(new Vector3(rgb2.R, rgb2.G, rgb2.B)); } } } private void ApplyAppearance() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Invalid comparison between Unknown and I4 //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Invalid comparison between Unknown and I4 //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Invalid comparison between Unknown and I4 AppearanceFile appearance = PrimeSwampNPCsPlugin.Appearance; Rgb rgb = appearance.Skin[Math.Min(Look.Skin, appearance.Skin.Length - 1)]; Rgb rgb2 = appearance.Hair[Math.Min(Look.HairColor, appearance.Hair.Length - 1)]; ApplyModel(); visuals.SetSkinColor(new Vector3(rgb.R, rgb.G, rgb.B)); visuals.SetHairColor(new Vector3(rgb2.R, rgb2.G, rgb2.B)); Human.SetHair(Look.Hair); Human.SetBeard(Look.Beard); foreach (ItemData allItem in Human.GetInventory().GetAllItems()) { if ((int)allItem.m_shared.m_itemType == 7 || (int)allItem.m_shared.m_itemType == 11 || (int)allItem.m_shared.m_itemType == 6) { Human.EquipItem(allItem, false); } } } private ItemData AddItem(string id, bool cosmetic = false) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(id)) { return null; } GameObject val = NpcFactory.Find(id); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.GetComponent<ItemDrop>())) { PrimeSwampNPCsPlugin.Warn(Profession + ": missing equipment " + id); return null; } ItemData val2 = val.GetComponent<ItemDrop>().m_itemData.Clone(); val2.m_shared = NpcFactory.CopyShared(val2.m_shared); val2.m_dropPrefab = val; if (cosmetic) { NpcCosmetics.StripBenefits(val2.m_shared); } val2.m_shared.m_useDurability = false; val2.m_shared.m_aiTargetType = (AiTarget)0; val2.m_shared.m_aiAttackInterval = 2f; val2.m_shared.m_aiAttackRange = ((id == "BowHuntsman") ? 25 : 2); val2.m_shared.m_aiAttackRangeMin = ((id == "BowHuntsman") ? 2 : 0); val2.m_shared.m_aiAttackMaxAngle = 45f; val2.m_shared.m_aiWhenWalking = true; val2.m_shared.m_aiWhenSwiming = true; if (!Human.GetInventory().AddItem(val2)) { return null; } return val2; } internal void Equip(bool combat) { //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Invalid comparison between Unknown and I4 if (!initialized || !View.IsOwner()) { return; } bool flag = NpcPolicy.Torch(identity, (Profession == "PrimeWarrior") ? PrimeSwampNPCsPlugin.WarriorTorchChance.Value : PrimeSwampNPCsPlugin.TorchChance.Value, EnvMan.IsNight(), combat, Definition.TorchEligible); int num = NpcBehaviorPolicy.Equipment(combat, fleeing, flag && torch != null); if (num == equipmentMode || (Profession == "PrimeWarrior" && ((Character)Human).InAttack())) { return; } equipmentMode = num; appearanceAudit = 0.5f; View.GetZDO().Set("PrimeNPC_combat", num == 2); if (Human.RightItem != null) { Human.UnequipItem(Human.RightItem, false); } if (Human.LeftItem != null) { Human.UnequipItem(Human.LeftItem, false); } if (Profession == "PrimeWarrior" && num == 1) { if (Weapon != null && NpcFinalPolicy.OneHanded(Look.Weapon)) { Human.EquipItem(Weapon, false); } Human.EquipItem(torch, false); return; } ItemData val = ((num == 1) ? torch : ((num == 0 && peace != null) ? peace : Weapon)); if (val != null) { Human.EquipItem(val, false); } if ((num == 2 || (Profession == "PrimeWarrior" && num == 0)) && shield != null && Weapon != null && (int)Weapon.m_shared.m_itemType == 3) { Human.EquipItem(shield, false); } } internal static void AlertNearby(Vector3 point, Character attacker, string homeKey) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_00af: Unknown result type (might be due to invalid IL or missing references) foreach (NpcRuntime instance in Instances) { if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.View) || !instance.View.IsValid()) { continue; } Vector3 val = ((Component)instance).transform.position - point; if (!(((Vector3)(ref val)).sqrMagnitude > 400f) && (homeKey == null || !(instance.View.GetZDO().GetString("PrimeNPC_settlement", "") != homeKey)) && (attacker.IsPlayer() || BaseAI.IsEnemy((Character)(object)instance.Human, attacker))) { if (instance.View.IsOwner()) { instance.OnProvoked(0L, attacker.GetZDOID()); continue; } instance.View.InvokeRPC("PrimeNPC_Provoked", new object[1] { attacker.GetZDOID() }); } } } private void OnProvoked(long sender, ZDOID attackerId) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_00c9: Unknown result type (might be due to invalid IL or missing references) if (!View.IsOwner() || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } GameObject val = ZNetScene.instance.FindInstance(attackerId); Character val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Character>() : null); if (!Object.op_Implicit((Object)(object)val2) || !PriestTargetSafe(val2) || Object.op_Implicit((Object)(object)((Component)val2).GetComponent<NpcRuntime>()) || !initialized || val2.IsDead() || Vector3.Distance(((Component)val2).transform.position, Home) > Definition.DefenseRadius) { return; } if (val2.IsPlayer()) { ((BaseAI)AI).SetAggravated(true, (AggravatedReason)0); return; } long num = Now + (long)(PrimeSwampNPCsPlugin.AngerSeconds.Value * 10000000f); ZDO zDO = View.GetZDO(); zDO.Set("PrimeNPC_threat", attackerId); zDO.Set("PrimeNPC_threatUntil", num); danger = val2; InterruptFarmerRoutine(); SetAlert(AI, arg2: true); fleeing = NpcBehaviorPolicy.Flee(Profession, ((Character)Human).GetHealthPercentage(), Definition.RetreatHealthFraction, threat: true); if (!fleeing && (val2.IsPlayer() || BaseAI.IsEnemy((Character)(object)Human, val2))) { SetTarget(AI, val2); Equip(combat: true); } } private void TrySpeech() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = View.GetZDO(); long now = Now; if (zDO.GetLong("PrimeNPC_nextSpeech", 0L) > now) { return; } ScheduleSpeech(zDO); if (NpcBehaviorPolicy.Speech((float)NpcPolicy.Unit(ref random), PrimeSwampNPCsPlugin.SpeechChance.Value, InCombat || fleeing, neighbourSpeaking: false) && Player.IsPlayerInRange(((Component)this).transform.position, PrimeSwampNPCsPlugin.DialogueDistance.Value)) { string text = NpcPolicy.ChooseSpeech(PrimeSwampNPCsPlugin.Dialogue[Profession].Lines, bonemass: Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetGlobalKey("defeated_bonemass"), last: zDO.GetString("PrimeNPC_lastLine", ""), afterDanger: zDO.GetLong("PrimeNPC_recentDanger", 0L) > now, random: ref random); if (!string.IsNullOrEmpty(text)) { zDO.Set("PrimeNPC_lastLine", text); View.InvokeRPC(ServerPeer, "PrimeNPC_RequestSpeech", new object[1] { text }); } } } private void OnSpeech(long sender, string text) { //IL_0068: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)View) && View.IsValid() && ZRoutedRpc.instance != null && sender == ServerPeer && Object.op_Implicit((Object)(object)Chat.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && !InCombat && !fleeing && Chat.instance.CurrentNpcTexts() <= 0) { Vector3 val = ((Component)Player.m_localPlayer).transform.position - ((Component)this).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > 144f)) { Chat.instance.SetNpcText(((Component)this).gameObject, new Vector3(0f, 2.1f, 0f), 12f, 5f, Definition.DisplayName, text, false); } } } private void TryWork() { //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) if (NpcCivilianPolicy.Supported(Profession) || !Definition.Work || !canWork || !Object.op_Implicit((Object)(object)animationSync) || peace == null || ((Character)Human).InAttack()) { return; } workTimer -= 0.25f; if (!(workTimer > 0f)) { Vector3 velocity = ((Character)Human).GetVelocity(); if (!(((Vector3)(ref velocity)).sqrMagnitude > 0.2f)) { workTimer = 20f + (float)NpcPolicy.Unit(ref random) * 25f; animationSync.SetTrigger(workTrigger); } } } private void OnDestroy() { Instances.Remove(this); if (Object.op_Implicit((Object)(object)Human)) { Humanoid human = Human; ((Character)human).m_onDeath = (Action)Delegate.Remove(((Character)human).m_onDeath, new Action(NativeDeath)); } } private void ScheduleSpeech(ZDO zdo) { float num = Mathf.Max(1f, PrimeSwampNPCsPlugin.SpeechMin.Value); float num2 = Mathf.Max(num, PrimeSwampNPCsPlugin.SpeechMax.Value); zdo.Set("PrimeNPC_nextSpeech", Now + (long)(((double)num + NpcPolicy.Unit(ref random) * (double)(num2 - num)) * 10000000.0)); } private void OnSpeechRequest(long sender, string text) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || sender != View.GetZDO().GetOwner() || ((Character)Human).IsDead() || InCombat || fleeing || !Player.IsPlayerInRange(((Component)this).transform.position, PrimeSwampNPCsPlugin.DialogueDistance.Value) || !PrimeSwampNPCsPlugin.Dialogue.TryGetValue(Profession, out var value) || !Array.Exists(value.Lines, (DialogueLine l) => l.Text == text)) { return; } if ((Object)(object)speechWorld != (Object)(object)ZNet.instance) { SpeechGate.Clear(); speechWorld = ZNet.instance; } double now = (double)Now / 10000000.0; if (SpeechGate.TryReserve(((Component)this).transform.position.x, ((Component)this).transform.position.z, now, Math.Max(6f, PrimeSwampNPCsPlugin.SpeechSpacing.Value))) { View.InvokeRPC(ZNetView.Everybody, "PrimeNPC_Speech", new object[1] { text }); EffectList speechEffects = PrimeSwampNPCsPlugin.SpeechEffects; if (speechEffects != null) { speechEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID)); } } } private void ResetSwimmerRoutine() { if (!(Profession != "PrimeSwimmer")) { bathClock.Advance(0f, danger: true, arrived: false, 0f, 0f, workOpportunity: false); bathClock.Advance(0f, danger: false, arrived: false, 0f, 0f, workOpportunity: false); bathRetry = 0f; bathDanger = false; threatScan = 0f; } } internal void UpdateSwimmerActivity(float dt) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_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_00d5: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: 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_016f: 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_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0279: 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_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: 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_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: 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) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) if (!OwnsSwimmerMovement) { return; } CivilianActivity activity = Definition.Activity; if (!activity.Enabled) { FarmStop((BaseAI)(object)AI); return; } if ((int)((BaseAI)AI).m_pathAgentType != 1) { ((BaseAI)AI).m_pathAgentType = (AgentType)1; LastFarmPath.Invoke((BaseAI)(object)AI) = -1000f; } float radius = NpcFarmerPolicy.Radius(activity.Radius, Definition.DefenseRadius); bool flag = fleeing && Object.op_Implicit((Object)(object)danger) && !danger.IsDead(); if (flag != bathDanger) { ResetSwimmerRoutine(); bathDanger = flag; } Vector3 val = ((Component)this).transform.position - Home; val.y = 0f; if (!NpcFinalPolicy.BathInside(val.x, val.z, radius)) { Vector3 point = Home; if (BathDestinationSafe(ref point)) { MoveHome((BaseAI)(object)AI, dt, point, 0.5f, flag); } else { FarmStop((BaseAI)(object)AI); } return; } if (InCombat) { bathClock.Advance(0f, danger: true, arrived: false, 0f, 0f, workOpportunity: false); Character targetCreature = ((BaseAI)AI).GetTargetCreature(); if (Object.op_Implicit((Object)(object)targetCreature)) { Vector3 val2 = ((Component)targetCreature).transform.position - Home; if (!NpcFinalPolicy.BathInside(val2.x, val2.z, radius)) { FarmStop((BaseAI)(object)AI); } } return; } bool flag2 = bathClock.Phase == FarmerPhase.Walking && MoveHome((BaseAI)(object)AI, dt, bathDestination, 0.5f, flag); if (bathClock.Phase != FarmerPhase.Walking) { FarmStop((BaseAI)(object)AI); } float pause = (flag2 ? FarmDuration(activity.IdleMinimumSeconds, activity.IdleMaximumSeconds) : 0f); bathClock.Advance(dt, danger: false, flag2, pause, 0f, workOpportunity: false); if (bathClock.Phase != FarmerPhase.Seeking) { return; } bathRetry -= dt; if (bathRetry > 0f) { return; } bathRetry = (flag ? 1 : 3); bool flag3 = false; Vector3 val3 = default(Vector3); float current = (flag ? Vector3.Distance(((Component)this).transform.position, ((Component)danger).transform.position) : 0f); for (int i = 0; i < 4; i++) { NpcFarmerPolicy.Destination(ref random, radius, out var x, out var z); Vector3 point2 = Home + new Vector3(x, 0f, z); if (Vector3.Distance(point2, ((Component)this).transform.position) < activity.MinimumTravelDistance || !BathDestinationSafe(ref point2)) { continue; } if (flag) { float num = Vector3.Distance(point2, ((Component)danger).transform.position); if (!NpcFinalPolicy.Safer(num, current)) { continue; } current = num; } val3 = point2; flag3 = true; if (!flag) { break; } } if (flag3) { bathDestination = val3; bathClock.BeginWalk(activity.WalkTimeoutSeconds); } else { FarmStop((BaseAI)(object)AI); } } private bool BathDestinationSafe(ref Vector3 point) { //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_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_004d: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0095: 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_00d9: 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_00ad: 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) if (!Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return false; } Vector3 val = point - Home; val.y = 0f; float radius = NpcFarmerPolicy.Radius(Definition.Activity.Radius, Definition.DefenseRadius); if (!NpcFinalPolicy.BathInside(val.x, val.z, radius) || !BathFloor(ref point)) { return false; } Vector3 val2 = ((Component)this).transform.position; for (int i = 1; i <= 4; i++) { Vector3 point2 = Vector3.Lerp(((Component)this).transform.position, point, (float)i / 4f); if (!BathFloor(ref point2) || Mathf.Abs(point2.y - val2.y) > 0.7f) { return false; } val2 = point2; } return FarmHavePath((BaseAI)(object)AI, point); } private bool BathFloor(ref Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_007d: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_0136: 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_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) if (!Object.op_Implicit((Object)(object)Heightmap.FindHeightmap(point))) { return false; } int mask = LayerMask.GetMask(new string[3] { "terrain", "static_solid", "piece" }); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(new Vector3(point.x, Home.y + 3f, point.z), Vector3.down, ref val, 8f, mask, (QueryTriggerInteraction)1)) { return false; } float depth = ZoneSystem.instance.m_waterLevel - ((RaycastHit)(ref val)).point.y; point.y = Mathf.Max(((RaycastHit)(ref val)).point.y + 0.1f, ZoneSystem.instance.m_waterLevel - ((Character)Human).m_swimDepth + 0.05f); int mask2 = LayerMask.GetMask(new string[2] { "static_solid", "piece" }); bool clear = !Physics.CheckCapsule(point + Vector3.up * 0.4f, point + Vector3.up * 1.4f, 0.3f, mask2, (QueryTriggerInteraction)1); return NpcFinalPolicy.BathGround(depth, Definition.Activity.MaximumWaterDepth, Vector3.Angle(((RaycastHit)(ref val)).normal, Vector3.up), clear, ((RaycastHit)(ref val)).point.y - Home.y); } } internal static class NpcBehaviorPolicy { internal static bool Proactive(string id) { if (!(id == "PrimeWarrior")) { return id == "PrimeDruid"; } return true; } internal static bool Flee(string id, float healthFraction, float threshold, bool threat) { if (threat && !Proactive(id)) { return healthFraction <= threshold; } return false; } internal static bool Defend(bool hostile, bool provoked, bool immediateThreat, bool proactive, bool player, bool angryAtPlayer, float actorHomeDistance, float targetHomeDistance, float radius) { if (actorHomeDistance <= radius && targetHomeDistance <= radius) { if (!player) { if (hostile) { return provoked || immediateThreat || proactive; } return false; } return angryAtPlayer; } return false; } internal static int Equipment(bool combat, bool fleeing, bool torch) { if (!combat || fleeing) { if (!torch || fleeing) { return 0; } return 1; } return 2; } internal static bool Speech(float roll, float chance, bool combat, bool neighbourSpeaking) { if (!combat && !neighbourSpeaking) { return roll < Math.Max(0f, Math.Min(1f, chance)); } return false; } internal static bool BeginDeath(bool owner, bool alreadyStarted) { if (owner) { return !alreadyStarted; } return false; } internal static bool RemembersOffender(long now, long until, bool offender) { return now < until && offender; } internal static bool Retaliating(long now, long until, bool offender, bool inArea) { return now < until && offender && inArea; } internal static bool AcceptNpcDamage(bool targetNpc, bool attackerSettler, bool attackerPlayer, bool pvpEnabled) { if (!targetNpc) { return !attackerPlayer || pvpEnabled; } return !attackerSettler; } internal static float MigratedHealth(float health, float oldMax, float newMax) { return Math.Min(newMax, Math.Max(0f, (oldMax > 0f) ? (health / oldMax * newMax) : health)); } } internal sealed class NpcSpeechGate { private sealed class Reservation { internal double X; internal double Z; internal double Until; internal double Radius; } private readonly List<Reservation> reservations = new List<Reservation>(); internal void Clear() { reservations.Clear(); } internal bool TryReserve(double x, double z, double now, double quiet, double radius = 12.0) { reservations.RemoveAll((Reservation r) => r.Until <= now); foreach (Reservation reservation in reservations) { if ((reservation.X - x) * (reservation.X - x) + (reservation.Z - z) * (reservation.Z - z) <= Math.Max(radius, reservation.Radius) * Math.Max(radius, reservation.Radius)) { return false; } } reservations.Add(new Reservation { X = x, Z = z, Until = now + quiet, Radius = radius }); return true; } } internal static class NpcCivilianPolicy { internal static bool Original(string id) { if (!(id == "PrimeFarmer") && !(id == "PrimeCommoner")) { return id == "PrimeFisherman"; } return true; } internal static bool Additional(string id) { switch (id) { default: return id == "PrimeSculptor"; case "PrimeWitch": case "PrimeDruid": case "PrimePriest": return true; } } internal static bool Supported(string id) { if (!Original(id) && !Additional(id)) { return id == "PrimeWarrior"; } return true; } internal static bool ValidMode(string id, string mode) { if ((!(id == "PrimeCommoner") || !(mode == "Hammer")) && (!(id == "PrimeFisherman") || !(mode == "Fishing")) && (!(id == "PrimeWitch") || !(mode == "Ritual")) && (!(id == "PrimeDruid") || !(mode == "Observe")) && (!(id == "PrimePriest") || !(mode == "Prayer")) && (!(id == "PrimeSculptor") || !(mode == "Hammer")) && (!(id == "PrimeWarrior") || !(mode == "Patrol"))) { if (id == "PrimeSwimmer") { return mode == "Bath"; } return false; } return true; } internal static string WorkTrigger(string mode, string tool) { if (!(mode == "Ritual") || !(tool == "StaffGreenRoots")) { if (!(mode == "Prayer") || !(tool == "StaffShield")) { switch (mode) { case "Hammer": if (tool == "Hammer") { return "swing_hammer"; } goto default; default: if (!(mode == "Fishing") || !(tool == "FishingRod")) { return ""; } return "fishingrod_throw"; case "Observe": case "Patrol": return "emote_point"; } } return "staff_shield"; } return "staff_fireball0"; } internal static bool ShoreWater(float ground, float water, float distance, float searchDistance, bool loaded, bool clear) { if (loaded && clear && ground <= water - 1f && distance >= 2f) { return distance <= searchDistance; } return false; } internal static bool CanWork(string mode, bool shore) { return mode != "Fishing" || shore; } internal static int AppearanceVersion(string id) { if (!(id == "PrimeSwimmer")) { return 9; } return 7; } internal static float ContactRange(string weapon, float nativeReach) { switch (weapon) { default: return 2f; case "KnifeChitin": case "SwordIron": case "MaceIron": case "SpearElderbark": case "AxeIron": case "AtgeirIron": case "Battleaxe": return NpcMeleePolicy.ContactRange(nativeReach); } } } internal static class NpcClothingPolicy { internal static bool LegItem(string id) { switch (id) { default: return id == "ArmorIronLegs"; case "ArmorRagsLegs": case "ArmorLeatherLegs": case "ArmorTrollLeatherLegs": case "ArmorRootLegs": return true; } } internal static void Migrate(NpcDefinition definition, AppearanceRecord saved, AppearanceRecord result) { result.Gender = saved.Gender; result.Skin = saved.Skin; result.HairColor = saved.HairColor; result.Hair = saved.Hair; result.Beard = ((saved.Gender == 0) ? saved.Beard : ""); result.Weapon = saved.Weapon; result.Shield = saved.Shield; result.Peace = saved.Peace; result.ProtectionItems = saved.ProtectionItems ?? saved.Armor; result.CombatArmor = saved.CombatArmor; if (NpcOutfitPolicy.RecordCompatible(definition, saved)) { result.Armor = saved.Armor; return; } OutfitDefinition outfitDefinition = null; OutfitDefinition[] outfits = definition.Outfits; foreach (OutfitDefinition outfitDefinition2 in outfits) { if (outfitDefinition2.Gender == saved.Gender && NpcOutfitPolicy.Compatible(outfitDefinition2, definition.Id) && Array.IndexOf(saved.Armor ?? Array.Empty<string>(), outfitDefinition2.Chest) >= 0) { outfitDefinition = outfitDefinition2; break; } } List<string> list = new List<string>(); string[] armor; if (outfitDefinition != null) { if (outfitDefinition.Chest != "") { list.Add(outfitDefinition.Chest); } if (outfitDefinition.Legs != "") { list.Add(outfitDefinition.Legs); } } else { armor = result.Armor; foreach (string text in armor) { if (!text.StartsWith("Helmet", StringComparison.Ordinal)) { list.Add(text); } } } string[] array = ((saved.Gender == 0) ? definition.MaleHelmets : definition.FemaleHelmets); armor = saved.Armor ?? Array.Empty<string>(); foreach (string text2 in armor) { if (text2.StartsWith("Helmet", StringComparison.Ordinal) && Array.IndexOf(array ?? Array.Empty<string>(), text2) >= 0) { list.Add(text2); break; } } result.Armor = list.ToArray(); } } internal sealed class NpcConfiguration { internal ProfessionFile Professions; internal AppearanceFile Appearance; internal DialogueFile Dialogue; internal SettlementFile Settlements; } internal static class NpcConfigurationLoader { private static readonly string[] ExpectedIds = new string[9] { "PrimeFarmer", "PrimeSwimmer", "PrimeDruid", "PrimeWitch", "PrimeFisherman", "PrimeWarrior", "PrimePriest", "PrimeCommoner", "PrimeSculptor" }; internal static NpcConfiguration LoadDirectory(string directory) { string text = Path.Combine(directory, "professions.json"); string text2 = Path.Combine(directory, "appearance.json"); string text3 = Path.Combine(directory, "dialogue.json"); string text4 = Path.Combine(directory, "settlements.json"); NpcConfiguration npcConfiguration = new NpcConfiguration { Professions = Read<ProfessionFile>(text), Appearance = Read<AppearanceFile>(text2), Dialogue = Read<DialogueFile>(text3), Settlements = Read<SettlementFile>(text4) }; HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); NpcDefinition[] array = Array(npcConfiguration.Professions.Professions, text, "Professions", nonempty: true); Require(array.Length == ExpectedIds.Length, text, "Professions", "must contain all nine professions"); for (int i = 0; i < array.Length; i++) { NpcDefinition npcDefinition = array[i]; string text5 = "Professions[" + i + "]"; Text(npcDefinition.Id, text, text5 + ".Id"); Text(npcDefinition.DisplayName, text, text5 + ".DisplayName"); Require(System.Array.IndexOf(ExpectedIds, npcDefinition.Id) >= 0 && hashSet.Add(npcDefinition.Id), text, text5 + ".Id", "must be a unique supported Prime NPC ID"); Require(npcDefinition.Gender >= -1 && npcDefinition.Gender <= 1, text, text5 + ".Gender", "must be -1, 0 or 1"); Number(npcDefinition.Health, 0f, float.MaxValue, text, text5 + ".Health", inclusive: false); Number(npcDefinition.WanderRadius, 0f, float.MaxValue, text, text5 + ".WanderRadius"); Number(npcDefinition.HelmetChance, 0f, 1f, text, text5 + ".HelmetChance"); Number(npcDefinition.FemaleChance, 0f, 1f, text, text5 + ".FemaleChance"); Number(npcDefinition.CosmeticHelmetChance, -1f, 1f, text, text5 + ".CosmeticHelmetChance"); Require(npcDefinition.Id == "PrimeFarmer" || (!NpcCivilianPolicy.Supported(npcDefinition.Id) && !NpcFinalPolicy.Final(npcDefinition.Id)) || npcDefinition.Activity != null, text, text5 + ".Activity", "required civilian activity settings are missing or null"); if (npcDefinition.Activity != null) { CivilianActivity a = npcDefinition.Activity; string text6 = text5 + ".Activity"; Require(NpcCivilianPolicy.ValidMode(npcDefinition.Id, a.Mode), text, text6 + ".Mode", "mode must match the civilian profession; Farmer keeps its existing cfg routine"); if (NpcCivilianPolicy.Additional(npcDefinition.Id)) { if (a.Mode == "Observe") { Require(npcDefinition.PeaceItems != null && npcDefinition.PeaceItems.Length == 0, text, text6, "observers retain their configured combat item while peaceful"); } else { Require(npcDefinition.PeaceItems != null && npcDefinition.PeaceItems.Length != 0 && System.Array.TrueForAll(npcDefinition.PeaceItems, (string tool) => NpcCivilianPolicy.WorkTrigger(a.Mode, tool) != ""), text, text6, "activity requires its verified decorative tool"); } } Number(a.Radius, 3f, 30f, text, text6 + ".Radius"); Number(a.MinimumTravelDistance, 1f, a.Radius, text, text6 + ".MinimumTravelDistance"); Number(a.WalkTimeoutSeconds, 4f, 60f, text, text6 + ".WalkTimeoutSeconds"); Number(a.IdleMinimumSeconds, 1f, 60f, text, text6 + ".IdleMinimumSeconds"); Number(a.IdleMaximumSeconds, a.IdleMinimumSeconds, 60f, text, text6 + ".IdleMaximumSeconds"); Number(a.WorkMinimumSeconds, 1f, 60f, text, text6 + ".WorkMinimumSeconds"); Number(a.WorkMaximumSeconds, a.WorkMinimumSeconds, 60f, text, text6 + ".WorkMaximumSeconds"); Number(a.WorkChance, 0f, 1f, text, text6 + ".WorkChance"); Number(a.MaximumWaterDepth, 0f, (npcDefinition.Id == "PrimeSwimmer") ? 2.5f : 0.4f, text, text6 + ".MaximumWaterDepth"); Number(a.ShoreChance, 0f, 1f, text, text6 + ".ShoreChance"); Number(a.ShoreSearchDistance, 2f, 12f, text, text6 + ".ShoreSearchDistance"); } if (npcDefinition.Id == "PrimeSwimmer") { Require(npcDefinition.CombatWeapons != null && npcDefinition.CombatWeapons.Length == 0 && npcDefinition.PeaceItems != null && npcDefinition.PeaceItems.Length == 0 && npcDefinition.Shields != null && npcDefinition.Shields.Length == 0 && npcDefinition.Drops != null && npcDefinition.Drops.Length == 0 && npcDefinition.MaleHelmets != null && npcDefinition.MaleHelmets.Length == 0 && npcDefinition.FemaleHelmets != null && npcDefinition.FemaleHelmets.Length == 0 && npcDefinition.MaleChest != null && npcDefinition.MaleChest.Length == 0 && npcDefinition.FemaleChest != null && npcDefinition.FemaleChest.Length == 0 && npcDefinition.Legs != null && npcDefinition.Legs.Length == 0 && npcDefinition.BaseArmor == 0f && !npcDefinition.TorchEligible, text, text5, "Swimmers must have no weapons/tools/helmets/shields/torch or loot"); Require(npcDefinition.Activity.Radius <= 4f && npcDefinition.Activity.WorkChance == 0f, text, text5, "bath radius must be at most 4m with native water/rest idle only"); } Number(npcDefinition.BaseArmor, 0f, float.MaxValue, text, text5 + ".BaseArmor"); Number(npcDefinition.DefenseRadius, 1f, 100f, text, text5 + ".DefenseRadius"); Number(npcDefinition.ThreatRadius, 0f, npcDefinition.DefenseRadius, text, text5 + ".ThreatRadius"); Number(npcDefinition.RetreatHealthFraction, 0f, 1f, text, text5 + ".RetreatHealthFraction"); Strings(npcDefinition.MaleChest, text, text5 + ".MaleChest"); Strings(npcDefinition.FemaleChest, text, text5 + ".FemaleChest");
BepInEx/plugins/PrimeSwampRevival/PrimeSwampRevival.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BiomeRevival.PrimeSwampNPCs; using ExpandWorldData; using ExpandWorldData.Locations; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SoftReferenceableAssets; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PrimeSwampRevival")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.13.0")] [assembly: AssemblyInformationalVersion("0.1.13+nexus.1")] [assembly: AssemblyProduct("PrimeSwampRevival")] [assembly: AssemblyTitle("PrimeSwampRevival")] [assembly: AssemblyVersion("0.1.13.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; } } } namespace BiomeRevival.PrimeSwampRevival { internal sealed class ScheduledWork { internal readonly string Name; internal readonly Action Execute; internal ScheduledWork(string name, Action execute) { Name = name; Execute = execute; } } internal static class ActivationPipeline { private static IEnumerator<ScheduledWork> job; private static ZNet world; private static bool started; private static int failures; internal static bool Ready; internal static void Step() { if ((Object)(object)world != (Object)(object)ZNet.instance) { world = ZNet.instance; job?.Dispose(); job = null; started = false; Ready = false; failures = 0; } if (!PrimeSwampRevivalPlugin.GenerationAllowed) { return; } if (!started) { started = true; job = Integration.ActivationWork().GetEnumerator(); PrimeSwampRevivalPlugin.Instance?.Note("ACTIVATION_START cinematicReleased=True frame=" + Time.frameCount); } while (job != null && Performance.CanStart) { bool flag; try { flag = job.MoveNext(); } catch (Exception ex) { failures++; PrimeSwampRevivalPlugin.Instance?.Note("ACTIVATION_ENUMERATOR_FAILED " + ex); flag = false; } if (!flag) { job.Dispose(); job = null; Ready = Integration.ContentApplied; PrimeSwampRevivalPlugin.Instance?.Note("ACTIVATION_COMPLETE ready=" + Ready + " failedUnits=" + failures); break; } ScheduledWork current = job.Current; try { Performance.Run(current.Name, current.Execute); } catch (Exception ex2) { failures++; PrimeSwampRevivalPlugin.Instance?.Note("ACTIVATION_UNIT_FAILED " + current.Name + " " + ex2); } } } } internal static class ActivationPolicy { internal const double FrameMilliseconds = 4.0; internal const double SafetyMilliseconds = 40.0; internal const int MaximumUnits = 16; internal const int MaximumDeferred = 20000; internal static bool Ready(bool active, long start, long now, long duration, bool overlay, int frame, int releasedFrame) { if (active && (start <= 0 || now >= start + duration) && !overlay) { return frame > releasedFrame; } return false; } internal static bool CanStart(double spent, int units) { if (spent < 4.0) { return units < 16; } return false; } internal static bool Overdue(double elapsed, int checkpoints) { if (!(elapsed >= 40.0)) { return checkpoints > 100000; } return true; } } internal sealed class FrameAllowance { private int frame = -1; private int units; private double spent; internal bool CanStart => ActivationPolicy.CanStart(spent, units); internal void Reset(int value) { if (frame != value) { frame = value; units = 0; spent = 0.0; } } internal void Charge(double elapsed) { spent += Math.Max(0.0, elapsed); units++; } } internal static class AmbientPolicy { internal static bool Selected(string prefab, bool swamp) { if (swamp) { switch (prefab) { default: return prefab == "Fish2"; case "PrimeBoar": case "PrimeNeck": case "PrimeForestSpirit": case "Seagal": case "Fish1": return true; } } return false; } internal static bool DaySpirit(string prefab, bool day, bool night) { if (prefab == "PrimeForestSpirit" && day) { return !night; } return false; } internal static string TextureName(string supplied, string root) { return supplied ?? root ?? ""; } } internal static class BiomeState { private static readonly MethodInfo Clone = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); internal static BiomeEnvSetup NativeSwamp; private static EnvSetup nativeRain; private static EnvMan rainWorld; internal static void Install(Harmony harmony) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown Type type = AccessTools.TypeByName("ExpandWorldData.Biome.BiomeManager"); harmony.Patch((MethodBase)AccessTools.Method(type, "Initialize", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BiomeState), "Capture", (Type[])null) { priority = int.MaxValue }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(type, "SetupBiomeEnvs", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BiomeState), "GateEnvironments", (Type[])null) { priority = int.MaxValue }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Type type2 = AccessTools.TypeByName("ExpandWorldData.Environment.EnvironmentManager"); harmony.Patch((MethodBase)AccessTools.Method(type2, "Initialize", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BiomeState), "Capture", (Type[])null) { priority = int.MaxValue }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Type type3 = AccessTools.TypeByName("PrimeSwampTrees.PrimeSwampTreesPlugin"); if (type3 != null) { AccessTools.Field(type3, "RestorationGate")?.SetValue(null, (Func<bool>)(() => PrimeSwampRevivalPlugin.VisualReady)); } Type type4 = AccessTools.TypeByName("BiomeRevival.PrimeForestSpirit.PrimeForestSpiritPlugin"); if (type4 != null) { AccessTools.Field(type4, "RestorationGate")?.SetValue(null, (Func<bool>)(() => PrimeSwampRevivalPlugin.ContentReady)); } Type type5 = AccessTools.TypeByName("CustomTextures.BepInExPlugin"); if (type5 != null) { harmony.Patch((MethodBase)AccessTools.Method(type5, "SetupVisEquipment", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BiomeState), "NpcTextures", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static bool NpcTextures(Humanoid __0) { if (Object.op_Implicit((Object)(object)__0)) { return !Object.op_Implicit((Object)(object)((Component)__0).GetComponent<NpcRuntime>()); } return true; } private static void Capture() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)EnvMan.instance)) { return; } if ((Object)(object)rainWorld != (Object)(object)EnvMan.instance) { NativeSwamp = null; nativeRain = null; rainWorld = EnvMan.instance; } if (NativeSwamp == null) { BiomeEnvSetup val = ((IEnumerable<BiomeEnvSetup>)EnvMan.instance.m_biomes).FirstOrDefault((Func<BiomeEnvSetup, bool>)((BiomeEnvSetup b) => (int)b.m_biome == 2)); if (val != null) { NativeSwamp = (BiomeEnvSetup)Clone.Invoke(val, null); NativeSwamp.m_environments = ((IEnumerable<EnvEntry>)val.m_environments).Select((Func<EnvEntry, EnvEntry>)((EnvEntry e) => (EnvEntry)Clone.Invoke(e, null))).ToList(); } } if (nativeRain == null) { EnvSetup val2 = ((IEnumerable<EnvSetup>)EnvMan.instance.m_environments).FirstOrDefault((Func<EnvSetup, bool>)((EnvSetup e) => e.m_name == "SwampRain")); if (val2 != null) { nativeRain = (EnvSetup)Clone.Invoke(val2, null); } } } private static void GateEnvironments(ref List<BiomeEnvSetup> __0) { Capture(); if (PrimeSwampRevivalPlugin.VisualReady || NativeSwamp == null) { return; } __0 = __0.Where((BiomeEnvSetup b) => (int)b.m_biome != 2).Concat((IEnumerable<BiomeEnvSetup>)(object)new BiomeEnvSetup[1] { Copy(NativeSwamp) }).ToList(); if (nativeRain != null && Object.op_Implicit((Object)(object)EnvMan.instance)) { List<EnvSetup> environments = EnvMan.instance.m_environments; int num = environments.FindIndex((EnvSetup e) => e.m_name == "SwampRain"); if (num >= 0) { environments[num] = nativeRain; } } } internal static void Apply() { if (!Object.op_Implicit((Object)(object)EnvMan.instance)) { return; } List<BiomeEnvSetup> list = (List<BiomeEnvSetup>)Integration.Field("ExpandWorldData.Biome.BiomeManager", "Environments"); if (list.Count > 0) { AccessTools.Method(AccessTools.TypeByName("ExpandWorldData.Biome.BiomeManager"), "SetupBiomeEnvs", (Type[])null, (Type[])null).Invoke(null, new object[1] { list.Select(Copy).ToList() }); } AccessTools.Field(typeof(EnvMan), "m_environmentPeriod").SetValue(EnvMan.instance, -1L); AccessTools.Field(typeof(EnvMan), "m_ambientMusicTimer").SetValue(EnvMan.instance, 3f); PrimeSwampRevivalPlugin.Instance?.Note("ENVIRONMENT_REFRESH restored=" + PrimeSwampRevivalPlugin.VisualReady + " swamp=" + string.Join(",", from b in EnvMan.instance.m_biomes where (int)b.m_biome == 2 select b.m_musicDay + "/" + b.m_musicNight + ":" + string.Join(",", b.m_environments.Select((EnvEntry e) => e.m_environment)))); } private static BiomeEnvSetup Copy(BiomeEnvSetup source) { //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_0047: Expected O, but got Unknown BiomeEnvSetup val = (BiomeEnvSetup)Clone.Invoke(source, null); val.m_environments = ((IEnumerable<EnvEntry>)source.m_environments).Select((Func<EnvEntry, EnvEntry>)((EnvEntry e) => (EnvEntry)Clone.Invoke(e, null))).ToList(); return val; } } [HarmonyPatch(typeof(ZoneSystem), "SpawnLocation")] internal static class BlueprintWitness { internal sealed class Witness { internal string Name; internal int Expected; internal int Actual; internal int Invalid; internal Witness Previous; internal Action Npc; internal bool Releasing; } internal static Witness Current; internal static string Last = "No new Prime blueprint observed this session"; internal static int Minimum(string name, HashSet<string> visiting = null) { visiting = visiting ?? new HashSet<string>(); if (!visiting.Add(name)) { throw new InvalidOperationException("Recursive blueprint " + name); } object[] array = new object[2] { name, null }; if (!(bool)AccessTools.Method(AccessTools.TypeByName("ExpandWorldData.Data.BlueprintManager"), "TryGet", (Type[])null, (Type[])null).Invoke(null, array)) { throw new InvalidOperationException("Missing blueprint " + name); } int num = 0; int num2 = 0; foreach (object item in (IEnumerable)AccessTools.Field(array[1].GetType(), "Objects").GetValue(array[1])) { num2++; string text = (string)AccessTools.Field(item.GetType(), "Prefab").GetValue(item); float num3 = (float)AccessTools.Field(item.GetType(), "Chance").GetValue(item); int num4 = (Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(text)) ? 1 : Minimum(text, visiting)); if (num3 >= 1f) { num += num4; } } visiting.Remove(name); if (num2 == 0) { throw new InvalidOperationException("Empty blueprint " + name); } return num; } private static void Prefix(ZoneLocation __0, SpawnMode __4, out Witness __state) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 __state = null; FutureGeneration.Scope current = FutureGeneration.Current; if (current != null && current.Restored && (int)__4 != 1 && Integration.Name(__0).StartsWith("PrimeSwamp", StringComparison.Ordinal)) { __state = new Witness { Name = Integration.Name(__0), Previous = Current }; Current = __state; PrimeSwampRevivalPlugin.Instance?.Note("BLUEPRINT_BEGIN " + __state.Name); } } private static Exception Finalizer(Witness __state, Exception __exception) { if (__state == null) { return __exception; } try { int num = Minimum(__state.Name); bool flag = __exception == null && __state.Expected >= num && __state.Actual == __state.Expected && __state.Invalid == 0; Last = __state.Name + " factoryVerified=" + flag + " minimum=" + num + " expected=" + __state.Expected + " actual=" + __state.Actual; PrimeSwampRevivalPlugin.Instance?.Note("BLUEPRINT_END " + Last); if (flag && __state.Npc != null) { __state.Releasing = true; __state.Npc(); } } catch (Exception ex) { PrimeSwampRevivalPlugin.Instance?.Note("BLUEPRINT_VERIFY_FAILED " + __state.Name + " " + ex); } finally { Current = __state.Previous; } return __exception; } internal static GameObject Instantiate(GameObject prefab, Vector3 point, Quaternion rotation) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Witness current = Current; if (current != null) { current.Expected++; } GameObject val = Object.Instantiate<GameObject>(prefab, point, rotation); if (current != null) { if (Object.op_Implicit((Object)(object)val)) { current.Actual++; } else { current.Invalid++; } } return val; } internal static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> source) { int replaced = 0; foreach (CodeInstruction item in source) { if (item.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Object) && methodInfo.Name == "Instantiate" && methodInfo.IsGenericMethod && methodInfo.GetGenericArguments()[0] == typeof(GameObject)) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 3 && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion)) { item.operand = typeof(BlueprintWitness).GetMethod("Instantiate", BindingFlags.Static | BindingFlags.NonPublic); replaced++; } } yield return item; } if (replaced == 0) { throw new MissingMethodException("EWD physical factory changed"); } } } [HarmonyPatch(typeof(SettlementManager), "LocationInitialized")] internal static class FutureNpcInitialization { private static bool Prefix(SettlementManager __instance, ZoneLocation __0, Vector3 __1, SpawnMode __2) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) FutureGeneration.Scope current = FutureGeneration.Current; if (current == null || !current.Restored) { return false; } BlueprintWitness.Witness current2 = BlueprintWitness.Current; if (current2 == null || current2.Releasing) { return true; } current2.Npc = delegate { //IL_002e: 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) AccessTools.Method(typeof(SettlementManager), "LocationInitialized", (Type[])null, (Type[])null).Invoke(__instance, new object[3] { __0, __1, __2 }); }; return false; } } internal static class Cinematic { private static CanvasGroup screen; private static TMP_Text text; private static bool active; private static bool musicPlayed; private static long musicSequence; internal static int ReleasedFrame = -1; internal static bool Visible => active; internal static void Tick() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) double num = (double)(PrimeSwampRevivalPlugin.Now - PrimeSwampRevivalPlugin.sequenceStart) / 10000000.0; if (!PrimeSwampRevivalPlugin.Playing || !Object.op_Implicit((Object)(object)Hud.instance) || !Object.op_Implicit((Object)(object)MessageHud.instance)) { Release(); return; } if (!active) { screen = (CanvasGroup)AccessTools.Field(typeof(Hud), "m_loadingScreen").GetValue(Hud.instance); TMP_Text val = (TMP_Text)AccessTools.Field(typeof(MessageHud), "m_messageCenterText").GetValue(MessageHud.instance); if (!Object.op_Implicit((Object)(object)screen) || !Object.op_Implicit((Object)(object)val)) { return; } Cinematic.text = Object.Instantiate<TMP_Text>(val, ((Component)screen).transform, false); ((Object)Cinematic.text).name = "PrimeRevivalText"; Cinematic.text.transform.localPosition = Vector3.zero; ((Component)Cinematic.text).gameObject.SetActive(true); ((Graphic)Cinematic.text).canvasRenderer.SetAlpha(1f); ((Graphic)Cinematic.text).raycastTarget = false; if (musicSequence != PrimeSwampRevivalPlugin.sequenceStart) { musicSequence = PrimeSwampRevivalPlugin.sequenceStart; musicPlayed = false; } active = true; } ((Component)screen).gameObject.SetActive(true); screen.alpha = Mathf.SmoothStep(0f, 1f, RevivalPolicy.Black(num)); string[] array = new string[3] { "m_loadingProgress", "m_sleepingProgress", "m_teleportingProgress" }; foreach (string text in array) { object? obj = AccessTools.Field(typeof(Hud), text)?.GetValue(Hud.instance); GameObject val2 = (GameObject)((obj is GameObject) ? obj : null); if (Object.op_Implicit((Object)(object)val2)) { val2.SetActive(false); } } int num2 = RevivalPolicy.Message(num); Cinematic.text.text = num2 switch { 2 => "Slowly, life returns to the wetlands…", 1 => "An ancient corruption begins to fade…", _ => "", }; Cinematic.text.alpha = Mathf.SmoothStep(0f, 1f, RevivalPolicy.TextAlpha(num)); if (num >= 14.0 && !musicPlayed) { musicPlayed = true; if (Object.op_Implicit((Object)(object)MusicMan.instance) && (string)AccessTools.Method(typeof(MusicMan), "GetCurrentMusic", (Type[])null, (Type[])null).Invoke(MusicMan.instance, null) != "morning") { MusicMan.instance.TriggerMusic("morning"); } } } internal static void Release() { if (!active) { return; } try { if (Object.op_Implicit((Object)(object)text)) { Object.Destroy((Object)(object)((Component)text).gameObject); } if (Object.op_Implicit((Object)(object)screen)) { screen.alpha = 0f; } } finally { screen = null; text = null; active = false; CinematicSafety.End(); ReleasedFrame = Time.frameCount; PrimeSwampRevivalPlugin.Instance?.Note("CINEMATIC_RELEASED frame=" + ReleasedFrame); } } } [HarmonyPatch(typeof(Hud), "UpdateBlackScreen")] internal static class RevivalFade { private static bool Prefix() { return !PrimeSwampRevivalPlugin.Playing; } } internal static class CinematicSafety { internal static ConfigEntry<float> RadiusSetting; private static readonly List<Vector3> areas = new List<Vector3>(); private static readonly List<Player> players = new List<Player>(); private static readonly HashSet<ZDOID> removed = new HashSet<ZDOID>(); private static readonly FieldInfo Drops = AccessTools.Field(typeof(CharacterDrop), "m_dropsEnabled"); private static ZNet world; private static long eventId; private static long until; private static double deadline; private static float radius; private static bool ended = true; internal static bool Active { get { if (ended || !Object.op_Implicit((Object)(object)world) || (Object)(object)world != (Object)(object)ZNet.instance) { return false; } bool num = CinematicSafetyPolicy.Active(sameWorld: true, ended: false, PrimeSwampRevivalPlugin.Now, until, Cinematic.Visible, Time.realtimeSinceStartupAsDouble, deadline); if (!num) { End(); } return num; } } internal static void Reset() { world = null; eventId = (until = 0L); ended = true; areas.Clear(); players.Clear(); removed.Clear(); } internal static void End() { if (!ended) { ended = true; areas.Clear(); players.Clear(); removed.Clear(); PrimeSwampRevivalPlugin.Instance?.Note("CINEMATIC_SAFETY_RELEASED"); } } private static void Initialize(long start, float distance) { world = ZNet.instance; eventId = start; until = start + 160000000; radius = Mathf.Clamp(distance, 1f, 250f); ended = false; deadline = Time.realtimeSinceStartupAsDouble + Math.Max(0.0, (double)(until - PrimeSwampRevivalPlugin.Now) / 10000000.0) + 2.0; players.Clear(); players.AddRange(Player.GetAllPlayers()); } internal static ZPackage BeginServer(long start) { //IL_00ca: 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_011d: Unknown result type (might be due to invalid IL or missing references) if (!CinematicSafetyPolicy.NewEvent(Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer(), (Object)(object)world == (Object)(object)ZNet.instance, eventId, start)) { return null; } Initialize(start, RadiusSetting.Value); areas.Clear(); removed.Clear(); foreach (Player player in players) { if (Object.op_Implicit((Object)(object)player)) { areas.Add(((Component)player).transform.position); } } Stopwatch stopwatch = Stopwatch.StartNew(); List<Character> list = new List<Character>(); int num = 0; ZNetView val = default(ZNetView); foreach (Vector3 area in areas) { list.Clear(); Character.GetCharactersInRange(area, radius, list); foreach (Character item in list) { if (IsHostile(item) && ((Component)item).TryGetComponent<ZNetView>(ref val) && val.IsValid() && removed.Add(val.GetZDO().m_uid)) { try { RemoveQuietly(item, val); num++; } catch (Exception ex) { PrimeSwampRevivalPlugin.Instance?.Note("CINEMATIC_CLEANUP_FAILED " + ex); } } } } PrimeSwampRevivalPlugin.Instance?.Note("HOSTILE_CLEANUP beforeFade=True nativeDeathCompleted=True areas=" + areas.Count + " radius=" + radius + " removed=" + num + " elapsedMs=" + stopwatch.Elapsed.TotalMilliseconds.ToString("F2", CultureInfo.InvariantCulture)); if (stopwatch.Elapsed.TotalMilliseconds > 4.0) { PrimeSwampRevivalPlugin.Instance?.Note("BUDGET_WARNING one-time local hostile cleanup elapsedMs=" + stopwatch.Elapsed.TotalMilliseconds.ToString("F2", CultureInfo.InvariantCulture)); } return CinematicSafetyPacket.Write(start, radius, areas); } internal static void Receive(ZPackage packet) { CinematicSafetyPacket cinematicSafetyPacket = CinematicSafetyPacket.Read(packet); long start = cinematicSafetyPacket.Start; if (PrimeSwampRevivalPlugin.Now <= start + 160000000 && (!((Object)(object)world == (Object)(object)ZNet.instance) || eventId != start)) { Initialize(start, cinematicSafetyPacket.Radius); areas.Clear(); areas.AddRange(cinematicSafetyPacket.Centers); } } internal static bool InArea(Vector3 point, float extra = 0f) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return false; } float num = radius + extra; foreach (Vector3 area in areas) { Vector3 val = area - point; if (((Vector3)(ref val)).sqrMagnitude <= num * num) { return true; } } return false; } internal static bool IsHostile(Character character, bool prefab = false) { if (!Object.op_Implicit((Object)(object)character)) { return false; } bool flag = character.IsPlayer(); bool flag2 = character.IsTamed(); bool flag3 = Object.op_Implicit((Object)(object)((Component)character).GetComponent<NpcRuntime>()); bool flag4 = Integration.ProtectedWildlife(character) || Object.op_Implicit((Object)(object)((Component)character).GetComponent<AnimalAI>()); bool flag5 = prefab || character.GetHealth() > 0f; bool flag6 = false; if (!flag && !flag2 && !flag4 && flag5) { foreach (Player player in players) { if (Object.op_Implicit((Object)(object)player) && BaseAI.IsEnemy(character, (Character)(object)player)) { flag6 = true; break; } } } return CinematicSafetyPolicy.Hostile(flag, flag2, flag4, flag3 && !flag6, flag5, flag6, inside: true); } internal static bool Block(Character character) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (Active && Object.op_Implicit((Object)(object)character) && InArea(((Component)character).transform.position)) { return IsHostile(character); } return false; } internal static bool BlockPrefab(GameObject prefab, Vector3 point, float extra = 0f) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (Active && Object.op_Implicit((Object)(object)prefab) && InArea(point, extra)) { return IsHostile(prefab.GetComponent<Character>(), prefab: true); } return false; } internal static void RemoveQuietly(Character character, ZNetView view) { CharacterDrop component = ((Component)character).GetComponent<CharacterDrop>(); bool dropsEnabled = Object.op_Implicit((Object)(object)component) && (bool)Drops.GetValue(component); if (Object.op_Implicit((Object)(object)component)) { component.SetDropsEnabled(false); } try { AudioSource[] componentsInChildren = ((Component)character).GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].Stop(); } view.GetZDO().SetOwner(ZDOMan.GetSessionID()); ZNetScene.instance.Destroy(((Component)character).gameObject); } catch { if (Object.op_Implicit((Object)(object)component)) { component.SetDropsEnabled(dropsEnabled); } throw; } } } [HarmonyPatch(typeof(SpawnSystem), "Spawn")] internal static class GuardNativeSpawn { private static bool Prefix(SpawnData __0, Vector3 __1) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return !CinematicSafety.BlockPrefab(__0.m_prefab, __1); } } [HarmonyPatch(typeof(CreatureSpawner), "Spawn")] internal static class GuardLocalSpawner { private static bool Prefix(CreatureSpawner __instance, ref ZNetView __result) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!CinematicSafety.Active || !CinematicSafety.BlockPrefab(__instance.m_creaturePrefab, ((Component)__instance).transform.position)) { return true; } __result = null; return false; } } [HarmonyPatch(typeof(SpawnArea), "SpawnOne")] internal static class GuardSpawnArea { private static bool Prefix(SpawnArea __instance, ref bool __result) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!CinematicSafety.Active || __instance.m_prefabs.Count == 0) { return true; } foreach (SpawnData prefab in __instance.m_prefabs) { if (!CinematicSafety.BlockPrefab(prefab.m_prefab, ((Component)__instance).transform.position, __instance.m_spawnRadius)) { return true; } } __result = false; return false; } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] internal static class GuardHostileAI { private static bool Prefix(MonsterAI __instance, ref bool __result) { if (!CinematicSafety.Active) { return true; } if (!CinematicSafety.Block(((Component)__instance).GetComponent<Character>())) { return true; } ((BaseAI)__instance).StopMoving(); __result = false; return false; } } [HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[] { typeof(Character), typeof(bool) })] internal static class GuardHostileAttack { private static bool Prefix(Humanoid __instance, ref bool __result) { if (!CinematicSafety.Block((Character)(object)__instance)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Character), "ApplyDamage")] internal static class GuardPlayerDamage { private static bool Prefix(Character __instance) { if (__instance.IsPlayer()) { return !CinematicSafety.Active; } return true; } } [HarmonyPatch(typeof(Character), "Start")] internal static class GuardExternalSpawn { private static void Postfix(Character __instance) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && CinematicSafety.Block(__instance)) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid()) { CinematicSafety.RemoveQuietly(__instance, component); } } } } internal sealed class CinematicSafetyPacket { internal long Start; internal float Radius; internal Vector3[] Centers; internal static ZPackage Write(long start, float radius, List<Vector3> centers) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_002b: 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_0032: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(start); val.Write(radius); val.Write(centers.Count); foreach (Vector3 center in centers) { val.Write(center); } return val; } internal static CinematicSafetyPacket Read(ZPackage p) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) long num = p.ReadLong(); float num2 = p.ReadSingle(); int num3 = p.ReadInt(); if (num <= 0 || num3 < 0 || num3 > 128 || float.IsNaN(num2) || float.IsInfinity(num2) || num2 < 1f || num2 > 250f) { throw new FormatException("Invalid cinematic safety packet"); } Vector3[] array = (Vector3[])(object)new Vector3[num3]; for (int i = 0; i < num3; i++) { array[i] = p.ReadVector3(); } return new CinematicSafetyPacket { Start = num, Radius = num2, Centers = array }; } } internal static class CinematicSafetyPolicy { internal static bool Hostile(bool player, bool tamed, bool ambient, bool settler, bool alive, bool enemy, bool inside) { return !player && !tamed && !ambient && !settler && alive && enemy && inside; } internal static bool Active(bool sameWorld, bool ended, long now, long until, bool visible, double realtime, double deadline) { if (sameWorld && !ended && now < until) { if (!visible) { return realtime < deadline; } return true; } return false; } internal static bool NewEvent(bool server, bool sameWorld, long seen, long incoming) { if (server && incoming > 0) { if (sameWorld) { return seen != incoming; } return true; } return false; } } internal static class FutureGeneration { internal sealed class Scope { internal Vector2s Zone; internal bool Restored; internal Scope Previous; } internal static Scope Current; internal static ZoneLocation Planning; internal static void Install(Harmony h) { //IL_0054: 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_0076: Expected O, but got Unknown //IL_0076: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown Type type = typeof(ZoneSystem).GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic).Single((Type t) => t.Name.Contains("GenerateLocationsTimeSliced") && t.GetField("location", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null); h.Patch((MethodBase)AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SpacingAllocation), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SpacingAllocation), "Finalizer", (Type[])null), (HarmonyMethod)null); SpacingAllocation.Install(h); string[][] array = new string[2][] { new string[2] { "ExpandWorldData.Create", "SharedBPO" }, new string[2] { "ExpandWorldData.Data.DataManager", "Instantiate" } }; foreach (string[] array2 in array) { h.Patch((MethodBase)AccessTools.Method(AccessTools.TypeByName(array2[0]), array2[1], (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(BlueprintWitness), "Transpile", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); } } internal static bool Swamp(Vector2s id) { //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_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_001b: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Invalid comparison between Unknown and I4 //IL_0061: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Invalid comparison between Unknown and I4 //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Invalid comparison between Unknown and I4 Vector3 zonePos = ZoneSystem.GetZonePos(id); WorldGenerator instance = WorldGenerator.instance; if ((int)instance.GetBiome(zonePos) != 2 && (int)instance.GetBiome(zonePos + new Vector3(-31f, 0f, -31f)) != 2 && (int)instance.GetBiome(zonePos + new Vector3(31f, 0f, -31f)) != 2 && (int)instance.GetBiome(zonePos + new Vector3(-31f, 0f, 31f)) != 2) { return (int)instance.GetBiome(zonePos + new Vector3(31f, 0f, 31f)) == 2; } return true; } internal static void Replace(Vector2s id, ZoneLocation target, Vector3 point) { //IL_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) ZoneSystem instance = ZoneSystem.instance; LocationInstance val = instance.m_locationInstances[id]; instance.m_locationInstances.Remove(id); object[] array = new object[3] { val.m_location.m_prefab.m_assetID, val.m_location.m_group, val.m_location.m_groupMax }; string[] array2 = new string[3] { "m_locationIDCache", "m_locationGroupCache", "m_locationMaxGroupCache" }; for (int i = 0; i < 3; i++) { IDictionary dictionary = (IDictionary)AccessTools.Field(typeof(ZoneSystem), array2[i]).GetValue(instance); if (array[i] == null || !dictionary.Contains(array[i])) { continue; } IList list = (IList)dictionary[array[i]]; for (int num = list.Count - 1; num >= 0; num--) { if (ZoneSystem.GetZone(((LocationInstance)list[num]).m_position) == id) { list.RemoveAt(num); } } } if (target != null) { AccessTools.Method(typeof(ZoneSystem), "RegisterLocation", (Type[])null, (Type[])null).Invoke(instance, new object[3] { target, point, false }); } } } [HarmonyPatch(typeof(ZoneSystem), "SpawnZone")] internal static class FreshZoneScope { private static readonly Func<ZoneSystem, Vector2s, bool> Generated = AccessTools.MethodDelegate<Func<ZoneSystem, Vector2s, bool>>(AccessTools.Method(typeof(ZoneSystem), "IsZoneGenerated", (Type[])null, (Type[])null), (object)null, true); [HarmonyPriority(int.MaxValue)] private unsafe static bool Prefix(ZoneSystem __instance, Vector2s __0, out FutureGeneration.Scope __state, ref bool __result) { //IL_0021: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0098: Unknown result type (might be due to invalid IL or missing references) __state = null; if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || Generated(__instance, __0) || !FutureGeneration.Swamp(__0)) { return true; } if (PrimeSwampRevivalPlugin.Active && !PrimeSwampRevivalPlugin.ContentReady) { __result = false; return false; } __state = new FutureGeneration.Scope { Zone = __0, Restored = FuturePolicy.Generate(alreadyGenerated: false, PrimeSwampRevivalPlugin.Active, PrimeSwampRevivalPlugin.ContentReady), Previous = FutureGeneration.Current }; FutureGeneration.Current = __state; PrimeSwampRevivalPlugin instance = PrimeSwampRevivalPlugin.Instance; if (instance != null) { string[] obj = new string[5] { "NEW_ZONE_BEGIN zone=", null, null, null, null }; Vector2s val = __0; obj[1] = ((object)(*(Vector2s*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = " restored="; obj[3] = __state.Restored.ToString(); obj[4] = " nativePreviouslyGenerated=False"; instance.Note(string.Concat(obj)); } return true; } private unsafe static Exception Finalizer(FutureGeneration.Scope __state, Exception __exception) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (__state != null) { PrimeSwampRevivalPlugin instance = PrimeSwampRevivalPlugin.Instance; if (instance != null) { Vector2s zone = __state.Zone; instance.Note("NEW_ZONE_END zone=" + ((object)(*(Vector2s*)(&zone))/*cast due to .constrained prefix*/).ToString() + " success=" + (__exception == null)); } FutureGeneration.Current = __state.Previous; } return __exception; } } [HarmonyPatch(typeof(ZoneSystem), "PlaceLocations")] internal static class FutureLocationSlot { [HarmonyPriority(int.MaxValue)] private unsafe static void Prefix(Vector2s __0) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_00bb: 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_0066: 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_006c: 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_0084: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_00a0: 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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) FutureGeneration.Scope current = FutureGeneration.Current; if (current == null || current.Zone != __0 || !ZoneSystem.instance.m_locationInstances.TryGetValue(__0, out var value) || value.m_placed) { return; } if (current.Restored && (Integration.Name(value.m_location).StartsWith("PrimeSwamp", StringComparison.Ordinal) || RevivalPolicy.Ordinary(Integration.Name(value.m_location))) && FutureProtection.Occupied(value.m_position, value.m_location.m_exteriorRadius + 3f)) { FutureGeneration.Replace(__0, null, value.m_position); PrimeSwampRevivalPlugin instance = PrimeSwampRevivalPlugin.Instance; if (instance != null) { Vector2s val = __0; instance.Note("NEW_ZONE_LOCATION_SKIPPED protected persistent content zone=" + ((object)(*(Vector2s*)(&val))/*cast due to .constrained prefix*/).ToString()); } return; } string text = Integration.Name(value.m_location); ZoneLocation val2 = null; if (!current.Restored && text.StartsWith("PrimeSwamp", StringComparison.Ordinal)) { string prefix = FuturePolicy.VanillaPrefix(text); List<ZoneLocation> source = (List<ZoneLocation>)Integration.Field("ExpandWorldData.Locations.LocationManager", "DefaultEntries"); if (prefix != null) { val2 = ((IEnumerable<ZoneLocation>)source).FirstOrDefault((Func<ZoneLocation, bool>)((ZoneLocation l) => (l.m_biome & 2) != 0 && Integration.Name(l).StartsWith(prefix, StringComparison.Ordinal))); } } else { if (!current.Restored || text.StartsWith("PrimeSwamp", StringComparison.Ordinal)) { return; } string text2 = RevivalPolicy.Replacement(text); if (text2 == null) { return; } val2 = Integration.Canonical(text2); if (val2 == null) { return; } } FutureGeneration.Replace(__0, val2, value.m_position); PrimeSwampRevivalPlugin instance2 = PrimeSwampRevivalPlugin.Instance; if (instance2 != null) { string[] obj = new string[6] { "NEW_ZONE_LOCATION zone=", null, null, null, null, null }; Vector2s val = __0; obj[1] = ((object)(*(Vector2s*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = " "; obj[3] = text; obj[4] = " -> "; obj[5] = ((val2 == null) ? "empty pre-restoration slot" : Integration.Name(val2)); instance2.Note(string.Concat(obj)); } } } internal static class FuturePolicy { internal static bool Generate(bool alreadyGenerated, bool restored, bool cinematicReleased) { return !alreadyGenerated && restored && cinematicReleased; } internal static string VanillaPrefix(string prime) { if (prime.StartsWith("PrimeSwampHut", StringComparison.Ordinal)) { return "SwampHut"; } if (prime.StartsWith("PrimeSwampRuin", StringComparison.Ordinal)) { return "SwampRuin"; } return prime switch { "PrimeSwampWell1" => "SwampWell", "PrimeSwampTower1" => "StoneTower", "PrimeSwampSquare1" => "Runestone", _ => null, }; } } internal static class FutureProtection { private static readonly int Creator = (int)AccessTools.Field(typeof(ZDOVars), "s_creator").GetValue(null); private static readonly int TerrainData = (int)AccessTools.Field(typeof(ZDOVars), "s_TCData").GetValue(null); internal static bool Occupied(Vector3 point, float radius) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_005a: Unknown result type (might be due to invalid IL or missing references) List<ZDO> list = new List<ZDO>(); List<ZDO> list2 = new List<ZDO>(); ZDOMan.instance.FindSectorObjects(ZoneSystem.GetZone(point), new SimulationDistance(Mathf.CeilToInt(radius / 64f) + 1, 0, false), list, list2); list.AddRange(list2); foreach (ZDO item in list) { Vector3 val = item.GetPosition() - point; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > radius * radius) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(item.GetPrefab()); if (!Object.op_Implicit((Object)(object)prefab)) { return true; } if (item.GetLong(Creator, 0L) != 0L || Object.op_Implicit((Object)(object)prefab.GetComponent<Container>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<Ship>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<Plant>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<Piece>())) { return true; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<TerrainComp>())) { byte[] byteArray = item.GetByteArray(TerrainData, (byte[])null); if (((byteArray != null && byteArray.Length != 0) ? 1 : 0) > (false ? 1 : 0)) { return true; } } else if (Object.op_Implicit((Object)(object)prefab.GetComponent<Character>())) { if (item.GetBool("tamed", false)) { return true; } } else if (item.Persistent && !Object.op_Implicit((Object)(object)prefab.GetComponent<TreeBase>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<TreeLog>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<Pickable>())) { return true; } } return false; } } internal static class Integration { private const Biome Swamp = (Biome)2; private static readonly MethodInfo Clone = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); private static List<ZoneVegetation> vegetation; private static List<ZoneLocation> locations; private static List<Clutter> clutter; private static ZoneSystem zone; internal static bool ContentApplied; private static readonly Dictionary<Renderer, Material[]> vanillaTrees = new Dictionary<Renderer, Material[]>(); private static readonly Dictionary<SpawnSystemList, List<SpawnData>> spawns = new Dictionary<SpawnSystemList, List<SpawnData>>(); private static readonly HashSet<SpawnData> ambientOwned = new HashSet<SpawnData>(); private static readonly SpawnRefreshGate spawnRefresh = new SpawnRefreshGate(); private static readonly Dictionary<SpawnSystemList, List<SpawnData>> preparedSpawns = new Dictionary<SpawnSystemList, List<SpawnData>>(); private static readonly FieldInfo spawnDefaults = AccessTools.Field(AccessTools.TypeByName("ExpandWorldData.Spawn.SpawnManager"), "Defaults"); private static readonly FieldInfo spawnOverride = AccessTools.Field(AccessTools.TypeByName("ExpandWorldData.Spawn.SpawnManager"), "Override"); private static readonly HashSet<int> wildlifeHashes = new HashSet<int> { StringExtensionMethods.GetStableHashCode("Boar"), StringExtensionMethods.GetStableHashCode("Neck") }; internal static IReadOnlyList<ZoneLocation> ConfiguredLocations => locations; internal static bool ProtectedWildlife(Character character) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); int item = ((Object.op_Implicit((Object)(object)component) && component.IsValid()) ? component.GetZDO().GetPrefab() : StringExtensionMethods.GetStableHashCode(((Object)((Component)character).gameObject).name.Replace("(Clone)", "").Trim())); return wildlifeHashes.Contains(item); } internal static object Field(string type, string field) { return AccessTools.Field(AccessTools.TypeByName(type), field).GetValue(null); } internal static string Name(ZoneLocation l) { if (!string.IsNullOrEmpty(l.m_prefabName)) { return l.m_prefabName; } return l.m_name; } private static T Copy<T>(T item) { return (T)Clone.Invoke(item, null); } internal static void Install(Harmony h) { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown Patch(h, "ExpandWorldData.Vegetation.VegetationManager", "LoadAndApply", "VegetationLoaded", prefix: false); Patch(h, "ExpandWorldData.Locations.LocationManager", "LoadAndApply", "LocationsLoaded", prefix: false); Patch(h, "ExpandWorldData.Clutter.ClutterManager", "Set", "ClutterLoaded", prefix: false); Patch(h, "ExpandWorldData.Spawn.SpawnManager", "ApplySpawnData", "SpawnsLoaded", prefix: false); string[] array = new string[2] { "TryGetColor", "TryGetData" }; foreach (string method in array) { Patch(h, "ExpandWorldData.Biome.BiomeManager", method, "BiomeGate", prefix: true); } array = new string[2] { "GetTerrain", "GetNature" }; foreach (string method2 in array) { Patch(h, "ExpandWorldData.Biome.BiomeManager", method2, "BiomeIdentity", prefix: true); } Type type = AccessTools.TypeByName("CustomTextures.BepInExPlugin"); if (type != null) { h.Patch((MethodBase)AccessTools.Method(type, "LoadTexture", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Integration), "TextureGate", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void Patch(Harmony h, string type, string method, string hook, bool prefix) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName(type), method, (Type[])null, (Type[])null); if (methodInfo == null) { throw new MissingMethodException(type, method); } HarmonyMethod val = new HarmonyMethod(typeof(Integration), hook, (Type[])null) { priority = (prefix ? 800 : 0) }; h.Patch((MethodBase)methodInfo, prefix ? val : null, prefix ? null : val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static List<T> Merge<T>(IEnumerable<T> configured, IEnumerable<T> defaults, string biomeField) { //IL_003c: 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_0044: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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) FieldInfo fieldInfo = AccessTools.Field(typeof(T), biomeField); List<T> list = new List<T>(); foreach (T item in configured ?? Enumerable.Empty<T>()) { Biome val = (Biome)((Biome)fieldInfo.GetValue(item) & -3); if ((int)val != 0) { T val2 = Copy(item); fieldInfo.SetValue(val2, val); list.Add(val2); } } foreach (T item2 in defaults ?? Enumerable.Empty<T>()) { if (((Biome)fieldInfo.GetValue(item2) & 2) != 0) { T val3 = Copy(item2); fieldInfo.SetValue(val3, (object)(Biome)2); list.Add(val3); } } return list; } private static void TrackZone() { if (!((Object)(object)zone == (Object)(object)ZoneSystem.instance)) { zone = ZoneSystem.instance; vegetation = null; locations = null; ContentApplied = false; } } private static void VegetationLoaded() { TrackZone(); if (Object.op_Implicit((Object)(object)zone)) { vegetation = new List<ZoneVegetation>(zone.m_vegetation); ApplyVegetation(); } } private static void LocationsLoaded() { TrackZone(); if (Object.op_Implicit((Object)(object)zone)) { locations = new List<ZoneLocation>(zone.m_locations); ApplyLocations(); } } private static void ClutterLoaded() { if (Object.op_Implicit((Object)(object)ClutterSystem.instance)) { clutter = new List<Clutter>(ClutterSystem.instance.m_clutter); ApplyClutter(); } } private static void SpawnsLoaded(SpawnSystem __0) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //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_019c: Invalid comparison between Unknown and I4 IList list = (IList)spawnDefaults.GetValue(null); if (list == null) { return; } List<SpawnData> list2 = (List<SpawnData>)spawnOverride.GetValue(null); if (spawnRefresh.Matches(ZoneSystem.instance, list2, list, list2?.Count ?? 0, list.Count)) { bool flag = true; foreach (SpawnSystemList spawnList in __0.m_spawnLists) { if (Object.op_Implicit((Object)(object)spawnList) && preparedSpawns.TryGetValue(spawnList, out var value)) { spawnList.m_spawners = value; } else { flag = false; } } if (flag) { return; } } Stopwatch stopwatch = Stopwatch.StartNew(); spawns.Clear(); preparedSpawns.Clear(); ambientOwned.Clear(); foreach (object item in list) { Type type = item.GetType(); SpawnSystemList val = (SpawnSystemList)type.GetField("Item1").GetValue(item); if (!Object.op_Implicit((Object)(object)val)) { continue; } List<SpawnData> list3 = (List<SpawnData>)type.GetField("Item2").GetValue(item); bool flag2 = list2 != null && __0.m_spawnLists.Contains(val); spawns[val] = new List<SpawnData>(flag2 ? list2 : list3); foreach (SpawnData item2 in spawns[val]) { if (Object.op_Implicit((Object)(object)item2.m_prefab) && AmbientPolicy.Selected(((Object)item2.m_prefab).name, (item2.m_biome & 2) > 0)) { wildlifeHashes.Add(StringExtensionMethods.GetStableHashCode(((Object)item2.m_prefab).name)); } } val.m_spawners = Merge(spawns[val], (List<SpawnData>)type.GetField("Item2").GetValue(item), "m_biome"); preparedSpawns[val] = val.m_spawners; } if (PrimeSwampRevivalPlugin.ContentReady) { ApplyAmbientSpawns(); } spawnRefresh.Remember(ZoneSystem.instance, list2, list, list2?.Count ?? 0, list.Count); PrimeSwampRevivalPlugin.Instance?.Note("SPAWN_TABLE_PREPARED lists=" + preparedSpawns.Count + " configured=" + (list2?.Count ?? 0) + " elapsedMs=" + stopwatch.Elapsed.TotalMilliseconds.ToString("F2", CultureInfo.InvariantCulture) + "; subsequent zone loads reuse rules"); } private static void ApplyAmbientSpawns() { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Invalid comparison between Unknown and I4 //IL_0196: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<SpawnSystemList, List<SpawnData>> spawn in spawns) { if (Object.op_Implicit((Object)(object)spawn.Key)) { spawn.Key.m_spawners.RemoveAll((SpawnData e) => ambientOwned.Contains(e)); } } ambientOwned.Clear(); foreach (KeyValuePair<SpawnSystemList, List<SpawnData>> spawn2 in spawns) { if (!Object.op_Implicit((Object)(object)spawn2.Key)) { continue; } HashSet<string> hashSet = new HashSet<string>(); foreach (SpawnData item in spawn2.Value) { if (!Object.op_Implicit((Object)(object)item.m_prefab) || !AmbientPolicy.Selected(((Object)item.m_prefab).name, (item.m_biome & 2) > 0) || AmbientPolicy.DaySpirit(((Object)item.m_prefab).name, item.m_spawnAtDay, item.m_spawnAtNight)) { continue; } string text = item.m_name + "/" + ((Object)item.m_prefab).name; if (hashSet.Add(text)) { if (!string.IsNullOrEmpty(item.m_requiredGlobalKey) && item.m_requiredGlobalKey != PrimeSwampRevivalPlugin.Key) { PrimeSwampRevivalPlugin.Instance?.Note("AMBIENT_SKIPPED conflicting required key " + text); continue; } SpawnData val = Copy<SpawnData>(item); val.m_biome = (Biome)2; val.m_requiredGlobalKey = PrimeSwampRevivalPlugin.Key; spawn2.Key.m_spawners.Add(val); ambientOwned.Add(val); PrimeSwampRevivalPlugin.Instance?.Note("AMBIENT_ENABLED " + text + " cap=" + val.m_maxSpawned + " interval=" + val.m_spawnInterval + " chance=" + val.m_spawnChance + " day=" + val.m_spawnAtDay + " night=" + val.m_spawnAtNight); } } } } internal static string AmbientSummary() { return string.Join("; ", ambientOwned.Select((SpawnData e) => ((Object)e.m_prefab).name + "/" + e.m_name + " cap=" + e.m_maxSpawned + " key=" + e.m_requiredGlobalKey)); } private static bool BiomeGate(Biome __0, ref bool __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)__0 != 2 || PrimeSwampRevivalPlugin.VisualReady) { return true; } __result = false; return false; } private static bool BiomeIdentity(Biome __0, ref Biome __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)__0 != 2 || PrimeSwampRevivalPlugin.VisualReady) { return true; } __result = (Biome)2; return false; } private static bool TreeGate() { return PrimeSwampRevivalPlugin.VisualReady; } private static bool TextureGate(string __0, Texture __1, ref Texture2D __result) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (PrimeSwampRevivalPlugin.VisualReady || (__0 ?? "").IndexOf("swamptree", StringComparison.OrdinalIgnoreCase) < 0 || !(__1 is Texture2D)) { return true; } __result = (Texture2D)__1; return false; } private static void ApplyVegetation() { if (Object.op_Implicit((Object)(object)zone) && vegetation != null) { zone.m_vegetation = (PrimeSwampRevivalPlugin.Active ? vegetation : Merge(vegetation, (List<ZoneVegetation>)Field("ExpandWorldData.Vegetation.VegetationManager", "DefaultEntries"), "m_biome")); ContentApplied = PrimeSwampRevivalPlugin.Active; } } private static void ApplyLocations() { if (!Object.op_Implicit((Object)(object)zone) || locations == null) { return; } zone.m_locations = locations.Where((ZoneLocation l) => (l.m_biome & 2) == 0 || !RevivalPolicy.Ordinary(Name(l)) || Name(l).StartsWith("Prime", StringComparison.Ordinal)).ToList(); Dictionary<int, ZoneLocation> dictionary = (Dictionary<int, ZoneLocation>)AccessTools.Field(typeof(ZoneSystem), "m_locationsByHash").GetValue(zone); foreach (ZoneLocation item in (List<ZoneLocation>)Field("ExpandWorldData.Locations.LocationManager", "DefaultEntries")) { if (!string.IsNullOrEmpty(item.m_prefabName) && !dictionary.ContainsKey(StringExtensionMethods.GetStableHashCode(item.m_prefabName))) { dictionary[StringExtensionMethods.GetStableHashCode(item.m_prefabName)] = item; } } } private static void ApplyClutter() { if (Object.op_Implicit((Object)(object)ClutterSystem.instance) && clutter != null) { ClutterSystem.instance.m_clutter = Merge(clutter, (List<Clutter>)Field("ExpandWorldData.Clutter.ClutterManager", "DefaultEntries"), "m_biome"); AccessTools.Field(typeof(ClutterSystem), "m_forceRebuild").SetValue(ClutterSystem.instance, true); } } internal static void Apply() { TrackZone(); ApplyVegetation(); ApplyLocations(); ApplyClutter(); if (PrimeSwampRevivalPlugin.Active) { return; } foreach (KeyValuePair<Renderer, Material[]> vanillaTree in vanillaTrees) { if (Object.op_Implicit((Object)(object)vanillaTree.Key)) { vanillaTree.Key.sharedMaterials = vanillaTree.Value; } } } internal static void SnapshotTrees(ZNetScene scene) { KeyValuePair<Renderer, Material[]>[] array = vanillaTrees.Where((KeyValuePair<Renderer, Material[]> e) => !Object.op_Implicit((Object)(object)e.Key)).ToArray(); for (int num = 0; num < array.Length; num++) { KeyValuePair<Renderer, Material[]> keyValuePair = array[num]; Material[] value = keyValuePair.Value; foreach (Material val in value) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } } vanillaTrees.Remove(keyValuePair.Key); } SpawnSystemList[] array2 = spawns.Keys.Where((SpawnSystemList k) => !Object.op_Implicit((Object)(object)k)).ToArray(); foreach (SpawnSystemList key in array2) { spawns.Remove(key); } foreach (KeyValuePair<Renderer, Material[]> vanillaTree in vanillaTrees) { if (Object.op_Implicit((Object)(object)vanillaTree.Key)) { vanillaTree.Key.sharedMaterials = vanillaTree.Value; } } foreach (GameObject item in scene.m_prefabs.Concat(scene.m_nonNetViewPrefabs)) { if (!Object.op_Implicit((Object)(object)item) || ((Object)item).name.IndexOf("swamptree", StringComparison.OrdinalIgnoreCase) < 0) { continue; } Renderer[] componentsInChildren = item.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if (!vanillaTrees.ContainsKey(val2)) { vanillaTrees[val2] = ((IEnumerable<Material>)val2.sharedMaterials).Select((Func<Material, Material>)((Material m) => Object.op_Implicit((Object)(object)m) ? new Material(m) : ((Material)null))).ToArray(); } } } } internal static IEnumerable<ScheduledWork> ActivationWork() { yield return new ScheduledWork("tables/vegetation", delegate { TrackZone(); ApplyVegetation(); }); yield return new ScheduledWork("tables/locations", ApplyLocations); yield return new ScheduledWork("tables/ambient-spawns", ApplyAmbientSpawns); yield return new ScheduledWork("environment", BiomeState.Apply); foreach (ScheduledWork item in RefreshVisuals()) { yield return item; } } internal static IEnumerable<ScheduledWork> RefreshVisuals() { Type trees = AccessTools.TypeByName("PrimeSwampTrees.PrimeSwampTreesPlugin"); object instance = ((trees == null) ? null : AccessTools.Field(trees, "Instance").GetValue(null)); Type type = AccessTools.TypeByName("CustomTextures.BepInExPlugin"); MethodInfo replace = ((type == null) ? null : AccessTools.Method(type, "ReplaceOneGameObjectTextures", new Type[3] { typeof(GameObject), typeof(string), typeof(string) }, (Type[])null)); HashSet<GameObject> roots = new HashSet<GameObject>(); if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { foreach (GameObject item in ZNetScene.instance.m_prefabs.Concat(ZNetScene.instance.m_nonNetViewPrefabs)) { if (Object.op_Implicit((Object)(object)item)) { roots.Add(item); } } } if (Object.op_Implicit((Object)(object)ClutterSystem.instance)) { foreach (Clutter item2 in ClutterSystem.instance.m_clutter) { if (Object.op_Implicit((Object)(object)item2.m_prefab)) { roots.Add(item2.m_prefab); } } } foreach (GameObject item3 in roots.Where((GameObject r) => Object.op_Implicit((Object)(object)r) && ((Object)r).name.IndexOf("swamptree", StringComparison.OrdinalIgnoreCase) >= 0)) { GameObject saved = item3; if (!(replace != null) || !(((Object)saved).name != "_NetSceneRoot")) { continue; } yield return new ScheduledWork("textures/prefab=" + ((Object)saved).name, delegate { if (Object.op_Implicit((Object)(object)saved)) { replace.Invoke(null, new object[3] { saved, ((Object)saved).name, "object" }); } }); } if (instance == null || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { yield break; } yield return new ScheduledWork("trees/cache", delegate { AccessTools.Method(AccessTools.Field(trees, "prepared").FieldType, "Clear", (Type[])null, (Type[])null).Invoke(AccessTools.Field(trees, "prepared").GetValue(instance), null); }); MethodInfo prepare = AccessTools.Method(trees, "PrepareGraph", new Type[1] { typeof(GameObject) }, (Type[])null); foreach (GameObject item4 in roots.Where((GameObject r) => Object.op_Implicit((Object)(object)r) && ((Object)r).name.IndexOf("swamptree", StringComparison.OrdinalIgnoreCase) >= 0)) { GameObject saved2 = item4; yield return new ScheduledWork("trees/prefab=" + ((Object)saved2).name, delegate { if (Object.op_Implicit((Object)(object)saved2)) { prepare.Invoke(instance, new object[1] { saved2 }); } }); } ZNetView[] array = ((Dictionary<ZDO, ZNetView>)AccessTools.Field(typeof(ZNetScene), "m_instances").GetValue(ZNetScene.instance)).Values.ToArray(); ZNetView[] array2 = array; foreach (ZNetView val in array2) { if (!Object.op_Implicit((Object)(object)val) || ((Object)((Component)val).gameObject).name.IndexOf("swamptree", StringComparison.OrdinalIgnoreCase) < 0) { continue; } ZNetView saved3 = val; yield return new ScheduledWork("trees/live=" + (saved3.GetZDO()?.m_uid).ToString(), delegate { if (Object.op_Implicit((Object)(object)saved3)) { AccessTools.Method(trees, "OnCreated", (Type[])null, (Type[])null).Invoke(instance, new object[2] { ((Component)saved3).gameObject, "revival" }); } }); } } internal static ZoneLocation Canonical(string name) { return locations?.FirstOrDefault((Func<ZoneLocation, bool>)((ZoneLocation l) => Name(l) == name)); } internal static ZoneLocation VanillaDonor() { return ((IEnumerable<ZoneLocation>)(List<ZoneLocation>)Field("ExpandWorldData.Locations.LocationManager", "DefaultEntries")).FirstOrDefault((Func<ZoneLocation, bool>)((ZoneLocation l) => Name(l) == "SwampHut1")); } } [HarmonyPatch(typeof(EnvMan), "GetBiomeEnvSetup")] internal static class VanillaSwampEnvironment { [HarmonyPriority(0)] private static void Postfix(Biome __0, ref BiomeEnvSetup __result) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if (__result != null && (int)__0 == 2 && !PrimeSwampRevivalPlugin.VisualReady) { __result = BiomeState.NativeSwamp ?? __result; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class TreeSnapshot { [HarmonyPriority(800)] private static void Prefix(ZNetScene __instance) { Integration.SnapshotTrees(__instance); } [HarmonyPriority(0)] private static void Postfix() { Integration.Apply(); } } [HarmonyPatch(typeof(ZoneSystem), "SpawnLocation")] internal static class WellTerrainContext { internal sealed class Frame { internal Vector3 Origin; internal Quaternion Rotation; internal Frame Previous; internal bool Applied; } internal static Frame Current; [HarmonyPriority(int.MaxValue)] private static void Prefix(ZoneLocation __0, Vector3 __2, Quaternion __3, SpawnMode __4, out Frame __state) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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) __state = null; FutureGeneration.Scope current = FutureGeneration.Current; if (current != null && current.Restored && (int)__4 != 1 && !(Integration.Name(__0) != "PrimeSwampWell1")) { __state = new Frame { Origin = __2, Rotation = __3, Previous = Current }; Current = __state; } } private static Exception Finalizer(Frame __state, Exception __exception) { if (__state != null) { Current = __state.Previous; } return __exception; } } [HarmonyPatch(typeof(LocationObjectDataAndSwap), "HandleTerrain")] internal static class ExcavateWellInterior { private static readonly FieldInfo Build = AccessTools.Field(typeof(Heightmap), "m_buildData"); private static readonly FieldInfo Heights = AccessTools.Field(Build.FieldType, "m_baseHeights"); private unsafe static void Postfix() { //IL_0034: 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_004e: 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_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) //IL_0063: 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_00fb: 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_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) WellTerrainContext.Frame current = WellTerrainContext.Current; if (current == null || current.Applied) { return; } FutureGeneration.Scope current2 = FutureGeneration.Current; if (current2 == null || !current2.Restored) { return; } current.Applied = true; try { Vector3 center = current.Origin + current.Rotation * new Vector3(0f, 0f, 0.249f); Heightmap val = Heightmap.FindHeightmap(center); if (!Object.op_Implicit((Object)(object)val)) { return; } float groundHeight = ZoneSystem.instance.GetGroundHeight(center); float water = ZoneSystem.instance.m_waterLevel; if (!LocationTerrainPolicy.Reachable(groundHeight, water)) { PrimeSwampRevivalPlugin instance = PrimeSwampRevivalPlugin.Instance; if (instance != null) { Vector3 val2 = center; instance.Note("WELL_WATER_SKIPPED natural water requires more than 6m excavation at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString()); } } else { if (1.5f + 1.415f * val.m_scale > 3.75f) { return; } int cx = default(int); int cz = default(int); val.WorldToVertex(center, ref cx, ref cz); int reach = Mathf.CeilToInt(1.5f / val.m_scale) + 1; if (cx - reach < 1 || cz - reach < 1 || cx + reach >= val.m_width || cz + reach >= val.m_width) { return; } int changed = 0; Terrain.ChangeTerrain(center, (Action<Heightmap, TerrainFakeData>)delegate(Heightmap hm, TerrainFakeData data) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_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_01de: Unknown result type (might be due to invalid IL or missing references) List<float> list = (List<float>)Heights.GetValue(Build.GetValue(hm)); List<KeyValuePair<int, float>> list2 = new List<KeyValuePair<int, float>>(25); Vector3 position = ((Component)hm).transform.position; for (int i = cz - reach; i <= cz + reach; i++) { for (int j = cx - reach; j <= cx + reach; j++) { Vector3 val3 = position + new Vector3(((float)(j - hm.m_width / 2) + 0.5f) * hm.m_scale, 0f, ((float)(i - hm.m_width / 2) + 0.5f) * hm.m_scale); float num = val3.x - center.x; float num2 = val3.z - center.z; float num3 = LocationTerrainPolicy.Weight(Mathf.Sqrt(num * num + num2 * num2)); if (!(num3 <= 0f)) { int num4 = i * (hm.m_width + 1) + j; float height = hm.GetHeight(j, i); float num5 = Mathf.Min(height, Mathf.Lerp(height, water - 0.35f, num3)); if (!LocationTerrainPolicy.Allowed(height, num5, list[num4])) { return; } if (height - num5 > 0.001f) { list2.Add(new KeyValuePair<int, float>(num4, num5 - list[num4])); } } } } foreach (KeyValuePair<int, float> item in list2) { if (data.SetHeight(item.Key, item.Value)) { changed++; } } if (changed > 0) { data.MarkOperation(center, 1.5f); } }); PrimeSwampRevivalPlugin instance2 = PrimeSwampRevivalPlugin.Instance; if (instance2 != null) { string[] obj = new string[6] { "WELL_WATER initial-generation center=", null, null, null, null, null }; Vector3 val2 = center; obj[1] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[2] = " outerRadius=1.5 coreRadius=1 target="; obj[3] = (water - 0.35f).ToString(); obj[4] = " vertices="; obj[5] = changed.ToString(); instance2.Note(string.Concat(obj)); } } } catch (Exception ex) { PrimeSwampRevivalPlugin.Instance?.Note("WELL_WATER_FAILED retained building geometry: " + ex); } } } [HarmonyPatch(typeof(ZoneSystem), "PlaceLocations")] internal static class TowerVegetationClearing { private static readonly Type Area = typeof(ZoneSystem).GetNestedType("ClearArea", BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo Center = AccessTools.Field(Area, "m_center"); private static readonly FieldInfo Radius = AccessTools.Field(Area, "m_radius"); [HarmonyPriority(int.MinValue)] private static void Prefix(Vector2s __0, out Vector3? __state) { //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_0037: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) __state = null; FutureGeneration.Scope current = FutureGeneration.Current; if (current != null && current.Restored && !(FutureGeneration.Current.Zone != __0) && ZoneSystem.instance.m_locationInstances.TryGetValue(__0, out var value) && !value.m_placed && Integration.Name(value.m_location) == "PrimeSwampTower1") { __state = value.m_position; } } private static void Postfix(Vector3? __state, object __4) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!__state.HasValue) { return; } foreach (object item in (IList)__4) { Vector3 val = (Vector3)Center.GetValue(item) - __state.Value; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { Radius.SetValue(item, Mathf.Min((float)Radius.GetValue(item), 6f)); } } } } internal static class LocationTerrainPolicy { internal const float WellOffset = -6.95f; internal const float CenterZ = 0.249f; internal const float CoreRadius = 1f; internal const float OuterRadius = 1.5f; internal const float WaterDepth = 0.35f; internal const float MaxDig = 6f; internal const float NativeLimit = 8f; internal const float TowerClearRadius = 6f; internal static bool Reachable(float ground, float water) { if (!float.IsNaN(ground) && !float.IsInfinity(ground)) { return ground - (water - 0.35f) <= 6f; } return false; } internal static float Weight(float radius) { if (radius >= 1.5f) { return 0f; } if (radius <= 1f) { return 1f; } float num = (1.5f - radius) / 0.5f; return num * num * (3f - 2f * num); } internal static bool Allowed(float current, float target, float original) { if (!float.IsNaN(target) && !float.IsInfinity(target) && target <= current && current - target <= 6f) { return Math.Abs(target - original) <= 8f; } return false; } } internal sealed class MatchingBuckets<T> { private readonly List<T> entries; private readonly Func<T, string, bool> matches; private readonly Dictionary<string, List<T>> buckets = new Dictionary<string, List<T>>(StringComparer.Ordinal); internal long MatchCalls; internal MatchingBuckets(IEnumerable<T> source, Func<T, string, bool> predicate) { entries = new List<T>(source); matches = predicate; } internal List<T> Get(string group) { group = group ?? ""; if (buckets.TryGetValue(group, out var value)) { return value; } value = new List<T>(); foreach (T entry in entries) { MatchCalls++; if (matches(entry, group)) { value.Add(entry); } } buckets.Add(group, value); return value; } internal void Add(T entry) { entries.Add(entry); foreach (KeyValuePair<string, List<T>> bucket in buckets) { MatchCalls++; if (matches(entry, bucket.Key)) { bucket.Value.Add(entry); } } } } internal static class PackagedTextureSearch { internal static string Resolve(string assemblyLocation) { return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(assemblyLocation), "..", "CustomTextures")); } internal static bool Exists(string native, string packaged) { if (!Directory.Exists(native)) { return Directory.Exists(packaged); } return true; } internal static string[] Files(string native, string pattern, SearchOption option, string packaged) { List<string> list = new List<string>(); if (Directory.Exists(packaged)) { list.AddRange(Directory.GetFiles(packaged, pattern, option)); } if (Directory.Exists(native) && !string.Equals(Path.GetFullPath(native), Path.GetFullPath(packaged), StringComparison.OrdinalIgnoreCase)) { list.AddRange(Directory.GetFiles(native, pattern, option)); } return list.ToArray(); } } internal static class Performance { internal sealed class Work : IDisposable { private readonly Work previous; private readonly long start = Stopwatch.GetTimestamp(); private readonly string name; internal double Elapsed => (double)(Stopwatch.GetTimestamp() - start) * 1000.0 / (double)Stopwatch.Frequency; internal Work(string value) { _ = CanStart; name = value; previous = current; current = this; Last = name; PrimeSwampRevivalPlugin.Instance?.Note("WORK_START " + name + " frame=" + Time.frameCount); } public void Dispose() { double elapsed = Elapsed; current = previous; if (previous == null) { allowance.Charge(elapsed); } PrimeSwampRevivalPlugin.Instance?.Note("WORK_END " + name + " elapsedMs=" + elapsed.ToString("F2", CultureInfo.InvariantCulture)); if (elapsed > 4.0) { PrimeSwampRevivalPlugin.Instance?.Note("BUDGET_WARNING " + name + " elapsedMs=" + elapsed.ToString("F2", CultureInfo.InvariantCulture) + " targetMs=4 atomic engine call or batch exceeded target"); } } } private static readonly FrameAllowance allowance = new FrameAllowance(); private static Work current; internal static string Last = "idle"; internal static bool CanStart { get { allowance.Reset(Time.frameCount); return allowance.CanStart; } } internal static Work Begin(string name) { return new Work(name); } internal static void Run(string name, Action action) { using (Begin(name)) { action(); } } } internal sealed class PrimeMusicSetting { public string name { get; set; } public string[] clips { get; set; } = Array.Empty<string>(); public float volume { get; set; } public float fadeInTime { get; set; } public bool alwaysFadeOut { get; set; } public bool loop { get; set; } public bool resume { get; set; } public bool ambientMusic { get; set; } } internal static class PrimeMusicSettings { internal static void Validate(IEnumerable<PrimeMusicSetting> entries) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); foreach (PrimeMusicSetting entry in entries) { if (entry == null || string.IsNullOrWhiteSpace(entry.name) || !hashSet.Add(entry.name) || entry.clips == null || entry.clips.Any(string.IsNullOrWhiteSpace) || float.IsNaN(entry.volume) || float.IsInfinity(entry.volume) || entry.volume < 0f || float.IsNaN(entry.fadeInTime) || float.IsInfinity(entry.fadeInTime) || entry.fadeInTime < 0f) { throw new ArgumentException("Invalid/duplicate Prime music setting"); } } } internal static bool CanResolve(PrimeMusicSetting entry, ISet<string> clips) { return entry.clips.All(clips.Contains); } } internal static class PrimeNativeMusic { private static PrimeMusicSetting[] entries; private static MusicMan applied; internal static void Load() { entries = JsonConvert.DeserializeObject<PrimeMusicSetting[]>(File.ReadAllText(Path.Combine(Path.GetDirectoryName(typeof(PrimeNativeMusic).Assembly.Location), "Data", "PrimeMusic.json"))); if (entries == null || entries.Length == 0) { throw new InvalidDataException("Empty Prime music catalog"); } PrimeMusicSettings.Validate(entries); } internal static void Apply(MusicMan manager) { //IL_0195: 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_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0243: 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_025e: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)manager) || (Object)(object)applied == (Object)(object)manager) { return; } if (Chainloader.PluginInfos.ContainsKey("expand_world_music")) { applied = manager; PrimeSwampRevivalPlugin.Instance.Note("PRIME_MUSIC_EXTERNAL Expand World Music supplies the music table."); return; } Dictionary<string, AudioClip> clips = new Dictionary<string, AudioClip>(StringComparer.Ordinal); foreach (NamedMusic item in manager.m_music) { AudioClip[] array = item.m_clips ?? Array.Empty<AudioClip>(); foreach (AudioClip val in array) { if (Object.op_Implicit((Object)(object)val) && !clips.ContainsKey(((Object)val).name)) { clips.Add(((Object)val).name, val); } } } HashSet<string> clipNames = new HashSet<string>(clips.Keys, StringComparer.Ordinal); string[] array2 = (from e in entries where !PrimeMusicSettings.CanResolve(e, clipNames) select e.name).ToArray(); if (array2.Length != 0) { applied = manager; PrimeSwampRevivalPlugin.Instance.ReportError("PRIME_MUSIC_MISSING native clips for " + string.Join(", ", array2) + "; native music retained; verify game/dependency baseline."); return; } List<NamedMusic> list = new List<NamedMusic>(manager.m_music); PrimeMusicSetting[] array3 = entries; foreach (PrimeMusicSetting entry in array3) { NamedMusic val2 = new NamedMusic { m_name = entry.name, m_clips = entry.clips.Select((string n) => clips[n]).ToArray(), m_volume = entry.volume, m_fadeInTime = entry.fadeInTime, m_alwaysFadeout = entry.alwaysFadeOut, m_loop = entry.loop, m_resume = entry.resume, m_ambientMusic = entry.ambientMusic, m_enabled = true }; int num = list.FindIndex((NamedMusic m) => m.m_name == entry.name); if (num >= 0) { list[num] = val2; } else { list.Add(val2); } } Dictionary<int, NamedMusic> dictionary = (Dictionary<int, NamedMusic>)AccessTools.Field(typeof(MusicMan), "m_musicHashes").GetValue(manager); Dictionary<int, NamedMusic> dictionary2 = new Dictionary<int, NamedMusic>(); foreach (NamedMusic item2 in list) { if (item2.m_clips != null && item2.m_clips.Length != 0 && Object.op_Implicit((Object)(object)item2.m_clips[0])) { int stableHashCode = StringExtensionMethods.GetStableHashCode(item2.m_name); if (dictionary2.ContainsKey(stableHashCode)) { applied = manager; PrimeSwampRevivalPlugin.Instance.ReportError("PRIME_MUSIC_CONFLICT duplicate music identity " + item2.m_name + "; native table retained."); return; } dictionary2.Add(stableHashCode, item2); } } manager.m_music = list; dictionary.Clear(); foreach (KeyValuePair<int, NamedMusic> item3 in dictionary2) { dictionary.Add(item3.Key, item3.Value); } applied = manager; PrimeSwampRevivalPlugin.Instance.Note("PRIME_MUSIC_READY entries=" + entries.Length + "; native clips, unchanged release settings; native selection retained."); } } [HarmonyPatch(typeof(MusicMan), "Awake")] internal static class PrimeMusicInitialized { [HarmonyPriority(0)] private static void Postfix(MusicMan __instance) { PrimeNativeMusic.Apply(__instance); } } internal static class PrimeSceneryRegistry { private static string[] names; internal static bool Ready; internal static void Install() { Ready = false; string text = Path.Combine(Path.GetDirectoryName(typeof(PrimeSceneryRegistry).Assembly.Location), "Data", "PrimeScenery.json"); names = JsonConvert.DeserializeObject<string[]>(File.ReadAllText(text)); if (names == null || names.Length == 0 || names.Any(string.IsNullOrWhiteSpace) || names.Distinct<string>(StringComparer.Ordinal).Count() != names.Length) { throw new InvalidDataException("Invalid Prime scenery catalog: " + text); } PrefabManager.OnPrefabsRegistered += Register; } internal static void Uninstall() { PrefabManager.OnPrefabsRegistered -= Register; Ready = false; } private static void Register() { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } Ready = false; Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs").GetValue(instance); List<string> list = new List<string>(); int num = 0; string[] array = names; foreach (string text in array) { int stableHashCode = StringExtensionMethods.GetStableHashCode(text); if (dictionary.TryGetValue(stableHashCode, out var value)) { if (!Object.op_Implicit((Object)(object)value) || ((Object)value).name != text) { list.Add(text + " (prefab hash collision)"); } continue; } if (text.StartsWith("Prime", StringComparison.Ordinal)) { list.Add(text + " (Prime provider did not register)"); continue; } GameObject prefab = PrefabManager.Instance.GetPrefab(text); if (Object.op_Implicit((Object)(object)prefab) && !(((Object)prefab).name != text)) { Scene scene = prefab.scene; if (!((Scene)(ref scene)).IsValid()) { dictionary.Add(stableHashCode, prefab); List<GameObject> list2 = (Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>()) ? instance.m_prefabs : instance.m_nonNetViewPrefabs); if (!list2.Contains(prefab)) { list2.Add(prefab); } num++; continue; } } list.Add(text); } if (list.Count > 0) { PrimeSwampRevivalPlugin.Instance.ReportError("PRIME_SCENERY_MISSING " + string.Join(", ", list) + "; do not use this installation on your only world copy."); return; } Ready = true; PrimeSwampRevivalPlugin.Instance.Note("PRIME_SCENERY_READY checked=" + names.Length + " registered=" + num + "; native objects only; no build or planting menus added."); } } [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.prime.swamprevival", "Prime Swamp Revival", "0.1.13")] [BepInDependency("com.jotunn.jotunn", "2.30.2")] [BepInDependency("com.prime.swampnpcs", "0.1.9")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency("com.primeswamp.trees", "0.4.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class PrimeSwampRevivalPlugin : BaseUnityPlugin { internal const string Id = "com.prime.swamprevival"; internal static PrimeSwampRevivalPlugin Instance; internal static long sequenceStart; private ZRoutedRpc routed; private ZNet world; private Harmony harmony; private static readonly Func<ZRoutedRpc, long> Server = AccessTools.MethodDelegate<Func<ZRoutedRpc, long>>(AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", (Type[])null, (Type[])null), (object)null, true); internal static readonly Dictionary<ZDOID, long> BossOwners = new Dictionary<ZDOID, long>(); internal static string Key => PrimeSwampNPCsPlugin.RestorationStateKey; internal static bool Active { get { if (Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return ZoneSystem.instance.GetGlobalKey(Key); } return false; } } internal static bool GenerationAllowed => ActivationPolicy.Ready(Active, sequenceStart, Now, 160000000L, Cinematic.Visible, Time.frameCount, Cinematic.ReleasedFrame); internal static bool VisualReady => GenerationAllowed; internal static bool ContentReady { get { if (PrimeSceneryRegistry.Ready && GenerationAllowed && ActivationPipeline.Ready) { return Integration.ContentApplied; } return false; } } internal static long Now { get { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return 0L; } return ZNet.instance.GetTime().Ticks; } } internal static bool Playing { get { if (sequenceStart > 0 && Now >= sequenceStart) { return Now < sequenceStart + 160000000; } return false; } } private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown CinematicSafety.RadiusSetting = ((BaseUnityPlugin)this).Config.Bind<float>("Cinematic", "HostileCleanupRadius", 100f, new ConfigDescription("Server-authoritative one-time hostile cleanup radius around each player receiving the cinematic, metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 250f), Array.Empty<object>())); Instance = this; PrimeSceneryRegistry.Install(); PrimeNativeMusic.Load(); harmony = new Harmony("com.prime.swamprevival"); harmony.PatchAll(); Integration.Install(harmony); BiomeState.Install(harmony); FutureGeneration.Install(harmony); TextureCompatibility.Install(harmony); SimpleDiagnostics.Install(); if (Object.op_Implicit((Object)(object)MusicMan.instance)) { PrimeNativeMusic.Apply(MusicMan.instance); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"0.1.13 Nexus dependency reduction: Prime tree textures, native scenery registration and native music; no building/planting system."); } internal void Note(string message) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } internal void ReportError(string message) { ((BaseUnityPlugin)this).Logger.LogError((object)message); } internal void EnsureRpc() { if (ZRoutedRpc.instance == null || routed == ZRoutedRpc.instance) { return; } routed = ZRoutedRpc.instance; routed.Register<ZDOID>("PrimeSwamp_BonemassDeath", (Action<long, ZDOID>)DeathRequest); routed.Register<ZDOID>("PrimeSwamp_BonemassDying", (Action<long, ZDOID>)delegate(long sender, ZDOID id) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(id) : null); if (val != null && val.GetPrefab() == StringExtensionMethods.GetStableHashCode("Bonemass") && val.GetOwner() == sender) { BossOwners[id] = sender; } } }); routed.Register<long>("PrimeSwamp_Revival", (Action<long, long>)BeginSequence); routed.Register<ZPackage>("PrimeSwamp_CinematicSafety", (Action<long, ZPackage>)delegate(long sender, ZPackage packet) { if (sender == Server(routed)) { CinematicSafety.Receive(packet); } }); } private void Update() { EnsureRpc(); if ((Object)(object)world != (Object)(object)ZNet.instance) { world = ZNet.instance; sequenceStart = 0L; BossOwners.Clear(); CinematicSafety.Reset(); } ActivationPipeline.Step(); } internal void ReportDeath(ZDOID id) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) EnsureRpc(); if (routed == null) { return; } if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { if (BossOwners.TryGetValue(id, out var value)) { DeathRequest(value, id); } } else { routed.InvokeRoutedRPC(Server(routed), "PrimeSwamp_BonemassDeath", new object[1] { id }); } } internal void ObserveDeath(ZDOID id, long owner) { //IL_0005: 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) BossOwners[id] = owner; EnsureRpc(); if (Object.op_Implicit((Object)(object)ZNet.instance
BepInEx/plugins/PrimeSwampTrees/PrimeSwampTrees.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PrimeSwampTrees")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.1.0")] [assembly: AssemblyInformationalVersion("0.4.1")] [assembly: AssemblyProduct("PrimeSwampTrees")] [assembly: AssemblyTitle("PrimeSwampTrees")] [assembly: AssemblyVersion("0.4.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PrimeSwampTrees { [BepInPlugin("com.primeswamp.trees", "Prime Swamp Trees", "0.4.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class PrimeSwampTreesPlugin : BaseUnityPlugin { private static class SceneReady { private static void Postfix(ZNetScene __instance) { Guard("ZNetScene.Awake", delegate(PrimeSwampTreesPlugin p) { p.PrepareScene(__instance); }); } } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class VegetationReady { [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix(ZoneSystem __instance) { Guard("ZoneSystem.Start", delegate(PrimeSwampTreesPlugin p) { p.PrepareVegetation(__instance); }); } } [HarmonyPatch(typeof(TreeBase), "Awake")] private static class StandingCreated { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(TreeBase __instance) { Guard("TreeBase.Awake", delegate(PrimeSwampTreesPlugin p) { if (p.IsTarget(((Component)__instance).gameObject)) { p.PrepareGraph(__instance.m_logPrefab); p.PrepareGraph(__instance.m_stubPrefab); p.OnCreated(((Component)__instance).gameObject, "TreeBase.Awake"); } }); } } [HarmonyPatch(typeof(TreeLog), "Awake")] private static class LogCreated { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(TreeLog __instance) { Guard("TreeLog.Awake", delegate(PrimeSwampTreesPlugin p) { if (p.IsTarget(((Component)__instance).gameObject)) { p.PrepareGraph(__instance.m_subLogPrefab); p.OnCreated(((Component)__instance).gameObject, "TreeLog.Awake"); } }); } } [HarmonyPatch(typeof(ZNetScene), "CreateObject", new Type[] { typeof(ZDO) })] private static class NetworkCreated { [HarmonyPrefix] private static void Prefix(ZNetScene __instance, ZDO __0, out bool __state) { bool target = false; Guard("ZNetScene.CreateObject prefix", delegate(PrimeSwampTreesPlugin p) { GameObject prefab = __instance.GetPrefab(__0.GetPrefab()); target = p.IsTarget(prefab); if (target) { p.PrepareGraph(prefab); } }); __state = target; } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(GameObject __result, bool __state) { if (__state) { Guard("ZNetScene.CreateObject postfix", delegate(PrimeSwampTreesPlugin p) { p.OnCreated(__result, "ZNetScene.CreateObject"); }); } } } public const string PluginId = "com.primeswamp.trees"; public const string CustomTexturesId = "cjayride.CustomTextures"; internal static PrimeSwampTreesPlugin Instance; public static Func<bool> RestorationGate; private Harmony harmony; private ConfigEntry<bool> verbose; private readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<Material, Material> replacements = new Dictionary<Material, Material>(); private readonly HashSet<Material> owned = new HashSet<Material>(); private readonly HashSet<GameObject> prepared = new HashSet<GameObject>(); private readonly HashSet<int> targetHashes = new HashSet<int>(); private readonly HashSet<string> messages = new HashSet<string>(); private readonly HashSet<string> matchedFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<int, WeakReference<GameObject>> liveRoots = new Dictionary<int, WeakReference<GameObject>>(); private readonly List<Texture2D> retiredTextures = new List<Texture2D>(); private int creationChecks; private string TextureDirectory => Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Textures"); private void Awake() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown Instance = this; verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "VerboseCoverage", true, "Log each prefab hierarchy, LOD renderer and material slot once. No recurring scene scans."); LoadTextures(mossOnly: false); if (textures.Count == 0) { ((BaseUnityPlugin)this).Logger.LogError((object)"No usable textures loaded; no patches installed and vanilla materials left intact."); return; } harmony = new Harmony("com.primeswamp.trees"); harmony.PatchAll(typeof(PrimeSwampTreesPlugin).Assembly); InstallPrefabHook(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Prime Swamp Trees 0.4.1 restoration-gated build: prefab preparation + creation safeguards; no periodic renderer scan."); } private void InstallPrefabHook() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null); HashSet<string> hashSet = new HashSet<string> { "cjayride.CustomTextures" }; Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo != null) { foreach (Patch postfix in patchInfo.Postfixes) { if (postfix.PatchMethod.DeclaringType.Assembly.GetName().Name == "CustomTextures") { hashSet.Add(postfix.owner); } } } string[] array = new string[hashSet.Count]; hashSet.CopyTo(array); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(SceneReady), "Postfix", (Type[])null, (Type[])null)) { priority = 0, after = array }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Prefab hook ordered after CustomTextures owners: " + string.Join(", ", array))); } private void LoadTextures(bool mossOnly) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown if (!Directory.Exists(TextureDirectory)) { ((BaseUnityPlugin)this).Logger.LogError((object)("Missing adjacent Textures folder: " + TextureDirectory)); return; } List<Texture2D> list = new List<Texture2D>(); string[] files = Directory.GetFiles(TextureDirectory, mossOnly ? "*MossTex.png" : "*.png"); foreach (string text in files) { Texture2D val = null; try { val = new Texture2D(2, 2, (TextureFormat)4, true); if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text))) { throw new InvalidDataException("Unity rejected PNG data"); } string key = (((Object)val).name = Path.GetFileNameWithoutExtension(text)); if (textures.TryGetValue(key, out var value)) { list.Add(value); } textures[key] = val; } catch (Exception ex) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } ((BaseUnityPlugin)this).Logger.LogWarning((object)("Cannot load " + text + ": " + ex.Message)); } } foreach (Material item in owned) { if (Object.op_Implicit((Object)(object)item)) { ApplyTextures(item); } } retiredTextures.AddRange(list); if (mossOnly) { ReapplyTrackedRoots(); } files = TextureRules.ExpectedFiles; foreach (string text2 in files) { if (!textures.ContainsKey(Path.GetFileNameWithoutExtension(text2))) { WarnOnce("missing:" + text2, "Missing/unreadable baseline texture: " + text2); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded " + textures.Count + " tree texture files" + (mossOnly ? " (moss reload)" : "") + ".")); } private void Update() { if (harmony != null && Input.GetKeyDown((KeyCode)289)) { LoadTextures(mossOnly: true); } } internal static void Guard(string context, Action<PrimeSwampTreesPlugin> action) { PrimeSwampTreesPlugin instance = Instance; if (!Object.op_Implicit((Object)(object)instance) || instance.harmony == null || RestorationGate == null || !RestorationGate()) { return; } try { action(instance); } catch (Exception ex) { instance.WarnOnce("exception:" + context, context + " failed (gameplay continues): " + ex); } } private void WarnOnce(string key, string message) { if (messages.Add(key)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); } } private void TraceOnce(string key, string message) { if (verbose.Value && messages.Add(key)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } } private bool HasMapping(Material material) { string normalizedMaterial = TextureRules.Normalize(((Object)material).name); foreach (string key in textures.Keys) { if (TextureRules.TryParse(key, out var material2, out var _) && TextureRules.Matches(normalizedMaterial, material2)) { return true; } } return false; } private int ApplyTextures(Material material) { //IL_00af: 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) string text = TextureRules.Normalize(((Object)material).name); int num = 0; foreach (KeyValuePair<string, Texture2D> texture in textures) { if (!TextureRules.TryParse(texture.Key, out var material2, out var suffix) || !TextureRules.Matches(text, material2)) { continue; } bool flag = false; if (suffix.Equals("mosstex", StringComparison.OrdinalIgnoreCase)) { string[] mossProperties = TextureRules.MossProperties; foreach (string text2 in mossProperties) { if (material.HasProperty(text2)) { material.SetTexture(text2, (Texture)(object)texture.Value); flag = true; } } if (flag) { if (material.HasProperty("_MossColor")) { material.SetColor("_MossColor", Color.white); } if (material.HasProperty("_MossTint")) { material.SetColor("_MossTint", Color.white); } } } else { string text3 = TextureRules.Property(suffix); if (material.HasProperty(text3)) { material.SetTexture(text3, (Texture)(object)texture.Value); flag = true; } } if (flag) { num++; matchedFiles.Add(texture.Key); TraceOnce("texture:" + text + ":" + texture.Key + ":" + ((Object)material.shader).name, "Applied " + texture.Key + " to " + text + " shader=" + ((Object)material.shader).name); } else { WarnOnce("property:" + text + ":" + suffix + ":" + ((Object)material.shader).name, "No supported property for " + texture.Key + " on " + text + " shader=" + ((Object)material.shader).name + "; left unchanged."); } } return num; } private Material Replacement(Material original) { //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_009a: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)original)) { return original; } if (owned.Contains(original)) { ApplyTextures(original); return original; } if (replacements.TryGetValue(original, out var value) && Object.op_Implicit((Object)(object)value)) { ApplyTextures(value); return value; } if (!HasMapping(original)) { if (TextureRules.IsSwampTree(((Object)original).name)) { WarnOnce("unmapped:" + ((Object)original).name, "Unmapped tree material '" + ((Object)original).name + "'; preserving it (no guessed texture)."); } return original; } Material val = new Material(original) { name = ((Object)original).name }; if (ApplyTextures(val) == 0) { Object.Destroy((Object)(object)val); return original; } replacements[original] = val; owned.Add(val); TraceOnce("copy:" + ((Object)original).GetInstanceID(), "Material copy: " + ((Object)original).name + " shader=" + ((Object)original.shader).name + " source=" + ((Object)original).GetInstanceID() + " replacement=" + ((Object)val).GetInstanceID()); return val; } private void ApplyHierarchy(GameObject root, string context, bool inventory) { int num = 0; int num2 = 0; Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; bool flag = false; for (int j = 0; j < sharedMaterials.Length; j++) { Material val2 = sharedMaterials[j]; Material val3 = Replacement(val2); num++; if (inventory) { TraceOnce("slot:" + ((Object)val).GetInstanceID() + ":" + j, context + " renderer=" + PathOf(root.transform, ((Component)val).transform) + " slot=" + j + " activeSelf=" + ((Component)val).gameObject.activeSelf + " enabled=" + val.enabled + " material=" + (Object.op_Implicit((Object)(object)val2) ? ((Object)val2).name : "<null>") + " coverage=" + ((Object.op_Implicit((Object)(object)val3) && owned.Contains(val3)) ? "custom" : "unchanged")); } if ((Object)(object)val3 != (Object)(object)val2) { sharedMaterials[j] = val3; flag = true; num2++; } } if (flag) { val.sharedMaterials = sharedMaterials; } } InstanceRenderer[] componentsInChildren2 = root.GetComponentsInChildren<InstanceRenderer>(true); foreach (InstanceRenderer val4 in componentsInChildren2) { Material val5 = Replacement(val4.m_material); if ((Object)(object)val5 != (Object)(object)val4.m_material) { val4.m_material = val5; num2++; } if (inventory) { TraceOnce("instanced:" + ((Object)val4).GetInstanceID(), context + " InstanceRenderer=" + PathOf(root.transform, ((Component)val4).transform) + " material=" + (Object.op_Implicit((Object)(object)val5) ? ((Object)val5).name : "<null>")); } } if (!inventory) { return; } LODGroup[] componentsInChildren3 = root.GetComponentsInChildren<LODGroup>(true); foreach (LODGroup val6 in componentsInChildren3) { LOD[] lODs = val6.GetLODs(); for (int k = 0; k < lODs.Length; k++) { componentsInChildren = lODs[k].renderers; foreach (Renderer val7 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val7)) { TraceOnce("lod:" + ((Object)val6).GetInstanceID() + ":" + k + ":" + ((Object)val7).GetInstanceID(), context + " LOD=" + k + " threshold=" + lODs[k].screenRelativeTransitionHeight + " renderer=" + PathOf(root.transform, ((Component)val7).transform)); if ((Object)(object)((Component)val7).transform != (Object)(object)root.transform && !((Component)val7).transform.IsChildOf(root.transform)) { WarnOnce("external-lod:" + ((Object)val7).GetInstanceID(), "LOD references renderer outside target hierarchy: " + ((Object)val7).name); } } } } } TraceOnce("hierarchy:" + ((Object)root).GetInstanceID(), context + " slots=" + num + " reassigned=" + num2); } private static string PathOf(Transform root, Transform child) { string text = ((Object)child).name; while ((Object)(object)child != (Object)(object)root && Object.op_Implicit((Object)(object)child.parent)) { child = child.parent; text = ((Object)child).name + "/" + text; } return text; } private void PrepareGraph(GameObject prefab) { if (Object.op_Implicit((Object)(object)prefab) && !prepared.Contains(prefab)) { PrepareGraph(prefab, new HashSet<GameObject>()); } } private void PrepareGraph(GameObject prefab, HashSet<GameObject> visiting) { if (Object.op_Implicit((Object)(object)prefab) && !prepared.Contains(prefab) && visiting.Add(prefab)) { ApplyHierarchy(prefab, "prefab=" + ((Object)prefab).name, inventory: true); targetHashes.Add(StringExtensionMethods.GetStableHashCode(((Object)prefab).name)); TreeBase[] componentsInChildren = prefab.GetComponentsInChildren<TreeBase>(true); foreach (TreeBase val in componentsInChildren) { TraceOnce("chain:" + ((Object)prefab).GetInstanceID(), "Chain " + ((Object)prefab).name + " -> log=" + (Object.op_Implicit((Object)(object)val.m_logPrefab) ? ((Object)val.m_logPrefab).name : "<none>") + " stump=" + (Object.op_Implicit((Object)(object)val.m_stubPrefab) ? ((Object)val.m_stubPrefab).name : "<none>")); PrepareGraph(val.m_logPrefab, visiting); PrepareGraph(val.m_stubPrefab, visiting); } TreeLog[] componentsInChildren2 = prefab.GetComponentsInChildren<TreeLog>(true); foreach (TreeLog val2 in componentsInChildren2) { TraceOnce("sublog:" + ((Object)prefab).GetInstanceID(), "Chain " + ((Object)prefab).name + " -> split=" + (Object.op_Implicit((Object)(object)val2.m_subLogPrefab) ? ((Object)val2.m_subLogPrefab).name : "<none>")); PrepareGraph(val2.m_subLogPrefab, visiting); } prepared.Add(prefab); } } private void PrepareScene(ZNetScene scene) { foreach (GameObject prefab in scene.m_prefabs) { if (Object.op_Implicit((Object)(object)prefab) && TextureRules.IsSwampTree(((Object)prefab).name)) { PrepareGraph(prefab); } } foreach (GameObject nonNetViewPrefab in scene.m_nonNetViewPrefabs) { if (Object.op_Implicit((Object)(object)nonNetViewPrefab) && TextureRules.IsSwampTree(((Object)nonNetViewPrefab).name)) { PrepareGraph(nonNetViewPrefab); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Prefab coverage: roots/references=" + prepared.Count + " cached materials=" + owned.Count + "; creation safeguards enabled.")); foreach (string key in textures.Keys) { if (!matchedFiles.Contains(key)) { WarnOnce("unused:" + key, "Texture not yet applied to a supported prefab material: " + key + " (check missing shader properties/late assets)."); } } } private void PrepareVegetation(ZoneSystem zone) { foreach (ZoneVegetation item in zone.m_vegetation) { if (Object.op_Implicit((Object)(object)item.m_prefab) && TextureRules.IsSwampTree(((Object)item.m_prefab).name)) { PrepareGraph(item.m_prefab); } } } private void OnCreated(GameObject root, string reason) { if (Object.op_Implicit((Object)(object)root)) { ApplyHierarchy(root, reason + "=" + ((Object)root).name, inventory: false); liveRoots[((Object)root).GetInstanceID()] = new WeakReference<GameObject>(root); creationChecks++; if ((creationChecks & 0xFF) == 0) { PruneTrackedRoots(); } TraceOnce("creation:" + reason + ":" + ((Object)root).name, "Creation safeguard " + reason + " for " + ((Object)root).name + "; checked before first rendering; cached materials=" + owned.Count); } } private void PruneTrackedRoots() { List<int> list = new List<int>(); foreach (KeyValuePair<int, WeakReference<GameObject>> liveRoot in liveRoots) { if (!liveRoot.Value.TryGetTarget(out var target) || !Object.op_Implicit((Object)(object)target)) { list.Add(liveRoot.Key); } } foreach (int item in list) { liveRoots.Remove(item); } } private void ReapplyTrackedRoots() { List<int> list = new List<int>(); foreach (KeyValuePair<int, WeakReference<GameObject>> liveRoot in liveRoots) { if (!liveRoot.Value.TryGetTarget(out var target) || !Object.op_Implicit((Object)(object)target)) { list.Add(liveRoot.Key); } else { ApplyHierarchy(target, "manual-moss-reload=" + ((Object)target).name, inventory: false); } } foreach (int item in list) { liveRoots.Remove(item); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Moss reapplied to tracked tree roots=" + liveRoots.Count + "; no scene enumeration.")); } private bool IsTarget(GameObject root) { if (!Object.op_Implicit((Object)(object)root)) { return false; } if (!TextureRules.IsSwampTree(((Object)root).name)) { return targetHashes.Contains(StringExtensionMethods.GetStableHashCode(((Object)root).name.Replace("(Clone)", "").Trim())); } return true; } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Prime Swamp Trees stopped; creation checks=" + creationChecks + ". Restart the game to unload visual resources safely.")); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } internal static class TextureRules { internal static readonly string[] MossProperties = new string[3] { "_MossTex", "_MossTexture", "_MossMap" }; internal static readonly string[] ExpectedFiles = new string[10] { "mat_swamptree_log_MainTex.png", "mat_swamptree_log_MossTex.png", "mat_swamptree1_bark_MainTex.png", "mat_swamptree1_bark_MossTex.png", "mat_swamptree1_branch_MainTex.png", "mat_swamptree2_bark_MainTex.png", "mat_swamptree2_bark_MossTex.png", "mat_swamptree2_branch_MainTex.png", "mat_swamptree2_log_MainTex.png", "mat_swamptree2_log_MossTex.png" }; internal static string Normalize(string name) { return (name ?? "").Replace(" (Instance)", "").Replace(" (Clone)", "").Trim() .ToLowerInvariant(); } internal static bool IsSwampTree(string name) { return (name ?? "").IndexOf("swamptree", StringComparison.OrdinalIgnoreCase) >= 0; } internal static bool Matches(string normalizedMaterial, string key) { if (!normalizedMaterial.Equals(key, StringComparison.OrdinalIgnoreCase)) { return normalizedMaterial.StartsWith(key + " ", StringComparison.OrdinalIgnoreCase); } return true; } internal static bool TryParse(string filename, out string material, out string suffix) { string text = Path.GetFileNameWithoutExtension(filename).ToLowerInvariant(); int num = text.LastIndexOf('_'); material = (suffix = ""); if (num <= 4) { return false; } material = text.Substring(4, num - 4); suffix = text.Substring(num + 1); return true; } internal static string Property(string suffix) { if (!suffix.Equals("maintex", StringComparison.OrdinalIgnoreCase)) { return "_" + suffix.ToLowerInvariant(); } return "_MainTex"; } } }
BepInEx/plugins/PrimeWildLife/PrimeWildlife.dll
Decompiled 4 days agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using HarmonyLib; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PrimeWildlife")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PrimeWildlife")] [assembly: AssemblyTitle("PrimeWildlife")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PrimeWildlife { [BepInPlugin("com.prime.wildlife", "Prime Wildlife", "0.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class PrimeWildlifePlugin : BaseUnityPlugin { private Harmony _harmony; private void Awake() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown _harmony = new Harmony("com.prime.wildlife"); _harmony.PatchAll(typeof(PrimeWildlifePlugin).Assembly); PrefabManager.OnVanillaPrefabsAvailable += RegisterWildlife; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Prime Wildlife 0.2 loaded."); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= RegisterWildlife; if (_harmony != null) { _harmony.UnpatchSelf(); } } private void RegisterWildlife() { PrefabManager.OnVanillaPrefabsAvailable -= RegisterWildlife; RegisterClone("Boar", "PrimeBoar"); RegisterClone("Neck", "PrimeNeck"); } private void RegisterClone(string original, string custom) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = PrefabManager.Instance.CreateClonedPrefab(custom, original); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)(custom + ": source prefab not found: " + original)); return; } Character component = val.GetComponent<Character>(); if ((Object)(object)component == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)(custom + ": Character component missing.")); return; } component.m_faction = (Faction)3; PrefabManager.Instance.AddPrefab(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)("REGISTERED " + custom + " (Undead faction; vanilla AI retained).")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)(custom + " registration failed: " + ex)); } } } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] internal static class MatchingWildlifeNeutrality { private static bool Prefix(Character a, Character b, ref bool __result) { if ((Object)(object)a == (Object)null || (Object)(object)b == (Object)null) { return true; } string a2 = CleanName(((Object)((Component)a).gameObject).name); string b2 = CleanName(((Object)((Component)b).gameObject).name); if (IsPair(a2, b2, "Boar", "PrimeBoar") || IsPair(a2, b2, "Neck", "PrimeNeck")) { __result = false; return false; } return true; } private static bool IsPair(string a, string b, string vanilla, string prime) { return (a == vanilla && b == prime) || (a == prime && b == vanilla); } private static string CleanName(string name) { return name.Replace("(Clone)", "").Trim(); } } }