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 WagonR v1.4.0
LCWagonR.dll
Decompiled a day 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.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; 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: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] namespace LCWagonR; [Serializable] public class MatInfo { public string name; public Color color; public string texture; public string mode; } [Serializable] public class PartInfo { public string name; public Vector3 pos; public Vector3 size; public Vector3 axis; } [Serializable] public class Meta { public Vector3 boundsMin; public Vector3 boundsMax; public List<PartInfo> parts = new List<PartInfo>(); public List<PartInfo> wheels = new List<PartInfo>(); public List<PartInfo> seats = new List<PartInfo>(); public List<MatInfo> materials = new List<MatInfo>(); public PartInfo Part(string n) { return parts.FirstOrDefault((PartInfo p) => p.name == n); } public PartInfo Wheel(string n) { return wheels.FirstOrDefault((PartInfo p) => p.name == n); } } internal static class WagonAssets { public static AssetBundle Bundle; public static GameObject ModelPrefab; public static Meta Meta; public static string Error; private static Dictionary<string, Material> cache = new Dictionary<string, Material>(); private static Dictionary<string, Texture2D> texCache; public static Material Charred; public static bool Load() { //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ModelPrefab != (Object)null) { return true; } try { string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location), "wagonr.bundle"); if (!File.Exists(text)) { Error = "wagonr.bundle not found next to the plugin dll (" + text + ")"; return false; } Bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)Bundle == (Object)null) { Error = "AssetBundle.LoadFromFile failed for " + text; return false; } ModelPrefab = Bundle.LoadAsset<GameObject>("WagonR_Model"); TextAsset val = Bundle.LoadAsset<TextAsset>("wagonr_meta"); if ((Object)(object)ModelPrefab == (Object)null || (Object)(object)val == (Object)null) { Error = "bundle is missing WagonR_Model / wagonr_meta"; return false; } Meta = ParseMeta(val.text); Plugin.Log.LogInfo((object)$"Loaded wagonr.bundle: {Meta.parts.Count} parts, {Meta.wheels.Count} wheels, {Meta.seats.Count} seat parts, {Meta.materials.Count} materials, bounds {Meta.boundsMin} .. {Meta.boundsMax}"); if (Meta.wheels.Count != 4 || Meta.Part("SteeringWheel") == null || Meta.materials.Count == 0) { Error = "wagonr_meta is incomplete (rebuild the bundle)"; return false; } return true; } catch (Exception ex) { Error = ex.ToString(); return false; } } private static float F(string s) { return float.Parse(s, CultureInfo.InvariantCulture); } private static Vector3 V3(string[] f, int i) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) return new Vector3(F(f[i]), F(f[i + 1]), F(f[i + 2])); } public static Meta ParseMeta(string text) { //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_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_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_00d4: 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_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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) Meta meta = new Meta(); string[] array = text.Split(new char[1] { '\n' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0) { string[] array2 = text2.Split('|'); switch (array2[0]) { case "bounds": meta.boundsMin = V3(array2, 1); meta.boundsMax = V3(array2, 4); break; case "part": case "wheel": case "seat": { PartInfo item = new PartInfo { name = array2[1], pos = V3(array2, 2), size = V3(array2, 5), axis = V3(array2, 8) }; ((array2[0] == "part") ? meta.parts : ((array2[0] == "wheel") ? meta.wheels : meta.seats)).Add(item); break; } case "mat": meta.materials.Add(new MatInfo { name = array2[1], color = new Color(F(array2[2]), F(array2[3]), F(array2[4]), F(array2[5])), texture = ((array2[6].Length > 0) ? array2[6] : null), mode = array2[7] }); break; } } } return meta; } private static Texture TextureByName(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (texCache == null) { texCache = new Dictionary<string, Texture2D>(); Texture2D[] array = Bundle.LoadAllAssets<Texture2D>(); foreach (Texture2D val in array) { texCache[((Object)val).name] = val; } Plugin.Log.LogInfo((object)("[Mat] bundle textures: " + string.Join(", ", texCache.Keys))); } if (texCache.TryGetValue(name, out var value)) { return (Texture)(object)value; } value = Bundle.LoadAsset<Texture2D>(name); if ((Object)(object)value == (Object)null) { Plugin.Log.LogWarning((object)("[Mat] texture '" + name + "' NOT FOUND in the bundle")); } return (Texture)(object)value; } private static Material Template(GameObject cruiser, string namePrefix) { Renderer[] componentsInChildren = cruiser.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] sharedMaterials = componentsInChildren[i].sharedMaterials; foreach (Material val in sharedMaterials) { if ((Object)(object)val != (Object)null && ((Object)val).name.StartsWith(namePrefix)) { return val; } } } return null; } public static void DescribeTemplate(Material m, string tag) { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m == (Object)null) { Plugin.Log.LogWarning((object)("[Mat] template " + tag + ": NOT FOUND")); return; } Plugin.Log.LogInfo((object)(string.Format("[Mat] template {0} '{1}' shader={2} queue={3} keywords=[{4}] ", tag, ((Object)m).name, ((Object)m.shader).name, m.renderQueue, string.Join(" ", m.shaderKeywords)) + string.Format("baseMap={0} mask={1} normal={2} ", m.HasProperty("_BaseColorMap") && (Object)(object)m.GetTexture("_BaseColorMap") != (Object)null, m.HasProperty("_MaskMap") && (Object)(object)m.GetTexture("_MaskMap") != (Object)null, m.HasProperty("_NormalMap") && (Object)(object)m.GetTexture("_NormalMap") != (Object)null) + string.Format("base={0} smooth={1} metal={2} ", m.HasProperty("_BaseColor") ? ((object)m.GetColor("_BaseColor")/*cast due to .constrained prefix*/).ToString() : "-", m.HasProperty("_Smoothness") ? m.GetFloat("_Smoothness") : (-1f), m.HasProperty("_Metallic") ? m.GetFloat("_Metallic") : (-1f)) + string.Format("surface={0}", m.HasProperty("_SurfaceType") ? m.GetFloat("_SurfaceType") : (-1f)))); } public static void BuildMaterials(GameObject cruiser) { //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown //IL_01b3: 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_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) //IL_00a8: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: 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) //IL_01cf: 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_0103: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) cache.Clear(); Material val = Template(cruiser, "TruckTexture"); Material val2 = Template(cruiser, "WindshieldGlass"); DescribeTemplate(val, "opaque"); DescribeTemplate(val2, "glass"); if ((Object)(object)val == (Object)null) { throw new Exception("Cruiser opaque template material not found"); } foreach (MatInfo material in Meta.materials) { Material val3; if (material.mode == "glass" && (Object)(object)val2 != (Object)null) { val3 = new Material(val2) { name = "WagonR_" + material.name }; Color color = material.color; if (color.r + color.g + color.b < 0.01f) { ((Color)(ref color))..ctor(0.08f, 0.1f, 0.12f, 1f); } if (val3.HasProperty("_BaseColor")) { Color color2 = val3.GetColor("_BaseColor"); val3.SetColor("_BaseColor", new Color(color.r, color.g, color.b, Mathf.Min(color2.a, 0.45f))); } val3.DisableKeyword("_MATERIAL_FEATURE_IRIDESCENCE"); if (val3.HasProperty("_MaterialID")) { val3.SetFloat("_MaterialID", 1f); } } else { val3 = new Material(val) { name = "WagonR_" + material.name }; ResetMaps(val3); Texture val4 = TextureByName(material.texture); Color val5 = (((Object)(object)val4 != (Object)null) ? Color.white : material.color); if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", val5); } if (val3.HasProperty("_BaseColorMap")) { val3.SetTexture("_BaseColorMap", val4); } if (val3.HasProperty("_Metallic")) { val3.SetFloat("_Metallic", ((Object)(object)val4 != (Object)null) ? 0.15f : 0.05f); } if (val3.HasProperty("_Smoothness")) { val3.SetFloat("_Smoothness", Smoothness(material.name)); } } cache[material.name] = val3; } Charred = new Material(val) { name = "WagonR_Charred" }; ResetMaps(Charred); if (Charred.HasProperty("_BaseColor")) { Charred.SetColor("_BaseColor", new Color(0.04f, 0.035f, 0.03f, 1f)); } if (Charred.HasProperty("_Smoothness")) { Charred.SetFloat("_Smoothness", 0.1f); } if (Charred.HasProperty("_Metallic")) { Charred.SetFloat("_Metallic", 0f); } Plugin.Log.LogInfo((object)$"[Mat] built {cache.Count} materials (glass template: {(Object)(object)val2 != (Object)null})"); } private static float Smoothness(string n) { if (n == "primary" || n.StartsWith("boot_ok") || n.StartsWith("door")) { return 0.45f; } if (n.StartsWith("wheel")) { return 0.35f; } if (n.StartsWith("interior")) { return 0.15f; } return 0.3f; } private static void ResetMaps(Material m) { //IL_00c5: 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) string[] array = new string[6] { "_NormalMap", "_MaskMap", "_EmissiveColorMap", "_DetailMap", "_BentNormalMap", "_HeightMap" }; foreach (string text in array) { if (m.HasProperty(text)) { m.SetTexture(text, (Texture)null); } } array = new string[7] { "_NORMALMAP", "_MASKMAP", "_EMISSIVE_COLOR_MAP", "_DETAIL_MAP", "_BENTNORMALMAP", "_HEIGHTMAP", "_NORMALMAP_TANGENT_SPACE" }; foreach (string text2 in array) { m.DisableKeyword(text2); } if (m.HasProperty("_EmissiveColor")) { m.SetColor("_EmissiveColor", Color.black); } if (m.HasProperty("_BaseColorMap_ST")) { m.SetVector("_BaseColorMap_ST", new Vector4(1f, 1f, 0f, 0f)); } } public static Material ByName(string materialName) { if (!cache.TryGetValue(materialName, out var value)) { return null; } return value; } public static void Apply(GameObject model) { Renderer[] componentsInChildren = model.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { array[j] = (((Object)(object)sharedMaterials[j] != (Object)null) ? ByName(((Object)sharedMaterials[j]).name) : null) ?? Charred; } val.sharedMaterials = array; val.shadowCastingMode = (ShadowCastingMode)1; val.receiveShadows = true; } } } public class WagonRunner : MonoBehaviour { } internal static class WagonAudio { private static readonly Dictionary<string, AudioClip> clips = new Dictionary<string, AudioClip>(); private static readonly Dictionary<AudioClip, AudioClip> pitched = new Dictionary<AudioClip, AudioClip>(); private static bool loaded; private static readonly FieldInfo HoodOpen = AccessTools.Field(typeof(VehicleController), "carHoodOpenSFX"); private static readonly FieldInfo HoodClose = AccessTools.Field(typeof(VehicleController), "carHoodCloseSFX"); private static AudioClip cdoorOpen; private static AudioClip cdoorClose; private static AudioClip chatchOpen; private static AudioClip chatchClose; private static AudioClip choodOpen; private static AudioClip choodClose; public static int Count => clips.Count; public static int PitchedCount => pitched.Count; public static void Load() { if (loaded) { return; } loaded = true; string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location), "audio"); if (!Directory.Exists(text)) { Plugin.Log.LogWarning((object)("[Audio] no audio folder at " + text + ": the Wagon R keeps the Cruiser's engine sounds")); return; } string[] files = Directory.GetFiles(text, "*.wav"); foreach (string path in files) { try { AudioClip val = Read(path); if ((Object)(object)val != (Object)null) { clips[((Object)val).name] = val; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Audio] " + Path.GetFileName(path) + ": " + ex.Message)); } } Plugin.Log.LogInfo((object)$"[Audio] loaded {clips.Count} clips from {text}"); } public static AudioClip Get(string name) { if (!clips.TryGetValue(name, out var value)) { return null; } return value; } private static void Put(ref AudioClip field, string name) { AudioClip val = Get(name); if ((Object)(object)val != (Object)null) { field = val; } else { Plugin.Log.LogWarning((object)("[Audio] missing clip " + name)); } } private static AudioClip Read(string path) { byte[] array = File.ReadAllBytes(path); if (array.Length < 44 || array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70) { throw new Exception("not a RIFF file"); } int i = 12; int num = 1; int num2 = 44100; int num3 = 16; int num4 = -1; int num5 = 0; int num6; for (; i + 8 <= array.Length; i += 8 + num6 + (num6 & 1)) { string text = Encoding.ASCII.GetString(array, i, 4); num6 = BitConverter.ToInt32(array, i + 4); if (text == "fmt ") { num = BitConverter.ToInt16(array, i + 10); num2 = BitConverter.ToInt32(array, i + 12); num3 = BitConverter.ToInt16(array, i + 22); } else if (text == "data") { num4 = i + 8; num5 = Math.Min(num6, array.Length - num4); break; } } if (num4 < 0 || num3 != 16) { throw new Exception("need 16-bit PCM"); } int num7 = num5 / 2; float[] array2 = new float[num7]; for (int j = 0; j < num7; j++) { array2[j] = (float)BitConverter.ToInt16(array, num4 + j * 2) / 32768f; } AudioClip obj = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num7 / num, num, num2, false); obj.SetData(array2, 0); ((Object)obj).hideFlags = (HideFlags)61; return obj; } private static List<KeyValuePair<AudioClip, bool>> ReusedClips(VehicleController c) { List<KeyValuePair<AudioClip, bool>> l = new List<KeyValuePair<AudioClip, bool>>(); Action<AudioClip, bool> action = delegate(AudioClip a, bool loop) { if ((Object)(object)a != (Object)null) { l.Add(new KeyValuePair<AudioClip, bool>(a, loop)); } }; action(c.insertKey, arg2: false); action(c.twistKey, arg2: false); action(c.removeKey, arg2: false); action(c.sitDown, arg2: false); action(c.engineRev, arg2: false); action(c.revEngineStart, arg2: true); action(c.headlightsToggleSFX, arg2: false); action(c.turboBoostSFX, arg2: false); action(c.jumpInCarSFX, arg2: false); action(c.windshieldBreak, arg2: false); AudioClip[][] array = new AudioClip[5][] { c.gearStickAudios, c.minCollisions, c.medCollisions, c.maxCollisions, c.obstacleCollisions }; foreach (AudioClip[] array2 in array) { if (array2 != null) { AudioClip[] array3 = array2; foreach (AudioClip arg in array3) { action(arg, arg2: false); } } } if ((Object)(object)c.hornAudio != (Object)null) { action(c.hornAudio.clip, arg2: true); } if ((Object)(object)c.rollingAudio != (Object)null) { action(c.rollingAudio.clip, arg2: true); } if ((Object)(object)c.skiddingAudio != (Object)null) { action(c.skiddingAudio.clip, arg2: true); } return l; } public static void PrepareCruiser(VehicleController cruiser) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown float value = Cfg.CruiserPitch.Value; if ((Object)(object)cruiser == (Object)null || Mathf.Approximately(value, 1f)) { return; } try { GameObject val = new GameObject("WagonR_AudioPrep") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)val); ((MonoBehaviour)val.AddComponent<WagonRunner>()).StartCoroutine(PitchAll(ReusedClips(cruiser), value)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Audio] pitched Cruiser sounds unavailable (the Cruiser's originals are used): " + ex.Message)); } } private static IEnumerator PitchAll(List<KeyValuePair<AudioClip, bool>> list, float k) { int ok = 0; int failed = 0; foreach (KeyValuePair<AudioClip, bool> kv in list) { AudioClip src = kv.Key; if (!((Object)(object)src == (Object)null) && !pitched.ContainsKey(src)) { if ((int)src.loadState == 0) { src.LoadAudioData(); } float waited = 0f; while ((int)src.loadState == 1 && waited < 8f) { waited += Time.unscaledDeltaTime; yield return null; } string why; AudioClip val = Resample(src, k, kv.Value, out why); if ((Object)(object)val != (Object)null) { pitched[src] = val; ok++; } else { failed++; Plugin.Log.LogWarning((object)$"[Audio] cannot pitch '{((Object)src).name}' ({why}; loadType={src.loadType}, state={src.loadState}): it keeps the Cruiser's original"); } yield return null; } } Plugin.Log.LogInfo((object)$"[Audio] pitched {ok} Cruiser clips up by {k:0.00}x ({failed} could not be read)"); } private static AudioClip Resample(AudioClip src, float k, bool loop, out string why) { why = null; try { int channels = src.channels; int samples = src.samples; if (samples < 2) { why = "empty"; return null; } float[] array = new float[samples * channels]; if (!src.GetData(array, 0)) { why = "GetData refused"; return null; } int num = Mathf.Max(2, Mathf.RoundToInt((float)samples / k)); float num2 = (float)samples / (float)num; float[] array2 = new float[num * channels]; for (int i = 0; i < num; i++) { float num3 = (float)i * num2; int num4 = Mathf.Min((int)num3, samples - 1); float num5 = num3 - (float)num4; int num6 = num4 + 1; if (num6 >= samples) { num6 = ((!loop) ? (samples - 1) : 0); } for (int j = 0; j < channels; j++) { array2[i * channels + j] = Mathf.Lerp(array[num4 * channels + j], array[num6 * channels + j], num5); } } AudioClip obj = AudioClip.Create(((Object)src).name + "_p", num, channels, src.frequency, false); obj.SetData(array2, 0); ((Object)obj).hideFlags = (HideFlags)61; return obj; } catch (Exception ex) { why = ex.Message; return null; } } private static AudioClip Map(AudioClip c) { if (!((Object)(object)c != (Object)null) || !pitched.TryGetValue(c, out var value)) { return c; } return value; } private static AudioClip[] Map(AudioClip[] a) { return a?.Select(Map).ToArray(); } public static void ApplyRuntime(VehicleController vc) { vc.insertKey = Map(vc.insertKey); vc.twistKey = Map(vc.twistKey); vc.removeKey = Map(vc.removeKey); vc.sitDown = Map(vc.sitDown); vc.engineRev = Map(vc.engineRev); vc.revEngineStart = Map(vc.revEngineStart); vc.headlightsToggleSFX = Map(vc.headlightsToggleSFX); vc.turboBoostSFX = Map(vc.turboBoostSFX); vc.jumpInCarSFX = Map(vc.jumpInCarSFX); vc.windshieldBreak = Map(vc.windshieldBreak); vc.gearStickAudios = Map(vc.gearStickAudios); vc.minCollisions = Map(vc.minCollisions); vc.medCollisions = Map(vc.medCollisions); vc.maxCollisions = Map(vc.maxCollisions); vc.obstacleCollisions = Map(vc.obstacleCollisions); if ((Object)(object)vc.hornAudio != (Object)null) { vc.hornAudio.clip = Map(vc.hornAudio.clip); } if ((Object)(object)vc.rollingAudio != (Object)null) { vc.rollingAudio.clip = Map(vc.rollingAudio.clip); } if ((Object)(object)vc.skiddingAudio != (Object)null) { vc.skiddingAudio.clip = Map(vc.skiddingAudio.clip); } AudioClip val = Get("silent"); if ((Object)(object)val != (Object)null) { if (HoodOpen != null) { HoodOpen.SetValue(vc, val); } if (HoodClose != null) { HoodClose.SetValue(vc, val); } } } public static void CaptureCruiserBody(GameObject car, AnimatedObjectTrigger backDoor) { Func<string, PlayAudioAnimationEvent> func = delegate(string path) { Transform val3 = car.transform.Find(path); return (!((Object)(object)val3 != (Object)null)) ? null : ((Component)val3).GetComponent<PlayAudioAnimationEvent>(); }; PlayAudioAnimationEvent val = func("Meshes/DoorLeftContainer") ?? func("Meshes/DoorRightContainer"); if ((Object)(object)val != (Object)null) { cdoorClose = val.audioClip; cdoorOpen = val.audioClip2; } PlayAudioAnimationEvent val2 = func("Meshes/CarHoodContainer/CarHoodMesh"); if ((Object)(object)val2 != (Object)null) { choodClose = val2.audioClip; choodOpen = val2.audioClip2; } if ((Object)(object)backDoor != (Object)null) { if (backDoor.boolTrueAudios != null && backDoor.boolTrueAudios.Length != 0) { chatchOpen = backDoor.boolTrueAudios[0]; } if (backDoor.boolFalseAudios != null && backDoor.boolFalseAudios.Length != 0) { chatchClose = backDoor.boolFalseAudios[0]; } } Plugin.Log.LogInfo((object)("[Audio] Cruiser body clips: door " + Nm(cdoorOpen) + "/" + Nm(cdoorClose) + ", hatch " + Nm(chatchOpen) + "/" + Nm(chatchClose) + ", bonnet " + Nm(choodOpen) + "/" + Nm(choodClose))); } private static string Nm(AudioClip c) { if (!((Object)(object)c != (Object)null)) { return "null"; } return ((Object)c).name; } public static void BodySounds(WagonHinge h, AudioSource template, string kind) { if (clips.Count == 0) { return; } AudioClip val = null; AudioClip val2 = null; switch (kind) { case "door": val = cdoorOpen; val2 = cdoorClose; break; case "hatch": val = chatchOpen; val2 = chatchClose; break; case "hood": val = choodOpen; val2 = choodClose; break; } if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)h == (Object)null)) { AudioSource val3 = ((Component)h).gameObject.AddComponent<AudioSource>(); val3.playOnAwake = false; val3.loop = false; val3.spatialBlend = 1f; val3.minDistance = 2f; val3.maxDistance = 30f; val3.rolloffMode = (AudioRolloffMode)1; val3.dopplerLevel = 0f; val3.pitch = Cfg.CruiserPitch.Value; if ((Object)(object)template != (Object)null) { val3.outputAudioMixerGroup = template.outputAudioMixerGroup; } h.sfx = val3; h.openClips = (AudioClip[])(object)new AudioClip[1] { val }; h.closeClips = (AudioClip[])(object)new AudioClip[1] { val2 }; } } public static void Apply(VehicleController vc, GameObject car) { if (clips.Count == 0) { return; } Put(ref vc.engineStartSuccessful, "engine_start"); Put(ref vc.engineRun, "engine_idle"); Put(ref vc.engineRun2, "engine_high"); Put(ref vc.turboBoostSFX2, "engine_blip"); if ((Object)(object)vc.engineAudio2 != (Object)null && (Object)(object)Get("engine_high") != (Object)null) { vc.engineAudio2.clip = Get("engine_high"); } AudioClip val = Get("silent"); if ((Object)(object)val != (Object)null) { PlayAudioAnimationEvent[] componentsInChildren = car.GetComponentsInChildren<PlayAudioAnimationEvent>(true); foreach (PlayAudioAnimationEvent val2 in componentsInChildren) { if ((Object)(object)val2.audioClip != (Object)null) { val2.audioClip = val; } if ((Object)(object)val2.audioClip2 != (Object)null) { val2.audioClip2 = val; } if ((Object)(object)val2.audioClip3 != (Object)null) { val2.audioClip3 = val; } if (val2.randomClips != null && val2.randomClips.Length != 0) { val2.randomClips = (AudioClip[])(object)new AudioClip[1] { val }; } if (val2.randomClips2 != null && val2.randomClips2.Length != 0) { val2.randomClips2 = (AudioClip[])(object)new AudioClip[1] { val }; } } } Plugin.Log.LogInfo((object)"[Audio] Wagon R engine sounds applied"); } } internal static class WagonSound { private const float Idle = 900f; private const float Limit = 5600f; private const float IdleClipRpm = 880f; private const float HighClipRpm = 3000f; private static readonly float[] GearTop = new float[5] { 0.3f, 0.5f, 0.7f, 0.9f, 1.15f }; private static float RpmAt(int gear, float g) { return Mathf.Clamp(900f + g / (GearTop[gear - 1] * Cfg.TopSpeed.Value) * 4700f, 900f, 7000f); } public static void Engine(VehicleController v, WagonTag t) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Invalid comparison between Unknown and I4 if (!v.ignitionStarted || (Object)(object)v.engineAudio1 == (Object)null || WagonAudio.Count == 0) { return; } float deltaTime = Time.deltaTime; if (deltaTime <= 0f) { return; } float num = Mathf.Abs(v.EngineRPM) / 60f * 2f * MathF.PI * Mathf.Max(0.05f, v.FrontLeftWheel.radius); t.sndAccel = Mathf.Lerp(t.sndAccel, (num - t.sndLastSpeed) / deltaTime, 1f - Mathf.Exp((0f - deltaTime) / 0.25f)); t.sndLastSpeed = num; bool num2 = (int)v.gear == 2; bool flag = ((NetworkBehaviour)v).IsOwner && v.localPlayerInControl && v.drivePedalPressed; if (num2 || num < 1.2f) { t.sndGear = 1; } else if (t.sndShift <= 0f) { if (t.sndGear < 5 && RpmAt(t.sndGear, num) > 4700f) { t.sndGear++; t.sndShift = 0.35f; } else if (t.sndGear > 1 && RpmAt(t.sndGear, num) < 1700f) { t.sndGear--; t.sndShift = 0.3f; } } float num3 = RpmAt(t.sndGear, num); if (num < 1.2f) { num3 = (flag ? 2600f : (900f + 12f * Mathf.Sin(Time.time * 9f))); } if (t.sndShift > 0f) { t.sndShift -= deltaTime; num3 = Mathf.Max(900f, num3 - 900f * Mathf.Sin(Mathf.Clamp01(t.sndShift / 0.35f) * MathF.PI)); } t.sndRpm += (num3 - t.sndRpm) * (1f - Mathf.Exp((0f - deltaTime) / ((num3 > t.sndRpm) ? 0.09f : 0.2f))); float num4 = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(1300f, 2000f, t.sndRpm)); float num5 = Mathf.Clamp01(0.35f + t.sndAccel / 3f); if (flag) { num5 = Mathf.Max(num5, 0.9f); } float num6 = Mathf.Lerp(0.6f, 1f, num5); v.engineAudio1.pitch = Mathf.Clamp(t.sndRpm / 880f, 0.7f, 2.6f); v.engineAudio1.volume = (1f - num4) * num6 * 0.9f; if ((Object)(object)v.engineAudio2 != (Object)null) { v.engineAudio2.pitch = Mathf.Clamp(t.sndRpm / 3000f, 0.45f, 2f); v.engineAudio2.volume = num4 * num6 * 0.9f; } } } [HarmonyPatch(typeof(VehicleController), "SetCarEffects")] internal static class P_Vehicle_Effects { private static void Postfix(VehicleController __instance) { WagonTag wagonTag = Tuning.Of(__instance); if ((Object)(object)wagonTag != (Object)null) { WagonSound.Engine(__instance, wagonTag); } } } public class WagonCabinGuard : MonoBehaviour { public VehicleController vc; public Transform[] ejectPoints; private Transform rig; private float lastTip = -99f; private float poseCheck; private float poseFix; private const float HalfWidth = 0.66f; private const float ZMin = -1.97f; private const float ZMax = 0.85f; private const float FeetMin = 0.48f; private const float FeetMax = 1.8f; private const int VehicleLayerMask = 1073741824; private float lastSeatLog = -99f; private void Awake() { rig = ((Component)this).transform.Find("Rig"); } private void LateUpdate() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (!Cfg.SeatedNoCollide.Value || (Object)(object)vc == (Object)null) { return; } GameNetworkManager instance = GameNetworkManager.Instance; PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null); if ((Object)(object)val == (Object)null || !val.isPlayerControlled || !val.inSpecialInteractAnimation || (!vc.localPlayerInPassengerSeat && !vc.localPlayerInControl)) { return; } CharacterController thisController = val.thisController; if ((Object)(object)thisController == (Object)null) { return; } LayerMask excludeLayers = ((Collider)thisController).excludeLayers; if ((((LayerMask)(ref excludeLayers)).value & 0x40000000) != 1073741824) { excludeLayers = ((Collider)thisController).excludeLayers; ((Collider)thisController).excludeLayers = LayerMask.op_Implicit(((LayerMask)(ref excludeLayers)).value | 0x40000000); if (Time.time - lastSeatLog > 2f) { lastSeatLog = Time.time; Plugin.Log.LogInfo((object)"[Seat] the game re-enabled car collisions for the seated local player: switched off again"); } } } public bool IsInside(Vector3 worldFeet) { //IL_0016: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rig == (Object)null) { return false; } Vector3 val = rig.InverseTransformPoint(worldFeet) / Cfg.ModelScale.Value; if (Mathf.Abs(val.x) < 0.66f && val.z > -1.97f && val.z < 0.85f && val.y > 0.48f) { return val.y < 1.8f; } return false; } private void CheckPassengerPose(PlayerControllerB me) { if (!Cfg.PassengerPoseFix.Value || Time.time < poseCheck) { return; } poseCheck = Time.time + 0.25f; if (!vc.localPlayerInPassengerSeat || vc.localPlayerInControl || !me.inSpecialInteractAnimation) { return; } Animator playerBodyAnimator = me.playerBodyAnimator; if (!((Object)(object)playerBodyAnimator == (Object)null)) { if (playerBodyAnimator.GetInteger("SA_CarAnim") != 0) { playerBodyAnimator.SetInteger("SA_CarAnim", 0); } int layerIndex = playerBodyAnimator.GetLayerIndex("SpecialAnimations"); if (layerIndex >= 0 && !(Time.time < poseFix) && playerBodyAnimator.GetCurrentAnimatorClipInfo(layerIndex).Any((AnimatorClipInfo c) => (Object)(object)((AnimatorClipInfo)(ref c)).clip != (Object)null && ((Object)((AnimatorClipInfo)(ref c)).clip).name == "SitAndSteer")) { poseFix = Time.time + 1.5f; playerBodyAnimator.ResetTrigger("SA_Truck"); playerBodyAnimator.SetTrigger("SA_Truck"); Plugin.Log.LogInfo((object)"[Cabin] passenger was in the driver's hands-on-the-wheel pose: put back"); } } } private void Update() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) if (!Cfg.KeepOutOfCabin.Value || (Object)(object)vc == (Object)null) { return; } GameNetworkManager instance = GameNetworkManager.Instance; PlayerControllerB me = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null); if ((Object)(object)me == (Object)null || !me.isPlayerControlled || me.isPlayerDead) { return; } CheckPassengerPose(me); if (me.inSpecialInteractAnimation || me.isCrouching || !IsInside(((Component)me).transform.position)) { return; } Transform val = ((ejectPoints != null) ? ejectPoints.Where((Transform p) => (Object)(object)p != (Object)null).OrderBy(delegate(Transform p) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = p.position - ((Component)me).transform.position; return ((Vector3)(ref val2)).sqrMagnitude; }).FirstOrDefault() : null); if (!((Object)(object)val == (Object)null)) { Plugin.Log.LogInfo((object)$"[Cabin] moved {me.playerUsername} out of the Wagon R body (was at {rig.InverseTransformPoint(((Component)me).transform.position) / Cfg.ModelScale.Value}) -> {((Object)val).name}"); me.TeleportPlayer(val.position, false, 0f, false, true); if (Time.time - lastTip > 4f && (Object)(object)HUDManager.Instance != (Object)null) { lastTip = Time.time; HUDManager.Instance.DisplayTip("Wagon R", "No room to stand inside. Use the seats.", false, false, "LC_WagonRStand"); } } } } internal static class Cfg { public static ConfigEntry<int> Price; public static ConfigEntry<string> DisplayName; public static ConfigEntry<int> Hitpoints; public static ConfigEntry<float> Mass; public static ConfigEntry<float> TopSpeed; public static ConfigEntry<float> ReverseSpeed; public static ConfigEntry<float> Power; public static ConfigEntry<float> ComHeight; public static ConfigEntry<float> HighSpeedLock; public static ConfigEntry<float> LockFadeSpeed; public static ConfigEntry<float> SteerReturn; public static ConfigEntry<float> ModelScale; public static ConfigEntry<float> SeatBack; public static ConfigEntry<float> WheelTowardDriver; public static ConfigEntry<bool> LightTuning; public static ConfigEntry<float> CruiserPitch; public static ConfigEntry<float> TyreGrip; public static ConfigEntry<float> TyrePeakSlip; public static ConfigEntry<float> TyreTraction; public static ConfigEntry<float> YawInertia; public static ConfigEntry<float> SteeringSpeed; public static ConfigEntry<float> RollingDrag; public static ConfigEntry<float> AngularDrag; public static ConfigEntry<float> EngineBraking; public static ConfigEntry<float> BrakeTorque; public static ConfigEntry<float> MaxLateralAccel; public static ConfigEntry<bool> AutoGearbox; public static ConfigEntry<Key> HandbrakeKey; public static ConfigEntry<bool> DriverSeatOnRight; public static ConfigEntry<bool> KeepOutOfCabin; public static ConfigEntry<bool> PassengerPoseFix; public static ConfigEntry<bool> SeatedNoCollide; public static ConfigEntry<bool> TowEnabled; public static ConfigEntry<bool> VehiclesCollide; public static ConfigEntry<bool> CrashScaling; public static ConfigEntry<bool> SoftLandings; public static ConfigEntry<float> RopeLength; public static ConfigEntry<float> RopeStiffness; public static ConfigEntry<float> RopeDamping; public static ConfigEntry<float> RopeSnap; public static ConfigEntry<bool> Debug; public static void Bind(ConfigFile c) { Price = c.Bind<int>("Shop", "Price", 250, "Terminal price in credits (the Company Cruiser costs 370)."); DisplayName = c.Bind<string>("Shop", "DisplayName", "Wagon R", "Name shown in the terminal store."); Hitpoints = c.Bind<int>("Car", "Hitpoints", 20, "Car health (the Cruiser has 30). It regenerates slowly above 16 like the Cruiser."); CrashScaling = c.Bind<bool>("Car", "CrashScaling", true, "The crash force that counts as a bump / a hard hit is scaled with the car's mass (LightMass / 200), so the same speed into a wall hurts the Wagon R as much as it hurts the Cruiser. A hit's force grows with the car's mass, so without this the lighter Wagon would be harder to damage. false = the Cruiser's thresholds as they are."); SoftLandings = c.Bind<bool>("Car", "SoftLandings", true, "Landing on a floor / ramp / the ground (a surface that faces up) is judged by the speed INTO the surface instead of the car's whole speed, and one landing counts once. Without it a jump that lands at 30 m/s forwards + 13 m/s down is above the Cruiser's 31 m/s 'near-destruction' limit and wrecks a small car in one go. A fall adds damage by its speed instead: nothing up to 14 m/s into the ground, 2 hit points at 20 m/s, 4 at 25 m/s, at most 6. Walls are not affected. false = the Cruiser's rules."); Mass = c.Bind<float>("Car", "LightMass", 140f, "Rigidbody mass (the Cruiser is 200). Lighter = zippier. The suspension is scaled with it. Must be the same for every player in the lobby."); ModelScale = c.Bind<float>("Car", "ModelScale", 1.6f, "Size of the car relative to the model file (1.0 = a real hatchback). The seated pose is a baked animation made for the Cruiser's big cab, so values around 1.5-1.7 fit best. Must be the same for every player in the lobby."); SeatBack = c.Bind<float>("Car", "SeatBackOffset", 0.2f, "Metres the seated player is moved back from the Cruiser-derived position (more room to the wheel; the baked hand animation then reaches slightly)."); WheelTowardDriver = c.Bind<float>("Car", "WheelTowardDriver", 0.08f, "Metres the steering wheel is moved towards the driver so the hands still reach it after SeatBackOffset."); CruiserPitch = c.Bind<float>("Sound", "CruiserPitch", 1.2f, "Every sound except the engine is the Company Cruiser's own recording, pitched up by this factor (1.0 = unchanged, 1.2 = 20% higher)."); LightTuning = c.Bind<bool>("Handling", "SmallCarTuning", true, "Handling of a small light hatchback instead of the Cruiser's big soft truck: tyres that bite (the Cruiser's peak at a 35 degree slip angle), a lower yaw inertia, quicker steering, rolling resistance and engine braking. false = the Cruiser's tuning."); TyreGrip = c.Bind<float>("Handling", "TyreGrip", 1.3f, "Maximum side grip of the tyres (about 1.3 g). The Cruiser's tyres give 2.0 g, which is why it corners like a rail and tips over if you push a lighter body."); TyrePeakSlip = c.Bind<float>("Handling", "TyrePeakSlip", 0.25f, "Slip at which the tyres give their maximum side force. Lower = crisper turn-in, but twitchier (the Cruiser: 0.7)."); TyreTraction = c.Bind<float>("Handling", "TyreTraction", 1.5f, "Forward (drive/brake) tyre stiffness, all four wheels (the Cruiser: 2.0 front, 0.75 rear)."); YawInertia = c.Bind<float>("Handling", "YawInertia", 0.65f, "Multiplier on the car's resistance to turning about its vertical axis. Lower = changes direction faster."); SteeringSpeed = c.Bind<float>("Handling", "SteeringSpeed", 6.5f, "How fast the steering wheel winds while a steering key is held (the Cruiser: 4)."); RollingDrag = c.Bind<float>("Handling", "RollingDrag", 0.01f, "Air + rolling resistance (linear drag). 0.01 is the Cruiser's: it coasts almost forever. A higher value (0.05) makes the car slow down quicker when you lift off."); AngularDrag = c.Bind<float>("Handling", "AngularDrag", 1f, "Damping of the car's rotation (the Cruiser: 0.5)."); EngineBraking = c.Bind<float>("Handling", "EngineBraking", 40f, "Brake torque per wheel (Nm) applied in Drive/Reverse when no pedal is pressed, so the car slows down when you lift off."); MaxLateralAccel = c.Bind<float>("Handling", "MaxCornerAccel", 22f, "The steering lock is reduced with speed so that the turn it asks for never needs more sideways acceleration than this (m/s2). The Cruiser's wheels never slip, so an unlimited lock at speed rolls a light car over (tested: it flips at 26 m/s with 13 degrees)."); BrakeTorque = c.Bind<float>("Handling", "BrakeTorque", 450f, "Brake torque per wheel (Nm) while braking: about 20 m/s2, stopping from 22 m/s in roughly a second (the world's gravity is 32 m/s2, so this is a firm but not instant stop). The Cruiser uses 2000, which stops it in under half a second."); AutoGearbox = c.Bind<bool>("Handling", "AutomaticGearbox", true, "W selects Drive from Park, S brakes and then reverses (S = gas while in Reverse). The gear lever on the console still works. false = Cruiser behaviour (lever only)."); TopSpeed = c.Bind<float>("Handling", "TopSpeed", 100f, "Soft top speed in m/s: the motors fade out over the last quarter of it. 100 means no limit of its own: the game caps every vehicle at 50 m/s (180 km/h) anyway. Use 30 (108 km/h) for a slower, more hatchback-like car. It also stretches the gears of the engine sound."); ReverseSpeed = c.Bind<float>("Handling", "ReverseSpeed", 9f, "Top reverse speed in m/s."); Power = c.Bind<float>("Handling", "Power", 0.45f, "Multiplier on the Cruiser's motor torque (it is clamped to 325..1000 Nm per wheel in vanilla). Lower = slower acceleration."); ComHeight = c.Bind<float>("Handling", "CenterOfMassHeight", 0.5f, "Centre of mass height above the ground in metres. Lower = harder to roll."); HighSpeedLock = c.Bind<float>("Handling", "HighSpeedSteerLimit", 0.9f, "Steering input limit at high speed (3 = full 45 degrees lock, 0.9 = 13.5 degrees)."); LockFadeSpeed = c.Bind<float>("Handling", "SteerLockFadeSpeed", 22f, "Speed in m/s at which the high-speed steering limit is fully applied."); SteerReturn = c.Bind<float>("Handling", "SteerReturnRate", 5f, "How fast the steering re-centres when no steering key is held (the Cruiser never re-centres)."); HandbrakeKey = c.Bind<Key>("Controls", "HandbrakeKey", (Key)30, "Keyboard key that pulls / releases the handbrake while you drive (the lever between the seats can be clicked too). Use a Key name of the Unity Input System: P, H, Space, LeftAlt ..."); DriverSeatOnRight = c.Bind<bool>("Car", "DriverSeatOnRight", true, "India-spec Wagon R is right-hand drive, like the model. false mirrors the seats (the car model itself is not mirrored)."); KeepOutOfCabin = c.Bind<bool>("Car", "KeepOutOfCabin", true, "A player who stands (not seated) inside the car body is moved out next to the nearest door. The Cruiser is an open truck; the Wagon has a roof and floor, and standing in it makes the car's physics fight the player and throws the car into the air."); PassengerPoseFix = c.Bind<bool>("Car", "PassengerPoseFix", true, "A passenger never sits with the driver's hands-on-the-wheel pose: if the game puts the driver's hand animation on a passenger it is taken off again."); SeatedNoCollide = c.Bind<bool>("Car", "SeatedPlayerNoCollide", true, "A player sitting in the car never collides with its body. The game re-enables that collision for a seated passenger whenever the car's physics moves to their machine (for example when the driver gets out); the Wagon has a solid body, so the squeeze launches the car into the air."); VehiclesCollide = c.Bind<bool>("Car", "VehiclesCollide", true, "Vehicles collide with each other (a Wagon R with a Cruiser or another Wagon R), through duplicates of their hulls on a private physics layer. Must be the same for every player."); TowEnabled = c.Bind<bool>("Tow", "Enabled", true, "Tow hitch on the Wagon R: hook a rope to another Wagon R or a Company Cruiser. Must be the same for every player."); RopeLength = c.Bind<float>("Tow", "RopeLength", 6f, "Length of the tow rope in metres, between the two tie points."); RopeStiffness = c.Bind<float>("Tow", "RopeStiffness", 9000f, "How hard the rope pulls once it is stretched (N per metre). Higher = less bounce, harder jerks."); RopeDamping = c.Bind<float>("Tow", "RopeDamping", 100f, "Damping of the rope's pull (N s per metre). Lower = bouncier."); RopeSnap = c.Bind<float>("Tow", "SnapStretch", 0f, "The rope snaps when it is stretched this many metres beyond its length. 0 = it never snaps (tug of war between two vehicles)."); Debug = c.Bind<bool>("Debug", "VerboseBuildLog", false, "Log every node the vehicle builder touches."); } } public class WagonHandbrake : MonoBehaviour { public VehicleController vc; public InteractTrigger trigger; public Transform lever; public const float ReleasedAngle = 14f; private const float Speed = 110f; private Quaternion baseRot; private float angle; private bool init; private bool lastOn; private bool Engaged => HandbrakeNet.On(vc); private float Target { get { if (!Engaged) { return 14f; } return 0f; } } public float Angle => angle; private void Update() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_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 ((Object)(object)vc == (Object)null) { return; } bool engaged = Engaged; if ((Object)(object)lever != (Object)null) { if (!init) { baseRot = lever.localRotation; angle = Target; lastOn = engaged; init = true; } angle = Mathf.MoveTowards(angle, Target, 110f * Time.deltaTime); lever.localRotation = Quaternion.Euler(angle, 0f, 0f) * baseRot; } if (engaged != lastOn) { lastOn = engaged; try { if ((Object)(object)vc.gearStickAudio != (Object)null && vc.gearStickAudios != null && vc.gearStickAudios.Length != 0) { vc.gearStickAudio.PlayOneShot(vc.gearStickAudios[0]); } } catch { } } if ((Object)(object)trigger != (Object)null) { string text = (vc.carDestroyed ? "" : (engaged ? "Release handbrake : [LMB]" : "Pull handbrake : [LMB]")); if (trigger.hoverTip != text) { trigger.hoverTip = text; } } } private void FixedUpdate() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 if (!((Object)(object)vc == (Object)null) && ((NetworkBehaviour)vc).IsOwner && !vc.localPlayerInControl && !((Object)(object)vc.currentDriver != (Object)null) && !vc.carDestroyed && !vc.magnetedToShip && vc.hasBeenSpawned && (!((Object)(object)TowManager.Instance != (Object)null) || TowManager.Instance.LinkOf(vc) == null)) { bool flag = (int)vc.gear == 3; bool engaged = Engaged; Hold(vc.FrontLeftWheel, flag, handbrake: false); Hold(vc.FrontRightWheel, flag, handbrake: false); Hold(vc.BackLeftWheel, flag || engaged, engaged); Hold(vc.BackRightWheel, flag || engaged, engaged); } } private static void Hold(WheelCollider w, bool locked, bool handbrake) { if (!((Object)(object)w == (Object)null)) { w.brakeTorque = (handbrake ? 20000f : (locked ? 2000f : 0f)); w.motorTorque = (locked ? 0f : 0.0001f); } } public bool Use(PlayerControllerB who) { PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val == (Object)null || (Object)(object)who != (Object)(object)val || (Object)(object)vc == (Object)null || vc.carDestroyed || (Object)(object)HandbrakeNet.Instance == (Object)null) { return true; } HandbrakeNet.Instance.Request(vc, !Engaged); return true; } public static void PollKey(VehicleController v) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if (current != null && !((Object)(object)val == (Object)null) && !((Object)(object)HandbrakeNet.Instance == (Object)null) && !v.carDestroyed && ((ButtonControl)current[Cfg.HandbrakeKey.Value]).wasPressedThisFrame && !val.isTypingChat && !val.inTerminalMenu && (!((Object)(object)val.quickMenuManager != (Object)null) || !val.quickMenuManager.isMenuOpen)) { HandbrakeNet.Instance.Request(v, !HandbrakeNet.On(v)); } } } public class HandbrakeNet : MonoBehaviour { public static HandbrakeNet Instance; public const float LockTorque = 20000f; private const string ReqName = "um.lcwagonr.hb.req"; private const string SyncName = "um.lcwagonr.hb.sync"; private readonly Dictionary<ulong, bool> state = new Dictionary<ulong, bool>(); private object registeredFor; private Action<ulong> connectedHandler; private float nextPrune; private static NetworkManager NM => NetworkManager.Singleton; private static bool IsServer { get { NetworkManager nM = NM; if ((Object)(object)nM != (Object)null && nM.IsListening) { return nM.IsServer; } return false; } } public static void Create() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)Instance != (Object)null)) { GameObject val = new GameObject("WagonR.Handbrake"); Object.DontDestroyOnLoad((Object)val); Instance = val.AddComponent<HandbrakeNet>(); } } public static ulong IdOf(VehicleController v) { if (!((Object)(object)v != (Object)null) || !((Object)(object)((NetworkBehaviour)v).NetworkObject != (Object)null) || !((NetworkBehaviour)v).NetworkObject.IsSpawned) { return 0uL; } return ((NetworkBehaviour)v).NetworkObject.NetworkObjectId; } public static bool On(VehicleController v) { HandbrakeNet instance = Instance; ulong num = IdOf(v); bool value = default(bool); return (Object)(object)instance != (Object)null && num != 0L && instance.state.TryGetValue(num, out value) && value; } public unsafe void Request(VehicleController v, bool on) { //IL_004f: 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_0061: 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_007a: Unknown result type (might be due to invalid IL or missing references) ulong num = IdOf(v); if (num == 0L) { return; } state[num] = on; if (IsServer) { Broadcast(); return; } NetworkManager nM = NM; if ((Object)(object)nM == (Object)null || nM.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(32, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref on, default(ForPrimitives)); nM.CustomMessagingManager.SendNamedMessage("um.lcwagonr.hb.req", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private void OnRequest(ulong sender, FastBufferReader r) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) if (IsServer) { ulong key = default(ulong); ((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref key, default(ForPrimitives)); bool value = default(bool); ((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref value, default(ForPrimitives)); state[key] = value; Broadcast(); } } private unsafe void Broadcast() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) NetworkManager nM = NM; if ((Object)(object)nM == (Object)null || nM.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16 + state.Count * 16, (Allocator)2, -1); try { int count = state.Count; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref count, default(ForPrimitives)); foreach (KeyValuePair<ulong, bool> item in state) { ulong key = item.Key; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref key, default(ForPrimitives)); bool value = item.Value; ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value, default(ForPrimitives)); } nM.CustomMessagingManager.SendNamedMessageToAll("um.lcwagonr.hb.sync", val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private void OnSync(ulong sender, FastBufferReader r) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!IsServer) { int num = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives)); state.Clear(); ulong key = default(ulong); bool value = default(bool); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref key, default(ForPrimitives)); ((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref value, default(ForPrimitives)); state[key] = value; } } } private void Register() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown NetworkManager nM = NM; if ((Object)(object)nM == (Object)null || !nM.IsListening || nM.CustomMessagingManager == null) { if (registeredFor != null) { registeredFor = null; state.Clear(); } } else { if (registeredFor == nM.CustomMessagingManager) { return; } registeredFor = nM.CustomMessagingManager; state.Clear(); nM.CustomMessagingManager.RegisterNamedMessageHandler("um.lcwagonr.hb.req", new HandleNamedMessageDelegate(OnRequest)); nM.CustomMessagingManager.RegisterNamedMessageHandler("um.lcwagonr.hb.sync", new HandleNamedMessageDelegate(OnSync)); if (nM.IsServer) { connectedHandler = delegate { if (state.Count > 0) { Broadcast(); } }; nM.OnClientConnectedCallback += connectedHandler; } Plugin.Log.LogInfo((object)("[Handbrake] network messages registered (" + (nM.IsServer ? "host" : "client") + ")")); } } private void Update() { Register(); if (!IsServer || !(Time.time > nextPrune)) { return; } nextPrune = Time.time + 5f; NetworkManager nM = NM; List<ulong> list = new List<ulong>(); foreach (ulong key in state.Keys) { if (nM.SpawnManager == null || !nM.SpawnManager.SpawnedObjects.TryGetValue(key, out var value) || (Object)(object)value == (Object)null) { list.Add(key); } } if (list.Count <= 0) { return; } foreach (ulong item in list) { state.Remove(item); } Broadcast(); } } [HarmonyPatch(typeof(VehicleController), "OnCollisionEnter")] internal static class P_Vehicle_Landing { public static bool Trace; private static readonly MethodInfo Damage = AccessTools.Method(typeof(VehicleController), "DealPermanentDamage", (Type[])null, (Type[])null); public static int FallDamage(float into) { return Mathf.Clamp(Mathf.RoundToInt((into - 14f) / 3f), 0, 6); } private static bool Prefix(VehicleController __instance, Collision collision, out Vector3 __state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_005c: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) __state = __instance.averageVelocity; WagonTag wagonTag = Tuning.Of(__instance); if ((Object)(object)wagonTag == (Object)null || !Cfg.SoftLandings.Value || !((NetworkBehaviour)__instance).IsOwner || ((Component)collision.collider).gameObject.layer != 8) { return true; } int contactCount = collision.contactCount; if (contactCount == 0) { return true; } Vector3 val = Vector3.zero; for (int i = 0; i < contactCount; i++) { Vector3 val2 = val; ContactPoint contact = collision.GetContact(i); val = val2 + ((ContactPoint)(ref contact)).normal; } val /= (float)contactCount; if (val.y < 0.6f) { return true; } ((Vector3)(ref val)).Normalize(); float num = ((wagonTag.Airborne || Time.time - wagonTag.touchdown < 0.5f) ? wagonTag.fallPeak : 0f); float num2 = Mathf.Max(Mathf.Abs(Vector3.Dot(collision.relativeVelocity, val)), num); if (Time.time - wagonTag.lastLanding < 0.6f) { return false; } if (num2 >= 4f) { wagonTag.lastLanding = Time.time; } __instance.averageVelocity = ((Vector3)(ref __state)).normalized * Mathf.Min(((Vector3)(ref __state)).magnitude, num2); int num3 = FallDamage(num2); if (Trace && num2 >= 6f) { Plugin.Log.LogInfo((object)$"[Landing] speed into the surface {Mathf.Abs(Vector3.Dot(collision.relativeVelocity, val)):0.0} at the first touch, fastest fall since take-off {num:0.0} (average velocity {__state.x:0.0}, {__state.y:0.0}, {__state.z:0.0}) -> judged {num2:0.0}, fall damage {num3}, hp {__instance.carHP}"); } if (num3 > 0 && Damage != null && !__instance.carDestroyed) { try { Damage.Invoke(__instance, new object[2] { num3, (object)default(Vector3) }); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Landing] fall damage failed: " + ex.Message)); } } return true; } private static void Postfix(VehicleController __instance, Vector3 __state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) __instance.averageVelocity = __state; } } public class WagonHinge : MonoBehaviour { public AnimatedObjectTrigger trigger; public VehicleController hoodOf; public GameObject showWhenClosed; public GameObject showWhenOpen; public Collider enableWhenClosed; public Vector3 axis = Vector3.up; public float openAngle = 68f; public float speed = 200f; public AudioSource sfx; public AudioClip[] openClips; public AudioClip[] closeClips; private float cur; private int last = -1; private bool closing; private static readonly FieldInfo CarHoodOpen = AccessTools.Field(typeof(VehicleController), "carHoodOpen"); private bool IsOpen() { if ((Object)(object)hoodOf != (Object)null) { return (bool)CarHoodOpen.GetValue(hoodOf); } if ((Object)(object)trigger != (Object)null) { return trigger.boolValue; } return false; } private void Update() { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) bool flag = IsOpen(); if ((flag ? 1 : 0) != last) { bool num = last < 0; last = (flag ? 1 : 0); if ((Object)(object)showWhenClosed != (Object)null) { showWhenClosed.SetActive(!flag); } if ((Object)(object)showWhenOpen != (Object)null) { showWhenOpen.SetActive(flag); } if ((Object)(object)enableWhenClosed != (Object)null) { enableWhenClosed.enabled = !flag; } if (!num) { closing = !flag; if (flag) { Play(openClips); } } } float num2 = (flag ? openAngle : 0f); if (!Mathf.Approximately(cur, num2)) { cur = Mathf.MoveTowards(cur, num2, speed * Time.deltaTime); ((Component)this).transform.localRotation = Quaternion.AngleAxis(cur, axis); if (closing && Mathf.Approximately(cur, 0f)) { closing = false; Play(closeClips); } } } private void Play(AudioClip[] set) { if ((Object)(object)sfx != (Object)null && set != null && set.Length != 0) { sfx.PlayOneShot(set[Random.Range(0, set.Length)]); } } } public class WagonSteering : MonoBehaviour { public VehicleController vc; public Quaternion baseRot; public float sign = 1f; public float lockToLock = 720f; private void LateUpdate() { //IL_0054: 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) if (!((Object)(object)vc == (Object)null) && !((Object)(object)vc.steeringWheelAnimator == (Object)null)) { float num = (0f - (vc.steeringWheelAnimator.GetFloat("steeringWheelTurnSpeed") - 0.5f)) * lockToLock * sign; ((Component)this).transform.localRotation = baseRot * Quaternion.Euler(0f, num, 0f); } } } public class WagonTag : MonoBehaviour { public VehicleController vc; public GameObject intact; public GameObject wreck; public float lastAutoShift; public float lastLanding = -99f; public float fallPeak; public float touchdown = -99f; private bool airborne; public float wheelbase = 4f; public float sndRpm = 900f; public float sndLastSpeed; public float sndAccel; public float sndShift; public int sndGear = 1; private bool shown; private static readonly FieldInfo AnimFloat = AccessTools.Field(typeof(VehicleController), "steeringWheelAnimFloat"); public readonly float[] roll = new float[4]; public readonly float[] rollRate = new float[4]; private Vector3 lastPos; private bool hasLast; private float speedFiltered; public bool Airborne => airborne; private void FixedUpdate() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)vc == (Object)null || !((NetworkBehaviour)vc).IsOwner || (Object)(object)vc.mainRigidbody == (Object)null) { return; } if (!vc.FrontLeftWheel.isGrounded && !vc.FrontRightWheel.isGrounded && !vc.BackLeftWheel.isGrounded && !vc.BackRightWheel.isGrounded) { if (!airborne) { airborne = true; fallPeak = 0f; } fallPeak = Mathf.Max(fallPeak, 0f - vc.mainRigidbody.velocity.y); } else if (airborne) { airborne = false; touchdown = Time.time; } } private void LateUpdate() { //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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_0093: 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_0211: 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) if ((Object)(object)vc == (Object)null) { return; } float deltaTime = Time.deltaTime; if (deltaTime <= 0f) { return; } Vector3 position = ((Component)vc).transform.position; float num = ((((NetworkBehaviour)vc).IsOwner && (Object)(object)vc.mainRigidbody != (Object)null && !vc.mainRigidbody.isKinematic) ? Vector3.Dot(vc.mainRigidbody.velocity, ((Component)vc).transform.forward) : (hasLast ? Vector3.Dot((position - lastPos) / deltaTime, ((Component)vc).transform.forward) : 0f)); lastPos = position; hasLast = true; speedFiltered = Mathf.Lerp(speedFiltered, num, 1f - Mathf.Exp((0f - deltaTime) / 0.08f)); float num2 = (float)AnimFloat.GetValue(vc) * 45f; MeshRenderer[] array = (MeshRenderer[])(object)new MeshRenderer[4] { vc.leftWheelMesh, vc.rightWheelMesh, vc.backLeftWheelMesh, vc.backRightWheelMesh }; float num3 = Mathf.Max(0.05f, vc.FrontLeftWheel.radius); float num4 = speedFiltered / (MathF.PI * 2f * num3) * 60f; for (int i = 0; i < 4; i++) { if (!((Object)(object)array[i] == (Object)null)) { rollRate[i] = num4 * 6f; roll[i] = Mathf.Repeat(roll[i] + rollRate[i] * deltaTime, 360f); ((Component)array[i]).transform.localRotation = Quaternion.Euler(0f, (i < 2) ? num2 : 0f, 0f) * Quaternion.Euler(roll[i], 0f, 0f); } } } private void Update() { if (!shown && !((Object)(object)vc == (Object)null) && vc.carDestroyed) { shown = true; if ((Object)(object)intact != (Object)null) { intact.SetActive(false); } if ((Object)(object)wreck != (Object)null) { wreck.SetActive(true); } } } } [BepInPlugin("um.lcwagonr", "Wagon R", "1.4.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "um.lcwagonr"; internal static ManualLogSource Log; internal static Plugin Instance; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Instance = this; Cfg.Bind(((BaseUnityPlugin)this).Config); new Harmony("um.lcwagonr").PatchAll(); Log.LogInfo((object)"Wagon R loaded"); } } public class WagonRearDoor : MonoBehaviour { public VehicleController vc; public InteractTrigger trigger; public InteractTrigger seat; public AnimatedObjectTrigger state; public Transform[] exitPoints; private string useTip; private static readonly FieldInfo ExitMask = AccessTools.Field(typeof(VehicleController), "exitCarLayerMask"); private void Awake() { if ((Object)(object)trigger != (Object)null) { useTip = trigger.hoverTip; } } public bool Use(PlayerControllerB who) { PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val == (Object)null || (Object)(object)who != (Object)(object)val || !val.inSpecialInteractAnimation || (Object)(object)val.currentTriggerInAnimationWith == (Object)null || (Object)(object)state == (Object)null || (Object)(object)trigger == (Object)null) { return false; } if (!trigger.interactable) { return true; } if (trigger.interactCooldown) { if (trigger.currentCooldownValue >= 0f) { return true; } trigger.currentCooldownValue = trigger.cooldownTime; } bool num = (Object)(object)val.currentTriggerInAnimationWith == (Object)(object)seat && !state.boolValue; state.TriggerAnimation(val); if (num) { Exit(val); } return true; } private void Exit(PlayerControllerB me) { //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_00af: Unknown result type (might be due to invalid IL or missing references) if (exitPoints != null && exitPoints.Length != 0) { int mask = ((ExitMask != null) ? ((int)ExitMask.GetValue(vc)) : 2305); Vector3 cam = ((Component)me.gameplayCamera).transform.position; Transform val = ((IEnumerable<Transform>)exitPoints).FirstOrDefault((Func<Transform, bool>)((Transform p) => (Object)(object)p != (Object)null && !Physics.Linecast(cam, p.position, mask, (QueryTriggerInteraction)1))) ?? ((IEnumerable<Transform>)exitPoints).FirstOrDefault((Func<Transform, bool>)((Transform p) => (Object)(object)p != (Object)null)); if (!((Object)(object)val == (Object)null)) { me.TeleportPlayer(val.position, false, 0f, false, true); } } } private void Update() { PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)trigger == (Object)null) && !((Object)(object)state == (Object)null)) { string text = useTip; if (val.inSpecialInteractAnimation && (Object)(object)val.currentTriggerInAnimationWith == (Object)(object)seat) { text = (state.boolValue ? "Close door : [LMB]" : "Exit : [LMB]"); } if (trigger.hoverTip != text && !string.IsNullOrEmpty(text)) { trigger.hoverTip = text; } } } } public class WagonRearSeat : MonoBehaviour { public VehicleController vc; public InteractTrigger seat; public AnimatedObjectTrigger door; private bool was; private void Update() { if (!((Object)(object)seat == (Object)null)) { bool isPlayingSpecialAnimation = seat.isPlayingSpecialAnimation; if (isPlayingSpecialAnimation && !was && (Object)(object)door != (Object)null && door.boolValue) { door.SetBoolOnClientOnly(false); } was = isPlayingSpecialAnimation; InteractTrigger val = (((Object)(object)vc != (Object)null) ? vc.passengerSeatTrigger : null); if ((Object)(object)val != (Object)null && !val.interactable && !val.isPlayingSpecialAnimation && !vc.carDestroyed) { val.interactable = true; } } } } [HarmonyPatch(typeof(InteractTrigger), "Interact")] internal static class P_Interact_RearDoor { private static bool Prefix(InteractTrigger __instance, Transform playerTransform) { if ((Object)(object)TowManager.Instance != (Object)null && (Object)(object)TowManager.RopeFrom != (Object)null && TowManager.IsPushSpot(__instance)) { PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val != (Object)null && (Object)(object)playerTransform == (Object)(object)((Component)val).transform && TowManager.Instance.TryAttachAtPushSpot(__instance)) { return false; } } WagonHandbrake component = ((Component)__instance).GetComponent<WagonHandbrake>(); if ((Object)(object)component != (Object)null) { component.Use(((Object)(object)playerTransform != (Object)null) ? ((Component)playerTransform).GetComponent<PlayerControllerB>() : null); return false; } WagonHitch component2 = ((Component)__instance).GetComponent<WagonHitch>(); if ((Object)(object)component2 != (Object)null) { PlayerControllerB who = (((Object)(object)playerTransform != (Object)null) ? ((Component)playerTransform).GetComponent<PlayerControllerB>() : null); component2.Use(who); return false; } WagonRearDoor component3 = ((Component)__instance).GetComponent<WagonRearDoor>(); if (Cfg.Debug.Value && ((Object)(object)component3 != (Object)null || (Object)(object)((Component)__instance).GetComponent<WagonRearSeat>() != (Object)null)) { PlayerControllerB val2 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); StackFrame[] frames = new StackTrace(1, fNeedFileInfo: false).GetFrames(); string text = string.Join(" < ", from f in frames.Take(4) select f.GetMethod().DeclaringType?.Name + "." + f.GetMethod().Name); Plugin.Log.LogInfo((object)string.Format("[Interact] {0}: seated={1} inSeat={2} called from {3}", ((Object)__instance).name, (Object)(object)val2 != (Object)null && val2.inSpecialInteractAnimation, ((Object)(object)val2 != (Object)null && (Object)(object)val2.currentTriggerInAnimationWith != (Object)null) ? ((Object)val2.currentTriggerInAnimationWith).name : "-", text)); } if ((Object)(object)component3 == (Object)null) { return true; } PlayerControllerB who2 = (((Object)(object)playerTransform != (Object)null) ? ((Component)playerTransform).GetComponent<PlayerControllerB>() : null); return !component3.Use(who2); } } internal static class Registration { public static GameObject Prefab; public static bool Failed; public static VehicleController PrefabController { get { if (!((Object)(object)Prefab != (Object)null)) { return null; } return Prefab.GetComponent<VehicleController>(); } } public static void BuildAndRegister(NetworkManager nm) { if ((Object)(object)Prefab != (Object)null || Failed) { return; } try { if (!WagonAssets.Load()) { Plugin.Log.LogError((object)("Wagon R disabled: " + WagonAssets.Error)); Failed = true; return; } GameObject val = nm.NetworkConfig.Prefabs.Prefabs.Select((NetworkPrefab p) => p.Prefab).FirstOrDefault((Func<GameObject, bool>)((GameObject g) => (Object)(object)g != (Object)null && (Object)(object)g.GetComponent<VehicleController>() != (Object)null)); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Wagon R disabled: no vehicle prefab among the network prefabs"); Failed = true; return; } WagonAssets.BuildMaterials(val); WagonAudio.Load(); WagonAudio.PrepareCruiser(val.GetComponent<VehicleController>()); Prefab = VehicleBuilder.Build(val); nm.AddNetworkPrefab(Prefab); Plugin.Log.LogInfo((object)"Wagon R network prefab registered"); } catch (Exception ex) { Plugin.Log.LogError((object)("Wagon R disabled, build failed: " + ex)); Failed = true; Prefab = null; } } public static void AddToVehiclesList(StartOfRound sor) { if (!((Object)(object)Prefab == (Object)null) && !sor.VehiclesList.Contains(Prefab)) { int num = sor.VehiclesList.Length; sor.VehiclesList = sor.VehiclesList.Concat((IEnumerable<GameObject>)(object)new GameObject[1] { Prefab }).ToArray(); Plugin.Log.LogInfo((object)$"VehiclesList: Wagon R at index {num}"); AssignId(num); } } private static void AssignId(int idx) { VehicleController prefabController = PrefabController; if (!((Object)(object)prefabController == (Object)null)) { if (prefabController.vehicleID != -1 && prefabController.vehicleID != idx) { Plugin.Log.LogWarning((object)$"Wagon R id mismatch: prefab has {prefabController.vehicleID}, list index is {idx} (another mod added vehicles?)"); } prefabController.vehicleID = idx; } } public static void AddToTerminal(Terminal t) { //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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown if ((Object)(object)Prefab == (Object)null || t.buyableVehicles.Any((BuyableVehicle b) => b != null && (Object)(object)b.vehiclePrefab == (Object)(object)Prefab)) { return; } int num = t.buyableVehicles.Length; t.buyableVehicles = t.buyableVehicles.Concat((IEnumerable<BuyableVehicle>)(object)new BuyableVehicle[1] { new BuyableVehicle { vehiclePrefab = Prefab, secondaryPrefab = null, vehicleDisplayName = Cfg.DisplayName.Value, creditsWorth = Cfg.Price.Value } }).ToArray(); Plugin.Log.LogInfo((object)$"Terminal.buyableVehicles: {Cfg.DisplayName.Value} at index {num}, ${Cfg.Price.Value}"); AssignId(num); if (t.itemSalesPercentages != null && t.itemSalesPercentages.Length != 0) { int[] itemSalesPercentages = t.itemSalesPercentages; int[] array = Enumerable.Repeat(100, t.buyableItemsList.Length + t.buyableVehicles.Length).ToArray(); Array.Copy(itemSalesPercentages, array, Math.Min(itemSalesPercentages.Length, array.Length)); t.itemSalesPercentages = array; } try { AddKeywords(t, num); } catch (Exception ex) { Plugin.Log.LogError((object)("terminal keyword setup failed: " + ex)); } } private static void AddKeywords(Terminal t, int idx) { //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown TerminalNodesList terminalNodes = t.terminalNodes; TerminalKeyword val = terminalNodes.allKeywords.First((TerminalKeyword k) => k.word == "buy"); TerminalNode result = val.compatibleNouns.First((CompatibleNoun n) => (Object)(object)n.noun != (Object)null && n.noun.word == "cruiser").result; CompatibleNoun val2 = result.terminalOptions.First((CompatibleNoun o) => o.noun.word == "confirm"); CompatibleNoun val3 = result.terminalOptions.First((CompatibleNoun o) => o.noun.word == "deny"); if (!terminalNodes.allKeywords.Any((TerminalKeyword k) => k.word == "wagonr")) { TerminalKeyword val4 = ScriptableObject.CreateInstance<TerminalKeyword>(); ((Object)val4).name = "WagonR"; val4.word = "wagonr"; val4.isVerb = false; val4.defaultVerb = val; TerminalNode val5 = Object.Instantiate<TerminalNode>(val2.result); ((Object)val5).name = "buyWagonR2"; val5.buyVehicleIndex = idx; val5.itemCost = Cfg.Price.Value; val5.displayText = "Ordered the " + Cfg.DisplayName.Value + ". Your new balance is [playerCredits].\n\nIt is delivered by the dropship, like the Cruiser. Only one vehicle can be on the moon at a time. Items cannot be purchased while the vehicle is en route.\n\n"; TerminalNode val6 = Object.Instantiate<TerminalNode>(result); ((Object)val6).name = "buyWagonR"; val6.buyVehicleIndex = idx; val6.itemCost = Cfg.Price.Value; val6.displayText = "You have requested to order the " + Cfg.DisplayName.Value + ". \n[warranty] Total cost of items: [totalCost].\n\nPlease CONFIRM or DENY.\n\n"; val6.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2] { new CompatibleNoun(val2.noun, val5), val3 }; val.compatibleNouns = val.compatibleNouns.Concat((IEnumerable<CompatibleNoun>)(object)new CompatibleNoun[1] { new CompatibleNoun(val4, val6) }).ToArray(); terminalNodes.allKeywords = terminalNodes.allKeywords.Concat((IEnumerable<TerminalKeyword>)(object)new TerminalKeyword[1] { val4 }).ToArray(); Plugin.Log.LogInfo((object)"Terminal: 'buy wagonr' added"); } } } [HarmonyPatch(typeof(GameNetworkManager), "Start")] internal static class P_GameNetworkManager_Start { private static void Postfix(GameNetworkManager __instance) { NetworkManager component = ((Component)__instance).GetComponent<NetworkManager>(); if ((Object)(object)component != (Object)null) { Registration.BuildAndRegister(component); } TowManager.Create(); HandbrakeNet.Create(); try { VehicleShell.Setup(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Car] vehicle-vehicle collisions unavailable: " + ex.Message)); } } } [HarmonyPatch(typeof(StartOfRound), "Awake")] internal static class P_StartOfRound_Awake { private static void Prefix(StartOfRound __instance) { Registration.AddToVehiclesList(__instance); } } [HarmonyPatch(typeof(Terminal), "Awake")] internal static class P_Terminal_Awake { private static void Prefix(Terminal __instance) { Registration.AddToTerminal(__instance); } } public class WagonHitch : MonoBehaviour { public VehicleController vc; public InteractTrigger trigger; public Transform eye; public Vector3 AnchorLocal => ((Component)vc).transform.InverseTransformPoint(((Object)(object)eye != (Object)null) ? eye.position : ((Component)this).transform.position); public bool TiedHere(TowManager.Link l) { //IL_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references) if (l == null) { return false; } ulong networkObjectId = ((NetworkBehaviour)vc).NetworkObject.NetworkObjectId; return Vector3.Distance((l.a == networkObjectId) ? l.la : l.lb, AnchorLocal) < 0.5f; } private void Update() { if (!((Object)(object)trigger == (Object)null) && !((Object)(object)vc == (Object)null) && !((Object)(object)TowManager.Instance == (Object)null)) { string text = ((!Cfg.TowEnabled.Value) ? "Towing is switched off" : ((TowManager.Instance.LinkOf(vc) != null) ? (TiedHere(TowManager.Instance.LinkOf(vc)) ? "Release tow rope : [LMB]" : "The tow rope is on the other hitch") : (((Object)(object)TowManager.RopeFrom == (Object)(object)vc) ? "Put the tow rope away : [LMB]" : ((!((Object)(object)TowManager.RopeFrom != (Object)null)) ? "Hook up tow rope : [LMB]" : "Attach tow rope here : [LMB]")))); if (trigger.hoverTip != text) { trigger.hoverTip = text; } } } public bool Use(PlayerControllerB who) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00ea: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val == (Object)null || (Object)(object)who != (Object)(object)val || (Object)(object)TowManager.Instance == (Object)null || !Cfg.TowEnabled.Value) { return true; } TowManager instance = TowManager.Instance; TowManager.Link link = instance.LinkOf(vc); if (link != null) { if (TiedHere(link)) { instance.RequestClear(vc); } else if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip("Tow rope", "The tow rope is on the other hitch.", false, false, "LC_Tip1"); } return true; } if ((Object)(object)TowManager.RopeFrom == (Object)(object)vc) { TowManager.Drop("You put the tow rope away."); return true; } if ((Object)(object)TowManager.RopeFrom != (Object)null) { VehicleController ropeFrom = TowManager.RopeFrom; Vector3 ropeLocal = TowManager.RopeLocal; TowManager.Drop(null); instance.RequestLink(ropeFrom, ropeLocal, vc, AnchorLocal); return true; } TowManager.PickUp(vc, AnchorLocal); return true; } } public class TowManager : MonoBehaviour { public class Link { public ulong a; public ulong b; public Vector3 la; public Vector3 lb; public float len; public ConfigurableJoint joint; public LineRenderer line; public bool sim; public int mode; } public static TowManager Instance; public static VehicleController RopeFrom; public static Vector3 RopeLocal; public const float ReleaseRadius = 1f; private const string ReqName = "um.lcwagonr.tow.req"; private const string SyncName = "um.lcwagonr.tow.sync"; public readonly List<Link> links = new List<Link>(); private LineRenderer handLine; private object registeredFor; private Action<ulong> connectedHandler; private float nextTick; private float nextWarn; private Material ropeMat; private static readonly int Mask = -1; public static VehicleController TestRemote; public static bool TestClick; private static NetworkManager NM => NetworkManager.Singleton; private static bool IsServer { get { NetworkManager nM = NM; if ((Object)(object)nM != (Object)null && nM.IsListening) { return nM.IsServer; } return false; } } private static PlayerControllerB Me { get { if (!((Object)(object)GameNetworkManager.Instance != (Object)null)) { return null; } return GameNetworkManager.Instance.localPlayerController; } } public static void Create() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)Instance != (Object)null)) { GameObject val = new GameObject("WagonR.Tow"); Object.DontDestroyOnLoad((Object)val); Instance = val.AddComponent<TowManager>(); } } private static VehicleController Find(ulong id) { NetworkManager nM = NM; if ((Object)(object)nM == (Object)null || nM.SpawnManager == null || !nM.SpawnManager.SpawnedObjects.TryGetValue(id, out var value) || (Object)(object)value == (Object)null) { return null; } return ((Component)value).GetComponent<VehicleController>(); } private static ulong IdOf(VehicleController v) { return ((NetworkBehaviour)v).NetworkObject.NetworkObjectId; } public Link LinkOf(VehicleController v) { if ((Object)(object)v == (Object)null || (Object)(object)((NetworkBehaviour)v).NetworkObject == (Object)null || !((NetworkBehaviour)v).NetworkObject.IsSpawned) { return null; } ulong id = IdOf(v); return links.FirstOrDefault((Link l) => l.a == id || l.b == id); } public static void PickUp(VehicleController v, Vector3 local) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) RopeFrom = v; RopeLocal = local; Tip("Tow rope", "Look at the other vehicle and click on it. Click the hitch again to put the rope away."); } public static void Drop(string message, string why = null) { if ((Object)(object)RopeFrom != (Object)null && why != null) { Plugin.Log.LogInfo((object)("[Tow] rope dropped: " + why)); } RopeFrom = null; if (!string.IsNullOrEmpty(message)) { Tip("Tow rope", message); } } private static void Tip(string head, string body) { if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip(head, body, false, false, "LC_Tip1"); } } public static Vector3 EndAnchorLocal(VehicleController v, Vector3 near) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: 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_01bb: 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_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: 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_0177: 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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: 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_01ef: Unknown result type (might be due to invalid IL or missing references) //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_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0211: 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_00b8: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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) Vector3 forward = ((Component)v).transform.forward; float num = float.MaxValue; float num2 = float.MinValue; float num3 = float.MaxValue; int num4 = LayerMask.NameToLayer("InteractableObject"); Collider[] componentsInChildren = ((Component)v).GetComponentsInChildren<Collider>(); Vector3 val2 = default(Vector3); foreach (Collider val in componentsInChildren) { if (!val.enabled || val.isTrigger || val is WheelCollider || ((Component)val).gameObject.layer == num4 || (Object)(object)val.attachedRigidbody != (Object)(object)v.mainRigidbody) { continue; } Bounds bounds = val.bounds; for (int j = 0; j < 8; j++) { ((Vector3)(ref val2))..ctor(((j & 1) == 0) ? ((Bounds)(ref bounds)).min.x : ((Bounds)(ref bounds)).max.x, ((j & 2) == 0) ? ((Bounds)(ref bounds)).min.y : ((Bounds)(ref bounds)).max.y, ((j & 4) == 0) ? ((Bounds)(ref bounds)).min.z : ((Bounds)(ref bounds)).max.z); float num5 = Vector3.Dot(val2, forward); if (num5 < num) { num = num5; } if (num5 > num2) { num2 = num5; } if (val2.y < num3) { num3 = val2.y; } } } if (num > num2) { Bounds bounds2 = ((Collider)v.boundsCollider).bounds; float num6 = Vector3.Dot(((Bounds)(ref bounds2)).center, forward); Vector3 extents = ((Bounds)(ref bounds2)).extents; num = num6 - ((Vector3)(ref extents)).magnitude * 0.5f; float num7 = num; extents = ((Bounds)(ref bounds2)).extents; num2 = num7 + ((Vector3)(ref extents)).magnitude; num3 = ((Bounds)(ref bounds2)).min.y; } float num8 = Vector3.Dot(((Component)v).transform.position, forward); float num9 = Vector3.Dot(near, forward); float num10 = ((Mathf.Abs(num9 - num2) < Mathf.Abs(num9 - num)) ? num2 : num); Vector3 val3 = ((Component)v).transform.position + forward * (num10 - num8); val3.y = num3 + 0.55f; return ((Component)v).transform.InverseTransformPoint(val3); } public void RequestLink(VehicleController a, Vector3 la, VehicleController b, Vector3 lb) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) if ((Object)(object)a == (Object)null || (Object)(object)b == (Object)null || (Object)(object)a == (Object)(object)b) { return; } if (IsServer) { ServerLink(IdOf(a), la, IdOf(b), lb, 0uL); return; } SendToServer(delegate(FastBufferWriter w) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) byte b2 = 1; ((FastBufferWriter)(ref w)).WriteValueSafe<byte>(ref b2, default(ForPrimitives)); ulong num = IdOf(a); ((FastBufferWriter)(ref w)).WriteValueSafe<ulong>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref w)).WriteValueSafe(ref la); num = IdOf(b); ((FastBufferWriter)(ref w)).WriteValueSafe<ulong>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref w)).WriteValueSafe(ref lb); }); } public void RequestClear(VehicleController v) { if ((Object)(object)v == (Object)null) { return; } if (IsServer) { ServerClear(IdOf(v)); return; } SendToServer(delegate(FastBufferWriter w) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) byte b = 2; ((FastBufferWriter)(ref w)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); ulong num = IdOf(v); ((FastBufferWriter)(ref w)).WriteValueSafe<ulong>(ref num, default(ForPrimitives)); }); } private unsafe static void SendToServer(Action<FastBufferWriter> fill) { //IL_0027: 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) NetworkManager nM = NM; if ((Object)(object)nM == (Object)null || nM.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); try { fill(val); nM.CustomMessagingManager.SendNamedMessage("um.lcwagonr.tow.req", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private void OnRequest(ulong sender, FastBufferReader r) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0056: 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_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) if (IsServer) { byte b = default(byte); ((FastBufferReader)(ref r)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); switch (b) { case 1: { ulong aId = default(ulong); ((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref aId, default(ForPrimitives)); Vector3 la = default(Vector3); ((FastBufferReader)(ref r)).ReadValueSafe(ref la); ulong bId = default(ulong); ((FastBufferReader)(