Skip to content

Commit

Permalink
Merge branch 'feature/continues-and-next-command' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
LucHeart committed Sep 23, 2024
2 parents 405c959 + fbe16ca commit 844689f
Show file tree
Hide file tree
Showing 12 changed files with 195 additions and 60 deletions.
2 changes: 1 addition & 1 deletion ShockOsc/Backend/BackendHubManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ await _chatboxService.SendRemoteControlMessage(log.Shocker.Name, sender.Name, se
case ControlType.Shock:
{
pain.LastIntensity = log.Intensity;
pain.LastDuration = log.Duration;
pain.LastDuration = (ushort)log.Duration;
pain.LastExecuted = log.ExecutedAt;

oneShock = true;
Expand Down
6 changes: 3 additions & 3 deletions ShockOsc/Config/BehaviourConf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ public sealed class BehaviourConf
{
public bool RandomIntensity { get; set; }
public bool RandomDuration { get; set; }
public JsonRange DurationRange { get; set; } = new JsonRange { Min = 1000, Max = 5000 };
public JsonRange IntensityRange { get; set; } = new JsonRange { Min = 1, Max = 30 };
public JsonRange<ushort> DurationRange { get; set; } = new JsonRange<ushort> { Min = 1000, Max = 5000 };
public JsonRange<byte> IntensityRange { get; set; } = new JsonRange<byte> { Min = 1, Max = 30 };
public byte FixedIntensity { get; set; } = 50;
public uint FixedDuration { get; set; } = 2000;
public ushort FixedDuration { get; set; } = 2000;
public uint HoldTime { get; set; } = 250;
public uint CooldownTime { get; set; } = 5000;
public BoneHeldAction WhileBoneHeld { get; set; } = BoneHeldAction.Vibrate;
Expand Down
6 changes: 3 additions & 3 deletions ShockOsc/Config/Group.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ public sealed class Group
public bool OverrideIntensity { get; set; }

public bool RandomIntensity { get; set; }
public JsonRange IntensityRange { get; set; } = new JsonRange { Min = 1, Max = 30 };
public JsonRange<byte> IntensityRange { get; set; } = new JsonRange<byte> { Min = 1, Max = 30 };
public byte FixedIntensity { get; set; } = 50;

public bool OverrideDuration { get; set; }
public bool RandomDuration { get; set; }
public JsonRange DurationRange { get; set; } = new JsonRange { Min = 1000, Max = 5000 };
public uint FixedDuration { get; set; } = 2000;
public JsonRange<ushort> DurationRange { get; set; } = new JsonRange<ushort> { Min = 1000, Max = 5000 };
public ushort FixedDuration { get; set; } = 2000;

public bool OverrideCooldownTime { get; set; }
public uint CooldownTime { get; set; } = 5000;
Expand Down
6 changes: 3 additions & 3 deletions ShockOsc/Config/JsonRange.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace OpenShock.ShockOsc.Config;

public class JsonRange
public class JsonRange<T> where T : struct
{
public required uint Min { get; set; }
public required uint Max { get; set; }
public required T Min { get; set; }
public required T Max { get; set; }
}
21 changes: 20 additions & 1 deletion ShockOsc/Models/ProgramGroup.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using OpenShock.SDK.CSharp.Models;
using OpenShock.ShockOsc.Config;
using OpenShock.ShockOsc.OscChangeTracker;
using OpenShock.ShockOsc.Services;
Expand All @@ -9,16 +10,29 @@ public sealed class ProgramGroup
public DateTime LastActive { get; set; }
public DateTime LastExecuted { get; set; }
public DateTime LastVibration { get; set; }
public uint LastDuration { get; set; }
public ushort LastDuration { get; set; }
public byte LastIntensity { get; set; }
public float LastStretchValue { get; set; }
public bool IsGrabbed { get; set; }

/// <summary>
/// Scaled to 0-100
/// </summary>
public byte NextIntensity { get; set; } = 0;

/// <summary>
/// Not scaled, 0-1 float, needs to be scaled to duration limits
/// </summary>
public float NextDuration { get; set; } = 0;

public ChangeTrackedOscParam<bool> ParamActive { get; }
public ChangeTrackedOscParam<bool> ParamCooldown { get; }
public ChangeTrackedOscParam<float> ParamCooldownPercentage { get; }
public ChangeTrackedOscParam<float> ParamIntensity { get; }

public byte LastConcurrentIntensity { get; set; } = 0;
public byte ConcurrentIntensity { get; set; } = 0;
public ControlType ConcurrentType { get; set; } = ControlType.Stop;

public Guid Id { get; }
public string Name { get; }
Expand All @@ -42,5 +56,10 @@ public void Reset()
{
IsGrabbed = false;
LastStretchValue = 0;
ConcurrentType = ControlType.Stop;
ConcurrentIntensity = 0;
LastConcurrentIntensity = 0;
NextIntensity = 0;
NextDuration = 0;
}
}
13 changes: 5 additions & 8 deletions ShockOsc/Services/LiveControlManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private async Task RefreshInternal()
await OnStateUpdated.Raise();
}

public void ControlGroupFramePhysbonePull(ProgramGroup group, byte intensity)
public void ControlGroupFrameCheckLoop(ProgramGroup group, byte intensity, ControlType type)
{
if (group.Id == Guid.Empty)
{
Expand All @@ -171,8 +171,9 @@ public void ControlGroupFramePhysbonePull(ProgramGroup group, byte intensity)

ControlFrame(apiDevice.Shockers
.Where(x => _configManager.Config.OpenShock.Shockers.Any(y => y.Key == x.Id && y.Value.Enabled))
.Select(x => x.Id), liveControlClient, intensity);
.Select(x => x.Id), liveControlClient, intensity, type);
}
return;
}

