Skip to content

Commit 844689f

Browse files
committed
Merge branch 'feature/continues-and-next-command' into develop
2 parents 405c959 + fbe16ca commit 844689f

File tree

12 files changed

+195
-60
lines changed

12 files changed

+195
-60
lines changed

ShockOsc/Backend/BackendHubManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ await _chatboxService.SendRemoteControlMessage(log.Shocker.Name, sender.Name, se
154154
case ControlType.Shock:
155155
{
156156
pain.LastIntensity = log.Intensity;
157-
pain.LastDuration = log.Duration;
157+
pain.LastDuration = (ushort)log.Duration;
158158
pain.LastExecuted = log.ExecutedAt;
159159

160160
oneShock = true;

ShockOsc/Config/BehaviourConf.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ public sealed class BehaviourConf
44
{
55
public bool RandomIntensity { get; set; }
66
public bool RandomDuration { get; set; }
7-
public JsonRange DurationRange { get; set; } = new JsonRange { Min = 1000, Max = 5000 };
8-
public JsonRange IntensityRange { get; set; } = new JsonRange { Min = 1, Max = 30 };
7+
public JsonRange<ushort> DurationRange { get; set; } = new JsonRange<ushort> { Min = 1000, Max = 5000 };
8+
public JsonRange<byte> IntensityRange { get; set; } = new JsonRange<byte> { Min = 1, Max = 30 };
99
public byte FixedIntensity { get; set; } = 50;
10-
public uint FixedDuration { get; set; } = 2000;
10+
public ushort FixedDuration { get; set; } = 2000;
1111
public uint HoldTime { get; set; } = 250;
1212
public uint CooldownTime { get; set; } = 5000;
1313
public BoneHeldAction WhileBoneHeld { get; set; } = BoneHeldAction.Vibrate;

ShockOsc/Config/Group.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ public sealed class Group
88
public bool OverrideIntensity { get; set; }
99

1010
public bool RandomIntensity { get; set; }
11-
public JsonRange IntensityRange { get; set; } = new JsonRange { Min = 1, Max = 30 };
11+
public JsonRange<byte> IntensityRange { get; set; } = new JsonRange<byte> { Min = 1, Max = 30 };
1212
public byte FixedIntensity { get; set; } = 50;
1313

1414
public bool OverrideDuration { get; set; }
1515
public bool RandomDuration { get; set; }
16-
public JsonRange DurationRange { get; set; } = new JsonRange { Min = 1000, Max = 5000 };
17-
public uint FixedDuration { get; set; } = 2000;
16+
public JsonRange<ushort> DurationRange { get; set; } = new JsonRange<ushort> { Min = 1000, Max = 5000 };
17+
public ushort FixedDuration { get; set; } = 2000;
1818

1919
public bool OverrideCooldownTime { get; set; }
2020
public uint CooldownTime { get; set; } = 5000;

ShockOsc/Config/JsonRange.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// ReSharper disable UnusedAutoPropertyAccessor.Global
22
namespace OpenShock.ShockOsc.Config;
33

4-
public class JsonRange
4+
public class JsonRange<T> where T : struct
55
{
6-
public required uint Min { get; set; }
7-
public required uint Max { get; set; }
6+
public required T Min { get; set; }
7+
public required T Max { get; set; }
88
}

ShockOsc/Models/ProgramGroup.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using OpenShock.SDK.CSharp.Models;
12
using OpenShock.ShockOsc.Config;
23
using OpenShock.ShockOsc.OscChangeTracker;
34
using OpenShock.ShockOsc.Services;
@@ -9,16 +10,29 @@ public sealed class ProgramGroup
910
public DateTime LastActive { get; set; }
1011
public DateTime LastExecuted { get; set; }
1112
public DateTime LastVibration { get; set; }
12-
public uint LastDuration { get; set; }
13+
public ushort LastDuration { get; set; }
1314
public byte LastIntensity { get; set; }
1415
public float LastStretchValue { get; set; }
1516
public bool IsGrabbed { get; set; }
17+
18+
/// <summary>
19+
/// Scaled to 0-100
20+
/// </summary>
21+
public byte NextIntensity { get; set; } = 0;
22+
23+
/// <summary>
24+
/// Not scaled, 0-1 float, needs to be scaled to duration limits
25+
/// </summary>
26+
public float NextDuration { get; set; } = 0;
1627

1728
public ChangeTrackedOscParam<bool> ParamActive { get; }
1829
public ChangeTrackedOscParam<bool> ParamCooldown { get; }
1930
public ChangeTrackedOscParam<float> ParamCooldownPercentage { get; }
2031
public ChangeTrackedOscParam<float> ParamIntensity { get; }
2132

33+
public byte LastConcurrentIntensity { get; set; } = 0;
34+
public byte ConcurrentIntensity { get; set; } = 0;
35+
public ControlType ConcurrentType { get; set; } = ControlType.Stop;
2236

2337
public Guid Id { get; }
2438
public string Name { get; }
@@ -42,5 +56,10 @@ public void Reset()
4256
{
4357
IsGrabbed = false;
4458
LastStretchValue = 0;
59+
ConcurrentType = ControlType.Stop;
60+
ConcurrentIntensity = 0;
61+
LastConcurrentIntensity = 0;
62+
NextIntensity = 0;
63+
NextDuration = 0;
4564
}
4665
}

ShockOsc/Services/LiveControlManager.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ private async Task RefreshInternal()
159159
await OnStateUpdated.Raise();
160160
}
161161

162-
public void ControlGroupFramePhysbonePull(ProgramGroup group, byte intensity)
162+
public void ControlGroupFrameCheckLoop(ProgramGroup group, byte intensity, ControlType type)
163163
{
164164
if (group.Id == Guid.Empty)
165165
{
@@ -171,8 +171,9 @@ public void ControlGroupFramePhysbonePull(ProgramGroup group, byte intensity)
171171

172172
ControlFrame(apiDevice.Shockers
173173
.Where(x => _configManager.Config.OpenShock.Shockers.Any(y => y.Key == x.Id && y.Value.Enabled))
174-
.Select(x => x.Id), liveControlClient, intensity);
174+
.Select(x => x.Id), liveControlClient, intensity, type);
175175
}
176+
return;
176177
}
177178

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

