Merge branch 'master' into 2020-04-28-tool-component
2
.vscode/extensions.json
vendored
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"ms-vscode.csharp",
|
"ms-dotnettools.csharp",
|
||||||
"editorconfig.editorconfig"
|
"editorconfig.editorconfig"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Content.Benchmarks
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
BenchmarkRunner.Run<ComponentManagerGetAllComponents>();
|
BenchmarkRunner.Run<StereoToMonoBenchmark>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
70
Content.Benchmarks/StereoToMonoBenchmark.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
|
||||||
|
namespace Content.Benchmarks
|
||||||
|
{
|
||||||
|
public class StereoToMonoBenchmark
|
||||||
|
{
|
||||||
|
[Params(128, 256, 512)]
|
||||||
|
public int N { get; set; }
|
||||||
|
|
||||||
|
private short[] _input;
|
||||||
|
private short[] _output;
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_input = new short[N * 2];
|
||||||
|
_output = new short[N];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void BenchSimple()
|
||||||
|
{
|
||||||
|
var l = N;
|
||||||
|
for (var j = 0; j < l; j++)
|
||||||
|
{
|
||||||
|
var k = j + l;
|
||||||
|
_output[j] = (short) ((_input[k] + _input[j]) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public unsafe void BenchSse()
|
||||||
|
{
|
||||||
|
var l = N;
|
||||||
|
fixed (short* iPtr = _input)
|
||||||
|
fixed (short* oPtr = _output)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < l; j += 8)
|
||||||
|
{
|
||||||
|
var k = j + l;
|
||||||
|
|
||||||
|
var jV = Sse2.ShiftRightArithmetic(Sse2.LoadVector128(iPtr + j), 1);
|
||||||
|
var kV = Sse2.ShiftRightArithmetic(Sse2.LoadVector128(iPtr + k), 1);
|
||||||
|
|
||||||
|
Sse2.Store(j + oPtr, Sse2.Add(jV, kV));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public unsafe void BenchAvx2()
|
||||||
|
{
|
||||||
|
var l = N;
|
||||||
|
fixed (short* iPtr = _input)
|
||||||
|
fixed (short* oPtr = _output)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < l; j += 16)
|
||||||
|
{
|
||||||
|
var k = j + l;
|
||||||
|
|
||||||
|
var jV = Avx2.ShiftRightArithmetic(Avx.LoadVector256(iPtr + j), 1);
|
||||||
|
var kV = Avx2.ShiftRightArithmetic(Avx.LoadVector256(iPtr + k), 1);
|
||||||
|
|
||||||
|
Avx.Store(j + oPtr, Avx2.Add(jV, kV));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,12 @@ namespace Content.Client.Chat
|
|||||||
{
|
{
|
||||||
internal sealed class ChatManager : IChatManager
|
internal sealed class ChatManager : IChatManager
|
||||||
{
|
{
|
||||||
|
private struct SpeechBubbleData
|
||||||
|
{
|
||||||
|
public string Message;
|
||||||
|
public SpeechBubble.SpeechType Type;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The max amount of chars allowed to fit in a single speech bubble.
|
/// The max amount of chars allowed to fit in a single speech bubble.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -117,7 +123,7 @@ namespace Content.Client.Chat
|
|||||||
|
|
||||||
var msg = queueData.MessageQueue.Dequeue();
|
var msg = queueData.MessageQueue.Dequeue();
|
||||||
|
|
||||||
queueData.TimeLeft += BubbleDelayBase + msg.Length * BubbleDelayFactor;
|
queueData.TimeLeft += BubbleDelayBase + msg.Message.Length * BubbleDelayFactor;
|
||||||
|
|
||||||
// We keep the queue around while it has 0 items. This allows us to keep the timer.
|
// We keep the queue around while it has 0 items. This allows us to keep the timer.
|
||||||
// When the timer hits 0 and there's no messages left, THEN we can clear it up.
|
// When the timer hits 0 and there's no messages left, THEN we can clear it up.
|
||||||
@@ -211,19 +217,19 @@ namespace Content.Client.Chat
|
|||||||
case OOCAlias:
|
case OOCAlias:
|
||||||
{
|
{
|
||||||
var conInput = text.Substring(1);
|
var conInput = text.Substring(1);
|
||||||
_console.ProcessCommand($"ooc \"{conInput}\"");
|
_console.ProcessCommand($"ooc \"{CommandParsing.Escape(conInput)}\"");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MeAlias:
|
case MeAlias:
|
||||||
{
|
{
|
||||||
var conInput = text.Substring(1);
|
var conInput = text.Substring(1);
|
||||||
_console.ProcessCommand($"me \"{conInput}\"");
|
_console.ProcessCommand($"me \"{CommandParsing.Escape(conInput)}\"");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
var conInput = _currentChatBox.DefaultChatFormat != null
|
var conInput = _currentChatBox.DefaultChatFormat != null
|
||||||
? string.Format(_currentChatBox.DefaultChatFormat, text)
|
? string.Format(_currentChatBox.DefaultChatFormat, CommandParsing.Escape(text))
|
||||||
: text;
|
: text;
|
||||||
_console.ProcessCommand(conInput);
|
_console.ProcessCommand(conInput);
|
||||||
break;
|
break;
|
||||||
@@ -291,13 +297,23 @@ namespace Content.Client.Chat
|
|||||||
WriteChatMessage(storedMessage);
|
WriteChatMessage(storedMessage);
|
||||||
|
|
||||||
// Local messages that have an entity attached get a speech bubble.
|
// Local messages that have an entity attached get a speech bubble.
|
||||||
if ((msg.Channel == ChatChannel.Local || msg.Channel == ChatChannel.Dead) && msg.SenderEntity != default)
|
if (msg.SenderEntity == default)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (msg.Channel)
|
||||||
{
|
{
|
||||||
AddSpeechBubble(msg);
|
case ChatChannel.Local:
|
||||||
|
case ChatChannel.Dead:
|
||||||
|
AddSpeechBubble(msg, SpeechBubble.SpeechType.Say);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ChatChannel.Emotes:
|
||||||
|
AddSpeechBubble(msg, SpeechBubble.SpeechType.Emote);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSpeechBubble(MsgChatMessage msg)
|
private void AddSpeechBubble(MsgChatMessage msg, SpeechBubble.SpeechType speechType)
|
||||||
{
|
{
|
||||||
if (!_entityManager.TryGetEntity(msg.SenderEntity, out var entity))
|
if (!_entityManager.TryGetEntity(msg.SenderEntity, out var entity))
|
||||||
{
|
{
|
||||||
@@ -305,8 +321,18 @@ namespace Content.Client.Chat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var messages = SplitMessage(msg.Message);
|
||||||
|
|
||||||
|
foreach (var message in messages)
|
||||||
|
{
|
||||||
|
EnqueueSpeechBubble(entity, message, speechType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> SplitMessage(string msg)
|
||||||
|
{
|
||||||
// Split message into words separated by spaces.
|
// Split message into words separated by spaces.
|
||||||
var words = msg.Message.Split(' ');
|
var words = msg.Split(' ');
|
||||||
var messages = new List<string>();
|
var messages = new List<string>();
|
||||||
var currentBuffer = new List<string>();
|
var currentBuffer = new List<string>();
|
||||||
|
|
||||||
@@ -346,13 +372,10 @@ namespace Content.Client.Chat
|
|||||||
messages.Add(string.Join(" ", currentBuffer));
|
messages.Add(string.Join(" ", currentBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var message in messages)
|
return messages;
|
||||||
{
|
|
||||||
EnqueueSpeechBubble(entity, message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnqueueSpeechBubble(IEntity entity, string contents)
|
private void EnqueueSpeechBubble(IEntity entity, string contents, SpeechBubble.SpeechType speechType)
|
||||||
{
|
{
|
||||||
if (!_queuedSpeechBubbles.TryGetValue(entity.Uid, out var queueData))
|
if (!_queuedSpeechBubbles.TryGetValue(entity.Uid, out var queueData))
|
||||||
{
|
{
|
||||||
@@ -360,12 +383,16 @@ namespace Content.Client.Chat
|
|||||||
_queuedSpeechBubbles.Add(entity.Uid, queueData);
|
_queuedSpeechBubbles.Add(entity.Uid, queueData);
|
||||||
}
|
}
|
||||||
|
|
||||||
queueData.MessageQueue.Enqueue(contents);
|
queueData.MessageQueue.Enqueue(new SpeechBubbleData
|
||||||
|
{
|
||||||
|
Message = contents,
|
||||||
|
Type = speechType,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateSpeechBubble(IEntity entity, string contents)
|
private void CreateSpeechBubble(IEntity entity, SpeechBubbleData speechData)
|
||||||
{
|
{
|
||||||
var bubble = new SpeechBubble(contents, entity, _eyeManager, this);
|
var bubble = SpeechBubble.CreateSpeechBubble(speechData.Type, speechData.Message, entity, _eyeManager, this);
|
||||||
|
|
||||||
if (_activeSpeechBubbles.TryGetValue(entity.Uid, out var existing))
|
if (_activeSpeechBubbles.TryGetValue(entity.Uid, out var existing))
|
||||||
{
|
{
|
||||||
@@ -405,7 +432,7 @@ namespace Content.Client.Chat
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float TimeLeft { get; set; }
|
public float TimeLeft { get; set; }
|
||||||
|
|
||||||
public Queue<string> MessageQueue { get; } = new Queue<string>();
|
public Queue<SpeechBubbleData> MessageQueue { get; } = new Queue<SpeechBubbleData>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Client.Interfaces.Chat;
|
using System;
|
||||||
|
using Content.Client.Interfaces.Chat;
|
||||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
@@ -9,8 +10,14 @@ using Robust.Shared.Timing;
|
|||||||
|
|
||||||
namespace Content.Client.Chat
|
namespace Content.Client.Chat
|
||||||
{
|
{
|
||||||
public class SpeechBubble : Control
|
public abstract class SpeechBubble : Control
|
||||||
{
|
{
|
||||||
|
public enum SpeechType
|
||||||
|
{
|
||||||
|
Emote,
|
||||||
|
Say
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The total time a speech bubble stays on screen.
|
/// The total time a speech bubble stays on screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -38,6 +45,21 @@ namespace Content.Client.Chat
|
|||||||
|
|
||||||
public float ContentHeight { get; private set; }
|
public float ContentHeight { get; private set; }
|
||||||
|
|
||||||
|
public static SpeechBubble CreateSpeechBubble(SpeechType type, string text, IEntity senderEntity, IEyeManager eyeManager, IChatManager chatManager)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SpeechType.Emote:
|
||||||
|
return new EmoteSpeechBubble(text, senderEntity, eyeManager, chatManager);
|
||||||
|
|
||||||
|
case SpeechType.Say:
|
||||||
|
return new SaySpeechBubble(text, senderEntity, eyeManager, chatManager);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public SpeechBubble(string text, IEntity senderEntity, IEyeManager eyeManager, IChatManager chatManager)
|
public SpeechBubble(string text, IEntity senderEntity, IEyeManager eyeManager, IChatManager chatManager)
|
||||||
{
|
{
|
||||||
_chatManager = chatManager;
|
_chatManager = chatManager;
|
||||||
@@ -47,27 +69,18 @@ namespace Content.Client.Chat
|
|||||||
// Use text clipping so new messages don't overlap old ones being pushed up.
|
// Use text clipping so new messages don't overlap old ones being pushed up.
|
||||||
RectClipContent = true;
|
RectClipContent = true;
|
||||||
|
|
||||||
var label = new RichTextLabel
|
var bubble = BuildBubble(text);
|
||||||
{
|
|
||||||
MaxWidth = 256,
|
|
||||||
};
|
|
||||||
label.SetMessage(text);
|
|
||||||
|
|
||||||
var panel = new PanelContainer
|
AddChild(bubble);
|
||||||
{
|
|
||||||
StyleClasses = { "tooltipBox" },
|
|
||||||
Children = { label },
|
|
||||||
ModulateSelfOverride = Color.White.WithAlpha(0.75f)
|
|
||||||
};
|
|
||||||
|
|
||||||
AddChild(panel);
|
|
||||||
|
|
||||||
ForceRunStyleUpdate();
|
ForceRunStyleUpdate();
|
||||||
|
|
||||||
ContentHeight = panel.CombinedMinimumSize.Y;
|
ContentHeight = bubble.CombinedMinimumSize.Y;
|
||||||
_verticalOffsetAchieved = -ContentHeight;
|
_verticalOffsetAchieved = -ContentHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract Control BuildBubble(string text);
|
||||||
|
|
||||||
protected override Vector2 CalculateMinimumSize()
|
protected override Vector2 CalculateMinimumSize()
|
||||||
{
|
{
|
||||||
return (base.CalculateMinimumSize().X, 0);
|
return (base.CalculateMinimumSize().X, 0);
|
||||||
@@ -134,4 +147,57 @@ namespace Content.Client.Chat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class EmoteSpeechBubble : SpeechBubble
|
||||||
|
|
||||||
|
{
|
||||||
|
public EmoteSpeechBubble(string text, IEntity senderEntity, IEyeManager eyeManager, IChatManager chatManager)
|
||||||
|
: base(text, senderEntity, eyeManager, chatManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Control BuildBubble(string text)
|
||||||
|
{
|
||||||
|
var label = new RichTextLabel
|
||||||
|
{
|
||||||
|
MaxWidth = 256,
|
||||||
|
};
|
||||||
|
label.SetMessage(text);
|
||||||
|
|
||||||
|
var panel = new PanelContainer
|
||||||
|
{
|
||||||
|
StyleClasses = { "speechBox", "emoteBox" },
|
||||||
|
Children = { label },
|
||||||
|
ModulateSelfOverride = Color.White.WithAlpha(0.75f)
|
||||||
|
};
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SaySpeechBubble : SpeechBubble
|
||||||
|
{
|
||||||
|
public SaySpeechBubble(string text, IEntity senderEntity, IEyeManager eyeManager, IChatManager chatManager)
|
||||||
|
: base(text, senderEntity, eyeManager, chatManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Control BuildBubble(string text)
|
||||||
|
{
|
||||||
|
var label = new RichTextLabel
|
||||||
|
{
|
||||||
|
MaxWidth = 256,
|
||||||
|
};
|
||||||
|
label.SetMessage(text);
|
||||||
|
|
||||||
|
var panel = new PanelContainer
|
||||||
|
{
|
||||||
|
StyleClasses = { "speechBox", "sayBox" },
|
||||||
|
Children = { label },
|
||||||
|
ModulateSelfOverride = Color.White.WithAlpha(0.75f)
|
||||||
|
};
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace Content.Client
|
|||||||
IoCManager.Register<IClientPreferencesManager, ClientPreferencesManager>();
|
IoCManager.Register<IClientPreferencesManager, ClientPreferencesManager>();
|
||||||
IoCManager.Register<IItemSlotManager, ItemSlotManager>();
|
IoCManager.Register<IItemSlotManager, ItemSlotManager>();
|
||||||
IoCManager.Register<IStylesheetManager, StylesheetManager>();
|
IoCManager.Register<IStylesheetManager, StylesheetManager>();
|
||||||
|
IoCManager.Register<IScreenshotHook, ScreenshotHook>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Client.Interfaces;
|
using Content.Client.Interfaces;
|
||||||
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
using Content.Shared;
|
using Content.Shared;
|
||||||
using Robust.Client.Interfaces.Console;
|
using Robust.Client.Interfaces.Console;
|
||||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
@@ -57,7 +58,11 @@ namespace Content.Client
|
|||||||
|
|
||||||
public void PopupMessage(ScreenCoordinates coordinates, string message)
|
public void PopupMessage(ScreenCoordinates coordinates, string message)
|
||||||
{
|
{
|
||||||
var label = new PopupLabel {Text = message};
|
var label = new PopupLabel
|
||||||
|
{
|
||||||
|
Text = message,
|
||||||
|
StyleClasses = { StyleNano.StyleClassPopupMessage },
|
||||||
|
};
|
||||||
var minimumSize = label.CombinedMinimumSize;
|
var minimumSize = label.CombinedMinimumSize;
|
||||||
LayoutContainer.SetPosition(label, label.InitialPos = coordinates.Position - minimumSize / 2);
|
LayoutContainer.SetPosition(label, label.InitialPos = coordinates.Position - minimumSize / 2);
|
||||||
_userInterfaceManager.PopupRoot.AddChild(label);
|
_userInterfaceManager.PopupRoot.AddChild(label);
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ using Content.Client.UserInterface.Stylesheets;
|
|||||||
using Content.Shared.GameObjects.Components;
|
using Content.Shared.GameObjects.Components;
|
||||||
using Content.Shared.GameObjects.Components.Cargo;
|
using Content.Shared.GameObjects.Components.Cargo;
|
||||||
using Content.Shared.GameObjects.Components.Chemistry;
|
using Content.Shared.GameObjects.Components.Chemistry;
|
||||||
|
using Content.Shared.GameObjects.Components.Gravity;
|
||||||
using Content.Shared.GameObjects.Components.Markers;
|
using Content.Shared.GameObjects.Components.Markers;
|
||||||
using Content.Shared.GameObjects.Components.Research;
|
using Content.Shared.GameObjects.Components.Research;
|
||||||
using Content.Shared.GameObjects.Components.VendingMachines;
|
using Content.Shared.GameObjects.Components.VendingMachines;
|
||||||
|
using Content.Shared.Kitchen;
|
||||||
using Robust.Client;
|
using Robust.Client;
|
||||||
using Robust.Client.Interfaces;
|
using Robust.Client.Interfaces;
|
||||||
using Robust.Client.Interfaces.Graphics.Overlays;
|
using Robust.Client.Interfaces.Graphics.Overlays;
|
||||||
@@ -142,7 +144,7 @@ namespace Content.Client
|
|||||||
"Mop",
|
"Mop",
|
||||||
"Bucket",
|
"Bucket",
|
||||||
"Puddle",
|
"Puddle",
|
||||||
"CanSpill",
|
"CanSpill"
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var ignoreName in registerIgnore)
|
foreach (var ignoreName in registerIgnore)
|
||||||
@@ -160,6 +162,8 @@ namespace Content.Client
|
|||||||
factory.Register<SharedWiresComponent>();
|
factory.Register<SharedWiresComponent>();
|
||||||
factory.Register<SharedCargoConsoleComponent>();
|
factory.Register<SharedCargoConsoleComponent>();
|
||||||
factory.Register<SharedReagentDispenserComponent>();
|
factory.Register<SharedReagentDispenserComponent>();
|
||||||
|
factory.Register<SharedMicrowaveComponent>();
|
||||||
|
factory.Register<SharedGravityGeneratorComponent>();
|
||||||
|
|
||||||
prototypes.RegisterIgnore("material");
|
prototypes.RegisterIgnore("material");
|
||||||
prototypes.RegisterIgnore("reaction"); //Chemical reactions only needed by server. Reactions checks are server-side.
|
prototypes.RegisterIgnore("reaction"); //Chemical reactions only needed by server. Reactions checks are server-side.
|
||||||
@@ -178,6 +182,7 @@ namespace Content.Client
|
|||||||
IoCManager.Resolve<IParallaxManager>().LoadParallax();
|
IoCManager.Resolve<IParallaxManager>().LoadParallax();
|
||||||
IoCManager.Resolve<IBaseClient>().PlayerJoinedServer += SubscribePlayerAttachmentEvents;
|
IoCManager.Resolve<IBaseClient>().PlayerJoinedServer += SubscribePlayerAttachmentEvents;
|
||||||
IoCManager.Resolve<IStylesheetManager>().Initialize();
|
IoCManager.Resolve<IStylesheetManager>().Initialize();
|
||||||
|
IoCManager.Resolve<IScreenshotHook>().Initialize();
|
||||||
|
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Shared.GameObjects.Components.Gravity;
|
||||||
|
using Robust.Client.GameObjects.Components.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
|
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Gravity
|
||||||
|
{
|
||||||
|
public class GravityGeneratorBoundUserInterface: BoundUserInterface
|
||||||
|
{
|
||||||
|
private GravityGeneratorWindow _window;
|
||||||
|
|
||||||
|
public bool IsOn;
|
||||||
|
|
||||||
|
public GravityGeneratorBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base (owner, uiKey)
|
||||||
|
{
|
||||||
|
SendMessage(new SharedGravityGeneratorComponent.GeneratorStatusRequestMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Open()
|
||||||
|
{
|
||||||
|
base.Open();
|
||||||
|
|
||||||
|
IsOn = false;
|
||||||
|
|
||||||
|
_window = new GravityGeneratorWindow(this);
|
||||||
|
|
||||||
|
_window.Switch.OnPressed += (args) =>
|
||||||
|
{
|
||||||
|
SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(!IsOn));
|
||||||
|
SendMessage(new SharedGravityGeneratorComponent.GeneratorStatusRequestMessage());
|
||||||
|
};
|
||||||
|
|
||||||
|
_window.OpenCentered();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateState(BoundUserInterfaceState state)
|
||||||
|
{
|
||||||
|
base.UpdateState(state);
|
||||||
|
|
||||||
|
var castState = (SharedGravityGeneratorComponent.GeneratorState) state;
|
||||||
|
IsOn = castState.On;
|
||||||
|
_window.UpdateButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (!disposing) return;
|
||||||
|
|
||||||
|
_window?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GravityGeneratorWindow : SS14Window
|
||||||
|
{
|
||||||
|
public Label Status;
|
||||||
|
|
||||||
|
public Button Switch;
|
||||||
|
|
||||||
|
public GravityGeneratorBoundUserInterface Owner;
|
||||||
|
|
||||||
|
public GravityGeneratorWindow(GravityGeneratorBoundUserInterface gravityGeneratorInterface = null)
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
|
Owner = gravityGeneratorInterface;
|
||||||
|
|
||||||
|
Title = Loc.GetString("Gravity Generator Control");
|
||||||
|
|
||||||
|
var vBox = new VBoxContainer
|
||||||
|
{
|
||||||
|
CustomMinimumSize = new Vector2(250, 100)
|
||||||
|
};
|
||||||
|
Status = new Label
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("Current Status: " + (Owner.IsOn ? "On" : "Off")),
|
||||||
|
FontColorOverride = Owner.IsOn ? Color.ForestGreen : Color.Red
|
||||||
|
};
|
||||||
|
Switch = new Button
|
||||||
|
{
|
||||||
|
Text = Loc.GetString(Owner.IsOn ? "Turn Off" : "Turn On"),
|
||||||
|
TextAlign = Label.AlignMode.Center,
|
||||||
|
CustomMinimumSize = new Vector2(150, 60)
|
||||||
|
};
|
||||||
|
|
||||||
|
vBox.AddChild(Status);
|
||||||
|
vBox.AddChild(Switch);
|
||||||
|
|
||||||
|
Contents.AddChild(vBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateButton()
|
||||||
|
{
|
||||||
|
Status.Text = Loc.GetString("Current Status: " + (Owner.IsOn ? "On" : "Off"));
|
||||||
|
Status.FontColorOverride = Owner.IsOn ? Color.ForestGreen : Color.Red;
|
||||||
|
Switch.Text = Loc.GetString(Owner.IsOn ? "Turn Off" : "Turn On");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -114,13 +114,13 @@ namespace Content.Client.GameObjects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void HandleInventoryKeybind(BaseButton.ButtonEventArgs args, Slots slot)
|
protected override void HandleInventoryKeybind(GUIBoundKeyEventArgs args, Slots slot)
|
||||||
{
|
{
|
||||||
if (!_inventoryButtons.TryGetValue(slot, out var buttons))
|
if (!_inventoryButtons.TryGetValue(slot, out var buttons))
|
||||||
return;
|
return;
|
||||||
if (!Owner.TryGetSlot(slot, out var item))
|
if (!Owner.TryGetSlot(slot, out var item))
|
||||||
return;
|
return;
|
||||||
if (_itemSlotManager.OnButtonPressed(args.Event, item))
|
if (_itemSlotManager.OnButtonPressed(args, item))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
base.HandleInventoryKeybind(args, slot);
|
base.HandleInventoryKeybind(args, slot);
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
using Content.Client.UserInterface;
|
using Content.Client.UserInterface;
|
||||||
using Content.Shared.GameObjects.Components.Inventory;
|
using Content.Shared.GameObjects.Components.Inventory;
|
||||||
using Content.Shared.Input;
|
using Content.Shared.Input;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
@@ -62,39 +63,35 @@ namespace Content.Client.GameObjects
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void HandleInventoryKeybind(BaseButton.ButtonEventArgs args, EquipmentSlotDefines.Slots slot)
|
protected virtual void HandleInventoryKeybind(GUIBoundKeyEventArgs args, EquipmentSlotDefines.Slots slot)
|
||||||
{
|
{
|
||||||
if (args.Event.CanFocus)
|
if (args.Function == EngineKeyFunctions.UIClick)
|
||||||
{
|
{
|
||||||
UseItemOnInventory(args, slot);
|
UseItemOnInventory(slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void AddToInventory(BaseButton.ButtonEventArgs args, EquipmentSlotDefines.Slots slot)
|
protected void AddToInventory(GUIBoundKeyEventArgs args, EquipmentSlotDefines.Slots slot)
|
||||||
{
|
{
|
||||||
if (!args.Event.CanFocus)
|
if (args.Function != EngineKeyFunctions.UIClick)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
args.Button.Pressed = false;
|
|
||||||
|
|
||||||
Owner.SendEquipMessage(slot);
|
Owner.SendEquipMessage(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void UseItemOnInventory(BaseButton.ButtonEventArgs args, EquipmentSlotDefines.Slots slot)
|
protected void UseItemOnInventory(EquipmentSlotDefines.Slots slot)
|
||||||
{
|
{
|
||||||
args.Button.Pressed = false;
|
|
||||||
|
|
||||||
Owner.SendUseMessage(slot);
|
Owner.SendUseMessage(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void OpenStorage(BaseButton.ButtonEventArgs args, EquipmentSlotDefines.Slots slot)
|
protected void OpenStorage(GUIBoundKeyEventArgs args, EquipmentSlotDefines.Slots slot)
|
||||||
{
|
{
|
||||||
if (!args.Event.CanFocus && args.Event.Function != ContentKeyFunctions.ActivateItemInWorld)
|
if (args.Function != EngineKeyFunctions.UIClick && args.Function != ContentKeyFunctions.ActivateItemInWorld)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
args.Button.Pressed = false;
|
|
||||||
|
|
||||||
Owner.SendOpenStorageUIMessage(slot);
|
Owner.SendOpenStorageUIMessage(slot);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
using Robust.Client.GameObjects.Components.UserInterface;
|
||||||
|
using Content.Shared.Kitchen;
|
||||||
|
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Content.Shared.Chemistry;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
|
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Kitchen
|
||||||
|
{
|
||||||
|
public class MicrowaveBoundUserInterface : BoundUserInterface
|
||||||
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||||
|
#pragma warning restore 649
|
||||||
|
private MicrowaveMenu _menu;
|
||||||
|
|
||||||
|
private Dictionary<int, EntityUid> _solids = new Dictionary<int, EntityUid>();
|
||||||
|
private Dictionary<int, Solution.ReagentQuantity> _reagents =new Dictionary<int, Solution.ReagentQuantity>();
|
||||||
|
|
||||||
|
public MicrowaveBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner,uiKey)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Open()
|
||||||
|
{
|
||||||
|
base.Open();
|
||||||
|
_menu = new MicrowaveMenu(this);
|
||||||
|
_menu.OpenCentered();
|
||||||
|
_menu.OnClose += Close;
|
||||||
|
_menu.StartButton.OnPressed += args => SendMessage(new SharedMicrowaveComponent.MicrowaveStartCookMessage());
|
||||||
|
_menu.EjectButton.OnPressed += args => SendMessage(new SharedMicrowaveComponent.MicrowaveEjectMessage());
|
||||||
|
_menu.IngredientsList.OnItemSelected += args =>
|
||||||
|
{
|
||||||
|
SendMessage(new SharedMicrowaveComponent.MicrowaveEjectSolidIndexedMessage(_solids[args.ItemIndex]));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
_menu.IngredientsListReagents.OnItemSelected += args =>
|
||||||
|
{
|
||||||
|
SendMessage(
|
||||||
|
new SharedMicrowaveComponent.MicrowaveVaporizeReagentIndexedMessage(_reagents[args.ItemIndex]));
|
||||||
|
};
|
||||||
|
|
||||||
|
_menu.OnCookTimeSelected += args =>
|
||||||
|
{
|
||||||
|
var actualButton = args.Button as Button;
|
||||||
|
var newTime = (uint) int.Parse(actualButton.Text);
|
||||||
|
_menu.VisualCookTime = newTime;
|
||||||
|
SendMessage(new SharedMicrowaveComponent.MicrowaveSelectCookTimeMessage(newTime));
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (!disposing)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_solids?.Clear();
|
||||||
|
_menu?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override void UpdateState(BoundUserInterfaceState state)
|
||||||
|
{
|
||||||
|
base.UpdateState(state);
|
||||||
|
if (!(state is MicrowaveUpdateUserInterfaceState cstate))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshContentsDisplay(cstate.ReagentsReagents, cstate.ContainedSolids);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void RefreshContentsDisplay(IReadOnlyList<Solution.ReagentQuantity> reagents, List<EntityUid> solids)
|
||||||
|
{
|
||||||
|
_reagents.Clear();
|
||||||
|
_menu.IngredientsListReagents.Clear();
|
||||||
|
foreach (var reagent in reagents)
|
||||||
|
{
|
||||||
|
_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto);
|
||||||
|
var reagentAdded = _menu.IngredientsListReagents.AddItem($"{reagent.Quantity} {proto.Name}");
|
||||||
|
var reagentIndex = _menu.IngredientsListReagents.IndexOf(reagentAdded);
|
||||||
|
_reagents.Add(reagentIndex, reagent);
|
||||||
|
}
|
||||||
|
|
||||||
|
_solids.Clear();
|
||||||
|
_menu.IngredientsList.Clear();
|
||||||
|
foreach (var entityID in solids)
|
||||||
|
{
|
||||||
|
var entity = _entityManager.GetEntity(entityID);
|
||||||
|
|
||||||
|
if (entity.TryGetComponent(out IconComponent icon))
|
||||||
|
{
|
||||||
|
var solidItem = _menu.IngredientsList.AddItem(entity.Name, icon.Icon.Default);
|
||||||
|
|
||||||
|
var solidIndex = _menu.IngredientsList.IndexOf(solidItem);
|
||||||
|
_solids.Add(solidIndex, entityID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
206
Content.Client/GameObjects/Components/Kitchen/MicrowaveMenu.cs
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Client.Graphics.Drawing;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Kitchen
|
||||||
|
{
|
||||||
|
public class MicrowaveMenu : SS14Window
|
||||||
|
{
|
||||||
|
protected override Vector2? CustomSize => (512, 256);
|
||||||
|
|
||||||
|
private MicrowaveBoundUserInterface Owner { get; set; }
|
||||||
|
|
||||||
|
public event Action<BaseButton.ButtonEventArgs> OnCookTimeSelected;
|
||||||
|
|
||||||
|
public uint VisualCookTime = 1;
|
||||||
|
|
||||||
|
public Button StartButton { get;}
|
||||||
|
public Button EjectButton { get;}
|
||||||
|
|
||||||
|
public PanelContainer TimerFacePlate { get; }
|
||||||
|
|
||||||
|
public ButtonGroup CookTimeButtonGroup { get; }
|
||||||
|
private VBoxContainer CookTimeButtonVbox { get; }
|
||||||
|
|
||||||
|
public ItemList IngredientsList { get;}
|
||||||
|
|
||||||
|
public ItemList IngredientsListReagents { get; }
|
||||||
|
private Label _cookTimeInfoLabel { get; }
|
||||||
|
|
||||||
|
public MicrowaveMenu(MicrowaveBoundUserInterface owner = null)
|
||||||
|
{
|
||||||
|
Owner = owner;
|
||||||
|
Title = Loc.GetString("Microwave");
|
||||||
|
var hSplit = new HBoxContainer
|
||||||
|
{
|
||||||
|
SizeFlagsHorizontal = SizeFlags.Fill,
|
||||||
|
SizeFlagsVertical = SizeFlags.Fill
|
||||||
|
};
|
||||||
|
|
||||||
|
IngredientsListReagents = new ItemList
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
SelectMode = ItemList.ItemListSelectMode.Button,
|
||||||
|
SizeFlagsStretchRatio = 2,
|
||||||
|
CustomMinimumSize = (100,128)
|
||||||
|
};
|
||||||
|
|
||||||
|
IngredientsList = new ItemList
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
SelectMode = ItemList.ItemListSelectMode.Button,
|
||||||
|
SizeFlagsStretchRatio = 2,
|
||||||
|
CustomMinimumSize = (100,128)
|
||||||
|
};
|
||||||
|
|
||||||
|
hSplit.AddChild(IngredientsListReagents);
|
||||||
|
//Padding between the lists.
|
||||||
|
hSplit.AddChild(new Control
|
||||||
|
{
|
||||||
|
CustomMinimumSize = (0,5),
|
||||||
|
});
|
||||||
|
|
||||||
|
hSplit.AddChild(IngredientsList);
|
||||||
|
|
||||||
|
var vSplit = new VBoxContainer
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
};
|
||||||
|
|
||||||
|
hSplit.AddChild(vSplit);
|
||||||
|
|
||||||
|
var buttonGridContainer = new VBoxContainer
|
||||||
|
{
|
||||||
|
Align = BoxContainer.AlignMode.Center,
|
||||||
|
SizeFlagsStretchRatio = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
StartButton = new Button
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("Start"),
|
||||||
|
TextAlign = Label.AlignMode.Center,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EjectButton = new Button
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("Eject All Contents"),
|
||||||
|
ToolTip = Loc.GetString("This vaporizes all reagents, but ejects any solids."),
|
||||||
|
TextAlign = Label.AlignMode.Center,
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonGridContainer.AddChild(StartButton);
|
||||||
|
buttonGridContainer.AddChild(EjectButton);
|
||||||
|
vSplit.AddChild(buttonGridContainer);
|
||||||
|
|
||||||
|
//Padding
|
||||||
|
vSplit.AddChild(new Control
|
||||||
|
{
|
||||||
|
CustomMinimumSize = (0, 15),
|
||||||
|
SizeFlagsVertical = SizeFlags.Fill,
|
||||||
|
});
|
||||||
|
|
||||||
|
CookTimeButtonGroup = new ButtonGroup();
|
||||||
|
CookTimeButtonVbox = new VBoxContainer
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
Align = BoxContainer.AlignMode.Center,
|
||||||
|
};
|
||||||
|
|
||||||
|
var index = 0;
|
||||||
|
for (var i = 0; i <= 12; i++)
|
||||||
|
{
|
||||||
|
var newButton = new Button
|
||||||
|
{
|
||||||
|
Text = (index <= 0 ? 1 : index).ToString(),
|
||||||
|
TextAlign = Label.AlignMode.Center,
|
||||||
|
Group = CookTimeButtonGroup,
|
||||||
|
};
|
||||||
|
CookTimeButtonVbox.AddChild(newButton);
|
||||||
|
newButton.OnPressed += args =>
|
||||||
|
{
|
||||||
|
OnCookTimeSelected?.Invoke(args);
|
||||||
|
_cookTimeInfoLabel.Text = $"{Loc.GetString("COOK TIME")}: {VisualCookTime}";
|
||||||
|
};
|
||||||
|
index+=5;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cookTimeOneSecondButton = (Button)CookTimeButtonVbox.GetChild(0);
|
||||||
|
cookTimeOneSecondButton.Pressed = true;
|
||||||
|
|
||||||
|
_cookTimeInfoLabel = new Label
|
||||||
|
{
|
||||||
|
Text = Loc.GetString($"COOK TIME: {VisualCookTime}"),
|
||||||
|
Align = Label.AlignMode.Center,
|
||||||
|
Modulate = Color.White,
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter
|
||||||
|
};
|
||||||
|
|
||||||
|
var innerTimerPanel = new PanelContainer
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
ModulateSelfOverride = Color.Red,
|
||||||
|
CustomMinimumSize = (100, 128),
|
||||||
|
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.5f)},
|
||||||
|
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
|
||||||
|
new VBoxContainer
|
||||||
|
{
|
||||||
|
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
|
||||||
|
new PanelContainer
|
||||||
|
{
|
||||||
|
PanelOverride = new StyleBoxFlat(){BackgroundColor = Color.Gray.WithAlpha(0.2f)},
|
||||||
|
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
_cookTimeInfoLabel
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
new ScrollContainer()
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
CookTimeButtonVbox,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TimerFacePlate = new PanelContainer()
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
|
||||||
|
innerTimerPanel
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
vSplit.AddChild(TimerFacePlate);
|
||||||
|
Contents.AddChild(hSplit);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using Content.Client.GameObjects.Components.Sound;
|
||||||
|
using Content.Shared.GameObjects.Components.Power;
|
||||||
|
using Content.Shared.GameObjects.Components.Sound;
|
||||||
|
using Content.Shared.Kitchen;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Interfaces.GameObjects.Components;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Kitchen
|
||||||
|
{
|
||||||
|
public sealed class MicrowaveVisualizer : AppearanceVisualizer
|
||||||
|
{
|
||||||
|
private SoundComponent _soundComponent;
|
||||||
|
private const string MicrowaveSoundLoop = "/Audio/machines/microwave_loop.ogg";
|
||||||
|
|
||||||
|
public override void OnChangeData(AppearanceComponent component)
|
||||||
|
{
|
||||||
|
base.OnChangeData(component);
|
||||||
|
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
||||||
|
_soundComponent ??= component.Owner.GetComponent<SoundComponent>();
|
||||||
|
if (!component.TryGetData(PowerDeviceVisuals.VisualState, out MicrowaveVisualState state))
|
||||||
|
{
|
||||||
|
state = MicrowaveVisualState.Idle;
|
||||||
|
}
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case MicrowaveVisualState.Idle:
|
||||||
|
sprite.LayerSetState(MicrowaveVisualizerLayers.Base, "mw");
|
||||||
|
sprite.LayerSetState(MicrowaveVisualizerLayers.BaseUnlit, "mw_unlit");
|
||||||
|
_soundComponent.StopAllSounds();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MicrowaveVisualState.Cooking:
|
||||||
|
sprite.LayerSetState(MicrowaveVisualizerLayers.Base, "mw");
|
||||||
|
sprite.LayerSetState(MicrowaveVisualizerLayers.BaseUnlit, "mw_running_unlit");
|
||||||
|
var audioParams = AudioParams.Default;
|
||||||
|
audioParams.Loop = true;
|
||||||
|
var schedSound = new ScheduledSound();
|
||||||
|
schedSound.Filename = MicrowaveSoundLoop;
|
||||||
|
schedSound.AudioParams = audioParams;
|
||||||
|
_soundComponent.AddScheduledSound(schedSound);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Logger.Debug($"Something terrible happened in {this}");
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var glowingPartsVisible = !(component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) && !powered);
|
||||||
|
sprite.LayerSetVisible(MicrowaveVisualizerLayers.BaseUnlit, glowingPartsVisible);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private enum MicrowaveVisualizerLayers
|
||||||
|
{
|
||||||
|
Base,
|
||||||
|
BaseUnlit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ namespace Content.Client.GameObjects.Components.Sound
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class SoundComponent : SharedSoundComponent
|
public class SoundComponent : SharedSoundComponent
|
||||||
{
|
{
|
||||||
private readonly List<ScheduledSound> _schedules = new List<ScheduledSound>();
|
private readonly Dictionary<ScheduledSound, IPlayingAudioStream> _audioStreams = new Dictionary<ScheduledSound, IPlayingAudioStream>();
|
||||||
private AudioSystem _audioSystem;
|
private AudioSystem _audioSystem;
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly IRobustRandom _random;
|
[Dependency] private readonly IRobustRandom _random;
|
||||||
@@ -23,26 +23,27 @@ namespace Content.Client.GameObjects.Components.Sound
|
|||||||
|
|
||||||
public override void StopAllSounds()
|
public override void StopAllSounds()
|
||||||
{
|
{
|
||||||
foreach (var schedule in _schedules)
|
foreach (var kvp in _audioStreams)
|
||||||
{
|
{
|
||||||
schedule.Play = false;
|
kvp.Key.Play = false;
|
||||||
|
kvp.Value.Stop();
|
||||||
}
|
}
|
||||||
_schedules.Clear();
|
_audioStreams.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void StopScheduledSound(string filename)
|
public override void StopScheduledSound(string filename)
|
||||||
{
|
{
|
||||||
foreach (var schedule in _schedules.ToArray())
|
foreach (var kvp in _audioStreams)
|
||||||
{
|
{
|
||||||
if (schedule.Filename != filename) continue;
|
if (kvp.Key.Filename != filename) continue;
|
||||||
schedule.Play = false;
|
kvp.Key.Play = false;
|
||||||
_schedules.Remove(schedule);
|
kvp.Value.Stop();
|
||||||
|
_audioStreams.Remove(kvp.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddScheduledSound(ScheduledSound schedule)
|
public override void AddScheduledSound(ScheduledSound schedule)
|
||||||
{
|
{
|
||||||
_schedules.Add(schedule);
|
|
||||||
Play(schedule);
|
Play(schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,16 +55,11 @@ namespace Content.Client.GameObjects.Components.Sound
|
|||||||
{
|
{
|
||||||
if (!schedule.Play) return; // We make sure this hasn't changed.
|
if (!schedule.Play) return; // We make sure this hasn't changed.
|
||||||
if (_audioSystem == null) _audioSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>();
|
if (_audioSystem == null) _audioSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>();
|
||||||
_audioSystem.Play(schedule.Filename, Owner, schedule.AudioParams);
|
_audioStreams.Add(schedule,_audioSystem.Play(schedule.Filename, Owner, schedule.AudioParams));
|
||||||
|
|
||||||
if (schedule.Times == 0)
|
if (schedule.Times == 0) return;
|
||||||
{
|
|
||||||
_schedules.Remove(schedule);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schedule.Times > 0)
|
if (schedule.Times > 0) schedule.Times--;
|
||||||
schedule.Times--;
|
|
||||||
|
|
||||||
Play(schedule);
|
Play(schedule);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class CombatModeSystem : SharedCombatModeSystem
|
public sealed class CombatModeSystem : SharedCombatModeSystem
|
||||||
{
|
{
|
||||||
private const float AttackTimeThreshold = 0.15f;
|
|
||||||
|
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly IGameHud _gameHud;
|
[Dependency] private readonly IGameHud _gameHud;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager;
|
[Dependency] private readonly IPlayerManager _playerManager;
|
||||||
@@ -37,9 +35,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
|
|
||||||
private InputSystem _inputSystem;
|
private InputSystem _inputSystem;
|
||||||
|
|
||||||
public bool UseOrAttackIsDown { get; private set; }
|
|
||||||
private float _timeHeld;
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -48,10 +43,8 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
_gameHud.OnTargetingZoneChanged = OnTargetingZoneChanged;
|
_gameHud.OnTargetingZoneChanged = OnTargetingZoneChanged;
|
||||||
|
|
||||||
_inputSystem = EntitySystemManager.GetEntitySystem<InputSystem>();
|
_inputSystem = EntitySystemManager.GetEntitySystem<InputSystem>();
|
||||||
_inputSystem.BindMap.BindFunction(ContentKeyFunctions.UseOrAttack, new InputHandler(this));
|
|
||||||
_inputSystem.BindMap.BindFunction(ContentKeyFunctions.ToggleCombatMode,
|
_inputSystem.BindMap.BindFunction(ContentKeyFunctions.ToggleCombatMode,
|
||||||
InputCmdHandler.FromDelegate(CombatModeToggled));
|
InputCmdHandler.FromDelegate(CombatModeToggled));
|
||||||
_overlayManager.AddOverlay(new CombatModeOverlay(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CombatModeToggled(ICommonSession session)
|
private void CombatModeToggled(ICommonSession session)
|
||||||
@@ -60,20 +53,10 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
{
|
{
|
||||||
EntityManager.RaisePredictiveEvent(
|
EntityManager.RaisePredictiveEvent(
|
||||||
new CombatModeSystemMessages.SetCombatModeActiveMessage(!IsInCombatMode()));
|
new CombatModeSystemMessages.SetCombatModeActiveMessage(!IsInCombatMode()));
|
||||||
|
|
||||||
// Just in case.
|
|
||||||
UseOrAttackIsDown = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public bool IsInCombatMode()
|
||||||
{
|
|
||||||
base.Shutdown();
|
|
||||||
|
|
||||||
_overlayManager.RemoveOverlay(nameof(CombatModeOverlay));
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsInCombatMode()
|
|
||||||
{
|
{
|
||||||
var entity = _playerManager.LocalPlayer.ControlledEntity;
|
var entity = _playerManager.LocalPlayer.ControlledEntity;
|
||||||
if (entity == null || !entity.TryGetComponent(out CombatModeComponent combatMode))
|
if (entity == null || !entity.TryGetComponent(out CombatModeComponent combatMode))
|
||||||
@@ -92,104 +75,6 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
private void OnCombatModeChanged(bool obj)
|
private void OnCombatModeChanged(bool obj)
|
||||||
{
|
{
|
||||||
EntityManager.RaisePredictiveEvent(new CombatModeSystemMessages.SetCombatModeActiveMessage(obj));
|
EntityManager.RaisePredictiveEvent(new CombatModeSystemMessages.SetCombatModeActiveMessage(obj));
|
||||||
|
|
||||||
// Just in case.
|
|
||||||
UseOrAttackIsDown = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool HandleInputMessage(ICommonSession session, InputCmdMessage message)
|
|
||||||
{
|
|
||||||
if (!(message is FullInputCmdMessage msg))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
void SendMsg(BoundKeyFunction function, BoundKeyState state)
|
|
||||||
{
|
|
||||||
var functionId = _inputManager.NetworkBindMap.KeyFunctionID(function);
|
|
||||||
|
|
||||||
var sendMsg = new FullInputCmdMessage(msg.Tick, functionId, state,
|
|
||||||
msg.Coordinates, msg.ScreenCoordinates, msg.Uid);
|
|
||||||
_inputSystem.HandleInputCommand(session, function, sendMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are not in combat mode, relay it as a regular Use instead.
|
|
||||||
if (!IsInCombatMode())
|
|
||||||
{
|
|
||||||
SendMsg(EngineKeyFunctions.Use, msg.State);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg.State == BoundKeyState.Down)
|
|
||||||
{
|
|
||||||
UseOrAttackIsDown = true;
|
|
||||||
_timeHeld = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Up.
|
|
||||||
if (UseOrAttackIsDown && _timeHeld >= AttackTimeThreshold)
|
|
||||||
{
|
|
||||||
// Attack.
|
|
||||||
SendMsg(ContentKeyFunctions.Attack, BoundKeyState.Down);
|
|
||||||
SendMsg(ContentKeyFunctions.Attack, BoundKeyState.Up);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use.
|
|
||||||
SendMsg(EngineKeyFunctions.Use, BoundKeyState.Down);
|
|
||||||
SendMsg(EngineKeyFunctions.Use, BoundKeyState.Up);
|
|
||||||
}
|
|
||||||
|
|
||||||
UseOrAttackIsDown = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void FrameUpdate(float frameTime)
|
|
||||||
{
|
|
||||||
if (UseOrAttackIsDown)
|
|
||||||
{
|
|
||||||
_timeHeld += frameTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom input handler type so we get the ENTIRE InputCmdMessage.
|
|
||||||
private sealed class InputHandler : InputCmdHandler
|
|
||||||
{
|
|
||||||
private readonly CombatModeSystem _combatModeSystem;
|
|
||||||
|
|
||||||
public InputHandler(CombatModeSystem combatModeSystem)
|
|
||||||
{
|
|
||||||
_combatModeSystem = combatModeSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool HandleCmdMessage(ICommonSession session, InputCmdMessage message)
|
|
||||||
{
|
|
||||||
return _combatModeSystem.HandleInputMessage(session, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class CombatModeOverlay : Overlay
|
|
||||||
{
|
|
||||||
private readonly CombatModeSystem _system;
|
|
||||||
|
|
||||||
public CombatModeOverlay(CombatModeSystem system) : base(nameof(CombatModeOverlay))
|
|
||||||
{
|
|
||||||
_system = system;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Draw(DrawingHandleBase handle)
|
|
||||||
{
|
|
||||||
var screenHandle = (DrawingHandleScreen) handle;
|
|
||||||
|
|
||||||
var mousePos = IoCManager.Resolve<IInputManager>().MouseScreenPosition;
|
|
||||||
|
|
||||||
if (_system.UseOrAttackIsDown && _system._timeHeld > AttackTimeThreshold)
|
|
||||||
{
|
|
||||||
var tex = ResC.GetTexture($"/Textures/Objects/Tools/toolbox_r.png");
|
|
||||||
|
|
||||||
screenHandle.DrawTextureRect(tex, UIBox2.FromDimensions(mousePos, tex.Size * 2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
var canFireSemi = _isFirstShot;
|
var canFireSemi = _isFirstShot;
|
||||||
var state = _inputSystem.CmdStates.GetState(ContentKeyFunctions.Attack);
|
var state = _inputSystem.CmdStates.GetState(EngineKeyFunctions.Use);
|
||||||
if (!_combatModeSystem.UseOrAttackIsDown && state != BoundKeyState.Down)
|
if (!_combatModeSystem.IsInCombatMode() || state != BoundKeyState.Down)
|
||||||
{
|
{
|
||||||
_isFirstShot = true;
|
_isFirstShot = true;
|
||||||
_blocked = false;
|
_blocked = false;
|
||||||
|
|||||||
@@ -150,7 +150,10 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(user, entity))
|
if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(user, entity))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var disabled = verb.GetVisibility(user, component) != VerbVisibility.Visible;
|
if (VerbUtility.IsVerbInvisible(verb, user, component, out var vis))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var disabled = vis != VerbVisibility.Visible;
|
||||||
var category = verb.GetCategory(user, component);
|
var category = verb.GetCategory(user, component);
|
||||||
|
|
||||||
|
|
||||||
@@ -166,7 +169,10 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
if (globalVerb.RequireInteractionRange && !VerbUtility.InVerbUseRange(user, entity))
|
if (globalVerb.RequireInteractionRange && !VerbUtility.InVerbUseRange(user, entity))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var disabled = globalVerb.GetVisibility(user, entity) != VerbVisibility.Visible;
|
if (VerbUtility.IsVerbInvisible(globalVerb, user, entity, out var vis))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var disabled = vis != VerbVisibility.Visible;
|
||||||
var category = globalVerb.GetCategory(user, entity);
|
var category = globalVerb.GetCategory(user, entity);
|
||||||
|
|
||||||
if(!buttons.ContainsKey(category))
|
if(!buttons.ContainsKey(category))
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ namespace Content.Client.Input
|
|||||||
common.AddFunction(ContentKeyFunctions.FocusChat);
|
common.AddFunction(ContentKeyFunctions.FocusChat);
|
||||||
common.AddFunction(ContentKeyFunctions.ExamineEntity);
|
common.AddFunction(ContentKeyFunctions.ExamineEntity);
|
||||||
common.AddFunction(ContentKeyFunctions.OpenTutorial);
|
common.AddFunction(ContentKeyFunctions.OpenTutorial);
|
||||||
common.AddFunction(ContentKeyFunctions.UseOrAttack);
|
common.AddFunction(ContentKeyFunctions.TakeScreenshot);
|
||||||
|
common.AddFunction(ContentKeyFunctions.TakeScreenshotNoUI);
|
||||||
|
|
||||||
var human = contexts.GetContext("human");
|
var human = contexts.GetContext("human");
|
||||||
human.AddFunction(ContentKeyFunctions.SwapHands);
|
human.AddFunction(ContentKeyFunctions.SwapHands);
|
||||||
@@ -27,9 +28,11 @@ namespace Content.Client.Input
|
|||||||
human.AddFunction(ContentKeyFunctions.OpenContextMenu);
|
human.AddFunction(ContentKeyFunctions.OpenContextMenu);
|
||||||
human.AddFunction(ContentKeyFunctions.OpenCraftingMenu);
|
human.AddFunction(ContentKeyFunctions.OpenCraftingMenu);
|
||||||
human.AddFunction(ContentKeyFunctions.OpenInventoryMenu);
|
human.AddFunction(ContentKeyFunctions.OpenInventoryMenu);
|
||||||
|
human.AddFunction(ContentKeyFunctions.SmartEquipBackpack);
|
||||||
|
human.AddFunction(ContentKeyFunctions.SmartEquipBelt);
|
||||||
human.AddFunction(ContentKeyFunctions.MouseMiddle);
|
human.AddFunction(ContentKeyFunctions.MouseMiddle);
|
||||||
human.AddFunction(ContentKeyFunctions.ToggleCombatMode);
|
human.AddFunction(ContentKeyFunctions.ToggleCombatMode);
|
||||||
human.AddFunction(ContentKeyFunctions.Attack);
|
human.AddFunction(ContentKeyFunctions.WideAttack);
|
||||||
|
|
||||||
var ghost = contexts.New("ghost", "common");
|
var ghost = contexts.New("ghost", "common");
|
||||||
ghost.AddFunction(EngineKeyFunctions.MoveUp);
|
ghost.AddFunction(EngineKeyFunctions.MoveUp);
|
||||||
|
|||||||
85
Content.Client/ScreenshotHook.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Shared.Input;
|
||||||
|
using Robust.Client.Interfaces.Graphics;
|
||||||
|
using Robust.Client.Interfaces.Input;
|
||||||
|
using Robust.Shared.Input;
|
||||||
|
using Robust.Shared.Interfaces.Resources;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
|
||||||
|
namespace Content.Client
|
||||||
|
{
|
||||||
|
internal class ScreenshotHook : IScreenshotHook
|
||||||
|
{
|
||||||
|
private static readonly ResourcePath BaseScreenshotPath = new ResourcePath("/Screenshots");
|
||||||
|
|
||||||
|
[Dependency] private readonly IInputManager _inputManager = default;
|
||||||
|
[Dependency] private readonly IClyde _clyde = default;
|
||||||
|
[Dependency] private readonly IResourceManager _resourceManager = default;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_inputManager.SetInputCommand(ContentKeyFunctions.TakeScreenshot, InputCmdHandler.FromDelegate(_ =>
|
||||||
|
{
|
||||||
|
Take(ScreenshotType.AfterUI);
|
||||||
|
}));
|
||||||
|
|
||||||
|
_inputManager.SetInputCommand(ContentKeyFunctions.TakeScreenshotNoUI, InputCmdHandler.FromDelegate(_ =>
|
||||||
|
{
|
||||||
|
Take(ScreenshotType.BeforeUI);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Take(ScreenshotType type)
|
||||||
|
{
|
||||||
|
var screenshot = await _clyde.ScreenshotAsync(type);
|
||||||
|
|
||||||
|
var time = DateTime.Now.ToString("yyyy-M-dd_HH.mm.ss");
|
||||||
|
|
||||||
|
if (!_resourceManager.UserData.IsDir(BaseScreenshotPath))
|
||||||
|
{
|
||||||
|
_resourceManager.UserData.CreateDir(BaseScreenshotPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filename = time;
|
||||||
|
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
filename = $"{filename}-{i}";
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var file =
|
||||||
|
_resourceManager.UserData.Open(BaseScreenshotPath / $"{filename}.png", FileMode.CreateNew);
|
||||||
|
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
// Saving takes forever, so don't hang the game on it.
|
||||||
|
screenshot.SaveAsPng(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
Logger.InfoS("screenshot", "Screenshot taken as {0}.png", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Logger.WarningS("screenshot", "Failed to save screenshot, retrying?:\n{0}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.ErrorS("screenshot", "Unable to save screenshot.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IScreenshotHook
|
||||||
|
{
|
||||||
|
void Initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ using Robust.Client.Interfaces.ResourceManagement;
|
|||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -57,10 +58,10 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
AddChild(hBox);
|
AddChild(hBox);
|
||||||
|
|
||||||
_leftButton.OnPressed += args => HandKeyBindDown(args.Event, HandNameLeft);
|
_leftButton.OnPressed += args => HandKeyBindDown(args, HandNameLeft);
|
||||||
_leftButton.OnStoragePressed += args => _OnStoragePressed(args.Event, HandNameLeft);
|
_leftButton.OnStoragePressed += args => _OnStoragePressed(args, HandNameLeft);
|
||||||
_rightButton.OnPressed += args => HandKeyBindDown(args.Event, HandNameRight);
|
_rightButton.OnPressed += args => HandKeyBindDown(args, HandNameRight);
|
||||||
_rightButton.OnStoragePressed += args => _OnStoragePressed(args.Event, HandNameRight);
|
_rightButton.OnStoragePressed += args => _OnStoragePressed(args, HandNameRight);
|
||||||
|
|
||||||
// Active hand
|
// Active hand
|
||||||
_leftButton.AddChild(ActiveHandRect = new TextureRect
|
_leftButton.AddChild(ActiveHandRect = new TextureRect
|
||||||
@@ -118,31 +119,34 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
private void HandKeyBindDown(GUIBoundKeyEventArgs args, string handIndex)
|
private void HandKeyBindDown(GUIBoundKeyEventArgs args, string handIndex)
|
||||||
{
|
{
|
||||||
args.Handle();
|
|
||||||
|
|
||||||
if (!TryGetHands(out var hands))
|
if (!TryGetHands(out var hands))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Function == ContentKeyFunctions.MouseMiddle)
|
if (args.Function == ContentKeyFunctions.MouseMiddle)
|
||||||
{
|
{
|
||||||
hands.SendChangeHand(handIndex);
|
hands.SendChangeHand(handIndex);
|
||||||
|
args.Handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var entity = hands.GetEntity(handIndex);
|
var entity = hands.GetEntity(handIndex);
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
if (args.CanFocus && hands.ActiveIndex != handIndex)
|
if (args.Function == EngineKeyFunctions.UIClick && hands.ActiveIndex != handIndex)
|
||||||
{
|
{
|
||||||
hands.SendChangeHand(handIndex);
|
hands.SendChangeHand(handIndex);
|
||||||
|
args.Handle();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_itemSlotManager.OnButtonPressed(args, entity))
|
if (_itemSlotManager.OnButtonPressed(args, entity))
|
||||||
|
{
|
||||||
|
args.Handle();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (args.CanFocus)
|
if (args.Function == EngineKeyFunctions.UIClick)
|
||||||
{
|
{
|
||||||
if (hands.ActiveIndex == handIndex)
|
if (hands.ActiveIndex == handIndex)
|
||||||
{
|
{
|
||||||
@@ -152,13 +156,14 @@ namespace Content.Client.UserInterface
|
|||||||
{
|
{
|
||||||
hands.AttackByInHand(handIndex);
|
hands.AttackByInHand(handIndex);
|
||||||
}
|
}
|
||||||
|
args.Handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _OnStoragePressed(GUIBoundKeyEventArgs args, string handIndex)
|
private void _OnStoragePressed(GUIBoundKeyEventArgs args, string handIndex)
|
||||||
{
|
{
|
||||||
if (!args.CanFocus)
|
if (args.Function != EngineKeyFunctions.UIClick)
|
||||||
return;
|
return;
|
||||||
if (!TryGetHands(out var hands))
|
if (!TryGetHands(out var hands))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Content.Shared.Input;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Shared.Input;
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
@@ -8,26 +10,26 @@ namespace Content.Client.GameObjects
|
|||||||
{
|
{
|
||||||
public sealed class ItemSlotButton : MarginContainer
|
public sealed class ItemSlotButton : MarginContainer
|
||||||
{
|
{
|
||||||
public BaseButton Button { get; }
|
public TextureRect Button { get; }
|
||||||
public SpriteView SpriteView { get; }
|
public SpriteView SpriteView { get; }
|
||||||
public BaseButton StorageButton { get; }
|
public BaseButton StorageButton { get; }
|
||||||
public TextureRect CooldownCircle { get; }
|
public TextureRect CooldownCircle { get; }
|
||||||
|
|
||||||
public Action<BaseButton.ButtonEventArgs> OnPressed { get; set; }
|
public Action<GUIBoundKeyEventArgs> OnPressed { get; set; }
|
||||||
public Action<BaseButton.ButtonEventArgs> OnStoragePressed { get; set; }
|
public Action<GUIBoundKeyEventArgs> OnStoragePressed { get; set; }
|
||||||
|
|
||||||
public ItemSlotButton(Texture texture, Texture storageTexture)
|
public ItemSlotButton(Texture texture, Texture storageTexture)
|
||||||
{
|
{
|
||||||
CustomMinimumSize = (64, 64);
|
CustomMinimumSize = (64, 64);
|
||||||
|
|
||||||
AddChild(Button = new TextureButton
|
AddChild(Button = new TextureRect
|
||||||
{
|
{
|
||||||
TextureNormal = texture,
|
Texture = texture,
|
||||||
Scale = (2, 2),
|
TextureScale = (2, 2),
|
||||||
EnableAllKeybinds = true
|
MouseFilter = MouseFilterMode.Stop
|
||||||
});
|
});
|
||||||
|
|
||||||
Button.OnPressed += OnButtonPressed;
|
Button.OnKeyBindDown += OnButtonPressed;
|
||||||
|
|
||||||
AddChild(SpriteView = new SpriteView
|
AddChild(SpriteView = new SpriteView
|
||||||
{
|
{
|
||||||
@@ -42,9 +44,16 @@ namespace Content.Client.GameObjects
|
|||||||
SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
|
SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
|
||||||
SizeFlagsVertical = SizeFlags.ShrinkEnd,
|
SizeFlagsVertical = SizeFlags.ShrinkEnd,
|
||||||
Visible = false,
|
Visible = false,
|
||||||
EnableAllKeybinds = true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
StorageButton.OnKeyBindDown += args =>
|
||||||
|
{
|
||||||
|
if (args.Function != EngineKeyFunctions.UIClick)
|
||||||
|
{
|
||||||
|
OnButtonPressed(args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
StorageButton.OnPressed += OnStorageButtonPressed;
|
StorageButton.OnPressed += OnStorageButtonPressed;
|
||||||
|
|
||||||
AddChild(CooldownCircle = new TextureRect
|
AddChild(CooldownCircle = new TextureRect
|
||||||
@@ -57,20 +66,20 @@ namespace Content.Client.GameObjects
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnButtonPressed(BaseButton.ButtonEventArgs args)
|
private void OnButtonPressed(GUIBoundKeyEventArgs args)
|
||||||
{
|
{
|
||||||
OnPressed?.Invoke(args);
|
OnPressed?.Invoke(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStorageButtonPressed(BaseButton.ButtonEventArgs args)
|
private void OnStorageButtonPressed(BaseButton.ButtonEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.Event.Function == EngineKeyFunctions.Use)
|
if (args.Event.Function == EngineKeyFunctions.UIClick)
|
||||||
{
|
{
|
||||||
OnStoragePressed?.Invoke(args);
|
OnStoragePressed?.Invoke(args.Event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OnPressed?.Invoke(args);
|
OnPressed?.Invoke(args.Event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ namespace Content.Client.UserInterface
|
|||||||
|
|
||||||
public bool OnButtonPressed(GUIBoundKeyEventArgs args, IEntity item)
|
public bool OnButtonPressed(GUIBoundKeyEventArgs args, IEntity item)
|
||||||
{
|
{
|
||||||
args.Handle();
|
|
||||||
|
|
||||||
if (item == null)
|
if (item == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -99,6 +97,7 @@ namespace Content.Client.UserInterface
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
args.Handle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
public const string StyleClassLabelSecondaryColor = "LabelSecondaryColor";
|
public const string StyleClassLabelSecondaryColor = "LabelSecondaryColor";
|
||||||
public const string StyleClassLabelBig = "LabelBig";
|
public const string StyleClassLabelBig = "LabelBig";
|
||||||
public const string StyleClassButtonBig = "ButtonBig";
|
public const string StyleClassButtonBig = "ButtonBig";
|
||||||
|
public const string StyleClassPopupMessage = "PopupMessage";
|
||||||
|
|
||||||
public static readonly Color NanoGold = Color.FromHex("#A88B5E");
|
public static readonly Color NanoGold = Color.FromHex("#A88B5E");
|
||||||
|
|
||||||
@@ -41,7 +42,9 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
public StyleNano(IResourceCache resCache) : base(resCache)
|
public StyleNano(IResourceCache resCache) : base(resCache)
|
||||||
{
|
{
|
||||||
var notoSans10 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 10);
|
var notoSans10 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 10);
|
||||||
|
var notoSansItalic10 = resCache.GetFont("/Nano/NotoSans/NotoSans-Italic.ttf", 10);
|
||||||
var notoSans12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 12);
|
var notoSans12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 12);
|
||||||
|
var notoSansItalic12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Italic.ttf", 12);
|
||||||
var notoSansBold12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Bold.ttf", 12);
|
var notoSansBold12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Bold.ttf", 12);
|
||||||
var notoSansDisplayBold14 = resCache.GetFont("/Fonts/NotoSansDisplay/NotoSansDisplay-Bold.ttf", 14);
|
var notoSansDisplayBold14 = resCache.GetFont("/Fonts/NotoSansDisplay/NotoSansDisplay-Bold.ttf", 14);
|
||||||
var notoSans16 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 16);
|
var notoSans16 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 16);
|
||||||
@@ -449,6 +452,19 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox)
|
new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
new StyleRule(new SelectorElement(typeof(PanelContainer), new[] {"speechBox", "sayBox"}, null, null), new[]
|
||||||
|
{
|
||||||
|
new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox)
|
||||||
|
}),
|
||||||
|
|
||||||
|
new StyleRule(new SelectorChild(
|
||||||
|
new SelectorElement(typeof(PanelContainer), new[] {"speechBox", "emoteBox"}, null, null),
|
||||||
|
new SelectorElement(typeof(RichTextLabel), null, null, null)),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new StyleProperty("font", notoSansItalic12),
|
||||||
|
}),
|
||||||
|
|
||||||
// Entity tooltip
|
// Entity tooltip
|
||||||
new StyleRule(
|
new StyleRule(
|
||||||
new SelectorElement(typeof(PanelContainer), new[] {ExamineSystem.StyleClassEntityTooltip}, null,
|
new SelectorElement(typeof(PanelContainer), new[] {ExamineSystem.StyleClassEntityTooltip}, null,
|
||||||
@@ -552,6 +568,14 @@ namespace Content.Client.UserInterface.Stylesheets
|
|||||||
new StyleProperty("font", notoSans16)
|
new StyleProperty("font", notoSans16)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// Popup messages
|
||||||
|
new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassPopupMessage}, null, null),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new StyleProperty("font", notoSansItalic10),
|
||||||
|
new StyleProperty("font-color", Color.LightGray),
|
||||||
|
}),
|
||||||
|
|
||||||
//APC and SMES power state label colors
|
//APC and SMES power state label colors
|
||||||
new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassPowerStateNone}, null, null), new[]
|
new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassPowerStateNone}, null, null), new[]
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,10 +69,14 @@ namespace Content.Client.UserInterface
|
|||||||
Switch hands: [color=#a4885c]{4}[/color]
|
Switch hands: [color=#a4885c]{4}[/color]
|
||||||
Use held item: [color=#a4885c]{5}[/color]
|
Use held item: [color=#a4885c]{5}[/color]
|
||||||
Drop held item: [color=#a4885c]{6}[/color]
|
Drop held item: [color=#a4885c]{6}[/color]
|
||||||
|
Smart equip from backpack: [color=#a4885c]{24}[/color]
|
||||||
|
Smart equip from belt: [color=#a4885c]{25}[/color]
|
||||||
Open inventory: [color=#a4885c]{7}[/color]
|
Open inventory: [color=#a4885c]{7}[/color]
|
||||||
Open character window: [color=#a4885c]{8}[/color]
|
Open character window: [color=#a4885c]{8}[/color]
|
||||||
Open crafting window: [color=#a4885c]{9}[/color]
|
Open crafting window: [color=#a4885c]{9}[/color]
|
||||||
Focus chat: [color=#a4885c]{10}[/color]
|
Focus chat: [color=#a4885c]{10}[/color]
|
||||||
|
Use hand/object in hand: [color=#a4885c]{22}[/color]
|
||||||
|
Do wide attack: [color=#a4885c]{23}[/color]
|
||||||
Use targeted entity: [color=#a4885c]{11}[/color]
|
Use targeted entity: [color=#a4885c]{11}[/color]
|
||||||
Throw held item: [color=#a4885c]{12}[/color]
|
Throw held item: [color=#a4885c]{12}[/color]
|
||||||
Examine entity: [color=#a4885c]{13}[/color]
|
Examine entity: [color=#a4885c]{13}[/color]
|
||||||
@@ -102,16 +106,20 @@ Toggle sandbox window: [color=#a4885c]{21}[/color]",
|
|||||||
Key(ShowDebugMonitors),
|
Key(ShowDebugMonitors),
|
||||||
Key(OpenEntitySpawnWindow),
|
Key(OpenEntitySpawnWindow),
|
||||||
Key(OpenTileSpawnWindow),
|
Key(OpenTileSpawnWindow),
|
||||||
Key(OpenSandboxWindow)));
|
Key(OpenSandboxWindow),
|
||||||
|
Key(Use),
|
||||||
//Gameplay
|
Key(WideAttack),
|
||||||
VBox.AddChild(new Label { FontOverride = headerFont, Text = Loc.GetString("\nSandbox spawner", Key(OpenSandboxWindow)) });
|
Key(SmartEquipBackpack),
|
||||||
AddFormattedText(SandboxSpawnerContents);
|
Key(SmartEquipBelt)));
|
||||||
|
|
||||||
//Gameplay
|
//Gameplay
|
||||||
VBox.AddChild(new Label { FontOverride = headerFont, Text = "\nGameplay" });
|
VBox.AddChild(new Label { FontOverride = headerFont, Text = "\nGameplay" });
|
||||||
AddFormattedText(GameplayContents);
|
AddFormattedText(GameplayContents);
|
||||||
|
|
||||||
|
//Gameplay
|
||||||
|
VBox.AddChild(new Label { FontOverride = headerFont, Text = Loc.GetString("\nSandbox spawner", Key(OpenSandboxWindow)) });
|
||||||
|
AddFormattedText(SandboxSpawnerContents);
|
||||||
|
|
||||||
//Feedback
|
//Feedback
|
||||||
VBox.AddChild(new Label { FontOverride = headerFont, Text = "\nFeedback" });
|
VBox.AddChild(new Label { FontOverride = headerFont, Text = "\nFeedback" });
|
||||||
AddFormattedText(FeedbackContents);
|
AddFormattedText(FeedbackContents);
|
||||||
|
|||||||
64
Content.IntegrationTests/Tests/GravityGridTest.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Client.GameObjects.Components.Gravity;
|
||||||
|
using Content.Server.GameObjects.Components.Gravity;
|
||||||
|
using Content.Server.GameObjects.Components.Power;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests
|
||||||
|
{
|
||||||
|
/// Tests the behavior of GravityGeneratorComponent,
|
||||||
|
/// making sure that gravity is applied to the correct grids.
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(GravityGeneratorComponent))]
|
||||||
|
public class GravityGridTest : ContentIntegrationTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public async Task Test()
|
||||||
|
{
|
||||||
|
var server = StartServerDummyTicker();
|
||||||
|
|
||||||
|
IEntity generator = null;
|
||||||
|
|
||||||
|
IMapGrid grid1 = null;
|
||||||
|
IMapGrid grid2 = null;
|
||||||
|
|
||||||
|
// Create grids
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||||
|
|
||||||
|
mapMan.CreateMap(new MapId(1));
|
||||||
|
grid1 = mapMan.CreateGrid(new MapId(1));
|
||||||
|
grid2 = mapMan.CreateGrid(new MapId(1));
|
||||||
|
|
||||||
|
var entityMan = IoCManager.Resolve<IEntityManager>();
|
||||||
|
|
||||||
|
generator = entityMan.SpawnEntity("GravityGenerator", new GridCoordinates(new Vector2(0, 0), grid2.Index));
|
||||||
|
Assert.That(generator.HasComponent<GravityGeneratorComponent>());
|
||||||
|
Assert.That(generator.HasComponent<PowerDeviceComponent>());
|
||||||
|
var generatorComponent = generator.GetComponent<GravityGeneratorComponent>();
|
||||||
|
var powerComponent = generator.GetComponent<PowerDeviceComponent>();
|
||||||
|
Assert.AreEqual(generatorComponent.Status, GravityGeneratorStatus.Unpowered);
|
||||||
|
powerComponent.ExternalPowered = true;
|
||||||
|
});
|
||||||
|
server.RunTicks(1);
|
||||||
|
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
var generatorComponent = generator.GetComponent<GravityGeneratorComponent>();
|
||||||
|
|
||||||
|
Assert.AreEqual(generatorComponent.Status, GravityGeneratorStatus.On);
|
||||||
|
|
||||||
|
Assert.That(!grid1.HasGravity);
|
||||||
|
Assert.That(grid2.HasGravity);
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using Content.Server.Interfaces.Chat;
|
|||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Preferences;
|
using Content.Server.Preferences;
|
||||||
using Content.Server.Sandbox;
|
using Content.Server.Sandbox;
|
||||||
|
using Content.Shared.Kitchen;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.ContentPack;
|
using Robust.Shared.ContentPack;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -70,6 +71,7 @@ namespace Content.Server
|
|||||||
logManager.GetSawmill("Storage").Level = LogLevel.Info;
|
logManager.GetSawmill("Storage").Level = LogLevel.Info;
|
||||||
|
|
||||||
IoCManager.Resolve<IServerPreferencesManager>().StartInit();
|
IoCManager.Resolve<IServerPreferencesManager>().StartInit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PostInit()
|
public override void PostInit()
|
||||||
@@ -79,6 +81,7 @@ namespace Content.Server
|
|||||||
_gameTicker.Initialize();
|
_gameTicker.Initialize();
|
||||||
IoCManager.Resolve<ISandboxManager>().Initialize();
|
IoCManager.Resolve<ISandboxManager>().Initialize();
|
||||||
IoCManager.Resolve<IServerPreferencesManager>().FinishInit();
|
IoCManager.Resolve<IServerPreferencesManager>().FinishInit();
|
||||||
|
IoCManager.Resolve<RecipeManager>().Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)
|
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)
|
||||||
|
|||||||
@@ -151,6 +151,12 @@ namespace Content.Server.GameObjects
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PutInHandOrDrop(ItemComponent item)
|
||||||
|
{
|
||||||
|
if (!PutInHand(item))
|
||||||
|
item.Owner.Transform.GridPosition = Owner.Transform.GridPosition;
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanPutInHand(ItemComponent item)
|
public bool CanPutInHand(ItemComponent item)
|
||||||
{
|
{
|
||||||
foreach (var hand in ActivePriorityEnumerable())
|
foreach (var hand in ActivePriorityEnumerable())
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
using Content.Server.GameObjects.Components.Damage;
|
||||||
|
using Content.Server.GameObjects.Components.Interactable.Tools;
|
||||||
|
using Content.Server.GameObjects.Components.Power;
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Server.Interfaces;
|
||||||
|
using Content.Shared.GameObjects.Components.Gravity;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.GameObjects.Components.UserInterface;
|
||||||
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Gravity
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class GravityGeneratorComponent: SharedGravityGeneratorComponent, IAttackBy, IBreakAct, IAttackHand
|
||||||
|
{
|
||||||
|
private BoundUserInterface _userInterface;
|
||||||
|
|
||||||
|
private PowerDeviceComponent _powerDevice;
|
||||||
|
|
||||||
|
private SpriteComponent _sprite;
|
||||||
|
|
||||||
|
private bool _switchedOn;
|
||||||
|
|
||||||
|
private bool _intact;
|
||||||
|
|
||||||
|
private GravityGeneratorStatus _status;
|
||||||
|
|
||||||
|
public bool Powered => _powerDevice.Powered;
|
||||||
|
|
||||||
|
public bool SwitchedOn => _switchedOn;
|
||||||
|
|
||||||
|
public bool Intact => _intact;
|
||||||
|
|
||||||
|
public GravityGeneratorStatus Status => _status;
|
||||||
|
|
||||||
|
public bool NeedsUpdate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (_status)
|
||||||
|
{
|
||||||
|
case GravityGeneratorStatus.On:
|
||||||
|
return !(Powered && SwitchedOn && Intact);
|
||||||
|
case GravityGeneratorStatus.Off:
|
||||||
|
return SwitchedOn || !(Powered && Intact);
|
||||||
|
case GravityGeneratorStatus.Unpowered:
|
||||||
|
return SwitchedOn || Powered || !Intact;
|
||||||
|
case GravityGeneratorStatus.Broken:
|
||||||
|
return SwitchedOn || Powered || Intact;
|
||||||
|
default:
|
||||||
|
return true; // This _should_ be unreachable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name => "GravityGenerator";
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||||
|
.GetBoundUserInterface(GravityGeneratorUiKey.Key);
|
||||||
|
_userInterface.OnReceiveMessage += HandleUIMessage;
|
||||||
|
_powerDevice = Owner.GetComponent<PowerDeviceComponent>();
|
||||||
|
_sprite = Owner.GetComponent<SpriteComponent>();
|
||||||
|
_switchedOn = true;
|
||||||
|
_intact = true;
|
||||||
|
_status = GravityGeneratorStatus.On;
|
||||||
|
UpdateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
|
serializer.DataField(ref _switchedOn, "switched_on", true);
|
||||||
|
serializer.DataField(ref _intact, "intact", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IAttackHand.AttackHand(AttackHandEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!eventArgs.User.TryGetComponent<IActorComponent>(out var actor))
|
||||||
|
return false;
|
||||||
|
if (Status != GravityGeneratorStatus.Off && Status != GravityGeneratorStatus.On)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OpenUserInterface(actor.playerSession);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AttackBy(AttackByEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!eventArgs.AttackWith.TryGetComponent<WelderComponent>(out var welder)) return false;
|
||||||
|
if (welder.TryUse(5.0f))
|
||||||
|
{
|
||||||
|
// Repair generator
|
||||||
|
var damagable = Owner.GetComponent<DamageableComponent>();
|
||||||
|
var breakable = Owner.GetComponent<BreakableComponent>();
|
||||||
|
damagable.HealAllDamage();
|
||||||
|
breakable.broken = false;
|
||||||
|
_intact = true;
|
||||||
|
|
||||||
|
var entitySystemManager = IoCManager.Resolve<IEntitySystemManager>();
|
||||||
|
var notifyManager = IoCManager.Resolve<IServerNotifyManager>();
|
||||||
|
|
||||||
|
entitySystemManager.GetEntitySystem<AudioSystem>().Play("/Audio/items/welder2.ogg", Owner);
|
||||||
|
notifyManager.PopupMessage(Owner, eventArgs.User, Loc.GetString("You repair the gravity generator with the welder"));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnBreak(BreakageEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
_intact = false;
|
||||||
|
_switchedOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateState()
|
||||||
|
{
|
||||||
|
if (!Intact)
|
||||||
|
{
|
||||||
|
MakeBroken();
|
||||||
|
} else if (!Powered)
|
||||||
|
{
|
||||||
|
MakeUnpowered();
|
||||||
|
} else if (!SwitchedOn)
|
||||||
|
{
|
||||||
|
MakeOff();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
MakeOn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleUIMessage(ServerBoundUserInterfaceMessage message)
|
||||||
|
{
|
||||||
|
switch (message.Message)
|
||||||
|
{
|
||||||
|
case GeneratorStatusRequestMessage _:
|
||||||
|
_userInterface.SetState(new GeneratorState(Status == GravityGeneratorStatus.On));
|
||||||
|
break;
|
||||||
|
case SwitchGeneratorMessage msg:
|
||||||
|
_switchedOn = msg.On;
|
||||||
|
UpdateState();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenUserInterface(IPlayerSession playerSession)
|
||||||
|
{
|
||||||
|
_userInterface.Open(playerSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MakeBroken()
|
||||||
|
{
|
||||||
|
_status = GravityGeneratorStatus.Broken;
|
||||||
|
_sprite.LayerSetState(0, "broken");
|
||||||
|
_sprite.LayerSetVisible(1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MakeUnpowered()
|
||||||
|
{
|
||||||
|
_status = GravityGeneratorStatus.Unpowered;
|
||||||
|
_sprite.LayerSetState(0, "off");
|
||||||
|
_sprite.LayerSetVisible(1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MakeOff()
|
||||||
|
{
|
||||||
|
_status = GravityGeneratorStatus.Off;
|
||||||
|
_sprite.LayerSetState(0, "off");
|
||||||
|
_sprite.LayerSetVisible(1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MakeOn()
|
||||||
|
{
|
||||||
|
_status = GravityGeneratorStatus.On;
|
||||||
|
_sprite.LayerSetState(0, "on");
|
||||||
|
_sprite.LayerSetVisible(1, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum GravityGeneratorStatus
|
||||||
|
{
|
||||||
|
Broken,
|
||||||
|
Unpowered,
|
||||||
|
Off,
|
||||||
|
On
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,6 +45,8 @@ namespace Content.Server.GameObjects
|
|||||||
private int StorageCapacityMax = 10000;
|
private int StorageCapacityMax = 10000;
|
||||||
public HashSet<IPlayerSession> SubscribedSessions = new HashSet<IPlayerSession>();
|
public HashSet<IPlayerSession> SubscribedSessions = new HashSet<IPlayerSession>();
|
||||||
|
|
||||||
|
public IReadOnlyCollection<IEntity> StoredEntities => storage.ContainedEntities;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -140,7 +142,6 @@ namespace Content.Server.GameObjects
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool AttackBy(AttackByEventArgs eventArgs)
|
public bool AttackBy(AttackByEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
_ensureInitialCalculated();
|
|
||||||
Logger.DebugS("Storage", "Storage (UID {0}) attacked by user (UID {1}) with entity (UID {2}).", Owner.Uid, eventArgs.User.Uid, eventArgs.AttackWith.Uid);
|
Logger.DebugS("Storage", "Storage (UID {0}) attacked by user (UID {1}) with entity (UID {2}).", Owner.Uid, eventArgs.User.Uid, eventArgs.AttackWith.Uid);
|
||||||
|
|
||||||
if(Owner.TryGetComponent<PlaceableSurfaceComponent>(out var placeableSurfaceComponent))
|
if(Owner.TryGetComponent<PlaceableSurfaceComponent>(out var placeableSurfaceComponent))
|
||||||
@@ -363,8 +364,10 @@ namespace Content.Server.GameObjects
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inserts an entity into the storage component from the players active hand.
|
/// Inserts an entity into the storage component from the players active hand.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool PlayerInsertEntity(IEntity player)
|
public bool PlayerInsertEntity(IEntity player)
|
||||||
{
|
{
|
||||||
|
_ensureInitialCalculated();
|
||||||
|
|
||||||
if (!player.TryGetComponent(out IHandsComponent hands) || hands.GetActiveHand == null)
|
if (!player.TryGetComponent(out IHandsComponent hands) || hands.GetActiveHand == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,408 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
using Content.Server.GameObjects.Components.Chemistry;
|
||||||
|
using Content.Server.GameObjects.Components.Nutrition;
|
||||||
|
using Content.Shared.Chemistry;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Content.Shared.Prototypes.Kitchen;
|
||||||
|
using Content.Shared.Kitchen;
|
||||||
|
using Robust.Shared.Timers;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Content.Shared.GameObjects.Components.Power;
|
||||||
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
|
using Content.Server.GameObjects.Components.Power;
|
||||||
|
using Robust.Server.GameObjects.Components.UserInterface;
|
||||||
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Content.Server.Interfaces;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using YamlDotNet.Serialization.NodeTypeResolvers;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Kitchen
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
[ComponentReference(typeof(IActivate))]
|
||||||
|
public class KitchenMicrowaveComponent : SharedMicrowaveComponent, IActivate, IAttackBy, ISolutionChange
|
||||||
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager;
|
||||||
|
[Dependency] private readonly RecipeManager _recipeManager;
|
||||||
|
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
#region YAMLSERIALIZE
|
||||||
|
private int _cookTimeDefault;
|
||||||
|
private int _cookTimeMultiplier; //For upgrades and stuff I guess?
|
||||||
|
private string _badRecipeName;
|
||||||
|
private string _startCookingSound;
|
||||||
|
private string _cookingCompleteSound;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region VIEWVARIABLES
|
||||||
|
[ViewVariables]
|
||||||
|
private SolutionComponent _solution;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private bool _busy = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a fixed offset of 5.
|
||||||
|
/// The cook times for all recipes should be divisible by 5,with a minimum of 1 second.
|
||||||
|
/// For right now, I don't think any recipe cook time should be greater than 60 seconds.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
private uint _currentCookTimerTime { get; set; } = 1;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private bool Powered => _powerDevice.Powered;
|
||||||
|
|
||||||
|
private bool HasContents => _solution.ReagentList.Count > 0 || _storage.ContainedEntities.Count > 0;
|
||||||
|
|
||||||
|
void ISolutionChange.SolutionChanged(SolutionChangeEventArgs eventArgs) => UpdateUserInterface();
|
||||||
|
|
||||||
|
private AudioSystem _audioSystem;
|
||||||
|
|
||||||
|
private AppearanceComponent _appearance;
|
||||||
|
private PowerDeviceComponent _powerDevice;
|
||||||
|
|
||||||
|
private BoundUserInterface _userInterface;
|
||||||
|
|
||||||
|
private Container _storage;
|
||||||
|
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
serializer.DataField(ref _badRecipeName, "failureResult", "FoodBadRecipe");
|
||||||
|
serializer.DataField(ref _cookTimeDefault, "cookTime", 5);
|
||||||
|
serializer.DataField(ref _cookTimeMultiplier, "cookTimeMultiplier", 1000);
|
||||||
|
serializer.DataField(ref _startCookingSound, "beginCookingSound","/Audio/machines/microwave_start_beep.ogg" );
|
||||||
|
serializer.DataField(ref _cookingCompleteSound, "foodDoneSound","/Audio/machines/microwave_done_beep.ogg" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
_solution ??= Owner.TryGetComponent(out SolutionComponent solutionComponent)
|
||||||
|
? solutionComponent
|
||||||
|
: Owner.AddComponent<SolutionComponent>();
|
||||||
|
|
||||||
|
_storage = ContainerManagerComponent.Ensure<Container>("microwave_entity_container", Owner, out var existed);
|
||||||
|
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||||
|
_powerDevice = Owner.GetComponent<PowerDeviceComponent>();
|
||||||
|
_audioSystem = _entitySystemManager.GetEntitySystem<AudioSystem>();
|
||||||
|
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||||
|
.GetBoundUserInterface(MicrowaveUiKey.Key);
|
||||||
|
|
||||||
|
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||||
|
{
|
||||||
|
if (!Powered || _busy)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message.Message)
|
||||||
|
{
|
||||||
|
case MicrowaveStartCookMessage msg :
|
||||||
|
wzhzhzh();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MicrowaveEjectMessage msg :
|
||||||
|
if (HasContents)
|
||||||
|
{
|
||||||
|
VaporizeReagents();
|
||||||
|
EjectSolids();
|
||||||
|
ClickSound();
|
||||||
|
UpdateUserInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MicrowaveEjectSolidIndexedMessage msg:
|
||||||
|
if (HasContents)
|
||||||
|
{
|
||||||
|
EjectSolidWithIndex(msg.EntityID);
|
||||||
|
ClickSound();
|
||||||
|
UpdateUserInterface();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MicrowaveVaporizeReagentIndexedMessage msg:
|
||||||
|
if (HasContents)
|
||||||
|
{
|
||||||
|
VaporizeReagentWithReagentQuantity(msg.ReagentQuantity);
|
||||||
|
ClickSound();
|
||||||
|
UpdateUserInterface();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MicrowaveSelectCookTimeMessage msg:
|
||||||
|
_currentCookTimerTime = msg.newCookTime;
|
||||||
|
ClickSound();
|
||||||
|
UpdateUserInterface();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAppearance(MicrowaveVisualState state)
|
||||||
|
{
|
||||||
|
if (_appearance != null || Owner.TryGetComponent(out _appearance))
|
||||||
|
{
|
||||||
|
_appearance.SetData(PowerDeviceVisuals.VisualState, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateUserInterface()
|
||||||
|
{
|
||||||
|
var solidsVisualList = new List<EntityUid>();
|
||||||
|
foreach(var item in _storage.ContainedEntities)
|
||||||
|
{
|
||||||
|
solidsVisualList.Add(item.Uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
_userInterface.SetState(new MicrowaveUpdateUserInterfaceState(_solution.Solution.Contents, solidsVisualList));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!eventArgs.User.TryGetComponent(out IActorComponent actor) || !Powered)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UpdateUserInterface();
|
||||||
|
_userInterface.Open(actor.playerSession);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AttackBy(AttackByEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
var itemEntity = eventArgs.User.GetComponent<HandsComponent>().GetActiveHand.Owner;
|
||||||
|
|
||||||
|
if(itemEntity.TryGetComponent<PourableComponent>(out var attackPourable))
|
||||||
|
{
|
||||||
|
//Get target and check if it can be poured into
|
||||||
|
if (!Owner.TryGetComponent<SolutionComponent>(out var mySolution)
|
||||||
|
|| !mySolution.CanPourIn)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!itemEntity.TryGetComponent<SolutionComponent>(out var attackSolution)
|
||||||
|
|| !attackSolution.CanPourOut)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get transfer amount. May be smaller than _transferAmount if not enough room
|
||||||
|
var realTransferAmount = ReagentUnit.Min(attackPourable.TransferAmount, mySolution.EmptyVolume);
|
||||||
|
if (realTransferAmount <= 0) //Special message if container is full
|
||||||
|
{
|
||||||
|
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
|
||||||
|
Loc.GetString("Container is full"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Move units from attackSolution to targetSolution
|
||||||
|
var removedSolution = attackSolution.SplitSolution(realTransferAmount);
|
||||||
|
if (!mySolution.TryAddSolution(removedSolution))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User,
|
||||||
|
Loc.GetString("Transferred {0}u", removedSolution.TotalVolume));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!itemEntity.TryGetComponent(typeof(FoodComponent), out var food))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ent = food.Owner; //Get the entity of the ItemComponent.
|
||||||
|
_storage.Insert(ent);
|
||||||
|
UpdateUserInterface();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//This is required. It's 'cook'.
|
||||||
|
private void wzhzhzh()
|
||||||
|
{
|
||||||
|
if (!HasContents)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_busy = true;
|
||||||
|
// Convert storage into Dictionary of ingredients
|
||||||
|
var solidsDict = new Dictionary<string, int>();
|
||||||
|
foreach(var item in _storage.ContainedEntities)
|
||||||
|
{
|
||||||
|
if(solidsDict.ContainsKey(item.Prototype.ID))
|
||||||
|
{
|
||||||
|
solidsDict[item.Prototype.ID]++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solidsDict.Add(item.Prototype.ID, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check recipes
|
||||||
|
FoodRecipePrototype recipeToCook = null;
|
||||||
|
foreach(var r in _recipeManager.Recipes)
|
||||||
|
{
|
||||||
|
if (!CanSatisfyRecipe(r, solidsDict))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
recipeToCook = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
var goodMeal = (recipeToCook != null)
|
||||||
|
&&
|
||||||
|
(_currentCookTimerTime == (uint)recipeToCook.CookTime) ? true : false;
|
||||||
|
|
||||||
|
SetAppearance(MicrowaveVisualState.Cooking);
|
||||||
|
_audioSystem.Play(_startCookingSound);
|
||||||
|
Timer.Spawn((int)(_currentCookTimerTime * _cookTimeMultiplier), () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
if (goodMeal)
|
||||||
|
{
|
||||||
|
SubtractContents(recipeToCook);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VaporizeReagents();
|
||||||
|
VaporizeSolids();
|
||||||
|
}
|
||||||
|
|
||||||
|
var entityToSpawn = goodMeal ? recipeToCook.Result : _badRecipeName;
|
||||||
|
_entityManager.SpawnEntity(entityToSpawn, Owner.Transform.GridPosition);
|
||||||
|
_audioSystem.Play(_cookingCompleteSound);
|
||||||
|
SetAppearance(MicrowaveVisualState.Idle);
|
||||||
|
_busy = false;
|
||||||
|
});
|
||||||
|
UpdateUserInterface();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VaporizeReagents()
|
||||||
|
{
|
||||||
|
_solution.RemoveAllSolution();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VaporizeReagentWithReagentQuantity(Solution.ReagentQuantity reagentQuantity)
|
||||||
|
{
|
||||||
|
_solution.TryRemoveReagent(reagentQuantity.ReagentId, reagentQuantity.Quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VaporizeSolids()
|
||||||
|
{
|
||||||
|
for(var i = _storage.ContainedEntities.Count-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
var item = _storage.ContainedEntities.ElementAt(i);
|
||||||
|
_storage.Remove(item);
|
||||||
|
item.Delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EjectSolids()
|
||||||
|
{
|
||||||
|
|
||||||
|
for(var i = _storage.ContainedEntities.Count-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
_storage.Remove(_storage.ContainedEntities.ElementAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EjectSolidWithIndex(EntityUid entityID)
|
||||||
|
{
|
||||||
|
if (_entityManager.EntityExists(entityID))
|
||||||
|
{
|
||||||
|
_storage.Remove(_entityManager.GetEntity(entityID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SubtractContents(FoodRecipePrototype recipe)
|
||||||
|
{
|
||||||
|
foreach(var recipeReagent in recipe.IngredientsReagents)
|
||||||
|
{
|
||||||
|
_solution.TryRemoveReagent(recipeReagent.Key, ReagentUnit.New(recipeReagent.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var recipeSolid in recipe.IngredientsSolids)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < recipeSolid.Value; i++)
|
||||||
|
{
|
||||||
|
foreach (var item in _storage.ContainedEntities)
|
||||||
|
{
|
||||||
|
if (item.Prototype.ID == recipeSolid.Key)
|
||||||
|
{
|
||||||
|
_storage.Remove(item);
|
||||||
|
item.Delete();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanSatisfyRecipe(FoodRecipePrototype recipe, Dictionary<string,int> solids)
|
||||||
|
{
|
||||||
|
foreach (var reagent in recipe.IngredientsReagents)
|
||||||
|
{
|
||||||
|
if (!_solution.ContainsReagent(reagent.Key, out var amount))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amount.Int() < reagent.Value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var solid in recipe.IngredientsSolids)
|
||||||
|
{
|
||||||
|
if (!solids.ContainsKey(solid.Key))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (solids[solid.Key] < solid.Value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClickSound()
|
||||||
|
{
|
||||||
|
|
||||||
|
_audioSystem.Play("/Audio/machines/machine_switch.ogg", AudioParams.Default.WithVolume(-2f));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,9 +118,17 @@ namespace Content.Server.GameObjects.Components.Mobs
|
|||||||
if (!ShowExamineInfo)
|
if (!ShowExamineInfo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var dead = false;
|
||||||
|
|
||||||
|
if(Owner.TryGetComponent<SpeciesComponent>(out var species))
|
||||||
|
if (species.CurrentDamageState is DeadState)
|
||||||
|
dead = true;
|
||||||
|
|
||||||
// TODO: Use gendered pronouns depending on the entity
|
// TODO: Use gendered pronouns depending on the entity
|
||||||
if(!HasMind)
|
if(!HasMind)
|
||||||
message.AddMarkup($"[color=red]They are totally catatonic. The stresses of life in deep-space must have been too much for them. Any recovery is unlikely.[/color]");
|
message.AddMarkup(!dead
|
||||||
|
? $"[color=red]They are totally catatonic. The stresses of life in deep-space must have been too much for them. Any recovery is unlikely.[/color]"
|
||||||
|
: $"[color=purple]Their soul has departed.[/color]");
|
||||||
else if(Mind.Session == null)
|
else if(Mind.Session == null)
|
||||||
message.AddMarkup("[color=yellow]They have a blank, absent-minded stare and appears completely unresponsive to anything. They may snap out of it soon.[/color]");
|
message.AddMarkup("[color=yellow]They have a blank, absent-minded stare and appears completely unresponsive to anything. They may snap out of it soon.[/color]");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ namespace Content.Server.GameObjects
|
|||||||
|
|
||||||
currentstate = threshold;
|
currentstate = threshold;
|
||||||
|
|
||||||
EntityEventArgs toRaise = new MobDamageStateChangedMessage(this);
|
var toRaise = new MobDamageStateChangedMessage(this);
|
||||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, toRaise);
|
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, toRaise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,15 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ViewVariables]
|
||||||
|
public float CurrentPushSpeed => 5.0f;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ViewVariables]
|
||||||
|
public float GrabRange => 0.2f;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the entity Sprinting (running)?
|
/// Is the entity Sprinting (running)?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -67,6 +67,14 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ViewVariables]
|
||||||
|
public float CurrentPushSpeed => 5.0f;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ViewVariables]
|
||||||
|
public float GrabRange => 0.2f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the entity Sprinting (running)?
|
/// Is the entity Sprinting (running)?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -34,6 +34,15 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float CurrentWalkSpeed { get; set; } = 8;
|
public float CurrentWalkSpeed { get; set; } = 8;
|
||||||
public float CurrentSprintSpeed { get; set; }
|
public float CurrentSprintSpeed { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ViewVariables]
|
||||||
|
public float CurrentPushSpeed => 0.0f;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[ViewVariables]
|
||||||
|
public float GrabRange => 0.0f;
|
||||||
|
|
||||||
public bool Sprinting { get; set; }
|
public bool Sprinting { get; set; }
|
||||||
public Vector2 VelocityDir { get; } = Vector2.Zero;
|
public Vector2 VelocityDir { get; } = Vector2.Zero;
|
||||||
public GridCoordinates LastPosition { get; set; }
|
public GridCoordinates LastPosition { get; set; }
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Audio;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
@@ -16,17 +17,24 @@ namespace Content.Server.GameObjects.Components.Sound
|
|||||||
public override string Name => "EmitSoundOnUse";
|
public override string Name => "EmitSoundOnUse";
|
||||||
|
|
||||||
public string _soundName;
|
public string _soundName;
|
||||||
|
public float _pitchVariation;
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
serializer.DataField(ref _soundName, "sound", "");
|
serializer.DataField(ref _soundName, "sound", string.Empty);
|
||||||
|
serializer.DataField(ref _pitchVariation, "variation", 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IUse.UseEntity(UseEntityEventArgs eventArgs)
|
bool IUse.UseEntity(UseEntityEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(_soundName))
|
if (!string.IsNullOrWhiteSpace(_soundName))
|
||||||
{
|
{
|
||||||
|
if (_pitchVariation > 0.0)
|
||||||
|
{
|
||||||
|
Owner.GetComponent<SoundComponent>().Play(_soundName, AudioHelpers.WithVariation(_pitchVariation).WithVolume(-2f));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Owner.GetComponent<SoundComponent>().Play(_soundName, AudioParams.Default.WithVolume(-2f));
|
Owner.GetComponent<SoundComponent>().Play(_soundName, AudioParams.Default.WithVolume(-2f));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -235,6 +235,14 @@ namespace Content.Server.GameObjects.Components
|
|||||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, player, _localizationManager.GetString("You have no hands."));
|
_notifyManager.PopupMessage(Owner.Transform.GridPosition, player, _localizationManager.GetString("You have no hands."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var interactionSystem = IoCManager.Resolve<EntitySystemManager>().GetEntitySystem<InteractionSystem>();
|
||||||
|
if (!interactionSystem.InRangeUnobstructed(player.Transform.MapPosition, Owner.Transform.WorldPosition, ignoredEnt: Owner))
|
||||||
|
{
|
||||||
|
_notifyManager.PopupMessage(Owner.Transform.GridPosition, player, _localizationManager.GetString("You can't reach there!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var activeHandEntity = handsComponent.GetActiveHand?.Owner;
|
var activeHandEntity = handsComponent.GetActiveHand?.Owner;
|
||||||
activeHandEntity.TryGetComponent<ToolComponent>(out var tool);
|
activeHandEntity.TryGetComponent<ToolComponent>(out var tool);
|
||||||
switch (msg.Action)
|
switch (msg.Action)
|
||||||
|
|||||||
@@ -417,8 +417,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
var inputSys = EntitySystemManager.GetEntitySystem<InputSystem>();
|
var inputSys = EntitySystemManager.GetEntitySystem<InputSystem>();
|
||||||
inputSys.BindMap.BindFunction(EngineKeyFunctions.Use,
|
inputSys.BindMap.BindFunction(EngineKeyFunctions.Use,
|
||||||
new PointerInputCmdHandler(HandleUseItemInHand));
|
new PointerInputCmdHandler(HandleUseItemInHand));
|
||||||
inputSys.BindMap.BindFunction(ContentKeyFunctions.Attack,
|
inputSys.BindMap.BindFunction(ContentKeyFunctions.WideAttack,
|
||||||
new PointerInputCmdHandler(HandleAttack));
|
new PointerInputCmdHandler(HandleWideAttack));
|
||||||
inputSys.BindMap.BindFunction(ContentKeyFunctions.ActivateItemInWorld,
|
inputSys.BindMap.BindFunction(ContentKeyFunctions.ActivateItemInWorld,
|
||||||
new PointerInputCmdHandler(HandleActivateItemInWorld));
|
new PointerInputCmdHandler(HandleActivateItemInWorld));
|
||||||
}
|
}
|
||||||
@@ -477,7 +477,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
activateComp.Activate(new ActivateEventArgs {User = user});
|
activateComp.Activate(new ActivateEventArgs {User = user});
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HandleAttack(ICommonSession session, GridCoordinates coords, EntityUid uid)
|
private bool HandleWideAttack(ICommonSession session, GridCoordinates coords, EntityUid uid)
|
||||||
{
|
{
|
||||||
// client sanitization
|
// client sanitization
|
||||||
if (!_mapManager.GridExists(coords.GridID))
|
if (!_mapManager.GridExists(coords.GridID))
|
||||||
|
|||||||
134
Content.Server/GameObjects/EntitySystems/GravitySystem.cs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects.Components.Gravity;
|
||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
|
using Robust.Shared.Interfaces.Random;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
public class GravitySystem: EntitySystem
|
||||||
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly IMapManager _mapManager;
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager;
|
||||||
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||||
|
[Dependency] private readonly IRobustRandom _random;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
private const float GravityKick = 100.0f;
|
||||||
|
|
||||||
|
private const uint ShakeTimes = 10;
|
||||||
|
|
||||||
|
private Dictionary<GridId, uint> _gridsToShake;
|
||||||
|
|
||||||
|
private float internalTimer = 0.0f;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
EntityQuery = new TypeEntityQuery<GravityGeneratorComponent>();
|
||||||
|
_gridsToShake = new Dictionary<GridId, uint>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
internalTimer += frameTime;
|
||||||
|
var gridsWithGravity = new List<GridId>();
|
||||||
|
foreach (var entity in RelevantEntities)
|
||||||
|
{
|
||||||
|
var generator = entity.GetComponent<GravityGeneratorComponent>();
|
||||||
|
if (generator.NeedsUpdate)
|
||||||
|
{
|
||||||
|
generator.UpdateState();
|
||||||
|
}
|
||||||
|
if (generator.Status == GravityGeneratorStatus.On)
|
||||||
|
{
|
||||||
|
gridsWithGravity.Add(entity.Transform.GridID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var grid in _mapManager.GetAllGrids())
|
||||||
|
{
|
||||||
|
if (grid.HasGravity && !gridsWithGravity.Contains(grid.Index))
|
||||||
|
{
|
||||||
|
grid.HasGravity = false;
|
||||||
|
ScheduleGridToShake(grid.Index, ShakeTimes);
|
||||||
|
} else if (!grid.HasGravity && gridsWithGravity.Contains(grid.Index))
|
||||||
|
{
|
||||||
|
grid.HasGravity = true;
|
||||||
|
ScheduleGridToShake(grid.Index, ShakeTimes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (internalTimer > 0.2f)
|
||||||
|
{
|
||||||
|
ShakeGrids();
|
||||||
|
internalTimer = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ScheduleGridToShake(GridId gridId, uint shakeTimes)
|
||||||
|
{
|
||||||
|
if (!_gridsToShake.Keys.Contains(gridId))
|
||||||
|
{
|
||||||
|
_gridsToShake.Add(gridId, shakeTimes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_gridsToShake[gridId] = shakeTimes;
|
||||||
|
}
|
||||||
|
// Play the gravity sound
|
||||||
|
foreach (var player in _playerManager.GetAllPlayers())
|
||||||
|
{
|
||||||
|
if (player.AttachedEntity == null
|
||||||
|
|| player.AttachedEntity.Transform.GridID != gridId) continue;
|
||||||
|
_entitySystemManager.GetEntitySystem<AudioSystem>().Play("/Audio/effects/alert.ogg", player.AttachedEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShakeGrids()
|
||||||
|
{
|
||||||
|
// I have to copy this because C# doesn't allow changing collections while they're
|
||||||
|
// getting enumerated.
|
||||||
|
var gridsToShake = new Dictionary<GridId, uint>(_gridsToShake);
|
||||||
|
foreach (var gridId in _gridsToShake.Keys)
|
||||||
|
{
|
||||||
|
if (_gridsToShake[gridId] == 0)
|
||||||
|
{
|
||||||
|
gridsToShake.Remove(gridId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ShakeGrid(gridId);
|
||||||
|
gridsToShake[gridId] -= 1;
|
||||||
|
}
|
||||||
|
_gridsToShake = gridsToShake;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShakeGrid(GridId gridId)
|
||||||
|
{
|
||||||
|
foreach (var player in _playerManager.GetAllPlayers())
|
||||||
|
{
|
||||||
|
if (player.AttachedEntity == null
|
||||||
|
|| player.AttachedEntity.Transform.GridID != gridId
|
||||||
|
|| !player.AttachedEntity.TryGetComponent(out CameraRecoilComponent recoil))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
recoil.Kick(new Vector2(_random.NextFloat(), _random.NextFloat()) * GravityKick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects;
|
||||||
using Content.Server.GameObjects.Components;
|
using Content.Server.GameObjects.Components;
|
||||||
using Content.Server.GameObjects.Components.Stack;
|
using Content.Server.GameObjects.Components.Stack;
|
||||||
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Interfaces.GameObjects;
|
using Content.Server.Interfaces.GameObjects;
|
||||||
using Content.Server.Throw;
|
using Content.Server.Throw;
|
||||||
|
using Content.Shared.GameObjects.Components.Inventory;
|
||||||
using Content.Shared.Input;
|
using Content.Shared.Input;
|
||||||
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
@@ -19,6 +24,7 @@ using Robust.Shared.Interfaces.Map;
|
|||||||
using Robust.Shared.Interfaces.Physics;
|
using Robust.Shared.Interfaces.Physics;
|
||||||
using Robust.Shared.Interfaces.Timing;
|
using Robust.Shared.Interfaces.Timing;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Log;
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
@@ -33,6 +39,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly IMapManager _mapManager;
|
[Dependency] private readonly IMapManager _mapManager;
|
||||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||||
|
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
private const float ThrowForce = 1.5f; // Throwing force of mobs in Newtons
|
private const float ThrowForce = 1.5f; // Throwing force of mobs in Newtons
|
||||||
@@ -50,6 +57,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
input.BindMap.BindFunction(ContentKeyFunctions.Drop, new PointerInputCmdHandler(HandleDrop));
|
input.BindMap.BindFunction(ContentKeyFunctions.Drop, new PointerInputCmdHandler(HandleDrop));
|
||||||
input.BindMap.BindFunction(ContentKeyFunctions.ActivateItemInHand, InputCmdHandler.FromDelegate(HandleActivateItem));
|
input.BindMap.BindFunction(ContentKeyFunctions.ActivateItemInHand, InputCmdHandler.FromDelegate(HandleActivateItem));
|
||||||
input.BindMap.BindFunction(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem));
|
input.BindMap.BindFunction(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem));
|
||||||
|
input.BindMap.BindFunction(ContentKeyFunctions.SmartEquipBackpack, InputCmdHandler.FromDelegate(HandleSmartEquipBackpack));
|
||||||
|
input.BindMap.BindFunction(ContentKeyFunctions.SmartEquipBelt, InputCmdHandler.FromDelegate(HandleSmartEquipBelt));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -126,7 +135,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
|
|
||||||
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
|
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
|
||||||
|
|
||||||
if(interactionSystem.InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, 0f, ignoredEnt: ent))
|
if(interactionSystem.InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, ignoredEnt: ent))
|
||||||
if (coords.InRange(_mapManager, ent.Transform.GridPosition, InteractionSystem.InteractionRange))
|
if (coords.InRange(_mapManager, ent.Transform.GridPosition, InteractionSystem.InteractionRange))
|
||||||
{
|
{
|
||||||
handsComp.Drop(handsComp.ActiveIndex, coords);
|
handsComp.Drop(handsComp.ActiveIndex, coords);
|
||||||
@@ -190,5 +199,53 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleSmartEquipBackpack(ICommonSession session)
|
||||||
|
{
|
||||||
|
HandleSmartEquip(session, EquipmentSlotDefines.Slots.BACKPACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleSmartEquipBelt(ICommonSession session)
|
||||||
|
{
|
||||||
|
HandleSmartEquip(session, EquipmentSlotDefines.Slots.BELT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleSmartEquip(ICommonSession session, EquipmentSlotDefines.Slots equipementSlot)
|
||||||
|
{
|
||||||
|
var plyEnt = ((IPlayerSession) session).AttachedEntity;
|
||||||
|
|
||||||
|
if (plyEnt == null || !plyEnt.IsValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!plyEnt.TryGetComponent(out HandsComponent handsComp) || !plyEnt.TryGetComponent(out InventoryComponent inventoryComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!inventoryComp.TryGetSlotItem(equipementSlot, out ItemComponent equipmentItem)
|
||||||
|
|| !equipmentItem.Owner.TryGetComponent<ServerStorageComponent>(out var storageComponent))
|
||||||
|
{
|
||||||
|
_notifyManager.PopupMessage(plyEnt, plyEnt, Loc.GetString("You have no {0} to take something out of!", EquipmentSlotDefines.SlotNames[equipementSlot].ToLower()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var heldItem = handsComp.GetHand(handsComp.ActiveIndex)?.Owner;
|
||||||
|
|
||||||
|
if (heldItem != null)
|
||||||
|
{
|
||||||
|
storageComponent.PlayerInsertEntity(plyEnt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (storageComponent.StoredEntities.Count == 0)
|
||||||
|
{
|
||||||
|
_notifyManager.PopupMessage(plyEnt, plyEnt, Loc.GetString("There's nothing in your {0} to take out!", EquipmentSlotDefines.SlotNames[equipementSlot].ToLower()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lastStoredEntity = Enumerable.Last(storageComponent.StoredEntities);
|
||||||
|
if (storageComponent.Remove(lastStoredEntity))
|
||||||
|
handsComp.PutInHandOrDrop(lastStoredEntity.GetComponent<ItemComponent>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Content.Server.GameObjects.Components;
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using Content.Server.GameObjects.Components;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.GameObjects.Components.Movement;
|
using Content.Server.GameObjects.Components.Movement;
|
||||||
using Content.Server.GameObjects.Components.Sound;
|
using Content.Server.GameObjects.Components.Sound;
|
||||||
@@ -15,6 +17,7 @@ using Robust.Server.Interfaces.Player;
|
|||||||
using Robust.Server.Interfaces.Timing;
|
using Robust.Server.Interfaces.Timing;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects.Components.Transform;
|
using Robust.Shared.GameObjects.Components.Transform;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Input;
|
using Robust.Shared.Input;
|
||||||
@@ -28,6 +31,7 @@ using Robust.Shared.Log;
|
|||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Players;
|
using Robust.Shared.Players;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
@@ -44,6 +48,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
[Dependency] private readonly IMapManager _mapManager;
|
[Dependency] private readonly IMapManager _mapManager;
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom;
|
[Dependency] private readonly IRobustRandom _robustRandom;
|
||||||
[Dependency] private readonly IConfigurationManager _configurationManager;
|
[Dependency] private readonly IConfigurationManager _configurationManager;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
private AudioSystem _audioSystem;
|
private AudioSystem _audioSystem;
|
||||||
@@ -130,13 +135,43 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
}
|
}
|
||||||
var mover = entity.GetComponent<IMoverComponent>();
|
var mover = entity.GetComponent<IMoverComponent>();
|
||||||
var physics = entity.GetComponent<PhysicsComponent>();
|
var physics = entity.GetComponent<PhysicsComponent>();
|
||||||
|
if (entity.TryGetComponent<CollidableComponent>(out var collider))
|
||||||
UpdateKinematics(entity.Transform, mover, physics);
|
{
|
||||||
|
UpdateKinematics(entity.Transform, mover, physics, collider);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateKinematics(entity.Transform, mover, physics);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, PhysicsComponent physics)
|
private void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, PhysicsComponent physics, CollidableComponent collider = null)
|
||||||
{
|
{
|
||||||
|
bool weightless = false;
|
||||||
|
|
||||||
|
var tile = _mapManager.GetGrid(transform.GridID).GetTileRef(transform.GridPosition).Tile;
|
||||||
|
|
||||||
|
if ((!_mapManager.GetGrid(transform.GridID).HasGravity || tile.IsEmpty) && collider != null)
|
||||||
|
{
|
||||||
|
weightless = true;
|
||||||
|
// No gravity: is our entity touching anything?
|
||||||
|
var touching = false;
|
||||||
|
foreach (var entity in _entityManager.GetEntitiesInRange(transform.Owner, mover.GrabRange, true))
|
||||||
|
{
|
||||||
|
if (entity.TryGetComponent<CollidableComponent>(out var otherCollider))
|
||||||
|
{
|
||||||
|
if (otherCollider.Owner == transform.Owner) continue; // Don't try to push off of yourself!
|
||||||
|
touching |= ((collider.CollisionMask & otherCollider.CollisionLayer) != 0x0
|
||||||
|
|| (otherCollider.CollisionMask & collider.CollisionLayer) != 0x0) // Ensure collision
|
||||||
|
&& !entity.HasComponent<ItemComponent>(); // This can't be an item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!touching)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (mover.VelocityDir.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner))
|
if (mover.VelocityDir.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner))
|
||||||
{
|
{
|
||||||
if (physics.LinearVelocity != Vector2.Zero)
|
if (physics.LinearVelocity != Vector2.Zero)
|
||||||
@@ -145,6 +180,13 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (weightless)
|
||||||
|
{
|
||||||
|
physics.LinearVelocity = mover.VelocityDir * mover.CurrentPushSpeed;
|
||||||
|
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
physics.LinearVelocity = mover.VelocityDir * (mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed);
|
physics.LinearVelocity = mover.VelocityDir * (mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed);
|
||||||
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
namespace Content.Server.GameTicking
|
using System.Collections.Generic;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
|
||||||
|
namespace Content.Server.GameTicking
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A round-start setup preset, such as which antagonists to spawn.
|
/// A round-start setup preset, such as which antagonists to spawn.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class GamePreset
|
public abstract class GamePreset
|
||||||
{
|
{
|
||||||
public abstract void Start();
|
public abstract bool Start(IReadOnlyList<IPlayerSession> players);
|
||||||
public virtual string ModeTitle => "Sandbox";
|
public virtual string ModeTitle => "Sandbox";
|
||||||
public virtual string Description => "Secret!";
|
public virtual string Description => "Secret!";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using Content.Server.GameTicking.GameRules;
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.GameTicking.GameRules;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Server.GameTicking.GamePresets
|
namespace Content.Server.GameTicking.GamePresets
|
||||||
@@ -10,9 +12,10 @@ namespace Content.Server.GameTicking.GamePresets
|
|||||||
[Dependency] private readonly IGameTicker _gameTicker;
|
[Dependency] private readonly IGameTicker _gameTicker;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
public override void Start()
|
public override bool Start(IReadOnlyList<IPlayerSession> readyPlayers)
|
||||||
{
|
{
|
||||||
_gameTicker.AddGameRule<RuleDeathMatch>();
|
_gameTicker.AddGameRule<RuleDeathMatch>();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ModeTitle => "Deathmatch";
|
public override string ModeTitle => "Deathmatch";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Content.Server.Sandbox;
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.Sandbox;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Server.GameTicking.GamePresets
|
namespace Content.Server.GameTicking.GamePresets
|
||||||
@@ -9,9 +11,10 @@ namespace Content.Server.GameTicking.GamePresets
|
|||||||
[Dependency] private readonly ISandboxManager _sandboxManager;
|
[Dependency] private readonly ISandboxManager _sandboxManager;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
public override void Start()
|
public override bool Start(IReadOnlyList<IPlayerSession> readyPlayers)
|
||||||
{
|
{
|
||||||
_sandboxManager.IsSandboxEnabled = true;
|
_sandboxManager.IsSandboxEnabled = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ModeTitle => "Sandbox";
|
public override string ModeTitle => "Sandbox";
|
||||||
|
|||||||
63
Content.Server/GameTicking/GamePresets/PresetSuspicion.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.GameTicking.GameRules;
|
||||||
|
using Content.Server.Interfaces.Chat;
|
||||||
|
using Content.Server.Interfaces.GameTicking;
|
||||||
|
using Content.Server.Mobs.Roles;
|
||||||
|
using Content.Server.Players;
|
||||||
|
using Content.Server.Sandbox;
|
||||||
|
using NFluidsynth;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
using Robust.Shared.Interfaces.Random;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
using Logger = Robust.Shared.Log.Logger;
|
||||||
|
|
||||||
|
namespace Content.Server.GameTicking.GamePresets
|
||||||
|
{
|
||||||
|
public class PresetSuspicion : GamePreset
|
||||||
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly ISandboxManager _sandboxManager;
|
||||||
|
[Dependency] private readonly IChatManager _chatManager;
|
||||||
|
[Dependency] private readonly IGameTicker _gameTicker;
|
||||||
|
[Dependency] private readonly IRobustRandom _random;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
public int MinPlayers { get; set; } = 5;
|
||||||
|
public int MinTraitors { get; set; } = 2;
|
||||||
|
public int PlayersPerTraitor { get; set; } = 5;
|
||||||
|
|
||||||
|
public override bool Start(IReadOnlyList<IPlayerSession> readyPlayers)
|
||||||
|
{
|
||||||
|
if (readyPlayers.Count < MinPlayers)
|
||||||
|
{
|
||||||
|
_chatManager.DispatchServerAnnouncement($"Not enough players readied up for the game! There were {readyPlayers.Count} players readied up out of {MinPlayers} needed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = new List<IPlayerSession>(readyPlayers);
|
||||||
|
var numTraitors = Math.Max(readyPlayers.Count() % PlayersPerTraitor, MinTraitors);
|
||||||
|
|
||||||
|
for (var i = 0; i < numTraitors; i++)
|
||||||
|
{
|
||||||
|
var traitor = _random.PickAndTake(list);
|
||||||
|
var mind = traitor.Data.ContentData().Mind;
|
||||||
|
mind.AddRole(new SuspicionTraitorRole(mind));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var player in list)
|
||||||
|
{
|
||||||
|
var mind = player.Data.ContentData().Mind;
|
||||||
|
mind.AddRole(new SuspicionInnocentRole(mind));
|
||||||
|
}
|
||||||
|
|
||||||
|
_gameTicker.AddGameRule<RuleSuspicion>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModeTitle => "Suspicion";
|
||||||
|
public override string Description => "Suspicion on the Space Station. There are traitors on board... Can you kill them before they kill you?";
|
||||||
|
}
|
||||||
|
}
|
||||||
122
Content.Server/GameTicking/GameRules/RuleSuspicion.cs
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Content.Server.GameObjects;
|
||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.GameObjects.Components.Observer;
|
||||||
|
using Content.Server.Interfaces.Chat;
|
||||||
|
using Content.Server.Interfaces.GameTicking;
|
||||||
|
using Content.Server.Mobs.Roles;
|
||||||
|
using Content.Server.Players;
|
||||||
|
using NFluidsynth;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Logger = Robust.Shared.Log.Logger;
|
||||||
|
using Timer = Robust.Shared.Timers.Timer;
|
||||||
|
|
||||||
|
namespace Content.Server.GameTicking.GameRules
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple GameRule that will do a free-for-all death match.
|
||||||
|
/// Kill everybody else to win.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RuleSuspicion : GameRule, IEntityEventSubscriber
|
||||||
|
{
|
||||||
|
private static readonly TimeSpan DeadCheckDelay = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager;
|
||||||
|
[Dependency] private readonly IChatManager _chatManager;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager;
|
||||||
|
[Dependency] private readonly IGameTicker _gameTicker;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
private readonly CancellationTokenSource _checkTimerCancel = new CancellationTokenSource();
|
||||||
|
|
||||||
|
public override void Added()
|
||||||
|
{
|
||||||
|
_chatManager.DispatchServerAnnouncement("There are traitors on the station! Find them, and kill them!");
|
||||||
|
|
||||||
|
_entityManager.EventBus.SubscribeEvent<MobDamageStateChangedMessage>(EventSource.Local, this, _onMobDamageStateChanged);
|
||||||
|
|
||||||
|
Timer.SpawnRepeating(DeadCheckDelay, _checkWinConditions, _checkTimerCancel.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _onMobDamageStateChanged(MobDamageStateChangedMessage message)
|
||||||
|
{
|
||||||
|
var owner = message.Species.Owner;
|
||||||
|
|
||||||
|
if (!(message.Species.CurrentDamageState is DeadState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!owner.TryGetComponent<MindComponent>(out var mind))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!mind.HasMind)
|
||||||
|
return;
|
||||||
|
|
||||||
|
message.Species.Owner.Description +=
|
||||||
|
mind.Mind.HasRole<SuspicionTraitorRole>() ? "\nThey were a traitor!" : "\nThey were an innocent!";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Removed()
|
||||||
|
{
|
||||||
|
base.Removed();
|
||||||
|
|
||||||
|
_checkTimerCancel.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _checkWinConditions()
|
||||||
|
{
|
||||||
|
var traitorsAlive = 0;
|
||||||
|
var innocentsAlive = 0;
|
||||||
|
|
||||||
|
foreach (var playerSession in _playerManager.GetAllPlayers())
|
||||||
|
{
|
||||||
|
if (playerSession.AttachedEntity == null
|
||||||
|
|| !playerSession.AttachedEntity.TryGetComponent(out SpeciesComponent species))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!species.CurrentDamageState.IsConscious)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerSession.ContentData().Mind.HasRole<SuspicionTraitorRole>())
|
||||||
|
traitorsAlive++;
|
||||||
|
else
|
||||||
|
innocentsAlive++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((innocentsAlive + traitorsAlive) == 0)
|
||||||
|
{
|
||||||
|
_chatManager.DispatchServerAnnouncement("Everybody is dead, it's a stalemate!");
|
||||||
|
EndRound();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (traitorsAlive == 0)
|
||||||
|
{
|
||||||
|
_chatManager.DispatchServerAnnouncement("The traitors are dead! The innocents win.");
|
||||||
|
EndRound();
|
||||||
|
}
|
||||||
|
else if (innocentsAlive == 0)
|
||||||
|
{
|
||||||
|
_chatManager.DispatchServerAnnouncement("The innocents are dead! The traitors win.");
|
||||||
|
EndRound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndRound()
|
||||||
|
{
|
||||||
|
_gameTicker.EndRound();
|
||||||
|
_chatManager.DispatchServerAnnouncement($"Restarting in 10 seconds.");
|
||||||
|
_checkTimerCancel.Cancel();
|
||||||
|
Timer.Spawn(TimeSpan.FromSeconds(10), () => _gameTicker.RestartRound());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -104,7 +104,8 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
_configurationManager.RegisterCVar("game.lobbyenabled", false, CVar.ARCHIVE);
|
_configurationManager.RegisterCVar("game.lobbyenabled", false, CVar.ARCHIVE);
|
||||||
_configurationManager.RegisterCVar("game.lobbyduration", 20, CVar.ARCHIVE);
|
_configurationManager.RegisterCVar("game.lobbyduration", 20, CVar.ARCHIVE);
|
||||||
_configurationManager.RegisterCVar("game.defaultpreset", "Sandbox", CVar.ARCHIVE);
|
_configurationManager.RegisterCVar("game.defaultpreset", "Suspicion", CVar.ARCHIVE);
|
||||||
|
_configurationManager.RegisterCVar("game.fallbackpreset", "Sandbox", CVar.ARCHIVE);
|
||||||
|
|
||||||
_playerManager.PlayerStatusChanged += _handlePlayerStatusChanged;
|
_playerManager.PlayerStatusChanged += _handlePlayerStatusChanged;
|
||||||
|
|
||||||
@@ -181,11 +182,6 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
SendServerMessage("The round is starting now...");
|
SendServerMessage("The round is starting now...");
|
||||||
|
|
||||||
RunLevel = GameRunLevel.InRound;
|
|
||||||
|
|
||||||
var preset = MakeGamePreset();
|
|
||||||
preset.Start();
|
|
||||||
|
|
||||||
List<IPlayerSession> readyPlayers;
|
List<IPlayerSession> readyPlayers;
|
||||||
if (LobbyEnabled)
|
if (LobbyEnabled)
|
||||||
{
|
{
|
||||||
@@ -196,6 +192,8 @@ namespace Content.Server.GameTicking
|
|||||||
readyPlayers = _playersInLobby.Keys.ToList();
|
readyPlayers = _playersInLobby.Keys.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunLevel = GameRunLevel.InRound;
|
||||||
|
|
||||||
// Get the profiles for each player for easier lookup.
|
// Get the profiles for each player for easier lookup.
|
||||||
var profiles = readyPlayers.ToDictionary(p => p, GetPlayerProfile);
|
var profiles = readyPlayers.ToDictionary(p => p, GetPlayerProfile);
|
||||||
|
|
||||||
@@ -222,6 +220,18 @@ namespace Content.Server.GameTicking
|
|||||||
SpawnPlayer(player, job, false);
|
SpawnPlayer(player, job, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Time to start the preset.
|
||||||
|
var preset = MakeGamePreset();
|
||||||
|
|
||||||
|
if (!preset.Start(assignedJobs.Keys.ToList()))
|
||||||
|
{
|
||||||
|
SetStartPreset(_configurationManager.GetCVar<string>("game.fallbackpreset"));
|
||||||
|
var newPreset = MakeGamePreset();
|
||||||
|
_chatManager.DispatchServerAnnouncement($"Failed to start {preset.ModeTitle} mode! Defaulting to {newPreset.ModeTitle}...");
|
||||||
|
if(!newPreset.Start(readyPlayers))
|
||||||
|
throw new ApplicationException("Fallback preset failed to start!");
|
||||||
|
}
|
||||||
|
|
||||||
_roundStartTimeSpan = IoCManager.Resolve<IGameTiming>().RealTime;
|
_roundStartTimeSpan = IoCManager.Resolve<IGameTiming>().RealTime;
|
||||||
_sendStatusToAll();
|
_sendStatusToAll();
|
||||||
}
|
}
|
||||||
@@ -255,15 +265,16 @@ namespace Content.Server.GameTicking
|
|||||||
var listOfPlayerInfo = new List<RoundEndPlayerInfo>();
|
var listOfPlayerInfo = new List<RoundEndPlayerInfo>();
|
||||||
foreach(var ply in _playerManager.GetAllPlayers().OrderBy(p => p.Name))
|
foreach(var ply in _playerManager.GetAllPlayers().OrderBy(p => p.Name))
|
||||||
{
|
{
|
||||||
if(ply.AttachedEntity.TryGetComponent<MindComponent>(out var mindComponent)
|
var mind = ply.ContentData().Mind;
|
||||||
&& mindComponent.HasMind)
|
if(mind != null)
|
||||||
{
|
{
|
||||||
|
var antag = mind.AllRoles.Any(role => role.Antag);
|
||||||
var playerEndRoundInfo = new RoundEndPlayerInfo()
|
var playerEndRoundInfo = new RoundEndPlayerInfo()
|
||||||
{
|
{
|
||||||
PlayerOOCName = ply.Name,
|
PlayerOOCName = ply.Name,
|
||||||
PlayerICName = mindComponent.Mind.CurrentEntity.Name,
|
PlayerICName = mind.CurrentEntity.Name,
|
||||||
Role = mindComponent.Mind.AllRoles.FirstOrDefault()?.Name ?? Loc.GetString("Unkown"),
|
Role = antag ? mind.AllRoles.First(role => role.Antag).Name : mind.AllRoles.FirstOrDefault()?.Name ?? Loc.GetString("Unkown"),
|
||||||
Antag = false
|
Antag = antag
|
||||||
};
|
};
|
||||||
listOfPlayerInfo.Add(playerEndRoundInfo);
|
listOfPlayerInfo.Add(playerEndRoundInfo);
|
||||||
}
|
}
|
||||||
@@ -339,6 +350,7 @@ namespace Content.Server.GameTicking
|
|||||||
{
|
{
|
||||||
"Sandbox" => typeof(PresetSandbox),
|
"Sandbox" => typeof(PresetSandbox),
|
||||||
"DeathMatch" => typeof(PresetDeathMatch),
|
"DeathMatch" => typeof(PresetDeathMatch),
|
||||||
|
"Suspicion" => typeof(PresetSuspicion),
|
||||||
_ => throw new NotSupportedException()
|
_ => throw new NotSupportedException()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,17 @@ namespace Content.Server.Interfaces.GameObjects.Components.Movement
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
float CurrentSprintSpeed { get; }
|
float CurrentSprintSpeed { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The movement speed (m/s) of the entity when it pushes off of a solid object in zero gravity.
|
||||||
|
/// </summary>
|
||||||
|
float CurrentPushSpeed { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How far an entity can reach (in meters) to grab hold of a solid object in zero gravity.
|
||||||
|
/// </summary>
|
||||||
|
float GrabRange { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the entity Sprinting (running)?
|
/// Is the entity Sprinting (running)?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Server.Mobs
|
namespace Content.Server.Mobs
|
||||||
@@ -130,6 +133,13 @@ namespace Content.Server.Mobs
|
|||||||
_roles.Remove(role);
|
_roles.Remove(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasRole<T>() where T : Role
|
||||||
|
{
|
||||||
|
var t = typeof(T);
|
||||||
|
|
||||||
|
return _roles.Any(role => role.GetType() == t);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transfer this mind's control over to a new entity.
|
/// Transfer this mind's control over to a new entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
// Hey look,
|
// Hey look,
|
||||||
// Antag Datums.
|
// Antag Datums.
|
||||||
|
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Mobs
|
namespace Content.Server.Mobs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -20,6 +23,11 @@ namespace Content.Server.Mobs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract string Name { get; }
|
public abstract string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this role should be considered antagonistic or not.
|
||||||
|
/// </summary>
|
||||||
|
public abstract bool Antag { get; }
|
||||||
|
|
||||||
protected Role(Mind mind)
|
protected Role(Mind mind)
|
||||||
{
|
{
|
||||||
Mind = mind;
|
Mind = mind;
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ namespace Content.Server.Mobs.Roles
|
|||||||
public JobPrototype Prototype { get; }
|
public JobPrototype Prototype { get; }
|
||||||
|
|
||||||
public override string Name { get; }
|
public override string Name { get; }
|
||||||
|
public override bool Antag => false;
|
||||||
|
|
||||||
public String StartingGear => Prototype.StartingGear;
|
public string StartingGear => Prototype.StartingGear;
|
||||||
|
|
||||||
public Job(Mind mind, JobPrototype jobPrototype) : base(mind)
|
public Job(Mind mind, JobPrototype jobPrototype) : base(mind)
|
||||||
{
|
{
|
||||||
@@ -25,9 +26,7 @@ namespace Content.Server.Mobs.Roles
|
|||||||
base.Greet();
|
base.Greet();
|
||||||
|
|
||||||
var chat = IoCManager.Resolve<IChatManager>();
|
var chat = IoCManager.Resolve<IChatManager>();
|
||||||
chat.DispatchServerMessage(
|
chat.DispatchServerMessage(Mind.Session, $"You're a new {Name}. Do your best!");
|
||||||
Mind.Session,
|
|
||||||
String.Format("You're a new {0}. Do your best!", Name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
25
Content.Server/Mobs/Roles/SuspicionInnocentRole.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Content.Server.GameObjects;
|
||||||
|
using Content.Server.Interfaces.Chat;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Mobs.Roles
|
||||||
|
{
|
||||||
|
public class SuspicionInnocentRole : Role
|
||||||
|
{
|
||||||
|
public SuspicionInnocentRole(Mind mind) : base(mind)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name => "Innocent";
|
||||||
|
public override bool Antag => false;
|
||||||
|
|
||||||
|
public override void Greet()
|
||||||
|
{
|
||||||
|
base.Greet();
|
||||||
|
|
||||||
|
var chat = IoCManager.Resolve<IChatManager>();
|
||||||
|
chat.DispatchServerMessage(Mind.Session, "You're an innocent!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Content.Server/Mobs/Roles/SuspicionTraitorRole.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Content.Server.GameObjects;
|
||||||
|
using Content.Server.Interfaces.Chat;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Mobs.Roles
|
||||||
|
{
|
||||||
|
public sealed class SuspicionTraitorRole : Role
|
||||||
|
{
|
||||||
|
public SuspicionTraitorRole(Mind mind) : base(mind)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name => "Traitor";
|
||||||
|
public override bool Antag => true;
|
||||||
|
|
||||||
|
public override void Greet()
|
||||||
|
{
|
||||||
|
base.Greet();
|
||||||
|
|
||||||
|
var chat = IoCManager.Resolve<IChatManager>();
|
||||||
|
chat.DispatchServerMessage(Mind.Session, "You're a traitor!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
using Content.Server.Interfaces.Chat;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
|
|
||||||
namespace Content.Server.Mobs.Roles
|
|
||||||
{
|
|
||||||
public sealed class Traitor : Role
|
|
||||||
{
|
|
||||||
public Traitor(Mind mind) : base(mind)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Name => "Traitor";
|
|
||||||
|
|
||||||
public override void Greet()
|
|
||||||
{
|
|
||||||
base.Greet();
|
|
||||||
|
|
||||||
var chat = IoCManager.Resolve<IChatManager>();
|
|
||||||
chat.DispatchServerMessage(
|
|
||||||
Mind.Session,
|
|
||||||
"You're a traitor. Go fuck something up. Or something. I don't care to be honest.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,7 @@ using Content.Server.Preferences;
|
|||||||
using Content.Server.Sandbox;
|
using Content.Server.Sandbox;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
|
using Content.Shared.Kitchen;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.Chemistry;
|
using Content.Shared.Interfaces.Chemistry;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -28,6 +29,7 @@ namespace Content.Server
|
|||||||
IoCManager.Register<ICargoOrderDataManager, CargoOrderDataManager>();
|
IoCManager.Register<ICargoOrderDataManager, CargoOrderDataManager>();
|
||||||
IoCManager.Register<IModuleManager, ServerModuleManager>();
|
IoCManager.Register<IModuleManager, ServerModuleManager>();
|
||||||
IoCManager.Register<IServerPreferencesManager, ServerPreferencesManager>();
|
IoCManager.Register<IServerPreferencesManager, ServerPreferencesManager>();
|
||||||
|
IoCManager.Register<RecipeManager, RecipeManager>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ namespace Content.Server.Throw
|
|||||||
var spd = a / (1f / timing.TickRate); // acceleration is applied in 1 tick instead of 1 second, scale appropriately
|
var spd = a / (1f / timing.TickRate); // acceleration is applied in 1 tick instead of 1 second, scale appropriately
|
||||||
|
|
||||||
physComp.LinearVelocity = angle.ToVec() * spd;
|
physComp.LinearVelocity = angle.ToVec() * spd;
|
||||||
|
|
||||||
|
if (throwSourceEnt != null)
|
||||||
|
{
|
||||||
|
var p = throwSourceEnt.GetComponent<PhysicsComponent>();
|
||||||
|
var playerAccel = 5 * throwForce / (float) Math.Max(0.001, p.Mass);
|
||||||
|
p.LinearVelocity = Angle.FromDegrees(angle.Degrees + 180).ToVec()
|
||||||
|
* playerAccel / (1f / timing.TickRate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
Content.Shared/Audio/AudioHelpers.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Shared.GameObjects.Components.Sound;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Random;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Shared.Audio
|
||||||
|
{
|
||||||
|
public static class AudioHelpers{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random pitch.
|
||||||
|
/// </summary>
|
||||||
|
public static AudioParams WithVariation(float amplitude)
|
||||||
|
{
|
||||||
|
var scale = (float)(IoCManager.Resolve<IRobustRandom>().NextGaussian(1, amplitude));
|
||||||
|
return AudioParams.Default.WithPitchScale(scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,36 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Robust.Shared.ContentPack;
|
using Robust.Shared.ContentPack;
|
||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared
|
namespace Content.Shared
|
||||||
{
|
{
|
||||||
public class EntryPoint : GameShared
|
public class EntryPoint : GameShared
|
||||||
{
|
{
|
||||||
|
// If you want to change your codebase's language, do it here.
|
||||||
|
private const string Culture = "en-US";
|
||||||
|
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||||
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager;
|
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager;
|
||||||
|
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
public override void PreInit()
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
|
// Default to en-US.
|
||||||
|
_localizationManager.LoadCulture(new CultureInfo(Culture));
|
||||||
|
}
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PostInit()
|
public override void PostInit()
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components.Gravity
|
||||||
|
{
|
||||||
|
public class SharedGravityGeneratorComponent: Component
|
||||||
|
{
|
||||||
|
public override string Name => "GravityGenerator";
|
||||||
|
|
||||||
|
public override uint? NetID => ContentNetIDs.GRAVITY_GENERATOR;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sent to the server to set whether the generator should be on or off
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class SwitchGeneratorMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public bool On;
|
||||||
|
|
||||||
|
public SwitchGeneratorMessage(bool on)
|
||||||
|
{
|
||||||
|
On = on;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sent to the server when requesting the status of the generator
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class GeneratorStatusRequestMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public GeneratorStatusRequestMessage()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class GeneratorState : BoundUserInterfaceState
|
||||||
|
{
|
||||||
|
public bool On;
|
||||||
|
|
||||||
|
public GeneratorState(bool on)
|
||||||
|
{
|
||||||
|
On = on;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum GravityGeneratorUiKey
|
||||||
|
{
|
||||||
|
Key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,5 +42,7 @@
|
|||||||
public const uint PAPER = 1037;
|
public const uint PAPER = 1037;
|
||||||
public const uint REAGENT_INJECTOR = 1038;
|
public const uint REAGENT_INJECTOR = 1038;
|
||||||
public const uint GHOST = 1039;
|
public const uint GHOST = 1039;
|
||||||
|
public const uint MICROWAVE = 1040;
|
||||||
|
public const uint GRAVITY_GENERATOR = 1041;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,13 +51,17 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, true);
|
var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, true);
|
||||||
if(!rayResults.DidHitObject || (insideBlockerValid && rayResults.DidHitObject && (rayResults.HitPos - otherCoords).Length < 1f))
|
if(!rayResults.DidHitObject || (insideBlockerValid && rayResults.DidHitObject && (rayResults.HitPos - otherCoords).Length < 1f))
|
||||||
{
|
{
|
||||||
_mapManager.TryFindGridAt(coords, out var mapGrid);
|
|
||||||
var srcPos = mapGrid.MapToGrid(coords);
|
if (_mapManager.TryFindGridAt(coords, out var mapGrid) && mapGrid != null)
|
||||||
var destPos = new GridCoordinates(otherCoords, mapGrid);
|
|
||||||
if (srcPos.InRange(_mapManager, destPos, range))
|
|
||||||
{
|
{
|
||||||
return true;
|
var srcPos = mapGrid.MapToGrid(coords);
|
||||||
|
var destPos = new GridCoordinates(otherCoords, mapGrid);
|
||||||
|
if (srcPos.InRange(_mapManager, destPos, range))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ namespace Content.Shared.Input
|
|||||||
[KeyFunctions]
|
[KeyFunctions]
|
||||||
public static class ContentKeyFunctions
|
public static class ContentKeyFunctions
|
||||||
{
|
{
|
||||||
public static readonly BoundKeyFunction UseOrAttack = "UseOrAttack";
|
public static readonly BoundKeyFunction WideAttack = "WideAttack";
|
||||||
public static readonly BoundKeyFunction Attack = "Attack";
|
|
||||||
public static readonly BoundKeyFunction ActivateItemInHand = "ActivateItemInHand";
|
public static readonly BoundKeyFunction ActivateItemInHand = "ActivateItemInHand";
|
||||||
public static readonly BoundKeyFunction ActivateItemInWorld = "ActivateItemInWorld"; // default action on world entity
|
public static readonly BoundKeyFunction ActivateItemInWorld = "ActivateItemInWorld"; // default action on world entity
|
||||||
public static readonly BoundKeyFunction Drop = "Drop";
|
public static readonly BoundKeyFunction Drop = "Drop";
|
||||||
@@ -16,6 +15,8 @@ namespace Content.Shared.Input
|
|||||||
public static readonly BoundKeyFunction OpenContextMenu = "OpenContextMenu";
|
public static readonly BoundKeyFunction OpenContextMenu = "OpenContextMenu";
|
||||||
public static readonly BoundKeyFunction OpenCraftingMenu = "OpenCraftingMenu";
|
public static readonly BoundKeyFunction OpenCraftingMenu = "OpenCraftingMenu";
|
||||||
public static readonly BoundKeyFunction OpenInventoryMenu = "OpenInventoryMenu";
|
public static readonly BoundKeyFunction OpenInventoryMenu = "OpenInventoryMenu";
|
||||||
|
public static readonly BoundKeyFunction SmartEquipBackpack = "SmartEquipBackpack";
|
||||||
|
public static readonly BoundKeyFunction SmartEquipBelt = "SmartEquipBelt";
|
||||||
public static readonly BoundKeyFunction OpenTutorial = "OpenTutorial";
|
public static readonly BoundKeyFunction OpenTutorial = "OpenTutorial";
|
||||||
public static readonly BoundKeyFunction SwapHands = "SwapHands";
|
public static readonly BoundKeyFunction SwapHands = "SwapHands";
|
||||||
public static readonly BoundKeyFunction ThrowItemInHand = "ThrowItemInHand";
|
public static readonly BoundKeyFunction ThrowItemInHand = "ThrowItemInHand";
|
||||||
@@ -24,5 +25,7 @@ namespace Content.Shared.Input
|
|||||||
public static readonly BoundKeyFunction OpenEntitySpawnWindow = "OpenEntitySpawnWindow";
|
public static readonly BoundKeyFunction OpenEntitySpawnWindow = "OpenEntitySpawnWindow";
|
||||||
public static readonly BoundKeyFunction OpenSandboxWindow = "OpenSandboxWindow";
|
public static readonly BoundKeyFunction OpenSandboxWindow = "OpenSandboxWindow";
|
||||||
public static readonly BoundKeyFunction OpenTileSpawnWindow = "OpenTileSpawnWindow";
|
public static readonly BoundKeyFunction OpenTileSpawnWindow = "OpenTileSpawnWindow";
|
||||||
|
public static readonly BoundKeyFunction TakeScreenshot = "TakeScreenshot";
|
||||||
|
public static readonly BoundKeyFunction TakeScreenshotNoUI = "TakeScreenshotNoUI";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
40
Content.Shared/Kitchen/RecipeManager.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Shared.Prototypes.Kitchen;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Kitchen
|
||||||
|
{
|
||||||
|
|
||||||
|
public class RecipeManager
|
||||||
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||||
|
#pragma warning restore 649
|
||||||
|
public List<FoodRecipePrototype> Recipes { get; private set; }
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
Recipes = new List<FoodRecipePrototype>();
|
||||||
|
foreach (var item in _prototypeManager.EnumeratePrototypes<FoodRecipePrototype>())
|
||||||
|
{
|
||||||
|
Recipes.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
Recipes.Sort(new RecipeComparer());
|
||||||
|
}
|
||||||
|
private class RecipeComparer : Comparer<FoodRecipePrototype>
|
||||||
|
{
|
||||||
|
public override int Compare(FoodRecipePrototype x, FoodRecipePrototype y)
|
||||||
|
{
|
||||||
|
if (x == null || y == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -x.IngredientsReagents.Count.CompareTo(y.IngredientsReagents.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
93
Content.Shared/Kitchen/SharedMicrowaveComponent.cs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Shared.Chemistry;
|
||||||
|
using Content.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||||
|
|
||||||
|
namespace Content.Shared.Kitchen
|
||||||
|
{
|
||||||
|
|
||||||
|
public class SharedMicrowaveComponent : Component
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string Name => "Microwave";
|
||||||
|
public override uint? NetID => ContentNetIDs.MICROWAVE;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class MicrowaveStartCookMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public MicrowaveStartCookMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class MicrowaveEjectMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public MicrowaveEjectMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class MicrowaveEjectSolidIndexedMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
|
||||||
|
public EntityUid EntityID;
|
||||||
|
public MicrowaveEjectSolidIndexedMessage(EntityUid entityID)
|
||||||
|
{
|
||||||
|
EntityID = entityID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class MicrowaveVaporizeReagentIndexedMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
|
||||||
|
public Solution.ReagentQuantity ReagentQuantity;
|
||||||
|
public MicrowaveVaporizeReagentIndexedMessage(Solution.ReagentQuantity reagentQuantity)
|
||||||
|
{
|
||||||
|
ReagentQuantity = reagentQuantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class MicrowaveSelectCookTimeMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public uint newCookTime;
|
||||||
|
public MicrowaveSelectCookTimeMessage(uint inputTime)
|
||||||
|
{
|
||||||
|
newCookTime = inputTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[NetSerializable, Serializable]
|
||||||
|
public class MicrowaveUpdateUserInterfaceState : BoundUserInterfaceState
|
||||||
|
{
|
||||||
|
public readonly IReadOnlyList<Solution.ReagentQuantity> ReagentsReagents;
|
||||||
|
public readonly List<EntityUid> ContainedSolids;
|
||||||
|
public MicrowaveUpdateUserInterfaceState(IReadOnlyList<Solution.ReagentQuantity> reagents, List<EntityUid> solids)
|
||||||
|
{
|
||||||
|
ReagentsReagents = reagents;
|
||||||
|
ContainedSolids = solids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum MicrowaveVisualState
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
Cooking
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetSerializable, Serializable]
|
||||||
|
public enum MicrowaveUiKey
|
||||||
|
{
|
||||||
|
Key
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using YamlDotNet.RepresentationModel;
|
||||||
|
|
||||||
|
namespace Content.Shared.Prototypes.Kitchen
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A recipe for space microwaves.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
[Prototype("microwaveMealRecipe")]
|
||||||
|
|
||||||
|
public class FoodRecipePrototype : IPrototype, IIndexedPrototype
|
||||||
|
{
|
||||||
|
|
||||||
|
private string _id;
|
||||||
|
private string _name;
|
||||||
|
private string _result;
|
||||||
|
private int _cookTime;
|
||||||
|
|
||||||
|
private Dictionary<string, int> _ingsReagents;
|
||||||
|
private Dictionary<string, int> _ingsSolids;
|
||||||
|
|
||||||
|
public string Name => Loc.GetString(_name);
|
||||||
|
public string ID => _id;
|
||||||
|
public string Result => _result;
|
||||||
|
public int CookTime => _cookTime;
|
||||||
|
public IReadOnlyDictionary<string, int> IngredientsReagents => _ingsReagents;
|
||||||
|
public IReadOnlyDictionary<string, int> IngredientsSolids => _ingsSolids;
|
||||||
|
|
||||||
|
|
||||||
|
public void LoadFrom(YamlMappingNode mapping)
|
||||||
|
{
|
||||||
|
var serializer = YamlObjectSerializer.NewReader(mapping);
|
||||||
|
|
||||||
|
serializer.DataField(ref _id, "id", string.Empty);
|
||||||
|
serializer.DataField(ref _name, "name", string.Empty);
|
||||||
|
serializer.DataField(ref _result, "result", string.Empty);
|
||||||
|
serializer.DataField(ref _ingsReagents, "reagents", new Dictionary<string, int>());
|
||||||
|
serializer.DataField(ref _ingsSolids, "solids", new Dictionary<string, int>());
|
||||||
|
serializer.DataField(ref _cookTime, "time", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -138,7 +138,7 @@ namespace Content.Shared
|
|||||||
|
|
||||||
public string GamemodeTitle;
|
public string GamemodeTitle;
|
||||||
public TimeSpan RoundDuration;
|
public TimeSpan RoundDuration;
|
||||||
|
|
||||||
|
|
||||||
public uint PlayerCount;
|
public uint PlayerCount;
|
||||||
|
|
||||||
|
|||||||
BIN
Resources/Audio/effects/alert.ogg
Normal file
BIN
Resources/Audio/machines/microwave_done_beep.ogg
Normal file
BIN
Resources/Audio/machines/microwave_loop.ogg
Normal file
BIN
Resources/Audio/machines/microwave_start_beep.ogg
Normal file
@@ -134,3 +134,4 @@
|
|||||||
- gc_mode
|
- gc_mode
|
||||||
CanViewVar: true
|
CanViewVar: true
|
||||||
CanAdminPlace: true
|
CanAdminPlace: true
|
||||||
|
CanScript: true
|
||||||
|
|||||||
19
Resources/Locale/nl-NL/tools.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Example Dutch translations
|
||||||
|
|
||||||
|
- msgid: Wrench
|
||||||
|
msgstr: Moersleutel
|
||||||
|
|
||||||
|
- msgid: Welding Tool
|
||||||
|
msgstr: Lasapparaat
|
||||||
|
|
||||||
|
- msgid: Crowbar
|
||||||
|
msgstr: Koevoet
|
||||||
|
|
||||||
|
- msgid: Screwdriver
|
||||||
|
msgstr: Schroevendraaier
|
||||||
|
|
||||||
|
- msgid: Wirecutters
|
||||||
|
msgstr: Draadtang
|
||||||
|
|
||||||
|
- msgid: Multitool
|
||||||
|
msgstr: Multi Tool # This is what google translate gives me idk.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
- type: entity
|
||||||
|
id: GravityGenerator
|
||||||
|
name: Gravity Generator
|
||||||
|
description: It's what keeps you to the floor.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Buildings/gravity_generator.rsi
|
||||||
|
layers:
|
||||||
|
- state: on
|
||||||
|
- sprite: Buildings/gravity_generator_core.rsi
|
||||||
|
state: activated
|
||||||
|
shader: unshaded
|
||||||
|
- type: Icon
|
||||||
|
sprite: Buildings/gravity_generator.rsi
|
||||||
|
state: on
|
||||||
|
- type: SnapGrid
|
||||||
|
offset: Center
|
||||||
|
- type: PowerDevice
|
||||||
|
load: 500
|
||||||
|
- type: Collidable
|
||||||
|
shapes:
|
||||||
|
- !type:PhysShapeAabb
|
||||||
|
bounds: "-1.5,-1.5,1.5,1.5"
|
||||||
|
layer: 15
|
||||||
|
- type: Clickable
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Damageable
|
||||||
|
- type: Breakable
|
||||||
|
threshold: 150
|
||||||
|
- type: GravityGenerator
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
- key: enum.GravityGeneratorUiKey.Key
|
||||||
|
type: GravityGeneratorBoundUserInterface
|
||||||
|
placement:
|
||||||
|
mode: AlignTileAny
|
||||||
@@ -36,7 +36,6 @@
|
|||||||
- type: Appearance
|
- type: Appearance
|
||||||
visuals:
|
visuals:
|
||||||
- type: MedicalScannerVisualizer2D
|
- type: MedicalScannerVisualizer2D
|
||||||
- type: PowerDevice
|
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
- key: enum.MedicalScannerUiKey.Key
|
- key: enum.MedicalScannerUiKey.Key
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
state: utilitybelt
|
state: utilitybelt
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
Size: 50
|
Size: 50
|
||||||
|
QuickEquip: false
|
||||||
sprite: Clothing/belt_utility.rsi
|
sprite: Clothing/belt_utility.rsi
|
||||||
- type: Storage
|
- type: Storage
|
||||||
Capacity: 40 # Full tool loadout is 35, plus an extra
|
Capacity: 40 # Full tool loadout is 35, plus an extra
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
# name: Ambrosia vulgar is crushed
|
# name: Ambrosia vulgar is crushed
|
||||||
# parent: FoodBase
|
# parent: FoodBase
|
||||||
# id: FoodAmbrosiaVulgarIsCrushed
|
# id: FoodAmbrosiaVulgarIsCrushed
|
||||||
# description:
|
# description:
|
||||||
# components:
|
# components:
|
||||||
# - type: Food
|
# - type: Food
|
||||||
# uses: 1
|
# uses: 1
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
# name: Bacon
|
# name: Bacon
|
||||||
# parent: FoodBase
|
# parent: FoodBase
|
||||||
# id: FoodBacon
|
# id: FoodBacon
|
||||||
# description:
|
# description:
|
||||||
# components:
|
# components:
|
||||||
# - type: Food
|
# - type: Food
|
||||||
# uses: 1
|
# uses: 1
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
name: Bread (slice)
|
name: Bread (slice)
|
||||||
parent: FoodBase
|
parent: FoodBase
|
||||||
id: FoodBreadSlice
|
id: FoodBreadSlice
|
||||||
description:
|
description:
|
||||||
components:
|
components:
|
||||||
- type: Food
|
- type: Food
|
||||||
contents:
|
contents:
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
name: Banana bread (slice)
|
name: Banana bread (slice)
|
||||||
parent: FoodBase
|
parent: FoodBase
|
||||||
id: FoodBananaBreadSlice
|
id: FoodBananaBreadSlice
|
||||||
description:
|
description:
|
||||||
components:
|
components:
|
||||||
- type: Food
|
- type: Food
|
||||||
contents:
|
contents:
|
||||||
@@ -233,7 +233,7 @@
|
|||||||
# name: Bear meat
|
# name: Bear meat
|
||||||
# parent: FoodBase
|
# parent: FoodBase
|
||||||
# id: FoodBearMeat
|
# id: FoodBearMeat
|
||||||
# description:
|
# description:
|
||||||
# components:
|
# components:
|
||||||
# - type: Food
|
# - type: Food
|
||||||
# uses: 1
|
# uses: 1
|
||||||
@@ -612,7 +612,7 @@
|
|||||||
# name: Cocoa
|
# name: Cocoa
|
||||||
# parent: FoodBase
|
# parent: FoodBase
|
||||||
# id: FoodCocoa
|
# id: FoodCocoa
|
||||||
# description:
|
# description:
|
||||||
# components:
|
# components:
|
||||||
# - type: Food
|
# - type: Food
|
||||||
# uses: 1
|
# uses: 1
|
||||||
@@ -1482,19 +1482,21 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Objects/Food/loadedbakedpotato.rsi
|
sprite: Objects/Food/loadedbakedpotato.rsi
|
||||||
|
|
||||||
#- type: entity
|
- type: entity
|
||||||
# parent: FoodBase
|
parent: FoodBase
|
||||||
# id: FoodMeat
|
id: FoodMeat
|
||||||
# name: Meat
|
name: Meat
|
||||||
# description: ''
|
description: A slab of meat.
|
||||||
# components:
|
components:
|
||||||
# - type: Food
|
- type: Food
|
||||||
# uses: 1
|
contents:
|
||||||
# restore_amount: 1
|
reagents:
|
||||||
# - type: Sprite
|
- ReagentId: chem.Nutriment
|
||||||
# sprite: Objects/Food/meat.rsi
|
Quantity: 5
|
||||||
# - type: Icon
|
- type: Sprite
|
||||||
# sprite: Objects/Food/meat.rsi
|
sprite: Objects/Food/meat.rsi
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Food/meat.rsi
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: FoodBase
|
parent: FoodBase
|
||||||
@@ -2835,19 +2837,21 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Objects/Food/xenobreadslice.rsi
|
sprite: Objects/Food/xenobreadslice.rsi
|
||||||
|
|
||||||
#- type: entity
|
- type: entity
|
||||||
# parent: FoodBase
|
parent: FoodBase
|
||||||
# id: FoodXenomeat
|
id: FoodXenomeat
|
||||||
# name: Xenomeat
|
name: Xenomeat
|
||||||
# description: ''
|
description: Yum.
|
||||||
# components:
|
components:
|
||||||
# - type: Food
|
- type: Food
|
||||||
# uses: 1
|
contents:
|
||||||
# restore_amount: 1
|
reagents:
|
||||||
# - type: Sprite
|
- ReagentId: chem.Nutriment
|
||||||
# sprite: Objects/Food/xenomeat.rsi
|
Quantity: 20
|
||||||
# - type: Icon
|
- type: Sprite
|
||||||
# sprite: Objects/Food/xenomeat.rsi
|
sprite: Objects/Food/xenomeat.rsi
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Food/xenomeat.rsi
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: FoodBase
|
parent: FoodBase
|
||||||
@@ -2865,3 +2869,20 @@
|
|||||||
sprite: Objects/Food/xenomeatpie.rsi
|
sprite: Objects/Food/xenomeatpie.rsi
|
||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Objects/Food/xenomeatpie.rsi
|
sprite: Objects/Food/xenomeatpie.rsi
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: FoodBase
|
||||||
|
id: DisgustingSweptSoup
|
||||||
|
name: Salty Sweet Miso Cola Soup
|
||||||
|
description: Jesus christ.
|
||||||
|
components:
|
||||||
|
- type: Food
|
||||||
|
contents:
|
||||||
|
reagents:
|
||||||
|
- ReagentId: chem.Bleach
|
||||||
|
Quantity: 15
|
||||||
|
spawn_on_finish: TrashSnackBowl
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Food/stew.rsi
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Food/stew.rsi
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
- type: entity
|
||||||
|
parent: BaseItem
|
||||||
|
id: ReagentContainerFlour
|
||||||
|
name: Flour
|
||||||
|
description: Not to be confused with flower.
|
||||||
|
components:
|
||||||
|
- type: Solution
|
||||||
|
maxVol: 50
|
||||||
|
contents:
|
||||||
|
reagents:
|
||||||
|
- ReagentId: chem.Flour
|
||||||
|
Quantity: 50
|
||||||
|
- type: Pourable
|
||||||
|
transferAmount: 5
|
||||||
|
- type: Drink
|
||||||
|
despawn_empty: true
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Food/flour.rsi
|
||||||
|
state: icon
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Food/flour.rsi
|
||||||
|
state: icon
|
||||||
@@ -23,6 +23,18 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
texture: Objects/Instruments/musician.rsi/h_synthesizer.png
|
texture: Objects/Instruments/musician.rsi/h_synthesizer.png
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: Acoustic Guitar
|
||||||
|
parent: BaseHandheldInstrument
|
||||||
|
id: AcousticGuitarInstrument
|
||||||
|
components:
|
||||||
|
- type: Instrument
|
||||||
|
program: 25
|
||||||
|
- type: Sprite
|
||||||
|
texture: Objects/Instruments/musician.rsi/guitar.png
|
||||||
|
- type: Icon
|
||||||
|
texture: Objects/Instruments/musician.rsi/guitar.png
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: Violin
|
name: Violin
|
||||||
parent: BaseHandheldInstrument
|
parent: BaseHandheldInstrument
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
- type: Sound
|
- type: Sound
|
||||||
- type: EmitSoundOnUse
|
- type: EmitSoundOnUse
|
||||||
sound: /Audio/items/bikehorn.ogg
|
sound: /Audio/items/bikehorn.ogg
|
||||||
|
variation: 0.2
|
||||||
|
|
||||||
- type: UseDelay
|
- type: UseDelay
|
||||||
delay: 0.5
|
delay: 0.5
|
||||||
|
|||||||
@@ -42,6 +42,3 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
Size: 24
|
Size: 24
|
||||||
sprite: Objects/Guns/SMGs/c20r.rsi
|
sprite: Objects/Guns/SMGs/c20r.rsi
|
||||||
- type: Item
|
|
||||||
Size: 24
|
|
||||||
sprite: Objects/Guns/SMGs/wt550.rsi
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
drawdepth: Objects
|
drawdepth: Objects
|
||||||
- type: Icon
|
- type: Icon
|
||||||
texture: Objects/Janitorial/mopbucket.png
|
texture: Objects/Janitorial/mopbucket.png
|
||||||
- type: Clickable
|
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
- type: Bucket
|
- type: Bucket
|
||||||
- type: Sound
|
- type: Sound
|
||||||
@@ -51,7 +50,6 @@
|
|||||||
- type: Physics
|
- type: Physics
|
||||||
mass: 5
|
mass: 5
|
||||||
Anchored: false
|
Anchored: false
|
||||||
- type: Sound
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseItem
|
||||||
|
|||||||
40
Resources/Prototypes/Entities/kitchen.yml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
- type: entity
|
||||||
|
id: KitchenMicrowave
|
||||||
|
name: Microwave
|
||||||
|
description: It's magic.
|
||||||
|
components:
|
||||||
|
- type: Microwave
|
||||||
|
- type: Clickable
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Solution
|
||||||
|
maxVol: 100
|
||||||
|
caps: 1
|
||||||
|
- type: Appearance
|
||||||
|
visuals:
|
||||||
|
- type: MicrowaveVisualizer
|
||||||
|
- type: Sound
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
- key: enum.MicrowaveUiKey.Key
|
||||||
|
type: MicrowaveBoundUserInterface
|
||||||
|
|
||||||
|
|
||||||
|
- type: Collidable
|
||||||
|
shapes:
|
||||||
|
- !type:PhysShapeAabb
|
||||||
|
bounds: "-0.25,-0.4,0.25,0.4"
|
||||||
|
layer: 15
|
||||||
|
IsScrapingFloor: true
|
||||||
|
- type: Sprite
|
||||||
|
netsync: false
|
||||||
|
sprite: Objects/Kitchen/microwave.rsi
|
||||||
|
layers:
|
||||||
|
- state: mw0
|
||||||
|
map: ["enum.MicrowaveVisualizerLayers.Base"]
|
||||||
|
- state: mw_unlit
|
||||||
|
shader: unshaded
|
||||||
|
map: ["enum.MicrowaveVisualizerLayers.BaseUnlit"]
|
||||||
|
- type: PowerDevice
|
||||||
|
- type: Icon
|
||||||
|
sprite: Objects/Kitchen/microwave.rsi
|
||||||
|
state: mw0
|
||||||
338
Resources/Prototypes/Kitchen/meal_recipes.yml
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
|
||||||
|
#Burgers
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeCheeseburger
|
||||||
|
name: Cheeseburger Recipe
|
||||||
|
result: FoodCheeseburger
|
||||||
|
time: 5
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 5
|
||||||
|
solids:
|
||||||
|
FoodMeat: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeTofuBurger
|
||||||
|
name: Tofu Burger Recipe
|
||||||
|
result: FoodTofuBurger
|
||||||
|
time: 5
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 15
|
||||||
|
solids:
|
||||||
|
Tofu: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeXenoburger
|
||||||
|
name: Xenoburger Recipe
|
||||||
|
result: FoodXenoburger
|
||||||
|
time: 5
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 5
|
||||||
|
solids:
|
||||||
|
FoodXenomeat: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeSuperBiteBurger
|
||||||
|
name: Super Bite Burger Recipe
|
||||||
|
result: FoodSuperBiteBurger
|
||||||
|
time: 20
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 15
|
||||||
|
chem.Salt: 5
|
||||||
|
chem.Pepper: 5
|
||||||
|
solids:
|
||||||
|
FoodMeat: 5
|
||||||
|
FoodCheeseWedge: 3
|
||||||
|
FoodTomato: 4
|
||||||
|
FoodEgg: 2
|
||||||
|
|
||||||
|
#Breads & Sandwiches
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeBread
|
||||||
|
name: Bread Recipe
|
||||||
|
result: DrinkFoodContainerBread
|
||||||
|
time: 15
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 15
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeSandwich
|
||||||
|
name: Sandwich Recipe
|
||||||
|
result: FoodSandwich
|
||||||
|
time: 10
|
||||||
|
solids:
|
||||||
|
FoodBreadSlice: 2
|
||||||
|
FoodMeatSteak: 1
|
||||||
|
FoodCheeseWedge: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeToastedSandwich
|
||||||
|
name: Toasted Sandwich Recipe
|
||||||
|
result: FoodToastedSandwich
|
||||||
|
time: 5
|
||||||
|
solids:
|
||||||
|
FoodSandwich: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeGrilledCheese
|
||||||
|
name: Grilled Cheese Recipe
|
||||||
|
result: FoodGrilledCheese
|
||||||
|
time: 5
|
||||||
|
solids:
|
||||||
|
FoodBreadSlice: 2
|
||||||
|
FoodCheeseWedge: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeBaguette
|
||||||
|
name: Baguette Recipe
|
||||||
|
result: FoodBaguette
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 15
|
||||||
|
chem.Salt: 1
|
||||||
|
chem.Pepper: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeCreamCheeseBread
|
||||||
|
name: Cream Cheese Bread Recipe
|
||||||
|
result: DrinkFoodContainerCreamCheeseBread
|
||||||
|
time: 20
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 15
|
||||||
|
solids:
|
||||||
|
FoodCheeseWedge: 2
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeBananaBread
|
||||||
|
name: Banana Bread Recipe
|
||||||
|
result: DrinkFoodContainerBananaBread
|
||||||
|
time: 25
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 15
|
||||||
|
chem.Milk: 5
|
||||||
|
solids:
|
||||||
|
FoodEgg: 3
|
||||||
|
FoodBanana: 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Pizzas
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeMargheritaPizza
|
||||||
|
name: Margherita Pizza Recipe
|
||||||
|
result: DrinkFoodContainerMargheritaPizza
|
||||||
|
time: 30
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 10
|
||||||
|
solids:
|
||||||
|
FoodCheeseWedge: 4
|
||||||
|
FoodTomato: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeMushroomPizza
|
||||||
|
name: Mushroom Pizza Recipe
|
||||||
|
result: DrinkFoodContainerMushroomPizza
|
||||||
|
time: 25
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 10
|
||||||
|
solids:
|
||||||
|
FoodMushroom: 5
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeMeatPizza
|
||||||
|
name: Meat Pizza Recipe
|
||||||
|
result: DrinkFoodContainerMeatPizza
|
||||||
|
time: 30
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 10
|
||||||
|
solids:
|
||||||
|
FoodMeat: 3
|
||||||
|
FoodCheeseWedge: 1
|
||||||
|
FoodTomato: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeVegetablePizza
|
||||||
|
name: Vegetable Pizza Recipe
|
||||||
|
result: DrinkFoodContainerVegetablePizza
|
||||||
|
time: 30
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 10
|
||||||
|
solids:
|
||||||
|
FoodEggplant: 1
|
||||||
|
FoodCarrot: 1
|
||||||
|
FoodCorn: 1
|
||||||
|
FoodTomato: 1
|
||||||
|
|
||||||
|
#Italian
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeSpaghetti
|
||||||
|
name: Spaghetti Recipe
|
||||||
|
result: FoodSpaghetti
|
||||||
|
time: 1
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 5
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeBoiledSpaghetti
|
||||||
|
name: Boiled Spaghetti Recipe
|
||||||
|
result: FoodSpagettiBoiled
|
||||||
|
time: 5
|
||||||
|
reagents:
|
||||||
|
chem.H2O: 5
|
||||||
|
solids:
|
||||||
|
FoodSpagetti: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipePastaTomato
|
||||||
|
name: Pasta Tomato Recipe
|
||||||
|
result: FoodPastaTomato
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.H2O: 5
|
||||||
|
solids:
|
||||||
|
FoodSpagetti: 1
|
||||||
|
FoodTomato: 2
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeMeatballSpaghetti
|
||||||
|
name: Spaghetti & Meatballs Recipe
|
||||||
|
result: FoodMeatballSpaghetti
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.H2O: 5
|
||||||
|
solids:
|
||||||
|
FoodSpagetti: 1
|
||||||
|
FoodMeatball: 2
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeCrabSpaghetti
|
||||||
|
name: Crab Spaghetti Recipe
|
||||||
|
result: FoodCrabSpaghetti
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.H2O: 5
|
||||||
|
solids:
|
||||||
|
FoodCrabMeat: 2
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeCopypasta
|
||||||
|
name: Copypasta Recipe
|
||||||
|
result: FoodCopypasta
|
||||||
|
time: 10
|
||||||
|
solids:
|
||||||
|
FoodPastaTomato: 2
|
||||||
|
|
||||||
|
# - type: microwaveMealRecipe
|
||||||
|
# id: RecipeMoMMISpaghetti
|
||||||
|
# name: MoMMI Spaghetti Recipe
|
||||||
|
# result: FoodMoMMISpaghetti
|
||||||
|
# time: 10
|
||||||
|
# reagents:
|
||||||
|
# chem.Flour: 5
|
||||||
|
# solids:
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeRisotto
|
||||||
|
name: Risotto Recipe
|
||||||
|
result: FoodRisotto
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 10 #This should be 10 units of rice.
|
||||||
|
chem.Wine: 5
|
||||||
|
solids:
|
||||||
|
FoodCheeseWedge: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeBruschetta
|
||||||
|
name: Bruschetta Recipe
|
||||||
|
result: FoodBruschetta
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.Flour: 10
|
||||||
|
chem.Salt: 2
|
||||||
|
solids:
|
||||||
|
FoodGarlic: 1
|
||||||
|
FoodCheeseWedge: 1
|
||||||
|
FoodTomato: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeQuiche
|
||||||
|
name: Quiche Recipe
|
||||||
|
result: FoodQuiche
|
||||||
|
time: 10
|
||||||
|
solids:
|
||||||
|
FoodBlueTomato: 1
|
||||||
|
FoodGarlic: 1
|
||||||
|
FoodEgg: 1
|
||||||
|
FoodCheeseWedge: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeLasagna
|
||||||
|
name: Lasagna Recipe
|
||||||
|
result: FoodLasagna
|
||||||
|
time: 15
|
||||||
|
# reagents:
|
||||||
|
# chem.TomatoJuice: 15
|
||||||
|
solids:
|
||||||
|
FoodFlatDough: 2
|
||||||
|
FoodMeat: 2
|
||||||
|
FoodEggPlant: 1
|
||||||
|
FoodCheeseWedge: 1
|
||||||
|
|
||||||
|
#Soups & Stew
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeMeatballSoup
|
||||||
|
name: Meatball Soup Recipe
|
||||||
|
result: FoodMeatballSoup
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.H2O: 10
|
||||||
|
solids:
|
||||||
|
FoodMeatball: 1
|
||||||
|
FoodCarrot: 1
|
||||||
|
FoodPotato: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeNettleSoup
|
||||||
|
name: Nettle Soup Recipe
|
||||||
|
result: FoodNettleSoup
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.H2O: 10
|
||||||
|
solids:
|
||||||
|
FoodNettle: 1
|
||||||
|
FoodEgg: 1
|
||||||
|
FoodPotato: 1
|
||||||
|
|
||||||
|
#Other
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeMeatSteak
|
||||||
|
name: Meat Steak Recipe
|
||||||
|
result: FoodMeatSteak
|
||||||
|
time: 10
|
||||||
|
reagents:
|
||||||
|
chem.Salt: 1
|
||||||
|
chem.Pepper: 1
|
||||||
|
solids:
|
||||||
|
FoodMeat: 1
|
||||||
|
|
||||||
|
- type: microwaveMealRecipe
|
||||||
|
id: RecipeMisoColaSoup
|
||||||
|
name: Salty Sweet MiloCola Soup Recipe
|
||||||
|
result: DisgustingSweptSoup
|
||||||
|
time: 15
|
||||||
|
reagents:
|
||||||
|
chem.Cola: 5
|
||||||
|
solids:
|
||||||
|
FoodMiloSoup: 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Handy template for copy **pasta**. Get it? Pasta? Aw whatever fuck you.
|
||||||
|
# - type: microwaveMealRecipe
|
||||||
|
# id:
|
||||||
|
# name:
|
||||||
|
# result:
|
||||||
|
# time: 5
|
||||||
|
# reagents:
|
||||||
|
|
||||||
|
# solids:
|
||||||
@@ -8,7 +8,9 @@
|
|||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: Screwdriver
|
id: Screwdriver
|
||||||
icon: Objects/Tools/screwdriver.png
|
icon:
|
||||||
|
sprite: Objects/Tools/screwdriver.rsi
|
||||||
|
state: screwdriver
|
||||||
result: Screwdriver
|
result: Screwdriver
|
||||||
completetime: 500
|
completetime: 500
|
||||||
materials:
|
materials:
|
||||||
@@ -16,7 +18,9 @@
|
|||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: Welder
|
id: Welder
|
||||||
icon: Objects/Tools/autolathe_welder.png
|
icon:
|
||||||
|
sprite: Objects/Tools/welder.rsi
|
||||||
|
state: welder
|
||||||
result: Welder
|
result: Welder
|
||||||
completetime: 500
|
completetime: 500
|
||||||
materials:
|
materials:
|
||||||
@@ -51,7 +55,9 @@
|
|||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: Multitool
|
id: Multitool
|
||||||
icon: Objects/Tools/multitool.png
|
icon:
|
||||||
|
sprite: Objects/Tools/multitool.rsi
|
||||||
|
state: multitool
|
||||||
result: Multitool
|
result: Multitool
|
||||||
completetime: 500
|
completetime: 500
|
||||||
materials:
|
materials:
|
||||||
|
|||||||
8
Resources/Prototypes/Reagents/food_reagents.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
- type: reagent
|
||||||
|
id: chem.Flour
|
||||||
|
name: Flour
|
||||||
|
desc: Used for baking.
|
||||||
|
color: "#FFFFFF"
|
||||||
|
metabolism:
|
||||||
|
- !type:DefaultFood
|
||||||
|
rate: 1
|
||||||
BIN
Resources/Textures/Buildings/gravity_generator.rsi/broken.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
23
Resources/Textures/Buildings/gravity_generator.rsi/meta.json
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"version":1,
|
||||||
|
"size":{
|
||||||
|
"x":96,
|
||||||
|
"y":96
|
||||||
|
},
|
||||||
|
"license":"CC-BY-SA-3.0",
|
||||||
|
"copyright":"Taken from https://github.com/tgstation/tgstation",
|
||||||
|
"states":[
|
||||||
|
{
|
||||||
|
"name":"on",
|
||||||
|
"directions": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "off",
|
||||||
|
"directions": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "broken",
|
||||||
|
"directions": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/Buildings/gravity_generator.rsi/off.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Resources/Textures/Buildings/gravity_generator.rsi/on.png
Executable file
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 684 B |
BIN
Resources/Textures/Buildings/gravity_generator_core.rsi/idle.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"version":1,
|
||||||
|
"size":{
|
||||||
|
"x":32,
|
||||||
|
"y":32
|
||||||
|
},
|
||||||
|
"license":"CC-BY-SA-3.0",
|
||||||
|
"copyright":"Taken from https://github.com/tgstation/tgstation",
|
||||||
|
"states":[
|
||||||
|
{
|
||||||
|
"name": "activated",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[0.1,
|
||||||
|
0.1,
|
||||||
|
0.1]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
105
Resources/Textures/Objects/Kitchen/microwave.rsi/meta.json
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"license": "AGPL v3",
|
||||||
|
"copyright": "Taken from https://github.com/discordia-space/CEV-Eris",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "mw",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mw_unlit",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mw0",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mw_running_unlit",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mwb",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mwbloody",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mwbloody0",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mwbloody1",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mwbloodyo",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mwo",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/Objects/Kitchen/microwave.rsi/mw.png
Normal file
|
After Width: | Height: | Size: 636 B |
BIN
Resources/Textures/Objects/Kitchen/microwave.rsi/mw0.png
Normal file
|
After Width: | Height: | Size: 614 B |
BIN
Resources/Textures/Objects/Kitchen/microwave.rsi/mw1.png
Normal file
|
After Width: | Height: | Size: 825 B |