Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upstream merge 11/01/2025 #21

Merged
merged 50 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
46d1bbe
Apply forensics when loading with an ammo box (#32280)
themias Jan 4, 2025
92d21bb
Automatic changelog update
PJBot Jan 4, 2025
a25128b
Update Credits (#34220)
github-actions[bot] Jan 5, 2025
bc6dc9e
Fix rainbow lizard plushie inhands (#34128)
ArtisticRoomba Jan 5, 2025
ad504e2
wielding refactor/fixes (#32188)
deltanedas Jan 5, 2025
1730efc
Automatic changelog update
PJBot Jan 5, 2025
520ddb4
Lobby chat width and custom lobby titles (#33783)
Errant-4 Jan 5, 2025
79ce4fd
Automatic changelog update
PJBot Jan 5, 2025
7b9966d
Adds bullet collision to station lights (#34070)
SpaceRox1244 Jan 5, 2025
42b6ec7
Automatic changelog update
PJBot Jan 5, 2025
7c0a40a
Make station anchor hitbox less insufferable (#34217)
ArtisticRoomba Jan 6, 2025
1d2eb40
Automatic changelog update
PJBot Jan 6, 2025
4103b93
Remove kessler and zombeteors gamemodes from the secret pool (#34051)
ArtisticRoomba Jan 7, 2025
c21639a
Automatic changelog update
PJBot Jan 7, 2025
74b4ff4
Added distinct ad and bye chatter to Dr. Gibb vending (#34182)
Alpaccalypse Jan 7, 2025
fe317df
Implement approved rule changes (#34233)
nikthechampiongr Jan 7, 2025
4fecf1b
Special reagents now appear in the guidebook (#34265)
Alpaccalypse Jan 7, 2025
aedd616
Automatic changelog update
PJBot Jan 7, 2025
78778f3
Fix compilation errors in tests from update (#34272)
PJB3005 Jan 7, 2025
e326e41
Fix portable scrubber appearing powered on spawn (#34274)
Tayrtahn Jan 7, 2025
5454554
[HOTFIX] Fix chameleon PDAs renaming IDs (#34249)
SlamBamActionman Jan 7, 2025
031c568
Update vessel_warning.ogg (#34263)
Pangogie Jan 8, 2025
7b69a28
Add bleating accent to goats (#34273)
Tayrtahn Jan 8, 2025
c6afeeb
Automatic changelog update
PJBot Jan 8, 2025
660ecc6
Happy New Year (#34288)
Piras314 Jan 8, 2025
39b0616
Fix empty lines in adminwho with stealthmins. (#34122)
c4llv07e Jan 8, 2025
2984847
Automatic changelog update
PJBot Jan 8, 2025
1e4d502
Automatic changelog update
PJBot Jan 9, 2025
59b2b9a
change locking to use ComplexInteraction (#34326)
deltanedas Jan 9, 2025
81c628e
Automatic changelog update
PJBot Jan 9, 2025
e0b076d
Drink titles and soda vendor consistency (#34178)
Alpaccalypse Jan 9, 2025
30ddd76
Automatic changelog update
PJBot Jan 9, 2025
153a4ee
Fix access configurator debug assert (#34330)
ScarKy0 Jan 10, 2025
f3c5321
Renamed water melon juice to watermelon juice (#34341)
Alpaccalypse Jan 10, 2025
c2cbd9a
Fix battery charging stopping just short of being full (#34028)
Errant-4 Jan 10, 2025
b6d5417
Add copy threshold button to air alarms (#34346)
southbridge-fur Jan 10, 2025
9c54193
Automatic changelog update
PJBot Jan 10, 2025
62a164e
Replace some sound PlayEntity with PlayPvs (#34317)
ElectroJr Jan 10, 2025
a784209
Fixed Forensic Gloves to be Security Contraband (#34193)
Coolsurf6 Jan 10, 2025
c9afc37
Automatic changelog update
PJBot Jan 10, 2025
a2fdc95
add large instruments to the cargo request computer (#34240)
TeenSarlacc Jan 10, 2025
daaf5c7
Automatic changelog update
PJBot Jan 10, 2025
e9c6cbe
Fix crayon losing durability on stamped paper (#34202)
themias Jan 10, 2025
979d86f
Automatic changelog update
PJBot Jan 10, 2025
192ec93
Adds a border to Oppenhopper poster (#34219)
Spessmann Jan 10, 2025
f9f2a0a
Trim trailing newlines from examine messages (#33381)
SpaceManiac Jan 10, 2025
9bd08a1
Add a popup message when ghost Boo action does nothing (#34369)
Tayrtahn Jan 10, 2025
6208d6c
fix ghost_component.ftl locale grammar (#34372)
ArtisticRoomba Jan 11, 2025
eb77deb
Let ghosts sometimes make certain devices say creepy things (#34368)
Tayrtahn Jan 11, 2025
57e38bc
Automatic changelog update
PJBot Jan 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ public void UpdateDeviceData(string addr, IAtmosDeviceData device)
if (!_pumps.TryGetValue(addr, out var pumpControl))
{
var control= new PumpControl(pump, addr);
control.PumpDataChanged += AtmosDeviceDataChanged!.Invoke;
control.PumpDataCopied += AtmosDeviceDataCopied!.Invoke;
control.PumpDataChanged += AtmosDeviceDataChanged;
control.PumpDataCopied += AtmosDeviceDataCopied;
_pumps.Add(addr, control);
CVentContainer.AddChild(control);
}
Expand All @@ -145,8 +145,8 @@ public void UpdateDeviceData(string addr, IAtmosDeviceData device)
if (!_scrubbers.TryGetValue(addr, out var scrubberControl))
{
var control = new ScrubberControl(scrubber, addr);
control.ScrubberDataChanged += AtmosDeviceDataChanged!.Invoke;
control.ScrubberDataCopied += AtmosDeviceDataCopied!.Invoke;
control.ScrubberDataChanged += AtmosDeviceDataChanged;
control.ScrubberDataCopied += AtmosDeviceDataCopied;
_scrubbers.Add(addr, control);
CScrubberContainer.AddChild(control);
}
Expand All @@ -161,6 +161,7 @@ public void UpdateDeviceData(string addr, IAtmosDeviceData device)
{
var control = new SensorInfo(sensor, addr);
control.OnThresholdUpdate += AtmosAlarmThresholdChanged;
control.SensorDataCopied += AtmosDeviceDataCopied;
_sensors.Add(addr, control);
CSensorContainer.AddChild(control);
}
Expand Down
8 changes: 4 additions & 4 deletions Content.Client/Atmos/Monitor/UI/Widgets/PumpControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ public PumpControl(GasVentPumpData data, string address)
PumpDataChanged?.Invoke(_address, _data);
};

_copySettings.OnPressed += _ =>
{
PumpDataCopied?.Invoke(_data);
};
_copySettings.OnPressed += _ =>
{
PumpDataCopied?.Invoke(_data);
};
}

public void ChangeData(GasVentPumpData data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ public ScrubberControl(GasVentScrubberData data, string address)
ScrubberDataChanged?.Invoke(_address, _data);
};

_copySettings.OnPressed += _ =>
{
ScrubberDataCopied?.Invoke(_data);
};
_copySettings.OnPressed += _ =>
{
ScrubberDataCopied?.Invoke(_data);
};

foreach (var value in Enum.GetValues<Gas>())
{
Expand Down
3 changes: 3 additions & 0 deletions Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
<CollapsibleHeading Name="SensorAddress" />
<CollapsibleBody Margin="20 2 2 2">
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<BoxContainer Orientation="Horizontal" Margin ="0 0 0 2">
<Button Name="CCopySettings" Text="{Loc 'air-alarm-ui-thresholds-copy'}" ToolTip="{Loc 'air-alarm-ui-thresholds-copy-tooltip'}" />
</BoxContainer>
<BoxContainer Orientation="Vertical" Margin="0 0 2 0" HorizontalExpand="True">
<RichTextLabel Name="AlarmStateLabel" />
<RichTextLabel Name="PressureLabel" />
Expand Down
13 changes: 10 additions & 3 deletions Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ namespace Content.Client.Atmos.Monitor.UI.Widgets;
public sealed partial class SensorInfo : BoxContainer
{
public Action<string, AtmosMonitorThresholdType, AtmosAlarmThreshold, Gas?>? OnThresholdUpdate;
public event Action<AtmosSensorData>? SensorDataCopied;
private string _address;

private ThresholdControl _pressureThreshold;
private ThresholdControl _temperatureThreshold;
private Dictionary<Gas, ThresholdControl> _gasThresholds = new();
private Dictionary<Gas, RichTextLabel> _gasLabels = new();
private Button _copySettings => CCopySettings;

public SensorInfo(AtmosSensorData data, string address)
{
Expand Down Expand Up @@ -56,7 +58,7 @@ public SensorInfo(AtmosSensorData data, string address)
gasThresholdControl.Margin = new Thickness(20, 2, 2, 2);
gasThresholdControl.ThresholdDataChanged += (type, alarmThreshold, arg3) =>
{
OnThresholdUpdate!(_address, type, alarmThreshold, arg3);
OnThresholdUpdate?.Invoke(_address, type, alarmThreshold, arg3);
};

_gasThresholds.Add(gas, gasThresholdControl);
Expand All @@ -72,12 +74,17 @@ public SensorInfo(AtmosSensorData data, string address)

_pressureThreshold.ThresholdDataChanged += (type, threshold, arg3) =>
{
OnThresholdUpdate!(_address, type, threshold, arg3);
OnThresholdUpdate?.Invoke(_address, type, threshold, arg3);
};

_temperatureThreshold.ThresholdDataChanged += (type, threshold, arg3) =>
{
OnThresholdUpdate!(_address, type, threshold, arg3);
OnThresholdUpdate?.Invoke(_address, type, threshold, arg3);
};

_copySettings.OnPressed += _ =>
{
SensorDataCopied?.Invoke(data);
};
}

Expand Down
16 changes: 14 additions & 2 deletions Content.Client/Lobby/LobbyState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@
using Content.Client.Message;
using Content.Client.UserInterface.Systems.Chat;
using Content.Client.Voting;
using Content.Shared.CCVar;
using Robust.Client;
using Robust.Client.Console;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
using Robust.Shared.Timing;


namespace Content.Client.Lobby
{
public sealed class LobbyState : Robust.Client.State.State
{
[Dependency] private readonly IBaseClient _baseClient = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
Expand Down Expand Up @@ -49,7 +51,17 @@ protected override void Startup()

_voteManager.SetPopupContainer(Lobby.VoteContainer);
LayoutContainer.SetAnchorPreset(Lobby, LayoutContainer.LayoutPreset.Wide);
Lobby.ServerName.Text = _baseClient.GameInfo?.ServerName; //The eye of refactor gazes upon you...

var lobbyNameCvar = _cfg.GetCVar(CCVars.ServerLobbyName);
var serverName = _baseClient.GameInfo?.ServerName ?? string.Empty;

Lobby.ServerName.Text = string.IsNullOrEmpty(lobbyNameCvar)
? Loc.GetString("ui-lobby-title", ("serverName", serverName))
: lobbyNameCvar;

var width = _cfg.GetCVar(CCVars.ServerLobbyRightPanelWidth);
Lobby.RightSide.SetWidth = width;

UpdateLobbyUi();

Lobby.CharacterPreview.CharacterSetupButton.OnPressed += OnSetupPressed;
Expand Down
4 changes: 1 addition & 3 deletions Content.Client/Lobby/UI/LobbyGui.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,12 @@
<Control Access="Public" Visible="False" Name="CharacterSetupState" VerticalExpand="True" />
</BoxContainer>
<!-- Right Panel -->
<PanelContainer Name="RightSide" StyleClasses="AngleRect" HorizontalAlignment="Right" VerticalExpand="True"
<PanelContainer Name="RightSide" Access="Public" StyleClasses="AngleRect" HorizontalAlignment="Right" VerticalExpand="True"
VerticalAlignment="Stretch">
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<!-- Top row -->
<BoxContainer Orientation="Horizontal" MinSize="0 40" Name="HeaderContainer" Access="Public"
SeparationOverride="4">
<Label Margin="8 0 0 0" StyleClasses="LabelHeadingBigger" VAlign="Center"
Text="{Loc 'ui-lobby-title'}" />
<Label Name="ServerName" Access="Public" StyleClasses="LabelHeadingBigger" VAlign="Center"
HorizontalExpand="True" HorizontalAlignment="Center" />
</BoxContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ await server.WaitAssertion(() =>
{
playerUid = serverPlayerManager.Sessions.Single().AttachedEntity.GetValueOrDefault();
#pragma warning disable NUnit2045 // Interdependent assertions.
Assert.That(playerUid, Is.Not.EqualTo(default));
Assert.That(playerUid, Is.Not.EqualTo(default(EntityUid)));
// Making sure it exists
Assert.That(entManager.HasComponent<AlertsComponent>(playerUid));
#pragma warning restore NUnit2045
Expand Down
3 changes: 1 addition & 2 deletions Content.IntegrationTests/Tests/PostMapInitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Content.Shared.Station.Components;
using FastAccessors;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;

Expand Down Expand Up @@ -67,7 +66,7 @@ public sealed class PostMapInitTest
"Loop",
"Elkridge"


};

/// <summary>
Expand Down
14 changes: 7 additions & 7 deletions Content.Server/Access/Systems/AccessOverriderSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ private void UpdateUserInterface(EntityUid uid, AccessOverriderComponent compone
targetLabel = Loc.GetString("access-overrider-window-target-label") + " " + EntityManager.GetComponent<MetaDataComponent>(component.TargetAccessReaderId).EntityName;
targetLabelColor = Color.White;

if (!_accessReader.GetMainAccessReader(accessReader, out var accessReaderComponent))
if (!_accessReader.GetMainAccessReader(accessReader, out var accessReaderEnt))
return;

var currentAccessHashsets = accessReaderComponent.AccessLists;
var currentAccessHashsets = accessReaderEnt.Value.Comp.AccessLists;
currentAccess = ConvertAccessHashSetsToList(currentAccessHashsets).ToArray();
}

Expand Down Expand Up @@ -210,10 +210,10 @@ private void TryWriteToTargetAccessReaderId(EntityUid uid,
return;
}

if (!_accessReader.GetMainAccessReader(component.TargetAccessReaderId, out var accessReader))
if (!_accessReader.GetMainAccessReader(component.TargetAccessReaderId, out var accessReaderEnt))
return;

var oldTags = ConvertAccessHashSetsToList(accessReader.AccessLists);
var oldTags = ConvertAccessHashSetsToList(accessReaderEnt.Value.Comp.AccessLists);
var privilegedId = component.PrivilegedIdSlot.Item;

if (oldTags.SequenceEqual(newAccessList))
Expand Down Expand Up @@ -242,10 +242,10 @@ private void TryWriteToTargetAccessReaderId(EntityUid uid,
var removedTags = oldTags.Except(newAccessList).Select(tag => "-" + tag).ToList();

_adminLogger.Add(LogType.Action, LogImpact.Medium,
$"{ToPrettyString(player):player} has modified {ToPrettyString(component.TargetAccessReaderId):entity} with the following allowed access level holders: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");
$"{ToPrettyString(player):player} has modified {ToPrettyString(accessReaderEnt.Value):entity} with the following allowed access level holders: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");

accessReader.AccessLists = ConvertAccessListToHashSet(newAccessList);
Dirty(component.TargetAccessReaderId, accessReader);
accessReaderEnt.Value.Comp.AccessLists = ConvertAccessListToHashSet(newAccessList);
Dirty(accessReaderEnt.Value);
}

/// <summary>
Expand Down
8 changes: 4 additions & 4 deletions Content.Server/Administration/Commands/AdminWhoCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
var first = true;
foreach (var admin in adminMgr.ActiveAdmins)
{
if (!first)
sb.Append('\n');
first = false;

var adminData = adminMgr.GetAdminData(admin)!;
DebugTools.AssertNotNull(adminData);

if (adminData.Stealth && !seeStealth)
continue;

if (!first)
sb.Append('\n');
first = false;

sb.Append(admin.Name);
if (adminData.Title is { } title)
sb.Append($": [{title}]");
Expand Down
20 changes: 20 additions & 0 deletions Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,19 @@ private void SetThreshold(EntityUid uid, string address, AtmosMonitorThresholdTy
SyncDevice(uid, address);
}

private void SetAllThresholds(EntityUid uid, string address, AtmosSensorData data)
{
var payload = new NetworkPayload
{
[DeviceNetworkConstants.Command] = AtmosMonitorSystem.AtmosMonitorSetAllThresholdsCmd,
[AtmosMonitorSystem.AtmosMonitorAllThresholdData] = data
};

_deviceNet.QueuePacket(uid, address, payload);

SyncDevice(uid, address);
}

/// <summary>
/// Sync this air alarm's mode with the rest of the network.
/// </summary>
Expand Down Expand Up @@ -341,6 +354,13 @@ private void OnCopyDeviceData(EntityUid uid, AirAlarmComponent component, AirAla
SetData(uid, addr, args.Data);
}
break;

case AtmosSensorData sensorData:
foreach (string addr in component.SensorData.Keys)
{
SetAllThresholds(uid, addr, sensorData);
}
break;
}
}

Expand Down
26 changes: 24 additions & 2 deletions Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ public sealed class AtmosMonitorSystem : EntitySystem

// Commands
public const string AtmosMonitorSetThresholdCmd = "atmos_monitor_set_threshold";
public const string AtmosMonitorSetAllThresholdsCmd = "atmos_monitor_set_all_thresholds";

// Packet data
public const string AtmosMonitorThresholdData = "atmos_monitor_threshold_data";

public const string AtmosMonitorAllThresholdData = "atmos_monitor_all_threshold_data";
public const string AtmosMonitorThresholdDataType = "atmos_monitor_threshold_type";

public const string AtmosMonitorThresholdGasType = "atmos_monitor_threshold_gas";
Expand Down Expand Up @@ -138,7 +139,12 @@ private void OnPacketRecv(EntityUid uid, AtmosMonitorComponent component, Device
args.Data.TryGetValue(AtmosMonitorThresholdGasType, out Gas? gas);
SetThreshold(uid, thresholdType.Value, thresholdData, gas);
}

break;
case AtmosMonitorSetAllThresholdsCmd:
if (args.Data.TryGetValue(AtmosMonitorAllThresholdData, out AtmosSensorData? allThresholdData))
{
SetAllThresholds(uid, allThresholdData);
}
break;
case AtmosDeviceNetworkSystem.SyncData:
var payload = new NetworkPayload();
Expand Down Expand Up @@ -403,4 +409,20 @@ public void SetThreshold(EntityUid uid, AtmosMonitorThresholdType type, AtmosAla
}

}

/// <summary>
/// Sets all of a monitor's thresholds at once according to the incoming
/// AtmosSensorData object's thresholds.
/// </summary>
/// <param name="uid">The entity's uid</param>
/// <param name="allThresholdData">An AtmosSensorData object from which the thresholds will be loaded.</param>
public void SetAllThresholds(EntityUid uid, AtmosSensorData allThresholdData)
{
SetThreshold(uid, AtmosMonitorThresholdType.Temperature, allThresholdData.TemperatureThreshold);
SetThreshold(uid, AtmosMonitorThresholdType.Pressure, allThresholdData.PressureThreshold);
foreach (var gas in Enum.GetValues<Gas>())
{
SetThreshold(uid, AtmosMonitorThresholdType.Gas, allThresholdData.GasThresholds[gas], gas);
}
}
}
5 changes: 5 additions & 0 deletions Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,11 @@ public void QueueExplosion(MapCoordinates epicenter,
// + if the bomb is big enough, people outside of it too
// this is capped to 30 because otherwise really huge bombs
// will attempt to play regular audio for people who can't hear it anyway because the epicenter is so far away
//
// TODO EXPLOSION redo this.
// Use the Filter.Pvs range-multiplier option instead of AddInRange.
// Also the default PVS range is 25*2 = 50. So capping it at 30 makes no sense here.
// So actually maybe don't use Filter.Pvs at all and only use AddInRange?
var audioRange = Math.Min(iterationIntensity.Count * 2, MaxExplosionAudioRange);
var filter = Filter.Pvs(pos).AddInRange(pos, audioRange);
var sound = iterationIntensity.Count < queued.Proto.SmallSoundIterationThreshold
Expand Down
37 changes: 37 additions & 0 deletions Content.Server/Ghost/Components/SpookySpeakerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Content.Shared.Dataset;
using Robust.Shared.Prototypes;

namespace Content.Server.Ghost.Components;

/// <summary>
/// Causes this entity to react to ghost player using the "Boo!" action by speaking
/// a randomly chosen message from a specified set.
/// </summary>
[RegisterComponent, AutoGenerateComponentPause]
public sealed partial class SpookySpeakerComponent : Component
{
/// <summary>
/// ProtoId of the LocalizedDataset to use for messages.
/// </summary>
[DataField(required: true)]
public ProtoId<LocalizedDatasetPrototype> MessageSet;

/// <summary>
/// Probability that this entity will speak if activated by a Boo action.
/// This is so whole banks of entities don't trigger at the same time.
/// </summary>
[DataField]
public float SpeakChance = 0.5f;

/// <summary>
/// Minimum time that must pass after speaking before this entity can speak again.
/// </summary>
[DataField]
public TimeSpan Cooldown = TimeSpan.FromSeconds(30);

/// <summary>
/// Time when the cooldown will have elapsed and the entity can speak again.
/// </summary>
[DataField, AutoPausedField]
public TimeSpan NextSpeakTime;
}
Loading
Loading