195-
ControlFrame(device.Select(x => x), client, intensity);
196+
ControlFrame(device.Select(x => x), client, intensity, type);
196197
}
197198
}
198199

199200
private void ControlFrame(IEnumerable<Guid> shockers, IOpenShockLiveControlClient client,
200-
byte vibrationIntensity)
201+
byte vibrationIntensity, ControlType type)
201202
{
202-
var type = _configManager.Config.Behaviour.WhileBoneHeld == BehaviourConf.BoneHeldAction.Shock
203-
? ControlType.Shock
204-
: ControlType.Vibrate;
205-
206203
foreach (var shocker in shockers)
207204
{
208205
client.IntakeFrame(shocker, type, vibrationIntensity);

ShockOsc/Services/ShockOsc.cs

Lines changed: 128 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ public sealed class ShockOsc
4444
"CooldownPercentage",
4545
"IShock",
4646
"IVibrate",
47-
"ISound"
47+
"ISound",
48+
"CShock",
49+
"NextIntensity",
50+
"NextDuration",
4851
};
4952

5053
public readonly Dictionary<string, object?> ShockOscParams = new();
@@ -302,6 +305,50 @@ private async Task ReceiveLogic()
302305
var value = received.Arguments.ElementAtOrDefault(0);
303306
switch (action)
304307
{
308+
case "NextIntensity":
309+
if (value is not float nextIntensity)
310+
{
311+
programGroup.NextIntensity = 0;
312+
return;
313+
}
314+
315+
programGroup.NextIntensity = Convert.ToByte(MathUtils.Saturate(nextIntensity) * 100f);
316+
break;
317+
318+
case "NextDuration":
319+
if (value is not float nextDuration)
320+
{
321+
programGroup.NextDuration = 0;
322+
return;
323+
}
324+
325+
programGroup.NextDuration = nextDuration;
326+
break;
327+
328+
case "CShock":
329+
if (value is not float intensity)
330+
{
331+
programGroup.ConcurrentIntensity = 0;
332+
programGroup.ConcurrentType = ControlType.Stop;
333+
return;
334+
}
335+
336+
var scaledIntensity = intensity * 100f;
337+
if(scaledIntensity > 127) break;
338+
339+
programGroup.ConcurrentIntensity = Convert.ToByte(intensity * 100f);
340+
341+
var ctype = action switch
342+
{
343+
"CShock" => ControlType.Shock,
344+
"CVibrate" => ControlType.Vibrate,
345+
"CSound" => ControlType.Sound,
346+
_ => ControlType.Vibrate
347+
};
348+
349+
programGroup.ConcurrentType = ctype;
350+
break;
351+
305352
case "IShock":
306353
case "IVibrate":
307354
case "ISound":
@@ -413,26 +460,30 @@ private async Task SenderLoopAsync()
413460
}
414461
}
415462

