1
0
Fork 0

Compare commits

..

6 Commits

Author SHA1 Message Date
ivan tkachenko 7730c19de1 Add integration with QMK/VIA keyboard on Framework Laptop 16 2026-03-07 00:31:30 +02:00
ivan tkachenko e1a9957154 Add sources of patches Unity assets 2026-02-19 22:17:08 +02:00
ivan tkachenko 09951704f0 README: Rewrite paragraph about HookahPlace 2026-02-19 22:15:22 +02:00
ivan tkachenko 3df1a555a7 README: Fix typo 2026-02-19 22:14:58 +02:00
ivan tkachenko 544e6c174c Bump version of dependency WaterGun-V70PoweredLights_Fix to 1.1.0
It doesn't quite work on its own: sound and animators are still somehow
missing, so I'm not removing the fixes on my end.
2026-01-24 17:24:31 +02:00
ivan tkachenko 8942b2ee37 Implement a better way to disable tracks while keeping them in JSON 2026-01-23 15:32:33 +02:00
2 changed files with 16 additions and 37 deletions

View File

@ -62,7 +62,7 @@ namespace MuzikaGromche
{ {
var seed = GetCurrentSeed(); var seed = GetCurrentSeed();
var (tracks, season) = GetTracksAndSeason(); var (tracks, season) = GetTracksAndSeason();
int[] weights = tracks.Select(track => track.Weight!.Value).ToArray(); int[] weights = tracks.Select(track => track.Weight.Value).ToArray();
var rwi = new RandomWeightedIndex(weights); var rwi = new RandomWeightedIndex(weights);
var trackId = rwi.GetRandomWeightedIndex(seed); var trackId = rwi.GetRandomWeightedIndex(seed);
var track = tracks[trackId]; var track = tracks[trackId];
@ -87,8 +87,8 @@ namespace MuzikaGromche
// Similar to RandomWeightedIndex: // Similar to RandomWeightedIndex:
// If everything is set to zero, everything is equally possible // If everything is set to zero, everything is equally possible
var allWeightsAreZero = tracks.All(t => t.Weight!.Value == 0); var allWeightsAreZero = tracks.All(t => t.Weight.Value == 0);
bool WeightIsCompatible(ISelectableTrack t) => allWeightsAreZero || t.Weight!.Value > 0; bool WeightIsCompatible(ISelectableTrack t) => allWeightsAreZero || t.Weight.Value > 0;
var compatibleSelectableTracks = tracks var compatibleSelectableTracks = tracks
.Where(track => WeightIsCompatible(track) && track.GetTracks().Any(TimerIsCompatible)) .Where(track => WeightIsCompatible(track) && track.GetTracks().Any(TimerIsCompatible))
@ -101,7 +101,7 @@ namespace MuzikaGromche
} }
// Select track group where at least one track member is compatible // Select track group where at least one track member is compatible
int[] weights = compatibleSelectableTracks.Select(track => track.Weight!.Value).ToArray(); int[] weights = compatibleSelectableTracks.Select(track => track.Weight.Value).ToArray();
var rwi = new RandomWeightedIndex(weights); var rwi = new RandomWeightedIndex(weights);
var trackId = rwi.GetRandomWeightedIndex(seed); var trackId = rwi.GetRandomWeightedIndex(seed);
var selectableTrack = compatibleSelectableTracks[trackId]; var selectableTrack = compatibleSelectableTracks[trackId];
@ -344,7 +344,7 @@ namespace MuzikaGromche
public bool IsExplicit { get; init; } public bool IsExplicit { get; init; }
// How often this track should be chosen, relative to the sum of weights of all tracks. // How often this track should be chosen, relative to the sum of weights of all tracks.
internal ConfigEntry<int>? Weight { get; set; } internal ConfigEntry<int> Weight { get; set; }
internal IAudioTrack[] GetTracks(); internal IAudioTrack[] GetTracks();
@ -587,7 +587,7 @@ namespace MuzikaGromche
public /* required */ Language Language { get; init; } public /* required */ Language Language { get; init; }
public bool IsExplicit { get; init; } = false; public bool IsExplicit { get; init; } = false;
public Season? Season { get; init; } = null; public Season? Season { get; init; } = null;
ConfigEntry<int>? ISelectableTrack.Weight { get; set; } = null; ConfigEntry<int> ISelectableTrack.Weight { get; set; } = null!;
IAudioTrack[] ISelectableTrack.GetTracks() => [this]; IAudioTrack[] ISelectableTrack.GetTracks() => [this];
@ -609,7 +609,7 @@ namespace MuzikaGromche
public /* required */ Language Language { get; init; } public /* required */ Language Language { get; init; }
public bool IsExplicit { get; init; } = false; public bool IsExplicit { get; init; } = false;
public Season? Season { get; init; } = null; public Season? Season { get; init; } = null;
ConfigEntry<int>? ISelectableTrack.Weight { get; set; } = null; ConfigEntry<int> ISelectableTrack.Weight { get; set; } = null!;
public /* required */ IAudioTrack[] Tracks = []; public /* required */ IAudioTrack[] Tracks = [];
@ -1645,14 +1645,11 @@ namespace MuzikaGromche
var button = new GenericButtonConfigItem(section, buttonOptionName, buttonDescription, buttonText, () => var button = new GenericButtonConfigItem(section, buttonOptionName, buttonDescription, buttonText, () =>
{ {
var tracks = Plugin.Tracks.Where(t => t.Language.Equals(language)).ToList(); var tracks = Plugin.Tracks.Where(t => t.Language.Equals(language)).ToList();
var isOff = tracks.All(t => t.Weight == null || t.Weight.Value == 0); var isOff = tracks.All(t => t.Weight.Value == 0);
var newWeight = isOff ? 50 : 0; var newWeight = isOff ? 50 : 0;
foreach (var t in tracks) foreach (var t in tracks)
{ {
if (t.Weight != null) t.Weight.Value = newWeight;
{
t.Weight.Value = newWeight;
}
} }
}); });
LethalConfigManager.AddConfigItem(button); LethalConfigManager.AddConfigItem(button);
@ -2120,10 +2117,7 @@ namespace MuzikaGromche
ChooseTrackDeferred(); ChooseTrackDeferred();
foreach (var track in Plugin.Tracks) foreach (var track in Plugin.Tracks)
{ {
if (track.Weight is { } weight) track.Weight.SettingChanged += ChooseTrackDeferredDelegate;
{
weight.SettingChanged += ChooseTrackDeferredDelegate;
}
} }
Config.SkipExplicitTracks.SettingChanged += ChooseTrackDeferredDelegate; Config.SkipExplicitTracks.SettingChanged += ChooseTrackDeferredDelegate;
base.OnNetworkSpawn(); base.OnNetworkSpawn();
@ -2133,10 +2127,7 @@ namespace MuzikaGromche
{ {
foreach (var track in Plugin.Tracks) foreach (var track in Plugin.Tracks)
{ {
if (track.Weight is { } weight) track.Weight.SettingChanged -= ChooseTrackDeferredDelegate;
{
weight.SettingChanged -= ChooseTrackDeferredDelegate;
}
} }
Config.SkipExplicitTracks.SettingChanged -= ChooseTrackDeferredDelegate; Config.SkipExplicitTracks.SettingChanged -= ChooseTrackDeferredDelegate;
base.OnNetworkDespawn(); base.OnNetworkDespawn();

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MuzikaGromche.Via; namespace MuzikaGromche.Via;
@ -15,43 +14,32 @@ interface ILightshow
class Animations class Animations
{ {
private static CancellationTokenSource? cts;
public static void Flicker(ILightshow lightshow) public static void Flicker(ILightshow lightshow)
{ {
if (cts != null) _ = Task.Run(() => FlickerAsync(lightshow));
{
cts.Cancel();
}
cts = new();
_ = Task.Run(async () => await FlickerAsync(lightshow, cts.Token), cts.Token);
} }
static async ValueTask FlickerAsync(ILightshow lightshow, CancellationToken cancellationToken) static async ValueTask FlickerAsync(ILightshow lightshow)
{ {
await foreach (var on in FlickerAnimationAsync()) await foreach (var on in FlickerAnimationAsync())
{ {
if (cancellationToken.IsCancellationRequested)
{
break;
}
byte brightness = on ? (byte)0xFF : (byte)0x00; byte brightness = on ? (byte)0xFF : (byte)0x00;
lightshow.SetBrightnessOverride(brightness); lightshow.SetBrightnessOverride(brightness);
} }
lightshow.SetBrightnessOverride(null); lightshow.SetBrightnessOverride(null);
} }
// Timestamps (in frames of 60 fps) of state switches, starting with 0 => ON. // Timestamps (in frames of 60 fps) of state switches, starting with 0 => OFF.
private static readonly int[] MansionWallLampFlicker = [ private static readonly int[] MansionWallLampFlicker = [
0, 4, 8, 26, 28, 32, 37, 41, 42, 58, 60, 71, 0, 4, 8, 26, 28, 32, 37, 41, 42, 58, 60, 71,
]; ];
public static async IAsyncEnumerable<bool> FlickerAnimationAsync() public static async IAsyncEnumerable<bool> FlickerAnimationAsync()
{ {
bool lastState = false; bool lastState = true;
int lastFrame = 0; int lastFrame = 0;
const int initialMillisecondsDelay = 4 * 1000 / 60; const int initialMillisecondsDelay = 100;
await Task.Delay(initialMillisecondsDelay); await Task.Delay(initialMillisecondsDelay);
foreach (int frame in MansionWallLampFlicker) foreach (int frame in MansionWallLampFlicker)