1
0
Fork 0

Compare commits

..

6 Commits

Author SHA1 Message Date
ivan tkachenko f77e41bd17 Add integration with QMK/VIA keyboard on Framework Laptop 16 2026-03-07 03:42:09 +02:00
ivan tkachenko 65784e726e Add sources of patches Unity assets 2026-03-07 01:33:39 +02:00
ivan tkachenko 0d44728ef7 README: Rewrite paragraph about HookahPlace 2026-03-07 01:33:39 +02:00
ivan tkachenko d8651ce7db README: Fix typo 2026-03-07 01:33:39 +02:00
ivan tkachenko f15e3a1e3d 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-03-07 01:33:38 +02:00
ivan tkachenko 98244dd3f1 Implement a better way to disable tracks while keeping them in JSON 2026-03-07 01:33:38 +02:00
2 changed files with 37 additions and 16 deletions

View File

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

View File

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