И твой сорванный голос мне напомнит о прошлом
This commit is contained in:
@@ -7,21 +7,21 @@ namespace Content.Client._White.Jukebox;
|
||||
public sealed class JukeboxBUI : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly EntityManager _entityManager = default!;
|
||||
private readonly SharedPopupSystem _sharedPopupSystem = default!;
|
||||
|
||||
private JukeboxMenu? _window;
|
||||
private readonly JukeboxMenu? _window;
|
||||
|
||||
public JukeboxBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_sharedPopupSystem = _entityManager.System<SharedPopupSystem>();
|
||||
var sharedPopupSystem = _entityManager.System<SharedPopupSystem>();
|
||||
|
||||
if (!_entityManager.TryGetComponent(owner, out JukeboxComponent? jukeboxComponent))
|
||||
{
|
||||
_sharedPopupSystem.PopupEntity($"Тут нет JukeboxComponent, звоните кодерам", owner);
|
||||
sharedPopupSystem.PopupEntity("Тут нет JukeboxComponent, звоните кодерам", owner);
|
||||
return;
|
||||
}
|
||||
|
||||
_window = new JukeboxMenu(jukeboxComponent);
|
||||
_window = new JukeboxMenu(owner, jukeboxComponent);
|
||||
_window.RepeatButton.OnToggled += OnRepeatButtonToggled;
|
||||
_window.StopButton.OnPressed += OnStopButtonPressed;
|
||||
_window.EjectButton.OnPressed += OnEjectButtonPressed;
|
||||
@@ -42,7 +42,6 @@ public sealed class JukeboxBUI : BoundUserInterface
|
||||
SendMessage(new JukeboxRepeatToggled(obj.Pressed));
|
||||
}
|
||||
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
@@ -64,4 +63,4 @@ public sealed class JukeboxBUI : BoundUserInterface
|
||||
|
||||
_window?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,20 +12,22 @@ namespace Content.Client._White.Jukebox;
|
||||
public sealed partial class JukeboxMenu : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
private readonly JukeboxSystem _jukeboxSystem = default!;
|
||||
private readonly JukeboxSystem _jukeboxSystem;
|
||||
|
||||
private readonly EntityUid _jukeboxEntity;
|
||||
private readonly JukeboxComponent _component;
|
||||
|
||||
private List<JukeboxSongEntry> _defaultSongsEntries = new();
|
||||
private List<JukeboxSongEntry> _tapeSongsEntries = new();
|
||||
private readonly List<JukeboxSongEntry> _defaultSongsEntries = [];
|
||||
private readonly List<JukeboxSongEntry> _tapeSongsEntries = [];
|
||||
|
||||
public JukeboxMenu(JukeboxComponent component)
|
||||
public JukeboxMenu(EntityUid jukeboxEntity, JukeboxComponent component)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_jukeboxSystem = _entityManager.System<JukeboxSystem>();
|
||||
|
||||
_jukeboxEntity = jukeboxEntity;
|
||||
_component = component;
|
||||
|
||||
/*TabContainer.SetTabTitle(DefaultSongsTab, "Прямо с завода");*/
|
||||
@@ -39,7 +41,7 @@ public sealed partial class JukeboxMenu : DefaultWindow
|
||||
{
|
||||
CurrenSongLabel.Text = _component.PlayingSongData == null ? "..." : _component.PlayingSongData.SongName!;
|
||||
|
||||
RepeatButton.Pressed = _component.Repeating;
|
||||
RepeatButton.Pressed = _component.Playing;
|
||||
|
||||
base.FrameUpdate(args);
|
||||
}
|
||||
@@ -94,6 +96,6 @@ public sealed partial class JukeboxMenu : DefaultWindow
|
||||
|
||||
private void RequestSongPlay(JukeboxSong song)
|
||||
{
|
||||
_jukeboxSystem.RequestSongToPlay(_component, song);
|
||||
_jukeboxSystem.RequestSongToPlay(_jukeboxEntity, _component, song);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using Robust.Client.Player;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Audio.Sources;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -17,12 +16,14 @@ namespace Content.Client._White.Jukebox;
|
||||
|
||||
public sealed class JukeboxSystem : EntitySystem
|
||||
{
|
||||
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IResourceCache _resource = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IAudioManager _clydeAudio = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
|
||||
private const CollisionGroup CollisionMask = CollisionGroup.Impassable;
|
||||
|
||||
private readonly Dictionary<JukeboxComponent, JukeboxAudio> _playingJukeboxes = new();
|
||||
|
||||
@@ -34,7 +35,6 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
|
||||
_cfg.OnValueChanged(WhiteCVars.JukeboxVolume, JukeboxVolumeChanged, true);
|
||||
|
||||
SubscribeLocalEvent<JukeboxComponent, ComponentHandleState>(OnStateChanged);
|
||||
SubscribeLocalEvent<JukeboxComponent, ComponentRemove>(OnComponentRemoved);
|
||||
SubscribeNetworkEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||
SubscribeNetworkEvent<TickerJoinLobbyEvent>(JoinLobby);
|
||||
@@ -60,6 +60,7 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
private void OnComponentRemoved(EntityUid uid, JukeboxComponent component, ComponentRemove args)
|
||||
{
|
||||
if (!_playingJukeboxes.TryGetValue(component, out var playingData)) return;
|
||||
|
||||
playingData.PlayingStream.StopPlaying();
|
||||
_playingJukeboxes.Remove(component);
|
||||
}
|
||||
@@ -67,36 +68,35 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
private void OnStopPlaying(JukeboxStopPlaying ev)
|
||||
{
|
||||
if (!ev.JukeboxUid.HasValue) return;
|
||||
if(!TryComp<JukeboxComponent>(GetEntity(ev.JukeboxUid), out var jukeboxComponent)) return;
|
||||
if (!TryComp<JukeboxComponent>(GetEntity(ev.JukeboxUid), out var jukeboxComponent)) return;
|
||||
|
||||
if(!_playingJukeboxes.TryGetValue(jukeboxComponent, out var jukeboxAudio)) return;
|
||||
if (!_playingJukeboxes.TryGetValue(jukeboxComponent, out var jukeboxAudio)) return;
|
||||
|
||||
jukeboxAudio.PlayingStream.StopPlaying();
|
||||
_playingJukeboxes.Remove(jukeboxComponent);
|
||||
}
|
||||
|
||||
public void RequestSongToPlay(JukeboxComponent component, JukeboxSong jukeboxSong)
|
||||
public void RequestSongToPlay(EntityUid jukebox, JukeboxComponent component, JukeboxSong jukeboxSong)
|
||||
{
|
||||
if (!_resource.TryGetResource<AudioResource>((ResPath) jukeboxSong.SongPath!, out var songResource))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RaiseNetworkEvent(new JukeboxRequestSongPlay()
|
||||
RaiseNetworkEvent(new JukeboxRequestSongPlay
|
||||
{
|
||||
Jukebox = GetNetEntity(component.Owner),
|
||||
Jukebox = GetNetEntity(jukebox),
|
||||
SongName = jukeboxSong.SongName,
|
||||
SongPath = jukeboxSong.SongPath,
|
||||
SongDuration = (float)songResource.AudioStream.Length.TotalSeconds
|
||||
SongDuration = (float) songResource.AudioStream.Length.TotalSeconds
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
var localPlayerEntity = _playerManager.LocalPlayer!.ControlledEntity;
|
||||
var localPlayerEntity = _playerManager.LocalEntity;
|
||||
if (!localPlayerEntity.HasValue)
|
||||
{
|
||||
CleanUp();
|
||||
@@ -108,18 +108,18 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
|
||||
private void ProcessJukeboxes()
|
||||
{
|
||||
var jukeboxes = EntityQuery<JukeboxComponent, TransformComponent>();
|
||||
var playerXform = Comp<TransformComponent>(_playerManager.LocalPlayer!.ControlledEntity!.Value);
|
||||
var jukeboxes = EntityQueryEnumerator<JukeboxComponent, TransformComponent>();
|
||||
var player = _playerManager.LocalEntity!.Value;
|
||||
var playerXform = Comp<TransformComponent>(player);
|
||||
|
||||
foreach (var (jukeboxComponent, jukeboxXform) in jukeboxes)
|
||||
while (jukeboxes.MoveNext(out var jukebox, out var jukeboxComponent, out var jukeboxXform))
|
||||
{
|
||||
|
||||
if (jukeboxXform.MapID != playerXform.MapID || (jukeboxXform.MapPosition.Position - playerXform.MapPosition.Position).Length() > jukeboxComponent.MaxAudioRange)
|
||||
if (jukeboxXform.MapID != playerXform.MapID ||
|
||||
(_transform.GetWorldPosition(jukebox) - _transform.GetWorldPosition(player)).Length() >
|
||||
jukeboxComponent.MaxAudioRange)
|
||||
{
|
||||
if (_playingJukeboxes.TryGetValue(jukeboxComponent, out var stream))
|
||||
if (_playingJukeboxes.Remove(jukeboxComponent, out var stream))
|
||||
{
|
||||
_playingJukeboxes.Remove(jukeboxComponent);
|
||||
|
||||
stream.PlayingStream.StopPlaying();
|
||||
stream.PlayingStream.Dispose();
|
||||
}
|
||||
@@ -131,28 +131,28 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
{
|
||||
if (!jukeboxAudio.PlayingStream.Playing)
|
||||
{
|
||||
HandleDoneStream(jukeboxAudio, jukeboxComponent, jukeboxXform, playerXform);
|
||||
HandleDoneStream(jukebox, player, jukeboxAudio, jukeboxComponent);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jukeboxAudio.SongData.SongPath != jukeboxComponent.PlayingSongData?.SongPath)
|
||||
{
|
||||
HandleSongChanged(jukeboxAudio, jukeboxComponent, jukeboxXform, playerXform);
|
||||
HandleSongChanged(jukebox, player, jukeboxAudio, jukeboxComponent);
|
||||
continue;
|
||||
}
|
||||
|
||||
SetRolloffAndOcclusion(jukeboxComponent, playerXform, jukeboxXform, jukeboxAudio);
|
||||
SetPosition(jukeboxXform, jukeboxAudio);
|
||||
SetRolloffAndOcclusion(jukebox, player, jukeboxComponent, jukeboxAudio);
|
||||
SetPosition(jukebox, jukeboxAudio);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jukeboxComponent.PlayingSongData == null)
|
||||
{
|
||||
SetBarsLayerVisible(jukeboxComponent, false);
|
||||
SetBarsLayerVisible(jukebox, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
var stream = TryCreateStream(jukeboxComponent, jukeboxXform, playerXform);
|
||||
var stream = TryCreateStream(jukebox, player, jukeboxComponent);
|
||||
|
||||
if (stream == null)
|
||||
{
|
||||
@@ -160,141 +160,139 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
}
|
||||
|
||||
_playingJukeboxes.Add(jukeboxComponent, stream);
|
||||
SetBarsLayerVisible(jukeboxComponent, true);
|
||||
SetBarsLayerVisible(jukebox, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPosition(TransformComponent jukeboxXform, JukeboxAudio jukeboxAudio)
|
||||
private void SetPosition(EntityUid jukebox, JukeboxAudio jukeboxAudio)
|
||||
{
|
||||
jukeboxAudio.PlayingStream.Position = jukeboxXform.MapPosition.Position;
|
||||
jukeboxAudio.PlayingStream.Position = _transform.GetWorldPosition(jukebox);
|
||||
}
|
||||
|
||||
private void SetRolloffAndOcclusion(JukeboxComponent jukeboxComponent, TransformComponent playerXform, TransformComponent jukeboxXform, JukeboxAudio jukeboxAudio)
|
||||
private void SetRolloffAndOcclusion(
|
||||
EntityUid player,
|
||||
EntityUid jukebox,
|
||||
JukeboxComponent jukeboxComponent,
|
||||
JukeboxAudio jukeboxAudio)
|
||||
{
|
||||
var collisionMask = CollisionGroup.Impassable;
|
||||
var sourceRelative = playerXform.MapPosition.Position - jukeboxXform.MapPosition.Position;
|
||||
var jukeboxWorldPosition = _transform.GetWorldPosition(jukebox);
|
||||
var playerWorldPosition = _transform.GetWorldPosition(player);
|
||||
var sourceRelative = playerWorldPosition - jukeboxWorldPosition;
|
||||
var occlusion = 0f;
|
||||
|
||||
if (sourceRelative.Length() > 0)
|
||||
{
|
||||
occlusion = _physicsSystem.IntersectRayPenetration(jukeboxXform.MapID,
|
||||
new CollisionRay(jukeboxXform.MapPosition.Position, sourceRelative.Normalized(), (int)collisionMask),
|
||||
sourceRelative.Length(), jukeboxXform.Owner) * 3f;
|
||||
occlusion = _physicsSystem.IntersectRayPenetration(_transform.GetMapCoordinates(jukebox).MapId,
|
||||
new CollisionRay(jukeboxWorldPosition, sourceRelative.Normalized(), (int) CollisionMask),
|
||||
sourceRelative.Length(), jukebox) * 3f;
|
||||
}
|
||||
|
||||
jukeboxAudio.PlayingStream.Occlusion = occlusion;
|
||||
jukeboxAudio.PlayingStream.RolloffFactor = (jukeboxXform.MapPosition.Position - playerXform.MapPosition.Position).Length() * jukeboxComponent.RolloffFactor;
|
||||
jukeboxAudio.PlayingStream.RolloffFactor =
|
||||
(jukeboxWorldPosition - playerWorldPosition).Length() * jukeboxComponent.RolloffFactor;
|
||||
}
|
||||
|
||||
private void HandleSongChanged(JukeboxAudio jukeboxAudio, JukeboxComponent jukeboxComponent, TransformComponent jukeboxXform, TransformComponent playerXform)
|
||||
private void HandleSongChanged(
|
||||
EntityUid jukebox,
|
||||
EntityUid player,
|
||||
JukeboxAudio jukeboxAudio,
|
||||
JukeboxComponent jukeboxComponent)
|
||||
{
|
||||
jukeboxAudio.PlayingStream.StopPlaying();
|
||||
|
||||
if (jukeboxComponent.PlayingSongData != null && jukeboxComponent.PlayingSongData.SongPath == jukeboxAudio.SongData.SongPath)
|
||||
if (jukeboxComponent.PlayingSongData != null &&
|
||||
jukeboxComponent.PlayingSongData.SongPath == jukeboxAudio.SongData.SongPath)
|
||||
{
|
||||
var newStream = TryCreateStream(jukeboxComponent, jukeboxXform, playerXform);
|
||||
if(newStream == null) return;
|
||||
var newStream = TryCreateStream(jukebox, player, jukeboxComponent);
|
||||
if (newStream == null) return;
|
||||
|
||||
_playingJukeboxes[jukeboxComponent] = newStream;
|
||||
SetBarsLayerVisible(jukeboxComponent, true);
|
||||
SetBarsLayerVisible(jukebox, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_playingJukeboxes.Remove(jukeboxComponent);
|
||||
SetBarsLayerVisible(jukeboxComponent, false);
|
||||
SetBarsLayerVisible(jukebox, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDoneStream(JukeboxAudio jukeboxAudio, JukeboxComponent jukeboxComponent, TransformComponent jukeboxXform, TransformComponent playerXform)
|
||||
private void HandleDoneStream(
|
||||
EntityUid jukebox,
|
||||
EntityUid player,
|
||||
JukeboxAudio jukeboxAudio,
|
||||
JukeboxComponent jukeboxComponent)
|
||||
{
|
||||
if (!jukeboxComponent.Repeating)
|
||||
if (!jukeboxComponent.Playing)
|
||||
{
|
||||
jukeboxAudio.PlayingStream.StopPlaying();
|
||||
_playingJukeboxes.Remove(jukeboxComponent);
|
||||
SetBarsLayerVisible(jukeboxComponent, false);
|
||||
SetBarsLayerVisible(jukebox, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if(jukeboxComponent.PlayingSongData == null) return;
|
||||
if (jukeboxComponent.PlayingSongData == null) return;
|
||||
|
||||
|
||||
var newStream = TryCreateStream(jukeboxComponent, jukeboxXform, playerXform);
|
||||
var newStream = TryCreateStream(jukebox, player, jukeboxComponent);
|
||||
|
||||
if (newStream == null)
|
||||
{
|
||||
_playingJukeboxes.Remove(jukeboxComponent);
|
||||
SetBarsLayerVisible(jukeboxComponent, false);
|
||||
SetBarsLayerVisible(jukebox, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
_playingJukeboxes[jukeboxComponent] = newStream;
|
||||
SetBarsLayerVisible(jukeboxComponent, true);
|
||||
SetBarsLayerVisible(jukebox, true);
|
||||
}
|
||||
}
|
||||
|
||||
private JukeboxAudio? TryCreateStream(JukeboxComponent jukeboxComponent, TransformComponent jukeboxXform, TransformComponent playerXform)
|
||||
private JukeboxAudio? TryCreateStream(EntityUid jukebox, EntityUid player, JukeboxComponent jukeboxComponent)
|
||||
{
|
||||
if (jukeboxComponent.PlayingSongData == null) return null!;
|
||||
|
||||
var resourcePath = jukeboxComponent.PlayingSongData.SongPath!;
|
||||
|
||||
if(!_resource.TryGetResource<AudioResource>((ResPath) resourcePath, out var audio))
|
||||
return null!;
|
||||
if (!_resource.TryGetResource<AudioResource>((ResPath) resourcePath, out var audio))
|
||||
return null;
|
||||
|
||||
if (audio.AudioStream.Length.TotalSeconds < jukeboxComponent.PlayingSongData!.PlaybackPosition)
|
||||
{
|
||||
return null!;
|
||||
return null;
|
||||
}
|
||||
|
||||
var playingStream = _clydeAudio.CreateAudioSource(audio.AudioStream);
|
||||
|
||||
if (playingStream == null)
|
||||
return null!;
|
||||
return null;
|
||||
|
||||
playingStream.Volume = _jukeboxVolume;
|
||||
playingStream.PlaybackPosition = jukeboxComponent.PlayingSongData.PlaybackPosition;
|
||||
|
||||
playingStream.Position = jukeboxXform.MapPosition.Position;
|
||||
playingStream.Position = _transform.GetWorldPosition(jukebox);
|
||||
|
||||
var jukeboxAudio = new JukeboxAudio(playingStream!, audio, jukeboxComponent.PlayingSongData);
|
||||
var jukeboxAudio = new JukeboxAudio(playingStream, audio, jukeboxComponent.PlayingSongData);
|
||||
|
||||
SetRolloffAndOcclusion(jukeboxComponent, playerXform, jukeboxXform, jukeboxAudio);
|
||||
SetRolloffAndOcclusion(jukebox, player, jukeboxComponent, jukeboxAudio);
|
||||
playingStream.StartPlaying();
|
||||
|
||||
return jukeboxAudio;
|
||||
}
|
||||
|
||||
private void SetBarsLayerVisible(JukeboxComponent jukeboxComponent, bool visible)
|
||||
private void SetBarsLayerVisible(EntityUid jukebox, bool visible)
|
||||
{
|
||||
var spriteComponent = Comp<SpriteComponent>(jukeboxComponent.Owner);
|
||||
var spriteComponent = Comp<SpriteComponent>(jukebox);
|
||||
spriteComponent.LayerMapTryGet("bars", out var layer);
|
||||
spriteComponent.LayerSetVisible(layer, visible);
|
||||
}
|
||||
|
||||
private void OnStateChanged(EntityUid uid, JukeboxComponent component, ref ComponentHandleState args)
|
||||
private sealed class JukeboxAudio(IAudioSource playingStream, AudioResource audioStream, PlayingSongData songData)
|
||||
{
|
||||
if (args.Current is JukeboxComponentState state)
|
||||
{
|
||||
component.Repeating = state.Playing;
|
||||
component.Volume = state.Volume;
|
||||
component.PlayingSongData = state.SongData;
|
||||
}
|
||||
}
|
||||
public PlayingSongData SongData { get; } = songData;
|
||||
|
||||
private class JukeboxAudio
|
||||
{
|
||||
public PlayingSongData SongData { get; }
|
||||
public IAudioSource PlayingStream { get; }
|
||||
public AudioResource AudioStream { get; }
|
||||
public IAudioSource PlayingStream { get; } = playingStream;
|
||||
|
||||
public JukeboxAudio(IAudioSource playingStream, AudioResource audioStream, PlayingSongData songData)
|
||||
{
|
||||
PlayingStream = playingStream;
|
||||
AudioStream = audioStream;
|
||||
SongData = songData;
|
||||
}
|
||||
public AudioResource AudioStream { get; } = audioStream;
|
||||
}
|
||||
|
||||
private void CleanUp()
|
||||
@@ -307,4 +305,4 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
|
||||
_playingJukeboxes.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public sealed partial class AdminVerbSystem
|
||||
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/White/Cult/interface.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
_cultRule.MakeCultist(args.Target);
|
||||
_cultRule.AdminMakeCultist(args.Target);
|
||||
}
|
||||
};
|
||||
args.Verbs.Add(cultist);
|
||||
@@ -142,12 +142,10 @@ public sealed partial class AdminVerbSystem
|
||||
{
|
||||
Text = Loc.GetString("admin-verb-text-make-changeling"),
|
||||
Category = VerbCategory.Antag,
|
||||
Icon = new SpriteSpecifier.Texture(new ("/Textures/White/Actions/changeling.rsi/absorb.png")),
|
||||
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/White/Actions/changeling.rsi/absorb.png")),
|
||||
Act = () =>
|
||||
{
|
||||
|
||||
var isHuman = HasComp<HumanoidAppearanceComponent>(args.Target);
|
||||
_changelingRule.MakeChangeling(args.Target);
|
||||
_changelingRule.AdminMakeChangeling(args.Target);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
Message = Loc.GetString("admin-verb-make-changeling"),
|
||||
|
||||
@@ -481,12 +481,12 @@ namespace Content.Server.Administration.Systems
|
||||
str = str[..(DescriptionMax - _maxAdditionalChars - unameLength)];
|
||||
}
|
||||
var nonAfkAdmins = GetNonAfkAdmins();
|
||||
_messageQueues[msg.UserId].Enqueue(GenerateAHelpMessage(senderSession.Name, str, !personalChannel, _gameTicker.RoundDuration().ToString("hh\\:mm\\:ss"), _gameTicker.RunLevel, playedSound: playSound, noReceivers: nonAfkAdmins.Count == 0));
|
||||
_messageQueues[msg.UserId].Enqueue(GenerateAHelpMessage(senderSession.Name, str, !personalChannel, _gameTicker.RoundDuration().ToString(@"hh\:mm\:ss"), _gameTicker.RunLevel, playedSound: playSound, noReceivers: nonAfkAdmins.Count == 0));
|
||||
}
|
||||
|
||||
// WD start
|
||||
var utkaCkey = _playerManager.GetSessionByUserId(message.UserId).ConnectedClient.UserName;
|
||||
var utkaSender = _playerManager.GetSessionByUserId(senderSession.UserId).ConnectedClient.UserName;
|
||||
var utkaCkey = _playerManager.GetSessionById(message.UserId).Channel.UserName;
|
||||
var utkaSender = _playerManager.GetSessionById(senderSession.UserId).Channel.UserName;
|
||||
UtkaSendAhelpPm(message.Text, utkaCkey, utkaSender);
|
||||
// WD end
|
||||
|
||||
@@ -624,8 +624,8 @@ namespace Content.Server.Administration.Systems
|
||||
// Notify player
|
||||
if (_playerManager.TryGetSessionById(receiver, out var session))
|
||||
{
|
||||
if (!admins.Contains(session.ConnectedClient))
|
||||
RaiseNetworkEvent(msg, session.ConnectedClient);
|
||||
if (!admins.Contains(session.Channel))
|
||||
RaiseNetworkEvent(msg, session.Channel);
|
||||
}
|
||||
|
||||
var sendsWebhook = _webhookUrl != string.Empty;
|
||||
@@ -642,10 +642,10 @@ namespace Content.Server.Administration.Systems
|
||||
str = str[..(DescriptionMax - _maxAdditionalChars - unameLength)];
|
||||
}
|
||||
_messageQueues[msg.UserId].Enqueue(GenerateAHelpMessage(sender, str, true,
|
||||
_gameTicker.RoundDuration().ToString("hh\\:mm\\:ss"), _gameTicker.RunLevel));
|
||||
_gameTicker.RoundDuration().ToString(@"hh\:mm\:ss"), _gameTicker.RunLevel, false));
|
||||
}
|
||||
|
||||
var utkaCkey = _playerManager.GetSessionByUserId(receiver).ConnectedClient.UserName;
|
||||
var utkaCkey = _playerManager.GetSessionById(receiver).Channel.UserName;
|
||||
UtkaSendAhelpPm(text, utkaCkey, sender);
|
||||
}
|
||||
|
||||
@@ -665,12 +665,12 @@ namespace Content.Server.Administration.Systems
|
||||
entity = meta.EntityName;
|
||||
}
|
||||
|
||||
var utkaAhelpEvent = new UtkaAhelpPmEvent()
|
||||
var utkaAhelpEvent = new UtkaAhelpPmEvent
|
||||
{
|
||||
Message = message,
|
||||
Ckey = ckey,
|
||||
Sender = sender,
|
||||
Rid = Get<GameTicker>().RoundId,
|
||||
Rid = _gameTicker.RoundId,
|
||||
NoAdmins = !admins,
|
||||
Entity = entity
|
||||
};
|
||||
|
||||
@@ -301,26 +301,21 @@ public sealed class RespiratorSystem : EntitySystem
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_inventorySystem.TryGetSlotEntity(target, "mask", out var maskUidTarget) &&
|
||||
EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUidTarget, out var blockerTarget) &&
|
||||
blockerTarget.Enabled)
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("cpr-mask-block-target", ("target", Identity.Entity(target, EntityManager))), target,
|
||||
user);
|
||||
return false;
|
||||
}
|
||||
if (!_inventorySystem.TryGetSlotEntity(target, "mask", out var maskUidTarget) ||
|
||||
!EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUidTarget, out var blockerTarget) ||
|
||||
!blockerTarget.Enabled)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("cpr-mask-block-target", ("target", Identity.Entity(target, EntityManager))), target, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DoCPR(EntityUid target, RespiratorComponent comp, EntityUid user)
|
||||
{
|
||||
var doAfterEventArgs = new DoAfterArgs(EntityManager, user, 1, new CPREndedEvent(), target,
|
||||
target: target)
|
||||
var doAfterEventArgs = new DoAfterArgs(EntityManager, user, 1, new CPREndedEvent(), target, target: target)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
BreakOnMove = true,
|
||||
BreakOnDamage = true,
|
||||
NeedHand = true,
|
||||
BreakOnHandChange = true
|
||||
@@ -334,12 +329,11 @@ public sealed class RespiratorSystem : EntitySystem
|
||||
|
||||
comp.CPRPerformedBy = user;
|
||||
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("cpr-started", ("target", Identity.Entity(target, EntityManager)),
|
||||
_popupSystem.PopupEntity(Loc.GetString("cpr-started", ("target", Identity.Entity(target, EntityManager)),
|
||||
("user", Identity.Entity(user, EntityManager))), target, PopupType.Medium);
|
||||
|
||||
comp.CPRPlayingStream =
|
||||
_audio.PlayPvs(comp.CPRSound, target, audioParams: AudioParams.Default.WithVolume(-3f).WithLoop(true)).Value
|
||||
.Entity;
|
||||
_audio.PlayPvs(comp.CPRSound, target, AudioParams.Default.WithVolume(-3f).WithLoop(true)).Value.Entity;
|
||||
|
||||
_adminLogger.Add(LogType.Action, LogImpact.High,
|
||||
$"{ToPrettyString(user):entity} начал произовдить СЛР на {ToPrettyString(target):entity}");
|
||||
@@ -351,7 +345,7 @@ public sealed class RespiratorSystem : EntitySystem
|
||||
return;
|
||||
|
||||
if (args.Cancelled || !TryComp<MobStateComponent>(args.Target, out var targetState) ||
|
||||
targetState!.CurrentState != MobState.Critical)
|
||||
targetState.CurrentState != MobState.Critical)
|
||||
{
|
||||
_audio.Stop(component.CPRPlayingStream);
|
||||
component.CPRPerformedBy = null;
|
||||
@@ -365,15 +359,16 @@ public sealed class RespiratorSystem : EntitySystem
|
||||
|
||||
_damageable.TryChangeDamage(uid, -component.Damage * 2, true, false);
|
||||
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("cpr-cycle-ended", ("target", Identity.Entity(uid, EntityManager)),
|
||||
_popupSystem.PopupEntity(Loc.GetString("cpr-cycle-ended", ("target", Identity.Entity(uid, EntityManager)),
|
||||
("user", Identity.Entity(args.User, EntityManager))), uid);
|
||||
|
||||
_adminLogger.Add(LogType.Action, LogImpact.High,
|
||||
$"{ToPrettyString(args.User):entity} произвёл СЛР на {ToPrettyString(args.Target):entity}");
|
||||
|
||||
if (args.Target != null && CanCPR(args.Target.Value, component, args.User))
|
||||
{
|
||||
args.Repeat = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
component.CPRPerformedBy = null;
|
||||
|
||||
@@ -14,20 +14,16 @@ using Content.Shared.Chat;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Silicons.Borgs.Components;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
@@ -36,31 +32,24 @@ namespace Content.Server.Borer;
|
||||
public sealed class ServerBorerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedActionsSystem _action = default!;
|
||||
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
|
||||
[Dependency] private readonly QuickDialogSystem _quickDialog = default!;
|
||||
[Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
|
||||
[Dependency] private readonly StunSystem _stuns = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly VomitSystem _vomitSystem = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
|
||||
[Dependency] private readonly SharedBorerSystem _sharedBorerSystem = default!;
|
||||
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
|
||||
[Dependency] private readonly GodmodeSystem _godmodeSystem = default!;
|
||||
|
||||
private const string SugarPrototype = "Sugar";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -85,15 +74,18 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
SubscribeLocalEvent<BorerHostComponent, BorerReproduceEvent>(OnReproduce);
|
||||
SubscribeLocalEvent<BorerHostComponent, BorerReproduceAfterEvent>(OnReproduceAfter);
|
||||
SubscribeLocalEvent<InfestedBorerComponent, BorerBrainResistAfterEvent>(OnResistAfterControl);
|
||||
|
||||
}
|
||||
|
||||
private void OnReproduceAfter(EntityUid uid, BorerHostComponent component, BorerReproduceAfterEvent args)
|
||||
{
|
||||
if (args.Cancelled || !TryComp(component.BorerContainer.ContainedEntities[0], out InfestedBorerComponent? borerComp)
|
||||
|| !WithrawPoints(component.BorerContainer.ContainedEntities[0], borerComp.ReproduceCost)
|
||||
|| !TryComp(uid, out TransformComponent? targetTransform))
|
||||
if (args.Cancelled
|
||||
|| !TryComp(component.BorerContainer.ContainedEntities[0], out InfestedBorerComponent? borerComp)
|
||||
|| !WithrawPoints(component.BorerContainer.ContainedEntities[0], borerComp.ReproduceCost)
|
||||
|| !TryComp(uid, out TransformComponent? targetTransform))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
_vomitSystem.Vomit(uid, -30, -30);
|
||||
_entityManager.SpawnEntity("MobSimpleBorer", targetTransform.Coordinates);
|
||||
@@ -103,32 +95,31 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
{
|
||||
if (!TryComp(component.BorerContainer.ContainedEntities[0], out InfestedBorerComponent? borerComp))
|
||||
return;
|
||||
|
||||
if (GetPoints(component.BorerContainer.ContainedEntities[0]) < borerComp.ReproduceCost)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-lowchem"),
|
||||
uid,
|
||||
uid, PopupType.LargeCaution);
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-lowchem"), uid, uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager,
|
||||
uid,
|
||||
TimeSpan.FromSeconds(3),
|
||||
new BorerReproduceAfterEvent(), uid)
|
||||
{
|
||||
Hidden = true
|
||||
});
|
||||
_doAfterSystem.TryStartDoAfter(
|
||||
new DoAfterArgs(EntityManager, uid, TimeSpan.FromSeconds(3), new BorerReproduceAfterEvent(), uid)
|
||||
{
|
||||
Hidden = true
|
||||
});
|
||||
}
|
||||
|
||||
public void ReleaseControl(EntityUid borerUid)
|
||||
{
|
||||
if (!TryComp(borerUid, out ActionsComponent? wormActComp) ||
|
||||
!TryComp(borerUid, out InfestedBorerComponent? borComp) ||
|
||||
!borComp.Host.HasValue ||
|
||||
!borComp.ControllingBrain)
|
||||
if (!TryComp(borerUid, out ActionsComponent? wormActComp)
|
||||
|| !TryComp(borerUid, out InfestedBorerComponent? borComp)
|
||||
|| !borComp.Host.HasValue
|
||||
|| !borComp.ControllingBrain)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TryComp(borComp.Host.Value, out ActionsComponent? bodyActComp);
|
||||
var wormHasMind = _mindSystem.TryGetMind(borerUid, out var hostMindId, out var hostMind);
|
||||
@@ -138,10 +129,10 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
|
||||
if (wormHasMind)
|
||||
_mindSystem.TransferTo(hostMindId, borComp.Host.Value, mind: hostMind);
|
||||
|
||||
if (bodyHasMind)
|
||||
_mindSystem.TransferTo(mindId, borerUid, mind: mind);
|
||||
|
||||
|
||||
_sharedBorerSystem.AddInfestedAbilities(borerUid, borComp);
|
||||
|
||||
_action.RemoveAction(borerUid, borComp.ActionBorerBrainResistEntity, wormActComp);
|
||||
@@ -164,6 +155,7 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
ReleaseControl(uid);
|
||||
}
|
||||
|
||||
@@ -171,69 +163,69 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
{
|
||||
if (GetPoints(uid) < component.AssumeControlCost)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-lowchem"),
|
||||
uid,
|
||||
uid, PopupType.LargeCaution);
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-lowchem"), uid, uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetSugarQuantityInHost(uid) > 0)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-toomuchsugar"), uid,
|
||||
uid, PopupType.LargeCaution);
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-toomuchsugar"), uid, uid, PopupType.LargeCaution);
|
||||
}
|
||||
|
||||
if (TryComp(component.Host, out MobStateComponent? state) &&
|
||||
state.CurrentState == MobState.Critical)
|
||||
if (TryComp(component.Host, out MobStateComponent? state) && state.CurrentState == MobState.Critical)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-braintake-critical"), uid,
|
||||
uid, PopupType.LargeCaution);
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-braintake-critical"), uid, uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager,
|
||||
uid,
|
||||
TimeSpan.FromSeconds(30),
|
||||
new BorerBrainTakeAfterEvent(), uid)
|
||||
{
|
||||
Hidden = true
|
||||
});
|
||||
_doAfterSystem.TryStartDoAfter(
|
||||
new DoAfterArgs(EntityManager, uid, TimeSpan.FromSeconds(30), new BorerBrainTakeAfterEvent(), uid)
|
||||
{
|
||||
Hidden = true
|
||||
});
|
||||
}
|
||||
|
||||
private void OnTakeControlAfter(EntityUid uid, InfestedBorerComponent component, BorerBrainTakeAfterEvent args)
|
||||
{
|
||||
if (!TryComp(uid, out ActionsComponent? comp) ||
|
||||
!TryComp(component.Host, out ActionsComponent? hostComp))
|
||||
if (args.Cancelled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
else if (TryComp(component.Host, out MobStateComponent? state) &&
|
||||
state.CurrentState == MobState.Critical)
|
||||
if (!TryComp(uid, out ActionsComponent? comp) || !TryComp(component.Host, out ActionsComponent? hostComp))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-braintake-critical"), uid,
|
||||
uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
else if (GetSugarQuantityInHost(uid) > 0)
|
||||
|
||||
if (TryComp(component.Host, out MobStateComponent? state) && state.CurrentState == MobState.Critical)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-toomuchsugar"), uid,
|
||||
uid, PopupType.LargeCaution);
|
||||
}
|
||||
else if (args.Cancelled || !WithrawPoints(uid, component.AssumeControlCost))
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-braintake-critical"), uid, uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetSugarQuantityInHost(uid) > 0)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-toomuchsugar"), uid, uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WithrawPoints(uid, component.AssumeControlCost))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var borHasMind = _mindSystem.TryGetMind(uid, out var mindId, out var mind);
|
||||
var hostHasMind = _mindSystem.TryGetMind(component.Host.Value, out var hostMindId, out var hostMind);
|
||||
|
||||
if (!borHasMind && !hostHasMind)
|
||||
return;
|
||||
|
||||
if (borHasMind)
|
||||
{
|
||||
_mindSystem.TransferTo(mindId, component.Host, mind: mind);
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-braintake-success"), component.Host.Value,
|
||||
component.Host.Value, PopupType.Large);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (hostHasMind)
|
||||
@@ -260,12 +252,15 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
|
||||
_action.AddAction(component.Host.Value, ref component.ActionBorerBrainReleaseEntity,
|
||||
component.ActionBorerBrainRelease, component: hostComp);
|
||||
|
||||
_action.AddAction(component.Host.Value, ref component.ActionBorerReproduceEntity,
|
||||
component.ActionBorerReproduce, component: hostComp);
|
||||
|
||||
if(component.ActionBorerReproduceEntity.HasValue)
|
||||
if (component.ActionBorerReproduceEntity.HasValue)
|
||||
{
|
||||
_metaData.SetEntityName(component.ActionBorerReproduceEntity.Value,
|
||||
$"{Loc.GetString("borer-abilities-reproduce-name")} ([color=red]{component.ReproduceCost}c[/color])");
|
||||
}
|
||||
|
||||
component.ControllingBrain = true;
|
||||
Dirty(uid, component);
|
||||
@@ -287,9 +282,10 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp(args.Target, out MobStateComponent? state) &&
|
||||
state.CurrentState == MobState.Dead)
|
||||
if (TryComp(args.Target, out MobStateComponent? state) && state.CurrentState == MobState.Dead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasComp<BorerHostComponent>(args.Target))
|
||||
{
|
||||
@@ -305,7 +301,7 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
StartInfest(uid, args.Target, component);
|
||||
StartInfest(uid, args.Target);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -316,9 +312,11 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
|
||||
if (!HasComp<HumanoidAppearanceComponent>(args.Target))
|
||||
return;
|
||||
if (TryComp(args.Target, out MobStateComponent? state) &&
|
||||
state.CurrentState == MobState.Dead)
|
||||
|
||||
if (TryComp(args.Target, out MobStateComponent? state) && state.CurrentState == MobState.Dead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasComp<BorerHostComponent>(args.Target))
|
||||
{
|
||||
@@ -348,29 +346,26 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
RemComp<BorerComponent>(uid);
|
||||
}
|
||||
|
||||
private void StartInfest(EntityUid user, EntityUid target, BorerComponent comp)
|
||||
private void StartInfest(EntityUid user, EntityUid target)
|
||||
{
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager,
|
||||
user,
|
||||
TimeSpan.FromSeconds(5),
|
||||
new BorerInfestDoAfterEvent(), user, target)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
Hidden = true
|
||||
});
|
||||
_doAfterSystem.TryStartDoAfter(
|
||||
new DoAfterArgs(EntityManager, user, TimeSpan.FromSeconds(5), new BorerInfestDoAfterEvent(), user, target)
|
||||
{
|
||||
BreakOnMove = true,
|
||||
Hidden = true
|
||||
});
|
||||
}
|
||||
|
||||
private void OnBorerScan(EntityUid uid, InfestedBorerComponent component, BorerScanInstantActionEvent args)
|
||||
{
|
||||
if (!component.Host.HasValue)
|
||||
return;
|
||||
|
||||
Dictionary<string, FixedPoint2> solution = new();
|
||||
if (EntityManager.TryGetComponent(component.Host.Value,
|
||||
out BloodstreamComponent? bloodContainer))
|
||||
if (EntityManager.TryGetComponent(component.Host.Value, out BloodstreamComponent? bloodContainer))
|
||||
{
|
||||
if(_solutionContainerSystem.TryGetSolution(component.Host.Value, bloodContainer.ChemicalSolutionName,
|
||||
out var sol))
|
||||
if (_solutionContainerSystem.TryGetSolution(component.Host.Value, bloodContainer.ChemicalSolutionName,
|
||||
out var sol))
|
||||
{
|
||||
foreach (var reagent in sol.Value.Comp.Solution)
|
||||
{
|
||||
@@ -414,7 +409,7 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
|
||||
private void OnTelepathicSpeech(EntityUid uid, InfestedBorerComponent component, BorerBrainSpeechActionEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(uid, out ActorComponent? actor))
|
||||
if (!TryComp(uid, out ActorComponent? actor))
|
||||
return;
|
||||
|
||||
_quickDialog.OpenDialog(actor.PlayerSession, Loc.GetString("borer-ui-converse-title"),
|
||||
@@ -422,40 +417,40 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
{
|
||||
_popup.PopupEntity(message, uid, uid, PopupType.Medium);
|
||||
|
||||
if (EntityManager.TryGetComponent(component.Host, out ActorComponent? hostActor))
|
||||
if (EntityManager.TryGetComponent(component.Host, out ActorComponent? _))
|
||||
{
|
||||
_popup.PopupEntity(message, component.Host.Value, component.Host.Value,
|
||||
PopupType.Medium);
|
||||
}
|
||||
});
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnInjectChemicals(BorerInjectActionEvent injectEvent, EntitySessionEventArgs eventArgs)
|
||||
{
|
||||
var borerEn = eventArgs.SenderSession.AttachedEntity;
|
||||
if (EntityManager.TryGetComponent(borerEn,
|
||||
out InfestedBorerComponent? infestedComponent) &&
|
||||
infestedComponent.Host.HasValue)
|
||||
if (!TryComp(borerEn, out InfestedBorerComponent? infestedComponent) || !infestedComponent.Host.HasValue)
|
||||
{
|
||||
if (!WithrawPoints(borerEn.Value, injectEvent.Cost))
|
||||
return;
|
||||
|
||||
var solution = new Solution();
|
||||
solution.AddReagent(injectEvent.ProtoId, 10);
|
||||
_bloodstreamSystem.TryAddToChemicals(infestedComponent.Host.Value, solution);
|
||||
_reactiveSystem.DoEntityReaction(infestedComponent.Host.Value, solution, ReactionMethod.Injection);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-injected", ("reagent", Loc.GetString("reagent-name-"+
|
||||
injectEvent.ProtoId.ToLower().Replace("spacedrugs", "space-drugs")))),
|
||||
borerEn.Value, borerEn.Value, PopupType.Medium);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WithrawPoints(borerEn.Value, injectEvent.Cost))
|
||||
return;
|
||||
|
||||
var solution = new Solution();
|
||||
solution.AddReagent(injectEvent.ProtoId, 10);
|
||||
_bloodstreamSystem.TryAddToChemicals(infestedComponent.Host.Value, solution);
|
||||
_reactiveSystem.DoEntityReaction(infestedComponent.Host.Value, solution, ReactionMethod.Injection);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-injected", ("reagent", Loc.GetString("reagent-name-" +
|
||||
injectEvent.ProtoId.ToLower().Replace("spacedrugs", "space-drugs")))),
|
||||
borerEn.Value, borerEn.Value, PopupType.Medium);
|
||||
}
|
||||
|
||||
public bool AddPoints(EntityUid borerUid, int value)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(borerUid,
|
||||
out InfestedBorerComponent? infestedComponent))
|
||||
if (!TryComp(borerUid, out InfestedBorerComponent? infestedComponent))
|
||||
return false;
|
||||
|
||||
infestedComponent.Points += value;
|
||||
@@ -466,21 +461,16 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
|
||||
public int GetPoints(EntityUid borerUid)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(borerUid,
|
||||
out InfestedBorerComponent? infestedComponent))
|
||||
return 0;
|
||||
|
||||
return infestedComponent.Points;
|
||||
return TryComp(borerUid, out InfestedBorerComponent? infestedComponent)
|
||||
? infestedComponent.Points
|
||||
: 0;
|
||||
}
|
||||
|
||||
public bool WithrawPoints(EntityUid borerUid, int value)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(borerUid,
|
||||
out InfestedBorerComponent? infestedComponent) || infestedComponent.Points < value)
|
||||
if (!TryComp(borerUid, out InfestedBorerComponent? infestedComponent) || infestedComponent.Points < value)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-lowchem"),
|
||||
borerUid,
|
||||
borerUid, PopupType.LargeCaution);
|
||||
_popup.PopupEntity(Loc.GetString("borer-popup-lowchem"), borerUid, borerUid, PopupType.LargeCaution);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -499,7 +489,10 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
{
|
||||
if (!TryComp(uid, out InfestedBorerComponent? component) ||
|
||||
!TryComp(component.Host, out BorerHostComponent? hostComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseControl(uid);
|
||||
|
||||
_vomitSystem.Vomit(component.Host.Value, -20, -20);
|
||||
@@ -513,16 +506,17 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
_godmodeSystem.DisableGodmode(uid);
|
||||
|
||||
RemComp<InfestedBorerComponent>(uid);
|
||||
_action.SetCooldown(borerComponent.ActionStunEntity, _timing.CurTime, _timing.CurTime+TimeSpan.FromSeconds(20));
|
||||
_action.SetCooldown(borerComponent.ActionInfestEntity, _timing.CurTime, _timing.CurTime+TimeSpan.FromSeconds(20));
|
||||
_action.SetCooldown(borerComponent.ActionStunEntity, _timing.CurTime,
|
||||
_timing.CurTime + TimeSpan.FromSeconds(20));
|
||||
|
||||
_action.SetCooldown(borerComponent.ActionInfestEntity, _timing.CurTime,
|
||||
_timing.CurTime + TimeSpan.FromSeconds(20));
|
||||
}
|
||||
|
||||
public int GetSugarQuantityInHost(EntityUid borerUid)
|
||||
{
|
||||
var sugarQuantity = 0;
|
||||
if (EntityManager.TryGetComponent(borerUid,
|
||||
out InfestedBorerComponent? component) &&
|
||||
component.Host.HasValue)
|
||||
if (TryComp(borerUid, out InfestedBorerComponent? component) && component.Host.HasValue)
|
||||
{
|
||||
sugarQuantity = GetSugarQuantityInEntity(component.Host.Value);
|
||||
}
|
||||
@@ -532,21 +526,20 @@ public sealed class ServerBorerSystem : EntitySystem
|
||||
|
||||
public int GetSugarQuantityInEntity(EntityUid uid)
|
||||
{
|
||||
if (EntityManager.TryGetComponent(uid,
|
||||
out BloodstreamComponent? bloodContainer))
|
||||
if (!TryComp(uid, out BloodstreamComponent? bloodContainer))
|
||||
return 0;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetSolution(uid, bloodContainer.ChemicalSolutionName, out var sol))
|
||||
return 0;
|
||||
|
||||
foreach (var reagent in sol.Value.Comp.Solution)
|
||||
{
|
||||
if(_solutionContainerSystem.TryGetSolution(uid, bloodContainer.ChemicalSolutionName,
|
||||
out var sol))
|
||||
if (reagent.Reagent.ToString() == SugarPrototype)
|
||||
{
|
||||
foreach (var reagent in sol.Value.Comp.Solution)
|
||||
{
|
||||
if (reagent.Reagent.ToString() == "Sugar")
|
||||
{
|
||||
return reagent.Quantity.Int();
|
||||
}
|
||||
}
|
||||
return reagent.Quantity.Int();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +1,121 @@
|
||||
using Content.Server.Botany.Components;
|
||||
using Content.Server.PowerCell;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Botany;
|
||||
using Content.Shared.Mobs.Components; //probably useless
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Botany
|
||||
namespace Content.Server.Botany.Systems;
|
||||
|
||||
public sealed class SeedAnalyzerSystem : EntitySystem
|
||||
{
|
||||
public sealed class SeedAnalyzerSystem : EntitySystem
|
||||
[Dependency] private readonly PowerCellSystem _cell = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
[Dependency] private readonly PowerCellSystem _cell = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<SeedAnalyzerComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
SubscribeLocalEvent<SeedAnalyzerComponent, SeedAnalyzerDoAfterEvent>(OnDoAfter);
|
||||
}
|
||||
|
||||
private void OnAfterInteract(EntityUid uid, SeedAnalyzerComponent seedAnalyzer, AfterInteractEvent args)
|
||||
{
|
||||
if (args.Target == null || !args.CanReach || !HasComp<PlantHolderComponent>(args.Target) || !_cell.HasActivatableCharge(uid, user: args.User))
|
||||
return;
|
||||
|
||||
_audio.PlayPvs(seedAnalyzer.ScanningBeginSound, uid); // maybe healthAnalyzer.ScanningBeginSound
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, seedAnalyzer.ScanDelay, new SeedAnalyzerDoAfterEvent(), uid, target: args.Target, used: uid) //maybe healthAnalyzer.ScanDelay
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
NeedHand = true
|
||||
});
|
||||
}
|
||||
|
||||
private void OnDoAfter(EntityUid uid, SeedAnalyzerComponent component, DoAfterEvent args)
|
||||
{
|
||||
if (args.Handled || args.Cancelled || args.Args.Target == null || !_cell.TryUseActivatableCharge(uid, user: args.User))
|
||||
return;
|
||||
|
||||
_audio.PlayPvs(component.ScanningEndSound, args.Args.User);
|
||||
|
||||
UpdateScannedSeed(uid, args.Args.User, args.Args.Target.Value, component);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OpenUserInterface(EntityUid user, EntityUid seedAnalyzer)
|
||||
{
|
||||
if (!TryComp<ActorComponent>(user, out var actor) || !_uiSystem.TryGetUi(seedAnalyzer, SeedAnalyzerUiKey.Key, out var ui))
|
||||
return;
|
||||
|
||||
_uiSystem.OpenUi(ui, actor.PlayerSession);
|
||||
}
|
||||
|
||||
public void UpdateScannedSeed(EntityUid uid, EntityUid user, EntityUid? target, SeedAnalyzerComponent? seedAnalyzer)
|
||||
{
|
||||
if (!Resolve(uid, ref seedAnalyzer))
|
||||
return;
|
||||
|
||||
if (target == null || !_uiSystem.TryGetUi(uid, SeedAnalyzerUiKey.Key, out var ui))
|
||||
return;
|
||||
|
||||
if (!TryComp<PlantHolderComponent>(target, out var plant))
|
||||
return;
|
||||
|
||||
if (plant!.Seed == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int zero = 0;
|
||||
string nonameseed = "None";
|
||||
Dictionary<string, FixedPoint2> emptydic = new Dictionary<string, FixedPoint2>();
|
||||
var zero2 = FixedPoint2.New(zero);
|
||||
emptydic?.Add("No chemicals", zero2!);
|
||||
Dictionary<string, FixedPoint2> passchems = new Dictionary<string, FixedPoint2>();
|
||||
|
||||
if (plant?.Seed?.Chemicals != null)
|
||||
{
|
||||
foreach (var (chem, quantity) in plant.Seed.Chemicals)
|
||||
{
|
||||
var amount = FixedPoint2.New(quantity.Min);
|
||||
amount += FixedPoint2.New(plant.Seed.Potency / quantity.PotencyDivisor);
|
||||
amount = FixedPoint2.New((int) MathHelper.Clamp(amount.Float(), quantity.Min, quantity.Max));
|
||||
passchems?.Add(chem, amount);
|
||||
}
|
||||
}
|
||||
|
||||
OpenUserInterface(user, uid);
|
||||
|
||||
_uiSystem.SendUiMessage(ui, new SeedAnalyzerScannedUserMessage(GetNetEntity(target),
|
||||
plant!.Seed?.Yield,
|
||||
plant != null ? plant.Seed?.Production : float.NaN,
|
||||
plant != null ? plant.Seed?.Lifespan : float.NaN,
|
||||
plant != null ? plant.Seed?.Maturation : float.NaN,
|
||||
plant != null ? plant.Seed?.Endurance : float.NaN,
|
||||
plant != null ? plant.Seed?.Potency : float.NaN,
|
||||
plant != null ? plant.Seed?.Viable : false,
|
||||
plant != null ? plant.Seed?.TurnIntoKudzu : false,
|
||||
plant != null ? plant.Seed?.Seedless : false,
|
||||
plant != null ? plant.Seed?.DisplayName : nonameseed,
|
||||
passchems != null ? passchems : emptydic,
|
||||
plant != null ? plant.Seed?.Ligneous : false,
|
||||
plant != null ? plant.Seed?.CanScream : false,
|
||||
plant != null ? plant.Seed?.Slip : false,
|
||||
plant != null ? plant.Seed?.Bioluminescent : false,
|
||||
plant != null ? plant.Seed?.Sentient : false));
|
||||
}
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<SeedAnalyzerComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
SubscribeLocalEvent<SeedAnalyzerComponent, SeedAnalyzerDoAfterEvent>(OnDoAfter);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAfterInteract(EntityUid uid, SeedAnalyzerComponent seedAnalyzer, AfterInteractEvent args)
|
||||
{
|
||||
if (args.Target == null || !args.CanReach || !HasComp<PlantHolderComponent>(args.Target) ||
|
||||
!_cell.HasActivatableCharge(uid, user: args.User))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_audio.PlayPvs(seedAnalyzer.ScanningBeginSound, uid);
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, seedAnalyzer.ScanDelay,
|
||||
new SeedAnalyzerDoAfterEvent(), uid, target: args.Target, used: uid)
|
||||
{
|
||||
BreakOnMove = true,
|
||||
NeedHand = true
|
||||
});
|
||||
}
|
||||
|
||||
private void OnDoAfter(EntityUid uid, SeedAnalyzerComponent component, DoAfterEvent args)
|
||||
{
|
||||
if (args.Handled || args.Cancelled || args.Args.Target == null ||
|
||||
!_cell.TryUseActivatableCharge(uid, user: args.User))
|
||||
return;
|
||||
|
||||
_audio.PlayPvs(component.ScanningEndSound, args.Args.User);
|
||||
|
||||
UpdateScannedSeed(uid, args.Args.User, args.Args.Target.Value, component);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OpenUserInterface(EntityUid user, EntityUid seedAnalyzer)
|
||||
{
|
||||
if (!TryComp<ActorComponent>(user, out var actor) ||
|
||||
!_uiSystem.TryGetUi(seedAnalyzer, SeedAnalyzerUiKey.Key, out var ui))
|
||||
return;
|
||||
|
||||
_uiSystem.OpenUi(ui, actor.PlayerSession);
|
||||
}
|
||||
|
||||
public void UpdateScannedSeed(
|
||||
EntityUid uid,
|
||||
EntityUid user,
|
||||
EntityUid? target,
|
||||
SeedAnalyzerComponent? seedAnalyzer = null)
|
||||
{
|
||||
if (!Resolve(uid, ref seedAnalyzer))
|
||||
return;
|
||||
|
||||
if (target == null || !_uiSystem.TryGetUi(uid, SeedAnalyzerUiKey.Key, out var ui))
|
||||
return;
|
||||
|
||||
if (!TryComp<PlantHolderComponent>(target, out var plant))
|
||||
return;
|
||||
|
||||
if (plant.Seed == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var zero2 = FixedPoint2.Zero;
|
||||
var emptydic = new Dictionary<string, FixedPoint2> { { "No chemicals", zero2 } };
|
||||
var passchems = new Dictionary<string, FixedPoint2>();
|
||||
|
||||
if (plant.Seed?.Chemicals != null)
|
||||
{
|
||||
foreach (var (chem, quantity) in plant.Seed.Chemicals)
|
||||
{
|
||||
var amount = FixedPoint2.New(quantity.Min);
|
||||
amount += FixedPoint2.New(plant.Seed.Potency / quantity.PotencyDivisor);
|
||||
amount = FixedPoint2.New((int) MathHelper.Clamp(amount.Float(), quantity.Min, quantity.Max));
|
||||
passchems?.Add(chem, amount);
|
||||
}
|
||||
}
|
||||
|
||||
OpenUserInterface(user, uid);
|
||||
|
||||
_uiSystem.SendUiMessage(ui, new SeedAnalyzerScannedUserMessage(GetNetEntity(target),
|
||||
plant.Seed?.Yield,
|
||||
plant.Seed?.Production,
|
||||
plant.Seed?.Lifespan,
|
||||
plant.Seed?.Maturation,
|
||||
plant.Seed?.Endurance,
|
||||
plant.Seed?.Potency,
|
||||
plant.Seed?.Viable,
|
||||
plant.Seed?.TurnIntoKudzu,
|
||||
plant.Seed?.Seedless,
|
||||
plant.Seed?.DisplayName,
|
||||
passchems ?? emptydic,
|
||||
plant.Seed?.Ligneous,
|
||||
plant.Seed?.CanScream,
|
||||
plant.Seed?.Slip,
|
||||
plant.Seed?.Bioluminescent,
|
||||
plant.Seed?.Sentient));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
@@ -160,6 +161,21 @@ public sealed class ChangelingRuleSystem : GameRuleSystem<ChangelingRuleComponen
|
||||
}
|
||||
}
|
||||
|
||||
public void AdminMakeChangeling(EntityUid entity)
|
||||
{
|
||||
var changelingRule = EntityQuery<ChangelingRuleComponent>().FirstOrDefault();
|
||||
if (changelingRule == null)
|
||||
{
|
||||
GameTicker.StartGameRule("Changeling", out var ruleEntity);
|
||||
changelingRule = Comp<ChangelingRuleComponent>(ruleEntity);
|
||||
}
|
||||
|
||||
if (HasComp<ChangelingRuleComponent>(entity))
|
||||
return;
|
||||
|
||||
MakeChangeling(entity, changelingRule);
|
||||
}
|
||||
|
||||
public bool MakeChangeling(EntityUid changeling, ChangelingRuleComponent rule, bool giveObjectives = true)
|
||||
{
|
||||
if (!_mindSystem.TryGetMind(changeling, out var mindId, out var mind))
|
||||
|
||||
@@ -69,9 +69,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
|
||||
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new PatchDoAfterEvent(), patch.Owner, target: target, used: patch.Owner)
|
||||
{
|
||||
BreakOnUserMove = true,
|
||||
BreakOnMove = true,
|
||||
BreakOnDamage = true,
|
||||
BreakOnTargetMove = true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -51,18 +51,17 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
SubscribeLocalEvent<EnergyDomeGeneratorComponent, GetVerbsEvent<ActivationVerb>>(AddToggleDomeVerb);
|
||||
SubscribeLocalEvent<EnergyDomeGeneratorComponent, ExaminedEvent>(OnExamine);
|
||||
|
||||
|
||||
SubscribeLocalEvent<EnergyDomeGeneratorComponent, ComponentRemove>(OnComponentRemove);
|
||||
|
||||
//Dome events
|
||||
SubscribeLocalEvent<EnergyDomeComponent, DamageChangedEvent>(OnDomeDamaged);
|
||||
}
|
||||
|
||||
|
||||
private void OnInit(Entity<EnergyDomeGeneratorComponent> generator, ref MapInitEvent args)
|
||||
{
|
||||
if (generator.Comp.CanDeviceNetworkUse)
|
||||
_signalSystem.EnsureSinkPorts(generator, generator.Comp.TogglePort, generator.Comp.OnPort, generator.Comp.OffPort);
|
||||
_signalSystem.EnsureSinkPorts(generator, generator.Comp.TogglePort, generator.Comp.OnPort,
|
||||
generator.Comp.OffPort);
|
||||
}
|
||||
|
||||
//different ways of use
|
||||
@@ -76,10 +75,12 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
{
|
||||
AttemptToggle(generator, true);
|
||||
}
|
||||
|
||||
if (args.Port == generator.Comp.OffPort)
|
||||
{
|
||||
AttemptToggle(generator, false);
|
||||
}
|
||||
|
||||
if (args.Port == generator.Comp.TogglePort)
|
||||
{
|
||||
AttemptToggle(generator, !generator.Comp.Enabled);
|
||||
@@ -102,17 +103,18 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
{
|
||||
args.PushMarkup(Loc.GetString(
|
||||
(generator.Comp.Enabled)
|
||||
? "energy-dome-on-examine-is-on-message"
|
||||
: "energy-dome-on-examine-is-off-message"
|
||||
));
|
||||
? "energy-dome-on-examine-is-on-message"
|
||||
: "energy-dome-on-examine-is-off-message"
|
||||
));
|
||||
}
|
||||
|
||||
private void AddToggleDomeVerb(Entity<EnergyDomeGeneratorComponent> generator, ref GetVerbsEvent<ActivationVerb> args)
|
||||
private void AddToggleDomeVerb(
|
||||
Entity<EnergyDomeGeneratorComponent> generator,
|
||||
ref GetVerbsEvent<ActivationVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || !generator.Comp.CanInteractUse)
|
||||
return;
|
||||
|
||||
var @event = args;
|
||||
ActivationVerb verb = new()
|
||||
{
|
||||
Text = Loc.GetString("energy-dome-verb-toggle"),
|
||||
@@ -121,6 +123,7 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void OnGetActions(Entity<EnergyDomeGeneratorComponent> generator, ref GetItemActionsEvent args)
|
||||
{
|
||||
if (generator.Comp.CanInteractUse)
|
||||
@@ -155,6 +158,7 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
if (args.Charge == 0)
|
||||
TurnOff(generator, true);
|
||||
}
|
||||
|
||||
private void OnDomeDamaged(Entity<EnergyDomeComponent> dome, ref DamageChangedEvent args)
|
||||
{
|
||||
if (dome.Comp.Generator == null)
|
||||
@@ -178,18 +182,19 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
_powerCell.TryGetBatteryFromSlot(generatorUid, out var cell);
|
||||
if (cell != null)
|
||||
{
|
||||
_battery.UseCharge(cell.Owner, energyLeak);
|
||||
_battery.UseCharge(generatorUid, energyLeak);
|
||||
|
||||
if (cell.Charge == 0)
|
||||
if (cell.CurrentCharge == 0)
|
||||
TurnOff((generatorUid, generatorComp), true);
|
||||
}
|
||||
}
|
||||
|
||||
//it seems to me it would not work well to hang both a powercell and an internal battery with wire charging on the object....
|
||||
if (TryComp<BatteryComponent>(generatorUid, out var battery)) {
|
||||
if (TryComp<BatteryComponent>(generatorUid, out var battery))
|
||||
{
|
||||
_battery.UseCharge(generatorUid, energyLeak);
|
||||
|
||||
if (battery.Charge == 0)
|
||||
if (battery.CurrentCharge == 0)
|
||||
TurnOff((generatorUid, generatorComp), true);
|
||||
}
|
||||
}
|
||||
@@ -213,44 +218,37 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
|
||||
public bool AttemptToggle(Entity<EnergyDomeGeneratorComponent> generator, bool status)
|
||||
{
|
||||
if (TryComp<UseDelayComponent>(generator, out var useDelay) && _useDelay.IsDelayed(new Entity<UseDelayComponent>(generator, useDelay)))
|
||||
if (TryComp<UseDelayComponent>(generator, out var useDelay) &&
|
||||
_useDelay.IsDelayed(new Entity<UseDelayComponent>(generator, useDelay)))
|
||||
{
|
||||
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
|
||||
_popup.PopupEntity(
|
||||
Loc.GetString("energy-dome-recharging"),
|
||||
generator);
|
||||
_popup.PopupEntity(Loc.GetString("energy-dome-recharging"), generator);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TryComp<PowerCellSlotComponent>(generator, out var powerCellSlot))
|
||||
if (TryComp<PowerCellSlotComponent>(generator, out _))
|
||||
{
|
||||
if (!_powerCell.TryGetBatteryFromSlot(generator, out var cell) && !TryComp(generator, out cell))
|
||||
if (!_powerCell.TryGetBatteryFromSlot(generator, out _) && !TryComp(generator, out BatteryComponent? _))
|
||||
{
|
||||
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
|
||||
_popup.PopupEntity(
|
||||
Loc.GetString("energy-dome-no-cell"),
|
||||
generator);
|
||||
_popup.PopupEntity(Loc.GetString("energy-dome-no-cell"), generator);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_powerCell.HasDrawCharge(generator))
|
||||
{
|
||||
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
|
||||
_popup.PopupEntity(
|
||||
Loc.GetString("energy-dome-no-power"),
|
||||
generator);
|
||||
_popup.PopupEntity(Loc.GetString("energy-dome-no-power"), generator);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (TryComp<BatteryComponent>(generator, out var battery))
|
||||
{
|
||||
if (battery.Charge == 0)
|
||||
if (battery.CurrentCharge == 0)
|
||||
{
|
||||
_audio.PlayPvs(generator.Comp.TurnOffSound, generator);
|
||||
_popup.PopupEntity(
|
||||
Loc.GetString("energy-dome-no-power"),
|
||||
generator);
|
||||
_popup.PopupEntity(Loc.GetString("energy-dome-no-power"), generator);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -284,7 +282,8 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
}
|
||||
|
||||
_powerCell.SetPowerCellDrawEnabled(generator, true);
|
||||
if (TryComp<BatterySelfRechargerComponent>(generator, out var recharger)) {
|
||||
if (TryComp<BatterySelfRechargerComponent>(generator, out var recharger))
|
||||
{
|
||||
recharger.AutoRecharge = true;
|
||||
}
|
||||
|
||||
@@ -326,4 +325,4 @@ public sealed partial class EnergyDomeSystem : EntitySystem
|
||||
? container.Owner
|
||||
: entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace Content.Server.Power.EntitySystems
|
||||
}
|
||||
if (comp.AutoRechargeRate < 0) //self discharging
|
||||
{
|
||||
if (batt.Charge == 0) continue;
|
||||
if (batt.CurrentCharge == 0) continue;
|
||||
UseCharge(uid, -comp.AutoRechargeRate * frameTime, batt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.SurveillanceCamera.Systems;
|
||||
using Content.Shared.DeviceNetwork;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.PowerCell;
|
||||
using Content.Shared.Clothing.EntitySystems;
|
||||
using Content.Shared.Examine;
|
||||
@@ -7,7 +8,7 @@ using Content.Shared.Item;
|
||||
using Content.Shared.PowerCell.Components;
|
||||
using Content.Shared.Toggleable;
|
||||
|
||||
namespace Content.Server.SurveillanceCamera;
|
||||
namespace Content.Server.SurveillanceCamera.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// This handles the bodycamera all itself. Activation, examine,init, powercell stuff.
|
||||
@@ -20,6 +21,7 @@ public sealed class SurveillanceBodyCameraSystem : EntitySystem
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SharedItemSystem _item = default!;
|
||||
[Dependency] private readonly ClothingSystem _clothing = default!;
|
||||
[Dependency] private readonly BatterySystem _battery = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -55,7 +57,7 @@ public sealed class SurveillanceBodyCameraSystem : EntitySystem
|
||||
if (!surComp.Active)
|
||||
continue;
|
||||
|
||||
if (!battery.TryUseCharge(cam.Wattage * frameTime))
|
||||
if (!_battery.TryUseCharge(uid, cam.Wattage * frameTime))
|
||||
{
|
||||
_surveillanceCameras.SetActive(uid, false, surComp);
|
||||
AppearanceChange(uid, surComp.Active);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Cargo.Systems;
|
||||
using Content.Server.Interaction;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
@@ -161,7 +160,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
||||
{
|
||||
if (dmg.Any())
|
||||
{
|
||||
_color.RaiseEffect(Color.Red, new List<EntityUid>() { hitEntity }, Filter.Pvs(hitEntity, entityManager: EntityManager));
|
||||
_color.RaiseEffect(Color.Red, [hitEntity], Filter.Pvs(hitEntity, entityManager: EntityManager));
|
||||
}
|
||||
|
||||
// TODO get fallback position for playing hit sound.
|
||||
@@ -223,7 +222,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
||||
Audio.PlayPvs(clumsy.ClumsySound, gunUid);
|
||||
|
||||
PopupSystem.PopupEntity(Loc.GetString("gun-clumsy"), user.Value);
|
||||
_adminLogger.Add(LogType.EntityDelete, LogImpact.Medium, $"{Loc.GetString("clumsy-gun-delete-log", ("prettyUser", ToPrettyString(user.Value)), ("prettyGun", ToPrettyString(gunUid)))}");
|
||||
Logs.Add(LogType.EntityDelete, LogImpact.Medium, $"{Loc.GetString("clumsy-gun-delete-log", ("prettyUser", ToPrettyString(user.Value)), ("prettyGun", ToPrettyString(gunUid)))}");
|
||||
Del(gunUid);
|
||||
userImpulse = false;
|
||||
return;
|
||||
@@ -240,7 +239,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
||||
var angle = GetRecoilAngle(Timing.CurTime, gun, mapDirection.ToAngle());
|
||||
|
||||
// If applicable, this ensures the projectile is parented to grid on spawn, instead of the map.
|
||||
var fromEnt = MapManager.TryFindGridAt(fromMap, out var gridUid, out _)
|
||||
var fromEnt = MapManager.TryFindGridAt(fromMap, out var gridUid, out var grid)
|
||||
? fromCoordinates.WithEntityId(gridUid, EntityManager)
|
||||
: new EntityCoordinates(MapManager.GetMapEntityId(fromMap.MapId), fromMap.Position);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public sealed class ChairLeakAspect : AspectSystem<ChairLeakAspectComponent>
|
||||
while (query.MoveNext(out var ent, out _))
|
||||
{
|
||||
if (TryComp(ent, out StrapComponent? strap))
|
||||
_buckle.StrapRemoveAll(strap);
|
||||
_buckle.StrapRemoveAll(ent, strap);
|
||||
|
||||
EntityManager.DeleteEntity(ent);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using Content.Server._Miracle.GulagSystem;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Antag;
|
||||
@@ -321,6 +322,21 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
return potentialTargets;
|
||||
}
|
||||
|
||||
public void AdminMakeCultist(EntityUid entity)
|
||||
{
|
||||
var cultistRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistRule == null)
|
||||
{
|
||||
GameTicker.StartGameRule("Cult", out var ruleEntity);
|
||||
cultistRule = Comp<CultRuleComponent>(ruleEntity);
|
||||
}
|
||||
|
||||
if (HasComp<CultistComponent>(entity))
|
||||
return;
|
||||
|
||||
MakeCultist(entity, cultistRule);
|
||||
}
|
||||
|
||||
public bool MakeCultist(EntityUid cultist, CultRuleComponent rule)
|
||||
{
|
||||
if (!_mindSystem.TryGetMind(cultist, out var mindId, out var mind))
|
||||
|
||||
@@ -94,7 +94,8 @@ public partial class CultSystem
|
||||
|
||||
private void OnTeleport(EntityUid uid, CultistComponent component, CultTeleportTargetActionEvent args)
|
||||
{
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) || !TryComp<ActorComponent>(uid, out var actor))
|
||||
if (!TryComp<BloodstreamComponent>(args.Performer, out var bloodstream) ||
|
||||
!TryComp<ActorComponent>(uid, out var actor))
|
||||
return;
|
||||
|
||||
if (!TryComp<CultistComponent>(args.Target, out _) &&
|
||||
@@ -246,8 +247,7 @@ public partial class CultSystem
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Performer, TimeSpan.FromSeconds(2),
|
||||
new ShacklesEvent(), args.Performer, args.Target)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
BreakOnMove = true,
|
||||
BreakOnDamage = true
|
||||
});
|
||||
|
||||
@@ -304,4 +304,4 @@ public partial class CultSystem
|
||||
_handsSystem.TryPickupAnyHand(args.Performer, dagger);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server._White.Cult.GameRule;
|
||||
using Content.Server._White.Cult.Runes.Comps;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared._White.Cult;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
|
||||
|
||||
namespace Content.Server._White.Cult.Runes.Systems;
|
||||
@@ -16,6 +16,7 @@ public partial class CultSystem
|
||||
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly ITileDefinitionManager _tileDefinition = default!;
|
||||
[Dependency] private readonly MapSystem _map = default!;
|
||||
|
||||
public void InitializeBuffSystem()
|
||||
{
|
||||
@@ -32,12 +33,10 @@ public partial class CultSystem
|
||||
|
||||
private void AnyCultistNearTile()
|
||||
{
|
||||
var cultists = EntityQuery<CultistComponent>();
|
||||
var cultistsQuery = EntityQueryEnumerator<CultistComponent>();
|
||||
|
||||
foreach (var cultist in cultists)
|
||||
while (cultistsQuery.MoveNext(out var uid, out _))
|
||||
{
|
||||
var uid = cultist.Owner;
|
||||
|
||||
if (HasComp<CultBuffComponent>(uid))
|
||||
continue;
|
||||
|
||||
@@ -56,16 +55,15 @@ public partial class CultSystem
|
||||
|
||||
private void UpdateBuffTimers(float frameTime)
|
||||
{
|
||||
var buffs = EntityQuery<CultBuffComponent>();
|
||||
var buffsQuery = EntityQueryEnumerator<CultBuffComponent>();
|
||||
|
||||
foreach (var buff in buffs)
|
||||
while (buffsQuery.MoveNext(out var uid, out var buff))
|
||||
{
|
||||
var uid = buff.Owner;
|
||||
var remainingTime = buff.BuffTime;
|
||||
|
||||
remainingTime -= TimeSpan.FromSeconds(frameTime);
|
||||
|
||||
if (TryComp<CultistComponent>(uid, out var cultist))
|
||||
if (HasComp<CultistComponent>(uid))
|
||||
{
|
||||
if (remainingTime < CultBuffComponent.CultTileBuffTime && AnyCultTilesNearby(uid))
|
||||
remainingTime = CultBuffComponent.CultTileBuffTime;
|
||||
@@ -75,21 +73,35 @@ public partial class CultSystem
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool AnyCultTilesNearby(EntityUid uid)
|
||||
{
|
||||
var localpos = Transform(uid).Coordinates.Position;
|
||||
|
||||
if (!TryComp<CultistComponent>(uid, out var cultist))
|
||||
if (!TryComp<CultistComponent>(uid, out _))
|
||||
return false;
|
||||
|
||||
var radius = CultBuffComponent.NearbyTilesBuffRadius;
|
||||
|
||||
if (!_mapManager.TryGetGrid(Transform(uid).GridUid, out var grid))
|
||||
var gridUid = Transform(uid).GridUid;
|
||||
if (!gridUid.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryComp(gridUid, out MapGridComponent? grid))
|
||||
return false;
|
||||
|
||||
var tilesRefs = grid.GetLocalTilesIntersecting(new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius)));
|
||||
var cultTileDef = (ContentTileDefinition) _tileDefinition[$"{CultRuleComponent.CultFloor}"];
|
||||
var tilesRefs = _map.GetLocalTilesIntersecting(gridUid.Value, grid, new Box2(
|
||||
localpos + new Vector2(-radius, -radius),
|
||||
localpos + new Vector2(radius, radius)));
|
||||
|
||||
var cultRule = EntityManager.EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultRule is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var cultTileDef = (ContentTileDefinition) _tileDefinition[$"{cultRule.CultFloor}"];
|
||||
var cultTile = new Tile(cultTileDef.TileId);
|
||||
|
||||
return tilesRefs.Any(tileRef => tileRef.Tile.TypeId == cultTile.TypeId);
|
||||
@@ -97,11 +109,10 @@ public partial class CultSystem
|
||||
|
||||
private void RemoveExpiredBuffs()
|
||||
{
|
||||
var buffs = EntityQuery<CultBuffComponent>();
|
||||
var buffsQuery = EntityQueryEnumerator<CultBuffComponent>();
|
||||
|
||||
foreach (var buff in buffs)
|
||||
while (buffsQuery.MoveNext(out var uid, out var buff))
|
||||
{
|
||||
var uid = buff.Owner;
|
||||
var remainingTime = buff.BuffTime;
|
||||
|
||||
if (remainingTime <= TimeSpan.Zero)
|
||||
@@ -111,4 +122,4 @@ public partial class CultSystem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,10 +112,8 @@ public sealed partial class CultSystem : EntitySystem
|
||||
InitializeConstructs();
|
||||
InitializeBarrierSystem();
|
||||
InitializeConstructsAbilities();
|
||||
InitializeCultists();
|
||||
InitializeActions();
|
||||
InitializeVerb();
|
||||
|
||||
}
|
||||
|
||||
private float _timeToDraw;
|
||||
@@ -325,9 +323,15 @@ public sealed partial class CultSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
var cultRule = EntityManager.EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultRule is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var solutions = _solutionContainerSystem.EnumerateSolutions((args.OtherEntity, solution));
|
||||
|
||||
if (solutions.Any(x => x.Solution.Comp.Solution.ContainsPrototype(CultRuleComponent.HolyWaterReagent)))
|
||||
if (solutions.Any(x => x.Solution.Comp.Solution.ContainsPrototype(cultRule.HolyWaterReagent)))
|
||||
{
|
||||
Del(uid);
|
||||
}
|
||||
@@ -522,10 +526,7 @@ public sealed partial class CultSystem : EntitySystem
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_entityManager.TryGetComponent<ActorComponent>(target, out var actorComponent))
|
||||
return false;
|
||||
|
||||
_ruleSystem.MakeCultist(actorComponent.PlayerSession);
|
||||
_ruleSystem.AdminMakeCultist(target);
|
||||
_stunSystem.TryStun(target, TimeSpan.FromSeconds(2f), false);
|
||||
HealCultist(target);
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public sealed partial class CultSystem
|
||||
new DoAfterArgs(_entityManager, ent, creationTime, new SpellCreatedEvent {Spell = action}, ent)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnUserMove = true
|
||||
BreakOnMove = true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,39 +4,28 @@ using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared._White.Jukebox;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server._White.Jukebox;
|
||||
|
||||
public sealed class JukeboxSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly PvsOverrideSystem _pvsOverrideSystem = default!;
|
||||
|
||||
private readonly List<JukeboxComponent> _playingJukeboxes = [];
|
||||
|
||||
private readonly List<JukeboxComponent> _playingJukeboxes = new();
|
||||
|
||||
private float _updateTimerDefaultTime = 1f;
|
||||
private const float UpdateTimerDefaultTime = 1f;
|
||||
private float _updateTimer;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeNetworkEvent<JukeboxRequestSongPlay>(OnSongRequestPlay);
|
||||
SubscribeLocalEvent<JukeboxComponent, InteractUsingEvent>(OnInteract);
|
||||
SubscribeLocalEvent<JukeboxComponent, ComponentGetState>(OnGetState);
|
||||
SubscribeLocalEvent<JukeboxComponent, JukeboxStopRequest>(OnRequestStop);
|
||||
SubscribeLocalEvent<JukeboxComponent, JukeboxRepeatToggled>(OnRepeatToggled);
|
||||
SubscribeLocalEvent<JukeboxComponent, JukeboxEjectRequest>(OnEjectRequest);
|
||||
@@ -57,13 +46,13 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
|
||||
private void OnEjectRequest(EntityUid uid, JukeboxComponent component, JukeboxEjectRequest args)
|
||||
{
|
||||
if(component.PlayingSongData != null) return;
|
||||
if (component.PlayingSongData != null) return;
|
||||
|
||||
var containedEntities = component.TapeContainer.ContainedEntities;
|
||||
|
||||
if (containedEntities.Count > 0)
|
||||
{
|
||||
_containerSystem.EmptyContainer(component.TapeContainer, true).ToList();
|
||||
_containerSystem.EmptyContainer(component.TapeContainer, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +62,7 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
if (jukeboxComponent.PlayingSongData != null) return;
|
||||
if (jukeboxComponent.TapeContainer.ContainedEntities.Count == 0) return;
|
||||
|
||||
var removeTapeVerb = new Verb()
|
||||
var removeTapeVerb = new Verb
|
||||
{
|
||||
Text = "Вытащить касету",
|
||||
Priority = 10000,
|
||||
@@ -95,77 +84,78 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
|
||||
private void OnRepeatToggled(EntityUid uid, JukeboxComponent component, JukeboxRepeatToggled args)
|
||||
{
|
||||
component.Repeating = args.NewState;
|
||||
Dirty(component);
|
||||
component.Playing = args.NewState;
|
||||
Dirty(uid, component);
|
||||
}
|
||||
|
||||
private void OnRequestStop(EntityUid uid, JukeboxComponent component, JukeboxStopRequest args)
|
||||
{
|
||||
component.PlayingSongData = null;
|
||||
Dirty(component);
|
||||
Dirty(uid, component);
|
||||
}
|
||||
|
||||
|
||||
private void OnInteract(EntityUid uid, JukeboxComponent component, InteractUsingEvent args)
|
||||
{
|
||||
if(component.PlayingSongData != null) return;
|
||||
if (component.PlayingSongData != null) return;
|
||||
|
||||
if (TryComp<TapeComponent>(args.Used, out var tape))
|
||||
if (!HasComp<TapeComponent>(args.Used))
|
||||
return;
|
||||
|
||||
var containedEntities = component.TapeContainer.ContainedEntities;
|
||||
|
||||
if (containedEntities.Count >= 1)
|
||||
{
|
||||
var containedEntities = component.TapeContainer.ContainedEntities;
|
||||
var removedTapes = _containerSystem.EmptyContainer(component.TapeContainer, true).ToList();
|
||||
_containerSystem.Insert(args.Used, component.TapeContainer);
|
||||
|
||||
if (containedEntities.Count >= 1)
|
||||
foreach (var tapeUid in removedTapes)
|
||||
{
|
||||
var removedTapes = _containerSystem.EmptyContainer(component.TapeContainer, true).ToList();
|
||||
component.TapeContainer.Insert(args.Used);
|
||||
|
||||
foreach (var tapeUid in removedTapes)
|
||||
{
|
||||
_handsSystem.PickupOrDrop(args.User, tapeUid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
component.TapeContainer.Insert(args.Used);
|
||||
_handsSystem.PickupOrDrop(args.User, tapeUid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_containerSystem.Insert(args.Used, component.TapeContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSongRequestPlay(JukeboxRequestSongPlay msg, EntitySessionEventArgs args)
|
||||
{
|
||||
var jukebox = Comp<JukeboxComponent>(GetEntity(msg.Jukebox!.Value));
|
||||
jukebox.Repeating = true;
|
||||
var entity = GetEntity(msg.Jukebox!.Value);
|
||||
var jukebox = Comp<JukeboxComponent>(entity);
|
||||
jukebox.Playing = true;
|
||||
|
||||
var songData = new PlayingSongData()
|
||||
var songData = new PlayingSongData
|
||||
{
|
||||
SongName = msg.SongName,
|
||||
SongPath = msg.SongPath,
|
||||
ActualSongLengthSeconds = msg.SongDuration,
|
||||
PlaybackPosition = 0f
|
||||
};
|
||||
|
||||
jukebox.PlayingSongData = songData;
|
||||
|
||||
_playingJukeboxes.Add(jukebox);
|
||||
|
||||
Dirty(jukebox);
|
||||
Dirty(entity, jukebox);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
if (_updateTimer <= _updateTimerDefaultTime)
|
||||
if (_updateTimer <= UpdateTimerDefaultTime)
|
||||
{
|
||||
_updateTimer += frameTime;
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessPlayingJukeboxes(frameTime);
|
||||
ProcessPlayingJukeboxes();
|
||||
}
|
||||
|
||||
private void ProcessPlayingJukeboxes(float frameTime)
|
||||
private void ProcessPlayingJukeboxes()
|
||||
{
|
||||
for (int i = _playingJukeboxes.Count - 1; i >= 0; i--)
|
||||
for (var i = _playingJukeboxes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var playingJukeboxData = _playingJukeboxes[i];
|
||||
|
||||
@@ -177,9 +167,10 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
|
||||
playingJukeboxData.PlayingSongData.PlaybackPosition += _updateTimer;
|
||||
|
||||
if (playingJukeboxData.PlayingSongData.PlaybackPosition >= playingJukeboxData.PlayingSongData.ActualSongLengthSeconds)
|
||||
if (playingJukeboxData.PlayingSongData.PlaybackPosition >=
|
||||
playingJukeboxData.PlayingSongData.ActualSongLengthSeconds)
|
||||
{
|
||||
if (playingJukeboxData.Repeating)
|
||||
if (playingJukeboxData.Playing)
|
||||
{
|
||||
playingJukeboxData.PlayingSongData.PlaybackPosition = 0;
|
||||
}
|
||||
@@ -195,14 +186,4 @@ public sealed class JukeboxSystem : EntitySystem
|
||||
|
||||
_updateTimer = 0;
|
||||
}
|
||||
|
||||
private void OnGetState(EntityUid uid, JukeboxComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new JukeboxComponentState()
|
||||
{
|
||||
SongData = component.PlayingSongData,
|
||||
Playing = component.Repeating,
|
||||
Volume = component.Volume
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ public sealed class ServerJukeboxSongsSyncManager : JukeboxSongsSyncManager
|
||||
}
|
||||
}
|
||||
|
||||
public (string songName, ResPath path) SyncSongData(string songName, List<byte> bytes)
|
||||
public (string SongName, ResPath Path) SyncSongData(string songName, List<byte> bytes)
|
||||
{
|
||||
if (ContentRoot.TryGetFile(new ResPath(songName + ".ogg"), out _))
|
||||
{
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared._White.Jukebox;
|
||||
using Robust.Shared.Configuration;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -16,16 +16,15 @@ namespace Content.Server._White.Jukebox;
|
||||
|
||||
public sealed class TapeCreatorSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly ServerJukeboxSongsSyncManager _songsSyncManager = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
[Dependency] private readonly TagSystem _tag = default!;
|
||||
|
||||
private const int RecordTime = 25;
|
||||
|
||||
private readonly int _recordTime = 25;
|
||||
|
||||
private static string TapeCreatorContainerName = "tape_creator_container";
|
||||
private const string TapeCreatorContainerName = "tape_creator_container";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -44,7 +43,7 @@ public sealed class TapeCreatorSystem : EntitySystem
|
||||
if (ev.Hands == null) return;
|
||||
if (component.TapeContainer.ContainedEntities.Count == 0) return;
|
||||
|
||||
var removeTapeVerb = new Verb()
|
||||
var removeTapeVerb = new Verb
|
||||
{
|
||||
Text = "Вытащить касету",
|
||||
Priority = 10000,
|
||||
@@ -52,15 +51,15 @@ public sealed class TapeCreatorSystem : EntitySystem
|
||||
Act = () =>
|
||||
{
|
||||
var tapes = component.TapeContainer.ContainedEntities.ToList();
|
||||
_containerSystem.EmptyContainer(component.TapeContainer, true);
|
||||
_container.EmptyContainer(component.TapeContainer, true);
|
||||
|
||||
foreach (var tape in tapes)
|
||||
{
|
||||
_handsSystem.PickupOrDrop(ev.User, tape);
|
||||
_hands.PickupOrDrop(ev.User, tape);
|
||||
}
|
||||
|
||||
component.InsertedTape = null;
|
||||
Dirty(component);
|
||||
Dirty(uid, component);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,7 +68,7 @@ public sealed class TapeCreatorSystem : EntitySystem
|
||||
|
||||
private void OnTapeStateChanged(EntityUid uid, TapeComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new TapeComponentState()
|
||||
args.State = new TapeComponentState
|
||||
{
|
||||
Songs = component.Songs
|
||||
};
|
||||
@@ -87,95 +86,105 @@ public sealed class TapeCreatorSystem : EntitySystem
|
||||
|
||||
private void OnComponentInit(EntityUid uid, TapeCreatorComponent component, ComponentInit args)
|
||||
{
|
||||
component.TapeContainer = _containerSystem.EnsureContainer<Container>(uid, TapeCreatorContainerName);
|
||||
component.TapeContainer = _container.EnsureContainer<Container>(uid, TapeCreatorContainerName);
|
||||
}
|
||||
|
||||
private void OnInteract(EntityUid uid, TapeCreatorComponent component, InteractUsingEvent args)
|
||||
{
|
||||
if(component.Recording) return;
|
||||
if (component.Recording)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<TapeComponent>(args.Used, out var tape))
|
||||
if (HasComp<TapeComponent>(args.Used))
|
||||
{
|
||||
var containedEntities = component.TapeContainer.ContainedEntities;
|
||||
|
||||
if (containedEntities.Count > 1)
|
||||
{
|
||||
var removedTapes = _containerSystem.EmptyContainer(component.TapeContainer, true).ToList();
|
||||
component.TapeContainer.Insert(args.Used);
|
||||
var removedTapes = _container.EmptyContainer(component.TapeContainer, true).ToList();
|
||||
_container.Insert(args.Used, component.TapeContainer);
|
||||
|
||||
foreach (var tapes in removedTapes)
|
||||
{
|
||||
_handsSystem.PickupOrDrop(args.User, tapes);
|
||||
_hands.PickupOrDrop(args.User, tapes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
component.TapeContainer.Insert(args.Used);
|
||||
_container.Insert(args.Used, component.TapeContainer);
|
||||
}
|
||||
|
||||
component.InsertedTape = GetNetEntity(tape.Owner);
|
||||
Dirty(component);
|
||||
component.InsertedTape = GetNetEntity(args.Used);
|
||||
Dirty(uid, component);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_tagSystem.HasTag(args.Used, "TapeRecorderCoin"))
|
||||
if (_tag.HasTag(args.Used, "TapeRecorderCoin"))
|
||||
{
|
||||
Del(args.Used);
|
||||
component.CoinBalance += 1;
|
||||
Dirty(component);
|
||||
|
||||
return;
|
||||
Dirty(uid, component);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSongUploaded(JukeboxSongUploadRequest ev)
|
||||
{
|
||||
if(!TryComp<TapeCreatorComponent>(GetEntity(ev.TapeCreatorUid), out var tapeCreatorComponent)) return;
|
||||
var tapeCreator = GetEntity(ev.TapeCreatorUid);
|
||||
if (!TryComp<TapeCreatorComponent>(tapeCreator, out var tapeCreatorComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tapeCreatorComponent.InsertedTape.HasValue || tapeCreatorComponent.CoinBalance <= 0)
|
||||
{
|
||||
_popupSystem.PopupEntity("Т# %ак@ э*^о сdf{ал б2я~b? Запись была прервана.", tapeCreatorComponent.Owner);
|
||||
_popup.PopupEntity("Т# %ак@ э*^о сdf{ал б2я~b? Запись была прервана.", tapeCreator);
|
||||
return;
|
||||
}
|
||||
|
||||
tapeCreatorComponent.CoinBalance -= 1;
|
||||
tapeCreatorComponent.Recording = true;
|
||||
|
||||
var tapeComponent = Comp<TapeComponent>(GetEntity(tapeCreatorComponent.InsertedTape.Value));
|
||||
var insertedTape = GetEntity(tapeCreatorComponent.InsertedTape.Value);
|
||||
var tapeComponent = Comp<TapeComponent>(insertedTape);
|
||||
var songData = _songsSyncManager.SyncSongData(ev.SongName, ev.SongBytes);
|
||||
|
||||
var song = new JukeboxSong()
|
||||
var song = new JukeboxSong
|
||||
{
|
||||
SongName = songData.songName,
|
||||
SongPath = songData.path
|
||||
SongName = songData.SongName,
|
||||
SongPath = songData.Path
|
||||
};
|
||||
|
||||
tapeComponent.Songs.Add(song);
|
||||
_popupSystem.PopupEntity($"Запись началась, примерное время ожидания: {_recordTime} секунд", tapeCreatorComponent.Owner);
|
||||
_popup.PopupEntity($"Запись началась, примерное время ожидания: {RecordTime} секунд", tapeCreator);
|
||||
|
||||
DirtyEntity(GetEntity(ev.TapeCreatorUid));
|
||||
Dirty(tapeComponent);
|
||||
StartRecordDelayAsync(tapeCreatorComponent, _popupSystem, _containerSystem);
|
||||
Dirty(insertedTape, tapeComponent);
|
||||
StartRecordDelayAsync(tapeCreator, tapeCreatorComponent, _popup, _container);
|
||||
}
|
||||
|
||||
private async void StartRecordDelayAsync(TapeCreatorComponent component, SharedPopupSystem popupSystem, SharedContainerSystem containerSystem)
|
||||
private async void StartRecordDelayAsync(
|
||||
EntityUid uid,
|
||||
TapeCreatorComponent component,
|
||||
SharedPopupSystem popupSystem,
|
||||
SharedContainerSystem containerSystem)
|
||||
{
|
||||
var recordTimeDelay = _recordTime * 1000 / 10;
|
||||
const int recordTimeDelay = RecordTime * 1000 / 10;
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
popupSystem.PopupEntity($"Запись мозговой активности выполнена на {i * 10}%", component.Owner);
|
||||
popupSystem.PopupEntity($"Запись мозговой активности выполнена на {i * 10}%", uid);
|
||||
await Task.Delay(recordTimeDelay);
|
||||
}
|
||||
|
||||
|
||||
containerSystem.EmptyContainer(component.TapeContainer, force: true).ToList();
|
||||
containerSystem.EmptyContainer(component.TapeContainer, force: true);
|
||||
|
||||
component.Recording = false;
|
||||
component.InsertedTape = null;
|
||||
|
||||
popupSystem.PopupEntity($"Запись мозговой активности завершена", component.Owner);
|
||||
Dirty(component);
|
||||
popupSystem.PopupEntity("Запись мозговой активности завершена", uid);
|
||||
Dirty(uid, component);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ namespace Content.Server._White.Keyhole;
|
||||
|
||||
public sealed partial class KeyholeSystem : EntitySystem
|
||||
{
|
||||
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
@@ -37,6 +36,11 @@ public sealed partial class KeyholeSystem : EntitySystem
|
||||
|
||||
private void OnKeyInsert(EntityUid uid, KeyComponent component, AfterInteractEvent ev)
|
||||
{
|
||||
if (!ev.Target.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<KeyformComponent>(ev.Target, out var keyformComponent))
|
||||
OnKeyInsertForm(uid, component, keyformComponent, ev);
|
||||
|
||||
@@ -45,24 +49,24 @@ public sealed partial class KeyholeSystem : EntitySystem
|
||||
|
||||
keyholeComponent.FormId ??= component.FormId;
|
||||
|
||||
if (!CanLock(keyholeComponent.Owner, keyholeComponent, component))
|
||||
if (!CanLock(ev.Target.Value, keyholeComponent, component))
|
||||
return;
|
||||
|
||||
var doAfterEventArgs =
|
||||
new DoAfterArgs(EntityManager, ev.User, keyholeComponent.Delay, new KeyInsertDoAfterEvent(), ev.Target, ev.Used)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
BreakOnDamage = true
|
||||
};
|
||||
var doAfterEventArgs = new DoAfterArgs(EntityManager, ev.User, keyholeComponent.Delay,
|
||||
new KeyInsertDoAfterEvent(), ev.Target, ev.Used)
|
||||
{
|
||||
BreakOnMove = true,
|
||||
BreakOnDamage = true
|
||||
};
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||
}
|
||||
|
||||
private bool CanLock(EntityUid uid, KeyholeComponent keyholeComponent, KeyComponent keyComponent)
|
||||
{
|
||||
var can = TryComp<DoorComponent>(uid, out var doorComponent) &&
|
||||
keyholeComponent.FormId == keyComponent.FormId &&
|
||||
doorComponent.State == DoorState.Closed;
|
||||
keyholeComponent.FormId == keyComponent.FormId &&
|
||||
doorComponent.State == DoorState.Closed;
|
||||
|
||||
return can;
|
||||
}
|
||||
@@ -80,13 +84,14 @@ public sealed partial class KeyholeSystem : EntitySystem
|
||||
private bool IsStateChanging(EntityUid uid)
|
||||
{
|
||||
return TryComp<DoorComponent>(uid, out var doorComponent) &&
|
||||
(doorComponent.State == DoorState.Closing || doorComponent.State == DoorState.Opening);
|
||||
(doorComponent.State == DoorState.Closing || doorComponent.State == DoorState.Opening);
|
||||
}
|
||||
|
||||
private void Lock(EntityUid uid, KeyholeComponent component, EntityUid user)
|
||||
{
|
||||
var sound = component.Locked ? component.UnlockSound : component.LockSound;
|
||||
var message = Loc.GetString(component.Locked ? "key-unlock-message" : "key-lock-message", ("name", user), ("door", uid));
|
||||
var message = Loc.GetString(component.Locked ? "key-unlock-message" : "key-lock-message", ("name", user),
|
||||
("door", uid));
|
||||
|
||||
var audioParams = new AudioParams().WithVolume(-5f);
|
||||
|
||||
@@ -96,7 +101,11 @@ public sealed partial class KeyholeSystem : EntitySystem
|
||||
component.Locked = !component.Locked;
|
||||
}
|
||||
|
||||
private void OnKeyInsertForm(EntityUid uid, KeyComponent keyComponent, KeyformComponent keyformComponent, AfterInteractEvent args)
|
||||
private void OnKeyInsertForm(
|
||||
EntityUid uid,
|
||||
KeyComponent keyComponent,
|
||||
KeyformComponent keyformComponent,
|
||||
AfterInteractEvent args)
|
||||
{
|
||||
if (!keyformComponent.IsUsed)
|
||||
{
|
||||
@@ -104,16 +113,16 @@ public sealed partial class KeyholeSystem : EntitySystem
|
||||
_appearance.SetData(keyformComponent.Owner, KeyformVisuals.IsUsed, true);
|
||||
|
||||
_audio.PlayPvs(keyformComponent.PressSound, uid);
|
||||
_popupSystem.PopupEntity(Loc.GetString("key-pressed-in-keyform-message-first", ("user", args.User), ("key", uid)), uid);
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("key-pressed-in-keyform-message-first", ("user", args.User), ("key", uid)), uid);
|
||||
|
||||
keyformComponent.IsUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyComponent.FormId = keyformComponent.FormId;
|
||||
_popupSystem.PopupEntity(Loc.GetString("key-pressed-in-keyform-message", ("user", args.User), ("key", uid)), uid);
|
||||
_popupSystem.PopupEntity(Loc.GetString("key-pressed-in-keyform-message", ("user", args.User), ("key", uid)),
|
||||
uid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
using Content.Server.Chat.Managers;
|
||||
using System.Linq;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Chat.Managers;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Server._White.Sponsors;
|
||||
@@ -17,18 +14,11 @@ using Content.Shared.GameTicking;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared._White;
|
||||
using Content.Shared._White.MeatyOre;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared._White;
|
||||
using Content.Shared._White.MeatyOre;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
@@ -49,21 +39,19 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||
[Dependency] private readonly PvsOverrideSystem _pvsOverrideSystem = default!;
|
||||
[Dependency] private readonly RoleSystem _roleSystem = default!;
|
||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||
[Dependency] private readonly SharedJobSystem _jobSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
|
||||
|
||||
private HttpClient _httpClient = default!;
|
||||
private string _apiUrl = default!;
|
||||
|
||||
private static readonly string StorePresetPrototype = "StorePresetMeatyOre";
|
||||
private static readonly string MeatyOreCurrencyPrototype = "MeatyOreCoin";
|
||||
private const string StorePresetPrototype = "StorePresetMeatyOre";
|
||||
private const string MeatyOreCurrencyPrototype = "MeatyOreCoin";
|
||||
|
||||
private bool _meatyOrePanelEnabled;
|
||||
private bool _antagGrantEnabled;
|
||||
|
||||
private readonly Dictionary<NetUserId, StoreComponent> _meatyOreStores = new();
|
||||
private readonly Dictionary<NetUserId, (EntityUid Entity, StoreComponent Component)> _meatyOreStores = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -73,17 +61,16 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
|
||||
_configurationManager.OnValueChanged(WhiteCVars.MeatyOrePanelEnabled, OnPanelEnableChanged, true);
|
||||
_configurationManager.OnValueChanged(WhiteCVars.OnlyInOhio, s => _apiUrl = s, true);
|
||||
_configurationManager.OnValueChanged(WhiteCVars.EnableGrantAntag, b => _antagGrantEnabled = b, true );
|
||||
_configurationManager.OnValueChanged(WhiteCVars.EnableGrantAntag, b => _antagGrantEnabled = b, true);
|
||||
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnPostRoundCleanup);
|
||||
SubscribeNetworkEvent<MeatyOreShopRequestEvent>(OnShopRequested);
|
||||
SubscribeLocalEvent<GetVerbsEvent<Verb>>(MeatyOreVerbs);
|
||||
|
||||
}
|
||||
|
||||
private void MeatyOreVerbs(GetVerbsEvent<Verb> ev)
|
||||
{
|
||||
if(!_antagGrantEnabled)
|
||||
if (!_antagGrantEnabled)
|
||||
return;
|
||||
|
||||
if (!EntityManager.TryGetComponent<ActorComponent>(ev.User, out var actorComponent))
|
||||
@@ -95,23 +82,22 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
if (!HasComp<HumanoidAppearanceComponent>(ev.Target))
|
||||
return;
|
||||
|
||||
if (!TryGetStore(actorComponent.PlayerSession, out var store))
|
||||
if (!TryGetStore(actorComponent.PlayerSession, out var store, out var storeEntity))
|
||||
return;
|
||||
|
||||
var verb = new Verb()
|
||||
var verb = new Verb
|
||||
{
|
||||
Text = $"Выдать роль.",
|
||||
Text = "Выдать роль.",
|
||||
ConfirmationPopup = true,
|
||||
Message = $"Цена - {MeatyOreCurrencyPrototype}:10",
|
||||
Act = () =>
|
||||
{
|
||||
TryAddRole(ev.User, ev.Target, store);
|
||||
TryAddRole(ev.User, ev.Target, store, storeEntity.Value);
|
||||
},
|
||||
Category = VerbCategory.MeatyOre
|
||||
};
|
||||
|
||||
ev.Verbs.Add(verb);
|
||||
|
||||
}
|
||||
|
||||
private void OnPanelEnableChanged(bool enabled)
|
||||
@@ -120,57 +106,66 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
{
|
||||
foreach (var meatyOreStoreData in _meatyOreStores)
|
||||
{
|
||||
var session = _playerManager.GetSessionByUserId(meatyOreStoreData.Key);
|
||||
var session = _playerManager.GetSessionById(meatyOreStoreData.Key);
|
||||
|
||||
var playerEntity = session.AttachedEntity;
|
||||
|
||||
if(!playerEntity.HasValue)
|
||||
if (!playerEntity.HasValue)
|
||||
continue;
|
||||
|
||||
_storeSystem.CloseUi(playerEntity.Value, meatyOreStoreData.Value);
|
||||
_storeSystem.CloseUi(playerEntity.Value, meatyOreStoreData.Value.Component);
|
||||
}
|
||||
}
|
||||
|
||||
_meatyOrePanelEnabled = enabled;
|
||||
}
|
||||
|
||||
private void OnShopRequested(MeatyOreShopRequestEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
|
||||
var playerSession = args.SenderSession;
|
||||
|
||||
if (!_meatyOrePanelEnabled)
|
||||
{
|
||||
_chatManager.DispatchServerMessage(playerSession!, "Мясная панель отключена на данном сервере! Приятной игры!");
|
||||
_chatManager.DispatchServerMessage(playerSession,
|
||||
"Мясная панель отключена на данном сервере! Приятной игры!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var playerEntity = args.SenderSession.AttachedEntity;
|
||||
|
||||
if(!playerEntity.HasValue)
|
||||
if (!playerEntity.HasValue)
|
||||
return;
|
||||
|
||||
if(!HasComp<HumanoidAppearanceComponent>(playerEntity.Value))
|
||||
if (!HasComp<HumanoidAppearanceComponent>(playerEntity.Value))
|
||||
return;
|
||||
|
||||
if(!TryGetStore(playerSession!, out var storeComponent))
|
||||
if (!TryGetStore(playerSession, out var storeComponent, out var storeEntity))
|
||||
return;
|
||||
|
||||
_pvsOverrideSystem.AddSessionOverride(storeComponent.Owner, playerSession!);
|
||||
_storeSystem.ToggleUi(playerEntity.Value, storeComponent.Owner, storeComponent);
|
||||
_pvsOverrideSystem.AddSessionOverride(storeEntity.Value, playerSession);
|
||||
_storeSystem.ToggleUi(playerEntity.Value, storeEntity.Value, storeComponent);
|
||||
}
|
||||
|
||||
private bool TryGetStore(ICommonSession session, out StoreComponent store)
|
||||
private bool TryGetStore(ICommonSession session, out StoreComponent store, [NotNullWhen(true)] out EntityUid? storeEntity)
|
||||
{
|
||||
store = null!;
|
||||
storeEntity = null!;
|
||||
|
||||
if (!_sponsorsManager.TryGetInfo(session.UserId, out var sponsorInfo))
|
||||
return false;
|
||||
if (_meatyOreStores.TryGetValue(session.UserId, out store!))
|
||||
|
||||
if (_meatyOreStores.TryGetValue(session.UserId, out var pair))
|
||||
{
|
||||
storeEntity = pair.Entity;
|
||||
store = pair.Component;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sponsorInfo.MeatyOreCoin == 0)
|
||||
return false;
|
||||
|
||||
store = CreateStore(session.UserId, sponsorInfo.MeatyOreCoin);
|
||||
(storeEntity, store) = CreateStore(session.UserId, sponsorInfo.MeatyOreCoin);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -178,29 +173,31 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
{
|
||||
foreach (var store in _meatyOreStores.Values)
|
||||
{
|
||||
Del(store.Owner);
|
||||
Del(store.Entity);
|
||||
}
|
||||
|
||||
_meatyOreStores.Clear();
|
||||
}
|
||||
|
||||
private StoreComponent CreateStore(NetUserId userId, int balance)
|
||||
private (EntityUid, StoreComponent) CreateStore(NetUserId userId, int balance)
|
||||
{
|
||||
var session = _playerManager.GetSessionByUserId(userId);
|
||||
var shopEntity = _entityManager.SpawnEntity("StoreMeatyOreEntity", MapCoordinates.Nullspace);
|
||||
var storeComponent = Comp<StoreComponent>(shopEntity);
|
||||
var session = _playerManager.GetSessionById(userId);
|
||||
var storeEntity = _entityManager.SpawnEntity("StoreMeatyOreEntity", MapCoordinates.Nullspace);
|
||||
var storeComponent = Comp<StoreComponent>(storeEntity);
|
||||
|
||||
_storeSystem.InitializeFromPreset(StorePresetPrototype, shopEntity, storeComponent);
|
||||
_storeSystem.InitializeFromPreset(StorePresetPrototype, storeEntity, storeComponent);
|
||||
storeComponent.Balance.Clear();
|
||||
|
||||
_storeSystem.TryAddCurrency(new Dictionary<string, FixedPoint2>() { { MeatyOreCurrencyPrototype, balance } }, storeComponent.Owner, storeComponent);
|
||||
_meatyOreStores[userId] = storeComponent;
|
||||
_pvsOverrideSystem.AddSessionOverride(shopEntity, session);
|
||||
_storeSystem.TryAddCurrency(new Dictionary<string, FixedPoint2> { { MeatyOreCurrencyPrototype, balance } },
|
||||
storeEntity, storeComponent);
|
||||
|
||||
return storeComponent;
|
||||
_meatyOreStores[userId] = (storeEntity, storeComponent);
|
||||
_pvsOverrideSystem.AddSessionOverride(storeEntity, session);
|
||||
|
||||
return (storeEntity, storeComponent);
|
||||
}
|
||||
|
||||
private async void TryAddRole(EntityUid user, EntityUid target, StoreComponent store)
|
||||
private async void TryAddRole(EntityUid user, EntityUid target, StoreComponent store, EntityUid storeEntity)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent<ActorComponent>(user, out var userActorComponent))
|
||||
return;
|
||||
@@ -217,10 +214,9 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
if (!store.Balance.TryGetValue(MeatyOreCurrencyPrototype, out var currency))
|
||||
return;
|
||||
|
||||
if(currency - 10 < 0)
|
||||
if (currency - 10 < 0)
|
||||
return;
|
||||
|
||||
|
||||
var fake = _roleSystem.MindIsAntagonist(targetMind.Mind.Value) || !_jobSystem.CanBeAntag(mindComponent.Session);
|
||||
|
||||
var ckey = userActorComponent.PlayerSession.Name;
|
||||
@@ -229,21 +225,23 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
|
||||
if (result)
|
||||
{
|
||||
_storeSystem.TryAddCurrency(new Dictionary<string, FixedPoint2> { { MeatyOreCurrencyPrototype, -10 } }, store.Owner, store);
|
||||
_storeSystem.TryAddCurrency(new Dictionary<string, FixedPoint2> { { MeatyOreCurrencyPrototype, -10 } },
|
||||
storeEntity, store);
|
||||
|
||||
if (!fake)
|
||||
{
|
||||
_traitorRuleSystem.MakeTraitor(targetActorComponent.PlayerSession);
|
||||
_traitorRuleSystem.MakeTraitorAdmin(target, true, true);
|
||||
|
||||
var msg = $"Игрок с сикеем {ckey} выдал антажку {targetActorComponent.PlayerSession.Name}";
|
||||
_chatManager.SendAdminAnnouncement(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
var msg = $"Игрок с сикеем {ckey} попытался выдать антажку {targetActorComponent.PlayerSession.Name}. Но обосрался. Была выдана фейковая антажка.";
|
||||
var msg =
|
||||
$"Игрок с сикеем {ckey} попытался выдать антажку {targetActorComponent.PlayerSession.Name}. Но обосрался. Была выдана фейковая антажка.";
|
||||
|
||||
_chatManager.SendAdminAnnouncement(msg);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -301,9 +299,7 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
url = $"{_apiUrl}/api/Antagonist/cooldownFriend?userId={ckey}";
|
||||
}
|
||||
|
||||
HttpResponseMessage response;
|
||||
|
||||
response = await _httpClient.GetAsync(url);
|
||||
var response = await _httpClient.GetAsync(url);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
@@ -311,7 +307,8 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
if (!string.IsNullOrEmpty(responseData))
|
||||
{
|
||||
var jsonObject = JObject.Parse(responseData);
|
||||
if (jsonObject.TryGetValue("remainingTime", out var remainingTimeToken) && TimeSpan.TryParse(remainingTimeToken.ToString(), out var remainingTime))
|
||||
if (jsonObject.TryGetValue("remainingTime", out var remainingTimeToken) &&
|
||||
TimeSpan.TryParse(remainingTimeToken.ToString(), out var remainingTime))
|
||||
{
|
||||
var time = new TimeSpan(remainingTime.Hours, remainingTime.Minutes, 0);
|
||||
return time;
|
||||
@@ -330,4 +327,4 @@ public sealed class MeatyOreStoreSystem : EntitySystem
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Server._White.SelfHeal;
|
||||
|
||||
public sealed class SelfHealSystem: EntitySystem
|
||||
public sealed class SelfHealSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||
@@ -49,7 +49,6 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
|
||||
private void OnDoAfter(EntityUid uid, DamageableComponent component, SelfHealDoAfterEvent args)
|
||||
{
|
||||
var dontRepeat = false;
|
||||
|
||||
if (!TryComp(args.User, out SelfHealComponent? healing) || args.Target == null)
|
||||
return;
|
||||
@@ -57,9 +56,9 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
if (args.Handled || args.Cancelled)
|
||||
return;
|
||||
|
||||
if (healing.DamageContainers is not null &&
|
||||
component.DamageContainerID is not null &&
|
||||
!healing.DamageContainers.Contains(component.DamageContainerID))
|
||||
if (healing.DamageContainers is not null
|
||||
&& component.DamageContainerID is not null
|
||||
&& !healing.DamageContainers.Contains(component.DamageContainerID))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -70,12 +69,11 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
Heal(args.Target.Value, healing, args);
|
||||
|
||||
// Logic to determine the whether or not to repeat the healing action
|
||||
args.Repeat = (HasDamage(component, healing) && !dontRepeat);
|
||||
if (!args.Repeat && !dontRepeat)
|
||||
args.Repeat = HasDamage(component, healing);
|
||||
if (!args.Repeat)
|
||||
_popupSystem.PopupEntity(Loc.GetString("self-heal-finished-using", ("name", uid)), uid, args.User);
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
}
|
||||
|
||||
private void Heal(EntityUid uid, SelfHealComponent component, SelfHealDoAfterEvent args)
|
||||
@@ -92,6 +90,7 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
var healMessage = uid != args.User
|
||||
? $"{userString:user} healed {targetString:target} for {total:damage} by licking"
|
||||
: $"{userString:user} healed themselves for {total:damage} by licking";
|
||||
|
||||
_adminLogger.Add(LogType.Healed, $"{healMessage}");
|
||||
|
||||
if (TryComp<SelfHealComponent>(args.User, out var selfHealComponent))
|
||||
@@ -100,13 +99,15 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
var audioParams = new AudioParams().WithVariation(2f).WithVolume(-5f);
|
||||
|
||||
_audio.PlayPvs(audio, args.User, audioParams);
|
||||
_popupSystem.PopupEntity(Loc.GetString("self-heal-using-other", ("user", args.Args.User), ("target", uid)), uid);
|
||||
_popupSystem.PopupEntity(Loc.GetString("self-heal-using-other", ("user", args.Args.User), ("target", uid)),
|
||||
uid);
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanHeal(EntityUid user, EntityUid target, SelfHealComponent component)
|
||||
{
|
||||
if (!TryComp<DamageableComponent>(target, out var targetDamage) || !HasComp<HumanoidAppearanceComponent>(target))
|
||||
if (!TryComp<DamageableComponent>(target, out var targetDamage) ||
|
||||
!HasComp<HumanoidAppearanceComponent>(target))
|
||||
return false;
|
||||
|
||||
if (user != target && !_interactionSystem.InRangeUnobstructed(user, target, popup: true))
|
||||
@@ -140,7 +141,9 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
{
|
||||
if (_inventorySystem.TryGetSlotEntity(target, clothing, out var blockedClothing))
|
||||
{
|
||||
var popup = Loc.GetString("self-heal-cant-use-clothing-other", ("name", target), ("clothing", blockedClothing));
|
||||
var popup = Loc.GetString("self-heal-cant-use-clothing-other", ("name", target),
|
||||
("clothing", blockedClothing));
|
||||
|
||||
_popupSystem.PopupEntity(popup, user, user);
|
||||
return false;
|
||||
}
|
||||
@@ -158,10 +161,10 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
var doAfterEventArgs =
|
||||
new DoAfterArgs(EntityManager, user, component.Delay, new SelfHealDoAfterEvent(), target, target)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
BreakOnMove = true,
|
||||
BreakOnDamage = true,
|
||||
};
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfterEventArgs);
|
||||
}
|
||||
|
||||
@@ -177,4 +180,4 @@ public sealed class SelfHealSystem: EntitySystem
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
using System.Linq;
|
||||
using Lidgren.Network;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -21,45 +19,46 @@ public enum TapeCreatorUIKey : byte
|
||||
Key
|
||||
}
|
||||
|
||||
[NetworkedComponent, RegisterComponent]
|
||||
[NetworkedComponent, RegisterComponent, AutoGenerateComponentState]
|
||||
public sealed partial class JukeboxComponent : Component
|
||||
{
|
||||
|
||||
public static string JukeboxContainerName = "jukebox_tapes";
|
||||
public static string JukeboxDefaultSongsName = "jukebox_default_tapes";
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public Container TapeContainer = default!;
|
||||
|
||||
[DataField("defaultTapes")]
|
||||
public List<string> DefaultTapes = new();
|
||||
[DataField]
|
||||
public List<string> DefaultTapes = [];
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public Container DefaultSongsContainer = default!;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly), AutoNetworkedField]
|
||||
public bool Playing { get; set; } = true;
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public bool Repeating { get; set; } = true;
|
||||
|
||||
[DataField("volume") ,ViewVariables(VVAccess.ReadOnly)]
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly), AutoNetworkedField]
|
||||
public float Volume { get; set; }
|
||||
|
||||
[DataField("maxAudioRange")]
|
||||
[DataField]
|
||||
public float MaxAudioRange { get; set; } = 20f;
|
||||
|
||||
[DataField("rolloffFactor")]
|
||||
[DataField]
|
||||
public float RolloffFactor { get; set; } = 0.3f;
|
||||
|
||||
[AutoNetworkedField]
|
||||
public PlayingSongData? PlayingSongData { get; set; }
|
||||
}
|
||||
|
||||
public sealed partial class TapeContainerComponent : Component
|
||||
{
|
||||
public int MaxTapeCount = 1;
|
||||
|
||||
public Container TapeContainer { get; set; } = new();
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class PlayingSongData
|
||||
public sealed class PlayingSongData
|
||||
{
|
||||
public ResPath? SongPath;
|
||||
public string? SongName;
|
||||
@@ -67,59 +66,56 @@ public class PlayingSongData
|
||||
public float ActualSongLengthSeconds;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class JukeboxComponentState : ComponentState
|
||||
{
|
||||
public bool Playing { get; set; }
|
||||
|
||||
public PlayingSongData? SongData { get; set; }
|
||||
public float Volume { get; set; }
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable, DataDefinition]
|
||||
public sealed partial class JukeboxSong
|
||||
{
|
||||
[DataField("songName")]
|
||||
[DataField]
|
||||
public string? SongName;
|
||||
|
||||
[DataField("path")]
|
||||
public ResPath? SongPath;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class JukeboxRequestSongPlay : EntityEventArgs
|
||||
public sealed class JukeboxRequestSongPlay : EntityEventArgs
|
||||
{
|
||||
public string? SongName { get; set; }
|
||||
|
||||
public ResPath? SongPath { get; set; }
|
||||
|
||||
public NetEntity? Jukebox { get; set; }
|
||||
|
||||
public float SongDuration { get; set; }
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class JukeboxRequestStop : EntityEventArgs
|
||||
public sealed class JukeboxRequestStop : EntityEventArgs
|
||||
{
|
||||
public NetEntity? JukeboxUid { get; set; }
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class JukeboxStopPlaying : EntityEventArgs
|
||||
public sealed class JukeboxStopPlaying : EntityEventArgs
|
||||
{
|
||||
public NetEntity? JukeboxUid { get; set; }
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class JukeboxSongUploadRequest : EntityEventArgs
|
||||
public sealed class JukeboxSongUploadRequest : EntityEventArgs
|
||||
{
|
||||
public string SongName = string.Empty;
|
||||
public List<byte> SongBytes = new();
|
||||
public List<byte> SongBytes = [];
|
||||
public NetEntity TapeCreatorUid = default!;
|
||||
}
|
||||
|
||||
public class JukeboxSongUploadNetMessage : NetMessage
|
||||
public sealed class JukeboxSongUploadNetMessage : NetMessage
|
||||
{
|
||||
public override NetDeliveryMethod DeliveryMethod => NetDeliveryMethod.ReliableUnordered;
|
||||
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
public ResPath RelativePath { get; set; } = ResPath.Self;
|
||||
|
||||
public byte[] Data { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
@@ -136,4 +132,4 @@ public class JukeboxSongUploadNetMessage : NetMessage
|
||||
buffer.Write(RelativePath.ToString());
|
||||
buffer.Write(ResPath.Separator);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,6 @@
|
||||
ClothingNeckCloakMoth: 2
|
||||
ClothingOuterDogi: 1
|
||||
ClothingHeadHatMagician: 1
|
||||
ClothingHeadHatBeretFrench: 2
|
||||
ClothingHeadHatRedRacoon: 2
|
||||
ClothingOuterRedRacoon: 2
|
||||
ClothingHeadHatGladiator: 1
|
||||
|
||||
Reference in New Issue
Block a user