Merge branch 'master' into engitape
Signed-off-by: zelezniciar1 <39102800+zelezniciar1@users.noreply.github.com>
|
|
@ -565,6 +565,7 @@ namespace Content.Client.Lobby.UI
|
|||
}
|
||||
|
||||
Traits.SetSelectedTraits(selectedTraits);
|
||||
Traits.UpdateConditions(Profile);
|
||||
}
|
||||
// End DeltaV - Traits Integration
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using Content.Client._DV.UserInterfaces.BuildInfo; // DeltaV - More info in Escape Menu
|
||||
using Content.Client.Credits; // DeltaV - More info in Escape Menu
|
||||
using Content.Client.MainMenu.UI;
|
||||
using Content.Client.UserInterface.Systems.EscapeMenu;
|
||||
using Robust.Client;
|
||||
|
|
@ -48,6 +50,8 @@ namespace Content.Client.MainMenu
|
|||
_mainMenuControl.DirectConnectButton.OnPressed += DirectConnectButtonPressed;
|
||||
_mainMenuControl.AddressBox.OnTextEntered += AddressBoxEntered;
|
||||
_mainMenuControl.ChangelogButton.OnPressed += ChangelogButtonPressed;
|
||||
_mainMenuControl.BuildInfoButton.OnPressed += BuildInfoButtonPressed; // DeltaV - More info in Escape Menu
|
||||
_mainMenuControl.CreditsButton.OnPressed += CreditsButtonPressed; // DeltaV - More info in Escape Menu
|
||||
|
||||
_client.RunLevelChanged += RunLevelChanged;
|
||||
}
|
||||
|
|
@ -66,6 +70,18 @@ namespace Content.Client.MainMenu
|
|||
_userInterfaceManager.GetUIController<ChangelogUIController>().ToggleWindow();
|
||||
}
|
||||
|
||||
// Begin DeltaV - More info in Escape Menu
|
||||
private void BuildInfoButtonPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
_userInterfaceManager.GetUIController<BuildInfoUIController>().ToggleWindow();
|
||||
}
|
||||
|
||||
private void CreditsButtonPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
new CreditsWindow().Open();
|
||||
}
|
||||
// End DeltaV - More info in Escape Menu
|
||||
|
||||
private void OptionsButtonPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
_userInterfaceManager.GetUIController<OptionsUIController>().ToggleWindow();
|
||||
|
|
|
|||
|
|
@ -48,5 +48,18 @@
|
|||
<clog:ChangelogButton
|
||||
Name="ChangelogButton"
|
||||
Access="Public"/>
|
||||
<!-- Begin DeltaV - More info in Escape Menu -->
|
||||
<Button
|
||||
Name="CreditsButton"
|
||||
Access="Public"
|
||||
Text="{Loc server-info-credits-button}"
|
||||
TextAlign="Center" />
|
||||
<Button
|
||||
Name="BuildInfoButton"
|
||||
Access="Public"
|
||||
Text="{Loc build-info-button}"
|
||||
ToolTip="{Loc build-info-tooltip}"
|
||||
TextAlign="Center" />
|
||||
<!-- End DeltaV - More info in Escape Menu -->
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
|
|
|
|||
|
|
@ -17,5 +17,10 @@
|
|||
<PanelContainer StyleClasses="LowDivider" Margin="0 2.5 0 2.5" />
|
||||
<Button Access="Public" Name="DisconnectButton" Text="{Loc 'ui-escape-disconnect'}" />
|
||||
<Button Access="Public" Name="QuitButton" Text="{Loc 'ui-escape-quit'}" StyleClasses="ButtonColorRed" />
|
||||
<!-- Begin DeltaV - More info in Escape Menu -->
|
||||
<PanelContainer StyleClasses="LowDivider" Margin="0 2.5 0 2.5" />
|
||||
<Button Access="Public" Name="CreditsButton" Text="{Loc server-info-credits-button}" />
|
||||
<Button Access="Public" Name="BuildInfoButton" Text="{Loc build-info-button}" ToolTip="{Loc build-info-tooltip}" />
|
||||
<!-- End DeltaV - More info in Escape Menu -->
|
||||
</BoxContainer>
|
||||
</ui1:EscapeMenu>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using Content.Client.Gameplay;
|
||||
using Content.Client._DV.UserInterfaces.BuildInfo; // DeltaV - More info in Escape Menu
|
||||
using Content.Client.Credits; // DeltaV - More info in Escape Menu
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.UserInterface.Systems.Guidebook;
|
||||
using Content.Client.UserInterface.Systems.Info;
|
||||
|
|
@ -25,6 +27,7 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
|
|||
[Dependency] private readonly InfoUIController _info = default!;
|
||||
[Dependency] private readonly OptionsUIController _options = default!;
|
||||
[Dependency] private readonly GuidebookUIController _guidebook = default!;
|
||||
[Dependency] private readonly BuildInfoUIController _buildInfo = default!; // DeltaV - More info in Escape Menu
|
||||
|
||||
private Options.UI.EscapeMenu? _escapeWindow;
|
||||
|
||||
|
|
@ -103,6 +106,19 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
|
|||
_guidebook.ToggleGuidebook();
|
||||
};
|
||||
|
||||
// Begin DeltaV - More info in Escape Menu
|
||||
_escapeWindow.BuildInfoButton.OnPressed += _ =>
|
||||
{
|
||||
CloseEscapeWindow();
|
||||
_buildInfo.OpenWindow();
|
||||
};
|
||||
|
||||
_escapeWindow.CreditsButton.OnPressed += _ =>
|
||||
{
|
||||
new CreditsWindow().Open();
|
||||
};
|
||||
// End DeltaV - More info in Escape Menu
|
||||
|
||||
// Hide wiki button if we don't have a link for it.
|
||||
_escapeWindow.WikiButton.Visible = _cfg.GetCVar(CCVars.InfoLinksWiki) != "";
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
using Content.Client._DV.Traits.UI;
|
||||
using Content.Shared._DV.CCVars;
|
||||
using Content.Shared._DV.Traits;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._DV.Traits;
|
||||
|
||||
/// <summary>
|
||||
/// Client system that shows a popup when traits are disabled due to unmet conditions.
|
||||
/// </summary>
|
||||
public sealed class DisabledTraitsPopupSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
private DisabledTraitsPopup? _window;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeNetworkEvent<DisabledTraitsEvent>(OnDisabledTraits);
|
||||
}
|
||||
|
||||
private void OnDisabledTraits(DisabledTraitsEvent ev)
|
||||
{
|
||||
// Don't show if user has opted to skip this popup
|
||||
if (_cfg.GetCVar(DCCVars.SkipDisabledTraitsPopup))
|
||||
return;
|
||||
|
||||
// Don't show if no traits were actually disabled
|
||||
if (ev.DisabledTraits.Count == 0)
|
||||
return;
|
||||
|
||||
OpenDisabledTraitsPopup(ev.DisabledTraits);
|
||||
}
|
||||
|
||||
private void OpenDisabledTraitsPopup(Dictionary<ProtoId<TraitPrototype>, List<string>> disabledTraits)
|
||||
{
|
||||
// Close existing window if one is open
|
||||
if (_window != null)
|
||||
{
|
||||
_window.Close();
|
||||
_window = null;
|
||||
}
|
||||
|
||||
_window = new DisabledTraitsPopup(disabledTraits);
|
||||
_window.OpenCentered();
|
||||
_window.OnClose += () => _window = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc disabled-traits-popup-title}"
|
||||
MinSize="400 200"
|
||||
SetSize="500 350">
|
||||
<BoxContainer Orientation="Vertical" Margin="10">
|
||||
<!-- Header -->
|
||||
<BoxContainer Orientation="Horizontal" Margin="0 0 0 10">
|
||||
<TextureRect TexturePath="/Textures/Interface/info.svg.192dpi.png"
|
||||
TextureScale="0.5 0.5"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 10 0" />
|
||||
<Label Name="TitleLabel"
|
||||
StyleClasses="LabelHeading"
|
||||
VAlign="Center" />
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Message -->
|
||||
<RichTextLabel Name="MessageLabel"
|
||||
Margin="0 0 0 15" />
|
||||
|
||||
<!-- List of disabled traits -->
|
||||
<Label Text="{Loc disabled-traits-popup-list-header}"
|
||||
StyleClasses="LabelSubText"
|
||||
Margin="0 0 0 5" />
|
||||
|
||||
<PanelContainer StyleClasses="BackgroundDark" VerticalExpand="True">
|
||||
<ScrollContainer HScrollEnabled="False" VerticalExpand="True">
|
||||
<BoxContainer Name="DisabledTraitsContainer"
|
||||
Orientation="Vertical"
|
||||
Margin="5" />
|
||||
</ScrollContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<!-- Footer with checkbox and close button -->
|
||||
<BoxContainer Orientation="Vertical" Margin="0 10 0 0">
|
||||
<CheckBox Name="SkipCheckBox"
|
||||
Text="{Loc disabled-traits-popup-skip-checkbox}"
|
||||
HorizontalAlignment="Center" />
|
||||
|
||||
<Button Name="ButtonClose"
|
||||
Text="{Loc disabled-traits-popup-close-button}"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0 10 0 0"
|
||||
MinSize="120 0" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared._DV.CCVars;
|
||||
using Content.Shared._DV.Traits;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client._DV.Traits.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class DisabledTraitsPopup : FancyWindow
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
private bool _initialSkipState;
|
||||
|
||||
public DisabledTraitsPopup(Dictionary<ProtoId<TraitPrototype>, List<string>> disabledTraits)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
InitializeUI(disabledTraits);
|
||||
InitializeEvents();
|
||||
}
|
||||
|
||||
private void InitializeUI(Dictionary<ProtoId<TraitPrototype>, List<string>> disabledTraits)
|
||||
{
|
||||
TitleLabel.Text = Loc.GetString("disabled-traits-popup-label");
|
||||
MessageLabel.SetMessage(FormattedMessage.FromMarkupOrThrow(
|
||||
Loc.GetString("disabled-traits-popup-message")));
|
||||
|
||||
_initialSkipState = _cfg.GetCVar(DCCVars.SkipDisabledTraitsPopup);
|
||||
SkipCheckBox.Pressed = _initialSkipState;
|
||||
|
||||
PopulateDisabledTraits(disabledTraits);
|
||||
}
|
||||
|
||||
private void PopulateDisabledTraits(Dictionary<ProtoId<TraitPrototype>, List<string>> disabledTraits)
|
||||
{
|
||||
DisabledTraitsContainer.RemoveAllChildren();
|
||||
|
||||
foreach (var (traitId, reasons) in disabledTraits)
|
||||
{
|
||||
if (!_prototype.TryIndex(traitId, out var trait))
|
||||
continue;
|
||||
|
||||
var container = new BoxContainer
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
||||
Margin = new Thickness(0, 0, 0, 10)
|
||||
};
|
||||
|
||||
// Trait name
|
||||
var nameLabel = new Label
|
||||
{
|
||||
Text = Loc.GetString(trait.Name),
|
||||
FontColorOverride = Color.FromHex("#ff6b6b"),
|
||||
StyleClasses = { "LabelSubText" }
|
||||
};
|
||||
container.AddChild(nameLabel);
|
||||
|
||||
// Reasons why it was disabled
|
||||
foreach (var reason in reasons)
|
||||
{
|
||||
var reasonLabel = new RichTextLabel
|
||||
{
|
||||
Margin = new Thickness(10, 2, 0, 0)
|
||||
};
|
||||
reasonLabel.SetMessage(FormattedMessage.FromMarkupOrThrow(
|
||||
Loc.GetString("disabled-traits-popup-reason", ("reason", reason))));
|
||||
container.AddChild(reasonLabel);
|
||||
}
|
||||
|
||||
DisabledTraitsContainer.AddChild(container);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
OnClose += SaveSkipState;
|
||||
ButtonClose.OnPressed += OnClosePressed;
|
||||
}
|
||||
|
||||
private void SaveSkipState()
|
||||
{
|
||||
if (SkipCheckBox.Pressed == _initialSkipState)
|
||||
return;
|
||||
|
||||
_cfg.SetCVar(DCCVars.SkipDisabledTraitsPopup, SkipCheckBox.Pressed);
|
||||
_cfg.SaveToFile();
|
||||
}
|
||||
|
||||
private void OnClosePressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
using System.Linq;
|
||||
using Content.Shared._DV.Traits;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
|
@ -169,11 +171,11 @@ public sealed partial class TraitCategory : BoxContainer
|
|||
/// Updates condition states for all trait entries based on current job/species.
|
||||
/// Traits that don't meet conditions are disabled but still visible.
|
||||
/// </summary>
|
||||
public void UpdateConditions(string? jobId, string? speciesId)
|
||||
public void UpdateConditions(ProtoId<JobPrototype>? jobId, ProtoId<SpeciesPrototype>? speciesId, IReadOnlySet<ProtoId<AntagPrototype>>? antagPreferences)
|
||||
{
|
||||
foreach (var (_, entry) in _traitEntries)
|
||||
{
|
||||
entry.UpdateConditionsMet(jobId, speciesId);
|
||||
entry.UpdateConditionsMet(jobId, speciesId, antagPreferences);
|
||||
}
|
||||
|
||||
// Update stats since some traits may have been deselected
|
||||
|
|
|
|||
|
|
@ -7,11 +7,27 @@
|
|||
HorizontalExpand="True"
|
||||
Margin="10 8">
|
||||
|
||||
<!-- Checkbox / Toggle -->
|
||||
<CheckBox Name="TraitCheckbox"
|
||||
StyleClasses="TraitsEntryCheckbox"
|
||||
VerticalAlignment="Top"
|
||||
Margin="0 2 10 0"/>
|
||||
<!-- Toggle Container -->
|
||||
<BoxContainer Name="ToggleContainer"
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Top"
|
||||
Margin="0 2 10 0"
|
||||
SetWidth="24">
|
||||
|
||||
<!-- Checkbox -->
|
||||
<CheckBox Name="TraitCheckbox"
|
||||
StyleClasses="TraitsEntryCheckbox"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<!-- Lock Icon -->
|
||||
<TextureRect Name="LockIcon"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
SetSize="20 20"
|
||||
Stretch="KeepAspectCentered"
|
||||
TexturePath="/Textures/Interface/VerbIcons/lock.svg.192dpi.png"
|
||||
Visible="False"/>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Trait Info -->
|
||||
<BoxContainer Orientation="Vertical"
|
||||
|
|
@ -31,7 +47,6 @@
|
|||
<!-- Description -->
|
||||
<RichTextLabel Name="TraitDescriptionLabel"
|
||||
StyleClasses="TraitsEntryDescriptionLabel"
|
||||
HorizontalExpand="True"
|
||||
Margin="0 4 0 0"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using Content.Shared._DV.Traits;
|
||||
using Content.Shared._DV.Traits.Conditions;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
|
|
@ -18,7 +20,8 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
public event Action<bool>? OnToggled;
|
||||
|
||||
public bool IsSelected => TraitCheckbox.Pressed;
|
||||
public int TraitCost { get; }
|
||||
public readonly int TraitCost;
|
||||
public bool MeetsConditions { get; private set; } = true;
|
||||
|
||||
private readonly TraitPrototype _trait;
|
||||
private bool _isUpdating;
|
||||
|
|
@ -88,7 +91,7 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
/// <summary>
|
||||
/// Updates whether conditions are met based on current job/species.
|
||||
/// </summary>
|
||||
public void UpdateConditionsMet(string? jobId, string? speciesId)
|
||||
public void UpdateConditionsMet(ProtoId<JobPrototype>? jobId, ProtoId<SpeciesPrototype>? speciesId, IReadOnlySet<ProtoId<AntagPrototype>>? antagPreferences)
|
||||
{
|
||||
_failedConditionTooltips.Clear();
|
||||
MeetsConditions = true;
|
||||
|
|
@ -100,6 +103,9 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
IsSpeciesCondition speciesCond => CheckSpeciesCondition(speciesCond, speciesId),
|
||||
HasJobCondition jobCond => CheckJobCondition(jobCond, jobId),
|
||||
InDepartmentCondition deptCond => CheckDepartmentCondition(deptCond, jobId),
|
||||
HasCompCondition compCond => !compCond.Invert, // can't check in lobby but screws with the inversion logic
|
||||
IsAntagEligibleCondition antagEligibleCond => CheckAntagEligibleCondition(antagEligibleCond, antagPreferences),
|
||||
AnyOfCondition anyOfCond => CheckAnyOfCondition(anyOfCond, jobId, speciesId, antagPreferences),
|
||||
_ => true,
|
||||
};
|
||||
|
||||
|
|
@ -118,39 +124,80 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
UpdateDisabledState();
|
||||
}
|
||||
|
||||
private bool CheckSpeciesCondition(IsSpeciesCondition condition, string? speciesId)
|
||||
private bool CheckSpeciesCondition(IsSpeciesCondition condition, ProtoId<SpeciesPrototype>? speciesId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(speciesId))
|
||||
if (!_prototype.TryIndex(speciesId, out var species))
|
||||
return false;
|
||||
|
||||
return speciesId == condition.Species.Id;
|
||||
return species == condition.Species;
|
||||
}
|
||||
|
||||
private bool CheckJobCondition(HasJobCondition condition, string? jobId)
|
||||
private bool CheckJobCondition(HasJobCondition condition, ProtoId<JobPrototype>? jobId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(jobId))
|
||||
if (!_prototype.TryIndex(jobId, out var job))
|
||||
return false;
|
||||
|
||||
return jobId == condition.Job;
|
||||
return job == condition.Job;
|
||||
}
|
||||
|
||||
private bool CheckDepartmentCondition(InDepartmentCondition condition, string? jobId)
|
||||
private bool CheckDepartmentCondition(InDepartmentCondition condition, ProtoId<JobPrototype>? jobId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(jobId))
|
||||
if (!_prototype.TryIndex(jobId, out var job))
|
||||
return false;
|
||||
|
||||
if (!_prototype.TryIndex(condition.Department, out var department))
|
||||
return false;
|
||||
|
||||
return department.Roles.Contains(jobId);
|
||||
return department.Roles.Contains(job);
|
||||
}
|
||||
|
||||
private bool CheckAntagEligibleCondition(IsAntagEligibleCondition condition, IReadOnlySet<ProtoId<AntagPrototype>>? antagPreferences)
|
||||
{
|
||||
if (antagPreferences is null)
|
||||
return false;
|
||||
|
||||
return antagPreferences.Contains(condition.Antag);
|
||||
}
|
||||
|
||||
private bool CheckAnyOfCondition(AnyOfCondition condition, ProtoId<JobPrototype>? jobId, ProtoId<SpeciesPrototype>? speciesId, IReadOnlySet<ProtoId<AntagPrototype>>? antagPreferences)
|
||||
{
|
||||
if (condition.Conditions.Count == 0)
|
||||
return false;
|
||||
|
||||
// Return true if ANY child condition evaluates to true
|
||||
foreach (var childCondition in condition.Conditions)
|
||||
{
|
||||
var result = childCondition switch
|
||||
{
|
||||
IsSpeciesCondition speciesCond => CheckSpeciesCondition(speciesCond, speciesId),
|
||||
HasJobCondition jobCond => CheckJobCondition(jobCond, jobId),
|
||||
InDepartmentCondition deptCond => CheckDepartmentCondition(deptCond, jobId),
|
||||
HasCompCondition compCond => !compCond.Invert, // can't check in lobby
|
||||
AnyOfCondition nestedAnyOf => CheckAnyOfCondition(nestedAnyOf, jobId, speciesId, antagPreferences), // Recursive!
|
||||
IsAntagEligibleCondition antagEligibleCond => CheckAntagEligibleCondition(antagEligibleCond, antagPreferences),
|
||||
_ => true,
|
||||
};
|
||||
|
||||
// Apply child's inversion
|
||||
result ^= childCondition.Invert;
|
||||
|
||||
// If any child passes, the AnyOf passes
|
||||
if (result)
|
||||
return true;
|
||||
}
|
||||
|
||||
// None of the children passed
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateDisabledState()
|
||||
{
|
||||
TraitCheckbox.Disabled = !MeetsConditions;
|
||||
|
||||
if (!MeetsConditions)
|
||||
{
|
||||
// Hide checkbox, show lock icon
|
||||
TraitCheckbox.Visible = false;
|
||||
LockIcon.Visible = true;
|
||||
|
||||
// Deselect if conditions no longer met
|
||||
if (TraitCheckbox.Pressed)
|
||||
{
|
||||
|
|
@ -161,7 +208,7 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
OnToggled?.Invoke(false);
|
||||
}
|
||||
|
||||
// Show why it's disabled
|
||||
// Add disabled styling
|
||||
AddStyleClass("TraitsEntryDisabled");
|
||||
|
||||
// Update tooltip to show failed conditions
|
||||
|
|
@ -175,8 +222,15 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
}
|
||||
else
|
||||
{
|
||||
// Show checkbox, hide lock icon
|
||||
TraitCheckbox.Visible = true;
|
||||
LockIcon.Visible = false;
|
||||
|
||||
// Remove disabled styling - stylesheet restores normal colors
|
||||
RemoveStyleClass("TraitsEntryDisabled");
|
||||
UpdateConditionTooltips(); // Reset to normal tooltips
|
||||
|
||||
// Reset to normal tooltips
|
||||
UpdateConditionTooltips();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +241,7 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
|
||||
if (!MeetsConditions)
|
||||
{
|
||||
// Prevent selection if conditions not met
|
||||
// This shouldn't happen since checkbox is hidden, but just in case
|
||||
_isUpdating = true;
|
||||
TraitCheckbox.Pressed = false;
|
||||
_isUpdating = false;
|
||||
|
|
@ -206,8 +260,6 @@ public sealed partial class TraitEntry : PanelContainer
|
|||
_isUpdating = false;
|
||||
}
|
||||
|
||||
public bool MeetsConditions { get; private set; } = true;
|
||||
|
||||
private void UpdateSelectedStyle()
|
||||
{
|
||||
if (TraitCheckbox.Pressed)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ public sealed class TraitsSheetlet<T> : Sheetlet<T> where T : PalettedStylesheet
|
|||
};
|
||||
entrySelectedBox.SetContentMarginOverride(StyleBox.Margin.All, 0);
|
||||
|
||||
var entryDisabledBox = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = Color.FromHex("#1a1a22"),
|
||||
BorderColor = Color.FromHex("#2a2a2a"),
|
||||
BorderThickness = new Thickness(1)
|
||||
};
|
||||
entryDisabledBox.SetContentMarginOverride(StyleBox.Margin.All, 0);
|
||||
|
||||
var progressBarBgBox = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = bgDark,
|
||||
|
|
@ -162,7 +170,7 @@ public sealed class TraitsSheetlet<T> : Sheetlet<T> where T : PalettedStylesheet
|
|||
|
||||
E<Button>()
|
||||
.Class("TraitsCategoryHeaderButton")
|
||||
.Prop(Button.StylePropertyStyleBox, categoryHeaderButtonBox),
|
||||
.Prop(ContainerButton.StylePropertyStyleBox, categoryHeaderButtonBox),
|
||||
|
||||
E<Label>()
|
||||
.Class("TraitsCategoryExpandIcon")
|
||||
|
|
@ -200,10 +208,15 @@ public sealed class TraitsSheetlet<T> : Sheetlet<T> where T : PalettedStylesheet
|
|||
.Panel(entryPanelBox),
|
||||
|
||||
E<PanelContainer>()
|
||||
.Class("TraitsEntryPanel")
|
||||
.Class("TraitsEntrySelected")
|
||||
.Class("TraitsEntryPanel", "TraitsEntrySelected")
|
||||
.Panel(entrySelectedBox),
|
||||
|
||||
// Disabled entry styling
|
||||
E<PanelContainer>()
|
||||
.Class("TraitsEntryPanel", "TraitsEntryDisabled")
|
||||
.Panel(entryDisabledBox)
|
||||
.Modulate(new Color(1f, 1f, 1f, 0.5f)),
|
||||
|
||||
E<Label>()
|
||||
.Class("TraitsEntryNameLabel")
|
||||
.Font(sheet.BaseFont.GetFont(11))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Linq;
|
||||
using Content.Shared._DV.CCVars;
|
||||
using Content.Shared._DV.Traits;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
|
@ -31,6 +33,8 @@ public sealed partial class TraitsTab : BoxContainer
|
|||
private string _currentSearchText = string.Empty;
|
||||
private bool _awaitingLayoutUpdate;
|
||||
|
||||
private HumanoidCharacterProfile? _profile;
|
||||
|
||||
public TraitsTab()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
|
@ -207,7 +211,7 @@ public sealed partial class TraitsTab : BoxContainer
|
|||
// If parent width is 0 (not laid out yet), defer until layout happens
|
||||
if (parentWidth > 0)
|
||||
{
|
||||
GlobalPointsBar.SetWidth = (int)(parentWidth * percentage);
|
||||
GlobalPointsBar.SetWidth = (int)((parentWidth - 2 ) * percentage);
|
||||
_awaitingLayoutUpdate = false;
|
||||
}
|
||||
else if (!_awaitingLayoutUpdate)
|
||||
|
|
@ -261,8 +265,25 @@ public sealed partial class TraitsTab : BoxContainer
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates all trait conditions based on current job and species.
|
||||
/// Call this when job or species changes in the character creator.
|
||||
/// </summary>
|
||||
/// <param name="profile">Current profile</param>
|
||||
public void UpdateConditions(HumanoidCharacterProfile profile)
|
||||
{
|
||||
_profile = profile;
|
||||
UpdateAllConditions();
|
||||
}
|
||||
|
||||
private void UpdateAllConditions()
|
||||
{
|
||||
foreach (var (_, categoryUi) in _categoryUis)
|
||||
{
|
||||
// If some fork wants to use the top selected job as well, just add that to the UpdateConditions method in the editor
|
||||
categoryUi.UpdateConditions(null, _profile?.Species, _profile?.AntagPreferences);
|
||||
}
|
||||
|
||||
RecalculateStats();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
using Content.Client._DV.UserInterfaces.BuildInfo.Controls;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
|
||||
namespace Content.Client._DV.UserInterfaces.BuildInfo;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class BuildInfoUIController : UIController
|
||||
{
|
||||
private BuildInfoWindow _changeLogWindow = default!;
|
||||
|
||||
public void OpenWindow()
|
||||
{
|
||||
EnsureWindow();
|
||||
|
||||
_changeLogWindow.OpenCentered();
|
||||
_changeLogWindow.MoveToFront();
|
||||
}
|
||||
|
||||
private void EnsureWindow()
|
||||
{
|
||||
if (_changeLogWindow is { Disposed: false })
|
||||
{
|
||||
// return; ADD THIS BACK WHEN I DON'T NEED HOT RELOAD
|
||||
}
|
||||
|
||||
_changeLogWindow = UIManager.CreateWindow<BuildInfoWindow>();
|
||||
}
|
||||
|
||||
public void ToggleWindow()
|
||||
{
|
||||
if (_changeLogWindow is { IsOpen: true })
|
||||
{
|
||||
_changeLogWindow.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<ui:BuildInfoRow xmlns="https://spacestation14.io"
|
||||
xmlns:ui="clr-namespace:Content.Client._DV.UserInterfaces.BuildInfo.Controls"
|
||||
Orientation="Horizontal">
|
||||
<Label Name="Label" HorizontalAlignment="Left" />
|
||||
<Label Name="Value" HorizontalAlignment="Right" HorizontalExpand="True" Margin="4" />
|
||||
<Button Name="CopyButton" HorizontalAlignment="Right" Text="{Loc ui-options-function-text-copy}" />
|
||||
</ui:BuildInfoRow>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client._DV.UserInterfaces.BuildInfo.Controls;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class BuildInfoRow : BoxContainer
|
||||
{
|
||||
[Dependency] private readonly IClipboardManager _clipboard = default!;
|
||||
|
||||
public string? LabelText
|
||||
{
|
||||
get => Label.Text;
|
||||
set => Label.Text = value;
|
||||
}
|
||||
|
||||
public string? ValueText
|
||||
{
|
||||
get => Value.Text;
|
||||
set => Value.Text = value;
|
||||
}
|
||||
|
||||
private void CopyValue(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
if (ValueText is { } value)
|
||||
_clipboard.SetText(value);
|
||||
}
|
||||
|
||||
public BuildInfoRow()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
CopyButton.OnPressed += CopyValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<buildInfo:BuildInfoWindow xmlns="https://spacestation14.io"
|
||||
xmlns:buildInfo="clr-namespace:Content.Client._DV.UserInterfaces.BuildInfo.Controls"
|
||||
Title="{Loc build-info-window-title}"
|
||||
Resizable="True">
|
||||
<BoxContainer Orientation="Vertical" Margin="4">
|
||||
<buildInfo:BuildInfoRow Name="EngineVersion" LabelText="{Loc build-info-engine-version-label}" />
|
||||
<buildInfo:BuildInfoRow Name="Fork" LabelText="{Loc build-info-fork-label}" />
|
||||
<buildInfo:BuildInfoRow Name="Version" LabelText="{Loc build-info-version-label}" />
|
||||
<buildInfo:BuildInfoRow Name="DownloadUrl" LabelText="{Loc build-info-download-url-label}" />
|
||||
<buildInfo:BuildInfoRow Name="BuildHash" LabelText="{Loc build-info-build-hash-label}" />
|
||||
<buildInfo:BuildInfoRow Name="BuildManifestUrl" LabelText="{Loc build-info-build-manifest-url-label}" />
|
||||
<buildInfo:BuildInfoRow Name="BuildManifestHash" LabelText="{Loc build-info-build-manifest-hash-label}" />
|
||||
</BoxContainer>
|
||||
</buildInfo:BuildInfoWindow>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Client._DV.UserInterfaces.BuildInfo.Controls;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class BuildInfoWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
public BuildInfoWindow()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
Version.ValueText = _cfg.GetCVar(CVars.BuildVersion);
|
||||
EngineVersion.ValueText = _cfg.GetCVar(CVars.BuildEngineVersion);
|
||||
Fork.ValueText = _cfg.GetCVar(CVars.BuildForkId);
|
||||
DownloadUrl.ValueText = _cfg.GetCVar(CVars.BuildDownloadUrl);
|
||||
BuildHash.ValueText = _cfg.GetCVar(CVars.BuildHash);
|
||||
BuildManifestUrl.ValueText = _cfg.GetCVar(CVars.BuildManifestUrl);
|
||||
BuildManifestHash.ValueText = _cfg.GetCVar(CVars.BuildManifestHash);
|
||||
}
|
||||
}
|
||||
|
|
@ -598,7 +598,7 @@ public sealed partial class TraitSystemTest
|
|||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
var validTraits = (HashSet<ProtoId<TraitPrototype>>)method?.Invoke(traitSys,
|
||||
new object[] { player, selectedTraits, null, null, null });
|
||||
new object[] { player, selectedTraits, null, null, null, null, new Dictionary<ProtoId<TraitPrototype>, List<string>>() });
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
|
|
@ -639,7 +639,7 @@ public sealed partial class TraitSystemTest
|
|||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
var validTraits = (HashSet<ProtoId<TraitPrototype>>)method?.Invoke(traitSys,
|
||||
new object[] { player, selectedTraits, null, null, null });
|
||||
new object[] { player, selectedTraits, null, null, null, null, new Dictionary<ProtoId<TraitPrototype>, List<string>>()});
|
||||
|
||||
Assert.That(validTraits?.Count, Is.EqualTo(2), "Should respect category maxTraits limit");
|
||||
|
||||
|
|
@ -673,7 +673,7 @@ public sealed partial class TraitSystemTest
|
|||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
var validTraits = (HashSet<ProtoId<TraitPrototype>>)method?.Invoke(traitSys,
|
||||
new object[] { player, selectedTraits, null, null, null });
|
||||
new object[] { player, selectedTraits, null, null, null, null, new Dictionary<ProtoId<TraitPrototype>, List<string>>() });
|
||||
|
||||
Assert.That(validTraits?.Count, Is.EqualTo(2), "Should respect category maxPoints limit");
|
||||
|
||||
|
|
@ -706,7 +706,7 @@ public sealed partial class TraitSystemTest
|
|||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
var validTraits = (HashSet<ProtoId<TraitPrototype>>)method?.Invoke(traitSys,
|
||||
new object[] { player, selectedTraits, null, null, null });
|
||||
new object[] { player, selectedTraits, null, null, null, null, new Dictionary<ProtoId<TraitPrototype>, List<string>>() });
|
||||
|
||||
Assert.That(validTraits?.Contains("TestTraitHasComp"), Is.True, "Trait with met condition should be valid");
|
||||
|
||||
|
|
@ -739,7 +739,7 @@ public sealed partial class TraitSystemTest
|
|||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
var validTraits = (HashSet<ProtoId<TraitPrototype>>)method?.Invoke(traitSys,
|
||||
new object[] { player, selectedTraits, null, null, null });
|
||||
new object[] { player, selectedTraits, null, null, null, null, new Dictionary<ProtoId<TraitPrototype>, List<string>>() });
|
||||
|
||||
Assert.That(validTraits?.Contains("TestTraitHasComp"),
|
||||
Is.False,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||
/// <seealso cref="ReagentDispenserComponent"/>
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed class ReagentDispenserSystem : EntitySystem
|
||||
public sealed partial class ReagentDispenserSystem : EntitySystem // Frontier - Made Partial, Auto-Label
|
||||
{
|
||||
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
|
||||
|
|
@ -41,8 +41,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ComponentStartup>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState, after: [typeof(SharedStorageSystem)]);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState, after: [typeof(SharedStorageSystem)]);
|
||||
//SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState, after: [typeof(SharedStorageSystem)]); // Frontier - Auto-Label
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage);
|
||||
|
|
@ -51,8 +51,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage);
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit, before: new[] { typeof(ItemSlotsSystem) });
|
||||
InitializeAutoLabeling(); // Frontier - Auto-Label
|
||||
}
|
||||
|
||||
private void SubscribeUpdateUiState<T>(Entity<ReagentDispenserComponent> ent, ref T ev)
|
||||
{
|
||||
UpdateUiState(ent);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ using Content.Shared.GameTicking;
|
|||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Player;
|
||||
|
|
@ -45,13 +47,16 @@ public sealed class TraitSystem : EntitySystem
|
|||
!jobProto.ApplyTraits)
|
||||
return;
|
||||
|
||||
// Get species ID for condition checking
|
||||
string? speciesId = null;
|
||||
// Use the species ID from the profile if for some reason we can't get the humanoid appearance
|
||||
ProtoId<SpeciesPrototype>? speciesId = args.Profile.Species;
|
||||
if (TryComp<HumanoidAppearanceComponent>(args.Mob, out var humanoid))
|
||||
speciesId = humanoid.Species;
|
||||
|
||||
// Track disabled traits and reasons
|
||||
var disabledTraits = new Dictionary<ProtoId<TraitPrototype>, List<string>>();
|
||||
|
||||
// Validate and collect valid traits
|
||||
var validTraits = ValidateTraits(args.Mob, args.Profile.TraitPreferences, args.Player, args.JobId, speciesId);
|
||||
var validTraits = ValidateTraits(args.Mob, args.Profile.TraitPreferences, args.Player, args.JobId, speciesId, args.Profile, disabledTraits);
|
||||
|
||||
// Apply valid traits
|
||||
foreach (var traitId in validTraits)
|
||||
|
|
@ -61,6 +66,12 @@ public sealed class TraitSystem : EntitySystem
|
|||
|
||||
ApplyTrait(args.Mob, trait);
|
||||
}
|
||||
|
||||
// Send disabled traits notification to client if any were rejected
|
||||
if (disabledTraits.Count > 0)
|
||||
{
|
||||
RaiseNetworkEvent(new DisabledTraitsEvent(disabledTraits), args.Player);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -71,7 +82,9 @@ public sealed class TraitSystem : EntitySystem
|
|||
IReadOnlySet<ProtoId<TraitPrototype>> selectedTraits,
|
||||
ICommonSession? session,
|
||||
string? jobId,
|
||||
string? speciesId)
|
||||
string? speciesId,
|
||||
HumanoidCharacterProfile? profile,
|
||||
Dictionary<ProtoId<TraitPrototype>, List<string>> disabledTraits)
|
||||
{
|
||||
var validTraits = new HashSet<ProtoId<TraitPrototype>>();
|
||||
var totalPoints = 0;
|
||||
|
|
@ -90,6 +103,7 @@ public sealed class TraitSystem : EntitySystem
|
|||
LogMan = _log,
|
||||
JobId = jobId,
|
||||
SpeciesId = speciesId,
|
||||
Profile = profile,
|
||||
};
|
||||
|
||||
foreach (var traitId in selectedTraits)
|
||||
|
|
@ -100,25 +114,31 @@ public sealed class TraitSystem : EntitySystem
|
|||
continue;
|
||||
}
|
||||
|
||||
var rejectionReasons = new List<string>();
|
||||
|
||||
// Check global trait count limit
|
||||
if (traitCount >= _maxTraitCount)
|
||||
{
|
||||
Log.Warning($"Trait {traitId} rejected: global trait count limit ({_maxTraitCount}) exceeded");
|
||||
rejectionReasons.Add(Loc.GetString("disabled-traits-reason-global-limit"));
|
||||
disabledTraits[traitId] = rejectionReasons;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check global points limit
|
||||
if (totalPoints + trait.Cost > _maxTraitPoints)
|
||||
{
|
||||
Log.Warning(
|
||||
$"Trait {traitId} rejected: global points limit ({_maxTraitPoints}) would be exceeded");
|
||||
Log.Warning($"Trait {traitId} rejected: global points limit ({_maxTraitPoints}) would be exceeded");
|
||||
rejectionReasons.Add(Loc.GetString("disabled-traits-reason-points-limit"));
|
||||
disabledTraits[traitId] = rejectionReasons;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check category limits
|
||||
if (!ValidateCategoryLimits(trait, categoryTraitCounts, categoryPointTotals))
|
||||
if (!ValidateCategoryLimits(trait, categoryTraitCounts, categoryPointTotals, rejectionReasons))
|
||||
{
|
||||
Log.Warning($"Trait {traitId} rejected: category limits exceeded");
|
||||
disabledTraits[traitId] = rejectionReasons;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -130,6 +150,11 @@ public sealed class TraitSystem : EntitySystem
|
|||
if (trait.Conflicts.Contains(validTraitId))
|
||||
{
|
||||
Log.Warning($"Trait {traitId} rejected: conflicts with {validTraitId}");
|
||||
if (_prototype.TryIndex(validTraitId, out var conflictTrait))
|
||||
{
|
||||
rejectionReasons.Add(Loc.GetString("disabled-traits-reason-conflict",
|
||||
("trait", Loc.GetString(conflictTrait.Name))));
|
||||
}
|
||||
hasConflict = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -139,18 +164,24 @@ public sealed class TraitSystem : EntitySystem
|
|||
validTrait.Conflicts.Contains(traitId))
|
||||
{
|
||||
Log.Warning($"Trait {traitId} rejected: {validTraitId} conflicts with it");
|
||||
rejectionReasons.Add(Loc.GetString("disabled-traits-reason-conflict",
|
||||
("trait", Loc.GetString(validTrait.Name))));
|
||||
hasConflict = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasConflict)
|
||||
{
|
||||
disabledTraits[traitId] = rejectionReasons;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check all conditions
|
||||
if (!CheckConditions(trait, conditionCtx))
|
||||
if (!CheckConditions(trait, conditionCtx, rejectionReasons))
|
||||
{
|
||||
Log.Warning($"Trait {traitId} rejected: conditions not met");
|
||||
disabledTraits[traitId] = rejectionReasons;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +207,8 @@ public sealed class TraitSystem : EntitySystem
|
|||
private bool ValidateCategoryLimits(
|
||||
TraitPrototype trait,
|
||||
Dictionary<ProtoId<TraitCategoryPrototype>, int> categoryTraitCounts,
|
||||
Dictionary<ProtoId<TraitCategoryPrototype>, int> categoryPointTotals)
|
||||
Dictionary<ProtoId<TraitCategoryPrototype>, int> categoryPointTotals,
|
||||
List<string> rejectionReasons)
|
||||
{
|
||||
if (!_prototype.TryIndex(trait.Category, out var category))
|
||||
return true; // Unknown category, allow it
|
||||
|
|
@ -186,11 +218,19 @@ public sealed class TraitSystem : EntitySystem
|
|||
|
||||
// Check category trait count limit
|
||||
if (category.MaxTraits.HasValue && currentCount >= category.MaxTraits.Value)
|
||||
{
|
||||
rejectionReasons.Add(Loc.GetString("disabled-traits-reason-category-limit",
|
||||
("category", Loc.GetString(category.Name))));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check category points limit
|
||||
if (category.MaxPoints.HasValue && currentPoints + trait.Cost > category.MaxPoints.Value)
|
||||
{
|
||||
rejectionReasons.Add(Loc.GetString("disabled-traits-reason-category-points",
|
||||
("category", Loc.GetString(category.Name))));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -198,12 +238,20 @@ public sealed class TraitSystem : EntitySystem
|
|||
/// <summary>
|
||||
/// Checks all conditions on a trait.
|
||||
/// </summary>
|
||||
private bool CheckConditions(TraitPrototype trait, TraitConditionContext ctx)
|
||||
private bool CheckConditions(TraitPrototype trait, TraitConditionContext ctx, List<string> rejectionReasons)
|
||||
{
|
||||
foreach (var condition in trait.Conditions)
|
||||
{
|
||||
if (!condition.Evaluate(ctx))
|
||||
return false;
|
||||
if (condition.Evaluate(ctx))
|
||||
continue;
|
||||
|
||||
// Get human-readable reason from the condition
|
||||
var tooltip = condition.GetTooltip(ctx.Proto, Loc);
|
||||
|
||||
if (!string.IsNullOrEmpty(tooltip))
|
||||
rejectionReasons.Add(tooltip);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
namespace Content.Server.Chemistry.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Frontier - Extends ReagentDispenserComponent.
|
||||
///
|
||||
/// Used primarily for the auto-labeling functionality.
|
||||
/// </summary>
|
||||
public sealed partial class ReagentDispenserComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns if the component's entity has the ability to auto-label.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool CanAutoLabel = true;
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the entity has auto-labeling toggled on.
|
||||
/// Will have no effect if <see cref="CanAutoLabel"/> is false.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public bool AutoLabelToggle = true;
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
using Content.Server.Chemistry.Components;
|
||||
using Robust.Shared.Containers;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Labels.EntitySystems;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
|
||||
public sealed partial class ReagentDispenserSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly LabelSystem _label = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
|
||||
private void InitializeAutoLabeling()
|
||||
{
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(OnEntInserted, after: [typeof(SharedStorageSystem)]);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, GetVerbsEvent<ExamineVerb>>(OnExamineVerb);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ExaminedEvent>(OnExamined);
|
||||
}
|
||||
|
||||
private void OnEntInserted(Entity<ReagentDispenserComponent> ent, ref EntInsertedIntoContainerMessage ev)
|
||||
{
|
||||
TryApplyAutoLabel(ent, ev.Entity);
|
||||
SubscribeUpdateUiState(ent, ref ev);
|
||||
}
|
||||
|
||||
private void OnExamineVerb(Entity<ReagentDispenserComponent> ent, ref GetVerbsEvent<ExamineVerb> args)
|
||||
{
|
||||
if (!ent.Comp.CanAutoLabel)
|
||||
return;
|
||||
|
||||
args.Verbs.Add(new ExamineVerb()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
SetAutoLabel(ent, !ent.Comp.AutoLabelToggle);
|
||||
},
|
||||
Text = ent.Comp.AutoLabelToggle ?
|
||||
Loc.GetString("reagent-dispenser-component-set-auto-label-off-verb")
|
||||
: Loc.GetString("reagent-dispenser-component-set-auto-label-on-verb"),
|
||||
Priority = -1, // Not important, low priority.
|
||||
CloseMenu = true
|
||||
});
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<ReagentDispenserComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
if (!args.IsInDetailsRange || !ent.Comp.CanAutoLabel)
|
||||
return;
|
||||
|
||||
if (ent.Comp.AutoLabelToggle)
|
||||
args.PushMarkup(Loc.GetString("reagent-dispenser-component-examine-auto-label-on"));
|
||||
else
|
||||
args.PushMarkup(Loc.GetString("reagent-dispenser-component-examine-auto-label-off"));
|
||||
}
|
||||
|
||||
private void SetAutoLabel(Entity<ReagentDispenserComponent> ent, bool autoLabel)
|
||||
{
|
||||
if (!ent.Comp.CanAutoLabel)
|
||||
return;
|
||||
|
||||
ent.Comp.AutoLabelToggle = autoLabel;
|
||||
|
||||
var popupMessage = autoLabel ? Loc.GetString("reagent-dispenser-component-verb-auto-label-turn-on")
|
||||
: Loc.GetString("reagent-dispenser-component-verb-auto-label-turn-off");
|
||||
|
||||
_popup.PopupEntity(popupMessage, ent.Owner);
|
||||
}
|
||||
|
||||
private void TryApplyAutoLabel(Entity<ReagentDispenserComponent> dispenser, EntityUid insertedEntity)
|
||||
{
|
||||
if (!dispenser.Comp.CanAutoLabel)
|
||||
return;
|
||||
|
||||
if (!dispenser.Comp.AutoLabelToggle)
|
||||
return;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetDrainableSolution(insertedEntity, out _, out var sol))
|
||||
return;
|
||||
|
||||
if (sol.GetPrimaryReagentId() is not { } reagentProtoId)
|
||||
return;
|
||||
|
||||
if (!_prototypeManager.TryIndex<ReagentPrototype>(reagentProtoId.Prototype, out var reagent))
|
||||
return;
|
||||
|
||||
var reagentQuantity = sol.GetReagentQuantity(reagentProtoId);
|
||||
var totalQuantity = sol.Volume;
|
||||
if (reagentQuantity == totalQuantity)
|
||||
_label.Label(insertedEntity, reagent.LocalizedName);
|
||||
else
|
||||
_label.Label(insertedEntity, Loc.GetString("reagent-dispenser-component-impure-auto-label", ("reagent", reagent.LocalizedName), ("purity", 100.0f * reagentQuantity / totalQuantity)));
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ using Robust.Shared.Utility;
|
|||
|
||||
namespace Content.Shared.Clothing.EntitySystems;
|
||||
|
||||
public sealed class ToggleableClothingSystem : EntitySystem
|
||||
public sealed partial class ToggleableClothingSystem : EntitySystem // DeltaV - Made Partial
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly INetManager _netMan = default!;
|
||||
|
|
@ -140,10 +140,12 @@ public sealed class ToggleableClothingSystem : EntitySystem
|
|||
|| toggleCom.Container == null)
|
||||
return;
|
||||
|
||||
var parent = Transform(uid).ParentUid; // DeltaV - Allow hats under toggleable helms
|
||||
if (!_inventorySystem.TryUnequip(Transform(uid).ParentUid, toggleCom.Slot, force: true))
|
||||
return;
|
||||
|
||||
_containerSystem.Insert(uid, toggleCom.Container);
|
||||
TryEquipUnderClothing(parent, component); // DeltaV - Allow hats under toggleable helms
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
|
|
@ -156,11 +158,17 @@ public sealed class ToggleableClothingSystem : EntitySystem
|
|||
if (_timing.ApplyingState)
|
||||
return;
|
||||
|
||||
var wasAttachedUnequipped = false; // DeltaV - Allow hats under toggleable helms
|
||||
|
||||
// If the attached clothing is not currently in the container, this just assumes that it is currently equipped.
|
||||
// This should maybe double check that the entity currently in the slot is actually the attached clothing, but
|
||||
// if its not, then something else has gone wrong already...
|
||||
if (component.Container != null && component.Container.ContainedEntity == null && component.ClothingUid != null)
|
||||
_inventorySystem.TryUnequip(args.Equipee, component.Slot, force: true, triggerHandContact: true);
|
||||
wasAttachedUnequipped = _inventorySystem.TryUnequip(args.Equipee, component.Slot, force: true, triggerHandContact: true); // DeltaV - Allow hats under toggleable helms
|
||||
|
||||
// DeltaV - If the toggleable helm was uneqipped, try to equip whats in the under clothing container
|
||||
if (wasAttachedUnequipped && !TryEquipUnderClothing(args.Equipee, component))
|
||||
TryDropUnderClothing(component);
|
||||
}
|
||||
|
||||
private void OnRemoveToggleable(EntityUid uid, ToggleableClothingComponent component, ComponentRemove args)
|
||||
|
|
@ -240,15 +248,30 @@ public sealed class ToggleableClothingSystem : EntitySystem
|
|||
return;
|
||||
|
||||
var parent = Transform(target).ParentUid;
|
||||
|
||||
// Begin DeltaV - Allow hats under toggleable helms!
|
||||
var wasAttachedUnequipped = false; // We want to track if the toggleable item was unequipped, assume false for now.
|
||||
|
||||
if (component.Container.ContainedEntity == null)
|
||||
_inventorySystem.TryUnequip(user, parent, component.Slot, force: true);
|
||||
else if (_inventorySystem.TryGetSlotEntity(parent, component.Slot, out var existing))
|
||||
{
|
||||
_popupSystem.PopupClient(Loc.GetString("toggleable-clothing-remove-first", ("entity", existing)),
|
||||
user, user);
|
||||
}
|
||||
wasAttachedUnequipped = _inventorySystem.TryUnequip(user, parent, component.Slot, force: true);
|
||||
|
||||
else
|
||||
{
|
||||
if (_inventorySystem.TryGetSlotEntity(parent, component.Slot, out var existing)
|
||||
&& !TryStoreUnderClothing(existing.Value, component))
|
||||
{
|
||||
_popupSystem.PopupClient(Loc.GetString("toggleable-clothing-remove-first", ("entity", existing)),
|
||||
user, user);
|
||||
return;
|
||||
}
|
||||
|
||||
_inventorySystem.TryEquip(user, parent, component.ClothingUid.Value, component.Slot, triggerHandContact: true);
|
||||
}
|
||||
|
||||
// If the toggleable clothing was uneqipped, try to equip whats in the under clothing container
|
||||
if (wasAttachedUnequipped && !TryEquipUnderClothing(user, parent, component))
|
||||
TryDropUnderClothing(component);
|
||||
// END DeltaV
|
||||
}
|
||||
|
||||
private void OnGetActions(EntityUid uid, ToggleableClothingComponent component, GetItemActionsEvent args)
|
||||
|
|
@ -264,6 +287,7 @@ public sealed class ToggleableClothingSystem : EntitySystem
|
|||
private void OnInit(EntityUid uid, ToggleableClothingComponent component, ComponentInit args)
|
||||
{
|
||||
component.Container = _containerSystem.EnsureContainer<ContainerSlot>(uid, component.ContainerId);
|
||||
component.UnderClothingContainer = _containerSystem.EnsureContainer<ContainerSlot>(uid, component.UnderClothingContainerId); // Wayfarer - Allow hats under toggleable helms!
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -141,6 +141,12 @@ public sealed partial class DCCVars
|
|||
public static readonly CVarDef<int> MaxTraitPoints =
|
||||
CVarDef.Create("traits.max_points", 15, CVar.SERVER | CVar.REPLICATED);
|
||||
|
||||
/// <summary>
|
||||
/// Whether to skip showing the disabled traits popup when spawning.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> SkipDisabledTraitsPopup =
|
||||
CVarDef.Create("traits.skip_disabled_traits_popup", false, CVar.CLIENT | CVar.ARCHIVE);
|
||||
|
||||
/*
|
||||
* Feedback webhook
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Shared.Clothing.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Extends upstream's ToggleableClothingComponent.
|
||||
///
|
||||
/// This portion of the ToggleableClothingComponent stores the clothing item under the toggled piece.
|
||||
/// Currently only supports a single piece of clothing, but pretty much all entities with ToggleableClothing
|
||||
/// are just hardsuit helmets.
|
||||
/// </summary>
|
||||
public sealed partial class ToggleableClothingComponent : Component
|
||||
{
|
||||
public const string DefaultUnderneathClothingContainerId = "toggleable-under-clothing";
|
||||
|
||||
/// <summary>
|
||||
/// The container ID of <see cref="UnderClothingContainer"/>.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public string UnderClothingContainerId = DefaultUnderneathClothingContainerId;
|
||||
|
||||
/// <summary>
|
||||
/// The container where the item that the toggled clothing replaced is put.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public ContainerSlot? UnderClothingContainer;
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
using Content.Shared.Clothing.Components;
|
||||
|
||||
namespace Content.Shared.Clothing.EntitySystems;
|
||||
|
||||
/// <summary>
|
||||
/// Extends upstream's ToggleableClothingSystem.
|
||||
///
|
||||
/// Provides methods that store and re-equip clothing when toggleable clothing is put on or taken off.
|
||||
/// Sidenote; god, I hate naming things.
|
||||
/// </summary>
|
||||
public sealed partial class ToggleableClothingSystem : EntitySystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to store clothing in <see cref="ToggleableClothingComponent.UnderClothingContainer"/>
|
||||
/// </summary>
|
||||
/// <param name="clothing">The clothing to be stored.</param>
|
||||
/// <param name="component">The ToggleableClothingComponent to store the clothing in.</param>
|
||||
/// <returns>True if clothing can be inserted and was inserted.</returns>
|
||||
private bool TryStoreUnderClothing(EntityUid clothing, ToggleableClothingComponent component)
|
||||
{
|
||||
if (component.UnderClothingContainer == null)
|
||||
return false;
|
||||
|
||||
// There is already something in there? Either way, return false because we
|
||||
// expect one thing.
|
||||
if (component.UnderClothingContainer.ContainedEntity.HasValue)
|
||||
return false;
|
||||
|
||||
return _containerSystem.Insert(clothing, component.UnderClothingContainer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to equip any stored clothing kept in <see cref="ToggleableClothingComponent.UnderClothingContainer"/>.
|
||||
/// </summary>
|
||||
/// <param name="actor">The person wearing the ToggleableClothing.</param>
|
||||
/// <param name="component">The ToggleableClothingComponent to check for an stored items.</param>
|
||||
/// <returns>True if something was equipped OR if there is nothing to equip.</returns>
|
||||
private bool TryEquipUnderClothing(EntityUid actor, ToggleableClothingComponent component)
|
||||
{
|
||||
return TryEquipUnderClothing(actor, actor, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to equip any stored clothing kept in <see cref="ToggleableClothingComponent.UnderClothingContainer"/>.
|
||||
/// </summary>
|
||||
/// <param name="actor">The person trying to equip the clothing.</param>
|
||||
/// <param name="target">The person who to equip the clothing on.</param>
|
||||
/// <param name="component">The ToggleableClothingComponent to check for an stored items.</param>
|
||||
/// <returns>True if something was equipped OR if there is nothing to equip.</returns>
|
||||
private bool TryEquipUnderClothing(EntityUid actor, EntityUid target, ToggleableClothingComponent component)
|
||||
{
|
||||
// if there is no UnderClothingContainer, then why are we here?
|
||||
if (component.UnderClothingContainer == null)
|
||||
return true;
|
||||
|
||||
// if nothing is contained so technically dropping nothing counts as a success
|
||||
if (!component.UnderClothingContainer.ContainedEntity.HasValue)
|
||||
return true;
|
||||
|
||||
return _inventorySystem.TryEquip(actor, target, component.UnderClothingContainer.ContainedEntity.Value, component.Slot, force: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to equip any stored clothing kept in <see cref="ToggleableClothingComponent.UnderClothingContainer"/>.
|
||||
/// </summary>
|
||||
/// <param name="actor">The person trying to equip the clothing.</param>
|
||||
/// <param name="component">The AttachedClothing of the ToggleableClothing to check for an stored items.</param>
|
||||
/// <returns>True if something was equipped OR if there is nothing to equip.</returns>
|
||||
private bool TryEquipUnderClothing(EntityUid actor, AttachedClothingComponent component)
|
||||
{
|
||||
if (!TryComp<ToggleableClothingComponent>(component.AttachedUid, out var toggleableComp))
|
||||
return false;
|
||||
|
||||
return TryEquipUnderClothing(actor, toggleableComp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to drop any stored clothing kept in <see cref="ToggleableClothingComponent.UnderClothingContainer"/>.
|
||||
/// </summary>
|
||||
/// <param name="component">The ToggleableClothingComponent that is holding the item to be dropped.</param>
|
||||
/// <returns>True if there is not an item to be dropped OR it was successfully dropped.</returns>
|
||||
private bool TryDropUnderClothing(ToggleableClothingComponent component)
|
||||
{
|
||||
// if there is no UnderClothingContainer, then why are we here?
|
||||
if (component.UnderClothingContainer == null)
|
||||
return true;
|
||||
|
||||
// if nothing is contained so technically dropping nothing counts as a success
|
||||
if (!component.UnderClothingContainer.ContainedEntity.HasValue)
|
||||
return true;
|
||||
|
||||
return _containerSystem.TryRemoveFromContainer(component.UnderClothingContainer.ContainedEntity.Value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using Content.Shared._DV.Traits.Assorted;
|
||||
using Content.Shared.Cloning.Events;
|
||||
|
||||
namespace Content.Shared._DV.Medical;
|
||||
|
||||
public sealed class UncloneableSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<UncloneableComponent, CloningAttemptEvent>(OnCloningAttempt);
|
||||
}
|
||||
|
||||
private void OnCloningAttempt(Entity<UncloneableComponent> ent, ref CloningAttemptEvent args)
|
||||
{
|
||||
args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._DV.Traits.Assorted;
|
||||
|
||||
/// <summary>
|
||||
/// This entity cannot be cloned but can still be revived by defibrillators.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class UncloneableComponent : Component;
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._DV.Traits.Conditions;
|
||||
|
||||
/// <summary>
|
||||
/// Condition that passes if ANY of the child conditions pass.
|
||||
/// Use this to create "must meet at least one of these requirements" checks.
|
||||
/// </summary>
|
||||
public sealed partial class AnyOfCondition : BaseTraitCondition
|
||||
{
|
||||
/// <summary>
|
||||
/// List of conditions to check. Passes if any condition evaluates to true.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public List<BaseTraitCondition> Conditions = new();
|
||||
|
||||
protected override bool EvaluateImplementation(TraitConditionContext ctx)
|
||||
{
|
||||
// Inversion doesn't make sense for AnyOfCondition - use inverted child conditions instead
|
||||
if (Invert)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"AnyOfCondition does not support Invert. To require none of the conditions, " +
|
||||
"invert the individual child conditions instead.");
|
||||
}
|
||||
|
||||
// Empty list should fail
|
||||
if (Conditions.Count == 0)
|
||||
return false;
|
||||
|
||||
// Return true if ANY condition passes
|
||||
foreach (var condition in Conditions)
|
||||
{
|
||||
if (condition.Evaluate(ctx))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GetTooltip(IPrototypeManager proto, ILocalizationManager loc)
|
||||
{
|
||||
if (Conditions.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var requirements = new List<string>();
|
||||
|
||||
foreach (var condition in Conditions)
|
||||
{
|
||||
var tooltip = condition.GetTooltip(proto, loc);
|
||||
if (!string.IsNullOrEmpty(tooltip))
|
||||
requirements.Add(tooltip);
|
||||
}
|
||||
|
||||
if (requirements.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
// AAAAAAAAAAA
|
||||
var joinedRequirements = string.Join("\n• ", requirements);
|
||||
|
||||
// Handle inversion in tooltip (ANY becomes NONE when inverted)
|
||||
return Loc.GetString("trait-condition-any-of", ("requirements", joinedRequirements));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Shared.Preferences;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
|
@ -57,4 +58,9 @@ public sealed class TraitConditionContext
|
|||
/// The species ID of the player, if available.
|
||||
/// </summary>
|
||||
public string? SpeciesId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="HumanoidCharacterProfile"/> of the player, if available.
|
||||
/// </summary>
|
||||
public HumanoidCharacterProfile? Profile { get; init; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ public sealed partial class HasCompCondition : BaseTraitCondition
|
|||
[DataField(required: true, customTypeSerializer: typeof(ComponentNameSerializer))]
|
||||
public string Component = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The tooltip text to display, if any.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? Tooltip;
|
||||
|
||||
protected override bool EvaluateImplementation(TraitConditionContext ctx)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Component))
|
||||
|
|
@ -35,6 +41,10 @@ public sealed partial class HasCompCondition : BaseTraitCondition
|
|||
|
||||
public override string GetTooltip(IPrototypeManager proto, ILocalizationManager loc)
|
||||
{
|
||||
// If there's a custom tooltip supplied, use that
|
||||
if (Tooltip is not null)
|
||||
return Loc.GetString(Tooltip);
|
||||
|
||||
// No tooltip for this condition since we're dealing with comps
|
||||
return string.Empty;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._DV.Traits.Conditions;
|
||||
|
||||
/// <summary>
|
||||
/// Condition that checks if the player has enabled a specific antag preference.
|
||||
/// </summary>
|
||||
public sealed partial class IsAntagEligibleCondition : BaseTraitCondition
|
||||
{
|
||||
/// <summary>
|
||||
/// The antag prototype ID to check for eligibility.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ProtoId<AntagPrototype> Antag;
|
||||
|
||||
protected override bool EvaluateImplementation(TraitConditionContext ctx)
|
||||
{
|
||||
if (ctx.Profile == null)
|
||||
return false;
|
||||
|
||||
// Check if the player has this antag preference enabled
|
||||
return ctx.Profile.AntagPreferences.Contains(Antag);
|
||||
}
|
||||
|
||||
public override string GetTooltip(IPrototypeManager proto, ILocalizationManager loc)
|
||||
{
|
||||
if (!proto.TryIndex(Antag, out var antagProto))
|
||||
return string.Empty;
|
||||
|
||||
var antagName = loc.GetString(antagProto.Name);
|
||||
|
||||
return Invert
|
||||
? loc.GetString("trait-condition-antag-not", ("antag", antagName))
|
||||
: loc.GetString("trait-condition-antag-is", ("antag", antagName));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._DV.Traits;
|
||||
|
||||
/// <summary>
|
||||
/// Sent from server to client when a player spawns with traits that were disabled due to unmet conditions.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DisabledTraitsEvent(Dictionary<ProtoId<TraitPrototype>, List<string>> disabledTraits)
|
||||
: EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Dictionary mapping disabled trait IDs to lists of reasons why they were disabled.
|
||||
/// </summary>
|
||||
public Dictionary<ProtoId<TraitPrototype>, List<string>> DisabledTraits = disabledTraits;
|
||||
}
|
||||
|
|
@ -1,100 +1,4 @@
|
|||
Entries:
|
||||
- author: Proxysseia
|
||||
changes:
|
||||
- message: reduced the emote cooldown to 3s from 5s
|
||||
type: Tweak
|
||||
id: 1594
|
||||
time: '2025-08-14T10:25:33.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4185
|
||||
- author: kotobdev
|
||||
changes:
|
||||
- message: Blinking is now an emote, and plays a silly noise.
|
||||
type: Add
|
||||
id: 1595
|
||||
time: '2025-08-14T20:57:10.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4155
|
||||
- author: Quanteey
|
||||
changes:
|
||||
- message: Merged upstream until June 20.
|
||||
type: Add
|
||||
id: 1596
|
||||
time: '2025-08-14T17:21:58.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4142
|
||||
- author: NoElkaTheGod
|
||||
changes:
|
||||
- message: Cosmic cult can now create a multispectral inhibitor, which jams any
|
||||
radio communication in a large area, by putting a telecommunication server on
|
||||
a glyph of cessation.
|
||||
type: Add
|
||||
id: 1597
|
||||
time: '2025-08-14T23:51:18.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4181
|
||||
- author: NoElkaTheGod
|
||||
changes:
|
||||
- message: Entropy is now less efficient for progressing the cosmic cult's monument.
|
||||
type: Tweak
|
||||
- message: Siphoning entropy now deals it's damage much slower, and the total amount
|
||||
is randomized to make it less metagameable.
|
||||
type: Tweak
|
||||
id: 1598
|
||||
time: '2025-08-15T06:24:29.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4099
|
||||
- author: Proxysseia
|
||||
changes:
|
||||
- message: IK30 has had its fire rate halved and now requires two hands to fire
|
||||
type: Tweak
|
||||
id: 1599
|
||||
time: '2025-08-15T18:54:13.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4189
|
||||
- author: NoElkaTheGod
|
||||
changes:
|
||||
- message: Cosmic cult win conditions are more fair now. Check PR for details.
|
||||
type: Tweak
|
||||
id: 1600
|
||||
time: '2025-08-16T12:24:12.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4156
|
||||
- author: Proxysseia
|
||||
changes:
|
||||
- message: Laser Rifles now deal more damage
|
||||
type: Tweak
|
||||
- message: Laser Cannons now deal more damage
|
||||
type: Tweak
|
||||
- message: Laser Rifles and their practice counterparts can be shot more before
|
||||
needing to recharge
|
||||
type: Tweak
|
||||
id: 1601
|
||||
time: '2025-08-16T18:16:57.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4198
|
||||
- author: kotobdev
|
||||
changes:
|
||||
- message: Mantises now get two mindbreaker pills in their locker.
|
||||
type: Add
|
||||
id: 1602
|
||||
time: '2025-08-17T00:12:24.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4207
|
||||
- author: Quanteey
|
||||
changes:
|
||||
- message: The AI shop is now properly localized
|
||||
type: Fix
|
||||
id: 1603
|
||||
time: '2025-08-17T12:56:47.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4210
|
||||
- author: Quanteey
|
||||
changes:
|
||||
- message: Fixed IK-30 and IK-60 spread glitches when wielded
|
||||
type: Fix
|
||||
id: 1604
|
||||
time: '2025-08-17T21:31:39.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4212
|
||||
- author: Proxysseia
|
||||
changes:
|
||||
- message: Emergency Lasers now come in boxes of 10
|
||||
type: Tweak
|
||||
- message: Emergency Lasers now do almost as much damage as a real gun
|
||||
type: Tweak
|
||||
id: 1605
|
||||
time: '2025-08-18T10:13:26.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4197
|
||||
- author: NoElkaTheGod
|
||||
changes:
|
||||
- message: Fixed ghosts not being able to see things like the monument or telegnostic
|
||||
|
|
@ -4477,4 +4381,104 @@
|
|||
id: 2093
|
||||
time: '2026-01-23T19:35:58.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5243
|
||||
- author: MilonPL
|
||||
changes:
|
||||
- message: The traits points bar will now show up correctly.
|
||||
type: Fix
|
||||
id: 2094
|
||||
time: '2026-01-24T20:55:31.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5275
|
||||
- author: MilonPL
|
||||
changes:
|
||||
- message: The uncloneable trait no longer prevents your character from getting
|
||||
revived by defibrillators.
|
||||
type: Fix
|
||||
id: 2095
|
||||
time: '2026-01-24T21:29:58.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5273
|
||||
- author: Halo3moth
|
||||
changes:
|
||||
- message: The energy magnums "magnum" rounds no longer pierce windows
|
||||
type: Fix
|
||||
id: 2096
|
||||
time: '2026-01-25T13:48:54.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5270
|
||||
- author: Toby222
|
||||
changes:
|
||||
- message: Added buttons for build info and credits to the escape menu
|
||||
type: Tweak
|
||||
id: 2097
|
||||
time: '2026-01-25T14:42:09.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5260
|
||||
- author: MilonPL
|
||||
changes:
|
||||
- message: Added the "Marked as Protected" trait which makes you immune to becoming
|
||||
a target objective.
|
||||
type: Add
|
||||
id: 2098
|
||||
time: '2026-01-25T16:30:18.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5274
|
||||
- author: AeraAuling
|
||||
changes:
|
||||
- message: Shadow damage no longer removes all your blood immediately
|
||||
type: Tweak
|
||||
id: 2099
|
||||
time: '2026-01-25T16:31:20.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5268
|
||||
- author: ShepardToTheStars
|
||||
changes:
|
||||
- message: You can now toggle your hardsuit helmet on over your hat or beret!
|
||||
type: Add
|
||||
id: 2100
|
||||
time: '2026-01-25T16:31:55.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5263
|
||||
- author: Pharaz4
|
||||
changes:
|
||||
- message: Bingus can no longer drink the **ENTIRE** keg.
|
||||
type: Fix
|
||||
- message: You can eat rice dishes with chopsticks now.
|
||||
type: Add
|
||||
- message: Fixed Smartfridge visuals always showing their wire panels open.
|
||||
type: Fix
|
||||
- message: Projectiles and Mr. Butlertion are now insulated against wizardry.
|
||||
type: Fix
|
||||
- message: Wording fix to initial infected's prompt. It now states that they can
|
||||
explicitly kill people.
|
||||
type: Fix
|
||||
id: 2101
|
||||
time: '2026-01-25T16:31:39.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5278
|
||||
- author: MantasDab360, whatston3, ShepardToTheStars
|
||||
changes:
|
||||
- message: Chemical Dispenser can now toggle between auto labeling!
|
||||
type: Add
|
||||
id: 2102
|
||||
time: '2026-01-25T16:46:12.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5261
|
||||
- author: keekee38
|
||||
changes:
|
||||
- message: a new compact submachine gun for security should be shipping in soon!
|
||||
type: Add
|
||||
- message: added machine pistol magazines to the security techfab's recipes.
|
||||
type: Tweak
|
||||
- message: added rubber SMG mags to the security techfab.
|
||||
type: Tweak
|
||||
id: 2103
|
||||
time: '2026-01-26T10:46:23.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5212
|
||||
- author: Halo3moth
|
||||
changes:
|
||||
- message: Security long coats have been resprited to be more in line with other
|
||||
security gear. (we ran out of red dye)
|
||||
type: Tweak
|
||||
id: 2104
|
||||
time: '2026-01-27T05:50:41.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5288
|
||||
- author: EmberAstra
|
||||
changes:
|
||||
- message: Plasteel can now be printed at the Engineering Techfab.
|
||||
type: Add
|
||||
id: 2105
|
||||
time: '2026-01-27T16:05:20.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5284
|
||||
Order: 1
|
||||
|
|
|
|||
|
|
@ -695,4 +695,27 @@
|
|||
id: 81
|
||||
time: '2026-01-20T23:30:07.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5241
|
||||
- author: Colin-Tel
|
||||
changes:
|
||||
- message: 'Division: Added AI cameras on their own network, cyborg control computer,
|
||||
a medical crash cart, and AI restoration computers.'
|
||||
type: Add
|
||||
- message: 'Division: Added more weapons to the armory.'
|
||||
type: Add
|
||||
- message: 'Division: Salvage''s gun safe is now in the LO office.'
|
||||
type: Tweak
|
||||
- message: 'Division: The arrivals area now fits the arrivals shuttle, and both
|
||||
arrivals and evac have anti-meteor zones put on them.'
|
||||
type: Tweak
|
||||
id: 82
|
||||
time: '2026-01-24T20:16:21.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5271
|
||||
- author: Fieldcommand
|
||||
changes:
|
||||
- message: 'Pebble: CJ has a bathroom, toilets have loot chance, and other small
|
||||
tweaks.'
|
||||
type: Tweak
|
||||
id: 83
|
||||
time: '2026-01-25T00:13:10.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5164
|
||||
Order: 3
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
zombie-bioterrorist-role-greeting = You are a syndicate sponsored bioterrorist sent to overtake the station by use of the Romerol virus. Coordinate with your team, get supplies and prepare for your eventual transformation. Death to nanotrasen!
|
||||
zombie-bioterrorist-romerol-active = The romerol in your blood is now active, you are ready to transform!
|
||||
zombie-patientzero-role-greeting = You are an initial infected. Get supplies and prepare for your eventual transformation. You may sabotage the station and kill crew before turning. Your goal is to overtake the station while infecting as many people as possible.
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ trait-category-disabilities = Disabilities
|
|||
trait-category-medical = Medical
|
||||
trait-category-mental = Mental
|
||||
trait-category-accents = Accents
|
||||
trait-category-meta = Meta
|
||||
|
|
|
|||
|
|
@ -5,6 +5,22 @@ trait-editor-search-placeholder = Search traits...
|
|||
trait-editor-footer-hint = Hover over traits for details
|
||||
trait-editor-footer-info = Negative costs grant bonus points
|
||||
|
||||
## Disabled Traits Popup
|
||||
disabled-traits-popup-title = Traits Disabled
|
||||
disabled-traits-popup-label = Traits Disabled
|
||||
disabled-traits-popup-message = Some of your selected traits could not be applied because they did not meet the required conditions.
|
||||
disabled-traits-popup-list-header = The following traits were disabled:
|
||||
disabled-traits-popup-reason = • {$reason}
|
||||
disabled-traits-popup-skip-checkbox = Don't show this again
|
||||
disabled-traits-popup-close-button = Close
|
||||
|
||||
## Disabled Traits Reasons
|
||||
disabled-traits-reason-global-limit = Global trait limit reached
|
||||
disabled-traits-reason-points-limit = Not enough trait points remaining
|
||||
disabled-traits-reason-category-limit = Category "{$category}" trait limit reached
|
||||
disabled-traits-reason-category-points = Category "{$category}" points limit reached
|
||||
disabled-traits-reason-conflict = Conflicts with selected trait: {$trait}
|
||||
|
||||
## Category suffixes
|
||||
trait-category-traits = {$selected} / {$max} traits
|
||||
trait-category-traits-unlimited = {$selected} traits
|
||||
|
|
@ -16,6 +32,10 @@ trait-conditions-tooltip = [bold]Requirements:[/bold]
|
|||
trait-conditions-not-met-tooltip = Requirements not met:
|
||||
{$requirements}
|
||||
|
||||
## Composite conditions
|
||||
trait-condition-any-of = Any of the following must be true:
|
||||
• {$requirements}
|
||||
|
||||
## Species conditions
|
||||
trait-condition-species-is = You must be a [color=yellow]{$species}[/color].
|
||||
trait-condition-species-not = You must not be a [color=yellow]{$species}[/color].
|
||||
|
|
@ -27,3 +47,10 @@ trait-condition-job-not = You must not be a [color={$color}]{$job}[/color].
|
|||
## Department conditions
|
||||
trait-condition-department-is = You must be in the [color={$color}]{$department}[/color] department.
|
||||
trait-condition-department-not = You must not be in the [color={$color}]{$department}[/color] department.
|
||||
|
||||
## HasComp borg conditions
|
||||
trait-condition-borg-not = You must not be a [color=yellow]borg[/color].
|
||||
|
||||
# Antag conditions
|
||||
trait-condition-antag-is = Must be eligible for [color=red]{$antag}[/color] antag role.
|
||||
trait-condition-antag-not = Must not be eligible for [color=red]{$antag}[/color] antag role.
|
||||
|
|
|
|||
|
|
@ -64,3 +64,6 @@ trait-redshirt-desc =
|
|||
|
||||
trait-anglish-name = Anglish tung
|
||||
trait-anglish-desc = Your tung is of the Saxons, and say unlike others aboard this skyship.
|
||||
|
||||
trait-protected-name = Marked as Protected
|
||||
trait-protected-desc = Due to your position, value, or circumstances, your survival is considered preferable. You won't be targeted by kill objectives.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
build-info-window-title = Build Info
|
||||
build-info-button = Build Info
|
||||
build-info-tooltip = Metadata about the game you're running
|
||||
build-info-version-label = Game Version:
|
||||
build-info-engine-version-label = Engine Version:
|
||||
build-info-fork-label = Fork ID:
|
||||
build-info-download-url-label = Client Download:
|
||||
build-info-build-hash-label = Client Hash:
|
||||
build-info-build-manifest-url-label = Manifest URL:
|
||||
build-info-build-manifest-hash-label = Manifest Hash:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# Frontier
|
||||
reagent-dispenser-component-impure-auto-label = {$reagent} ({$purity}%)
|
||||
reagent-dispenser-component-set-auto-label-on-verb = Turn on auto-labeler
|
||||
reagent-dispenser-component-set-auto-label-off-verb = Turn off auto-labeler
|
||||
reagent-dispenser-component-examine-auto-label-on = The auto-labeler is turned [color=darkgreen]on[/color].
|
||||
reagent-dispenser-component-examine-auto-label-off = The auto-labeler is turned [color=red]off[/color].
|
||||
reagent-dispenser-component-verb-auto-label-turn-on = The auto-labeler has been turned on.
|
||||
reagent-dispenser-component-verb-auto-label-turn-off = The auto-labeler has been turned off.
|
||||
|
|
@ -7,7 +7,8 @@ zombieteors-description = The undead have been unleashed on the station amid a c
|
|||
zombie-not-enough-ready-players = Not enough players readied up for the game! There were {$readyPlayersCount} players readied up out of {$minimumPlayers} needed. Can't start Zombies.
|
||||
zombie-no-one-ready = No players readied up! Can't start Zombies.
|
||||
|
||||
zombie-patientzero-role-greeting = You are an initial infected. Get supplies and prepare for your eventual transformation. Your goal is to overtake the station while infecting as many people as possible.
|
||||
# Delta V - Moved to _DV file
|
||||
# zombie-patientzero-role-greeting = You are an initial infected. Get supplies and prepare for your eventual transformation. Your goal is to overtake the station while infecting as many people as possible.
|
||||
zombie-healing = You feel a stirring in your flesh
|
||||
zombie-infection-warning = You feel the zombie virus take hold
|
||||
zombie-infection-underway = Your blood begins to thicken
|
||||
|
|
|
|||
|
|
@ -549,11 +549,11 @@ WeaponSubMachineGunVectorRubber: null
|
|||
PosterContrabandLustyExomorph: PosterContrabandRealExomorph
|
||||
PosterContrabandBustyBackdoorExoBabes6: PosterContrabandRouny
|
||||
|
||||
# 2025-02-20
|
||||
MagazineBoxAntiMaterielBig: null
|
||||
MagazineBoxCaselessRifle10x24: null
|
||||
MagazineBoxCaselessRifleBig: null
|
||||
MagazinePistolHighCapacityRubber: null
|
||||
# 2025-02-20 # DeltaV - We still have these. Migrated to _DV namespace.
|
||||
#MagazineBoxAntiMaterielBig: null
|
||||
#MagazineBoxCaselessRifle10x24: null
|
||||
#MagazineBoxCaselessRifleBig: null
|
||||
#MagazinePistolHighCapacityRubber: null
|
||||
|
||||
# 2025-03-18
|
||||
EpinephrineChemistryBottle: ChemistryBottleEpinephrine
|
||||
|
|
|
|||
|
|
@ -271,6 +271,7 @@
|
|||
Piercing: 0.2
|
||||
Poison: 0.0
|
||||
Radiation: 0.0
|
||||
Shadow: 0.0 # DeltaV
|
||||
Shock: 0.0
|
||||
Slash: 0.25
|
||||
Structural: 0.0
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
|
||||
- type: entity
|
||||
parent: ClothingNeckBase
|
||||
|
|
@ -188,6 +189,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: TypingIndicatorClothing
|
||||
proto: moth
|
||||
|
||||
|
|
@ -207,6 +209,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: TypingIndicatorClothing
|
||||
proto: alien
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
storagebase: !type:Container
|
||||
ents: []
|
||||
|
||||
|
|
@ -137,6 +138,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: GroupExamine
|
||||
- type: Tag
|
||||
tags:
|
||||
|
|
@ -201,6 +203,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
storagebase: !type:Container
|
||||
ents: []
|
||||
|
||||
|
|
|
|||
|
|
@ -1189,6 +1189,7 @@
|
|||
- type: ContainerContainer # Delta V-Brings back clownsuit but make it make sense
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
|
||||
#Mime Hardsuit
|
||||
- type: entity
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
@ -173,6 +174,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: ProtectedFromStepTriggers
|
||||
slots: WITHOUT_POCKET
|
||||
- type: Tag
|
||||
|
|
@ -255,6 +256,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: ProtectedFromStepTriggers
|
||||
slots: WITHOUT_POCKET
|
||||
|
||||
|
|
@ -275,6 +277,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
- type: Construction
|
||||
graph: ClothingOuterSuitIan
|
||||
node: suit
|
||||
|
|
@ -308,6 +311,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterSuitCarp
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {} # DeltaV - Allow hats under toggleable clothing
|
||||
storagebase: !type:Container
|
||||
ents: []
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
- type: Edible
|
||||
trash:
|
||||
- FoodBowlBig
|
||||
utensil: Spoon
|
||||
utensil:
|
||||
- Spoon
|
||||
- Fork # Delta V - Mainly so people can eat rice dishes with a chopstick
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
|
|
|
|||
|
|
@ -25,26 +25,6 @@
|
|||
- type: Appearance
|
||||
|
||||
# Boxes
|
||||
- type: entity
|
||||
parent: BaseMagazineBoxAntiMateriel
|
||||
id: MagazineBoxAntiMaterielBig
|
||||
name: ammunition box (.60 anti-materiel)
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
capacity: 30
|
||||
proto: CartridgeAntiMateriel
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: base-b
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: magb-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: MagazineVisuals
|
||||
magState: magb
|
||||
steps: 4
|
||||
zeroVisible: false
|
||||
- type: Appearance
|
||||
|
||||
- type: entity
|
||||
parent: BaseMagazineBoxAntiMateriel
|
||||
id: MagazineBoxAntiMateriel
|
||||
|
|
|
|||
|
|
@ -25,46 +25,6 @@
|
|||
- type: Appearance
|
||||
|
||||
# Boxes
|
||||
- type: entity
|
||||
parent: BaseMagazineBoxCaselessRifle
|
||||
id: MagazineBoxCaselessRifle10x24
|
||||
name: ammunition box (.25 caseless)
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
capacity: 200
|
||||
proto: CartridgeCaselessRifle
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: base-10x24
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag10-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: MagazineVisuals
|
||||
magState: mag10
|
||||
steps: 4
|
||||
zeroVisible: false
|
||||
- type: Appearance
|
||||
|
||||
- type: entity
|
||||
parent: BaseMagazineBoxCaselessRifle
|
||||
id: MagazineBoxCaselessRifleBig
|
||||
name: ammunition box (.25 caseless)
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
capacity: 200
|
||||
proto: CartridgeCaselessRifle
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: base-b
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: magb-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: MagazineVisuals
|
||||
magState: magb
|
||||
steps: 4
|
||||
zeroVisible: false
|
||||
- type: Appearance
|
||||
|
||||
- type: entity
|
||||
parent: BaseMagazineBoxCaselessRifle
|
||||
id: MagazineBoxCaselessRifle
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
whitelist:
|
||||
tags:
|
||||
- CartridgePistol
|
||||
capacity: 16
|
||||
capacity: 20 # Delta-V, was 16
|
||||
- type: Item
|
||||
size: Small
|
||||
- type: ContainerContainer
|
||||
|
|
@ -247,6 +247,7 @@
|
|||
- type: entity
|
||||
id: MagazinePistolHighCapacityEmpty
|
||||
name: machine pistol magazine (.35 auto any)
|
||||
description: 20-round double-stack single feed magazine for machine pistols. #Delta V
|
||||
suffix: empty
|
||||
parent: BaseMagazinePistolHighCapacity
|
||||
components:
|
||||
|
|
@ -268,6 +269,7 @@
|
|||
- type: entity
|
||||
id: MagazinePistolHighCapacity
|
||||
name: machine pistol magazine (.35 auto)
|
||||
description: 20-round double-stack single feed magazine for machine pistols. Intended to hold general-purpose kinetic ammunition. #Delta V
|
||||
parent: BaseMagazinePistolHighCapacity
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
|
|
@ -292,6 +294,7 @@
|
|||
- type: entity
|
||||
id: MagazinePistolHighCapacityPractice
|
||||
name: machine pistol magazine (.35 auto practice)
|
||||
description: 20-round double-stack single feed magazine for machine pistols. Intended to hold non-harmful chalk ammunition. #Delta V
|
||||
parent: BaseMagazinePistolHighCapacity
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
|
|
@ -313,20 +316,6 @@
|
|||
- state: inhand-right-stripe
|
||||
color: "#ea5800"
|
||||
|
||||
- type: entity
|
||||
id: MagazinePistolHighCapacityRubber
|
||||
name: machine pistol magazine (.35 auto rubber)
|
||||
parent: BaseMagazinePistolHighCapacity
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
proto: CartridgePistolRubber # DeltaV: upstream still has this for some reason but not using rubber
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: rubber
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
|
||||
- type: entity
|
||||
id: MagazinePistolSubMachineGun
|
||||
name: SMG magazine (.35 auto)
|
||||
|
|
@ -443,4 +432,3 @@
|
|||
- state: inhand-left-mag
|
||||
right:
|
||||
- state: inhand-right-mag
|
||||
|
||||
|
|
|
|||
|
|
@ -1366,6 +1366,16 @@
|
|||
types:
|
||||
Heat: 24
|
||||
Piercing: 11
|
||||
- type: Fixtures # Delta V - ensures that it doesnt pierce windows
|
||||
fixtures:
|
||||
projectile:
|
||||
shape:
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.1,-0.1,0.1,0.1"
|
||||
hard: true
|
||||
mask:
|
||||
- Impassable
|
||||
- BulletImpassable
|
||||
|
||||
- type: entity
|
||||
name: magnum window-piercing bolt
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
- TegGenerator
|
||||
- TegCirculator
|
||||
- XenoArtifact
|
||||
- Roboisseur # Delta V - Butlerton is scary
|
||||
- Projectile
|
||||
event: !type:ChangeComponentsSpellEvent
|
||||
toAdd:
|
||||
- type: Animate
|
||||
|
|
|
|||
|
|
@ -19,13 +19,8 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot
|
||||
showEnts: false
|
||||
occludes: true
|
||||
ent: null
|
||||
toggleable-under-clothing: !type:ContainerSlot {}
|
||||
storagebase: !type:Container
|
||||
showEnts: false
|
||||
occludes: true
|
||||
ents: []
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterHardsuitSyndie
|
||||
|
|
|
|||
|
|
@ -43,14 +43,9 @@
|
|||
clothingPrototype: ClothingHeadHatHoodWinterMailCarrier
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
storagebase: !type:Container
|
||||
showEnts: False
|
||||
occludes: True
|
||||
ents: []
|
||||
toggleable-clothing: !type:ContainerSlot
|
||||
showEnts: False
|
||||
occludes: True
|
||||
ent: null
|
||||
toggleable-under-clothing: !type:ContainerSlot {}
|
||||
storagebase: !type:Container
|
||||
- type: Sprite
|
||||
sprite: Nyanotrasen/Clothing/OuterClothing/WinterCoats/mail_winter_coat.rsi
|
||||
- type: Clothing
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectUniversalIntercom
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-intercom
|
||||
|
|
@ -205,6 +206,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactBecomeRandomInstrument
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-become-instrument
|
||||
|
|
@ -220,6 +222,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactStorage
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-storage
|
||||
|
|
@ -236,6 +239,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactPhasing
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-phasing
|
||||
|
|
@ -245,6 +249,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactWandering
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-wandering
|
||||
|
|
@ -260,6 +265,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactSolutionStorage
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-solution-storage
|
||||
|
|
@ -293,6 +299,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactSpeedUp
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-speedup
|
||||
|
|
@ -306,6 +313,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactDrill
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-drill
|
||||
|
|
@ -324,6 +332,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactGenerateEnergy
|
||||
parent: BaseOneTimeXenoArtifactEffect # todo - increment power, but only once per node
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-generator
|
||||
|
|
@ -342,6 +351,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactGun
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gun
|
||||
|
|
@ -375,6 +385,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactGhost
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-ghost
|
||||
|
|
@ -397,6 +408,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactOmnitool
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-omnitool
|
||||
|
|
@ -446,6 +458,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectBadFeeling
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-feeling
|
||||
|
|
@ -478,6 +491,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectGoodFeeling
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-feeling
|
||||
|
|
@ -509,6 +523,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectJunkSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-junk
|
||||
|
|
@ -534,6 +549,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectLightFlicker
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-flicker
|
||||
|
|
@ -543,6 +559,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactPotassiumWave
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-potassium
|
||||
|
|
@ -572,6 +589,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactFloraSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-flora
|
||||
|
|
@ -589,6 +607,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactChemicalPuddle
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
# todo: make description say what exact chemical is produced, maybe add mixes into possible chemicals
|
||||
|
|
@ -628,6 +647,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactThrowThingsAround
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-throw
|
||||
|
|
@ -637,6 +657,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactColdWave
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-cold
|
||||
|
|
@ -647,6 +668,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactHeatWave
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-heat
|
||||
|
|
@ -657,6 +679,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactFoamMild
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
# todo: separate in 1 for each chemical for description? actually sounds like a very good idea
|
||||
|
|
@ -680,6 +703,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRandomInstrumentSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-create-instrument
|
||||
|
|
@ -702,6 +726,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactMonkeySpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-monkey
|
||||
|
|
@ -727,6 +752,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRadioactive
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-radioactive-mild
|
||||
|
|
@ -742,6 +768,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactChargeBattery
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-charge
|
||||
|
|
@ -754,6 +781,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactKnock
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-knock
|
||||
|
|
@ -764,6 +792,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactMagnet
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-magnet
|
||||
|
|
@ -780,6 +809,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactMagnetNegative
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-magnet
|
||||
|
|
@ -796,6 +826,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactStealth
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-stealth
|
||||
|
|
@ -811,6 +842,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRareMaterialSpawn
|
||||
parent: BaseXenoArtifactEffect # todo: splice into different well-named effects, amounts should reflect how rare material is
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-rare-materials
|
||||
|
|
@ -843,6 +875,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRareMaterialSpawnSilver
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-rare-materials
|
||||
|
|
@ -868,6 +901,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRareMaterialSpawnPlasma
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-plasma
|
||||
|
|
@ -893,6 +927,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRareMaterialSpawnGold
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gold
|
||||
|
|
@ -918,6 +953,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRareMaterialSpawnUranium
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-uranium
|
||||
|
|
@ -943,6 +979,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactAngryCarpSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-carp
|
||||
|
|
@ -968,6 +1005,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactFaunaSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-fauna
|
||||
|
|
@ -1017,6 +1055,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactHostileFaunaSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
description: Create hostile fauna
|
||||
components:
|
||||
- type: XenoArtifactNode
|
||||
|
|
@ -1044,6 +1083,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactCashSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-cash
|
||||
|
|
@ -1075,6 +1115,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactShatterWindows
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-shatter
|
||||
|
|
@ -1096,6 +1137,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactFoamGood
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-foam-medicine
|
||||
|
|
@ -1119,6 +1161,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactFoamDangerous
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-foam-poison
|
||||
|
|
@ -1143,6 +1186,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactPuddleRare
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-puddle-rare
|
||||
|
|
@ -1175,6 +1219,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactAnomalySpawn
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-anomaly
|
||||
|
|
@ -1192,6 +1237,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactIgnite
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-ignite
|
||||
|
|
@ -1205,6 +1251,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactTeleport
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-teleport
|
||||
|
|
@ -1214,6 +1261,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEmp
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-emp
|
||||
|
|
@ -1228,6 +1276,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactPolyMonkey
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-poly-monkey
|
||||
|
|
@ -1237,6 +1286,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactPolyLizard
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-poly-lizard
|
||||
|
|
@ -1247,6 +1297,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactPolyLuminous
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-poly-luminous
|
||||
|
|
@ -1257,6 +1308,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactRadioactiveStrong
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-radioactive-strong
|
||||
|
|
@ -1272,6 +1324,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactMaterialSpawnGlass
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-glass
|
||||
|
|
@ -1289,6 +1342,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactMaterialSpawnSteel
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-steel
|
||||
|
|
@ -1306,6 +1360,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactMaterialSpawnPlastic
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-plastic
|
||||
|
|
@ -1323,6 +1378,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactPortal
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-portal
|
||||
|
|
@ -1332,6 +1388,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactArtifactSpawn
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-artifact
|
||||
|
|
@ -1354,6 +1411,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactShuffle
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-shuffle
|
||||
|
|
@ -1367,6 +1425,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactHealAll
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-heal
|
||||
|
|
@ -1385,6 +1444,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactTesla
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-tesla
|
||||
|
|
@ -1403,6 +1463,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactSingularity
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-singularity
|
||||
|
|
@ -1421,6 +1482,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactExplosionScary
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-explosion-radioactive
|
||||
|
|
@ -1438,6 +1500,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactBoom
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-explosion-default
|
||||
|
|
@ -1454,6 +1517,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectCreationGasPlasma
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gas-plasma
|
||||
|
|
@ -1465,6 +1529,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectCreationGasTritium
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gas-tritium
|
||||
|
|
@ -1476,6 +1541,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectCreationGasAmmonia
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gas-ammonia
|
||||
|
|
@ -1487,6 +1553,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectCreationGasFrezon
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gas-frezon
|
||||
|
|
@ -1498,6 +1565,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectCreationGasNitrousOxide
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gas-nitrous
|
||||
|
|
@ -1509,6 +1577,7 @@
|
|||
- type: entity
|
||||
id: XenoArtifactEffectCreationGasCarbonDioxide
|
||||
parent: BaseXenoArtifactEffect
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails # DeltaV
|
||||
specificTip: xenoarch-effect-tip-specific-gas-carbon
|
||||
|
|
|
|||
|
|
@ -147,3 +147,15 @@
|
|||
amount: 2
|
||||
- id: BoxShotgunPractice
|
||||
amount: 2
|
||||
|
||||
- type: entity
|
||||
parent: GunSafeBaseSecure
|
||||
id: GunSafeSubMachineGunPatos
|
||||
name: patos safe
|
||||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: WeaponSubMachineGunPatos
|
||||
amount: 2
|
||||
- id: MagazinePistolHighCapacity
|
||||
amount: 4
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot { }
|
||||
toggleable-under-clothing: !type:ContainerSlot {}
|
||||
- type: Armor
|
||||
modifiers:
|
||||
coefficients:
|
||||
|
|
@ -96,6 +97,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {}
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
toggleable-under-clothing: !type:ContainerSlot {}
|
||||
storagebase: !type:Container
|
||||
ents: []
|
||||
|
||||
|
|
|
|||
|
|
@ -81,3 +81,14 @@
|
|||
children:
|
||||
- id: SalvageGunSafeRevolverSnub
|
||||
- id: SalvageGunSafeVulcan
|
||||
|
||||
- type: entity
|
||||
parent: BaseGunSafeSpawner
|
||||
id: SubMachineGunSafeSpawner
|
||||
suffix: SubMachineGun
|
||||
components:
|
||||
- type: EntityTableSpawner
|
||||
table: !type:GroupSelector
|
||||
children:
|
||||
- id: GunSafeSubMachineGunDrozd
|
||||
- id: GunSafeSubMachineGunPatos
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
- type: entity
|
||||
parent: BaseMagazineBoxAntiMateriel
|
||||
id: MagazineBoxAntiMaterielBig
|
||||
name: ammunition box (.60 anti-materiel)
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
capacity: 30
|
||||
proto: CartridgeAntiMateriel
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: base-b
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: magb-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: MagazineVisuals
|
||||
magState: magb
|
||||
steps: 4
|
||||
zeroVisible: false
|
||||
- type: Appearance
|
||||
|
||||
- type: entity
|
||||
parent: MagazineBoxAntiMateriel
|
||||
id: MagazineBoxLMGAntiMateriel
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
- type: entity
|
||||
parent: BaseMagazineBoxCaselessRifle
|
||||
id: MagazineBoxCaselessRifle10x24
|
||||
name: ammunition box (.25 caseless)
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
capacity: 200
|
||||
proto: CartridgeCaselessRifle
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: base-10x24
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag10-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: MagazineVisuals
|
||||
magState: mag10
|
||||
steps: 4
|
||||
zeroVisible: false
|
||||
- type: Appearance
|
||||
|
||||
- type: entity
|
||||
parent: BaseMagazineBoxCaselessRifle
|
||||
id: MagazineBoxCaselessRifleBig
|
||||
name: ammunition box (.25 caseless)
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
capacity: 200
|
||||
proto: CartridgeCaselessRifle
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: base-b
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: magb-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: MagazineVisuals
|
||||
magState: magb
|
||||
steps: 4
|
||||
zeroVisible: false
|
||||
- type: Appearance
|
||||
|
|
@ -1,4 +1,48 @@
|
|||
# .35 auto
|
||||
- type: entity
|
||||
id: MagazinePistolHighCapacityRubber
|
||||
name: machine pistol magazine (.35 auto rubber)
|
||||
description: 20-round double-stack single feed magazine for machine pistols. Intended to hold less-lethal rubber ammunition. #Delta V
|
||||
parent: BaseMagazinePistolHighCapacity
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
proto: CartridgePistolRubber
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: rubber
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
|
||||
- type: entity
|
||||
id: MagazinePistolHighCapacityIncendiary
|
||||
name: machine pistol magazine (.35 auto incendiary)
|
||||
description: 20-round double-stack single feed magazine for machine pistols. Intended to hold self-igniting incendiary ammunition. #Delta V
|
||||
parent: BaseMagazinePistolHighCapacity
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
proto: CartridgePistolIncendiary
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
|
||||
- type: entity
|
||||
id: MagazinePistolHighCapacityUranium
|
||||
name: machine pistol magazine (.35 auto uranium)
|
||||
description: 20-round double-stack single feed magazine for machine pistols. Intended to hold exotic uranium-core ammunition. #Delta V
|
||||
parent: BaseMagazinePistolHighCapacity
|
||||
components:
|
||||
- type: BallisticAmmoProvider
|
||||
proto: CartridgePistolUranium
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: uranium
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-1
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
|
||||
- type: entity
|
||||
parent: BaseMagazinePistol
|
||||
|
|
|
|||
|
|
@ -48,3 +48,66 @@
|
|||
steps: 1
|
||||
zeroVisible: true
|
||||
- type: Appearance
|
||||
|
||||
- type: entity
|
||||
name: Patos
|
||||
parent: BaseWeaponSubMachineGun
|
||||
id: WeaponSubMachineGunPatos
|
||||
description: A compact and lightweight personal defense weapon, with an aggressive compensator. Uses .35 auto ammo.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _DV/Objects/Weapons/Guns/SMGs/patos.rsi
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.GunVisualLayers.Base"]
|
||||
- state: mag-0
|
||||
map: ["enum.GunVisualLayers.Mag"]
|
||||
- type: Item
|
||||
size: Normal
|
||||
shape:
|
||||
- 0,0,1,1
|
||||
- type: Clothing
|
||||
sprite: _DV/Objects/Weapons/Guns/SMGs/patos.rsi
|
||||
slots:
|
||||
- Back
|
||||
- suitStorage
|
||||
- type: Gun
|
||||
minAngle: 4
|
||||
maxAngle: 24
|
||||
fireRate: 7
|
||||
angleIncrease: 4.5
|
||||
angleDecay: 24
|
||||
selectedMode: FullAuto
|
||||
availableModes:
|
||||
- SemiAuto
|
||||
- FullAuto
|
||||
soundGunshot:
|
||||
path: /Audio/Weapons/Guns/Gunshots/smg.ogg
|
||||
defaultDirection: 1, 0
|
||||
- type: ChamberMagazineAmmoProvider
|
||||
soundRack:
|
||||
path: /Audio/Weapons/Guns/Cock/smg_cock.ogg
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
gun_magazine:
|
||||
name: Magazine
|
||||
startingItem: MagazinePistolHighCapacity
|
||||
insertSound: /Audio/Weapons/Guns/MagIn/smg_magin.ogg
|
||||
ejectSound: /Audio/Weapons/Guns/MagOut/smg_magout.ogg
|
||||
priority: 2
|
||||
whitelist:
|
||||
tags:
|
||||
- MagazinePistolHighCapacity
|
||||
whitelistFailPopup: gun-magazine-whitelist-fail
|
||||
gun_chamber:
|
||||
name: Chamber
|
||||
startingItem: CartridgePistol
|
||||
priority: 1
|
||||
whitelist:
|
||||
tags:
|
||||
- CartridgePistol
|
||||
- type: MagazineVisuals
|
||||
magState: mag
|
||||
steps: 5
|
||||
zeroVisible: true
|
||||
- type: Appearance
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@
|
|||
description: A refrigerated storage unit for keeping items cold and fresh.
|
||||
components:
|
||||
- type: StationAiWhitelist
|
||||
- type: Vocalizer
|
||||
hideChat: true
|
||||
- type: VocalizerRequiresPower
|
||||
- type: DatasetVocalizer
|
||||
dataset: SmartFridgeAds
|
||||
- type: Speech
|
||||
- type: Appearance
|
||||
- type: Sprite
|
||||
sprite: Structures/Machines/smartfridge.rsi
|
||||
snapCardinals: true
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
- type: Edible
|
||||
edible: Drink
|
||||
solution: tank
|
||||
destroyOnEmpty: false
|
||||
- type: Spillable
|
||||
solution: tank
|
||||
- type: DumpableSolution
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
id: EngineeringStaticDeltaV
|
||||
recipes:
|
||||
- HolotapeProjector
|
||||
- SheetPlasteel
|
||||
|
||||
## Dynamic
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
recipes:
|
||||
- MagazineBoxSpecialPractice
|
||||
- SpeedLoaderSpecialPractice
|
||||
- MagazinePistolHighCapacityPractice
|
||||
|
||||
- type: latheRecipePack
|
||||
id: SecurityAmmoStaticDeltaV
|
||||
|
|
@ -29,6 +30,7 @@
|
|||
- BoxShellTranquilizer
|
||||
- MagazineShotgunBeanbag
|
||||
- MagazineLaser
|
||||
- MagazinePistolHighCapacity
|
||||
|
||||
- type: latheRecipePack
|
||||
id: SecurityShotgunDrumsStatic
|
||||
|
|
@ -50,6 +52,8 @@
|
|||
- MagazineBoxLightRifleRubber
|
||||
- MagazineBoxRifleRubber
|
||||
- MagazineBoxSpecialRubber
|
||||
- MagazinePistolSubMachineGunRubber
|
||||
- MagazinePistolHighCapacityRubber
|
||||
|
||||
- type: latheRecipePack
|
||||
parent: SecurityDisablers
|
||||
|
|
@ -69,6 +73,8 @@
|
|||
- MagazineBoxSpecialHoly
|
||||
- MagazineBoxSpecialMindbreaker
|
||||
- GamblagatorCapacitor
|
||||
- MagazinePistolHighCapacityUranium
|
||||
- MagazinePistolHighCapacityIncendiary
|
||||
|
||||
- type: latheRecipePack
|
||||
parent: SecurityHardsuits
|
||||
|
|
|
|||
|
|
@ -59,3 +59,11 @@
|
|||
parent: BaseFauxTileRecipe
|
||||
id: FauxTileMowedAstroSnow
|
||||
result: FloorTileItemMowedAstroSnow
|
||||
|
||||
- type: latheRecipe
|
||||
id: SheetPlasteel
|
||||
result: SheetPlasteel
|
||||
completetime: 1
|
||||
materials:
|
||||
Steel: 200
|
||||
Plasma: 100
|
||||
|
|
|
|||
|
|
@ -133,6 +133,22 @@
|
|||
Steel: 25
|
||||
Plastic: 500
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseAmmoRecipe
|
||||
id: MagazinePistolSubMachineGunRubber
|
||||
result: MagazinePistolSubMachineGunRubber
|
||||
materials:
|
||||
Steel: 25
|
||||
Plastic: 360
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseAmmoRecipe
|
||||
id: MagazinePistolHighCapacityRubber
|
||||
result: MagazinePistolHighCapacityRubber
|
||||
materials:
|
||||
Steel: 25
|
||||
Plastic: 240
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseAmmoRecipe
|
||||
id: SpeedLoaderMagnumRubber
|
||||
|
|
@ -169,6 +185,40 @@
|
|||
materials:
|
||||
Plastic: 750
|
||||
|
||||
|
||||
# Machine pistol mags, aside from rubber
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseAmmoRecipe
|
||||
id: MagazinePistolHighCapacity
|
||||
result: MagazinePistolHighCapacity
|
||||
materials:
|
||||
Steel: 210
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseAmmoRecipe
|
||||
id: MagazinePistolHighCapacityPractice
|
||||
result: MagazinePistolHighCapacityPractice
|
||||
materials:
|
||||
Steel: 125
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseAmmoRecipe
|
||||
id: MagazinePistolHighCapacityIncendiary
|
||||
result: MagazinePistolHighCapacityIncendiary
|
||||
materials:
|
||||
Steel: 25
|
||||
Plastic: 225
|
||||
|
||||
- type: latheRecipe
|
||||
parent: BaseAmmoRecipe
|
||||
id: MagazinePistolHighCapacityUranium
|
||||
result: MagazinePistolHighCapacityUranium
|
||||
materials:
|
||||
Steel: 25
|
||||
Plastic: 200
|
||||
Uranium: 200
|
||||
|
||||
# Armour vests
|
||||
|
||||
- type: latheRecipe
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
- BoxShotgunUranium
|
||||
- SpeedLoaderSpecialUranium
|
||||
- MagazineBoxSpecialUranium
|
||||
- MagazinePistolHighCapacityUranium
|
||||
# Incendiary
|
||||
- BoxShotgunIncendiary
|
||||
- MagazineRifleIncendiary
|
||||
|
|
@ -54,6 +55,7 @@
|
|||
- SpeedLoaderSpecialUranium
|
||||
- MagazineBoxSpecialIncendiary
|
||||
- MagazineBoxSpecialHoly
|
||||
- MagazinePistolHighCapacityIncendiary
|
||||
|
||||
- type: technology
|
||||
id: EnergyGuns
|
||||
|
|
|
|||
|
|
@ -56,8 +56,7 @@
|
|||
effects:
|
||||
- !type:AddCompsEffect
|
||||
components:
|
||||
- type: Unrevivable
|
||||
cloneable: false
|
||||
- type: Uncloneable
|
||||
|
||||
- type: trait
|
||||
id: Unborgable
|
||||
|
|
@ -98,6 +97,7 @@
|
|||
- !type:HasCompCondition
|
||||
component: BorgChassis
|
||||
invert: true
|
||||
tooltip: trait-condition-borg-not
|
||||
- !type:IsSpeciesCondition
|
||||
species: IPC
|
||||
invert: true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
- type: trait
|
||||
id: MarkedAsProtected
|
||||
name: trait-protected-name
|
||||
description: trait-protected-desc
|
||||
category: Meta
|
||||
conditions:
|
||||
- !type:InDepartmentCondition
|
||||
department: Command
|
||||
invert: true
|
||||
- !type:InDepartmentCondition
|
||||
department: Security
|
||||
invert: true
|
||||
- !type:IsAntagEligibleCondition
|
||||
antag: Thief
|
||||
invert: true
|
||||
- !type:IsAntagEligibleCondition
|
||||
antag: Traitor
|
||||
invert: true
|
||||
- !type:IsAntagEligibleCondition
|
||||
antag: TraitorSleeper
|
||||
invert: true
|
||||
effects:
|
||||
- !type:AddCompsEffect
|
||||
components:
|
||||
- type: TargetObjectiveImmune
|
||||
|
|
@ -56,6 +56,7 @@
|
|||
- !type:HasCompCondition
|
||||
component: BorgChassis
|
||||
invert: true
|
||||
tooltip: trait-condition-borg-not
|
||||
effects:
|
||||
- !type:AddCompsEffect
|
||||
components:
|
||||
|
|
@ -168,6 +169,7 @@
|
|||
- !type:HasCompCondition
|
||||
component: BorgChassis
|
||||
invert: true
|
||||
tooltip: trait-condition-borg-not
|
||||
effects:
|
||||
- !type:AddCompsEffect
|
||||
components:
|
||||
|
|
|
|||
|
|
@ -23,3 +23,10 @@
|
|||
name: trait-category-medical
|
||||
priority: 40
|
||||
accentColor: "#ef4444" # Red
|
||||
|
||||
- type: traitCategory
|
||||
id: Meta
|
||||
name: trait-category-meta
|
||||
priority: 50
|
||||
maxTraits: 1
|
||||
accentColor: "#eab308" # Yellow
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
- type: entity
|
||||
parent: BaseXenoArtifactEffect
|
||||
id: XenoArtifactRaiseGlimmer
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails
|
||||
specificTip: xenoarch-effect-tip-specific-glimmer
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
- type: entity
|
||||
parent: XenoArtifactRaiseGlimmer
|
||||
id: XenoArtifactRaiseGlimmerLarge
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: GlimmerArtifact
|
||||
range:
|
||||
|
|
@ -38,6 +40,7 @@
|
|||
- type: entity
|
||||
parent: XenoArtifactRaiseGlimmer
|
||||
id: XenoArtifactLowerGlimmer
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: GlimmerArtifact
|
||||
range:
|
||||
|
|
@ -48,6 +51,7 @@
|
|||
- type: entity
|
||||
parent: BaseOneTimeXenoArtifactEffect
|
||||
id: XenoArtifactMakePsionic
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: XAEDetails
|
||||
specificTip: xenoarch-effect-tip-specific-psionic
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 519 B |
|
After Width: | Height: | Size: 526 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 582 B |
|
After Width: | Height: | Size: 965 B |
|
After Width: | Height: | Size: 963 B |
|
After Width: | Height: | Size: 255 B |
|
After Width: | Height: | Size: 256 B |
|
After Width: | Height: | Size: 255 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 258 B |
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC0-1.0",
|
||||
"copyright": "sprites made by keke38",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "base"
|
||||
},
|
||||
{
|
||||
"name": "mag-0"
|
||||
},
|
||||
{
|
||||
"name": "mag-1"
|
||||
},
|
||||
{
|
||||
"name": "mag-2"
|
||||
},
|
||||
{
|
||||
"name": "mag-3"
|
||||
},
|
||||
{
|
||||
"name": "mag-4"
|
||||
},
|
||||
{
|
||||
"name": "bolt-open"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-BACKPACK",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "equipped-SUITSTORAGE",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |