Decompiled source of Weapon Framework v1.0.2
WeaponFramework.dll
Decompiled 12 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using InControl; using LevelEditor; using MenuOverhaul; using SFQoL; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("WeaponFramework")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+562f2a5697c435654782039a6e570db5445afc1f")] [assembly: AssemblyProduct("WeaponFramework")] [assembly: AssemblyTitle("WeaponFramework")] [assembly: AssemblyVersion("1.0.2.0")] namespace SFQoL { internal static class Ui { public static readonly Color Panel = new Color(0.176f, 0.176f, 0.176f); public static readonly Color Strip = new Color(0.147f, 0.147f, 0.147f); public static readonly Color Item = new Color(0.265f, 0.265f, 0.265f); public static readonly Color Grey = new Color(0.6f, 0.6f, 0.6f); private static TMP_FontAsset font; private static Sprite box; private static bool boxSearched; private static Camera menuCam; private static float menuCamSearchAt; public static TMP_FontAsset Font { get { if ((Object)(object)font == (Object)null) { GameManager instance = GameManager.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.winText != (Object)null) { font = ((TMP_Text)instance.winText).font; } if ((Object)(object)font == (Object)null) { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (((Object)val).name.StartsWith("Anton")) { font = val; break; } } } } return font; } } public static Sprite BoxSprite { get { if ((Object)(object)box == (Object)null && !boxSearched) { boxSearched = true; Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>(); foreach (Sprite val in array) { if (((Object)val).name == "box") { box = val; break; } } } return box; } } public static int MenuLayer { get { int num = LayerMask.NameToLayer("MENU"); if (num < 0) { return 31; } return num; } } public static void Attach(Canvas c) { //IL_00dd: 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_00aa: Invalid comparison between Unknown and I4 if ((Object)(object)c == (Object)null) { return; } if (((Object)(object)menuCam == (Object)null || !((Behaviour)menuCam).isActiveAndEnabled) && Time.unscaledTime >= menuCamSearchAt) { menuCamSearchAt = Time.unscaledTime + 1f; menuCam = null; Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if (((Object)val).name == "Camera_Pause" && (val.cullingMask & (1 << MenuLayer)) != 0) { menuCam = val; break; } } } if ((Object)(object)menuCam != (Object)null && ((Behaviour)menuCam).isActiveAndEnabled) { if ((int)c.renderMode != 1 || (Object)(object)c.worldCamera != (Object)(object)menuCam) { c.renderMode = (RenderMode)1; c.worldCamera = menuCam; c.planeDistance = 1f; } } else if ((int)c.renderMode != 0) { c.renderMode = (RenderMode)0; } } public static Canvas MakeCanvas(string name, int order) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name) { layer = MenuLayer }; Object.DontDestroyOnLoad((Object)val); Canvas val2 = val.AddComponent<Canvas>(); val2.renderMode = (RenderMode)0; val2.sortingOrder = order; Attach(val2); CanvasScaler obj = val.AddComponent<CanvasScaler>(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); obj.matchWidthOrHeight = 0.5f; return val2; } public static RectTransform Rect(Transform parent, string name) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }) { layer = ((Component)parent).gameObject.layer }; val.transform.SetParent(parent, false); RectTransform val2 = (RectTransform)val.transform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); val2.anchorMax = val3; val2.anchorMin = val3; val2.pivot = new Vector2(0.5f, 0.5f); return val2; } public static Image Box(Transform parent, string name, Color color, Vector2 pos, Vector2 size, bool rounded = false) { //IL_0008: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = Rect(parent, name); obj.anchoredPosition = pos; obj.sizeDelta = size; Image val = ((Component)obj).gameObject.AddComponent<Image>(); ((Graphic)val).color = color; ((Graphic)val).raycastTarget = false; if (rounded && (Object)(object)BoxSprite != (Object)null) { val.sprite = BoxSprite; Vector4 border = BoxSprite.border; if (((Vector4)(ref border)).sqrMagnitude > 0f) { val.type = (Type)1; } } return val; } public static void Fill(RectTransform rt, float inset) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = new Vector2(inset, inset); rt.offsetMax = new Vector2(0f - inset, 0f - inset); } public static TextMeshProUGUI Text(Transform parent, string name, string text, float size, Color color, TextAlignmentOptions align) { //IL_0032: 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) TextMeshProUGUI val = ((Component)Rect(parent, name)).gameObject.AddComponent<TextMeshProUGUI>(); if ((Object)(object)Font != (Object)null) { ((TMP_Text)val).font = Font; } ((TMP_Text)val).fontSize = size; ((Graphic)val).color = color; ((TMP_Text)val).alignment = align; ((TMP_Text)val).enableWordWrapping = false; ((TMP_Text)val).richText = true; ((Graphic)val).raycastTarget = false; ((TMP_Text)val).text = text; return val; } public static Color PlayerColor(Controller c) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c != (Object)null) { SpriteRenderer componentInChildren = ((Component)c).GetComponentInChildren<SpriteRenderer>(); SetColorWhenDamaged val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent<SetColorWhenDamaged>() : null); if ((Object)(object)val == (Object)null) { val = ((Component)c).GetComponentInChildren<SetColorWhenDamaged>(true); } if ((Object)(object)val != (Object)null && val.startColor.a > 0f) { Color startColor = val.startColor; startColor.a = 1f; return startColor; } ControllerHandler instance = ControllerHandler.Instance; if ((Object)(object)instance != (Object)null && instance.colors != null && c.playerID >= 0 && c.playerID < instance.colors.Length && (Object)(object)instance.colors[c.playerID] != (Object)null) { return instance.colors[c.playerID].color; } } return Color.white; } public static Color SlotColor(int id) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) ControllerHandler instance = ControllerHandler.Instance; if ((Object)(object)instance != (Object)null && instance.colors != null && id >= 0 && id < instance.colors.Length && (Object)(object)instance.colors[id] != (Object)null) { Color color = instance.colors[id].color; color.a = 1f; return color; } return Color.white; } public static string Hex(Color c) { //IL_0005: 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_0043: Unknown result type (might be due to invalid IL or missing references) return "#" + ((int)(Mathf.Clamp01(c.r) * 255f)).ToString("X2") + ((int)(Mathf.Clamp01(c.g) * 255f)).ToString("X2") + ((int)(Mathf.Clamp01(c.b) * 255f)).ToString("X2"); } public static string Colored(string text, Color c) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return "<color=" + Hex(c) + ">" + text + "</color>"; } public static Color WithAlpha(Color c, float a) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) c.a = a; return c; } } } namespace WeaponFramework { public enum SoundKind { Shoot, Draw, Drop } public static class Sounds { internal sealed class Pack { public AudioClip[] Shoot; public AudioClip[] Draw; public AudioClip[] Drop; public float? Volume; public float? Pitch; } private static readonly Dictionary<string, AudioClip> cache = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Pack> packs = new Dictionary<string, Pack>(); internal static string Root => Path.Combine(Path.Combine(Paths.ConfigPath, "WeaponFramework"), "Sounds"); public static AudioClip Load(string path) { if (string.IsNullOrEmpty(path)) { return null; } if (cache.TryGetValue(path, out var value) && (Object)(object)value != (Object)null) { return value; } try { value = Wav.Read(path); if ((Object)(object)value != (Object)null) { cache[path] = value; } return value; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't load sound " + path + ": " + ex.Message)); return null; } } public static AudioClip[] LoadFolder(string folder, string prefix = null) { if (string.IsNullOrEmpty(folder) || !Directory.Exists(folder)) { return null; } List<string> list = new List<string>(Directory.GetFiles(folder, "*.wav")); list.Sort(StringComparer.OrdinalIgnoreCase); List<AudioClip> list2 = new List<AudioClip>(); foreach (string item in list) { if (prefix == null || Path.GetFileName(item).StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { AudioClip val = Load(item); if ((Object)(object)val != (Object)null) { list2.Add(val); } } } if (list2.Count <= 0) { return null; } return list2.ToArray(); } public static AudioClip[] Of(VanillaWeapon weapon, SoundKind kind) { Weapon val = Core.PrefabWeapon((int)weapon); if ((Object)(object)val == (Object)null) { return null; } AudioClip[] array = kind switch { SoundKind.Draw => val.drawSounds, SoundKind.Shoot => val.clips, _ => val.dropSound, }; if (array == null || array.Length == 0) { return null; } return array; } public static void Play(Controller player, AudioClip clip, float volume = 1f) { if (!((Object)(object)player == (Object)null) && !((Object)(object)clip == (Object)null)) { AudioSource componentInChildren = ((Component)player).GetComponentInChildren<AudioSource>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.PlayOneShot(clip, volume); } } } public static void Play(Controller player, VanillaWeapon weapon, SoundKind kind = SoundKind.Shoot, float volume = 1f) { AudioClip[] array = Of(weapon, kind); if (array != null) { Play(player, array[Random.Range(0, array.Length)], volume); } } internal static void ScanPacks(IList<WeaponInfo> weapons) { packs.Clear(); cache.Clear(); try { string root = Root; Directory.CreateDirectory(root); WriteGuide(root, weapons); Dictionary<string, WeaponInfo> dictionary = new Dictionary<string, WeaponInfo>(StringComparer.OrdinalIgnoreCase); foreach (WeaponInfo weapon in weapons) { dictionary[weapon.Id] = weapon; if (!dictionary.ContainsKey(weapon.OriginalName)) { dictionary[weapon.OriginalName] = weapon; } } string[] directories = Directory.GetDirectories(root); foreach (string text in directories) { if (!dictionary.TryGetValue(Path.GetFileName(text), out var value)) { Plugin.Log.LogWarning((object)("Sound folder '" + Path.GetFileName(text) + "' doesn't match a weapon id or name (see " + Path.Combine(root, "weapons.txt") + ").")); continue; } Pack pack = new Pack { Shoot = LoadFolder(text, "shoot"), Draw = LoadFolder(text, "draw"), Drop = LoadFolder(text, "drop") }; ReadSettings(Path.Combine(text, "sound.txt"), pack); if (pack.Shoot != null || pack.Draw != null || pack.Drop != null || pack.Volume.HasValue || pack.Pitch.HasValue) { packs[value.Id] = pack; Plugin.Log.LogInfo((object)("Custom sounds for " + value.Name + ": " + Count(pack.Shoot) + " shoot, " + Count(pack.Draw) + " draw, " + Count(pack.Drop) + " drop.")); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't read the sound folders: " + ex.Message)); } } internal static Pack PackFor(WeaponInfo w) { if (w == null || !packs.TryGetValue(w.Id, out var value)) { return null; } return value; } private static int Count(AudioClip[] a) { if (a == null) { return 0; } return a.Length; } private static void ReadSettings(string file, Pack p) { if (!File.Exists(file)) { return; } string[] array = File.ReadAllLines(file); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); int num = text.IndexOf('='); if (num <= 0 || text.StartsWith("#")) { continue; } string text2 = text.Substring(0, num).Trim().ToLowerInvariant(); if (float.TryParse(text.Substring(num + 1).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { result = Mathf.Clamp(result, 0f, 4f); if (text2 == "volume") { p.Volume = result; } else if (text2 == "pitch") { p.Pitch = result; } } } } private static void WriteGuide(string root, IList<WeaponInfo> weapons) { List<string> list = new List<string> { "Custom weapon sounds (Weapon Framework)", "", "Make a folder here named after a weapon's id or name (both listed below), e.g.", " Sounds\\vanilla.ak47\\ or Sounds\\AK 47\\", "and put .wav files in it:", " shoot*.wav played when it fires or swings (one picked at random)", " draw*.wav played when it is picked up", " drop*.wav played when it is dropped", " sound.txt optional, lines like: volume = 0.8 pitch = 1.1", "Anything you leave out keeps the weapon's own sound. Changes load the next time the lobby", "loads (start the game, or finish a match). This file is rewritten every time.", "", "id = name" }; foreach (WeaponInfo weapon in weapons) { list.Add(weapon.Id + " = " + weapon.OriginalName); } File.WriteAllText(Path.Combine(root, "weapons.txt"), string.Join(Environment.NewLine, list.ToArray())); } } internal static class Wav { public static AudioClip Read(string path) { byte[] array = File.ReadAllBytes(path); if (array.Length < 44 || Ascii(array, 0) != "RIFF" || Ascii(array, 8) != "WAVE") { throw new Exception("not a WAV file"); } int num = 12; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = -1; int num7 = 0; while (num + 8 <= array.Length) { string text = Ascii(array, num); int num8 = BitConverter.ToInt32(array, num + 4); int num9 = num + 8; if (text == "fmt ") { num2 = BitConverter.ToUInt16(array, num9); num3 = BitConverter.ToUInt16(array, num9 + 2); num4 = BitConverter.ToInt32(array, num9 + 4); num5 = BitConverter.ToUInt16(array, num9 + 14); if (num2 == 65534 && num8 >= 26) { num2 = BitConverter.ToUInt16(array, num9 + 24); } } else if (text == "data") { num6 = num9; num7 = Math.Min(num8, array.Length - num9); break; } num = num9 + num8 + (num8 & 1); } if (num6 < 0 || num3 < 1 || num4 < 1) { throw new Exception("no audio data"); } if (num2 != 1 && num2 != 3) { throw new Exception("only PCM or float WAV files are supported (format " + num2 + ")"); } int num10 = num5 / 8; if (num10 < 1 || (num2 == 3 && num5 != 32)) { throw new Exception(num5 + "-bit audio isn't supported"); } int num11 = num7 / num10; float[] array2 = new float[num11]; for (int i = 0; i < num11; i++) { int num12 = num6 + i * num10; switch ((num2 != 3) ? num5 : 0) { case 0: array2[i] = BitConverter.ToSingle(array, num12); break; case 8: array2[i] = (float)(array[num12] - 128) / 128f; break; case 16: array2[i] = (float)BitConverter.ToInt16(array, num12) / 32768f; break; case 24: array2[i] = (float)(((array[num12] << 8) | (array[num12 + 1] << 16) | (array[num12 + 2] << 24)) >> 8) / 8388608f; break; case 32: array2[i] = (float)BitConverter.ToInt32(array, num12) / 2.1474836E+09f; break; default: throw new Exception(num5 + "-bit audio isn't supported"); } } AudioClip obj = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num11 / num3, num3, num4, false); obj.SetData(array2, 0); return obj; } private static string Ascii(byte[] b, int at) { if (at + 4 > b.Length) { return ""; } return Encoding.ASCII.GetString(b, at, 4); } } public static class SpawnWeights { public const int MaxTickets = 1000; public static readonly int[] Steps = new int[19] { 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 60, 80, 100 }; private static Func<WeaponInfo, int> getter; private static Action<WeaponInfo, int> setter; private static readonly HashSet<string> failed = new HashSet<string>(); public static bool HasProvider => getter != null; public static string ProviderName { get; private set; } public static bool SetProvider(string modName, Func<WeaponInfo, int> get, Action<WeaponInfo, int> set) { if (get == null) { throw new ArgumentNullException("get"); } if (getter != null) { Plugin.Log.LogWarning((object)(modName + " tried to provide spawn weights, but " + ProviderName + " already does. Only one mod may change spawn odds.")); return false; } getter = get; setter = set; ProviderName = (string.IsNullOrEmpty(modName) ? "?" : modName); Plugin.Log.LogInfo((object)("Spawn weights come from " + ProviderName + ".")); Core.MenuChanged(); Refresh(); return true; } public static void Refresh() { Core.RebuildBag(); } public static int Override(WeaponInfo w) { if (getter == null || w == null) { return -1; } try { int num = getter(w); return (num < 0) ? (-1) : Math.Min(num, 1000); } catch (Exception ex) { if (failed.Add(w.Id)) { Plugin.Log.LogError((object)(ProviderName + " failed to give a spawn weight for " + w.Id + " (its default is used; further errors for it aren't logged): " + ex.Message)); } return -1; } } internal static void Set(WeaponInfo w, int tickets) { if (setter != null && w != null) { try { setter(w, tickets); } catch (Exception ex) { Plugin.Log.LogError((object)(ProviderName + " failed to store a spawn weight for " + w.Id + ": " + ex.Message)); } Refresh(); } } internal static int Step(int current, int dir) { if (dir > 0) { int[] steps = Steps; foreach (int num in steps) { if (num > current) { return num; } } if (Steps[Steps.Length - 1] <= current) { return current; } return Steps[Steps.Length - 1]; } for (int num2 = Steps.Length - 1; num2 >= 0; num2--) { if (Steps[num2] < current) { return Steps[num2]; } } return 0; } } public enum VanillaWeapon { Pistol, AK47, Sword, GrenadeLauncher, BlinkDagger, Sniper, Revolver, IceGun, Shield, Fan, MilitaryShotgun, BallLauncher, Thruster, Bow, Laser, Lightsaber, Uzi, OldMinigun, TinyMinigun, Minigun, Bouncer, TimeBubble, RPG, FlameThrower, SnakeGun, SnakeGrenade, SnakeLauncher, GlueGun, LaserPlanter, HolySword, GodMinigun, GodPistol, M1, SnakeMinigun, LavaWhip, LavaStream, LavaSpray, SnakeShotgun, LavaSpikeBall, LavaBeam, LavaSpikeGun, BlackHole, HalloweenShotgun, HalloweenSaw, HalloweenLaser, HalloweenAK, HalloweenRing, HalloweenPew, HalloweenPewPew, HalloweenBlocker, HalloweenPew2, HalloweenRevolver, HalloweenBlocker2, HalloweenPistol, HalloweenWaves, HalloweenInverse, HalloweenPewRainbow, HalloweenSniper, HalloweenBouncePew, PumpkinGun, M16, Deagle, SawedOff, Spear, FlyingSnake } public abstract class WeaponBehaviour : MonoBehaviour { private Weapon weapon; private Controller owner; private Fighting fighting; private Rigidbody torso; private Transform aim; protected bool CountsAttackAsShot = true; public WeaponInfo Info { get; internal set; } public Weapon Weapon { get { if ((Object)(object)weapon == (Object)null) { weapon = ((Component)this).GetComponent<Weapon>(); } return weapon; } } public Controller Owner { get { if ((Object)(object)owner == (Object)null) { owner = ((Component)((Component)this).transform.root).GetComponent<Controller>(); } return owner; } } public Fighting Fighting { get { if ((Object)(object)fighting == (Object)null) { fighting = ((Component)((Component)this).transform.root).GetComponent<Fighting>(); } return fighting; } } public Rigidbody Torso { get { if ((Object)(object)torso == (Object)null) { Torso componentInChildren = ((Component)((Component)this).transform.root).GetComponentInChildren<Torso>(); if ((Object)(object)componentInChildren != (Object)null) { torso = ((Component)componentInChildren).GetComponent<Rigidbody>(); } } return torso; } } public Vector3 Aim { get { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_006e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)aim == (Object)null) { AimTarget componentInChildren = ((Component)((Component)this).transform.root).GetComponentInChildren<AimTarget>(); if ((Object)(object)componentInChildren != (Object)null) { aim = ((Component)componentInChildren).transform; } } if ((Object)(object)aim == (Object)null) { return Vector3.forward; } Vector3 forward = aim.forward; forward.x = 0f; if (!(((Vector3)(ref forward)).sqrMagnitude > 1E-06f)) { return Vector3.forward; } return ((Vector3)(ref forward)).normalized; } } public Vector3 Muzzle { get { //IL_0039: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_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) Shoot componentInChildren = ((Component)this).GetComponentInChildren<Shoot>(true); Vector3 result = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).transform.position : (((Component)this).transform.position + Aim * 0.5f)); result.x = 0f; return result; } } public Transform MuzzleTransform { get { Shoot componentInChildren = ((Component)this).GetComponentInChildren<Shoot>(true); if (!((Object)(object)componentInChildren != (Object)null)) { return ((Component)this).transform; } return ((Component)componentInChildren).transform; } } public float Charge { get; internal set; } public int AmmoLeft { get { if (!((Object)(object)Fighting != (Object)null)) { return 0; } return Access.BulletsLeft.Invoke(Fighting); } set { if ((Object)(object)Fighting != (Object)null) { Access.BulletsLeft.Invoke(Fighting) = value; } } } public bool IsHeld { get { if ((Object)(object)Fighting != (Object)null) { return (Object)(object)Fighting.weapon == (Object)(object)Weapon; } return false; } } internal bool CountsAsShot => CountsAttackAsShot; public void SetVisible(bool on) { Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!(val is ParticleSystemRenderer)) { val.enabled = on; } } Collider[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = on; } } internal void UseAmmoInternal(int shots) { UseAmmo(shots); } public virtual void OnEquip() { } public virtual void OnUnequip() { } public virtual bool OnAttack() { return false; } public virtual void AfterAttack() { } public virtual void OnAttackHeld(float seconds) { } public virtual void OnAttackReleased(float heldFor) { } public virtual void OnAltPressed() { } public virtual void OnAltHeld(float seconds) { } public virtual void OnAltReleased(float heldFor) { } public virtual void OnShot(GameObject projectile) { } public virtual float ModifyDamage(Controller victim, float damage) { return damage; } public virtual void OnDamageDealt(Controller victim, float damage, bool killed) { } protected void UseAmmo(int shots = 1) { Fighting val = Fighting; if (!((Object)(object)val == (Object)null) && IsHeld) { int num = Access.BulletsLeft.Invoke(val) - shots; Access.BulletsLeft.Invoke(val) = num; if (num <= 0) { val.ThrowWeapon(true); } } } protected void Drop() { if (IsHeld) { Fighting.ThrowWeapon(true); } } protected void PlayShootSound() { Weapon val = Weapon; if ((Object)(object)val != (Object)null && val.clips != null && val.clips.Length != 0) { Sounds.Play(Owner, val.clips[Random.Range(0, val.clips.Length)], val.volumeFix); } } protected void ResetCooldown() { if ((Object)(object)Fighting != (Object)null) { Fighting.counter = 0f; } } } public sealed class WeaponCategory { public const string Pistols = "pistols"; public const string Rifles = "rifles"; public const string Shotguns = "shotguns"; public const string Heavy = "heavy"; public const string Explosives = "explosives"; public const string Melee = "melee"; public const string Control = "control"; public const string Gadgets = "gadgets"; public const string Party = "party"; public const string Lava = "lava"; public const string Snake = "snake"; public const string Godlike = "godlike"; internal int Added; public string Id { get; private set; } public string Name { get; internal set; } public string Description { get; internal set; } public int Order { get; internal set; } public string Mod { get; internal set; } internal WeaponCategory(string id, string name, int order, string description, string mod) { Id = id; Name = name; Order = order; Description = description; Mod = mod; } public override string ToString() { return Name + " (" + Id + ")"; } } public sealed class WeaponDefinition { public string Id; public string Name; public string Category = "gadgets"; public string Description; public string Mod; public VanillaWeapon Base; public VanillaWeapon? Existing; public int Rarity = 5; public bool OnByDefault = true; public int Ammo; public float? Cooldown; public float ChargeTime; public float ChargePower = 1f; public Type Behaviour; public WeaponModel Model; public Color? Tint; public bool GiftBox; public VanillaWeapon? SoundsFrom; public AudioClip[] ShootSounds; public AudioClip[] DrawSounds; public AudioClip[] DropSounds; public float? Volume; public float? Pitch; public Action<Weapon> Configure; public Action<GameObject> ConfigureModel; public Action<GameObject> ConfigurePickup; internal int BaseIndex => (int)(Existing ?? Base); public WeaponDefinition() { } public WeaponDefinition(string id, string name, VanillaWeapon baseWeapon) { Id = id; Name = name; Base = baseWeapon; } public static WeaponDefinition FromExisting(string id, string name, VanillaWeapon weapon) { return new WeaponDefinition { Id = id, Name = name, Existing = weapon, Base = weapon }; } } public sealed class WeaponInfo { internal bool OnByDefault; internal int VanillaRow = -1; internal int VanillaTickets; internal GameObject Pickup; public string Id { get; private set; } public string Name { get; internal set; } public string OriginalName { get; private set; } public string Category { get; internal set; } public string Description { get; internal set; } public string Mod { get; internal set; } public int Index { get; internal set; } public int DefaultTickets { get; internal set; } public bool IsVanilla { get; private set; } public string MenuLabel { get; private set; } public WeaponDefinition Definition { get; private set; } public GameObject PickupPrefab => Pickup; public bool AllowedOnline => IsVanilla; public bool Enabled => Core.IsEnabled(this); public int Tickets => Core.TicketsFor(this, online: false); public float Chance => Core.ChanceOf(this); internal WeaponInfo(string id, string name, string category, bool vanilla, string menuLabel, WeaponDefinition def) { Id = id; Name = name; OriginalName = name; Category = category; IsVanilla = vanilla; MenuLabel = menuLabel; Definition = def; Index = -1; } public override string ToString() { return Name + " (" + Id + ", #" + Index + ")"; } } public static class WeaponModels { public static void Build(Transform parent, WeaponModel model) { if ((Object)(object)parent != (Object)null && model != null) { ModelBuilder.BuildVisual(parent, model); } } } public static class GameMaterials { public const string Weapon = "WeaponMaterial"; public const string Blink = "Blink"; public const string Explosive = "Explosive"; public const string Gray = "gray"; } public sealed class WeaponModel { internal sealed class Part { public PrimitiveType Shape; public Vector3 Position; public Vector3 Size; public float Pitch; public Color? Color; public float Glow; public bool Solid; public string Material; public bool FaceCamera; public string Name; } internal readonly List<Part> Parts = new List<Part>(); public Vector3 Grip = Vector3.zero; public Vector3? OffHandGrip; public Vector3 Muzzle = new Vector3(0f, 0.08f, 0.35f); public Vector3 PickupCollider = Vector3.zero; public WeaponModel Paint(string gameMaterial) { if (Parts.Count > 0) { Parts[Parts.Count - 1].Material = gameMaterial; } return this; } public WeaponModel Named(string name) { if (Parts.Count > 0) { Parts[Parts.Count - 1].Name = name; } return this; } public WeaponModel Box(Vector3 center, Vector3 size, float pitch = 0f, Color? color = null, bool solid = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Parts.Add(new Part { Shape = (PrimitiveType)3, Position = center, Size = size, Pitch = pitch, Color = color, Solid = solid }); return this; } public WeaponModel Cylinder(Vector3 center, float diameter, float length, float pitch = 0f, Color? color = null, bool solid = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Parts.Add(new Part { Shape = (PrimitiveType)2, Position = center, Size = new Vector3(diameter, diameter, length), Pitch = pitch, Color = color, Solid = solid }); return this; } public WeaponModel Disc(Vector3 center, float diameter, float thickness = 0.06f, Color? color = null, bool solid = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Parts.Add(new Part { Shape = (PrimitiveType)2, Position = center, Size = new Vector3(diameter, diameter, thickness), Pitch = 0f, Color = color, Solid = solid, FaceCamera = true }); return this; } public WeaponModel Ball(Vector3 center, float diameter, Color? color = null, bool solid = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Parts.Add(new Part { Shape = (PrimitiveType)0, Position = center, Size = Vector3.one * diameter, Color = color, Solid = solid }); return this; } public WeaponModel Glow(Vector3 center, Vector3 size, Color color, float brightness = 2f, float pitch = 0f, bool solid = false) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Parts.Add(new Part { Shape = (PrimitiveType)3, Position = center, Size = size, Pitch = pitch, Color = color, Glow = brightness, Solid = solid }); return this; } internal Bounds LocalBounds() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_00b3: 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_00c2: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if (Parts.Count == 0) { return new Bounds(Vector3.zero, Vector3.one * 0.3f); } Bounds result = default(Bounds); ((Bounds)(ref result))..ctor(Parts[0].Position, Vector3.zero); Vector3 val3 = default(Vector3); foreach (Part part in Parts) { Quaternion val = Quaternion.Euler(part.Pitch, 0f, 0f); Vector3 val2 = (Vector3)(part.FaceCamera ? new Vector3(part.Size.z, part.Size.x, part.Size.x) : part.Size) * 0.5f; for (int i = 0; i < 8; i++) { ((Vector3)(ref val3))..ctor(((i & 1) == 0) ? (0f - val2.x) : val2.x, ((i & 2) == 0) ? (0f - val2.y) : val2.y, ((i & 4) == 0) ? (0f - val2.z) : val2.z); ((Bounds)(ref result)).Encapsulate(part.Position + val * val3); } } return result; } } public static class WeaponRegistry { public static bool IsReady => Core.Built; public static IList<WeaponInfo> All => Core.Weapons.AsReadOnly(); public static IList<WeaponCategory> Categories => Core.SortedCategories().AsReadOnly(); public static event Action Ready; public static event Action<Controller> PlayerArmed; [MethodImpl(MethodImplOptions.NoInlining)] public static WeaponCategory AddCategory(string id, string name, int order = 0, string description = null) { return Core.AddCategory(id, name, order, description, ModOf(Assembly.GetCallingAssembly())); } [MethodImpl(MethodImplOptions.NoInlining)] public static WeaponInfo Add(WeaponDefinition definition) { if (definition == null) { throw new ArgumentNullException("definition"); } if (string.IsNullOrEmpty(definition.Mod)) { definition.Mod = ModOf(Assembly.GetCallingAssembly()); } return Core.AddWeapon(definition); } public static WeaponInfo Get(string id) { return Core.Find(id); } public static WeaponCategory GetCategory(string id) { return Core.FindCategory(id); } public static WeaponInfo GetByIndex(int index) { return Core.ByIndex(index); } public static WeaponInfo Of(Weapon weapon) { return Core.Of(weapon); } public static WeaponInfo Held(Controller player) { if ((Object)(object)player == (Object)null) { return null; } Fighting component = ((Component)player).GetComponent<Fighting>(); if (!((Object)(object)component != (Object)null)) { return null; } return Core.Of(component.weapon); } public static void SetName(string id, string name) { if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(name)) { Core.SetName(id, name); } } public static void SetCategoryName(string id, string name) { WeaponCategory weaponCategory = Core.FindCategory(id); if (weaponCategory != null && !string.IsNullOrEmpty(name)) { weaponCategory.Name = name; Core.MenuChanged(); } } public static void SetCategory(string id, string category) { if (!string.IsNullOrEmpty(id) && Core.FindCategory(category) != null) { Core.SetCategory(id, category); } } public static void SetDefaultTickets(string id, int tickets) { if (!string.IsNullOrEmpty(id) && tickets >= 0) { Core.SetDefaultTickets(id, Math.Min(tickets, 1000)); } } public static bool IsEnabled(string id) { WeaponInfo weaponInfo = Core.Find(id); if (weaponInfo != null) { return Core.IsEnabled(weaponInfo); } return false; } public static void SetEnabled(string id, bool on) { WeaponInfo weaponInfo = Core.Find(id); if (weaponInfo != null) { Settings.SetWeapon(weaponInfo.Id, on); Core.SyncGameLists(); Core.MenuChanged(); SpawnWeights.Refresh(); } } internal static void RaiseReady() { if (WeaponRegistry.Ready == null) { return; } Delegate[] invocationList = WeaponRegistry.Ready.GetInvocationList(); foreach (Delegate obj in invocationList) { try { ((Action)obj)(); } catch (Exception ex) { Plugin.Log.LogError((object)("A WeaponRegistry.Ready handler failed: " + ex)); } } } internal static void RaisePlayerArmed(Controller c) { if (WeaponRegistry.PlayerArmed == null) { return; } Delegate[] invocationList = WeaponRegistry.PlayerArmed.GetInvocationList(); foreach (Delegate obj in invocationList) { try { ((Action<Controller>)obj)(c); } catch (Exception ex) { Plugin.Log.LogError((object)("A WeaponRegistry.PlayerArmed handler failed: " + ex)); } } } internal static string ModOf(Assembly asm) { if ((object)asm == typeof(WeaponRegistry).Assembly) { return "Weapon Framework"; } try { string location = asm.Location; foreach (PluginInfo value in Chainloader.PluginInfos.Values) { if ((Object)(object)value.Instance != (Object)null && (object)((object)value.Instance).GetType().Assembly == asm) { return value.Metadata.Name; } if (!string.IsNullOrEmpty(location) && string.Equals(value.Location, location, StringComparison.OrdinalIgnoreCase)) { return value.Metadata.Name; } } } catch { } if ((object)asm == null) { return "?"; } return asm.GetName().Name; } } internal static class Access { public static readonly FieldRef<Fighting, int> BulletsLeft = AccessTools.FieldRefAccess<Fighting, int>("bulletsLeft"); public static readonly FieldRef<Fighting, bool> JustAttacked = AccessTools.FieldRefAccess<Fighting, bool>("mJustAttacked"); public static readonly FieldRef<Fighting, BlockHandler> FightingBlock = AccessTools.FieldRefAccess<Fighting, BlockHandler>("blockHandler"); public static readonly FieldRef<Controller, CharacterActions> Actions = AccessTools.FieldRefAccess<Controller, CharacterActions>("mPlayerActions"); public static readonly FieldRef<Controller, bool> HasControl = AccessTools.FieldRefAccess<Controller, bool>("mHasControl"); public static readonly FieldRef<Controller, CharacterInformation> Info = AccessTools.FieldRefAccess<Controller, CharacterInformation>("info"); public static readonly FieldRef<Controller, Fighting> ControllerFighting = AccessTools.FieldRefAccess<Controller, Fighting>("fighting"); public static readonly FieldRef<WeaponSelectionHandler, List<byte>> Bag = AccessTools.FieldRefAccess<WeaponSelectionHandler, List<byte>>("m_WeaponRaritiesArray"); public static readonly FieldRef<WeaponSelectionHandler, GameObject[]> WeaponObjects = AccessTools.FieldRefAccess<WeaponSelectionHandler, GameObject[]>("m_WeaponObjects"); public static readonly FieldRef<WeaponSelectionHandler, GameObject> PlayerObject = AccessTools.FieldRefAccess<WeaponSelectionHandler, GameObject>("m_PlayerObject"); public static readonly FieldRef<WeaponSelectionHandler, List<SingleWeaponUI>> MenuWeapons = AccessTools.FieldRefAccess<WeaponSelectionHandler, List<SingleWeaponUI>>("m_Weapons"); public static readonly FieldRef<WeaponSelectionHandler, List<WeaponCategoryUI>> MenuCategories = AccessTools.FieldRefAccess<WeaponSelectionHandler, List<WeaponCategoryUI>>("m_Categories"); public static readonly FieldRef<WeaponSelectionHandler, int> NumberOfWeapons = AccessTools.FieldRefAccess<WeaponSelectionHandler, int>("m_NumberOfWeapons"); public static readonly FieldRef<WeaponSelectionHandler, int> NumberOfCategories = AccessTools.FieldRefAccess<WeaponSelectionHandler, int>("m_NumberOfCategories"); public static readonly FieldRef<PauseManager, CodeStateAnimation> WeaponAnim = AccessTools.FieldRefAccess<PauseManager, CodeStateAnimation>("weaponAnim"); } internal static class Catalog { internal struct Entry { public string Id; public string Name; public string Category; public Entry(string id, string name, string category) { Id = id; Name = name; Category = category; } } private static readonly Dictionary<int, Entry> byIndex = new Dictionary<int, Entry> { { 0, new Entry("vanilla.pistol", null, "pistols") }, { 6, new Entry("vanilla.revolver", null, "pistols") }, { 61, new Entry("vanilla.deagle", null, "pistols") }, { 16, new Entry("vanilla.uzi", null, "pistols") }, { 31, new Entry("vanilla.godpistol", null, "godlike") }, { 1, new Entry("vanilla.ak47", null, "rifles") }, { 60, new Entry("vanilla.m16", null, "rifles") }, { 32, new Entry("vanilla.m1", null, "rifles") }, { 5, new Entry("vanilla.sniper", null, "rifles") }, { 62, new Entry("vanilla.sawedoff", null, "shotguns") }, { 10, new Entry("vanilla.militaryshotgun", null, "shotguns") }, { 20, new Entry("vanilla.bouncer", null, "rifles") }, { 3, new Entry("vanilla.grenadelauncher", null, "explosives") }, { 12, new Entry("vanilla.thruster", null, "explosives") }, { 22, new Entry("vanilla.rpg", null, "explosives") }, { 24, new Entry("vanilla.snakegun", "SNAKE GUN", "snake") }, { 37, new Entry("vanilla.snakeshotgun", "SNAKE SHOTGUN", "snake") }, { 25, new Entry("vanilla.snakegrenade", "SNAKE GRENADE", "snake") }, { 26, new Entry("vanilla.snakelauncher", "SNAKE LAUNCHER", "snake") }, { 33, new Entry("vanilla.snakeminigun", null, "snake") }, { 64, new Entry("vanilla.flyingsnake", null, "snake") }, { 38, new Entry("vanilla.spikeball", null, "lava") }, { 39, new Entry("vanilla.beam", null, "lava") }, { 35, new Entry("vanilla.stream", null, "lava") }, { 36, new Entry("vanilla.spray", null, "lava") }, { 40, new Entry("vanilla.spikegun", null, "lava") }, { 2, new Entry("vanilla.sword", null, "melee") }, { 4, new Entry("vanilla.blinkdagger", null, "melee") }, { 63, new Entry("vanilla.spear", null, "melee") }, { 21, new Entry("vanilla.timebubble", null, "control") }, { 14, new Entry("vanilla.laser", null, "heavy") }, { 7, new Entry("vanilla.icegun", null, "control") }, { 41, new Entry("vanilla.blackhole", null, "control") }, { 27, new Entry("vanilla.gluegun", null, "control") }, { 19, new Entry("vanilla.minigun", null, "heavy") }, { 23, new Entry("vanilla.flamethrower", null, "heavy") } }; private static readonly Dictionary<string, string> byRow = new Dictionary<string, string> { { "pistols", "pistols" }, { "rifles", "rifles" }, { "explosives", "explosives" }, { "snake", "snake" }, { "lava", "lava" }, { "melee", "melee" }, { "other", "control" } }; public static Entry For(int index, string label, string row) { if (byIndex.TryGetValue(index, out var value)) { return value; } if (row == null || !byRow.TryGetValue(row.ToLowerInvariant(), out var value2)) { value2 = "gadgets"; } return new Entry("vanilla." + Squash(label), null, value2); } public static void AddBuiltInCategories() { Core.AddCategory("pistols", "PISTOLS", 100, "Sidearms. Quick, light and common.", "Stick Fight"); Core.AddCategory("rifles", "RIFLES", 200, "Long guns and precision.", "Stick Fight"); Core.AddCategory("shotguns", "SHOTGUNS", 300, "Close range, big push.", "Stick Fight"); Core.AddCategory("heavy", "HEAVY", 400, "Sustained fire and beams.", "Stick Fight"); Core.AddCategory("explosives", "EXPLOSIVES", 500, "Area damage.", "Stick Fight"); Core.AddCategory("melee", "MELEE", 600, "Blades and close fights.", "Stick Fight"); Core.AddCategory("control", "CONTROL", 700, "Freeze, stick, pull and push.", "Stick Fight"); Core.AddCategory("gadgets", "GADGETS", 800, "Mobility, traps and tools.", "Stick Fight"); Core.AddCategory("party", "PARTY", 900, "Silly ones.", "Stick Fight"); Core.AddCategory("lava", "LAVA", 1000, "The lava set.", "Stick Fight"); Core.AddCategory("snake", "SNAKE", 1100, "The snake set.", "Stick Fight"); Core.AddCategory("godlike", "GODLIKE", 1200, "Overpowered. One press turns them all off.", "Stick Fight"); } public static string Squash(string s) { if (s != null) { return s.Trim().Replace(" ", string.Empty).ToLowerInvariant(); } return ""; } } internal static class Core { private static readonly Dictionary<string, WeaponCategory> categories; private static readonly List<WeaponInfo> modded; internal static readonly List<WeaponInfo> Weapons; private static WeaponInfo[] byIndex; private static readonly Dictionary<string, string> renames; private static readonly Dictionary<string, string> moves; private static readonly Dictionary<string, int> tickets; private static WeaponSelectionHandler handler; private static Transform prefabWeapons; private static GameObject templates; private static GameObject basePickup; private static bool bagOnline; private static int categoriesAdded; internal static bool Built; internal static int VanillaCount; private static readonly Dictionary<string, GameObject> pickups; internal static WeaponSelectionHandler Handler => handler; internal static bool BagIsStale { get { if (Built) { return bagOnline != MatchmakingHandler.IsNetworkMatch; } return false; } } static Core() { categories = new Dictionary<string, WeaponCategory>(StringComparer.OrdinalIgnoreCase); modded = new List<WeaponInfo>(); Weapons = new List<WeaponInfo>(); byIndex = new WeaponInfo[0]; renames = new Dictionary<string, string>(); moves = new Dictionary<string, string>(); tickets = new Dictionary<string, int>(); pickups = new Dictionary<string, GameObject>(); Catalog.AddBuiltInCategories(); } internal static WeaponCategory AddCategory(string id, string name, int order, string description, string mod) { if (string.IsNullOrEmpty(id)) { throw new ArgumentException("A category needs an id."); } if (categories.TryGetValue(id, out var value)) { return value; } value = new WeaponCategory(id, string.IsNullOrEmpty(name) ? id.ToUpperInvariant() : name, (order > 0) ? order : 2000, description, mod); value.Added = categoriesAdded++; categories[id] = value; MenuChanged(); return value; } internal static WeaponInfo AddWeapon(WeaponDefinition d) { if (string.IsNullOrEmpty(d.Id)) { throw new ArgumentException("A weapon needs an id."); } if (string.IsNullOrEmpty(d.Name)) { d.Name = d.Id.ToUpperInvariant(); } foreach (WeaponInfo item in modded) { if (string.Equals(item.Id, d.Id, StringComparison.OrdinalIgnoreCase)) { Plugin.Log.LogWarning((object)("Weapon id '" + d.Id + "' was added twice; the second one is ignored.")); return item; } } if ((object)d.Behaviour != null && !typeof(WeaponBehaviour).IsAssignableFrom(d.Behaviour)) { Plugin.Log.LogError((object)(d.Id + ": Behaviour " + d.Behaviour.Name + " isn't a WeaponBehaviour; ignored.")); d.Behaviour = null; } WeaponInfo weaponInfo = new WeaponInfo(d.Id, d.Name, d.Category, vanilla: false, null, d) { Description = d.Description, Mod = d.Mod, DefaultTickets = Mathf.Clamp(d.Rarity, 0, 1000), OnByDefault = d.OnByDefault }; modded.Add(weaponInfo); if (Built) { Plugin.Log.LogWarning((object)(d.Id + " was added after the weapon list was built; it appears after the lobby reloads.")); } return weaponInfo; } internal static void SetName(string id, string name) { renames[id] = name; WeaponInfo weaponInfo = Find(id); if (weaponInfo != null) { weaponInfo.Name = name; } MenuChanged(); } internal static void SetCategory(string id, string cat) { WeaponCategory weaponCategory = FindCategory(cat); if (weaponCategory != null) { cat = weaponCategory.Id; } moves[id] = cat; WeaponInfo weaponInfo = Find(id); if (weaponInfo != null) { weaponInfo.Category = cat; } MenuChanged(); RebuildBag(); } internal static void SetDefaultTickets(string id, int n) { tickets[id] = n; WeaponInfo weaponInfo = Find(id); if (weaponInfo != null) { weaponInfo.DefaultTickets = n; } MenuChanged(); RebuildBag(); } internal static WeaponInfo Find(string id) { if (id == null) { return null; } foreach (WeaponInfo weapon in Weapons) { if (string.Equals(weapon.Id, id, StringComparison.OrdinalIgnoreCase)) { return weapon; } } foreach (WeaponInfo item in modded) { if (string.Equals(item.Id, id, StringComparison.OrdinalIgnoreCase)) { return item; } } return null; } internal static WeaponCategory FindCategory(string id) { if (id == null || !categories.TryGetValue(id, out var value)) { return null; } return value; } internal static WeaponInfo ByIndex(int i) { if (i < 0 || i >= byIndex.Length) { return null; } return byIndex[i]; } internal static WeaponInfo Of(Weapon w) { if ((Object)(object)w == (Object)null || (Object)(object)((Component)w).transform.parent == (Object)null || (Object)(object)((Component)((Component)w).transform.parent).GetComponent<Weapons>() == (Object)null) { return null; } return ByIndex(((Component)w).transform.GetSiblingIndex()); } internal static Weapon PrefabWeapon(int index) { Transform val = PrefabHolder(); if (!((Object)(object)val != (Object)null) || index < 0 || index >= val.childCount) { return null; } return ((Component)val.GetChild(index)).GetComponent<Weapon>(); } private static Transform PrefabHolder() { if ((Object)(object)prefabWeapons == (Object)null && (Object)(object)ResourcesManager.Instance != (Object)null && (Object)(object)ResourcesManager.Instance.CharacterObject != (Object)null) { prefabWeapons = ResourcesManager.Instance.CharacterObject.transform.Find("Weapons"); } return prefabWeapons; } internal static List<WeaponCategory> SortedCategories() { List<WeaponCategory> list = new List<WeaponCategory>(categories.Values); list.Sort((WeaponCategory a, WeaponCategory b) => (a.Order == b.Order) ? a.Added.CompareTo(b.Added) : a.Order.CompareTo(b.Order)); return list; } internal static List<WeaponInfo> InCategory(string id) { List<WeaponInfo> list = new List<WeaponInfo>(); foreach (WeaponInfo weapon in Weapons) { if (string.Equals(weapon.Category, id, StringComparison.OrdinalIgnoreCase)) { list.Add(weapon); } } return list; } internal static bool IsEnabled(WeaponInfo w) { if (w != null && w.Index >= 0 && Settings.CategoryOn(w.Category)) { return Settings.WeaponOn(w); } return false; } internal static int TicketsFor(WeaponInfo w, bool online) { if (!IsEnabled(w) || (Object)(object)w.Pickup == (Object)null) { return 0; } if (online) { if (!w.AllowedOnline) { return 0; } return w.VanillaTickets; } int num = SpawnWeights.Override(w); if (num < 0) { return w.DefaultTickets; } return num; } internal static float ChanceOf(WeaponInfo w) { int num = 0; foreach (WeaponInfo weapon in Weapons) { num += TicketsFor(weapon, online: false); } if (num <= 0) { return 0f; } return (float)TicketsFor(w, online: false) / (float)num; } internal static void MenuChanged() { if ((Object)(object)WeaponPage.Instance != (Object)null) { ((TwoPanePage)WeaponPage.Instance).MarkDirty(); } } internal static void Build(WeaponSelectionHandler h) { Built = false; handler = h; prefabWeapons = null; Transform val = PrefabHolder(); if ((Object)(object)val == (Object)null) { throw new Exception("the player prefab has no Weapons object"); } Access.PlayerObject.Invoke(h) = ResourcesManager.Instance.CharacterObject; VanillaCount = val.childCount; Weapons.Clear(); Settings.Load(); HashSet<int> hashSet = new HashSet<int>(); WeaponCategoryTAG[] componentsInChildren = ((Component)h).GetComponentsInChildren<WeaponCategoryTAG>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (((Object)componentsInChildren[i]).name == "Special") { continue; } Transform val2 = ((Component)componentsInChildren[i]).transform.Find("Grid"); if ((Object)(object)val2 == (Object)null) { continue; } Toggle[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Toggle>(true); foreach (Toggle val3 in componentsInChildren2) { TextMeshProUGUI componentInChildren = ((Component)val3).GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)componentInChildren == (Object)null) { continue; } int num = IndexOfName(val, ((TMP_Text)componentInChildren).text); if (num >= 0 && hashSet.Add(num)) { Catalog.Entry entry = Catalog.For(num, ((TMP_Text)componentInChildren).text, ((Object)componentsInChildren[i]).name); Weapon component = ((Component)val.GetChild(num)).GetComponent<Weapon>(); WeaponInfo item = new WeaponInfo(entry.Id, entry.Name ?? ((TMP_Text)componentInChildren).text.Trim().ToUpperInvariant(), entry.Category, vanilla: true, ((TMP_Text)componentInChildren).text, null) { Mod = "Stick Fight", Index = num, DefaultTickets = component.Rarity, VanillaTickets = component.Rarity, OnByDefault = val3.isOn, VanillaRow = i, Pickup = component.weaponDrop }; Weapons.Add(item); if ((Object)(object)basePickup == (Object)null && (Object)(object)component.weaponDrop != (Object)null && (Object)(object)component.weaponDrop.GetComponent<WeaponPickUp>() != (Object)null) { basePickup = component.weaponDrop; } } } } int vanillaCount = VanillaCount; foreach (WeaponInfo item2 in modded) { WeaponDefinition definition = item2.Definition; item2.Index = -1; int baseIndex = definition.BaseIndex; if (baseIndex < 0 || baseIndex >= VanillaCount) { Plugin.Log.LogError((object)(item2.Id + ": no game weapon #" + baseIndex + "; skipped.")); continue; } if (definition.Existing.HasValue) { if (!hashSet.Add(baseIndex)) { Plugin.Log.LogError((object)(item2.Id + ": game weapon #" + baseIndex + " is already in the menu; skipped.")); continue; } item2.Index = baseIndex; } else { if (vanillaCount > 254) { Plugin.Log.LogError((object)(item2.Id + ": too many weapons (the game counts them in a byte); skipped.")); continue; } item2.Index = vanillaCount++; } WeaponCategory weaponCategory = FindCategory(item2.Category); if (weaponCategory == null) { Plugin.Log.LogWarning((object)(item2.Id + ": no category '" + item2.Category + "' (add it with WeaponRegistry.AddCategory); put in Gadgets.")); item2.Category = "gadgets"; } else { item2.Category = weaponCategory.Id; } item2.Pickup = PickupFor(item2, val); Weapons.Add(item2); } foreach (WeaponInfo weapon in Weapons) { if (renames.TryGetValue(weapon.Id, out var value)) { weapon.Name = value; } WeaponCategory weaponCategory2; if (moves.TryGetValue(weapon.Id, out value) && (weaponCategory2 = FindCategory(value)) != null) { weapon.Category = weaponCategory2.Id; } if (tickets.TryGetValue(weapon.Id, out var value2)) { weapon.DefaultTickets = value2; } } byIndex = new WeaponInfo[Math.Max(vanillaCount, VanillaCount)]; foreach (WeaponInfo weapon2 in Weapons) { byIndex[weapon2.Index] = weapon2; } Settings.ImportIfNew(Weapons, VanillaCount); FillGameLists(h); Sounds.ScanPacks(Weapons); Built = true; RebuildBag(); Plugin.Log.LogInfo((object)("Weapon list: " + Weapons.Count + " weapons (" + (Weapons.Count - modded.Count) + " from the game) in " + categories.Count + " categories.")); WeaponRegistry.RaiseReady(); } private static void FillGameLists(WeaponSelectionHandler h) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown GameObject[] array = (GameObject[])(object)new GameObject[byIndex.Length]; List<SingleWeaponUI> list = new List<SingleWeaponUI>(); List<SelectableWeapon> list2 = new List<SelectableWeapon>(); foreach (WeaponInfo weapon in Weapons) { array[weapon.Index] = weapon.Pickup; SingleWeaponUI val = new SingleWeaponUI(weapon.Name, weapon.Category, (byte)weapon.Index, (byte)Mathf.Clamp(weapon.DefaultTickets, 0, 255)); val.IsLocallyActive = Settings.WeaponOn(weapon); list.Add(val); if (weapon.IsVanilla) { list2.Add(new SelectableWeapon(weapon.Index, weapon.MenuLabel, weapon.Pickup)); } } List<WeaponCategoryUI> list3 = new List<WeaponCategoryUI>(); byte b = 0; foreach (WeaponCategory item in SortedCategories()) { WeaponCategoryUI val2 = new WeaponCategoryUI(item.Id, b++); val2.IsActive = Settings.CategoryOn(item.Id); list3.Add(val2); } Access.WeaponObjects.Invoke(h) = array; Access.MenuWeapons.Invoke(h) = list; Access.MenuCategories.Invoke(h) = list3; Access.NumberOfWeapons.Invoke(h) = array.Length; Access.NumberOfCategories.Invoke(h) = list3.Count; AccessTools.Property(typeof(WeaponSelectionHandler), "SelectableWeapons").SetValue(null, list2, null); } internal static void SyncGameLists() { if ((Object)(object)handler == (Object)null) { return; } List<SingleWeaponUI> list = Access.MenuWeapons.Invoke(handler); if (list != null) { foreach (SingleWeaponUI item in list) { WeaponInfo weaponInfo = ByIndex(item.WeaponIndex); if (weaponInfo != null) { item.IsLocallyActive = Settings.WeaponOn(weaponInfo); } } } List<WeaponCategoryUI> list2 = Access.MenuCategories.Invoke(handler); if (list2 == null) { return; } foreach (WeaponCategoryUI item2 in list2) { item2.IsActive = Settings.CategoryOn(item2.Category); } } internal static void RebuildBag() { if (Built && !((Object)(object)handler == (Object)null)) { List<byte> list = Access.Bag.Invoke(handler); if (list == null) { list = new List<byte>(); Access.Bag.Invoke(handler) = list; } FillBag(list); } } internal static void FillBag(List<byte> bag) { bagOnline = MatchmakingHandler.IsNetworkMatch; bag.Clear(); foreach (WeaponInfo weapon in Weapons) { int num = TicketsFor(weapon, bagOnline); for (int i = 0; i < num; i++) { bag.Add((byte)weapon.Index); } } } private static GameObject Templates() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)templates == (Object)null) { templates = new GameObject("WeaponFramework Templates"); templates.SetActive(false); Object.DontDestroyOnLoad((Object)(object)templates); } return templates; } private static GameObject PickupFor(WeaponInfo w, Transform holder) { //IL_01b6: Unknown result type (might be due to invalid IL or missing references) if (pickups.TryGetValue(w.Id, out var value) && (Object)(object)value != (Object)null) { return value; } WeaponDefinition definition = w.Definition; Weapon component = ((Component)holder.GetChild(definition.BaseIndex)).GetComponent<Weapon>(); GameObject val = (((Object)(object)component != (Object)null) ? component.weaponDrop : null); WeaponPickUp val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<WeaponPickUp>() : null); GameObject val3; if (definition.Existing.HasValue && (Object)(object)val2 != (Object)null && val2.id == w.Index && !definition.GiftBox && definition.ConfigurePickup == null && !definition.Tint.HasValue) { val3 = val; } else { bool flag = definition.Model != null && !definition.Existing.HasValue; bool flag2 = definition.GiftBox || (!flag && ((Object)(object)val2 == (Object)null || (definition.Existing.HasValue && val2.id != w.Index))); GameObject val4 = (((Object)(object)val2 != (Object)null) ? val : basePickup); if ((Object)(object)val4 == (Object)null) { Plugin.Log.LogError((object)(w.Id + ": no pickup to copy.")); return null; } val3 = Object.Instantiate<GameObject>(val4, Templates().transform, false); ((Object)val3).name = "Pickup " + w.Id; val3.GetComponent<WeaponPickUp>().id = w.Index; if (flag2) { MakePresent(val3); } else if (flag) { ModelBuilder.ApplyPickup(val3, definition.Model); } if (definition.Tint.HasValue && !flag2) { Looks.Tint(val3, definition.Tint.Value); } if (definition.ConfigurePickup != null) { try { definition.ConfigurePickup(val3); } catch (Exception ex) { Plugin.Log.LogError((object)(w.Id + ": ConfigurePickup failed: " + ex)); } } } pickups[w.Id] = val3; return val3; } private static void MakePresent(GameObject p) { for (int num = p.transform.childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)p.transform.GetChild(num)).gameObject); } ConstantForce component = p.GetComponent<ConstantForce>(); p.GetComponent<Rigidbody>().constraints = (RigidbodyConstraints)98; GameObject val = Resources.Load<GameObject>("PacketGFX"); if ((Object)(object)val != (Object)null) { Object.Instantiate<GameObject>(val, p.transform, false); } if ((Object)(object)component == (Object)null) { ((Behaviour)p.AddComponent<ConstantForce>()).enabled = false; } } private static int IndexOfName(Transform holder, string label) { string text = Catalog.Squash(label); for (int i = 0; i < holder.childCount; i++) { string name = ((Object)holder.GetChild(i)).name; int num = name.IndexOf(' '); if (num > 0 && Catalog.Squash(name.Substring(num)) == text) { return i; } } return -1; } internal static IEnumerable<WeaponInfo> ModdedCopies() { foreach (WeaponInfo weapon in Weapons) { if (!weapon.IsVanilla && weapon.Definition != null && !weapon.Definition.Existing.HasValue && weapon.Index >= VanillaCount) { yield return weapon; } } } } internal sealed class DebugLog : ILogListener, IDisposable { private readonly StreamWriter writer; private DebugLog(string path) { writer = new StreamWriter(new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { AutoFlush = true }; } public static void Start() { try { Logger.Listeners.Add((ILogListener)(object)new DebugLog(Path.Combine(Paths.BepInExRootPath, "WeaponFramework-debug.log"))); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't open the debug log: " + ex.Message)); } } public void LogEvent(object sender, LogEventArgs e) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) try { string text = ((e.Data != null) ? e.Data.ToString() : ""); if (text.IndexOf("Steamworks", StringComparison.Ordinal) < 0) { writer.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " [" + ((object)e.Level/*cast due to .constrained prefix*/).ToString() + ":" + e.Source.SourceName + "] " + text); } } catch { } } public void Dispose() { try { writer.Dispose(); } catch { } } } internal sealed class HoldMass : MonoBehaviour { internal struct Layout { public Vector3 Centre; public Vector3 Inertia; public Quaternion Rotation; } private static readonly Dictionary<string, Layout> measured = new Dictionary<string, Layout>(); public Layout Base; internal static Layout? Measure(GameObject weapon, string key) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) if (measured.TryGetValue(key, out var value)) { return value; } GameObject val = new GameObject("WF mass probe"); try { val.transform.position = new Vector3(0f, -5000f, 0f); Rigidbody val2 = val.AddComponent<Rigidbody>(); val2.useGravity = false; Transform transform = weapon.transform; int num = 0; Collider[] componentsInChildren = weapon.GetComponentsInChildren<Collider>(true); foreach (Collider val3 in componentsInChildren) { if (!val3.isTrigger) { GameObject val4 = new GameObject("part"); Transform transform2 = val4.transform; transform2.SetParent(val.transform, false); transform2.localPosition = transform.InverseTransformPoint(((Component)val3).transform.position); transform2.localRotation = Quaternion.Inverse(transform.rotation) * ((Component)val3).transform.rotation; Vector3 lossyScale = transform.lossyScale; Vector3 lossyScale2 = ((Component)val3).transform.lossyScale; transform2.localScale = new Vector3(lossyScale2.x / lossyScale.x, lossyScale2.y / lossyScale.y, lossyScale2.z / lossyScale.z); if (!Copy(val3, val4)) { Object.DestroyImmediate((Object)(object)val4); } else { num++; } } } if (num == 0) { return null; } val2.ResetCenterOfMass(); val2.ResetInertiaTensor(); value = new Layout { Centre = val2.centerOfMass, Inertia = val2.inertiaTensor, Rotation = val2.inertiaTensorRotation }; measured[key] = value; if (Plugin.DebugKeys.Value) { Plugin.Log.LogInfo((object)("Hold mass of " + key + ": centre " + ((Vector3)(ref value.Centre)).ToString("F3") + ", inertia " + ((Vector3)(ref value.Inertia)).ToString("F4") + " from " + num + " parts")); } return value; } finally { Object.DestroyImmediate((Object)(object)val); } } private static bool Copy(Collider c, GameObject to) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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) BoxCollider val = (BoxCollider)(object)((c is BoxCollider) ? c : null); if ((Object)(object)val != (Object)null) { BoxCollider obj = to.AddComponent<BoxCollider>(); obj.center = val.center; obj.size = val.size; return true; } SphereCollider val2 = (SphereCollider)(object)((c is SphereCollider) ? c : null); if ((Object)(object)val2 != (Object)null) { SphereCollider obj2 = to.AddComponent<SphereCollider>(); obj2.center = val2.center; obj2.radius = val2.radius; return true; } CapsuleCollider val3 = (CapsuleCollider)(object)((c is CapsuleCollider) ? c : null); if ((Object)(object)val3 != (Object)null) { CapsuleCollider obj3 = to.AddComponent<CapsuleCollider>(); obj3.center = val3.center; obj3.radius = val3.radius; obj3.height = val3.height; obj3.direction = val3.direction; return true; } MeshCollider val4 = (MeshCollider)(object)((c is MeshCollider) ? c : null); if ((Object)(object)val4 != (Object)null && (Object)(object)val4.sharedMesh != (Object)null) { MeshCollider obj4 = to.AddComponent<MeshCollider>(); obj4.sharedMesh = val4.sharedMesh; obj4.convex = true; return true; } return false; } private void OnEnable() { Apply(); } private void Start() { Apply(); } private void Apply() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0040: 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) Rigidbody component = ((Component)this).GetComponent<Rigidbody>(); if (!((Object)(object)component == (Object)null)) { component.centerOfMass = Base.Centre; if ((component.constraints & 0x70) == 0) { component.inertiaTensor = Base.Inertia * component.mass; component.inertiaTensorRotation = Base.Rotation; } } } } [HarmonyPatch] internal static class Hooks { private sealed class Held { public float Attack; public float Alt; public float Charge; } private const float MinCharge = 0.15f; private static readonly Dictionary<int, Held> held = new Dictionary<int, Held>(); private static readonly Dictionary<string, int> failures = new Dictionary<string, int>(); private static readonly Dictionary<Type, bool> wantsShots = new Dictionary<Type, bool>(); private static readonly Dictionary<GameObject, GameObject> markedProjectiles = new Dictionary<GameObject, GameObject>(); private static GameObject markerHolder; private static bool Local => !MatchmakingHandler.IsNetworkMatch; private static WeaponBehaviour BehaviourOf(Weapon w) { if (!((Object)(object)w != (Object)null)) { return null; } return ((Component)w).GetComponent<WeaponBehaviour>(); } private static bool IsCharged(Weapon w, out float drawTime, out float power) { drawTime = 0f; power = 1f; WeaponInfo weaponInfo = Core.Of(w); if (weaponInfo == null || weaponInfo.Definition == null) { return false; } WeaponDefinition definition = weaponInfo.Definition; if (definition.ChargeTime <= 0f && !w.isCharged) { return false; } drawTime = ((definition.ChargeTime > 0f) ? definition.ChargeTime : 0.6f); power = ((definition.ChargePower > 0f) ? definition.ChargePower : 1f); return true; } [HarmonyPrefix] [HarmonyPatch(typeof(Fighting), "Attack")] private static bool BeforeAttack(Fighting __instance, out float __state) { __state = __instance.counter; if (!Local) { return true; } Weapon weapon = __instance.weapon; WeaponBehaviour weaponBehaviour = BehaviourOf(weapon); if ((Object)(object)weaponBehaviour == (Object)null || Access.FightingBlock.Invoke(__instance).isBlocking || __instance.counter <= weapon.cd) { return true; } bool flag; try { flag = weaponBehaviour.OnAttack(); } catch (Exception e) { Fail(weaponBehaviour, "OnAttack", e); return true; } if (!flag) { return true; } __instance.counter = 0f; Access.JustAttacked.Invoke(__instance) = true; if (weaponBehaviour.CountsAsShot) { weaponBehaviour.UseAmmoInternal(1); } return false; } [HarmonyPostfix] [HarmonyPatch(typeof(Fighting), "Attack")] private static void AfterAttack(Fighting __instance, bool __runOriginal, float __state) { if (!Local || !__runOriginal) { return; } WeaponBehaviour weaponBehaviour = BehaviourOf(__instance.weapon); if ((Object)(object)weaponBehaviour == (Object)null || !(__instance.counter < __state) || __instance.counter != 0f) { return; } try { weaponBehaviour.AfterAttack(); } catch (Exception e) { Fail(weaponBehaviour, "AfterAttack", e); } } [HarmonyPrefix] [HarmonyPatch(typeof(Controller), "Attack")] private static bool BeforeControllerAttack(Fighting ___fighting) { float drawTime; float power; if (Local && (Object)(object)___fighting != (Object)null && (Object)(object)___fighting.weapon != (Object)null) { return !IsCharged(___fighting.weapon, out drawTime, out power); } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(Controller), "Update")] private static void AfterUpdate(Controller __instance) { if (!Local || __instance.inactive || __instance.isAI || PauseManager.isPaused || (!GameManager.inFight && !GameManager.stillInMenu)) { return; } CharacterInformation val = Access.Info.Invoke(__instance); CharacterActions val2 = Access.Actions.Invoke(__instance); Fighting val3 = Access.ControllerFighting.Invoke(__instance); if ((Object)(object)val == (Object)null || val.isDead || val2 == null || (Object)(object)val3 == (Object)null || !Access.HasControl.Invoke(__instance)) { return; } Weapon weapon = val3.weapon; if (!held.TryGetValue(((Object)__instance).GetInstanceID(), out var value)) { value = new Held(); held[((Object)__instance).GetInstanceID()] = value; } if ((Object)(object)weapon == (Object)null) { value.Attack = (value.Alt = (value.Charge = 0f)); return; } WeaponBehaviour weaponBehaviour = BehaviourOf(weapon); float deltaTime = Time.deltaTime; if (IsCharged(weapon, out var drawTime, out var power)) { if (((OneAxisInputControl)val2.PunchOrFire).IsPressed) { value.Charge = Mathf.Min(1f, value.Charge + deltaTime / drawTime); if (weapon.isCharged) { weapon.currentCharge = value.Charge * weapon.maxChargeTime * power; } if ((Object)(object)weaponBehaviour != (Object)null) { weaponBehaviour.Charge = value.Charge; } } else if (((OneAxisInputControl)val2.PunchOrFire).WasReleased && value.Charge > 0f) { if (value.Charge >= 0.15f || !weapon.isCharged) { if (weapon.isCharged) { weapon.currentCharge = value.Charge * weapon.maxChargeTime * power; } if ((Object)(object)weaponBehaviour != (Object)null) { weaponBehaviour.Charge = value.Charge; } val3.Attack(); } value.Charge = 0f; if ((Object)(object)weapon != (Object)null && weapon.isCharged) { weapon.currentCharge = 0f; } if ((Object)(object)weaponBehaviour != (Object)null) { weaponBehaviour.Charge = 0f; } } } if ((Object)(object)weaponBehaviour == (Object)null) { return; } try { if (((OneAxisInputControl)val2.PunchOrFire).IsPressed) { value.Attack += deltaTime; weaponBehaviour.OnAttackHeld(value.Attack); } else if (value.Attack > 0f) { float attack = value.Attack; value.Attack = 0f; weaponBehaviour.OnAttackReleased(attack); } } catch (Exception e) { Fail(weaponBehaviour, "OnAttackHeld/Released", e); } try { if (((OneAxisInputControl)val2.Block).WasPressed) { value.Alt = 0f; weaponBehaviour.OnAltPressed(); } if (((OneAxisInputControl)val2.Block).IsPressed) { value.Alt += deltaTime; weaponBehaviour.OnAltHeld(value.Alt); } else if (value.Alt > 0f) { float alt = value.Alt; value.Alt = 0f; weaponBehaviour.OnAltReleased(alt); } } catch (Exception e2) { Fail(weaponBehaviour, "OnAlt", e2); } } private static void Call(WeaponBehaviour b, string what, Action a) { try { a(); } catch (Exception e) { Fail(b, what, e); } } private static void Fail(WeaponBehaviour b, string what, Exception e) { string text = (((Object)(object)b != (Object)null) ? ((object)b).GetType().Name : "?") + "." + what; failures.TryGetValue(text, out var value); value = (failures[text] = value + 1); if (value == 1) { Plugin.Log.LogError((object)(text + " failed (later failures of it aren't logged): " + e)); } } private static bool WantsShots(WeaponBehaviour b) { Type type = ((object)b).GetType(); if (!wantsShots.TryGetValue(type, out var value)) { MethodInfo method = type.GetMethod("OnShot", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(GameObject) }, null); value = (object)method != null && (object)method.DeclaringType != typeof(WeaponBehaviour); wantsShots[type] = value; } return value; } [HarmonyPrefix] [HarmonyPatch(typeof(Weapon), "ActuallyShoot")] private static void BeforeShoot(Weapon __instance, out GameObject __state) { __state = null; if (Local && !((Object)(object)__instance.projectile == (Object)null)) { WeaponBehaviour weaponBehaviour = BehaviourOf(__instance); if (!((Object)(object)weaponBehaviour == (Object)null) && WantsShots(weaponBehaviour)) { __state = __instance.projectile; __instance.projectile = Marked(__instance.projectile); ShotMarker.Pending.Clear(); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Weapon), "ActuallyShoot")] private static void AfterShoot(Weapon __instance, GameObject __state) { if ((Object)(object)__state != (Object)null) { __instance.projectile = __state; WeaponBehaviour b = BehaviourOf(__instance); List<GameObject> list = new List<GameObject>(ShotMarker.Pending); ShotMarker.Pending.Clear(); if ((Object)(object)b != (Object)null) { foreach (GameObject p in list) { if ((Object)(object)p != (Object)null) { Call(b, "OnShot", delegate { b.OnShot(p); }); } } } } if (Local && __instance.isCharged && Core.Of(__instance) != null) { __instance.currentCharge = 0f; } } [HarmonyFinalizer] [HarmonyPatch(typeof(Weapon), "ActuallyShoot")] private static Exception ShootFinalizer(Weapon __instance, GameObject __state, Exception __exception) { if ((Object)(object)__state != (Object)null && (Object)(object)__instance.projectile != (Object)(object)__state) { __instance.projectile = __state; } return __exception; } private static GameObject Marked(GameObject prefab) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if (markedProjectiles.TryGetValue(prefab, out var value) && (Object)(object)value != (Object)null) { return value; } if ((Object)(object)markerHolder == (Object)null) { markerHolder = new GameObject("WeaponFramework Projectiles"); markerHolder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)markerHolder); } value = Object.Instantiate<GameObject>(prefab, markerHolder.transform, false); ((Object)value).name = ((Object)prefab).name; value.AddComponent<ShotMarker>(); markedProjectiles[prefab] = value; return value; } [HarmonyPrefix] [HarmonyPatch(typeof(Fighting), "SetWeapon")] private static void BeforeSetWeapon(Fighting __instance) { Unequip(__instance.weapon); } [HarmonyPostfix] [HarmonyPatch(typeof(Fighting), "SetWeapon")] private static void AfterSetWeapon(Fighting __instance) { if (Local) { WeaponBehaviour weaponBehaviour = BehaviourOf(__instance.weapon); if (!((Object)(object)weaponBehaviour == (Object)null)) { weaponBehaviour.Charge = 0f; Call(weaponBehaviour, "OnEquip", weaponBehaviour.OnEquip); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Fighting), "Dissarm")] private static void BeforeDisarm(Fighting __instance) { Unequip(__instance.weapon); } private static void Unequip(Weapon w) { if (Local) { WeaponBehaviour weaponBehaviour = BehaviourOf(w); if (!((Object)(object)weaponBehaviour == (Object)null) && ((Component)weaponBehaviour).gameObject.activeSelf) { weaponBehaviour.Charge = 0f; Call(weaponBehaviour, "OnUnequip", weaponBehaviour.OnUnequip); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Fighting), "ThrowWeapon")] private static void BeforeThrow(Fighting __instance, bool justDrop, out List<MonoBehaviour> __state) { __state = null; if (!justDrop || !Local || (Object)(object)__instance.weapon == (Object)null) { return; } MonoBehaviour[] componentsInChildren = ((Component)__instance.weapon).GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && (val is WeaponBehaviour || val is OffHand || val is Deflector)) { if (__state == null) { __state = new List<MonoBehaviour>(); } ((Behaviour)val).enabled = false; __state.Add(val); } } } [HarmonyFinalizer] [HarmonyPatch(typeof(Fighting), "ThrowWeapon")] private static Exception ThrowFinalizer(List<MonoBehaviour> __state, Exception __exception) { if (__state != null) { foreach (MonoBehaviour item in __state) { if ((Object)(object)item != (Object)null) { ((Behaviour)item).enabled = true; } } } return __exception; } [HarmonyPrefix] [HarmonyPatch(typeof(HealthHandler), "TakeDamage", new Type[] { typeof(float), typeof(Controller), typeof(DamageType), typeof(bool), typeof(Vector3), typeof(Vector3) })] private static void BeforeDamage(HealthHandler __instance, ref float damage, Controller damager, out WeaponBehaviour __state) { __state = null; if (!Local || (Object)(object)damager == (Object)null) { return; } Fighting component = ((Component)damager).GetComponent<Fighting>(); WeaponBehaviour weaponBehaviour = (((Object)(object)component != (Object)null) ? BehaviourOf(component.weapon) : null); if (!((Object)(object)weaponBehaviour == (Object)null)) { Controller component2 = ((Component)((Component)__instance).transform.root).GetComponent<Controller>(); try { damage = weaponBehaviour.ModifyDamage(component2, damage); } catch (Exception e) { Fail(weaponBehaviour, "ModifyDamage", e); } __state = weaponBehaviour; } } [HarmonyPostfix] [HarmonyPatch(typeof(HealthHandler), "TakeDamage", new Type[] { typeof(float), typeof(Controller), typeof(DamageType), typeof(bool), typeof(Vector3), typeof(Vector3) })] private static void AfterDamage(HealthHandler __instance, bool __result, float damage, WeaponBehaviour __state) { if (!((Object)(object)__state == (Object)null) && __result) { Controller victim = ((Component)((Component)__instance).transform.root).GetComponent<Controller>(); bool killed = __instance.health <= 0f; Call(__state, "OnDamageDealt", delegate { __state.OnDamageDealt(victim, damage, killed); }); } } } internal sealed class ShotMarker : MonoBehaviour { internal static readonly List<GameObject> Pending = new List<GameObject>(); private void Awake() { Pending.Add(((Component)this).gameObject); } } internal static class ModelBuilder { private static readonly Dictionary<string, Material> mats = new Dictionary<string, Material>(); private static readonly Dictionary<string, Material> gameMats = new Dictionary<string, Material>(); public static void ApplyHeld(GameObject weapon, WeaponModel m, string baseKey) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) HoldMass.Layout? layout = HoldMass.Measure(weapon, baseKey); Material black = StripParts(weapon.transform, null); Transform val = ((weapon.transform.childCount > 0) ? weapon.transform.GetChild(0) : null); if ((Object)(object)val != (Object)null && ((Object)val).name == "handPosition") { if (layout.HasValue) { HoldMass.Layout value = layout.Value; ref Vector3 centre = ref value.Centre; centre += m.Grip - val.localPosition; (weapon.GetComponent<HoldMass>() ?? weapon.AddComponent<HoldMass>()).Base = value; } val.localPosition = m.Grip; } Shoot[] componentsInChildren = weapon.GetComponentsInChildren<Shoot>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).transform.localPosition = m.Muzzle; } ParticleSystem[] componentsInChildren2 = weapon.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val2 in componentsInChildren2) { if ((Object)(object)((Component)val2).transform.parent == (Object)(object)weapon.transform) { ((Component)val2).transform.localPosition = m.Muzzle; } } Build(weapon.transform, m, weapon.layer, black, colliders: true); if (m.OffHandGrip.HasValue) { (weapon.GetComponent<OffHand>() ?? weapon.AddComponent<OffHand>()).Local = m.OffHandGrip.Value; } } public static void ApplyPickup(GameObject pickup, WeaponModel m) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_0120: 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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) Transform val = null; foreach (Transform item in pickup.transform) { Transform val2 = item; if ((Object)(object)((Component)val2).GetComponent<Collider>() != (Object)null && (Object)(object)((Component)val2).GetComponent<MeshFilter>() != (Object)null) { val = val2; break; } } Material black = StripParts(pickup.transform, val); Build(pickup.transform, m, pickup.layer, black, colliders: false); Bounds val3 = m.LocalBounds(); if ((Object)(object)val == (Object)null) { val = GameObject.CreatePrimitive((PrimitiveType)3).transform; val.SetParent(pickup.transform, false); ((Component)val).gameObject.layer = pickup.layer; } ((Object)val).name = "Cube"; MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = false; } val.localRotation = Quaternion.identity; val.localPosition = ((Bounds)(ref val3)).center; val.localScale = ((m.PickupCollider != Vector3.zero) ? m.PickupCollider : Vector3.Max(((Bounds)(ref val3)).size + new Vector3(0.2f, 0.12f, 0.12f), new Vector3(0.36f, 0.36f, 0.64f))); } public static void BuildVisual(Transform parent, WeaponModel m) { Build(parent, m, ((Component)parent).gameObject.layer, GameMaterial("WeaponMaterial"), colliders: false); } private static Material StripParts(Transform root, Transform except) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown Material val = null; List<GameObject> list = new List<GameObject>(); foreach (Transform item in root) { Transform val2 = item; if (!((Object)(object)val2 == (Object)(object)except) && !((Object)(object)((Component)val2).GetComponent<MeshFilter>() == (Object)null)) { MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>(); if ((Object)(object)val == (Object)null && (Object)(object)component != (Object)null && (Object)(object)((Renderer)component).sharedMaterial != (Object)null && ((Object)((Renderer)component).sharedMaterial).name.StartsWith("WeaponMaterial")) { val = ((Renderer)component).sharedMaterial; } list.Add(((Component)val2).gameObject); } } foreach (GameObject item2 in list) { if ((Object)(object)val == (Object)null) { MeshRenderer component2 = item2.GetComponent<MeshRenderer>(); if ((Object)(object)component2 != (Object)null) { val = ((Renderer)component2).sharedMaterial; } } Object.DestroyImmediate((Object)(object)item2); } return val; } private static void Build(Transform parent, WeaponModel m, int layer, Material black, bool colliders) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Invalid comparison between Unknown and I4 //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Invalid comparison between Unknown and I4 //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might b