if (group.ConfigGroup == null)
Expand All @@ -192,17 +193,13 @@ public void ControlGroupFramePhysbonePull(ProgramGroup group, byte intensity)
if (device.Key == null) continue;
if (!LiveControlClients.TryGetValue(device.Key.Value, out var client)) continue;

ControlFrame(device.Select(x => x), client, intensity);
ControlFrame(device.Select(x => x), client, intensity, type);
}
}

private void ControlFrame(IEnumerable<Guid> shockers, IOpenShockLiveControlClient client,
byte vibrationIntensity)
byte vibrationIntensity, ControlType type)
{
var type = _configManager.Config.Behaviour.WhileBoneHeld == BehaviourConf.BoneHeldAction.Shock
? ControlType.Shock
: ControlType.Vibrate;

foreach (var shocker in shockers)
{
client.IntakeFrame(shocker, type, vibrationIntensity);
Expand Down
145 changes: 128 additions & 17 deletions ShockOsc/Services/ShockOsc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ public sealed class ShockOsc
"CooldownPercentage",
"IShock",
"IVibrate",
"ISound"
"ISound",
"CShock",
"NextIntensity",
"NextDuration",
};

public readonly Dictionary<string, object?> ShockOscParams = new();
Expand Down Expand Up @@ -302,6 +305,50 @@ private async Task ReceiveLogic()
var value = received.Arguments.ElementAtOrDefault(0);
switch (action)
{
case "NextIntensity":
if (value is not float nextIntensity)
{
programGroup.NextIntensity = 0;
return;
}

programGroup.NextIntensity = Convert.ToByte(MathUtils.Saturate(nextIntensity) * 100f);
break;

case "NextDuration":
if (value is not float nextDuration)
{
programGroup.NextDuration = 0;
return;
}

programGroup.NextDuration = nextDuration;
break;

case "CShock":
if (value is not float intensity)
{
programGroup.ConcurrentIntensity = 0;
programGroup.ConcurrentType = ControlType.Stop;
return;
}

var scaledIntensity = intensity * 100f;
if(scaledIntensity > 127) break;

programGroup.ConcurrentIntensity = Convert.ToByte(intensity * 100f);

var ctype = action switch
{
"CShock" => ControlType.Shock,
"CVibrate" => ControlType.Vibrate,
"CSound" => ControlType.Sound,
_ => ControlType.Vibrate
};

programGroup.ConcurrentType = ctype;
break;

case "IShock":
case "IVibrate":
case "ISound":
Expand Down Expand Up @@ -413,26 +460,30 @@ private async Task SenderLoopAsync()
}
}

