diff --git a/SCHIZO/Commands/DevCommands.cs b/SCHIZO/Commands/DevCommands.cs index 1180f794..288eca8f 100644 --- a/SCHIZO/Commands/DevCommands.cs +++ b/SCHIZO/Commands/DevCommands.cs @@ -1,6 +1,9 @@ +using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using SCHIZO.Commands.Attributes; +using SCHIZO.Commands.Input; using SCHIZO.Commands.Output; using SCHIZO.Helpers; using SCHIZO.Tweaks; @@ -87,4 +90,52 @@ public static void DevMode() else Player.main.gameObject.AddComponent(); } + + [Command(Name = "_get", + DisplayName = "Get static member", + Description = "Get value of a static member", + RegisterConsoleCommand = true)] + public static object PrintField(string typeName, string memberName) + { + Type type = ReflectionCache.GetType(typeName); + if (type is null) return $"Could not find type '{typeName}'"; + MemberInfo[] member = type.GetMember(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + if (member is null) return $"Could not find '{memberName}' in type '{typeName}' (must be static)"; + return ReflectionHelpers.GetStaticMemberValue(member.Single()); + } + + [Command(Name = "_set", + DisplayName = "Set static member", + Description = "Set value of a static member", + RegisterConsoleCommand = true)] + public static object SetField(string typeName, string memberName, string valueStr) + { + Type type = ReflectionCache.GetType(typeName); + if (type is null) return $"Could not find type '{typeName}'"; + MemberInfo member = type.GetMember(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Single(); + if (member is null) return $"Could not find '{memberName}' in type '{typeName}' (must be static)"; + Type memberType = member switch + { + PropertyInfo p => p.PropertyType, + FieldInfo f => f.FieldType, + _ => null + }; + if (memberType is null) return $"'{memberName}' is not a property or field"; + + if (!Conversion.TryParseOrConvert(valueStr, memberType, out object value)) + { + return $"Could not convert '{valueStr}' to type '{memberType}'"; + } + switch (member) + { + case PropertyInfo prop: + prop.SetValue(null, value); + return null; + case FieldInfo field: + field.SetValue(null, value); + return null; + default: + throw new InvalidOperationException("Unreachable"); + } + } } diff --git a/SCHIZO/Resources/AssetBundles/Assets.cs b/SCHIZO/Resources/AssetBundles/Assets.cs index 7240e8f3..1da60707 100644 --- a/SCHIZO/Resources/AssetBundles/Assets.cs +++ b/SCHIZO/Resources/AssetBundles/Assets.cs @@ -12,7 +12,7 @@ namespace SCHIZO.Resources; public static class Assets { - private const int _rnd = 2142497487; + private const int _rnd = -1269642852; private static readonly UnityEngine.AssetBundle _a = ResourceManager.GetAssetBundle("assets"); @@ -26,5 +26,6 @@ public static class Assets public static SCHIZO.Options.Bool.ToggleModOption Mod_Options_EnableAutomaticEvents = _a.LoadAsset("Assets/Mod/Options/Enable automatic events.asset"); public static SCHIZO.Options.Button.ButtonModOption Mod_Options_SwarmControl = _a.LoadAsset("Assets/Mod/Options/Swarm Control.asset"); public static SCHIZO.Registering.ModRegistry Mod_Registry = _a.LoadAsset("Assets/Mod/Registry.asset"); + public static UnityEngine.GameObject Mod_SwarmControl_DeadPixel = _a.LoadAsset("Assets/Mod/Swarm Control/DeadPixel.prefab"); public static UnityEngine.Material Mod_VFX_ARGCensor_ARGcensorMat = _a.LoadAsset("Assets/Mod/VFX/ARG Censor/ARGcensor_mat.mat"); } diff --git a/SCHIZO/Resources/AssetBundles/assets b/SCHIZO/Resources/AssetBundles/assets index 89e608b7..d880795a 100644 Binary files a/SCHIZO/Resources/AssetBundles/assets and b/SCHIZO/Resources/AssetBundles/assets differ diff --git a/SCHIZO/SwarmControl/Redeems/Annoying/DeadPixelRedeem.cs b/SCHIZO/SwarmControl/Redeems/Annoying/DeadPixelRedeem.cs new file mode 100644 index 00000000..68aa0184 --- /dev/null +++ b/SCHIZO/SwarmControl/Redeems/Annoying/DeadPixelRedeem.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using SCHIZO.Commands.Base; +using SCHIZO.Commands.Context; +using SCHIZO.Resources; +using UnityEngine; + +namespace SCHIZO.SwarmControl.Redeems.Annoying; +#nullable enable + +[Redeem( + Name = "redeem_deadpixel", + DisplayName = "Dead Pixel", + Description = "The whole screen is your canvas... Lasts 5 minutes" +)] +internal class DeadPixelRedeem : Command, IParameters +{ + public static float Duration = 300f; + public IReadOnlyList Parameters => []; + + protected override object? ExecuteCore(CommandExecutionContext ctx) + { + Vector2 coords = new(Random.Range(0, 1920), Random.Range(0, 1080)); + GameObject instance = GameObject.Instantiate(Assets.Mod_SwarmControl_DeadPixel); + instance.EnsureComponent().duration = Duration; + instance.transform.SetParent(uGUI.main.screenCanvas.transform, false); + instance.transform.localPosition = new Vector2(coords.x-960, coords.y-540); + return $"Your pixel is at {coords}"; + } +} diff --git a/SCHIZO/SwarmControl/Redeems/Annoying/DetachBackSeatruckModule.cs b/SCHIZO/SwarmControl/Redeems/Annoying/DetachBackSeatruckModule.cs new file mode 100644 index 00000000..e62b1847 --- /dev/null +++ b/SCHIZO/SwarmControl/Redeems/Annoying/DetachBackSeatruckModule.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using SCHIZO.Commands.Base; +using SCHIZO.Commands.Context; +using SCHIZO.Commands.Output; +using UnityEngine; + +namespace SCHIZO.SwarmControl.Redeems.Annoying; + +#nullable enable +[Redeem( + Name = "redeem_detach", + DisplayName = "Bad Glue", + Description = "Whoever designed the Sea Truck module connector should be fired..." +)] +internal class DetachBackSeatruckModule : Command, IParameters +{ + public IReadOnlyList Parameters => []; + + protected override object? ExecuteCore(CommandExecutionContext ctx) + { + if (!Player.main) return CommonResults.Error("Requires a loaded game."); + + SeaTruckUpgrades cabin = GameObject.FindObjectOfType(); + if (!cabin) return CommonResults.Error("Sea Truck not found."); + + SeaTruckSegment cabinSegment = cabin.GetComponent(); + SeaTruckSegment rearSegment = cabinSegment; + while (rearSegment.rearConnection && rearSegment.rearConnection.connection) + rearSegment = rearSegment.rearConnection.connection.truckSegment; + + if (rearSegment == cabinSegment) + return CommonResults.Error("Sea Truck not connected to any modules."); + + rearSegment.Detach(); + + return CommonResults.OK(); + } +} diff --git a/SCHIZO/SwarmControl/Redeems/Annoying/ShowNotif.cs b/SCHIZO/SwarmControl/Redeems/Annoying/ShowNotif.cs index d392feb2..fca9ac06 100644 --- a/SCHIZO/SwarmControl/Redeems/Annoying/ShowNotif.cs +++ b/SCHIZO/SwarmControl/Redeems/Annoying/ShowNotif.cs @@ -4,8 +4,8 @@ using SCHIZO.Commands.Output; namespace SCHIZO.SwarmControl.Redeems.Annoying; -#nullable enable +#nullable enable [Redeem( Name = "redeem_notif", DisplayName = "Ping Alex", @@ -24,10 +24,10 @@ internal class ShowNotif : Command, IParameters "OperationCanceledException: The operation was canceled.", "The parameter is incorrect", """ - System.Net.WebSockets.WebSocketException (0x80004005): The 'System.Net.WebSockets.ServerWebSocket' instance cannot be used for communication because it has been transitioned into the 'Aborted' state. - ---> System.Net.WebSockets.WebSocketException (0x80004005): An internal WebSocket error occurred. Please see the innerException, if present, for more details. ---> System.Net.HttpListenerException (0x80004005): An operation was attempted on a nonexistent network connection - at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs) - at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.d__9.MoveNext() + System.Net.WebSockets.WebSocketException (0x80004005): The 'System.Net.WebSockets.ClientWebSocket' instance cannot be used for communication because it has been transitioned into the 'Aborted' state. + ---> System.Net.WebSockets.WebSocketException (0x80004005): An internal WebSocket error occurred. Please see the innerException, if present, for more details. ---> System.Net.HttpClientException (0x80004005): An operation was attempted on a nonexistent network connection + at System.Net.WebSockets.WebSocketHttpClientDuplexStream.WriteAsyncFast(HttpClientAsyncEventArgs eventArgs) + at System.Net.WebSockets.WebSocketHttpClientDuplexStream.d__9.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) diff --git a/SCHIZO/SwarmControl/Redeems/Misc/BigErm.cs b/SCHIZO/SwarmControl/Redeems/Misc/BigErm.cs index 625d370f..6b1cfe79 100644 --- a/SCHIZO/SwarmControl/Redeems/Misc/BigErm.cs +++ b/SCHIZO/SwarmControl/Redeems/Misc/BigErm.cs @@ -18,7 +18,7 @@ namespace SCHIZO.SwarmControl.Redeems.Misc; #nullable enable [Redeem(Name = "redeem_bigerm", DisplayName = "Big Erm", - Description = "It's time to Get Big" + Description = "The Erm Moon sends its regards" )] internal class BigErm : Command, IParameters { diff --git a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/AddSignalRedeem.cs b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/AddSignalRedeem.cs index 95afa4ea..f4f030c5 100644 --- a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/AddSignalRedeem.cs +++ b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/AddSignalRedeem.cs @@ -1,38 +1,46 @@ +using System.Collections; using System.Collections.Generic; using SCHIZO.Commands.Base; +using SCHIZO.Commands.Context; using SCHIZO.Commands.Input; +using SCHIZO.Commands.Output; +using SCHIZO.Twitch; +using SwarmControl.Models.Game.Messages; using UnityEngine; +using UWE; namespace SCHIZO.SwarmControl.Redeems.PayAttentionToMeStreamer; #nullable enable [Redeem( Name = "redeem_addsignal", - DisplayName = "Add Beacon", - Description = "Adds a beacon ping to the map." + DisplayName = "Add Signal", + Description = "Adds a signal marker to the world. After redeeming, your next Twitch chat message will name the beacon." )] -internal class AddSignalRedeem() : ProxyCommand("addsignal") +internal class AddSignalRedeem : Command, IParameters { - public override IReadOnlyList Parameters { get; } = [ - new Parameter(new("coords", "Coordinates", "Beacon coordinates"), typeof(Vector3), false), - new Parameter(new("name", "Name", "Beacon name"), typeof(string), false) + public IReadOnlyList Parameters { get; } = [ + new Parameter(new("coords", "Coordinates", "Beacon coordinates"), typeof(Vector3), false) ]; - protected override Dictionary? GetTargetArgs(Dictionary? proxyArgs) + protected override object? ExecuteCore(CommandExecutionContext ctx) { - if (proxyArgs is null) return []; - - NamedArgs args = new(proxyArgs); - Dictionary targetArgs = []; - if (!args.TryGetValue("coords", out Vector3 coords) || !args.TryGetValue("name", out string? name)) - return targetArgs; + RedeemMessage? model = (ctx.Input as RemoteInput)?.Model; + TwitchUser? user = model?.User; + if (user is null) + return CommonResults.Error("Could not get user"); + if (!ctx.Input.GetNamedArguments().TryGetValue("coords", out Vector3 coords)) + return CommonResults.Error("Invalid coordinates"); + CoroutineHost.StartCoroutine(Coro(user, coords)); + return "Success - the next message you send in Twitch chat will be used to name the beacon."; + } - return new() - { - { "x", coords.x }, - { "y", coords.y }, - { "z", coords.z }, - { "signalName", name } - }; + private IEnumerator Coro(TwitchUser user, Vector3 coords) + { + string? message = null; + TwitchIntegration.AddNextMessageCallback(user, (msg) => message = msg ?? "(unnamed)"); + yield return new WaitUntil(() => message is { }); + CustomSignalManager.AddSignal(coords.x, coords.y, coords.z, + $"[{user.DisplayName}]\n{message}"); } } diff --git a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Hint.cs b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Hint.cs index 7582e3b4..3b42206f 100644 --- a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Hint.cs +++ b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Hint.cs @@ -1,46 +1,42 @@ +using System.Collections; using System.Collections.Generic; +using SCHIZO.Commands; using SCHIZO.Commands.Base; using SCHIZO.Commands.Context; using SCHIZO.Commands.Input; -using SwarmControl.Models.Game; +using SCHIZO.Commands.Output; +using SwarmControl.Models.Game.Messages; +using UnityEngine; +using UWE; namespace SCHIZO.SwarmControl.Redeems.PayAttentionToMeStreamer; #nullable enable [Redeem( Name = "redeem_hint", - DisplayName = "Send Hint", - Description = "Display a message in the center of the screen", + DisplayName = "Send Message", + Description = "Your next Twitch chat message will be displayed in-game", Announce = false // the message itself is the announcement )] -internal class Hint() : ProxyCommand("hint") +internal class Hint : Command, IParameters { - public override IReadOnlyList Parameters => [ - new TextParameter(new NamedModel("message", "Message", "The message to display")) { - MinLength = 1 - } - ]; + public IReadOnlyList Parameters => []; - protected override JsonContext GetContextForTarget(JsonContext proxyCtx) + protected override object? ExecuteCore(CommandExecutionContext ctx) { - RemoteInput input = proxyCtx.JsonInput; - input.Model.Announce = false; - string submitter = input.Model.GetDisplayName(); - NamedArgs args = input.GetNamedArguments(); - args.TryGetValue("message", out string? message); - if (string.IsNullOrWhiteSpace(message)) - message = "(no message)"; - args["message"] = $"{submitter}: {message}"; - return base.GetContextForTarget(proxyCtx); + RedeemMessage? model = (ctx.Input as RemoteInput)?.Model; + TwitchUser? user = model?.User; + if (user is null) + return CommonResults.Error("Could not get user"); + CoroutineHost.StartCoroutine(Coro(user)); + return "Success - the next message you send in Twitch chat will be displayed in-game."; } - protected override Dictionary GetTargetArgs(Dictionary? proxyArgs) + private IEnumerator Coro(TwitchUser user) { - if (proxyArgs is null) return []; - - return new Dictionary - { - { "message", proxyArgs["message"] } - }; + string? message = null; + Twitch.TwitchIntegration.AddNextMessageCallback(user, (msg) => message = msg ?? "(no message)"); + yield return new WaitUntil(() => message is { }); + DevCommands.Hint($"{user.DisplayName}: {message}"); } } diff --git a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/NameTagErmfish.cs b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/NameTagErmfish.cs index 3d1abf03..3edd2182 100644 --- a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/NameTagErmfish.cs +++ b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/NameTagErmfish.cs @@ -47,11 +47,8 @@ protected override object ExecuteCore(CommandExecutionContext ctx) .Select(tag => tag.gameObject) .FirstOrDefault(erm => { - NameTag tag = erm.GetComponentInChildren(); - if (!tag) return false; - if (!string.IsNullOrWhiteSpace(tag.textMesh.text)) return false; - - return true; + NameTag tag = erm.GetComponentInChildren(true); + return tag && !tag.isActiveAndEnabled; }); RemoteInput? input = ctx.Input as RemoteInput; @@ -91,10 +88,10 @@ private IEnumerator SpawnCoro(string? user) private void SetNameTag(GameObject ermfish, string? user) { - NameTag tag = ermfish.GetComponentInChildren(); - if (!tag) return; - if (!string.IsNullOrWhiteSpace(tag.textMesh.text)) return; + NameTag tag = ermfish.GetComponentInChildren(true); + if (!tag || tag.isActiveAndEnabled) return; tag.textMesh.text = user; + tag.gameObject.SetActive(true); } } diff --git a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Say.cs b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Say.cs index a4bf1ef7..b4ace120 100644 --- a/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Say.cs +++ b/SCHIZO/SwarmControl/Redeems/PayAttentionToMeStreamer/Say.cs @@ -11,6 +11,7 @@ namespace SCHIZO.SwarmControl.Redeems.PayAttentionToMeStreamer; Name = "redeem_say", DisplayName = "Send Text", Description = "Display text in the top left of the screen", + Export = false, /// deprecated in favor of Announce = false // the message itself is the announcement )] internal class Say() : ProxyCommand("say") diff --git a/SCHIZO/SwarmControl/SwarmControlManager.cs b/SCHIZO/SwarmControl/SwarmControlManager.cs index 47c0b2e6..150fe119 100644 --- a/SCHIZO/SwarmControl/SwarmControlManager.cs +++ b/SCHIZO/SwarmControl/SwarmControlManager.cs @@ -102,14 +102,17 @@ private static void SetKey(string key) } [Command(Name = "sc_rc", RegisterConsoleCommand = true)] - private static void ManualReconnect() + private static void ManualReconnectCommand() { - Task.Run(async () => - { - await Instance._socket.Disconnect(); - if (!await Instance._socket.ConnectSocket()) - LOGGER.LogError("Manual reconnect failed"); - }); + _ = Instance.ManualReconnect(); + } + + private async Task ManualReconnect() + { + await _socket.Disconnect(); + if (!await _socket.ConnectSocket()) + QueueOnMainThread(() => LOGGER.LogWarning("Manual reconnect failed")); + _reconnectCoro ??= StartCoroutine(AutoReconnectCoro()); } private void ButtonPressed() @@ -161,7 +164,11 @@ private IEnumerator ConnectCoro(CancellationToken ct) private void Disconnect() { - if (_reconnectCoro is { }) StopCoroutine(_reconnectCoro); + if (_reconnectCoro is { }) + { + StopCoroutine(_reconnectCoro); + _reconnectCoro = null; + } if (!_socket.IsConnected) return; StartCoroutine(DisconnectCoro()); } diff --git a/SCHIZO/Twitch/CustomSignalManager.cs b/SCHIZO/Twitch/CustomSignalManager.cs index 20aa7840..727a77b1 100644 --- a/SCHIZO/Twitch/CustomSignalManager.cs +++ b/SCHIZO/Twitch/CustomSignalManager.cs @@ -87,7 +87,7 @@ public static object AddSignal(float x, float y, float z, [TakeRemaining] string return CommonResults.Error("developer forgor prefab for custom signal, please point and laugh"); if (string.IsNullOrEmpty(signalName)) return CommonResults.ShowUsage(); - if (_allSignals.ContainsKey(signalName)) + if (_allSignals.ContainsKey(signalName) || _customSignals.ContainsKey(signalName)) return CommonResults.Error($"Signal \"{signalName}\" already exists"); Vector3 pos = new(x, y, z); diff --git a/SCHIZO/Twitch/TwitchIntegration.cs b/SCHIZO/Twitch/TwitchIntegration.cs index 362aef3a..3b947337 100644 --- a/SCHIZO/Twitch/TwitchIntegration.cs +++ b/SCHIZO/Twitch/TwitchIntegration.cs @@ -1,8 +1,11 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Threading.Tasks; using SCHIZO.Commands.Attributes; using SCHIZO.Helpers; +using SCHIZO.SwarmControl; +using SwarmControl.Models.Game.Messages; using TwitchLib.Client; using TwitchLib.Client.Events; using TwitchLib.Client.Models; @@ -40,6 +43,7 @@ private void Awake() _client.OnJoinedChannel += (_, evt) => LOGGER.LogInfo($"Joined Twitch channel {evt.Channel}"); _client.OnFailureToReceiveJoinConfirmation += (_, evt) => LOGGER.LogError($"Could not join Twitch channel: {evt.Exception.Details}"); _client.OnMessageReceived += Client_OnMessageReceived; + _client.OnUserTimedout += Client_OnTimeoutReceived; string username = PlayerPrefs.GetString(_usernamePlayerPrefsKey, ""); string token = PlayerPrefs.GetString(_tokenPlayerPrefsKey, ""); @@ -56,10 +60,17 @@ private void Awake() _client.Connect(); } + private void Client_OnTimeoutReceived(object sender, OnUserTimedoutArgs e) + { + if (!_timeoutCallbacks.TryRemove(e.UserTimeout.TargetUserId, out Action cb)) return; + SwarmControlManager.Instance.QueueOnMainThread(cb); + } + private void Client_OnMessageReceived(object _, OnMessageReceivedArgs evt) { ChatMessage message = evt.ChatMessage; - + TwitchUser user = new(message.UserId, message.Username, message.DisplayName); + InvokeCallbacksOnMessage(user, message.Message); if (!IsUserWhitelisted(message.Username)) return; // ensure I don't get isekaid if (!CheckPrefix(message.Message)) return; @@ -99,4 +110,39 @@ public static string SetTwitchLogin(string username, string token) PlayerPrefs.SetString(_tokenPlayerPrefsKey, token); return "Twitch login updated. Please restart Subnautica."; } + + private static ConcurrentDictionary Callback, float ModerationDelay)> _nextMessageCallbacks = []; + private static ConcurrentDictionary _timeoutCallbacks = []; + public static void AddNextMessageCallback(TwitchUser user, Action callback, float moderationDelay = 5f) + { + _nextMessageCallbacks.AddOrUpdate(user.Id, (callback, moderationDelay), (_, existing) => + { + // i love delegates + existing.Callback += callback; + existing.ModerationDelay = Mathf.Max(existing.ModerationDelay, moderationDelay); + return existing; + }); + } + + private static void InvokeCallbacksOnMessage(TwitchUser user, string message) + { + if (!_nextMessageCallbacks.TryRemove(user.Id, out (Action callback, float delay) existing)) + return; + + if (existing.delay <= 0) + { + SwarmControlManager.Instance.QueueOnMainThread(() => existing.callback(message)); + return; + } + bool timedOut = false; + Action cb = () => timedOut = true; + _timeoutCallbacks.AddOrUpdate(user.Id, cb, (_, existing) => existing + cb); + Task.Delay(TimeSpan.FromSeconds(existing.delay)).ContinueWith(t => + { + _timeoutCallbacks.TryRemove(user.Id, out _); + if (timedOut) + message = "(filtered)"; + SwarmControlManager.Instance.QueueOnMainThread(() => existing.callback(message)); + }); + } } diff --git a/Unity/Assets/Mod/Ermfish/Ermfish.prefab b/Unity/Assets/Mod/Ermfish/Ermfish.prefab index 81997f66..2a5da41d 100644 --- a/Unity/Assets/Mod/Ermfish/Ermfish.prefab +++ b/Unity/Assets/Mod/Ermfish/Ermfish.prefab @@ -565,6 +565,11 @@ PrefabInstance: propertyPath: m_Name value: NameTag objectReference: {fileID: 0} + - target: {fileID: 1798442205062231381, guid: e0c81479ecf70ff4bbc5d8cdbf5653ce, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} - target: {fileID: 2229945086217208043, guid: e0c81479ecf70ff4bbc5d8cdbf5653ce, type: 3} propertyPath: m_FontSize @@ -640,6 +645,11 @@ PrefabInstance: propertyPath: m_text value: ' ' objectReference: {fileID: 0} + - target: {fileID: 6243598954101647917, guid: e0c81479ecf70ff4bbc5d8cdbf5653ce, + type: 3} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} - target: {fileID: 6243598954101647917, guid: e0c81479ecf70ff4bbc5d8cdbf5653ce, type: 3} propertyPath: m_fontSizeBase diff --git a/Unity/Assets/Mod/Swarm Control/DeadPixel.prefab b/Unity/Assets/Mod/Swarm Control/DeadPixel.prefab new file mode 100644 index 00000000..9bae7068 --- /dev/null +++ b/Unity/Assets/Mod/Swarm Control/DeadPixel.prefab @@ -0,0 +1,90 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &370268358655551518 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8595100206946119668} + - component: {fileID: 7925771296604569977} + - component: {fileID: 4135815620925489650} + - component: {fileID: 7630312927154394080} + m_Layer: 5 + m_Name: DeadPixel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8595100206946119668 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 370268358655551518} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 5, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7925771296604569977 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 370268358655551518} + m_CullTransparentMesh: 0 +--- !u!114 &4135815620925489650 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 370268358655551518} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 1, b: 0.060247898, a: 1} + m_RaycastTarget: 0 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 9f9a2f24f32f06243a3ad50de2ade03d, type: 3} + m_Type: 3 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &7630312927154394080 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 370268358655551518} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b0aec18254efcbe47ac7484ebfd66ffd, type: 3} + m_Name: + m_EditorClassIdentifier: + duration: 300 diff --git a/Unity/Assets/Mod/Swarm Control/DeadPixel.prefab.meta b/Unity/Assets/Mod/Swarm Control/DeadPixel.prefab.meta new file mode 100644 index 00000000..e733a4ad --- /dev/null +++ b/Unity/Assets/Mod/Swarm Control/DeadPixel.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dce507ca4441db349a7e99b99efa4052 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: assets + assetBundleVariant: diff --git a/Unity/Assets/Mod/Swarm Control/New Sprite.prefab b/Unity/Assets/Mod/Swarm Control/New Sprite.prefab new file mode 100644 index 00000000..d6553b1f --- /dev/null +++ b/Unity/Assets/Mod/Swarm Control/New Sprite.prefab @@ -0,0 +1,83 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &586529522683886146 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6963744918765121955} + - component: {fileID: 4283795455305002051} + m_Layer: 0 + m_Name: New Sprite + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6963744918765121955 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 586529522683886146} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &4283795455305002051 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 586529522683886146} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: 9f9a2f24f32f06243a3ad50de2ade03d, type: 3} + m_Color: {r: 0, g: 1, b: 0.14361954, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 diff --git a/Unity/Assets/Mod/Swarm Control/New Sprite.prefab.meta b/Unity/Assets/Mod/Swarm Control/New Sprite.prefab.meta new file mode 100644 index 00000000..a316c50e --- /dev/null +++ b/Unity/Assets/Mod/Swarm Control/New Sprite.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2c20a5a42f7278b45b026e249af3045f +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Mod/Swarm Control/Square.png b/Unity/Assets/Mod/Swarm Control/Square.png new file mode 100644 index 00000000..8eb1b1ec Binary files /dev/null and b/Unity/Assets/Mod/Swarm Control/Square.png differ diff --git a/Unity/Assets/Mod/Swarm Control/Square.png.meta b/Unity/Assets/Mod/Swarm Control/Square.png.meta new file mode 100644 index 00000000..a7b872fa --- /dev/null +++ b/Unity/Assets/Mod/Swarm Control/Square.png.meta @@ -0,0 +1,100 @@ +fileFormatVersion: 2 +guid: 9f9a2f24f32f06243a3ad50de2ade03d +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 3 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 4 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 4 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: + - - {x: -2, y: -2} + - {x: 2, y: -2} + - {x: 2, y: 2} + - {x: -2, y: 2} + physicsShape: + - - {x: -2, y: -2} + - {x: 2, y: -2} + - {x: 2, y: 2} + - {x: -2, y: 2} + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Mod/Twitch/TwitchManager.prefab b/Unity/Assets/Mod/Twitch/TwitchManager.prefab index 6f653be1..57c52da7 100644 --- a/Unity/Assets/Mod/Twitch/TwitchManager.prefab +++ b/Unity/Assets/Mod/Twitch/TwitchManager.prefab @@ -51,7 +51,6 @@ MonoBehaviour: whitelistedUsers: - alexejherodev - govorunb - - heiroflife1 --- !u!114 &5996699951319224428 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Unity/Assets/Scripts/SCHIZO/SwarmControl/DeadPixel.cs b/Unity/Assets/Scripts/SCHIZO/SwarmControl/DeadPixel.cs new file mode 100644 index 00000000..8c0edc37 --- /dev/null +++ b/Unity/Assets/Scripts/SCHIZO/SwarmControl/DeadPixel.cs @@ -0,0 +1,16 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace SCHIZO.SwarmControl +{ + [RequireComponent(typeof(Image))] + [AddComponentMenu("SCHIZO/SwarmControl/Dead Pixel")] + public sealed class DeadPixel : MonoBehaviour + { + public float duration; + private void Start() + { + Destroy(gameObject, duration); + } + } +} \ No newline at end of file diff --git a/Unity/Assets/Scripts/SCHIZO/SwarmControl/DeadPixel.cs.meta b/Unity/Assets/Scripts/SCHIZO/SwarmControl/DeadPixel.cs.meta new file mode 100644 index 00000000..c03c5231 --- /dev/null +++ b/Unity/Assets/Scripts/SCHIZO/SwarmControl/DeadPixel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0aec18254efcbe47ac7484ebfd66ffd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: