Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SkyforgeFireworks v0.6.0
BepInEx/plugins/SkyforgeFireworks/SkyforgeFireworks.dll
Decompiled 11 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Audio; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("SkyforgeFireworks.PrivateTests")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SkyforgeFireworks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.6.0.0")] [assembly: AssemblyInformationalVersion("0.6.0")] [assembly: AssemblyProduct("SkyforgeFireworks")] [assembly: AssemblyTitle("SkyforgeFireworks")] [assembly: AssemblyVersion("0.6.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SkyforgeFireworks { internal static class CarvingCodec { internal static string Encode(ShowSettings plan) { if (plan == null || !plan.Valid) { throw new ArgumentException("Invalid launcher carving"); } return string.Join("|", "2", plan.Rune.ToString(CultureInfo.InvariantCulture), plan.Shots.ToString(CultureInfo.InvariantCulture), plan.Pattern.ToString(CultureInfo.InvariantCulture), plan.Delay.ToString("R", CultureInfo.InvariantCulture), plan.Interval.ToString("R", CultureInfo.InvariantCulture), plan.Fuse.ToString("R", CultureInfo.InvariantCulture), plan.Spread.ToString(CultureInfo.InvariantCulture), plan.Preset.ToString(CultureInfo.InvariantCulture)); } internal static bool TryDecode(string text, out ShowSettings plan) { plan = null; if (string.IsNullOrEmpty(text) || text.Length > 256) { return false; } string[] array = text.Split(new char[1] { '|' }); bool flag = array.Length == 7 && array[0] == "1"; if (!flag && (array.Length != 9 || !(array[0] == "2"))) { return false; } ShowSettings showSettings = new ShowSettings(); CultureInfo invariantCulture = CultureInfo.InvariantCulture; if (!int.TryParse(array[1], NumberStyles.Integer, invariantCulture, out showSettings.Rune) || !int.TryParse(array[2], NumberStyles.Integer, invariantCulture, out showSettings.Shots) || !int.TryParse(array[3], NumberStyles.Integer, invariantCulture, out showSettings.Pattern) || !float.TryParse(array[4], NumberStyles.Float, invariantCulture, out showSettings.Delay) || !float.TryParse(array[5], NumberStyles.Float, invariantCulture, out showSettings.Interval) || !float.TryParse(array[6], NumberStyles.Float, invariantCulture, out showSettings.Fuse) || (!flag && (!int.TryParse(array[7], NumberStyles.Integer, invariantCulture, out showSettings.Spread) || !int.TryParse(array[8], NumberStyles.Integer, invariantCulture, out showSettings.Preset))) || !showSettings.Valid) { return false; } plan = showSettings; return true; } } public sealed class FireworkPiece : MonoBehaviour, Hoverable, Interactable { internal sealed class PreviewRow { internal string Name; internal string Status; internal float Distance; internal float Delay; internal float Interval; internal int Planned; internal int Available; internal bool Included; internal int Shots => Math.Min(Planned, Available); } public int Kind; internal static readonly HashSet<FireworkPiece> All = new HashSet<FireworkPiece>(); private const string RequestRpc = "Skyforge_Request_3"; private const string ArmRpc = "Skyforge_Arm_2"; private const string NoticeRpc = "Skyforge_Notice_1"; internal ZNetView View; private Container box; private bool wasOwner; private float nextTick; private List<FireworkPiece> targets; private double showDuration; private ZDOID actorId; private long actorPeer; private FuseVisual fuse; internal int LastNotice { get; private set; } internal static long Now { get { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return 0L; } return ZNet.instance.GetTime().Ticks; } } internal bool Ready { get { if (Object.op_Implicit((Object)(object)View)) { return View.IsValid(); } return false; } } internal ZDO Data => View.GetZDO(); internal long StartTime { get { if (!Ready) { return 0L; } return Data.GetLong("SF_start", 0L); } } internal bool Running => StartTime > 0; internal ShowSettings Settings => new ShowSettings { Pattern = Data.GetInt("SF_pattern", 0), Spread = Data.GetInt("SF_spread", 0), Preset = Data.GetInt("SF_preset", 0), Rune = Data.GetInt("SF_rune", 1), Delay = Data.GetFloat("SF_delay", 0f), Interval = Data.GetFloat("SF_interval", 1f), Shots = Data.GetInt("SF_shots", (Kind == 0) ? 1 : 6), Fuse = Data.GetFloat("SF_fuse", 6f) }; internal ShowSettings RunSettings { get { ShowSettings settings = Settings; if (Data.GetBool("SF_runPlan", false)) { settings.Pattern = Data.GetInt("SF_runPattern", settings.Pattern); settings.Spread = Data.GetInt("SF_runSpread", settings.Spread); settings.Shots = Data.GetInt("SF_runShots", settings.Shots); settings.Delay = Data.GetFloat("SF_runDelay", settings.Delay); settings.Interval = Data.GetFloat("SF_runInterval", settings.Interval); } return settings; } } internal string Label { get { if (Kind != 2) { if (Kind != 1) { return "Launch stand"; } return "Salvo rack"; } return "Show fuse board"; } } private void SetRunSettings(ShowSettings plan) { Data.Set("SF_runPattern", plan.Pattern); Data.Set("SF_runSpread", (Kind == 1) ? plan.Spread : 0); Data.Set("SF_runShots", plan.Shots); Data.Set("SF_runDelay", plan.Delay); Data.Set("SF_runInterval", plan.Interval); Data.Set("SF_runPlan", true); } internal ShowSettings PlannedFor(FireworkPiece launcher, int index, int count, int preset) { if (preset != 0) { return ShowPresets.Plan(preset, index, count, launcher.Settings); } return launcher.Settings; } private void Start() { View = ((Component)this).GetComponent<ZNetView>(); box = ((Component)this).GetComponent<Container>(); if (!Ready) { ((Behaviour)this).enabled = false; return; } View.Register<ZPackage>("Skyforge_Request_3", (Action<long, ZPackage>)OnRequest); View.Register<ZPackage>("Skyforge_Arm_2", (Action<long, ZPackage>)OnArm); View.Register<int>("Skyforge_Notice_1", (Action<long, int>)OnNotice); wasOwner = View.IsOwner(); if (wasOwner) { Stop(); } All.Add(this); fuse = ((Component)this).gameObject.AddComponent<FuseVisual>(); } private void OnDestroy() { All.Remove(this); if ((Object)(object)SettingsPanel.Target == (Object)(object)this) { SettingsPanel.Close(); } } internal static bool HasTorch(Player actor) { object obj; if (!Object.op_Implicit((Object)(object)actor)) { obj = null; } else { ZNetView component = ((Component)actor).GetComponent<ZNetView>(); obj = ((component != null) ? component.GetZDO() : null); } ZDO val = (ZDO)obj; int stableHashCode = StringExtensionMethods.GetStableHashCode("Torch"); if (val != null && (val.GetInt(ZDOVars.s_leftItem, 0) == stableHashCode || val.GetInt(ZDOVars.s_rightItem, 0) == stableHashCode)) { return !((Character)actor).IsDead(); } return false; } public string GetHoverName() { return Label; } public float GetHoverOffset() { return 0.8f; } public string GetHoverText() { if (!Ready) { return Label; } string text = Label + " · Rune " + Settings.Rune; if (Running) { double num = (double)(StartTime - Now) / 10000000.0; text += ((num > 0.0) ? ("\nFuse burning · " + Math.Ceiling(num) + "s") : "\nShow in progress"); return Localization.instance.Localize(text + "\n[<color=yellow>$KEY_Use</color>] Snuff / stop remaining shots"); } if (Kind < 2) { text = text + "\n" + VikingRocket.PatternName(Settings.Pattern) + " - loaded for " + AvailableShots() + " shots"; text = text + "\n" + Settings.Shots + " planned - delay " + Settings.Delay + "s - every " + Settings.Interval + "s"; text += (HasTorch(Player.m_localPlayer) ? "\nPut away your torch to open the ammunition box." : "\n[<color=yellow>$KEY_Use</color>] Load fireworks"); } else { text += "\nLinks matching runes within 40m (up to 16 launchers)"; } text += "\n[<color=yellow>Shift + $KEY_Use</color>] Arrange show\nEquip torch + [<color=yellow>$KEY_Use</color>] Light fuse"; return Localization.instance.Localize(text); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (hold || !Ready || (Object)(object)user != (Object)(object)Player.m_localPlayer || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return false; } if (Running) { Request(2); return true; } if (alt || !HasTorch((Player)(object)((user is Player) ? user : null))) { SettingsPanel.Open(this); return true; } Request(1); return true; } public bool UseItem(Humanoid user, ItemData item) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) object obj; if (item == null) { obj = null; } else { GameObject dropPrefab = item.m_dropPrefab; obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null); } if ((string?)obj != "Torch" || (Object)(object)user != (Object)(object)Player.m_localPlayer || !Ready) { return false; } if (!HasTorch((Player)(object)((user is Player) ? user : null))) { ((Character)user).Message((MessageType)2, "Equip your torch, then use it on the fuse.", 0, (Sprite)null, false); return true; } if (!Running && PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { Request(1); } return true; } internal unsafe void Request(int action, ShowSettings settings = null) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_001f: 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_0127: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Ready && Object.op_Implicit((Object)(object)localPlayer)) { ZPackage val = new ZPackage(); val.Write(((Character)localPlayer).GetZDOID()); val.Write(Now); val.Write(action); if (action == 0) { val.Write(settings.Rune); val.Write(settings.Delay); val.Write(settings.Interval); val.Write(settings.Shots); val.Write(settings.Fuse); val.Write(settings.Pattern); val.Write(settings.Spread); val.Write(settings.Preset); } string[] obj = new string[10] { "Request action=", action.ToString(), " target=", null, null, null, null, null, null, null }; ZDOID uid = Data.m_uid; obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[4] = " owner="; obj[5] = Data.GetOwner().ToString(); obj[6] = " local="; obj[7] = ZNet.GetUID().ToString(); obj[8] = " registered="; obj[9] = ((Object)(object)ZNetScene.instance.FindInstance(Data.m_uid) == (Object)(object)((Component)this).gameObject).ToString(); Plugin.Note(string.Concat(obj)); View.InvokeRPC("Skyforge_Request_3", new object[1] { val }); } } private static Player Actor(ZDOID id, long sender) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(id) : null); ZNetView val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ZNetView>() : null); if (!Object.op_Implicit((Object)(object)val2) || !val2.IsValid() || val2.GetZDO().GetOwner() != sender) { return null; } return val.GetComponent<Player>(); } private static bool Access(Player player, Vector3 pos) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player) || player.GetPlayerID() == 0L) { return false; } bool flag = false; foreach (PrivateArea item in (List<PrivateArea>)AccessTools.Field(typeof(PrivateArea), "m_allAreas").GetValue(null)) { if (Object.op_Implicit((Object)(object)item) && (bool)AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null).Invoke(item, null) && (bool)AccessTools.Method(typeof(PrivateArea), "IsInside", (Type[])null, (Type[])null).Invoke(item, new object[2] { pos, 0f })) { if (((Component)item).GetComponent<Piece>().GetCreator() == player.GetPlayerID() || (bool)AccessTools.Method(typeof(PrivateArea), "IsPermitted", (Type[])null, (Type[])null).Invoke(item, new object[1] { player.GetPlayerID() })) { return true; } flag = true; } } return !flag; } private void Notice(long peer, int code) { View.InvokeRPC(peer, "Skyforge_Notice_1", new object[1] { code }); } private void OnNotice(long sender, int code) { if (Ready && sender == Data.GetOwner() && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { string text = code switch { 5 => "This saved arrangement is invalid. Open Arrange and carve valid settings.", 4 => "Load fireworks into this launcher first.", 3 => "Close the ammunition box before lighting its fuse.", 2 => "Another show is already using this rune nearby.", 1 => "Load fireworks into a nearby launcher on this rune first.", _ => null, }; if (text != null) { LastNotice = code; ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } } internal int AvailableShots() { if (!Ready || !Object.op_Implicit((Object)(object)box)) { return 0; } if (!box.IsInUse()) { AccessTools.Method(typeof(Container), "Load", (Type[])null, (Type[])null).Invoke(box, null); } FireworkItem value; return (from i in box.GetInventory().GetAllItems() group i by i.m_shared.m_name).Sum((IGrouping<string, ItemData> group) => Plugin.Ammunition.TryGetValue(group.Key, out value) ? (group.Sum((ItemData i) => i.m_stack) / value.m_fireworkItemCount) : 0); } internal List<PreviewRow> Preview(Player player, int rune, int preset = 0) { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) List<PreviewRow> list = new List<PreviewRow>(); int num = 0; FireworkPiece[] array = (from f in All where Object.op_Implicit((Object)(object)f) && f.Ready && f.Kind < 2 && f.Settings.Rune == rune && Vector3.Distance(((Component)f).transform.position, ((Component)this).transform.position) <= 40f && Access(player, ((Component)f).transform.position) orderby Vector3.Distance(((Component)f).transform.position, ((Component)this).transform.position) select f).ThenBy<FireworkPiece, string>((FireworkPiece f) => ((object)Unsafe.As<ZDOID, ZDOID>(ref f.Data.m_uid)/*cast due to .constrained prefix*/).ToString(), StringComparer.Ordinal).ToArray(); int count = Math.Min(16, array.Count((FireworkPiece f) => f.Settings.Valid && !f.Running && !f.box.IsInUse() && f.AvailableShots() > 0)); FireworkPiece[] array2 = array; foreach (FireworkPiece fireworkPiece in array2) { ShowSettings settings = fireworkPiece.Settings; PreviewRow previewRow = new PreviewRow { Name = fireworkPiece.Label + " / " + VikingRocket.PatternName(settings.Pattern), Distance = Vector3.Distance(((Component)fireworkPiece).transform.position, ((Component)this).transform.position), Planned = settings.Shots, Delay = settings.Delay, Interval = settings.Interval, Available = fireworkPiece.AvailableShots() }; previewRow.Status = ((!settings.Valid) ? "Invalid arrangement" : (fireworkPiece.Running ? "Already firing" : (fireworkPiece.box.IsInUse() ? "Box open" : ((previewRow.Available == 0) ? "No fireworks" : ((num >= 16) ? "Beyond 16-launcher limit" : "Ready"))))); previewRow.Included = previewRow.Status == "Ready"; if (previewRow.Included) { ShowSettings showSettings = PlannedFor(fireworkPiece, num, count, preset); previewRow.Planned = showSettings.Shots; previewRow.Delay = showSettings.Delay; previewRow.Interval = showSettings.Interval; if (preset != 0) { previewRow.Name = fireworkPiece.Label + " / Vanilla"; } num++; } list.Add(previewRow); } return list; } private unsafe void OnRequest(long sender, ZPackage pkg) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Unknown result type (might be due to invalid IL or missing references) if (!Ready || !View.IsOwner()) { Plugin.Note("Request ignored: not authoritative owner"); return; } try { ZDOID id = pkg.ReadZDOID(); long num = pkg.ReadLong(); int num2 = pkg.ReadInt(); Player player = Actor(id, sender); if (!Object.op_Implicit((Object)(object)player) || Vector3.Distance(((Component)player).transform.position, ((Component)this).transform.position) > 8f || !Access(player, ((Component)this).transform.position) || !ShowRules.Fresh(Now, num, Data.GetLong("SF_request", 0L))) { Plugin.Note("Request rejected: actor=" + Object.op_Implicit((Object)(object)player) + " sender=" + sender + " action=" + num2 + " now=" + Now + " issued=" + num + " prior=" + Data.GetLong("SF_request", 0L)); return; } Data.Set("SF_request", num); if (num2 == 2) { Stop(); } else { if (Running) { return; } switch (num2) { case 0: { ShowSettings showSettings = new ShowSettings { Rune = pkg.ReadInt(), Delay = pkg.ReadSingle(), Interval = pkg.ReadSingle(), Shots = pkg.ReadInt(), Fuse = pkg.ReadSingle(), Pattern = pkg.ReadInt(), Spread = pkg.ReadInt(), Preset = pkg.ReadInt() }; if (showSettings.Valid) { Data.Set("SF_spread", (Kind == 1) ? showSettings.Spread : 0); Data.Set("SF_preset", (Kind == 2) ? showSettings.Preset : 0); Data.Set("SF_pattern", showSettings.Pattern); Data.Set("SF_rune", showSettings.Rune); Data.Set("SF_delay", showSettings.Delay); Data.Set("SF_interval", showSettings.Interval); Data.Set("SF_shots", showSettings.Shots); Data.Set("SF_fuse", showSettings.Fuse); ZDOID uid = Data.m_uid; Plugin.Note("Settings carved on " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString()); } break; } case 1: if (HasTorch(player)) { if (!Settings.Valid) { Notice(sender, 5); break; } actorId = id; actorPeer = sender; if (Kind == 2) { if (All.Any((FireworkPiece f) => Object.op_Implicit((Object)(object)f) && (Object)(object)f != (Object)(object)this && f.Ready && f.Kind == 2 && f.Running && f.Settings.Rune == Settings.Rune && Vector3.Distance(((Component)f).transform.position, ((Component)this).transform.position) <= 80f)) { Notice(sender, 2); break; } targets = (from f in All where Object.op_Implicit((Object)(object)f) && f.Ready && f.Kind < 2 && f.Settings.Valid && f.Settings.Rune == Settings.Rune && Vector3.Distance(((Component)f).transform.position, ((Component)this).transform.position) <= 40f && !f.Running && Access(player, ((Component)f).transform.position) && Object.op_Implicit((Object)(object)f.box) && !f.box.IsInUse() && f.NextAmmo() != null orderby Vector3.Distance(((Component)f).transform.position, ((Component)this).transform.position) select f).ThenBy<FireworkPiece, string>((FireworkPiece f) => ((object)Unsafe.As<ZDOID, ZDOID>(ref f.Data.m_uid)/*cast due to .constrained prefix*/).ToString(), StringComparer.Ordinal).Take(16).ToList(); if (targets.Count == 0) { Notice(sender, 1); break; } showDuration = (from s in targets.Select((FireworkPiece t, int i) => PlannedFor(t, i, targets.Count, Settings.Preset)) select (double)s.Delay + (double)((float)(s.Shots - 1) * s.Interval)).Max() + 2.0; } else { if (box.IsInUse()) { Notice(sender, 3); break; } if (NextAmmo() == null) { Notice(sender, 4); break; } } long num3 = Now + (long)(Settings.Fuse * 10000000f); SetRunSettings(Settings); Data.Set("SF_beat", Now); Data.Set("SF_cursor", 0); Data.Set("SF_start", num3); Data.Set("SF_controller", ZDOID.None); Data.Set("SF_lastRun", num3); string[] obj = new string[6] { "Fuse lit: ", Label, " ", null, null, null }; ZDOID uid = Data.m_uid; obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[4] = " start="; obj[5] = num3.ToString(); Plugin.Note(string.Concat(obj)); if (Kind == 2) { ArmTargets(); } break; } goto default; default: Plugin.Note("Ignition requires equipped torch"); break; } } } catch (Exception ex) { Plugin.Note("Rejected malformed show request: " + ex.GetType().Name); } } private void ArmTargets() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (targets == null) { return; } for (int i = 0; i < targets.Count; i++) { FireworkPiece fireworkPiece = targets[i]; if (Object.op_Implicit((Object)(object)fireworkPiece) && fireworkPiece.Ready) { ZPackage val = new ZPackage(); val.Write(Data.m_uid); val.Write(actorId); val.Write(actorPeer); val.Write(StartTime); val.Write(i); val.Write(targets.Count); fireworkPiece.View.InvokeRPC("Skyforge_Arm_2", new object[1] { val }); } } } private static FireworkPiece Find(ZDOID id) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; if (instance == null) { return null; } GameObject obj = instance.FindInstance(id); if (obj == null) { return null; } return obj.GetComponent<FireworkPiece>(); } private void OnArm(long sender, ZPackage p) { //IL_0029: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) if (!Ready || !View.IsOwner() || Kind == 2 || Running) { return; } try { FireworkPiece fireworkPiece = Find(p.ReadZDOID()); Player player = Actor(p.ReadZDOID(), p.ReadLong()); long num = p.ReadLong(); int num2 = p.ReadInt(); int num3 = p.ReadInt(); if (num2 >= 0 && num3 >= 1 && num3 <= 16 && num2 < num3 && Object.op_Implicit((Object)(object)fireworkPiece) && fireworkPiece.Ready && fireworkPiece.Kind == 2 && fireworkPiece.Data.GetOwner() == sender && fireworkPiece.StartTime == num && num > Now + 10000000 && num <= Now + 160000000 && Data.GetLong("SF_lastRun", 0L) < num && fireworkPiece.Settings.Rune == Settings.Rune && !(Vector3.Distance(((Component)this).transform.position, ((Component)fireworkPiece).transform.position) > 40f) && Access(player, ((Component)this).transform.position) && Access(player, ((Component)fireworkPiece).transform.position) && !box.IsInUse() && NextAmmo() != null) { ShowSettings showSettings = fireworkPiece.PlannedFor(this, num2, num3, fireworkPiece.Settings.Preset); if (showSettings.Valid) { SetRunSettings(showSettings); Data.Set("SF_controller", fireworkPiece.Data.m_uid); Data.Set("SF_cursor", 0); Data.Set("SF_lastRun", num); Data.Set("SF_start", num); } } } catch (Exception ex) { Plugin.Note("Rejected malformed arm request: " + ex.GetType().Name); } } private void Stop() { if (Ready && View.IsOwner()) { Data.Set("SF_start", 0L); Data.Set("SF_cursor", 0); Data.Set("SF_runPlan", false); } targets = null; } private void Update() { //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) if (!Ready) { return; } if (Object.op_Implicit((Object)(object)fuse)) { fuse.SetBurning(Running && Now < StartTime, (float)Math.Max(0.0, (double)(StartTime - Now) / 10000000.0)); } bool flag = View.IsOwner(); if (flag != wasOwner) { wasOwner = flag; if (flag) { Stop(); } } if (!flag || !Running || Time.unscaledTime < nextTick) { return; } nextTick = Time.unscaledTime + 0.05f; long now = Now; long start = StartTime; if (Kind == 2) { if (targets == null) { Stop(); return; } if (now - Data.GetLong("SF_beat", 0L) > 5000000) { Data.Set("SF_beat", now); if (now < start - 10000000) { ArmTargets(); } } foreach (FireworkPiece item in targets.Where((FireworkPiece t) => Object.op_Implicit((Object)(object)t) && t.Ready && t.StartTime == start && t.Data.GetZDOID("SF_controller") == Data.m_uid)) { ShowSettings runSettings = item.RunSettings; if (runSettings.Valid) { showDuration = Math.Max(showDuration, runSettings.Delay + (float)(runSettings.Shots - 1) * runSettings.Interval + 2f); } } double num = showDuration; if ((double)now > (double)start + num * 10000000.0) { Stop(); } return; } ZDOID zDOID = Data.GetZDOID("SF_controller"); if (zDOID != ZDOID.None) { FireworkPiece fireworkPiece = Find(zDOID); if (!Object.op_Implicit((Object)(object)fireworkPiece) || !fireworkPiece.Ready || fireworkPiece.StartTime != start || now - fireworkPiece.Data.GetLong("SF_beat", 0L) > 30000000) { Stop(); return; } } ShowSettings runSettings2 = RunSettings; int num2 = Data.GetInt("SF_cursor", 0); if (!runSettings2.Valid || num2 >= runSettings2.Shots || box.IsInUse()) { Stop(); return; } long num3 = runSettings2.Due(start, num2); if (now >= num3) { Data.Set("SF_cursor", num2 + 1); if (!ShowRules.Expired(now, num3)) { Launch(); } } } private ItemData NextAmmo() { if (!Object.op_Implicit((Object)(object)box) || box.GetInventory() == null) { return null; } if (!box.IsInUse()) { AccessTools.Method(typeof(Container), "Load", (Type[])null, (Type[])null).Invoke(box, null); } Inventory inv = box.GetInventory(); FireworkItem value; return ((IEnumerable<ItemData>)(from i in inv.GetAllItems() orderby i.m_gridPos.y, i.m_gridPos.x select i)).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => Plugin.Ammunition.TryGetValue(i.m_shared.m_name, out value) && inv.CountItems(i.m_shared.m_name, -1, true) >= value.m_fireworkItemCount)); } private unsafe void Launch() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: 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) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) ItemData val = NextAmmo(); if (val == null) { Stop(); return; } FireworkItem val2 = Plugin.Ammunition[val.m_shared.m_name]; box.GetInventory().RemoveItem(val.m_shared.m_name, val2.m_fireworkItemCount, -1, true); try { int num = Data.GetInt("SF_cursor", 1) - 1; ShowSettings runSettings = RunSettings; int num2 = runSettings.BurstAt(num); LaunchSpread.Offset((Kind == 1) ? runSettings.Spread : 0, num, (int)StartTime ^ StringExtensionMethods.GetStableHashCode(((object)Unsafe.As<ZDOID, ZDOID>(ref Data.m_uid)/*cast due to .constrained prefix*/).ToString()), out var x, out var z); Quaternion val3 = Quaternion.Euler(0f, ((Component)this).transform.eulerAngles.y, 0f); ? val4; if (Kind != 1 || runSettings.Spread == 0) { val4 = ((num2 == 0) ? Quaternion.identity : ((Component)this).transform.rotation); } else { Vector3 up = Vector3.up; Vector3 val5 = new Vector3(x, 1f, z); val4 = val3 * Quaternion.FromToRotation(up, ((Vector3)(ref val5)).normalized); } Quaternion val6 = (Quaternion)val4; Vector3 val7 = ((Component)this).transform.position + Vector3.up * 1.4f + ((Kind == 1 && runSettings.Spread != 0) ? (val3 * new Vector3((float)(num % 5 - 2) * 0.22f, 0f, 0f)) : Vector3.zero); GameObject[] array = (GameObject[])((num2 == 0) ? ((Array)val2.m_fireworksEffects.Create(val7, val6, (Transform)null, 1f, -1, default(ZDOID))) : ((Array)new GameObject[1] { Object.Instantiate<GameObject>(VikingRocket.Prefabs[num2], val7, val6) })); string[] obj = new string[10] { "LAUNCH ", null, null, null, null, null, null, null, null, null }; ZDOID uid = Data.m_uid; obj[1] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[2] = " shot="; obj[3] = Data.GetInt("SF_cursor", 0).ToString(); obj[4] = " item="; obj[5] = ((Object)val2.m_fireworkItem).name; obj[6] = " effects="; obj[7] = array.Length.ToString(); obj[8] = " networkTicks="; obj[9] = Now.ToString(); Plugin.Note(string.Concat(obj)); } catch (Exception ex) { Stop(); Plugin.Note("Launch stopped after effect error: " + ex); } } } public static class FuseAudio { public static float[] Create(int rate = 22050, int seconds = 4) { float[] array = new float[rate * seconds]; Random random = new Random(1731); double num = 0.0; double num2 = 0.0; int num3 = Math.Max(1, rate / 100); for (int i = 0; i < array.Length; i++) { double num4 = random.NextDouble() * 2.0 - 1.0; num = 0.84 * num + 0.16 * num4; if (random.NextDouble() < 13.0 / (double)rate) { num2 = (0.15 + random.NextDouble() * 0.3) * (double)((random.Next(2) != 0) ? 1 : (-1)); } num2 *= 0.985; double num5 = Math.Min(1.0, Math.Min((double)i / (double)num3, (double)(array.Length - 1 - i) / (double)num3)); array[i] = (float)Math.Max(-0.6, Math.Min(0.6, ((num4 - num) * 0.14 + num * 0.13 + num2) * num5)); } return array; } } public sealed class FuseVisual : MonoBehaviour { private GameObject ember; private Light glow; private ParticleSystem sparks; private AudioSource sound; private static AudioClip clip; private bool burning; private float burnDuration; private void Ensure() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ember)) { ember = new GameObject("Burning fuse ember"); ember.transform.SetParent(((Component)this).transform, false); ember.transform.localPosition = new Vector3(0f, 0.85f, -0.27f); glow = ember.AddComponent<Light>(); glow.color = new Color(1f, 0.46f, 0.08f); glow.range = 2f; glow.intensity = 0.5f; sparks = ember.AddComponent<ParticleSystem>(); MainModule main = sparks.main; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.28f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.65f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.035f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(1f, 0.65f, 0.12f)); ((MainModule)(ref main)).maxParticles = 40; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; if (Object.op_Implicit((Object)(object)Plugin.SparkMaterial)) { ((Renderer)((Component)sparks).GetComponent<ParticleSystemRenderer>()).sharedMaterial = Plugin.SparkMaterial; } else { ((Renderer)((Component)sparks).GetComponent<ParticleSystemRenderer>()).enabled = false; } EmissionModule emission = sparks.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(25f); ShapeModule shape = sparks.shape; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4; ((ShapeModule)(ref shape)).angle = 35f; ((ShapeModule)(ref shape)).radius = 0.015f; ((Component)sparks).transform.localRotation = Quaternion.Euler(-90f, 0f, 0f); GameObject val = new GameObject("Hemp fuse sizzle"); val.transform.SetParent(((Component)this).transform, false); val.transform.localPosition = ember.transform.localPosition; sound = val.AddComponent<AudioSource>(); sound.spatialBlend = 1f; sound.minDistance = 1f; sound.maxDistance = 12f; sound.rolloffMode = (AudioRolloffMode)1; sound.loop = true; sound.volume = 0f; sound.outputAudioMixerGroup = Plugin.EffectsMixer; if (!Object.op_Implicit((Object)(object)clip)) { float[] array = FuseAudio.Create(); clip = AudioClip.Create("Hemp fuse sizzle", array.Length, 1, 22050, false); typeof(AudioClip).GetMethod("SetData", new Type[2] { typeof(float[]), typeof(int) }).Invoke(clip, new object[2] { array, 0 }); } sound.clip = clip; } } public void SetBurning(bool value, float remaining) { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (!value && !Object.op_Implicit((Object)(object)ember)) { return; } Ensure(); if (value != burning) { burning = value; ember.SetActive(value); if (value) { burnDuration = Mathf.Max(0.1f, remaining); sparks.Play(); sound.Play(); } } sound.volume = Mathf.MoveTowards(sound.volume, value ? 0.14f : 0f, Time.unscaledDeltaTime * 0.7f); if (!value && sound.volume <= 0f && sound.isPlaying) { sound.Stop(); } if (value) { float num = Mathf.Clamp01(remaining / burnDuration); ember.transform.localPosition = new Vector3(num * 0.45f - 0.225f, 0.85f, -0.27f); glow.intensity = 0.4f + Mathf.Sin(Time.time * 37f) * 0.12f; sound.pitch = 1.02f - num * 0.1f; } } internal static void Dispose() { if (Object.op_Implicit((Object)(object)clip)) { Object.Destroy((Object)(object)clip); } clip = null; } } public static class LaunchSpread { public static void Offset(int mode, int slot, int seed, out float x, out float z) { if (mode < 0 || mode > 2) { throw new ArgumentOutOfRangeException("mode"); } if (slot < 0) { throw new ArgumentOutOfRangeException("slot"); } x = (z = 0f); switch (mode) { case 0: return; case 1: x = (float)Math.Tan((double)(slot % 5 - 2) * 12.0 * Math.PI / 180.0); return; } uint num = (uint)(seed + slot * -1640531527); double num2 = Unit(Mix(num ^ 0xA511E9B3u)) * Math.PI * 2.0; double num3 = Math.Tan((8.0 + Unit(Mix(num ^ 0x63D83595)) * 17.0) * Math.PI / 180.0); x = (float)(Math.Cos(num2) * num3); z = (float)(Math.Sin(num2) * num3); } private static double Unit(uint value) { return (double)value / 4294967296.0; } private static uint Mix(uint value) { value ^= value >> 16; value *= 2146121005; value ^= value >> 15; value *= 2221713035u; value ^= value >> 16; return value; } } [BepInPlugin("SmeagsMods.SkyforgeFireworks", "Skyforge Fireworks", "0.6.0")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class Register { private static void Postfix(ZNetScene __instance, Dictionary<int, GameObject> ___m_namedPrefabs) { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Expected O, but got Unknown //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) Prefabs.Clear(); Ammunition.Clear(); GameObject prefab = __instance.GetPrefab("fire_pit"); Fireplace val = ((prefab != null) ? prefab.GetComponent<Fireplace>() : null); if ((Object)(object)val == (Object)null) { Note("No campfire effect catalog; registration stopped."); return; } TimberMaterial = (__instance.GetPrefab("wood_pole") ?? __instance.GetPrefab("piece_chest_wood")).GetComponentsInChildren<MeshRenderer>(true).SelectMany((MeshRenderer r) => ((Renderer)r).sharedMaterials).First((Material m) => Object.op_Implicit((Object)(object)m) && ((Object)m).name.IndexOf("wood", StringComparison.OrdinalIgnoreCase) >= 0 && ((Object)m.shader).name.IndexOf("Snow", StringComparison.OrdinalIgnoreCase) < 0); if (Object.op_Implicit((Object)(object)FuseMaterial)) { Object.Destroy((Object)(object)FuseMaterial); } FuseMaterial = new Material(TimberMaterial); if (FuseMaterial.HasProperty("_Color")) { FuseMaterial.SetColor("_Color", new Color(0.72f, 0.54f, 0.28f)); } SparkMaterial = (from r in ((Component)val).GetComponentsInChildren<ParticleSystemRenderer>(true) where Object.op_Implicit((Object)(object)((Renderer)r).sharedMaterial) select ((Renderer)r).sharedMaterial).FirstOrDefault(); GameObject prefab2 = __instance.GetPrefab("sfx_firework_explode"); object effectsMixer; if (prefab2 == null) { effectsMixer = null; } else { AudioSource component = prefab2.GetComponent<AudioSource>(); effectsMixer = ((component != null) ? component.outputAudioMixerGroup : null); } EffectsMixer = (AudioMixerGroup)effectsMixer; if (!Object.op_Implicit((Object)(object)EffectsMixer) && Object.op_Implicit((Object)(object)AudioMan.instance?.m_masterMixer)) { EffectsMixer = AudioMan.instance.m_masterMixer.FindMatchingGroups("SFX").FirstOrDefault(); } string[] obj = new string[6] { "Materials: wood=", ((Object)TimberMaterial).name, " shader=", ((Object)TimberMaterial.shader).name, " sparks=", null }; Material sparkMaterial = SparkMaterial; obj[5] = ((sparkMaterial != null) ? ((Object)sparkMaterial).name : null); Note(string.Concat(obj)); FireworkItem[] fireworkItemList = val.m_fireworkItemList; foreach (FireworkItem val2 in fireworkItemList) { if ((Object)(object)val2.m_fireworkItem != (Object)null && val2.m_fireworkItemCount > 0 && val2.m_fireworksEffects.HasEffects()) { Ammunition[val2.m_fireworkItem.m_itemData.m_shared.m_name] = val2; string[] obj2 = new string[6] { "Ammo ", ((Object)val2.m_fireworkItem).name, " x", null, null, null }; int fireworkItemCount = val2.m_fireworkItemCount; obj2[3] = fireworkItemCount.ToString(); obj2[4] = " -> "; obj2[5] = string.Join(",", val2.m_fireworksEffects.m_effectPrefabs.Select((EffectData e) => (!Object.op_Implicit((Object)(object)e.m_prefab)) ? "null" : ((Object)e.m_prefab).name)); Note(string.Concat(obj2)); } } GameObject val3 = new GameObject("Skyforge prefab storage"); val3.SetActive(false); val3.transform.SetParent(((Component)__instance).transform, false); VikingRocket.Register(__instance, ___m_namedPrefabs, val3.transform); Make(__instance, ___m_namedPrefabs, val3.transform, "Skyforge_Stand", "Launch stand", 0); Make(__instance, ___m_namedPrefabs, val3.transform, "Skyforge_Rack", "Salvo rack", 1); Make(__instance, ___m_namedPrefabs, val3.transform, "Skyforge_FuseBoard", "Show fuse board", 2); AddToHammer(); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class HammerAwake { private static void Postfix() { AddToHammer(); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private static class HammerCopy { private static void Postfix() { AddToHammer(); } } [HarmonyPatch(typeof(Container), "GetHoverText")] private static class ChestHover { private static void Postfix(Container __instance, ref string __result) { FireworkPiece component = ((Component)__instance).GetComponent<FireworkPiece>(); if (Object.op_Implicit((Object)(object)component) && component.Ready) { __result = component.GetHoverText(); } } } [HarmonyPatch(typeof(Container), "Interact")] private static class ChestInteract { private static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result) { FireworkPiece component = ((Component)__instance).GetComponent<FireworkPiece>(); if (!Object.op_Implicit((Object)(object)component) || !component.Ready) { return true; } if (component.Running || alt || FireworkPiece.HasTorch((Player)(object)((character is Player) ? character : null))) { __result = component.Interact(character, hold, alt); return false; } return true; } } [HarmonyPatch(typeof(Container), "UseItem")] private static class ChestItem { private static bool Prefix(Container __instance, Humanoid user, ItemData item, ref bool __result) { FireworkPiece component = ((Component)__instance).GetComponent<FireworkPiece>(); if (!Object.op_Implicit((Object)(object)component)) { return true; } __result = component.UseItem(user, item); return false; } } [HarmonyPatch(typeof(Container), "RPC_RequestOpen")] [HarmonyPatch(typeof(Container), "RPC_RequestStack")] [HarmonyPatch(typeof(Container), "RPC_RequestTakeAll")] private static class ChestLock { private static bool Prefix(Container __instance) { FireworkPiece component = ((Component)__instance).GetComponent<FireworkPiece>(); if (component == null) { return true; } return !component.Running; } } public const string Id = "SmeagsMods.SkyforgeFireworks"; internal static Plugin Instance; internal static readonly Dictionary<string, FireworkItem> Ammunition = new Dictionary<string, FireworkItem>(); internal static readonly List<GameObject> Prefabs = new List<GameObject>(); internal static Material TimberMaterial; internal static Material FuseMaterial; internal static Material SparkMaterial; internal static AudioMixerGroup EffectsMixer; private Harmony harmony; private ConfigEntry<string> savedCarving; internal static void Note(string text) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)text); } private void Awake() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown Instance = this; try { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; savedCarving = ((BaseUnityPlugin)this).Config.Bind<string>("Carving", "RememberedLauncher", "", "Last remembered launcher plan for this local profile. Use Remember carving in game to replace it."); SettingsPanel.LoadCarving(savedCarving.Value); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not load remembered carving; fireworks remain available. " + ex.Message)); } harmony = new Harmony("SmeagsMods.SkyforgeFireworks"); harmony.PatchAll(); Note("Private prototype 0.6.0. Matching mod required on all peers."); } internal bool SaveCarving(ShowSettings plan) { if (savedCarving == null) { return false; } try { savedCarving.Value = CarvingCodec.Encode(plan); ((BaseUnityPlugin)this).Config.Save(); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not save remembered carving; keeping it for this session. " + ex.Message)); return false; } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } SettingsPanel.Dispose(); FuseVisual.Dispose(); if (Object.op_Implicit((Object)(object)FuseMaterial)) { Object.Destroy((Object)(object)FuseMaterial); } } private void OnGUI() { SettingsPanel.Draw(); } private static void Make(ZNetScene scene, Dictionary<int, GameObject> named, Transform root, string id, string label, int kind) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00f9: 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_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = scene.GetPrefab("piece_chest_wood"); if (!Object.op_Implicit((Object)(object)prefab)) { throw new InvalidOperationException("Missing vanilla construction template " + id); } GameObject val = Object.Instantiate<GameObject>(prefab, root, false); ((Object)val).name = id; Piece component = val.GetComponent<Piece>(); component.m_name = label; component.m_description = ((kind == 2) ? "Match rune channels, then light the fuse with a torch. Nearby launchers follow their own timing." : "Load fireworks, set a rune and timing, then light a fuse. Unused ammunition stays in the box."); component.m_category = (PieceCategory)0; component.m_resources = (Requirement[])(object)new Requirement[2] { new Requirement { m_resItem = scene.GetPrefab("Wood").GetComponent<ItemDrop>(), m_amount = ((kind == 1) ? 15 : 8), m_recover = true }, new Requirement { m_resItem = scene.GetPrefab("Resin").GetComponent<ItemDrop>(), m_amount = 2, m_recover = true } }; Container component2 = val.GetComponent<Container>(); if (Object.op_Implicit((Object)(object)component2)) { component2.m_name = label; component2.m_width = ((kind == 0) ? 2 : 4); component2.m_height = 2; component2.m_privacy = (PrivacySetting)2; } if (kind == 2) { Object.DestroyImmediate((Object)(object)component2); foreach (Transform item in val.transform) { ((Component)item).gameObject.SetActive(false); } WearNTear component3 = val.GetComponent<WearNTear>(); component3.m_new = null; component3.m_worn = null; component3.m_broken = null; component3.m_wet = null; component3.m_snow = null; component3.m_snowWorn = null; component3.m_snowBroken = null; Material timberMaterial = TimberMaterial; BuildPart(val.transform, (PrimitiveType)3, "Timber board", new Vector3(0f, 0.75f, 0f), new Vector3(1.25f, 0.8f, 0.16f), timberMaterial); BuildPart(val.transform, (PrimitiveType)3, "Left leg", new Vector3(-0.45f, 0.35f, 0f), new Vector3(0.14f, 0.7f, 0.14f), timberMaterial); BuildPart(val.transform, (PrimitiveType)3, "Right leg", new Vector3(0.45f, 0.35f, 0f), new Vector3(0.14f, 0.7f, 0.14f), timberMaterial); } else { Material timberMaterial2 = TimberMaterial; int num = ((kind == 0) ? 1 : 5); for (int i = 0; i < num; i++) { BuildPart(val.transform, (PrimitiveType)2, "Launch tube", new Vector3(((float)i - (float)(num - 1) * 0.5f) * 0.22f, 0.9f, 0f), new Vector3(0.17f, 0.42f, 0.17f), timberMaterial2); } } BuildPart(val.transform, (PrimitiveType)2, "Hemp fuse", new Vector3(0f, 0.85f, -0.25f), new Vector3(0.035f, 0.28f, 0.035f), FuseMaterial).transform.localRotation = Quaternion.Euler(0f, 0f, 90f); val.AddComponent<FireworkPiece>().Kind = kind; val.SetActive(true); Prefabs.Add(val); scene.m_prefabs.Add(val); named.Add(StringExtensionMethods.GetStableHashCode(id), val); Note("Registered " + id); } private static GameObject BuildPart(Transform parent, PrimitiveType type, string name, Vector3 at, Vector3 scale, Material material) { //IL_0000: 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_002d: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive(type); ((Object)val).name = name; val.transform.SetParent(parent, false); val.transform.localPosition = at; val.transform.localScale = scale; val.layer = ((Component)parent).gameObject.layer; if (Object.op_Implicit((Object)(object)material)) { val.GetComponent<Renderer>().sharedMaterial = material; } return val; } private static void AddToHammer() { ObjectDB instance = ObjectDB.instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } GameObject itemPrefab = instance.GetItemPrefab("Hammer"); PieceTable val = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); if (!Object.op_Implicit((Object)(object)val)) { return; } val.m_pieces.RemoveAll((GameObject p) => !Object.op_Implicit((Object)(object)p)); foreach (GameObject prefab in Prefabs) { if (Object.op_Implicit((Object)(object)prefab) && !val.m_pieces.Contains(prefab)) { val.m_pieces.Add(prefab); } } } } internal static class SettingsPanel { [HarmonyPatch(typeof(Player), "TakeInput")] private static class PlayerInput { private static void Postfix(ref bool __result) { if (Object.op_Implicit((Object)(object)Target) || Time.frameCount <= SuppressThrough) { __result = false; } } } [HarmonyPatch(typeof(PlayerController), "TakeInput")] private static class ControllerInput { private static void Postfix(ref bool __result) { if (Object.op_Implicit((Object)(object)Target) || Time.frameCount <= SuppressThrough) { __result = false; } } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] private static class Cursor { private static bool Prefix() { if (!Object.op_Implicit((Object)(object)Target)) { return true; } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); return false; } } internal static FireworkPiece Target; private static ShowSettings settings; private static bool recoveredInvalid; private static ShowSettings carving; private static GUIStyle panelStyle; private static GUIStyle textStyle; private static GUIStyle titleStyle; private static GUIStyle buttonStyle; private static Texture2D panelTexture; private static List<FireworkPiece.PreviewRow> preview; private static Vector2 scroll; private static Vector2 contentScroll; private static float refreshAt; private static int previewRune; private static int previewPreset; private static int stock; internal static int SuppressThrough; internal static bool CarvingSaved { get; private set; } internal static void Open(FireworkPiece piece) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) Target = piece; settings = piece.Settings; recoveredInvalid = !settings.Valid; if (recoveredInvalid) { settings = new ShowSettings(); } preview = null; refreshAt = 0f; scroll = (contentScroll = Vector2.zero); } internal static void LoadCarving(string text) { CarvingSaved = CarvingCodec.TryDecode(text, out carving); if (!CarvingSaved && !string.IsNullOrEmpty(text)) { Plugin.Note("Ignored invalid remembered carving; use Remember carving to replace it."); } } internal static void Remember() { carving = settings.Copy(); CarvingSaved = Plugin.Instance.SaveCarving(carving); } internal static void Recall() { if (carving != null) { settings = carving.Copy(); } } internal static void Close() { Target = null; SuppressThrough = Time.frameCount + 2; } internal static void Dispose() { Close(); carving = null; CarvingSaved = false; if (Object.op_Implicit((Object)(object)panelTexture)) { Object.Destroy((Object)(object)panelTexture); } panelStyle = null; } private static void Styles() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_006a: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00fb: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown if (panelStyle == null) { panelTexture = new Texture2D(1, 1); panelTexture.SetPixel(0, 0, new Color(0.1f, 0.065f, 0.035f, 1f)); panelTexture.Apply(); panelStyle = new GUIStyle(GUI.skin.box) { padding = new RectOffset(20, 20, 12, 12) }; panelStyle.normal.background = panelTexture; textStyle = new GUIStyle(GUI.skin.label) { fontSize = 18, wordWrap = true }; textStyle.normal.textColor = new Color(0.92f, 0.87f, 0.76f); titleStyle = new GUIStyle(textStyle) { fontSize = 21, fontStyle = (FontStyle)1 }; titleStyle.normal.textColor = new Color(1f, 0.73f, 0.29f); buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 18 }; } } internal static void Draw() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 //IL_0839: Unknown result type (might be due to invalid IL or missing references) //IL_0851: Unknown result type (might be due to invalid IL or missing references) //IL_0856: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Target)) { return; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Target.Ready || Target.Running || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)Target).transform.position) > 8f) { Close(); return; } if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 27) { Event.current.Use(); Close(); return; } Styles(); float num = Mathf.Min(700, Screen.width - 30); float num2 = Mathf.Min(660, Screen.height - 30); GUILayout.BeginArea(new Rect(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, num, num2), panelStyle); GUILayout.Space(8f); GUILayout.Label("SKYFORGE / " + Target.Label.ToUpperInvariant(), titleStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Arrange the show. Light its fuse with your torch.\nFine-tune time by 0.1s with - / +.", textStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(16f); contentScroll = GUILayout.BeginScrollView(contentScroll, Array.Empty<GUILayoutOption>()); if (recoveredInvalid) { GUILayout.Label("Invalid saved arrangement. These are safe draft defaults; Carve settings repairs this piece, Leave unchanged preserves it.", textStyle, Array.Empty<GUILayoutOption>()); } settings.Rune = Mathf.RoundToInt(Slider("Rune channel", settings.Rune, 1f, 8f, "0")); settings.Fuse = Slider((Target.Kind == 2) ? "Show fuse (seconds)" : "Standalone fuse (seconds)", settings.Fuse, 3f, 15f, "0.0"); if (Target.Kind < 2) { GUILayout.Label("Rhythm carving - shots / interval", textStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Opening 4 / 2s", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { settings.ApplyRhythm(0); } if (GUILayout.Button("Volley 8 / 1s", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { settings.ApplyRhythm(1); } if (GUILayout.Button("Finale 12 / 0.5s", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { settings.ApplyRhythm(2); } GUILayout.EndHorizontal(); settings.Delay = Slider("Delay after fuse (seconds)", settings.Delay, 0f, 30f, "0.0"); settings.Interval = Slider("Between shots (seconds)", settings.Interval, 0.5f, 10f, "0.0"); settings.Shots = Mathf.RoundToInt(Slider("Shots", settings.Shots, 1f, 24f, "0")); GUILayout.Label("Burst rune: " + VikingRocket.PatternName(settings.Pattern), textStyle, Array.Empty<GUILayoutOption>()); settings.Pattern = GUILayout.Toolbar(settings.Pattern, new string[5] { "Vanilla", "Bifrost", "World tree", "Mjolnir", "Rune cycle" }, buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }); if (Target.Kind == 1) { GUILayout.Label("Launch direction", textStyle, Array.Empty<GUILayoutOption>()); settings.Spread = GUILayout.Toolbar(settings.Spread, new string[3] { "Straight", "Fan", "Random scatter" }, buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }); GUILayout.Label((settings.Spread == 1) ? "Five tube positions sweep left to right across a 48-degree fan." : ((settings.Spread == 2) ? "Each shot scatters within 25 degrees of upright; no repeated single burst point." : "Classic upright launch. Fan and scatter spread the bursts across the sky."), textStyle, Array.Empty<GUILayoutOption>()); } if (settings.Pattern == 4) { GUILayout.Label("Bifrost > World tree > Mjolnir, repeating from the first shot.", textStyle, Array.Empty<GUILayoutOption>()); } if (Time.unscaledTime >= refreshAt) { stock = Target.AvailableShots(); refreshAt = Time.unscaledTime + 0.5f; } int num3 = Mathf.Min(stock, settings.Shots); GUILayout.Label("Loaded for " + stock + " shots. This plan fires " + num3 + " / " + settings.Shots + ".\n" + ((num3 == 0) ? "Load fireworks before lighting the fuse." : ("Launches +" + (settings.Fuse + settings.Delay).ToString("0.0") + "s to +" + (settings.Fuse + settings.Delay + (float)(num3 - 1) * settings.Interval).ToString("0.0") + "s after lighting.")), textStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Remember carving", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) })) { Remember(); } GUI.enabled = carving != null; if (GUILayout.Button("Recall carving", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) })) { Recall(); } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Label((carving == null) ? "Remember a launcher plan to reuse across game sessions." : (CarvingSaved ? "Carving saved in this profile. Recall previews it; Carve settings applies it." : "Carving remembered for this session only; could not save it. Recall previews it; Carve settings applies it."), textStyle, Array.Empty<GUILayoutOption>()); } else { GUILayout.Label("Premade vanilla show", titleStyle, Array.Empty<GUILayoutOption>()); settings.Preset = GUILayout.SelectionGrid(settings.Preset, Enumerable.Range(0, 6).Select(ShowPresets.Name).ToArray(), 2, buttonStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label(ShowPresets.Description(settings.Preset), textStyle, Array.Empty<GUILayoutOption>()); if (settings.Preset != 0) { GUILayout.Label("Uses only loaded vanilla fireworks. This run overrides shot timing/burst/direction, not your saved launcher arrangements. Carve settings selects the show; a torch starts it.", textStyle, Array.Empty<GUILayoutOption>()); } if (preview == null || previewRune != settings.Rune || previewPreset != settings.Preset || Time.unscaledTime >= refreshAt) { preview = Target.Preview(localPlayer, settings.Rune, settings.Preset); previewRune = settings.Rune; previewPreset = settings.Preset; refreshAt = Time.unscaledTime + 0.5f; } GUILayout.Label(preview.Count((FireworkPiece.PreviewRow p) => p.Included) + " ready launchers / " + preview.Where((FireworkPiece.PreviewRow p) => p.Included).Sum((FireworkPiece.PreviewRow p) => p.Shots) + " loaded shots", titleStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Within 40m, up to 16. Times below are after lighting.\nPreview updates as ammunition changes.", textStyle, Array.Empty<GUILayoutOption>()); scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(190f) }); if (preview.Count == 0) { GUILayout.Label("No accessible launchers on this rune nearby.", textStyle, Array.Empty<GUILayoutOption>()); } foreach (FireworkPiece.PreviewRow item in preview) { string text = (item.Included ? (item.Shots + " / " + item.Planned + " shots: +" + (settings.Fuse + item.Delay).ToString("0.0") + "s to +" + (settings.Fuse + item.Delay + (float)(item.Shots - 1) * item.Interval).ToString("0.0") + "s") : item.Status); GUILayout.Label(item.Name + " (" + item.Distance.ToString("0") + "m) - " + text, textStyle, Array.Empty<GUILayoutOption>()); } GUILayout.EndScrollView(); } GUILayout.EndScrollView(); GUILayout.Space(8f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Carve settings", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(42f) })) { Target.Request(0, settings); Close(); } if (GUILayout.Button("Leave unchanged", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(42f) })) { Close(); } GUILayout.EndHorizontal(); GUILayout.Space(8f); GUILayout.EndArea(); } private static float Slider(string label, float value, float min, float max, string format) { float num = ((format == "0") ? 1f : 0.1f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.Label(value.ToString(format), textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(64f) }); bool enabled = GUI.enabled; GUI.enabled = enabled && value > min; if (GUILayout.Button("-", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(32f), GUILayout.Height(28f) })) { value = Mathf.Clamp(value - num, min, max); } GUI.enabled = enabled && value < max; if (GUILayout.Button("+", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(32f), GUILayout.Height(28f) })) { value = Mathf.Clamp(value + num, min, max); } GUI.enabled = enabled; GUILayout.EndHorizontal(); return Mathf.Round(GUILayout.HorizontalSlider(value, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }) * 10f) / 10f; } } public static class ShowPresets { public static string Name(int preset) { return preset switch { 0 => "Custom arrangement", 1 => "Hearthlight Welcome", 2 => "Fjord Echoes", 3 => "Northern Rain", 4 => "Viking Salute", 5 => "Grand Thing Finale", _ => throw new ArgumentOutOfRangeException("preset"), }; } public static string Description(int preset) { return preset switch { 0 => "Use each launcher's saved timing, burst and direction.", 1 => "Six gentle fan shots per launcher, two seconds apart, with a half-second ripple.", 2 => "Eight fan shots per launcher; paired launchers answer each other in staggered echoes.", 3 => "Ten scattered shots per launcher, one second apart, with a soft stagger.", 4 => "Twelve fan shots per launcher, three-quarter-second beats opening from the centre of the launcher order.", 5 => "Twenty-four scattered shots per launcher, half a second apart, in a tightly staggered finale.", _ => throw new ArgumentOutOfRangeException("preset"), }; } public static ShowSettings Plan(int preset, int index, int count, ShowSettings original) { if (preset < 1 || preset > 5) { throw new ArgumentOutOfRangeException("preset"); } if (count < 1 || count > 16) { throw new ArgumentOutOfRangeException("count"); } if (index < 0 || index >= count) { throw new ArgumentOutOfRangeException("index"); } if (original == null) { throw new ArgumentNullException("original"); } if (!original.Valid) { throw new ArgumentException("Invalid source launcher settings", "original"); } ShowSettings showSettings = original.Copy(); showSettings.Pattern = 0; showSettings.Preset = 0; switch (preset) { case 1: showSettings.Shots = 6; showSettings.Interval = 2f; showSettings.Delay = (float)index * 0.5f; showSettings.Spread = 1; break; case 2: showSettings.Shots = 8; showSettings.Interval = 1.5f; showSettings.Delay = (float)(index % 2) * 0.75f + (float)(index / 2) * 0.25f; showSettings.Spread = 1; break; case 3: showSettings.Shots = 10; showSettings.Interval = 1f; showSettings.Delay = (float)index * 0.2f; showSettings.Spread = 2; break; case 4: showSettings.Shots = 12; showSettings.Interval = 0.75f; showSettings.Delay = Math.Abs((float)index - (float)(count - 1) * 0.5f) * 0.35f; showSettings.Spread = 1; break; case 5: showSettings.Shots = 24; showSettings.Interval = 0.5f; showSettings.Delay = (float)index * 0.1f; showSettings.Spread = 2; break; } return showSettings; } } public sealed class ShowSettings { public int Rune = 1; public int Shots = 6; public int Pattern; public int Spread; public int Preset; public float Delay; public float Interval = 1f; public float Fuse = 6f; public bool Valid { get { if (Spread >= 0 && Spread <= 2 && Preset >= 0 && Preset <= 5 && Pattern >= 0 && Pattern <= 4 && Rune >= 1 && Rune <= 8 && Shots >= 1 && Shots <= 24 && Finite(Delay) && Delay >= 0f && Delay <= 30f && Finite(Interval) && Interval >= 0.5f && Interval <= 10f && Finite(Fuse) && Fuse >= 3f) { return Fuse <= 15f; } return false; } } private static bool Finite(float n) { if (!float.IsNaN(n)) { return !float.IsInfinity(n); } return false; } public long Due(long start, int index) { return start + (long)(((double)Delay + (double)index * (double)Interval) * 10000000.0); } public int BurstAt(int slot) { if (Pattern != 4) { return Pattern; } return 1 + Math.Max(0, slot) % 3; } public ShowSettings Copy() { return new ShowSettings { Rune = Rune, Shots = Shots, Pattern = Pattern, Spread = Spread, Preset = Preset, Delay = Delay, Interval = Interval, Fuse = Fuse }; } public void ApplyRhythm(int rhythm) { if (rhythm < 0 || rhythm > 2) { throw new ArgumentOutOfRangeException("rhythm"); } Shots = rhythm switch { 1 => 8, 0 => 4, _ => 12, }; Interval = rhythm switch { 1 => 1f, 0 => 2f, _ => 0.5f, }; } } public static class ShowRules { public const double LateTolerance = 0.25; public static bool Fresh(long now, long request, long previous) { if (request > previous && request <= now + 10000000) { return request >= now - 30000000; } return false; } public static bool Due(long now, long due) { if (now >= due) { return (double)(now - due) <= 2500000.0; } return false; } public static bool Expired(long now, long due) { return (double)(now - due) > 2500000.0; } } public sealed class VikingRocket : MonoBehaviour { internal static readonly Dictionary<int, GameObject> Prefabs = new Dictionary<int, GameObject>(); internal static readonly HashSet<VikingRocket> Live = new HashSet<VikingRocket>(); private static Material material; private static GameObject launchSound; private static GameObject burstSound; private const float Ascent = 2.8f; private const float Height = 40f; private const float Life = 8f; public int Pattern; private ZNetView view; private ParticleSystem trail; private ParticleSystem burst; private Light glow; private long birth; private bool launchSoundHandled; internal bool HasBurst { get; private set; } internal int EmittedParticles { get; private set; } internal static string PatternName(int pattern) { return pattern switch { 4 => "Rune cycle", 3 => "Mjolnir", 2 => "World tree", 1 => "Bifrost", _ => "Vanilla", }; } internal static void Register(ZNetScene scene, Dictionary<int, GameObject> named, Transform root) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_00f4: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) Prefabs.Clear(); if (Object.op_Implicit((Object)(object)material)) { Object.Destroy((Object)(object)material); } ZSFX[] componentsInChildren = scene.GetPrefab("sfx_firework_explode").GetComponentsInChildren<ZSFX>(true); launchSound = SoundTemplate(((IEnumerable<ZSFX>)componentsInChildren).FirstOrDefault((Func<ZSFX, bool>)((ZSFX s) => s.m_maxDelay <= 0f)), root, "Skyforge launch sound"); burstSound = SoundTemplate(((IEnumerable<ZSFX>)componentsInChildren.OrderByDescending((ZSFX s) => s.m_maxDelay)).FirstOrDefault((Func<ZSFX, bool>)((ZSFX s) => s.m_maxDelay > 0f)), root, "Skyforge burst sound"); if (Object.op_Implicit((Object)(object)Plugin.SparkMaterial)) { material = new Material(Plugin.SparkMaterial); if (material.HasProperty("_TintColor")) { material.SetColor("_TintColor", Color.white); } if (material.HasProperty("_Color")) { material.SetColor("_Color", Color.white); } } ZNetView component = scene.GetPrefab("vfx_Firework_Rocket").GetComponent<ZNetView>(); for (int num = 1; num <= 3; num++) { string text = num switch { 2 => "Skyforge_WorldTreeRocket", 1 => "Skyforge_BifrostRocket", _ => "Skyforge_MjolnirRocket", }; GameObject val = new GameObject(text); val.transform.SetParent(root, false); ZNetView obj = val.AddComponent<ZNetView>(); obj.m_persistent = false; obj.m_distant = true; obj.m_type = component.m_type; TimedDestruction obj2 = val.AddComponent<TimedDestruction>(); obj2.m_timeout = 9f; obj2.m_triggerOnAwake = true; obj2.m_forceTakeOwnershipAndDestroy = true; val.AddComponent<VikingRocket>().Pattern = num; Prefabs.Add(num, val); scene.m_prefabs.Add(val); named.Add(StringExtensionMethods.GetStableHashCode(text), val); } } private static GameObject SoundTemplate(ZSFX source, Transform root, string name) { if (!Object.op_Implicit((Object)(object)source)) { Plugin.Note("Missing native sound template: " + name); return null; } GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, root, false); ((Object)val).name = name; if (Object.op_Implicit((Object)(object)val.GetComponentInChildren<ZNetView>(true))) { Object.Destroy((Object)(object)val); Plugin.Note("Unexpected network sound child; skipped " + name); return null; } ZSFX[] componentsInChildren = val.GetComponentsInChildren<ZSFX>(true); foreach (ZSFX obj in componentsInChildren) { obj.m_minDelay = 0f; obj.m_maxDelay = 0f; } return val; } private void PlaySound(bool burstEvent) { //IL_001f: 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_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_0048: Unknown result type (might be due to invalid IL or missing references) GameObject val = (burstEvent ? burstSound : launchSound); if (Object.op_Implicit((Object)(object)val)) { Object.Instantiate<GameObject>(val, ((Component)this).transform.position + ((Component)this).transform.up * (burstEvent ? 40f : 0f), Quaternion.identity, ((Component)this).transform); } } private void Start() { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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) view = ((Component)this).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)view) || !view.IsValid()) { ((Behaviour)this).enabled = false; return; } if (view.IsOwner() && view.GetZDO().GetLong("SF_birth", 0L) == 0L) { view.GetZDO().Set("SF_birth", FireworkPiece.Now); } Live.Add(this); trail = Particles("Ascending spark", 0.65f, 0.12f, (Pattern == 2) ? new Color(0.35f, 1f, 0.3f) : new Color(0.5f, 0.8f, 1f)); MainModule main = trail.main; ((MainModule)(ref main)).loop = true; EmissionModule emission = trail.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(50f); glow = ((Component)trail).gameObject.AddComponent<Light>(); glow.range = 3f; glow.intensity = 1.4f; glow.color = ((Pattern == 2) ? Color.green : Color.cyan); } private ParticleSystem Particles(string name, float lifetime, float size, Color color) { //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_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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_00ff: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(((Component)this).transform, false); ParticleSystem val2 = val.AddComponent<ParticleSystem>(); val2.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = val2.main; ((MainModule)(ref main)).playOnAwake = false; ((MainModule)(ref main)).loop = false; ((MainModule)(ref main)).duration = 4f; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(lifetime); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(size); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color); ((MainModule)(ref main)).maxParticles = 400; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).enabled = false; ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).enabled = false; ParticleSystemRenderer component = ((Component)val2).GetComponent<ParticleSystemRenderer>(); if (Object.op_Implicit((Object)(object)material)) { ((Renderer)component).sharedMaterial = material; } else { ((Renderer)component).enabled = false; } ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; Gradient val3 = new Gradient(); val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[3] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0.9f, 0.5f), new GradientAlphaKey(0f, 1f) }); ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val3); return val2; } private void Update() { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view) || !view.IsValid()) { return; } if (birth == 0L) { birth = view.GetZDO().GetLong("SF_birth", 0L); } if (birth == 0L) { return; } float num = Mathf.Max(0f, (float)((double)(FireworkPiece.Now - birth) / 10000000.0)); if (!launchSoundHandled) { launchSoundHandled = true; if (num < 0.4f) { PlaySound(burstEvent: false); } } if (num > 8f) { if (view.IsOwner()) { ZNetScene.instance.Destroy(((Component)this).gameObject); } } else if (num < 2.8f) { ((Component)trail).transform.localPosition = Vector3.up * (40f * num / 2.8f); if (!trail.isPlaying) { trail.Play(); } if (Pattern == 1) { MainModule main = trail.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.HSVToRGB(num * 0.3f % 1f, 0.75f, 1f)); } } else if (!HasBurst) { HasBurst = true; trail.Stop(true, (ParticleSystemStopBehavior)1); ((Behaviour)glow).enabled = false; if (num < 5.8f) { Burst(num - 2.8f); } if (num < 3.2f) { PlaySound(burstEvent: true); } } } private void Emit(Vector3 velocity, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) ParticleSystem obj = burst; EmitParams val = default(EmitParams); ((EmitParams)(ref val)).position = ((Component)this).transform.position + ((Component)this).transform.up * 40f; ((EmitParams)(ref val)).velocity = ((Component)this).transform.rotation * velocity; ((EmitParams)(ref val)).startColor = Color32.op_Implicit(color); ((EmitParams)(ref val)).startLifetime = 3f; ((EmitParams)(ref val)).startSize = ((Pattern == 3) ? 0.7f : 0.19f); obj.Emit(val, 1); EmittedParticles++; } private unsafe void Burst(float catchup) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) burst = Particles("Runic sky burst", 3f, 0.19f, Color.white); MainModule main = burst.main; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0.08f); burst.Play(); if (Pattern == 1) { for (int i = 0; i < 7; i++) { for (int j = 0; j < 28; j++) { float num = (float)j * (float)Math.PI * 2f / 28f; Vector3 val = new Vector3(Mathf.Cos(num), Mathf.Sin(num), Mathf.Cos(num) * (float)(i - 3) * 0.14f); Vector3 velocity = ((Vector3)(ref val)).normalized * (8f + (float)i * 0.5f); Emit(velocity, Color.HSVToRGB((float)i / 7f, 0.85f, 1f)); } } } else if (Pattern == 2) { for (int k = 0; k < 30; k++) { Emit(new Vector3(0f, -8f + (float)k * 15f / 29f, 0f), new Color(1f, 0.75f, 0.22f)); } for (int l = 0; l < 5; l++) { for (int m = 0; m < 6; m++) { for (int n = 1; n <= 8; n++) { float num2 = (9f - (float)l * 1.3f) * (float)n / 8f; float num3 = (float)m * (float)Math.PI / 3f; Emit(new Vector3(Mathf.Cos(num3) * num2, -5f + (float)l * 2.2f + (float)n * 0.25f, Mathf.Sin(num3) * num2), (n == 8) ? new Color(1f, 0.85f, 0.3f) : new Color(0.25f, 1f, 0.42f)); } } } } else if (Pattern == 3) { Color color = default(Color); ((Color)(ref color))..ctor(1f, 0.75f, 0.2f); Color color2 = default(Color); ((Color)(ref color2))..ctor(0.4f, 0.8f, 1f); Stroke(new Vector3(-8f, 2f, 0f), new Vector3(8f, 2f, 0f), 20, color); Stroke(new Vector3(8f, 2f, 0f), new Vector3(8f, 7f, 0f), 20, color); Stroke(new Vector3(8f, 7f, 0f), new Vector3(-8f, 7f, 0f), 20, color); Stroke(new Vector3(-8f, 7f, 0f), new Vector3(-8f, 2f, 0f), 20, color); Stroke(new Vector3(-1f, -8f, 0f), new Vector3(-1f, 2f, 0f), 20, color); Stroke(new Vector3(1f, -8f, 0f), new Vector3(1f, 2f, 0f), 20, color); Stroke(new Vector3(-1f, -8f, 0f), new Vector3(1f, -8f, 0f), 20, color); Stroke(new Vector3(-8f, 4.5f, 0f), new Vector3(8f, 4.5f, 0f), 20, color); int[] array = new int[2] { -1, 1 }; foreach (int num5 in array) { Stroke(new Vector3((float)(num5 * 10), 8f, 0f), new Vector3((float)(num5 * 12), 3f, 0f), 8, color2); Stroke(new Vector3((float)(num5 * 12), 3f, 0f), new Vector3((float)(num5 * 9), 3f, 0f), 8, color2); Stroke(new Vector3((float)(num5 * 9), 3f, 0f), new Vector3((float)(num5 * 11), -3f, 0f), 8, color2); } } if (catchup > 0f) { burst.Simulate(catchup, true, false, false); burst.Play(); } string[] obj = new string[10] { "CUSTOM BURST ", PatternName(Pattern), " zdo=", null, null, null, null, null, null, null }; ZDOID uid = view.GetZDO().m_uid; obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[4] = " particles="; obj[5] = EmittedParticles.ToString(); obj[6] = " birth="; obj[7] = birth.ToString(); obj[8] = " ticks="; obj[9] = FireworkPiece.Now.ToString(); Plugin.Note(string.Concat(obj)); } private void Stroke(Vector3 from, Vector3 to, int count, Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < count; i++) { Emit(Vector3.Lerp(from, to, (float)i / (float)(count - 1)), color); } } private void OnDestroy() { Live.Remove(this); } } }