416-
private async Task InstantAction(ProgramGroup programGroup, uint duration, byte intensity, ControlType type,
463+
private async Task InstantAction(ProgramGroup programGroup, ushort duration, byte intensity, ControlType type,
417464
bool exclusive = false)
418465
{
466+
// Intensity is pre scaled to 0 - 100
467+
var actualIntensity = programGroup.NextIntensity == 0 ? intensity : programGroup.NextIntensity;
468+
var actualDuration = programGroup.NextDuration == 0 ? duration : GetScaledDuration(programGroup, programGroup.NextDuration);
469+
419470
if (type == ControlType.Shock)
420471
{
421472
programGroup.LastExecuted = DateTime.UtcNow;
422-
programGroup.LastDuration = duration;
423-
programGroup.LastIntensity = intensity;
473+
programGroup.LastDuration = actualDuration;
474+
programGroup.LastIntensity = actualIntensity;
424475
_oscHandler.ForceUnmute();
425476
_oscHandler.SendParams();
426477
}
427478

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

434-
await _backendHubManager.ControlGroup(programGroup.Id, duration, intensity, type, exclusive);
435-
await _chatboxService.SendLocalControlMessage(programGroup.Name, intensity, duration, type);
485+
await _backendHubManager.ControlGroup(programGroup.Id, actualDuration, actualIntensity, type, exclusive);
486+
await _chatboxService.SendLocalControlMessage(programGroup.Name, actualIntensity, actualDuration, type);
436487
}
437488

438489
private async Task CheckLoop()
@@ -463,6 +514,20 @@ private async Task CheckLogic()
463514

464515
private async Task CheckProgramGroup(ProgramGroup programGroup, Guid pos, BehaviourConf config)
465516
{
517+
if (programGroup.ConcurrentIntensity != 0)
518+
{
519+
_liveControlManager.ControlGroupFrameCheckLoop(programGroup, GetScaledIntensity(programGroup, programGroup.ConcurrentIntensity), programGroup.ConcurrentType);
520+
programGroup.LastConcurrentIntensity = programGroup.ConcurrentIntensity;
521+
return;
522+
}
523+
524+
if (programGroup.LastConcurrentIntensity != 0)
525+
{
526+
_liveControlManager.ControlGroupFrameCheckLoop(programGroup, 0, ControlType.Stop);
527+
programGroup.LastConcurrentIntensity = 0;
528+
_logger.LogInformation("Stopping");
529+
}
530+
466531
var cooldownTime = _configManager.Config.Behaviour.CooldownTime;
467532
if (programGroup.ConfigGroup is { OverrideCooldownTime: true })
468533
cooldownTime = programGroup.ConfigGroup.CooldownTime;
@@ -483,7 +548,9 @@ private async Task CheckProgramGroup(ProgramGroup programGroup, Guid pos, Behavi
483548

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

486-
_liveControlManager.ControlGroupFramePhysbonePull(programGroup, pullIntensityTranslated);
551+
_liveControlManager.ControlGroupFrameCheckLoop(programGroup, pullIntensityTranslated, _configManager.Config.Behaviour.WhileBoneHeld == BehaviourConf.BoneHeldAction.Shock
552+
? ControlType.Shock
553+
: ControlType.Vibrate);
487554
}
488555

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

529596
InstantAction(programGroup, GetDuration(programGroup), intensity, ControlType.Shock, exclusive);
530597
}
598+
599+
private ushort GetScaledDuration(ProgramGroup programGroup, float scale)
600+
{
601+
scale = MathUtils.Saturate(scale);
602+
603+
if (programGroup.ConfigGroup is not { OverrideDuration: true })
604+
{
605+
// Use global config
606+
var config = _configManager.Config.Behaviour;
607+
608+
if (!config.RandomDuration) return (ushort) (config.FixedDuration * scale);
609+
var rdr = config.DurationRange;
610+
return (ushort)
611+
(MathUtils.LerpUShort(
612+
(ushort)(rdr.Min / DurationStep), (ushort)(rdr.Max / DurationStep), scale)
613+
* DurationStep);
614+
}
615+
616+
// Use group config
617+
var groupConfig = programGroup.ConfigGroup;
618+
619+
if (!groupConfig.RandomDuration) return (ushort) (groupConfig.FixedDuration * scale);
620+
var groupRdr = groupConfig.DurationRange;
621+
return (ushort)(MathUtils.LerpUShort((ushort) (groupRdr.Min / DurationStep),
622+
(ushort)(groupRdr.Max / DurationStep), scale) * DurationStep);
623+
}
624+
625+
private byte GetScaledIntensity(ProgramGroup programGroup, byte intensity)
626+
{
627+
if (programGroup.ConfigGroup is not { OverrideIntensity: true })
628+
{
629+
// Use global config
630+
var config = _configManager.Config.Behaviour;
631+
632+
if (!config.RandomIntensity) return (byte)MathUtils.LerpFloat(0, config.FixedIntensity, intensity / 100f);
633+
return (byte)MathUtils.LerpFloat(config.IntensityRange.Min, config.IntensityRange.Max, intensity / 100f);
634+
}
635+
636+
// Use group config
637+
var groupConfig = programGroup.ConfigGroup;
638+
639+
if (!groupConfig.RandomIntensity) return (byte)MathUtils.LerpFloat(0, groupConfig.FixedIntensity, intensity / 100f);
640+
return (byte)MathUtils.LerpFloat(groupConfig.IntensityRange.Min, groupConfig.IntensityRange.Max, intensity / 100f);
641+
}
531642

532643
private byte GetPhysbonePullIntensity(ProgramGroup programGroup, float stretch)
533644
{
@@ -548,9 +659,9 @@ private byte GetPhysbonePullIntensity(ProgramGroup programGroup, float stretch)
548659
return (byte)MathUtils.LerpFloat(groupConfig.IntensityRange.Min, groupConfig.IntensityRange.Max, stretch);
549660
}
550661

551-
private const uint DurationStep = 100;
662+
private const ushort DurationStep = 100;
552663

553-
private uint GetDuration(ProgramGroup programGroup)
664+
private ushort GetDuration(ProgramGroup programGroup)
554665
{
555666
if (programGroup.ConfigGroup is not { OverrideDuration: true })
556667
{
@@ -559,17 +670,17 @@ private uint GetDuration(ProgramGroup programGroup)
559670

560671
if (!config.RandomDuration) return config.FixedDuration;
561672
var rdr = config.DurationRange;
562-
return (uint)(Random.Next((int)(rdr.Min / DurationStep),
563-
(int)(rdr.Max / DurationStep)) * DurationStep);
673+
return (ushort)(Random.Next(rdr.Min / DurationStep,
674+
rdr.Max / DurationStep) * DurationStep);
564675
}
565676

566677
// Use group config
567678
var groupConfig = programGroup.ConfigGroup;
568679

569680
if (!groupConfig.RandomDuration) return groupConfig.FixedDuration;
570681
var groupRdr = groupConfig.DurationRange;
571-
return (uint)(Random.Next((int)(groupRdr.Min / DurationStep),
572-
(int)(groupRdr.Max / DurationStep)) * DurationStep);
682+
return (ushort)(Random.Next(groupRdr.Min / DurationStep,
683+
groupRdr.Max / DurationStep) * DurationStep);
573684
}
574685

575686
private byte GetIntensity(ProgramGroup programGroup)
@@ -581,7 +692,7 @@ private byte GetIntensity(ProgramGroup programGroup)
581692

582693
if (!config.RandomIntensity) return config.FixedIntensity;
583694
var rir = config.IntensityRange;
584-
var intensityValue = Random.Next((int)rir.Min, (int)rir.Max);
695+
var intensityValue = Random.Next(rir.Min, rir.Max);
585696
return (byte)intensityValue;
586697
}
587698

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

591702
if (!groupConfig.RandomIntensity) return groupConfig.FixedIntensity;
592703
var groupRir = groupConfig.IntensityRange;
593-
var groupIntensityValue = Random.Next((int)groupRir.Min, (int)groupRir.Max);
704+
var groupIntensityValue = Random.Next(groupRir.Min, groupRir.Max);
594705
return (byte)groupIntensityValue;
595706
}
596707
}

0 commit comments

Comments
 (0)