private async Task InstantAction(ProgramGroup programGroup, uint duration, byte intensity, ControlType type,
private async Task InstantAction(ProgramGroup programGroup, ushort duration, byte intensity, ControlType type,
bool exclusive = false)
{
// Intensity is pre scaled to 0 - 100
var actualIntensity = programGroup.NextIntensity == 0 ? intensity : programGroup.NextIntensity;
var actualDuration = programGroup.NextDuration == 0 ? duration : GetScaledDuration(programGroup, programGroup.NextDuration);

if (type == ControlType.Shock)
{
programGroup.LastExecuted = DateTime.UtcNow;
programGroup.LastDuration = duration;
programGroup.LastIntensity = intensity;
programGroup.LastDuration = actualDuration;
programGroup.LastIntensity = actualIntensity;
_oscHandler.ForceUnmute();
_oscHandler.SendParams();
}

programGroup.TriggerMethod = TriggerMethod.None;
var inSeconds = MathF.Round(duration / 1000f, 1).ToString(CultureInfo.InvariantCulture);
var inSeconds = MathF.Round(actualDuration / 1000f, 1).ToString(CultureInfo.InvariantCulture);
_logger.LogInformation(
"Sending {Type} to {GroupName} Intensity: {Intensity} Length:{Length}s Exclusive: {Exclusive}", type,
programGroup.Name, intensity, inSeconds, exclusive);
programGroup.Name, actualIntensity, inSeconds, exclusive);

await _backendHubManager.ControlGroup(programGroup.Id, duration, intensity, type, exclusive);
await _chatboxService.SendLocalControlMessage(programGroup.Name, intensity, duration, type);
await _backendHubManager.ControlGroup(programGroup.Id, actualDuration, actualIntensity, type, exclusive);
await _chatboxService.SendLocalControlMessage(programGroup.Name, actualIntensity, actualDuration, type);
}

private async Task CheckLoop()
Expand Down Expand Up @@ -463,6 +514,20 @@ private async Task CheckLogic()

private async Task CheckProgramGroup(ProgramGroup programGroup, Guid pos, BehaviourConf config)
{
if (programGroup.ConcurrentIntensity != 0)
{
_liveControlManager.ControlGroupFrameCheckLoop(programGroup, GetScaledIntensity(programGroup, programGroup.ConcurrentIntensity), programGroup.ConcurrentType);
programGroup.LastConcurrentIntensity = programGroup.ConcurrentIntensity;
return;
}

if (programGroup.LastConcurrentIntensity != 0)
{
_liveControlManager.ControlGroupFrameCheckLoop(programGroup, 0, ControlType.Stop);
programGroup.LastConcurrentIntensity = 0;
_logger.LogInformation("Stopping");
}

var cooldownTime = _configManager.Config.Behaviour.CooldownTime;
if (programGroup.ConfigGroup is { OverrideCooldownTime: true })
cooldownTime = programGroup.ConfigGroup.CooldownTime;
Expand All @@ -483,7 +548,9 @@ private async Task CheckProgramGroup(ProgramGroup programGroup, Guid pos, Behavi

_logger.LogDebug("Vibrating/Shocking {Shocker} at {Intensity}", pos, pullIntensityTranslated);

_liveControlManager.ControlGroupFramePhysbonePull(programGroup, pullIntensityTranslated);
_liveControlManager.ControlGroupFrameCheckLoop(programGroup, pullIntensityTranslated, _configManager.Config.Behaviour.WhileBoneHeld == BehaviourConf.BoneHeldAction.Shock
? ControlType.Shock
: ControlType.Vibrate);
}

if (programGroup.TriggerMethod == TriggerMethod.None)
Expand Down Expand Up @@ -528,6 +595,50 @@ private async Task CheckProgramGroup(ProgramGroup programGroup, Guid pos, Behavi

InstantAction(programGroup, GetDuration(programGroup), intensity, ControlType.Shock, exclusive);
}

private ushort GetScaledDuration(ProgramGroup programGroup, float scale)
{
scale = MathUtils.Saturate(scale);

if (programGroup.ConfigGroup is not { OverrideDuration: true })
{
// Use global config
var config = _configManager.Config.Behaviour;

if (!config.RandomDuration) return (ushort) (config.FixedDuration * scale);
var rdr = config.DurationRange;
return (ushort)
(MathUtils.LerpUShort(
(ushort)(rdr.Min / DurationStep), (ushort)(rdr.Max / DurationStep), scale)
* DurationStep);
}

// Use group config
var groupConfig = programGroup.ConfigGroup;

if (!groupConfig.RandomDuration) return (ushort) (groupConfig.FixedDuration * scale);
var groupRdr = groupConfig.DurationRange;
return (ushort)(MathUtils.LerpUShort((ushort) (groupRdr.Min / DurationStep),
(ushort)(groupRdr.Max / DurationStep), scale) * DurationStep);
}

private byte GetScaledIntensity(ProgramGroup programGroup, byte intensity)
{
if (programGroup.ConfigGroup is not { OverrideIntensity: true })
{
// Use global config
var config = _configManager.Config.Behaviour;

if (!config.RandomIntensity) return (byte)MathUtils.LerpFloat(0, config.FixedIntensity, intensity / 100f);
return (byte)MathUtils.LerpFloat(config.IntensityRange.Min, config.IntensityRange.Max, intensity / 100f);
}

// Use group config
var groupConfig = programGroup.ConfigGroup;

if (!groupConfig.RandomIntensity) return (byte)MathUtils.LerpFloat(0, groupConfig.FixedIntensity, intensity / 100f);
return (byte)MathUtils.LerpFloat(groupConfig.IntensityRange.Min, groupConfig.IntensityRange.Max, intensity / 100f);
}

private byte GetPhysbonePullIntensity(ProgramGroup programGroup, float stretch)
{
Expand All @@ -548,9 +659,9 @@ private byte GetPhysbonePullIntensity(ProgramGroup programGroup, float stretch)
return (byte)MathUtils.LerpFloat(groupConfig.IntensityRange.Min, groupConfig.IntensityRange.Max, stretch);
}

private const uint DurationStep = 100;
private const ushort DurationStep = 100;

private uint GetDuration(ProgramGroup programGroup)
private ushort GetDuration(ProgramGroup programGroup)
{
if (programGroup.ConfigGroup is not { OverrideDuration: true })
{
Expand All @@ -559,17 +670,17 @@ private uint GetDuration(ProgramGroup programGroup)

if (!config.RandomDuration) return config.FixedDuration;
var rdr = config.DurationRange;
return (uint)(Random.Next((int)(rdr.Min / DurationStep),
(int)(rdr.Max / DurationStep)) * DurationStep);
return (ushort)(Random.Next(rdr.Min / DurationStep,
rdr.Max / DurationStep) * DurationStep);
}

// Use group config
var groupConfig = programGroup.ConfigGroup;

if (!groupConfig.RandomDuration) return groupConfig.FixedDuration;
var groupRdr = groupConfig.DurationRange;
return (uint)(Random.Next((int)(groupRdr.Min / DurationStep),
(int)(groupRdr.Max / DurationStep)) * DurationStep);
return (ushort)(Random.Next(groupRdr.Min / DurationStep,
groupRdr.Max / DurationStep) * DurationStep);
}

private byte GetIntensity(ProgramGroup programGroup)
Expand All @@ -581,7 +692,7 @@ private byte GetIntensity(ProgramGroup programGroup)

if (!config.RandomIntensity) return config.FixedIntensity;
var rir = config.IntensityRange;
var intensityValue = Random.Next((int)rir.Min, (int)rir.Max);
var intensityValue = Random.Next(rir.Min, rir.Max);
return (byte)intensityValue;
}

Expand All @@ -590,7 +701,7 @@ private byte GetIntensity(ProgramGroup programGroup)

if (!groupConfig.RandomIntensity) return groupConfig.FixedIntensity;
var groupRir = groupConfig.IntensityRange;
var groupIntensityValue = Random.Next((int)groupRir.Min, (int)groupRir.Max);
var groupIntensityValue = Random.Next(groupRir.Min, groupRir.Max);
return (byte)groupIntensityValue;
}
}
Loading

0 comments on commit 844689f

Please sign in to comment.