RND Rework [Death to Techweb] (#16370)
* Techweb rework * more ui work * finishing ui * Finish all the C# logic * the techs + lathes * remove old-tech * mirror-review
29
Content.Client/Research/UI/MiniTechnologyCardControl.xaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<Control xmlns="https://spacestation14.io">
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<PanelContainer Name="Background"
|
||||||
|
Access="Public"
|
||||||
|
StyleClasses="PDABackground"
|
||||||
|
VerticalExpand="False"
|
||||||
|
HorizontalExpand="False"
|
||||||
|
MaxWidth="10"
|
||||||
|
Margin="0 0 -5 0"/>
|
||||||
|
<Button Name="Main"
|
||||||
|
Disabled="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="False"
|
||||||
|
StyleClasses="ButtonSquare"
|
||||||
|
Margin="0"
|
||||||
|
ToolTip="foobar"
|
||||||
|
TooltipDelay="0.25">
|
||||||
|
<BoxContainer Orientation="Horizontal" Margin="0">
|
||||||
|
<TextureRect Name="Texture"
|
||||||
|
HorizontalExpand="False"
|
||||||
|
VerticalExpand="False"
|
||||||
|
Margin="1"
|
||||||
|
TextureScale="0.5 0.5"/>
|
||||||
|
<Control MinWidth="5"/>
|
||||||
|
<RichTextLabel Name="NameLabel" StyleClasses="LabelSubText" VerticalAlignment="Center"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</Button>
|
||||||
|
</BoxContainer>
|
||||||
|
</Control>
|
||||||
24
Content.Client/Research/UI/MiniTechnologyCardControl.xaml.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Content.Shared.Research.Prototypes;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.Research.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class MiniTechnologyCardControl : Control
|
||||||
|
{
|
||||||
|
public MiniTechnologyCardControl(TechnologyPrototype technology, IPrototypeManager prototypeManager, SpriteSystem spriteSys, FormattedMessage description)
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
|
var discipline = prototypeManager.Index<TechDisciplinePrototype>(technology.Discipline);
|
||||||
|
Background.ModulateSelfOverride = discipline.Color;
|
||||||
|
Texture.Texture = spriteSys.Frame0(technology.Icon);
|
||||||
|
NameLabel.SetMessage(Loc.GetString(technology.Name));
|
||||||
|
Main.ToolTip = description.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,83 +4,56 @@ using Content.Shared.Research.Systems;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.Research.UI
|
namespace Content.Client.Research.UI;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface
|
||||||
{
|
{
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface
|
|
||||||
{
|
|
||||||
public int Points { get; private set; }
|
|
||||||
public int PointsPerSecond { get; private set; }
|
|
||||||
private ResearchConsoleMenu? _consoleMenu;
|
private ResearchConsoleMenu? _consoleMenu;
|
||||||
private TechnologyDatabaseComponent? _technologyDatabase;
|
|
||||||
private readonly IEntityManager _entityManager;
|
|
||||||
private readonly SharedResearchSystem _research;
|
|
||||||
|
|
||||||
public ResearchConsoleBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
public ResearchConsoleBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
||||||
{
|
{
|
||||||
SendMessage(new ConsoleServerSyncMessage());
|
SendMessage(new ConsoleServerSyncMessage());
|
||||||
_entityManager = IoCManager.Resolve<IEntityManager>();
|
|
||||||
_research = _entityManager.System<SharedResearchSystem>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Open()
|
protected override void Open()
|
||||||
{
|
{
|
||||||
base.Open();
|
base.Open();
|
||||||
|
|
||||||
if (!_entityManager.TryGetComponent(Owner.Owner, out _technologyDatabase))
|
var owner = Owner.Owner;
|
||||||
return;
|
|
||||||
|
|
||||||
_consoleMenu = new ResearchConsoleMenu(this);
|
_consoleMenu = new ResearchConsoleMenu(owner);
|
||||||
|
|
||||||
_consoleMenu.OnClose += Close;
|
_consoleMenu.OnTechnologyCardPressed += id =>
|
||||||
|
|
||||||
_consoleMenu.ServerSyncButton.OnPressed += (_) =>
|
|
||||||
{
|
{
|
||||||
SendMessage(new ConsoleServerSyncMessage());
|
SendMessage(new ConsoleUnlockTechnologyMessage(id));
|
||||||
};
|
};
|
||||||
|
|
||||||
_consoleMenu.ServerSelectionButton.OnPressed += (_) =>
|
_consoleMenu.OnServerButtonPressed += () =>
|
||||||
{
|
{
|
||||||
SendMessage(new ConsoleServerSelectionMessage());
|
SendMessage(new ConsoleServerSelectionMessage());
|
||||||
};
|
};
|
||||||
|
|
||||||
_consoleMenu.UnlockButton.OnPressed += (_) =>
|
_consoleMenu.OnSyncButtonPressed += () =>
|
||||||
{
|
{
|
||||||
if (_consoleMenu.TechnologySelected != null)
|
SendMessage(new ConsoleServerSyncMessage());
|
||||||
{
|
|
||||||
SendMessage(new ConsoleUnlockTechnologyMessage(_consoleMenu.TechnologySelected.ID));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_consoleMenu.OnClose += Close;
|
||||||
|
|
||||||
_consoleMenu.OpenCentered();
|
_consoleMenu.OpenCentered();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsTechnologyUnlocked(TechnologyPrototype technology)
|
|
||||||
{
|
|
||||||
if (_technologyDatabase == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return _research.IsTechnologyUnlocked(_technologyDatabase.Owner, technology, _technologyDatabase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanUnlockTechnology(TechnologyPrototype technology)
|
|
||||||
{
|
|
||||||
if (_technologyDatabase == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return _research.ArePrerequesitesUnlocked(_technologyDatabase.Owner, technology, _technologyDatabase);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateState(BoundUserInterfaceState state)
|
protected override void UpdateState(BoundUserInterfaceState state)
|
||||||
{
|
{
|
||||||
base.UpdateState(state);
|
base.UpdateState(state);
|
||||||
|
|
||||||
var castState = (ResearchConsoleBoundInterfaceState)state;
|
if (state is not ResearchConsoleBoundInterfaceState castState)
|
||||||
Points = castState.Points;
|
return;
|
||||||
PointsPerSecond = castState.PointsPerSecond;
|
_consoleMenu?.UpdatePanels(castState);
|
||||||
// We update the user interface here.
|
_consoleMenu?.UpdateInformationPanel(castState);
|
||||||
_consoleMenu?.PopulatePoints();
|
|
||||||
_consoleMenu?.Populate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
@@ -90,5 +63,4 @@ namespace Content.Client.Research.UI
|
|||||||
return;
|
return;
|
||||||
_consoleMenu?.Dispose();
|
_consoleMenu?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +1,101 @@
|
|||||||
<DefaultWindow xmlns="https://spacestation14.io"
|
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||||
|
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
|
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
Title="{Loc 'research-console-menu-title'}"
|
Title="{Loc 'research-console-menu-title'}"
|
||||||
MinSize="800 400"
|
MinSize="625 400"
|
||||||
SetSize="800 400">
|
SetSize="700 550">
|
||||||
<BoxContainer Orientation="Vertical"
|
<BoxContainer Orientation="Vertical"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
VerticalExpand="True">
|
VerticalExpand="True">
|
||||||
<BoxContainer Orientation="Horizontal"
|
<BoxContainer Orientation="Horizontal"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="False"
|
||||||
|
MinHeight="85"
|
||||||
|
Margin="10">
|
||||||
|
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
||||||
|
<RichTextLabel Name="ResearchAmountLabel"/>
|
||||||
|
<RichTextLabel Name="MainDisciplineLabel"/>
|
||||||
|
<Control VerticalExpand="True"/>
|
||||||
|
<BoxContainer Name="TierDisplayContainer" Orientation="Horizontal" HorizontalExpand="True" VerticalAlignment="Bottom"/>
|
||||||
|
<!-- This is where we put all of the little graphics that display discipline tiers!-->
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalAlignment="Right">
|
||||||
|
<Button Name="ServerButton" Text="{Loc 'research-console-menu-server-selection-button'}" VerticalExpand="True"/>
|
||||||
|
<Control MinHeight="5"/>
|
||||||
|
<!--todo is this button even necessary?!-->
|
||||||
|
<Button Name="SyncButton" Text="{Loc 'research-console-menu-server-sync-button'}" VerticalExpand="True"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Orientation="Horizontal"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="True">
|
||||||
|
<BoxContainer Orientation="Vertical"
|
||||||
VerticalExpand="True"
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
SizeFlagsStretchRatio="2"
|
SizeFlagsStretchRatio="2"
|
||||||
SeparationOverride="10">
|
Margin="10 0 10 10"
|
||||||
<BoxContainer Orientation="Vertical"
|
MinWidth="175">
|
||||||
|
<Label Text="{Loc 'research-console-available-text'}" HorizontalAlignment="Center"/>
|
||||||
|
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 0 0 10"/>
|
||||||
|
<PanelContainer VerticalExpand="True">
|
||||||
|
<PanelContainer.PanelOverride>
|
||||||
|
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
|
||||||
|
</PanelContainer.PanelOverride>
|
||||||
|
<ScrollContainer
|
||||||
|
HScrollEnabled="False"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
VerticalExpand="True">
|
VerticalExpand="True">
|
||||||
<Label Text="{Loc 'research-console-menu-unlocked-technologies-label'}" />
|
<BoxContainer
|
||||||
<ItemList Name="UnlockedTechnologies"
|
Name="AvailableCardsContainer"
|
||||||
SelectMode="Button"
|
Orientation="Vertical"
|
||||||
|
VerticalExpand="True">
|
||||||
|
</BoxContainer>
|
||||||
|
</ScrollContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
<Control MinHeight="10"/>
|
||||||
|
<Label Text="{Loc 'research-console-unlocked-text'}" HorizontalAlignment="Center"/>
|
||||||
|
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 0 0 10"/>
|
||||||
|
<PanelContainer VerticalExpand="True">
|
||||||
|
<PanelContainer.PanelOverride>
|
||||||
|
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
|
||||||
|
</PanelContainer.PanelOverride>
|
||||||
|
<ScrollContainer
|
||||||
|
HScrollEnabled="False"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
VerticalExpand="True">
|
VerticalExpand="True">
|
||||||
<!-- Unlocked technologies are added here by code -->
|
<BoxContainer
|
||||||
</ItemList>
|
Name="UnlockedCardsContainer"
|
||||||
|
Orientation="Vertical"
|
||||||
|
VerticalExpand="True">
|
||||||
|
</BoxContainer>
|
||||||
|
</ScrollContainer>
|
||||||
|
</PanelContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<BoxContainer Orientation="Vertical"
|
<BoxContainer Orientation="Vertical"
|
||||||
HorizontalExpand="True"
|
|
||||||
VerticalExpand="True">
|
|
||||||
<Label Text="{Loc 'research-console-menu-unlockable-technologies-label'}" />
|
|
||||||
<ItemList Name="UnlockableTechnologies"
|
|
||||||
SelectMode="Button"
|
|
||||||
HorizontalExpand="True"
|
|
||||||
VerticalExpand="True">
|
|
||||||
<!-- Unlockable technologies are added here by code -->
|
|
||||||
</ItemList>
|
|
||||||
</BoxContainer>
|
|
||||||
<BoxContainer Orientation="Vertical"
|
|
||||||
HorizontalExpand="True"
|
|
||||||
VerticalExpand="True">
|
|
||||||
<Label Text="{Loc 'research-console-menu-future-technologies-label'}" />
|
|
||||||
<ItemList Name="FutureTechnologies"
|
|
||||||
SelectMode="Button"
|
|
||||||
HorizontalExpand="True"
|
|
||||||
VerticalExpand="True">
|
|
||||||
<!-- Future technologies are added here by code -->
|
|
||||||
</ItemList>
|
|
||||||
</BoxContainer>
|
|
||||||
</BoxContainer>
|
|
||||||
<BoxContainer Orientation="Horizontal"
|
|
||||||
HorizontalExpand="True"
|
|
||||||
VerticalExpand="True"
|
VerticalExpand="True"
|
||||||
SizeFlagsStretchRatio="1">
|
|
||||||
<TextureRect Name="TechnologyIcon"
|
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
VerticalExpand="True"
|
SizeFlagsStretchRatio="3"
|
||||||
SizeFlagsStretchRatio="1"
|
Margin="0 0 10 10">
|
||||||
Stretch="KeepAspectCentered" />
|
<PanelContainer VerticalExpand="True" MinSize="0 200">
|
||||||
<BoxContainer Orientation="Vertical"
|
<PanelContainer.PanelOverride>
|
||||||
HorizontalExpand="True"
|
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
|
||||||
VerticalExpand="True"
|
</PanelContainer.PanelOverride>
|
||||||
SizeFlagsStretchRatio="3">
|
<ScrollContainer
|
||||||
<Label Name="TechnologyName" />
|
HScrollEnabled="False"
|
||||||
<Label Name="TechnologyDescription" />
|
|
||||||
<Label Name="TechnologyRequirements" />
|
|
||||||
</BoxContainer>
|
|
||||||
<BoxContainer Orientation="Vertical"
|
|
||||||
HorizontalExpand="True"
|
|
||||||
VerticalExpand="True"
|
|
||||||
SizeFlagsStretchRatio="1">
|
|
||||||
<Label Name="PointLabel" />
|
|
||||||
<Label Name="PointsPerSecondLabel" />
|
|
||||||
<BoxContainer Orientation="Vertical"
|
|
||||||
Align="End"
|
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
|
SizeFlagsStretchRatio="2"
|
||||||
VerticalExpand="True">
|
VerticalExpand="True">
|
||||||
<Button Name="ServerSelectionButton"
|
<BoxContainer
|
||||||
Access="Public"
|
Name="TechnologyCardsContainer"
|
||||||
Text="{Loc 'research-console-menu-server-selection-button'}" />
|
MinSize="100 256"
|
||||||
<Button Name="ServerSyncButton"
|
Orientation="Vertical"
|
||||||
Access="Public"
|
SizeFlagsStretchRatio="2"
|
||||||
Text="{Loc 'research-console-menu-server-sync-button'}" />
|
VerticalExpand="True">
|
||||||
<Button Name="UnlockButton"
|
</BoxContainer>
|
||||||
Access="Public"
|
</ScrollContainer>
|
||||||
Disabled="True" />
|
</PanelContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</BoxContainer>
|
</controls:FancyWindow>
|
||||||
</DefaultWindow>
|
|
||||||
|
|||||||
@@ -1,195 +1,167 @@
|
|||||||
using System.Collections.Generic;
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Content.Shared.Research.Components;
|
||||||
using Content.Shared.Research.Prototypes;
|
using Content.Shared.Research.Prototypes;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Client.Utility;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Localization;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Client.Research.UI
|
namespace Content.Client.Research.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class ResearchConsoleMenu : FancyWindow
|
||||||
{
|
{
|
||||||
[GenerateTypedNameReferences]
|
public Action<string>? OnTechnologyCardPressed;
|
||||||
public sealed partial class ResearchConsoleMenu : DefaultWindow
|
public Action? OnServerButtonPressed;
|
||||||
{
|
public Action? OnSyncButtonPressed;
|
||||||
public ResearchConsoleBoundUserInterface Owner { get; }
|
|
||||||
|
|
||||||
private readonly List<TechnologyPrototype> _unlockedTechnologyPrototypes = new();
|
[Dependency] private readonly IEntityManager _entity = default!;
|
||||||
private readonly List<TechnologyPrototype> _unlockableTechnologyPrototypes = new();
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
private readonly List<TechnologyPrototype> _futureTechnologyPrototypes = new();
|
private readonly TechnologyDatabaseComponent? _technologyDatabase;
|
||||||
|
private readonly ResearchSystem _research;
|
||||||
|
private readonly SpriteSystem _sprite;
|
||||||
|
|
||||||
public TechnologyPrototype? TechnologySelected;
|
public readonly EntityUid Entity;
|
||||||
|
|
||||||
public ResearchConsoleMenu(ResearchConsoleBoundUserInterface owner)
|
public ResearchConsoleMenu(EntityUid entity)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
Owner = owner;
|
_research = _entity.System<ResearchSystem>();
|
||||||
|
_sprite = _entity.System<SpriteSystem>();
|
||||||
|
Entity = entity;
|
||||||
|
|
||||||
UnlockedTechnologies.OnItemSelected += UnlockedTechnologySelected;
|
ServerButton.OnPressed += _ => OnServerButtonPressed?.Invoke();
|
||||||
UnlockableTechnologies.OnItemSelected += UnlockableTechnologySelected;
|
SyncButton.OnPressed += _ => OnSyncButtonPressed?.Invoke();
|
||||||
FutureTechnologies.OnItemSelected += FutureTechnologySelected;
|
|
||||||
|
|
||||||
PointLabel.Text = Loc.GetString("research-console-menu-research-points-text", ("points", 0));
|
_entity.TryGetComponent(entity, out _technologyDatabase);
|
||||||
PointsPerSecondLabel.Text = Loc.GetString("research-console-menu-points-per-second-text", ("pointsPerSecond", 0));
|
|
||||||
|
|
||||||
UnlockButton.Text = Loc.GetString("research-console-menu-server-unlock-button");
|
|
||||||
|
|
||||||
UnlockButton.OnPressed += _ =>
|
|
||||||
{
|
|
||||||
CleanSelectedTechnology();
|
|
||||||
};
|
|
||||||
|
|
||||||
Populate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void UpdatePanels(ResearchConsoleBoundInterfaceState state)
|
||||||
/// Cleans the selected technology controls to blank.
|
|
||||||
/// </summary>
|
|
||||||
private void CleanSelectedTechnology()
|
|
||||||
{
|
{
|
||||||
UnlockButton.Disabled = true;
|
var allTech = _research.GetAvailableTechnologies(Entity);
|
||||||
TechnologyIcon.Texture = Texture.Transparent;
|
AvailableCardsContainer.Children.Clear();
|
||||||
TechnologyName.Text = string.Empty;
|
TechnologyCardsContainer.Children.Clear();
|
||||||
TechnologyDescription.Text = string.Empty;
|
UnlockedCardsContainer.Children.Clear();
|
||||||
TechnologyRequirements.Text = string.Empty;
|
|
||||||
|
foreach (var tech in allTech)
|
||||||
|
{
|
||||||
|
var mini = new MiniTechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech, false));
|
||||||
|
AvailableCardsContainer.AddChild(mini);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
if (_technologyDatabase == null)
|
||||||
/// Called when an unlocked technology is selected.
|
|
||||||
/// </summary>
|
|
||||||
private void UnlockedTechnologySelected(ItemList.ItemListSelectedEventArgs obj)
|
|
||||||
{
|
|
||||||
TechnologySelected = _unlockedTechnologyPrototypes[obj.ItemIndex];
|
|
||||||
|
|
||||||
UnlockButton.Disabled = true;
|
|
||||||
|
|
||||||
PopulateSelectedTechnology();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when an unlockable technology is selected.
|
|
||||||
/// </summary>
|
|
||||||
private void UnlockableTechnologySelected(ItemList.ItemListSelectedEventArgs obj)
|
|
||||||
{
|
|
||||||
TechnologySelected = _unlockableTechnologyPrototypes[obj.ItemIndex];
|
|
||||||
|
|
||||||
UnlockButton.Disabled = Owner.Points < TechnologySelected.RequiredPoints;
|
|
||||||
|
|
||||||
PopulateSelectedTechnology();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when a future technology is selected
|
|
||||||
/// </summary>
|
|
||||||
private void FutureTechnologySelected(ItemList.ItemListSelectedEventArgs obj)
|
|
||||||
{
|
|
||||||
TechnologySelected = _futureTechnologyPrototypes[obj.ItemIndex];
|
|
||||||
|
|
||||||
UnlockButton.Disabled = true;
|
|
||||||
|
|
||||||
PopulateSelectedTechnology();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Populate all technologies in the ItemLists.
|
|
||||||
/// </summary>
|
|
||||||
public void PopulateItemLists()
|
|
||||||
{
|
|
||||||
UnlockedTechnologies.Clear();
|
|
||||||
UnlockableTechnologies.Clear();
|
|
||||||
FutureTechnologies.Clear();
|
|
||||||
|
|
||||||
_unlockedTechnologyPrototypes.Clear();
|
|
||||||
_unlockableTechnologyPrototypes.Clear();
|
|
||||||
_futureTechnologyPrototypes.Clear();
|
|
||||||
|
|
||||||
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
|
||||||
|
|
||||||
// For now, we retrieve all technologies. In the future, this should be changed.
|
|
||||||
foreach (var tech in prototypeMan.EnumeratePrototypes<TechnologyPrototype>())
|
|
||||||
{
|
|
||||||
var techName = GetTechName(tech);
|
|
||||||
if (Owner.IsTechnologyUnlocked(tech))
|
|
||||||
{
|
|
||||||
UnlockedTechnologies.AddItem(techName, tech.Icon.Frame0());
|
|
||||||
_unlockedTechnologyPrototypes.Add(tech);
|
|
||||||
}
|
|
||||||
else if (Owner.CanUnlockTechnology(tech))
|
|
||||||
{
|
|
||||||
UnlockableTechnologies.AddItem(techName, tech.Icon.Frame0());
|
|
||||||
_unlockableTechnologyPrototypes.Add(tech);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FutureTechnologies.AddItem(techName, tech.Icon.Frame0());
|
|
||||||
_futureTechnologyPrototypes.Add(tech);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetTechName(TechnologyPrototype prototype)
|
|
||||||
{
|
|
||||||
if (prototype.Name is { } name)
|
|
||||||
return Loc.GetString(name);
|
|
||||||
|
|
||||||
return prototype.ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fills the selected technology controls with details.
|
|
||||||
/// </summary>
|
|
||||||
public void PopulateSelectedTechnology()
|
|
||||||
{
|
|
||||||
if (TechnologySelected == null)
|
|
||||||
{
|
|
||||||
TechnologyName.Text = string.Empty;
|
|
||||||
TechnologyDescription.Text = string.Empty;
|
|
||||||
TechnologyRequirements.Text = string.Empty;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
TechnologyIcon.Texture = TechnologySelected.Icon.Frame0();
|
// i can't figure out the spacing so here you go
|
||||||
TechnologyName.Text = GetTechName(TechnologySelected);
|
TechnologyCardsContainer.AddChild(new Control
|
||||||
var desc = Loc.GetString(TechnologySelected.Description);
|
|
||||||
TechnologyDescription.Text = desc + $"\n{TechnologySelected.RequiredPoints} " + Loc.GetString("research-console-menu-research-points-text" ,("points", Owner.Points)).ToLowerInvariant();
|
|
||||||
TechnologyRequirements.Text = Loc.GetString("research-console-tech-requirements-none");
|
|
||||||
|
|
||||||
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
|
||||||
|
|
||||||
for (var i = 0; i < TechnologySelected.RequiredTechnologies.Count; i++)
|
|
||||||
{
|
{
|
||||||
var requiredId = TechnologySelected.RequiredTechnologies[i];
|
MinHeight = 10
|
||||||
if (!prototypeMan.TryIndex(requiredId, out TechnologyPrototype? prototype)) continue;
|
});
|
||||||
var protoName = GetTechName(prototype);
|
foreach (var techId in _technologyDatabase.CurrentTechnologyCards)
|
||||||
if (i == 0)
|
{
|
||||||
TechnologyRequirements.Text = Loc.GetString("research-console-tech-requirements-prototype-name", ("prototypeName", protoName));
|
var tech = _prototype.Index<TechnologyPrototype>(techId);
|
||||||
else
|
var cardControl = new TechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech), state.Points);
|
||||||
TechnologyRequirements.Text += $", {protoName}";
|
cardControl.OnPressed += () => OnTechnologyCardPressed?.Invoke(techId);
|
||||||
|
TechnologyCardsContainer.AddChild(cardControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var unlocked in _technologyDatabase.UnlockedTechnologies)
|
||||||
|
{
|
||||||
|
var tech = _prototype.Index<TechnologyPrototype>(unlocked);
|
||||||
|
var cardControl = new MiniTechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech, false));
|
||||||
|
UnlockedCardsContainer.AddChild(cardControl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public FormattedMessage GetTechnologyDescription(TechnologyPrototype technology, bool includeCost = true)
|
||||||
/// Updates the research point labels.
|
|
||||||
/// </summary>
|
|
||||||
public void PopulatePoints()
|
|
||||||
{
|
{
|
||||||
PointLabel.Text = Loc.GetString("research-console-menu-research-points-text", ("points", Owner.Points));
|
var description = new FormattedMessage();
|
||||||
PointsPerSecondLabel.Text = Loc.GetString("research-console-menu-points-per-second-text", ("pointsPerSecond", Owner.PointsPerSecond));
|
if (includeCost)
|
||||||
|
{
|
||||||
|
description.AddMarkup(Loc.GetString("research-console-cost", ("amount", technology.Cost)));
|
||||||
|
description.PushNewline();
|
||||||
|
}
|
||||||
|
description.AddMarkup(Loc.GetString("research-console-unlocks-list-start"));
|
||||||
|
foreach (var recipe in technology.RecipeUnlocks)
|
||||||
|
{
|
||||||
|
var recipeProto = _prototype.Index<LatheRecipePrototype>(recipe);
|
||||||
|
description.PushNewline();
|
||||||
|
description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry",
|
||||||
|
("name",recipeProto.Name)));
|
||||||
|
}
|
||||||
|
foreach (var generic in technology.GenericUnlocks)
|
||||||
|
{
|
||||||
|
description.PushNewline();
|
||||||
|
description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry-generic",
|
||||||
|
("name", Loc.GetString(generic.UnlockDescription))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
return description;
|
||||||
/// Updates the whole user interface.
|
}
|
||||||
/// </summary>
|
|
||||||
public void Populate()
|
public void UpdateInformationPanel(ResearchConsoleBoundInterfaceState state)
|
||||||
{
|
{
|
||||||
PopulatePoints();
|
var amountMsg = new FormattedMessage();
|
||||||
PopulateSelectedTechnology();
|
amountMsg.AddMarkup(Loc.GetString("research-console-menu-research-points-text",
|
||||||
PopulateItemLists();
|
("points", state.Points)));
|
||||||
|
ResearchAmountLabel.SetMessage(amountMsg);
|
||||||
|
|
||||||
|
if (_technologyDatabase == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var disciplineText = Loc.GetString("research-discipline-none");
|
||||||
|
var disciplineColor = Color.Gray;
|
||||||
|
if (_technologyDatabase.MainDiscipline != null)
|
||||||
|
{
|
||||||
|
var discipline = _prototype.Index<TechDisciplinePrototype>(_technologyDatabase.MainDiscipline);
|
||||||
|
disciplineText = Loc.GetString(discipline.Name);
|
||||||
|
disciplineColor = discipline.Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg = new FormattedMessage();
|
||||||
|
msg.AddMarkup(Loc.GetString("research-console-menu-main-discipline",
|
||||||
|
("name", disciplineText), ("color", disciplineColor)));
|
||||||
|
MainDisciplineLabel.SetMessage(msg);
|
||||||
|
|
||||||
|
TierDisplayContainer.Children.Clear();
|
||||||
|
foreach (var disciplineId in _technologyDatabase.SupportedDisciplines)
|
||||||
|
{
|
||||||
|
var discipline = _prototype.Index<TechDisciplinePrototype>(disciplineId);
|
||||||
|
var tier = _research.GetHighestDisciplineTier(_technologyDatabase, discipline);
|
||||||
|
|
||||||
|
// don't show tiers with no available tech
|
||||||
|
if (tier == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// i'm building the small-ass control here to spare me some mild annoyance in making a new file
|
||||||
|
var texture = new TextureRect
|
||||||
|
{
|
||||||
|
TextureScale = ( 2, 2 ),
|
||||||
|
VerticalAlignment = VAlignment.Center
|
||||||
|
};
|
||||||
|
var label = new RichTextLabel();
|
||||||
|
texture.Texture = _sprite.Frame0(discipline.Icon);
|
||||||
|
label.SetMessage(Loc.GetString("research-console-tier-info-small", ("tier", tier)));
|
||||||
|
|
||||||
|
var control = new BoxContainer
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
texture,
|
||||||
|
label,
|
||||||
|
new Control
|
||||||
|
{
|
||||||
|
MinWidth = 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TierDisplayContainer.AddChild(control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
42
Content.Client/Research/UI/TechnologyCardControl.xaml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<Control xmlns="https://spacestation14.io"
|
||||||
|
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls">
|
||||||
|
<BoxContainer Name="MainContainer" Orientation="Vertical" Margin="10 0 10 10">
|
||||||
|
<PanelContainer Name="Background"
|
||||||
|
Access="Public"
|
||||||
|
StyleClasses="PDABackground"
|
||||||
|
MinHeight="15"
|
||||||
|
VerticalExpand="False"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Margin="0 0 0 -5"/>
|
||||||
|
<Button Name="MainButton"
|
||||||
|
Disabled="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="True"
|
||||||
|
StyleClasses="ButtonSquare"
|
||||||
|
Margin="0">
|
||||||
|
<BoxContainer Orientation="Vertical"
|
||||||
|
VerticalExpand="True"
|
||||||
|
Margin="5">
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||||
|
<TextureRect Name="TechnologyTexture"
|
||||||
|
TextureScale="2 2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center" Margin="10 0 0 0">
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<Label Name="TechnologyNameLabel" StyleClasses="LabelKeyText" HorizontalExpand="True"/>
|
||||||
|
<TextureRect Name="DisciplineTexture" TextureScale="2 2" VerticalAlignment="Top" HorizontalAlignment="Right"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 5 0 5"/>
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<RichTextLabel Name="TierLabel" HorizontalAlignment="Left" StyleClasses="LabelSubText" HorizontalExpand="True"/>
|
||||||
|
<Button Name="ResearchButton" Text="{Loc 'research-console-menu-server-research-button'}"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
<Control MinHeight="5"></Control>
|
||||||
|
<RichTextLabel Name="UnlocksLabel" HorizontalExpand="True" StyleClasses="LabelSubText"></RichTextLabel>
|
||||||
|
</BoxContainer>
|
||||||
|
</Button>
|
||||||
|
</BoxContainer>
|
||||||
|
</Control>
|
||||||
36
Content.Client/Research/UI/TechnologyCardControl.xaml.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Content.Shared.Research.Prototypes;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.Research.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class TechnologyCardControl : Control
|
||||||
|
{
|
||||||
|
public Action? OnPressed;
|
||||||
|
|
||||||
|
public TechnologyCardControl(TechnologyPrototype technology, IPrototypeManager prototypeManager, SpriteSystem spriteSys, FormattedMessage description, int points)
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
|
var discipline = prototypeManager.Index<TechDisciplinePrototype>(technology.Discipline);
|
||||||
|
Background.ModulateSelfOverride = discipline.Color;
|
||||||
|
|
||||||
|
DisciplineTexture.Texture = spriteSys.Frame0(discipline.Icon);
|
||||||
|
TechnologyNameLabel.Text = Loc.GetString(technology.Name);
|
||||||
|
var message = new FormattedMessage();
|
||||||
|
message.AddMarkup(Loc.GetString("research-console-tier-discipline-info",
|
||||||
|
("tier", technology.Tier), ("color", discipline.Color), ("discipline", Loc.GetString(discipline.Name))));
|
||||||
|
TierLabel.SetMessage(message);
|
||||||
|
UnlocksLabel.SetMessage(description);
|
||||||
|
|
||||||
|
TechnologyTexture.Texture = spriteSys.Frame0(technology.Icon);
|
||||||
|
|
||||||
|
ResearchButton.Disabled = points < technology.Cost;
|
||||||
|
ResearchButton.OnPressed += _ => OnPressed?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1351,6 +1351,10 @@ namespace Content.Client.Stylesheets
|
|||||||
.Prop(Label.StylePropertyFont, notoSans12)
|
.Prop(Label.StylePropertyFont, notoSans12)
|
||||||
.Prop(Control.StylePropertyModulateSelf, Color.FromHex("#111111")),
|
.Prop(Control.StylePropertyModulateSelf, Color.FromHex("#111111")),
|
||||||
|
|
||||||
|
Element<RichTextLabel>().Class("LabelSubText")
|
||||||
|
.Prop(Label.StylePropertyFont, notoSans10)
|
||||||
|
.Prop(Label.StylePropertyFontColor, Color.DarkGray),
|
||||||
|
|
||||||
Element<LineEdit>().Class("PaperLineEdit")
|
Element<LineEdit>().Class("PaperLineEdit")
|
||||||
.Prop(LineEdit.StylePropertyStyleBox, new StyleBoxEmpty()),
|
.Prop(LineEdit.StylePropertyStyleBox, new StyleBoxEmpty()),
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Shared.Lathe;
|
using Content.Shared.Lathe;
|
||||||
using Content.Shared.Research.Prototypes;
|
using Content.Shared.Research.Prototypes;
|
||||||
@@ -10,6 +11,40 @@ namespace Content.IntegrationTests.Tests;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public sealed class ResearchTest
|
public sealed class ResearchTest
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public async Task DisciplineValidTierPrerequesitesTest()
|
||||||
|
{
|
||||||
|
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings {NoClient = true});
|
||||||
|
var server = pairTracker.Pair.Server;
|
||||||
|
|
||||||
|
var protoManager = server.ResolveDependency<IPrototypeManager>();
|
||||||
|
|
||||||
|
await server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
var allTechs = protoManager.EnumeratePrototypes<TechnologyPrototype>().ToList();
|
||||||
|
|
||||||
|
foreach (var discipline in protoManager.EnumeratePrototypes<TechDisciplinePrototype>())
|
||||||
|
{
|
||||||
|
foreach (var tech in allTechs)
|
||||||
|
{
|
||||||
|
if (tech.Discipline != discipline.ID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// we ignore these, anyways
|
||||||
|
if (tech.Tier == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Assert.That(tech.Tier, Is.GreaterThan(0), $"Technology {tech} has invalid tier {tech.Tier}.");
|
||||||
|
|
||||||
|
Assert.That(discipline.TierPrerequisites.ContainsKey(tech.Tier),
|
||||||
|
$"Discipline {discipline.ID} does not have a TierPrerequisites definition for tier {tech.Tier}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await pairTracker.CleanReturnAsync();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task AllTechPrintableTest()
|
public async Task AllTechPrintableTest()
|
||||||
{
|
{
|
||||||
@@ -40,14 +75,13 @@ public sealed class ResearchTest
|
|||||||
|
|
||||||
foreach (var recipe in lathe.DynamicRecipes)
|
foreach (var recipe in lathe.DynamicRecipes)
|
||||||
{
|
{
|
||||||
if (!latheTechs.Contains(recipe))
|
|
||||||
latheTechs.Add(recipe);
|
latheTechs.Add(recipe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var tech in protoManager.EnumeratePrototypes<TechnologyPrototype>())
|
foreach (var tech in protoManager.EnumeratePrototypes<TechnologyPrototype>())
|
||||||
{
|
{
|
||||||
foreach (var recipe in tech.UnlockedRecipes)
|
foreach (var recipe in tech.RecipeUnlocks)
|
||||||
{
|
{
|
||||||
Assert.That(latheTechs, Does.Contain(recipe), $"Recipe \"{recipe}\" cannot be unlocked on any lathes.");
|
Assert.That(latheTechs, Does.Contain(recipe), $"Recipe \"{recipe}\" cannot be unlocked on any lathes.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ namespace Content.Server.Lathe
|
|||||||
if (uid != args.Lathe || !TryComp<LatheComponent>(uid, out var latheComponent) || latheComponent.DynamicRecipes == null)
|
if (uid != args.Lathe || !TryComp<LatheComponent>(uid, out var latheComponent) || latheComponent.DynamicRecipes == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.Recipes = args.Recipes.Union(component.RecipeIds.Where(r => latheComponent.DynamicRecipes.Contains(r))).ToList();
|
args.Recipes = args.Recipes.Union(component.UnlockedRecipes.Where(r => latheComponent.DynamicRecipes.Contains(r))).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMaterialAmountChanged(EntityUid uid, LatheComponent component, ref MaterialAmountChangedEvent args)
|
private void OnMaterialAmountChanged(EntityUid uid, LatheComponent component, ref MaterialAmountChangedEvent args)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Content.Server.Research.Disk
|
|||||||
if (!TryComp<ResearchServerComponent>(args.Target, out var server))
|
if (!TryComp<ResearchServerComponent>(args.Target, out var server))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_research.AddPointsToServer(server.Owner, component.Points, server);
|
_research.ModifyServerPoints(args.Target.Value, component.Points, server);
|
||||||
_popupSystem.PopupEntity(Loc.GetString("research-disk-inserted", ("points", component.Points)), args.Target.Value, args.User);
|
_popupSystem.PopupEntity(Loc.GetString("research-disk-inserted", ("points", component.Points)), args.Target.Value, args.User);
|
||||||
EntityManager.QueueDeleteEntity(uid);
|
EntityManager.QueueDeleteEntity(uid);
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ namespace Content.Server.Research.Disk
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
component.Points = _prototype.EnumeratePrototypes<TechnologyPrototype>()
|
component.Points = _prototype.EnumeratePrototypes<TechnologyPrototype>()
|
||||||
.Sum(tech => tech.RequiredPoints);
|
.Sum(tech => tech.Cost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,8 +105,10 @@ public sealed partial class ResearchSystem
|
|||||||
/// <param name="serverComponent">The server's ResearchServerComponent. Null if false</param>
|
/// <param name="serverComponent">The server's ResearchServerComponent. Null if false</param>
|
||||||
/// <param name="component">The client's Researchclient component</param>
|
/// <param name="component">The client's Researchclient component</param>
|
||||||
/// <returns>If the server was successfully retrieved.</returns>
|
/// <returns>If the server was successfully retrieved.</returns>
|
||||||
public bool TryGetClientServer(EntityUid uid, [NotNullWhen(returnValue: true)] out EntityUid? server,
|
public bool TryGetClientServer(EntityUid uid,
|
||||||
[NotNullWhen(returnValue: true)] out ResearchServerComponent? serverComponent, ResearchClientComponent? component = null)
|
[NotNullWhen(returnValue: true)] out EntityUid? server,
|
||||||
|
[NotNullWhen(returnValue: true)] out ResearchServerComponent? serverComponent,
|
||||||
|
ResearchClientComponent? component = null)
|
||||||
{
|
{
|
||||||
server = null;
|
server = null;
|
||||||
serverComponent = null;
|
serverComponent = null;
|
||||||
@@ -117,11 +119,10 @@ public sealed partial class ResearchSystem
|
|||||||
if (component.Server == null)
|
if (component.Server == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!TryComp<ResearchServerComponent>(component.Server, out var sc))
|
if (!TryComp(component.Server, out serverComponent))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
server = component.Server;
|
server = component.Server;
|
||||||
serverComponent = sc;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,18 +33,17 @@ public sealed partial class ResearchSystem
|
|||||||
|
|
||||||
ResearchConsoleBoundInterfaceState state;
|
ResearchConsoleBoundInterfaceState state;
|
||||||
|
|
||||||
if (TryGetClientServer(uid, out var server, out var serverComponent, clientComponent))
|
if (TryGetClientServer(uid, out _, out var serverComponent, clientComponent))
|
||||||
{
|
{
|
||||||
var points = clientComponent.ConnectedToServer ? serverComponent.Points : 0;
|
var points = clientComponent.ConnectedToServer ? serverComponent.Points : 0;
|
||||||
var pointsPerSecond = clientComponent.ConnectedToServer ? PointsPerSecond(server.Value, serverComponent) : 0;
|
state = new ResearchConsoleBoundInterfaceState(points);
|
||||||
state = new ResearchConsoleBoundInterfaceState(points, pointsPerSecond);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state = new ResearchConsoleBoundInterfaceState(default, default);
|
state = new ResearchConsoleBoundInterfaceState(default);
|
||||||
}
|
}
|
||||||
|
|
||||||
_uiSystem.TrySetUiState(component.Owner, ResearchConsoleUiKey.Key, state);
|
_uiSystem.TrySetUiState(uid, ResearchConsoleUiKey.Key, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPointsChanged(EntityUid uid, ResearchConsoleComponent component, ref ResearchServerPointsChangedEvent args)
|
private void OnPointsChanged(EntityUid uid, ResearchConsoleComponent component, ref ResearchServerPointsChangedEvent args)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public sealed partial class ResearchSystem
|
|||||||
|
|
||||||
if (!CanRun(uid))
|
if (!CanRun(uid))
|
||||||
return;
|
return;
|
||||||
AddPointsToServer(uid, PointsPerSecond(uid, component) * time, component);
|
ModifyServerPoints(uid, GetPointsPerSecond(uid, component) * time, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -60,15 +60,14 @@ public sealed partial class ResearchSystem
|
|||||||
/// <param name="clientComponent"></param>
|
/// <param name="clientComponent"></param>
|
||||||
/// <param name="serverComponent"></param>
|
/// <param name="serverComponent"></param>
|
||||||
/// <param name="dirtyServer">Whether or not to dirty the server component after registration</param>
|
/// <param name="dirtyServer">Whether or not to dirty the server component after registration</param>
|
||||||
/// <returns>Whether or not the client was successfully registered to the server</returns>
|
public void RegisterClient(EntityUid client, EntityUid server, ResearchClientComponent? clientComponent = null,
|
||||||
public bool RegisterClient(EntityUid client, EntityUid server, ResearchClientComponent? clientComponent = null,
|
|
||||||
ResearchServerComponent? serverComponent = null, bool dirtyServer = true)
|
ResearchServerComponent? serverComponent = null, bool dirtyServer = true)
|
||||||
{
|
{
|
||||||
if (!Resolve(client, ref clientComponent) || !Resolve(server, ref serverComponent))
|
if (!Resolve(client, ref clientComponent) || !Resolve(server, ref serverComponent))
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (serverComponent.Clients.Contains(client))
|
if (serverComponent.Clients.Contains(client))
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
serverComponent.Clients.Add(client);
|
serverComponent.Clients.Add(client);
|
||||||
clientComponent.Server = server;
|
clientComponent.Server = server;
|
||||||
@@ -78,7 +77,6 @@ public sealed partial class ResearchSystem
|
|||||||
|
|
||||||
var ev = new ResearchRegistrationChangedEvent(server);
|
var ev = new ResearchRegistrationChangedEvent(server);
|
||||||
RaiseLocalEvent(client, ref ev);
|
RaiseLocalEvent(client, ref ev);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -130,7 +128,7 @@ public sealed partial class ResearchSystem
|
|||||||
/// <param name="uid"></param>
|
/// <param name="uid"></param>
|
||||||
/// <param name="component"></param>
|
/// <param name="component"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public int PointsPerSecond(EntityUid uid, ResearchServerComponent? component = null)
|
public int GetPointsPerSecond(EntityUid uid, ResearchServerComponent? component = null)
|
||||||
{
|
{
|
||||||
var points = 0;
|
var points = 0;
|
||||||
|
|
||||||
@@ -154,7 +152,7 @@ public sealed partial class ResearchSystem
|
|||||||
/// <param name="uid">The server</param>
|
/// <param name="uid">The server</param>
|
||||||
/// <param name="points">The amount of points being added</param>
|
/// <param name="points">The amount of points being added</param>
|
||||||
/// <param name="component"></param>
|
/// <param name="component"></param>
|
||||||
public void AddPointsToServer(EntityUid uid, int points, ResearchServerComponent? component = null)
|
public void ModifyServerPoints(EntityUid uid, int points, ResearchServerComponent? component = null)
|
||||||
{
|
{
|
||||||
if (points == 0)
|
if (points == 0)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared.Research.Components;
|
using Content.Shared.Research.Components;
|
||||||
using Content.Shared.Research.Prototypes;
|
using Content.Shared.Research.Prototypes;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace Content.Server.Research.Systems;
|
namespace Content.Server.Research.Systems;
|
||||||
|
|
||||||
@@ -13,13 +14,16 @@ public sealed partial class ResearchSystem
|
|||||||
if (!Resolve(primaryUid, ref primaryDb) || !Resolve(otherUid, ref otherDb))
|
if (!Resolve(primaryUid, ref primaryDb) || !Resolve(otherUid, ref otherDb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
primaryDb.TechnologyIds = otherDb.TechnologyIds;
|
primaryDb.MainDiscipline = otherDb.MainDiscipline;
|
||||||
primaryDb.RecipeIds = otherDb.RecipeIds;
|
primaryDb.CurrentTechnologyCards = otherDb.CurrentTechnologyCards;
|
||||||
|
primaryDb.SupportedDisciplines = otherDb.SupportedDisciplines;
|
||||||
|
primaryDb.UnlockedTechnologies = otherDb.UnlockedTechnologies;
|
||||||
|
primaryDb.UnlockedRecipes = otherDb.UnlockedRecipes;
|
||||||
|
|
||||||
Dirty(primaryDb);
|
Dirty(primaryDb);
|
||||||
|
|
||||||
var ev = new TechnologyDatabaseModifiedEvent();
|
var ev = new TechnologyDatabaseModifiedEvent();
|
||||||
RaiseLocalEvent(primaryDb.Owner, ref ev);
|
RaiseLocalEvent(primaryUid, ref ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -28,16 +32,15 @@ public sealed partial class ResearchSystem
|
|||||||
/// syncs against the research server, and the server against the local database.
|
/// syncs against the research server, and the server against the local database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Whether it could sync or not</returns>
|
/// <returns>Whether it could sync or not</returns>
|
||||||
public bool SyncClientWithServer(EntityUid uid, TechnologyDatabaseComponent? databaseComponent = null, ResearchClientComponent? clientComponent = null)
|
public void SyncClientWithServer(EntityUid uid, TechnologyDatabaseComponent? databaseComponent = null, ResearchClientComponent? clientComponent = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref databaseComponent, ref clientComponent, false))
|
if (!Resolve(uid, ref databaseComponent, ref clientComponent, false))
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (!TryComp<TechnologyDatabaseComponent>(clientComponent.Server, out var serverDatabase))
|
if (!TryComp<TechnologyDatabaseComponent>(clientComponent.Server, out var serverDatabase))
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
Sync(uid, clientComponent.Server.Value, databaseComponent, serverDatabase);
|
Sync(uid, clientComponent.Server.Value, databaseComponent, serverDatabase);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -45,45 +48,49 @@ public sealed partial class ResearchSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>If the technology was successfully added</returns>
|
/// <returns>If the technology was successfully added</returns>
|
||||||
public bool UnlockTechnology(EntityUid client, string prototypeid, ResearchClientComponent? component = null,
|
public bool UnlockTechnology(EntityUid client, string prototypeid, ResearchClientComponent? component = null,
|
||||||
TechnologyDatabaseComponent? databaseComponent = null)
|
TechnologyDatabaseComponent? clientDatabase = null)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.TryIndex<TechnologyPrototype>(prototypeid, out var prototype))
|
if (!PrototypeManager.TryIndex<TechnologyPrototype>(prototypeid, out var prototype))
|
||||||
{
|
|
||||||
Logger.Error("invalid technology prototype");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return UnlockTechnology(client, prototype, component, databaseComponent);
|
return UnlockTechnology(client, prototype, component, clientDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to add a technology to a database, checking if it is able to
|
/// Tries to add a technology to a database, checking if it is able to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>If the technology was successfully added</returns>
|
/// <returns>If the technology was successfully added</returns>
|
||||||
public bool UnlockTechnology(EntityUid client, TechnologyPrototype prototype, ResearchClientComponent? component = null,
|
public bool UnlockTechnology(EntityUid client,
|
||||||
TechnologyDatabaseComponent? databaseComponent = null)
|
TechnologyPrototype prototype,
|
||||||
|
ResearchClientComponent? component = null,
|
||||||
|
TechnologyDatabaseComponent? clientDatabase = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(client, ref component, ref databaseComponent, false))
|
if (!Resolve(client, ref component, ref clientDatabase, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CanUnlockTechnology(client, prototype, databaseComponent))
|
if (!TryGetClientServer(client, out var serverEnt, out _, component))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (component.Server is not { } server)
|
if (!CanServerUnlockTechnology(client, prototype, clientDatabase, component))
|
||||||
return false;
|
return false;
|
||||||
AddTechnology(server, prototype.ID);
|
|
||||||
AddPointsToServer(server, -prototype.RequiredPoints);
|
AddTechnology(serverEnt.Value, prototype);
|
||||||
|
TrySetMainDiscipline(prototype, serverEnt.Value);
|
||||||
|
ModifyServerPoints(serverEnt.Value, -prototype.Cost);
|
||||||
|
UpdateTechnologyCards(serverEnt.Value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a technology to the database without checking if it could be unlocked.
|
/// Adds a technology to the database without checking if it could be unlocked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
public void AddTechnology(EntityUid uid, string technology, TechnologyDatabaseComponent? component = null)
|
public void AddTechnology(EntityUid uid, string technology, TechnologyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref component))
|
if (!Resolve(uid, ref component))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_prototypeManager.TryIndex<TechnologyPrototype>(technology, out var prototype))
|
if (!PrototypeManager.TryIndex<TechnologyPrototype>(technology, out var prototype))
|
||||||
return;
|
return;
|
||||||
AddTechnology(uid, prototype, component);
|
AddTechnology(uid, prototype, component);
|
||||||
}
|
}
|
||||||
@@ -96,12 +103,19 @@ public sealed partial class ResearchSystem
|
|||||||
if (!Resolve(uid, ref component))
|
if (!Resolve(uid, ref component))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.TechnologyIds.Add(technology.ID);
|
//todo this needs to support some other stuff, too
|
||||||
foreach (var unlock in technology.UnlockedRecipes)
|
foreach (var generic in technology.GenericUnlocks)
|
||||||
{
|
{
|
||||||
if (component.RecipeIds.Contains(unlock))
|
if (generic.PurchaseEvent != null)
|
||||||
|
RaiseLocalEvent(generic.PurchaseEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
component.UnlockedTechnologies.Add(technology.ID);
|
||||||
|
foreach (var unlock in technology.RecipeUnlocks)
|
||||||
|
{
|
||||||
|
if (component.UnlockedRecipes.Contains(unlock))
|
||||||
continue;
|
continue;
|
||||||
component.RecipeIds.Add(unlock);
|
component.UnlockedRecipes.Add(unlock);
|
||||||
}
|
}
|
||||||
Dirty(component);
|
Dirty(component);
|
||||||
|
|
||||||
@@ -113,16 +127,15 @@ public sealed partial class ResearchSystem
|
|||||||
/// Adds a lathe recipe to the specified technology database
|
/// Adds a lathe recipe to the specified technology database
|
||||||
/// without checking if it can be unlocked.
|
/// without checking if it can be unlocked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddLatheRecipe(EntityUid uid, string recipe, TechnologyDatabaseComponent? component = null, bool dirty = true)
|
public void AddLatheRecipe(EntityUid uid, string recipe, TechnologyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref component))
|
if (!Resolve(uid, ref component))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.RecipeIds.Contains(recipe))
|
if (component.UnlockedRecipes.Contains(recipe))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.RecipeIds.Add(recipe);
|
component.UnlockedRecipes.Add(recipe);
|
||||||
if (dirty)
|
|
||||||
Dirty(component);
|
Dirty(component);
|
||||||
|
|
||||||
var ev = new TechnologyDatabaseModifiedEvent();
|
var ev = new TechnologyDatabaseModifiedEvent();
|
||||||
@@ -134,34 +147,36 @@ public sealed partial class ResearchSystem
|
|||||||
/// taking parent technologies into account.
|
/// taking parent technologies into account.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Whether it could be unlocked or not</returns>
|
/// <returns>Whether it could be unlocked or not</returns>
|
||||||
public bool CanUnlockTechnology(EntityUid uid, string technology, TechnologyDatabaseComponent? database = null, ResearchClientComponent? client = null)
|
public bool CanServerUnlockTechnology(EntityUid uid,
|
||||||
|
TechnologyPrototype technology,
|
||||||
|
TechnologyDatabaseComponent? database = null,
|
||||||
|
ResearchClientComponent? client = null)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.TryIndex<TechnologyPrototype>(technology, out var prototype))
|
|
||||||
return false;
|
|
||||||
return CanUnlockTechnology(uid, prototype, database, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
if (!Resolve(uid, ref client, ref database, false))
|
||||||
/// Returns whether a technology can be unlocked on this database,
|
|
||||||
/// taking parent technologies into account.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Whether it could be unlocked or not</returns>
|
|
||||||
public bool CanUnlockTechnology(EntityUid uid, TechnologyPrototype technology, TechnologyDatabaseComponent? database = null, ResearchClientComponent? client = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref database, ref client))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!TryGetClientServer(uid, out _, out var serverComponent, client))
|
if (!TryGetClientServer(uid, out _, out var serverComp, client))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (serverComponent.Points < technology.RequiredPoints)
|
if (!IsTechnologyAvailable(database, technology))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (IsTechnologyUnlocked(uid, technology, database))
|
if (technology.Cost > serverComp.Points)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ArePrerequesitesUnlocked(uid, technology, database))
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDatabaseRegistrationChanged(EntityUid uid, TechnologyDatabaseComponent component, ref ResearchRegistrationChangedEvent args)
|
||||||
|
{
|
||||||
|
if (args.Server != null)
|
||||||
|
return;
|
||||||
|
component.MainDiscipline = null;
|
||||||
|
component.CurrentTechnologyCards = new List<string>();
|
||||||
|
component.SupportedDisciplines = new List<string>();
|
||||||
|
component.UnlockedTechnologies = new List<string>();
|
||||||
|
component.UnlockedRecipes = new List<string>();
|
||||||
|
Dirty(component);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Content.Shared.Research.Components;
|
|||||||
using Content.Shared.Research.Systems;
|
using Content.Shared.Research.Systems;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Research.Systems
|
namespace Content.Server.Research.Systems
|
||||||
@@ -13,7 +12,6 @@ namespace Content.Server.Research.Systems
|
|||||||
public sealed partial class ResearchSystem : SharedResearchSystem
|
public sealed partial class ResearchSystem : SharedResearchSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -23,6 +21,8 @@ namespace Content.Server.Research.Systems
|
|||||||
InitializeConsole();
|
InitializeConsole();
|
||||||
InitializeSource();
|
InitializeSource();
|
||||||
InitializeServer();
|
InitializeServer();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<TechnologyDatabaseComponent, ResearchRegistrationChangedEvent>(OnDatabaseRegistrationChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public sealed class DiskConsoleSystem : EntitySystem
|
|||||||
if (serverComp.Points < component.PricePerDisk)
|
if (serverComp.Points < component.PricePerDisk)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_research.AddPointsToServer(server.Value, -component.PricePerDisk, serverComp);
|
_research.ModifyServerPoints(server.Value, -component.PricePerDisk, serverComp);
|
||||||
_audio.PlayPvs(component.PrintSound, uid);
|
_audio.PlayPvs(component.PrintSound, uid);
|
||||||
|
|
||||||
var printing = EnsureComp<DiskConsolePrintingComponent>(uid);
|
var printing = EnsureComp<DiskConsolePrintingComponent>(uid);
|
||||||
|
|||||||
@@ -38,12 +38,11 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
foreach (var recipe in component.Recipes)
|
foreach (var recipe in component.Recipes)
|
||||||
{
|
{
|
||||||
_research.AddLatheRecipe(target, recipe, database, false);
|
_research.AddLatheRecipe(target, recipe, database);
|
||||||
}
|
}
|
||||||
Dirty(database);
|
|
||||||
}
|
}
|
||||||
_popup.PopupEntity(Loc.GetString("tech-disk-inserted"), target, args.User);
|
_popup.PopupEntity(Loc.GetString("tech-disk-inserted"), target, args.User);
|
||||||
EntityManager.DeleteEntity(uid);
|
Del(uid);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +70,7 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
|||||||
var allTechs = new List<string>();
|
var allTechs = new List<string>();
|
||||||
foreach (var tech in _prototype.EnumeratePrototypes<TechnologyPrototype>())
|
foreach (var tech in _prototype.EnumeratePrototypes<TechnologyPrototype>())
|
||||||
{
|
{
|
||||||
allTechs.AddRange(tech.UnlockedRecipes);
|
allTechs.AddRange(tech.RecipeUnlocks);
|
||||||
}
|
}
|
||||||
allTechs = allTechs.Distinct().ToList();
|
allTechs = allTechs.Distinct().ToList();
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
|||||||
var allUnlocked = new List<string>();
|
var allUnlocked = new List<string>();
|
||||||
foreach (var database in EntityQuery<TechnologyDatabaseComponent>())
|
foreach (var database in EntityQuery<TechnologyDatabaseComponent>())
|
||||||
{
|
{
|
||||||
allUnlocked.AddRange(database.RecipeIds);
|
allUnlocked.AddRange(database.UnlockedRecipes);
|
||||||
}
|
}
|
||||||
allUnlocked = allUnlocked.Distinct().ToList();
|
allUnlocked = allUnlocked.Distinct().ToList();
|
||||||
|
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
|||||||
if (pointValue == 0)
|
if (pointValue == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_research.AddPointsToServer(server.Value, pointValue, serverComponent);
|
_research.ModifyServerPoints(server.Value, pointValue, serverComponent);
|
||||||
_artifact.AdjustConsumedPoints(artifact.Value, pointValue);
|
_artifact.AdjustConsumedPoints(artifact.Value, pointValue);
|
||||||
|
|
||||||
_audio.PlayPvs(component.DestroySound, component.AnalyzerEntity.Value, AudioParams.Default.WithVolume(2f));
|
_audio.PlayPvs(component.DestroySound, component.AnalyzerEntity.Value, AudioParams.Default.WithVolume(2f));
|
||||||
|
|||||||
@@ -2,26 +2,29 @@ using Robust.Shared.GameStates;
|
|||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Shared.Research.Components
|
namespace Content.Shared.Research.Components;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class ResearchServerComponent : Component
|
||||||
{
|
{
|
||||||
[RegisterComponent, NetworkedComponent]
|
|
||||||
public sealed class ResearchServerComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the server
|
/// The name of the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("servername"), ViewVariables(VVAccess.ReadWrite)]
|
[AutoNetworkedField]
|
||||||
|
[DataField("serverName"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
public string ServerName = "RDSERVER";
|
public string ServerName = "RDSERVER";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of points on the server.
|
/// The amount of points on the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[AutoNetworkedField]
|
||||||
[DataField("points"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField("points"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
public int Points;
|
public int Points;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A unique numeric id representing the server
|
/// A unique numeric id representing the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[AutoNetworkedField]
|
||||||
[ViewVariables(VVAccess.ReadOnly)]
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
public int Id;
|
public int Id;
|
||||||
|
|
||||||
@@ -39,36 +42,22 @@ namespace Content.Shared.Research.Components
|
|||||||
|
|
||||||
[DataField("researchConsoleUpdateTime"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField("researchConsoleUpdateTime"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
public readonly TimeSpan ResearchConsoleUpdateTime = TimeSpan.FromSeconds(1);
|
public readonly TimeSpan ResearchConsoleUpdateTime = TimeSpan.FromSeconds(1);
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class ResearchServerState : ComponentState
|
|
||||||
{
|
|
||||||
public string ServerName;
|
|
||||||
public int Points;
|
|
||||||
public int Id;
|
|
||||||
public ResearchServerState(string serverName, int points, int id)
|
|
||||||
{
|
|
||||||
ServerName = serverName;
|
|
||||||
Points = points;
|
|
||||||
Id = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event raised on a server's clients when the point value of the server is changed.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Server"></param>
|
|
||||||
/// <param name="Total"></param>
|
|
||||||
/// <param name="Delta"></param>
|
|
||||||
[ByRefEvent]
|
|
||||||
public readonly record struct ResearchServerPointsChangedEvent(EntityUid Server, int Total, int Delta);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event raised every second to calculate the amount of points added to the server.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Server"></param>
|
|
||||||
/// <param name="Points"></param>
|
|
||||||
[ByRefEvent]
|
|
||||||
public record struct ResearchServerGetPointsPerSecondEvent(EntityUid Server, int Points);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event raised on a server's clients when the point value of the server is changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Server"></param>
|
||||||
|
/// <param name="Total"></param>
|
||||||
|
/// <param name="Delta"></param>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct ResearchServerPointsChangedEvent(EntityUid Server, int Total, int Delta);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event raised every second to calculate the amount of points added to the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Server"></param>
|
||||||
|
/// <param name="Points"></param>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct ResearchServerGetPointsPerSecondEvent(EntityUid Server, int Points);
|
||||||
|
|
||||||
|
|||||||
@@ -35,11 +35,9 @@ namespace Content.Shared.Research.Components
|
|||||||
public sealed class ResearchConsoleBoundInterfaceState : BoundUserInterfaceState
|
public sealed class ResearchConsoleBoundInterfaceState : BoundUserInterfaceState
|
||||||
{
|
{
|
||||||
public int Points;
|
public int Points;
|
||||||
public int PointsPerSecond;
|
public ResearchConsoleBoundInterfaceState(int points)
|
||||||
public ResearchConsoleBoundInterfaceState(int points, int pointsPerSecond)
|
|
||||||
{
|
{
|
||||||
Points = points;
|
Points = points;
|
||||||
PointsPerSecond = pointsPerSecond;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,56 @@
|
|||||||
using Content.Shared.Research.Prototypes;
|
using Content.Shared.Research.Prototypes;
|
||||||
|
using Content.Shared.Research.Systems;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||||
|
|
||||||
namespace Content.Shared.Research.Components
|
namespace Content.Shared.Research.Components;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedResearchSystem)), AutoGenerateComponentState]
|
||||||
|
public sealed partial class TechnologyDatabaseComponent : Component
|
||||||
{
|
{
|
||||||
[RegisterComponent, NetworkedComponent]
|
/// <summary>
|
||||||
public sealed class TechnologyDatabaseComponent : Component
|
/// A main discipline that locks out other discipline technology past a certain tier.
|
||||||
{
|
/// </summary>
|
||||||
|
[AutoNetworkedField]
|
||||||
|
[DataField("mainDiscipline", customTypeSerializer: typeof(PrototypeIdSerializer<TechDisciplinePrototype>))]
|
||||||
|
public string? MainDiscipline;
|
||||||
|
|
||||||
|
[AutoNetworkedField(true)]
|
||||||
|
[DataField("currentTechnologyCards")]
|
||||||
|
public List<string> CurrentTechnologyCards = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Which research disciplines are able to be unlocked
|
||||||
|
/// </summary>
|
||||||
|
[AutoNetworkedField(true)]
|
||||||
|
[DataField("supportedDisciplines", customTypeSerializer: typeof(PrototypeIdListSerializer<TechDisciplinePrototype>))]
|
||||||
|
public List<string> SupportedDisciplines = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ids of all the technologies which have been unlocked.
|
/// The ids of all the technologies which have been unlocked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("technologyIds", customTypeSerializer: typeof(PrototypeIdListSerializer<TechnologyPrototype>))]
|
[AutoNetworkedField(true)]
|
||||||
public List<string> TechnologyIds = new();
|
[DataField("unlockedTechnologies", customTypeSerializer: typeof(PrototypeIdListSerializer<TechnologyPrototype>))]
|
||||||
|
public List<string> UnlockedTechnologies = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ids of all the lathe recipes which have been unlocked.
|
/// The ids of all the lathe recipes which have been unlocked.
|
||||||
/// This is maintained alongside the TechnologyIds
|
/// This is maintained alongside the TechnologyIds
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("recipeIds", customTypeSerializer: typeof(PrototypeIdListSerializer<LatheRecipePrototype>))]
|
/// todo: if you unlock all the recipes in a tech, it doesn't count as unlocking the tech. sadge
|
||||||
public List<string> RecipeIds = new();
|
[AutoNetworkedField(true)]
|
||||||
}
|
[DataField("unlockedRecipes", customTypeSerializer: typeof(PrototypeIdListSerializer<LatheRecipePrototype>))]
|
||||||
|
public List<string> UnlockedRecipes = new();
|
||||||
/// <summary>
|
|
||||||
/// Event raised on the database whenever its
|
|
||||||
/// technologies or recipes are modified.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This event is forwarded from the
|
|
||||||
/// server to all of it's clients.
|
|
||||||
/// </remarks>
|
|
||||||
[ByRefEvent]
|
|
||||||
public readonly record struct TechnologyDatabaseModifiedEvent;
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class TechnologyDatabaseState : ComponentState
|
|
||||||
{
|
|
||||||
public List<string> Technologies;
|
|
||||||
public List<string> Recipes;
|
|
||||||
|
|
||||||
public TechnologyDatabaseState(List<string> technologies, List<string> recipes)
|
|
||||||
{
|
|
||||||
Technologies = technologies;
|
|
||||||
Recipes = recipes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event raised on the database whenever its
|
||||||
|
/// technologies or recipes are modified.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This event is forwarded from the
|
||||||
|
/// server to all of it's clients.
|
||||||
|
/// </remarks>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct TechnologyDatabaseModifiedEvent;
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Shared.Research.Prototypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a prototype for a research discipline, a category
|
||||||
|
/// that governs how <see cref="TechnologyPrototype"/>s are unlocked.
|
||||||
|
/// </summary>
|
||||||
|
[Prototype("techDiscipline")]
|
||||||
|
public sealed class TechDisciplinePrototype : IPrototype
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[IdDataField]
|
||||||
|
public string ID { get; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Player-facing name.
|
||||||
|
/// Supports locale strings.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("name", required: true)]
|
||||||
|
public readonly string Name = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A color used for UI
|
||||||
|
/// </summary>
|
||||||
|
[DataField("color", required: true)]
|
||||||
|
public readonly Color Color;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An icon used to visually represent the discipline in UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("icon")]
|
||||||
|
public readonly SpriteSpecifier Icon = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For each tier a discipline supports, what percentage
|
||||||
|
/// of the previous tier must be unlocked for it to become available
|
||||||
|
/// </summary>
|
||||||
|
[DataField("tierPrerequisites", required: true)]
|
||||||
|
public readonly Dictionary<int, float> TierPrerequisites = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Purchasing this tier of technology causes a server to become "locked" to this discipline.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("lockoutTier")]
|
||||||
|
public readonly int LockoutTier = 3;
|
||||||
|
}
|
||||||
@@ -1,54 +1,92 @@
|
|||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.Research.Prototypes
|
namespace Content.Shared.Research.Prototypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a prototype for a technology that can be unlocked.
|
||||||
|
/// </summary>
|
||||||
|
[Prototype("technology")]
|
||||||
|
public sealed class TechnologyPrototype : IPrototype
|
||||||
{
|
{
|
||||||
[NetSerializable, Serializable, Prototype("technology")]
|
/// <inheritdoc/>
|
||||||
public sealed class TechnologyPrototype : IPrototype
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The ID of this technology prototype.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
[IdDataField]
|
[IdDataField]
|
||||||
public string ID { get; } = default!;
|
public string ID { get; } = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name this technology will have on user interfaces.
|
/// The name of the technology.
|
||||||
|
/// Supports locale strings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("name")]
|
[DataField("name", required: true)]
|
||||||
public string? Name { get; private set; }
|
public readonly string Name = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An icon that represent this technology.
|
/// An icon used to visually represent the technology in UI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("icon")]
|
[DataField("icon", required: true)]
|
||||||
public SpriteSpecifier Icon { get; } = SpriteSpecifier.Invalid;
|
public readonly SpriteSpecifier Icon = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A short description of the technology.
|
/// What research discipline this technology belongs to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("description")]
|
[DataField("discipline", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<TechDisciplinePrototype>))]
|
||||||
public string Description { get; private set; } = "";
|
public readonly string Discipline = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The required research points to unlock this technology.
|
/// What tier research is this?
|
||||||
|
/// The tier governs how much lower-tier technology
|
||||||
|
/// needs to be unlocked before this one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("requiredPoints")]
|
[DataField("tier", required: true)]
|
||||||
public int RequiredPoints { get; }
|
public readonly int Tier;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of technology IDs required to unlock this technology.
|
/// Hidden tech is not ever available at the research console.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("requiredTechnologies", customTypeSerializer: typeof(PrototypeIdListSerializer<TechnologyPrototype>))]
|
[DataField("hidden")]
|
||||||
public List<string> RequiredTechnologies { get; } = new();
|
public readonly bool Hidden;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of recipe IDs this technology unlocks.
|
/// How much research is needed to unlock.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("unlockedRecipes", customTypeSerializer:typeof(PrototypeIdListSerializer<LatheRecipePrototype>))]
|
[DataField("cost")]
|
||||||
public List<string> UnlockedRecipes { get; } = new();
|
public readonly int Cost = 10000;
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of <see cref="TechnologyPrototype"/>s that need to be unlocked in order to unlock this technology.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("technologyPrerequisites", customTypeSerializer: typeof(PrototypeIdListSerializer<TechnologyPrototype>))]
|
||||||
|
public readonly IReadOnlyList<string> TechnologyPrerequisites = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of <see cref="LatheRecipePrototype"/>s that are unlocked by this technology
|
||||||
|
/// </summary>
|
||||||
|
[DataField("recipeUnlocks", customTypeSerializer: typeof(PrototypeIdListSerializer<LatheRecipePrototype>))]
|
||||||
|
public readonly IReadOnlyList<string> RecipeUnlocks = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of non-standard effects that are done when this technology is unlocked.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("genericUnlocks")]
|
||||||
|
public readonly IReadOnlyList<GenericUnlock> GenericUnlocks = new List<GenericUnlock>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataDefinition]
|
||||||
|
public record struct GenericUnlock()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// What event is raised when this is unlocked?
|
||||||
|
/// Used for doing non-standard logic.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("purchaseEvent")]
|
||||||
|
public readonly object? PurchaseEvent = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A player facing tooltip for what the unlock does.
|
||||||
|
/// Supports locale strings.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("unlockDescription")]
|
||||||
|
public readonly string UnlockDescription = string.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,145 @@
|
|||||||
using Content.Shared.Research.Components;
|
using System.Linq;
|
||||||
|
using Content.Shared.Research.Components;
|
||||||
using Content.Shared.Research.Prototypes;
|
using Content.Shared.Research.Prototypes;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Shared.Research.Systems;
|
namespace Content.Shared.Research.Systems;
|
||||||
|
|
||||||
public abstract class SharedResearchSystem : EntitySystem
|
public abstract class SharedResearchSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<ResearchServerComponent, ComponentGetState>(OnServerGetState);
|
SubscribeLocalEvent<TechnologyDatabaseComponent, MapInitEvent>(OnMapInit);
|
||||||
SubscribeLocalEvent<ResearchServerComponent, ComponentHandleState>(OnServerHandleState);
|
|
||||||
SubscribeLocalEvent<TechnologyDatabaseComponent, ComponentGetState>(OnTechnologyGetState);
|
|
||||||
SubscribeLocalEvent<TechnologyDatabaseComponent, ComponentHandleState>(OnTechnologyHandleState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnServerGetState(EntityUid uid, ResearchServerComponent component, ref ComponentGetState args)
|
private void OnMapInit(EntityUid uid, TechnologyDatabaseComponent component, MapInitEvent args)
|
||||||
{
|
{
|
||||||
args.State = new ResearchServerState(component.ServerName, component.Points, component.Id);
|
UpdateTechnologyCards(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnServerHandleState(EntityUid uid, ResearchServerComponent component, ref ComponentHandleState args)
|
public void UpdateTechnologyCards(EntityUid uid, TechnologyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
if (args.Current is not ResearchServerState state)
|
if (!Resolve(uid, ref component))
|
||||||
return;
|
return;
|
||||||
component.ServerName = state.ServerName;
|
|
||||||
component.Points = state.Points;
|
var availableTechnology = GetAvailableTechnologies(uid, component);
|
||||||
component.Id = state.Id;
|
_random.Shuffle(availableTechnology);
|
||||||
|
|
||||||
|
component.CurrentTechnologyCards.Clear();
|
||||||
|
foreach (var discipline in component.SupportedDisciplines)
|
||||||
|
{
|
||||||
|
var selected = availableTechnology.FirstOrDefault(p => p.Discipline == discipline);
|
||||||
|
if (selected == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
component.CurrentTechnologyCards.Add(selected.ID);
|
||||||
|
}
|
||||||
|
Dirty(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTechnologyHandleState(EntityUid uid, TechnologyDatabaseComponent component, ref ComponentHandleState args)
|
public List<TechnologyPrototype> GetAvailableTechnologies(EntityUid uid, TechnologyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
if (args.Current is not TechnologyDatabaseState state)
|
if (!Resolve(uid, ref component, false))
|
||||||
return;
|
return new List<TechnologyPrototype>();
|
||||||
component.TechnologyIds = new (state.Technologies);
|
|
||||||
component.RecipeIds = new(state.Recipes);
|
var availableTechnologies = new List<TechnologyPrototype>();
|
||||||
|
var disciplineTiers = GetDisciplineTiers(component);
|
||||||
|
foreach (var tech in PrototypeManager.EnumeratePrototypes<TechnologyPrototype>())
|
||||||
|
{
|
||||||
|
if (IsTechnologyAvailable(component, tech, disciplineTiers))
|
||||||
|
availableTechnologies.Add(tech);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTechnologyGetState(EntityUid uid, TechnologyDatabaseComponent component, ref ComponentGetState args)
|
return availableTechnologies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsTechnologyAvailable(TechnologyDatabaseComponent component, TechnologyPrototype tech, Dictionary<string, int>? disciplineTiers = null)
|
||||||
{
|
{
|
||||||
args.State = new TechnologyDatabaseState(component.TechnologyIds, component.RecipeIds);
|
disciplineTiers ??= GetDisciplineTiers(component);
|
||||||
|
|
||||||
|
if (tech.Hidden)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!component.SupportedDisciplines.Contains(tech.Discipline))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (tech.Tier > disciplineTiers[tech.Discipline])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (component.UnlockedTechnologies.Contains(tech.ID))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var prereq in tech.TechnologyPrerequisites)
|
||||||
|
{
|
||||||
|
if (!component.UnlockedTechnologies.Contains(prereq))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, int> GetDisciplineTiers(TechnologyDatabaseComponent component)
|
||||||
|
{
|
||||||
|
var tiers = new Dictionary<string, int>();
|
||||||
|
foreach (var discipline in component.SupportedDisciplines)
|
||||||
|
{
|
||||||
|
tiers.Add(discipline, GetHighestDisciplineTier(component, discipline));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHighestDisciplineTier(TechnologyDatabaseComponent component, string disciplineId)
|
||||||
|
{
|
||||||
|
return GetHighestDisciplineTier(component, PrototypeManager.Index<TechDisciplinePrototype>(disciplineId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHighestDisciplineTier(TechnologyDatabaseComponent component, TechDisciplinePrototype techDiscipline)
|
||||||
|
{
|
||||||
|
var allTech = PrototypeManager.EnumeratePrototypes<TechnologyPrototype>()
|
||||||
|
.Where(p => p.Discipline == techDiscipline.ID && !p.Hidden).ToList();
|
||||||
|
var allUnlocked = new List<TechnologyPrototype>();
|
||||||
|
foreach (var recipe in component.UnlockedTechnologies)
|
||||||
|
{
|
||||||
|
var proto = PrototypeManager.Index<TechnologyPrototype>(recipe);
|
||||||
|
if (proto.Discipline != techDiscipline.ID)
|
||||||
|
continue;
|
||||||
|
allUnlocked.Add(proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
var highestTier = techDiscipline.TierPrerequisites.Keys.Max();
|
||||||
|
var tier = 2; //tier 1 is always given
|
||||||
|
|
||||||
|
// todo this might break if you have hidden technologies. i'm not sure
|
||||||
|
|
||||||
|
while (tier <= highestTier)
|
||||||
|
{
|
||||||
|
// we need to get the tech for the tier 1 below because that's
|
||||||
|
// what the percentage in TierPrerequisites is referring to.
|
||||||
|
var unlockedTierTech = allUnlocked.Where(p => p.Tier == tier - 1).ToList();
|
||||||
|
var allTierTech = allTech.Where(p => p.Discipline == techDiscipline.ID && p.Tier == tier - 1).ToList();
|
||||||
|
|
||||||
|
if (allTierTech.Count == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
var percent = (float) unlockedTierTech.Count / allTierTech.Count;
|
||||||
|
if (percent < techDiscipline.TierPrerequisites[tier])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (tier >= techDiscipline.LockoutTier &&
|
||||||
|
component.MainDiscipline != null &&
|
||||||
|
techDiscipline.ID != component.MainDiscipline)
|
||||||
|
break;
|
||||||
|
tier++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tier - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -58,26 +157,18 @@ public abstract class SharedResearchSystem : EntitySystem
|
|||||||
/// <returns>Whether it is unlocked or not</returns>
|
/// <returns>Whether it is unlocked or not</returns>
|
||||||
public bool IsTechnologyUnlocked(EntityUid uid, string technologyId, TechnologyDatabaseComponent? component = null)
|
public bool IsTechnologyUnlocked(EntityUid uid, string technologyId, TechnologyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
return Resolve(uid, ref component, false) && component.TechnologyIds.Contains(technologyId);
|
return Resolve(uid, ref component, false) && component.UnlockedTechnologies.Contains(technologyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void TrySetMainDiscipline(TechnologyPrototype prototype, EntityUid uid, TechnologyDatabaseComponent? component = null)
|
||||||
/// Returns whether or not all the prerequisite
|
|
||||||
/// technologies for a technology are unlocked.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="uid"></param>
|
|
||||||
/// <param name="prototype"></param>
|
|
||||||
/// <param name="component"></param>
|
|
||||||
/// <returns>Whether or not the prerequesites are present</returns>
|
|
||||||
public bool ArePrerequesitesUnlocked(EntityUid uid, TechnologyPrototype prototype, TechnologyDatabaseComponent? component = null)
|
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref component))
|
if (!Resolve(uid, ref component))
|
||||||
return false;
|
return;
|
||||||
foreach (var technologyId in prototype.RequiredTechnologies)
|
|
||||||
{
|
var discipline = PrototypeManager.Index<TechDisciplinePrototype>(prototype.Discipline);
|
||||||
if (!IsTechnologyUnlocked(uid, technologyId, component))
|
if (prototype.Tier < discipline.LockoutTier)
|
||||||
return false;
|
return;
|
||||||
}
|
component.MainDiscipline = prototype.Discipline;
|
||||||
return true;
|
Dirty(component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
technologies-basic-research-technology = Basic research technology
|
|
||||||
technologies-basic-research-technology-description = Nanotrasen basic research technologies.
|
|
||||||
|
|
||||||
technologies-cleaning-technology = Cleaning technology
|
|
||||||
technologies-cleaning-technology-description = Start to a shiny clean station.
|
|
||||||
|
|
||||||
technologies-advanced-cleaning-technology = Advanced cleaning technology
|
|
||||||
technologies-advanced-cleaning-technology-description = Advanced tools won't stop people from trashing the station, sadly.
|
|
||||||
|
|
||||||
technologies-advanced-spray-technology = Advanced spray technology
|
|
||||||
technologies-advanced-spray-technology-description = The newest ways to hose down the station. Filthy animals.
|
|
||||||
|
|
||||||
technologies-foodbev-technology = Food and beverage technology
|
|
||||||
technologies-food-and-beverage-technology-description = Robust service from better technology.
|
|
||||||
|
|
||||||
technologies-biological-technology = Biological technology
|
|
||||||
technologies-biological-technology-description = Investigations into the natural world.
|
|
||||||
|
|
||||||
technologies-advanced-botany = Advanced botany
|
|
||||||
technologies-advanced-botany-description = A better understanding of botany.
|
|
||||||
|
|
||||||
technologies-virology = Virology
|
|
||||||
technologies-virology-description = The secrets of the immune system.
|
|
||||||
|
|
||||||
technologies-advanced-surgery = Advanced surgery
|
|
||||||
technologies-advanced-surgery-description = Research new surgical procedures.
|
|
||||||
|
|
||||||
technologies-chemistry-technology = Chemistry technology
|
|
||||||
technologies-chemistry-technology-description = A crash course in chemistry.
|
|
||||||
|
|
||||||
technologies-medical-machinery = Medical machinery
|
|
||||||
technologies-medical-machinery-description = Machines any self-respecting medbay would need.
|
|
||||||
|
|
||||||
technologies-advanced-life-support = Advanced life support systems
|
|
||||||
technologies-advanced-life-support-description = The cutting edge of life and death.
|
|
||||||
|
|
||||||
technologies-salvage-equipment = Salvage equipment
|
|
||||||
technologies-salvage-equipment-description = Newer and faster resource collection.
|
|
||||||
|
|
||||||
technologies-spacefaring = Spacefaring technology
|
|
||||||
technologies-spacefaring-description = Able to bring you into the stars!
|
|
||||||
|
|
||||||
technologies-surveillance = Surveillance technology
|
|
||||||
technologies-surveillance-description = Retro-styled cameras straight from the year 1984!
|
|
||||||
|
|
||||||
technologies-industrial-engineering = Industrial engineering
|
|
||||||
technologies-industrial-engineering-description = A refresher course on modern engineering technology.
|
|
||||||
|
|
||||||
technologies-rapid-upgrade = Rapid upgrade
|
|
||||||
technologies-rapid-upgrade-description = The ability to quickly improve the station like never before.
|
|
||||||
|
|
||||||
technologies-material-sheet-printing = Material sheet printing
|
|
||||||
technologies-material-sheet-printing-description = Print those sheets!
|
|
||||||
|
|
||||||
technologies-electromagnetic-theory = Electromagnetic theory
|
|
||||||
technologies-electromagnetic-theory-description = Try not to fry yourself.
|
|
||||||
|
|
||||||
technologies-electrical-engineering = Electrical engineering
|
|
||||||
technologies-electrical-engineering-description = Machinery used to keep the station stable.
|
|
||||||
|
|
||||||
technologies-advanced-atmospherics-technology = Advanced atmospherics technology
|
|
||||||
technologies-advanced-atmospherics-technology-description = As if it can get more advanced.
|
|
||||||
|
|
||||||
technologies-compact-power-technology = Compact power technology
|
|
||||||
technologies-compact-power-technology-description = Power, but smaller.
|
|
||||||
|
|
||||||
technologies-applied-musicology = Applied musicology
|
|
||||||
technologies-applied-musicology-description = Bringing you the latest in audio-audio technology.
|
|
||||||
|
|
||||||
technologies-basic-powercell-printing = Basic powercell printing
|
|
||||||
technologies-basic-powercell-printing-description = Print standard powercells.
|
|
||||||
|
|
||||||
technologies-advanced-powercell-printing = Advanced powercell printing
|
|
||||||
technologies-advanced-powercell-printing-description = Print advanced powercells.
|
|
||||||
|
|
||||||
technologies-super-powercell-printing = Super powercell printing
|
|
||||||
technologies-super-powercell-printing-description = Print super powercells.
|
|
||||||
|
|
||||||
technologies-scientific-technology = Scientific technology
|
|
||||||
technologies-scientific-technology-description = The basics of a research team's supplies.
|
|
||||||
|
|
||||||
technologies-anomaly-technology = Anomaly technology
|
|
||||||
technologies-anomaly-technology-description = Machines for advanced anomaly containment.
|
|
||||||
|
|
||||||
technologies-robotics-technology = Robotics technology
|
|
||||||
technologies-robotics-technology-description = Parts needed for constructing mechanized friends.
|
|
||||||
|
|
||||||
technologies-archaeology = Archeological equipment
|
|
||||||
technologies-archaeology-description = Advanced equipment for uncovering the secrets of artifacts.
|
|
||||||
|
|
||||||
technologies-ripley-technology = Exosuit: Ripley
|
|
||||||
technologies-ripley-technology-description = The latest and greatest in mechanized cargo construction.
|
|
||||||
|
|
||||||
technologies-clown-technology = Exosuit: H.O.N.K.
|
|
||||||
technologies-clown-technology-description = Honk?!
|
|
||||||
|
|
||||||
technologies-adv-parts-technology-description = Like the previous ones, but better!
|
|
||||||
technologies-adv-parts-technology = Advanced parts technology
|
|
||||||
|
|
||||||
technologies-super-parts-technology = Super parts technology
|
|
||||||
technologies-super-parts-technology-description = New heights of machine performance.
|
|
||||||
|
|
||||||
technologies-magboots-technology = Magboots technology
|
|
||||||
technologies-magboots-technology-description = Magboots for a space escape from the assistant.
|
|
||||||
|
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
## UI
|
## UI
|
||||||
|
|
||||||
research-console-menu-title = R&D Console
|
research-console-menu-title = R&D Console
|
||||||
research-console-menu-unlocked-technologies-label = Unlocked technologies
|
research-console-menu-research-points-text = Research: [color=orchid]{$points}[/color]
|
||||||
research-console-menu-unlockable-technologies-label = Unlockable technologies
|
research-console-menu-main-discipline = Main Discipline: [color={$color}]{$name}[/color]
|
||||||
research-console-menu-future-technologies-label = Future technologies
|
|
||||||
research-console-menu-research-points-text = Research Points: {$points}
|
|
||||||
research-console-menu-points-per-second-text = Points per Second {$pointsPerSecond}
|
|
||||||
research-console-menu-server-selection-button = Server list
|
research-console-menu-server-selection-button = Server list
|
||||||
research-console-menu-server-sync-button = Sync
|
research-console-menu-server-sync-button = Sync
|
||||||
research-console-menu-server-unlock-button = Unlock
|
research-console-menu-server-research-button = Research
|
||||||
research-console-tech-requirements-none = No technology requirements.
|
research-console-available-text = Researchable Technologies
|
||||||
research-console-tech-requirements-prototype-name = Requires: {$prototypeName}
|
research-console-unlocked-text = Unlocked Technologies
|
||||||
|
research-console-tier-discipline-info = Tier {$tier}, [color={$color}]{$discipline}[/color]
|
||||||
|
research-console-tier-info-small = : Tier {$tier}
|
||||||
|
research-console-cost = Cost: [color=orchid]{$amount}[/color]
|
||||||
|
research-console-unlocks-list-start = Unlocks:
|
||||||
|
research-console-unlocks-list-entry = - [color=yellow]{$name}[/color]
|
||||||
|
research-console-unlocks-list-entry-generic = - [color=green]{$text}[/color]
|
||||||
|
|||||||
51
Resources/Locale/en-US/research/technologies.ftl
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
research-discipline-none = None
|
||||||
|
research-discipline-industrial = Industrial
|
||||||
|
research-discipline-biochemical = Biochemical
|
||||||
|
research-discipline-experimental = Experimental
|
||||||
|
research-discipline-civilian-services = Civilian Services
|
||||||
|
|
||||||
|
research-technology-salvage-equipment = Salvage Equipment
|
||||||
|
research-technology-advanced-powercells = Advanced Powercells
|
||||||
|
research-technology-compact-power = Compact Power
|
||||||
|
research-technology-industrial-engineering = Industrial Engineering
|
||||||
|
research-technology-power-generation = Power Generation
|
||||||
|
research-technology-atmospheric-tech = Atmospherics
|
||||||
|
research-technology-rapid-construction = Rapid Construction
|
||||||
|
research-technology-shuttlecraft = Shuttlecraft
|
||||||
|
research-technology-ripley-aplu = Ripley APLU
|
||||||
|
research-technology-advanced-atmospherics = Advanced Atmospherics
|
||||||
|
research-technology-super-powercells = Super Powercells
|
||||||
|
research-technology-bluespace-storage = Bluespace Storage
|
||||||
|
|
||||||
|
research-technology-chemistry = Chemistry
|
||||||
|
research-technology-surgical-tools = Surgical Tools
|
||||||
|
research-technology-biochemical-stasis = Biochemical Stasis
|
||||||
|
research-technology-virology = Virology
|
||||||
|
research-technology-cryogenics = Cryogenics
|
||||||
|
research-technology-chemical-dispensary = Chemical Dispensary
|
||||||
|
research-technology-crew-monitoring = Crew Monitoring
|
||||||
|
research-technology-cloning = Cloning
|
||||||
|
|
||||||
|
research-technology-basic-robotics = Basic Robotics
|
||||||
|
research-technology-signalling-tech = Signalling Tech
|
||||||
|
research-technology-basic-anomalous-research = Basic Anomalous Research
|
||||||
|
research-technology-basic-xenoarcheology = Basic XenoArcheology
|
||||||
|
research-technology-alternative-research = Alternative Research
|
||||||
|
research-technology-magnets-tech = Localized Magnetism
|
||||||
|
research-technology-advanced-parts = Advanced Parts
|
||||||
|
research-technology-abnormal-artifact-manipulation = Abnormal Artifact Manipulation
|
||||||
|
research-technology-mobile-anomaly-tech = Mobile Anomaly Tech
|
||||||
|
research-technology-rped = Rapid Part Exchange
|
||||||
|
research-technology-super-parts = Super Parts
|
||||||
|
|
||||||
|
research-technology-janitorial-equipment = Janitorial Equipment
|
||||||
|
research-technology-laundry-tech = Laundry Tech
|
||||||
|
research-technology-basic-hydroponics = Basic Hydroponics
|
||||||
|
research-technology-food-service = Food Service
|
||||||
|
research-technology-advanced-entertainment = Advanced Entertainment
|
||||||
|
research-technology-audio-visual-communication = A/V Communication
|
||||||
|
research-technology-advanced-cleaning = Advanced Cleaning
|
||||||
|
research-technology-meat-manipulation = Meat Manipulation
|
||||||
|
research-technology-honk-mech = H.O.N.K. Mech
|
||||||
|
research-technology-advanced-spray = Advanced Spray
|
||||||
|
|
||||||
@@ -1,655 +0,0 @@
|
|||||||
# In order to make this list somewhat organized, please place
|
|
||||||
# new technologies underneath their overarching "base" technology.
|
|
||||||
|
|
||||||
# Base Technology
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-basic-research-technology
|
|
||||||
id: BasicResearch
|
|
||||||
description: technologies-basic-research-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Machines/server.rsi
|
|
||||||
state: server-on
|
|
||||||
requiredPoints: 2500
|
|
||||||
|
|
||||||
# Cleaning Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-cleaning-technology
|
|
||||||
id: CleaningTechnology
|
|
||||||
description: technologies-cleaning-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Janitorial/janitorial.rsi
|
|
||||||
state: mopbucket
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- Bucket
|
|
||||||
- MopItem
|
|
||||||
- SprayBottle
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-advanced-cleaning-technology
|
|
||||||
id: AdvancedCleaningTechnology
|
|
||||||
description: technologies-advanced-cleaning-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Janitorial/advmop.rsi
|
|
||||||
state: advmop
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- CleaningTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- AdvMopItem
|
|
||||||
- MegaSprayBottle
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
id: AdvancedSprayTechnology
|
|
||||||
name: technologies-advanced-spray-technology
|
|
||||||
description: technologies-advanced-spray-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Weapons/Guns/Basic/spraynozzle.rsi
|
|
||||||
state: icon
|
|
||||||
requiredPoints: 7500
|
|
||||||
requiredTechnologies:
|
|
||||||
- AdvancedCleaningTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- WeaponSprayNozzle
|
|
||||||
- ClothingBackpackWaterTank
|
|
||||||
|
|
||||||
# Food/Bev Service Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-foodbev-technology
|
|
||||||
id: FoodBevTechnology
|
|
||||||
description: technologies-food-and-beverage-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Weapons/Melee/cleaver.rsi
|
|
||||||
state: butch
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- ButchCleaver
|
|
||||||
- KitchenKnife
|
|
||||||
- MicrowaveMachineCircuitboard
|
|
||||||
- BoozeDispenserMachineCircuitboard
|
|
||||||
- SodaDispenserMachineCircuitboard
|
|
||||||
- FatExtractorMachineCircuitboard
|
|
||||||
|
|
||||||
# Biological Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-biological-technology
|
|
||||||
id: BiologicalTechnology
|
|
||||||
description: technologies-biological-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Furniture/potted_plants.rsi
|
|
||||||
state: applebush
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- HydroponicsToolScythe
|
|
||||||
- HydroponicsToolHatchet
|
|
||||||
- Shovel
|
|
||||||
- MiniHoe
|
|
||||||
- Spade
|
|
||||||
- Clippers
|
|
||||||
- ButchCleaver
|
|
||||||
- KitchenKnife
|
|
||||||
- MicrowaveMachineCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-advanced-botany
|
|
||||||
id: AdvancedBotany
|
|
||||||
description: technologies-advanced-botany-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Hydroponics/potato.rsi
|
|
||||||
state: seed
|
|
||||||
requiredPoints: 15000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BiologicalTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- SeedExtractorMachineCircuitboard
|
|
||||||
- HydroponicsTrayMachineCircuitboard
|
|
||||||
- Vape
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-virology
|
|
||||||
id: Virology
|
|
||||||
description: technologies-virology-description
|
|
||||||
icon:
|
|
||||||
sprite: Clothing/Mask/sterile.rsi
|
|
||||||
state: icon
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BiologicalTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- VaccinatorMachineCircuitboard
|
|
||||||
- DiagnoserMachineCircuitboard
|
|
||||||
|
|
||||||
# Medical Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-chemistry-technology
|
|
||||||
id: ChemistryTechnology
|
|
||||||
description: technologies-chemistry-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Chemistry/beaker_large.rsi
|
|
||||||
state: beakerlarge
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- Beaker
|
|
||||||
- LargeBeaker
|
|
||||||
- CryostasisBeaker
|
|
||||||
- Dropper
|
|
||||||
- Syringe
|
|
||||||
- ReagentGrinderMachineCircuitboard
|
|
||||||
- HotplateMachineCircuitboard
|
|
||||||
- PillCanister
|
|
||||||
- ChemistryEmptyBottle01
|
|
||||||
- ChemicalPayload
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-advanced-surgery
|
|
||||||
id: AdvancedSugery
|
|
||||||
description: technologies-advanced-surgery-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Medical/Surgery/saw.rsi
|
|
||||||
state: saw
|
|
||||||
requiredPoints: 7500
|
|
||||||
requiredTechnologies:
|
|
||||||
- BiologicalTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- Scalpel
|
|
||||||
- Retractor
|
|
||||||
- Cautery
|
|
||||||
- Drill
|
|
||||||
- Saw
|
|
||||||
- Hemostat
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-medical-machinery
|
|
||||||
id: MedicalMachinery
|
|
||||||
description: technologies-medical-machinery-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/dispensers.rsi
|
|
||||||
state: industrial-working
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BiologicalTechnology
|
|
||||||
- ChemistryTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- ChemMasterMachineCircuitboard
|
|
||||||
- ChemDispenserMachineCircuitboard
|
|
||||||
- HandheldCrewMonitor
|
|
||||||
- BiomassReclaimerMachineCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-advanced-life-support
|
|
||||||
id: AdvancedLifeSupport
|
|
||||||
description: technologies-advanced-life-support-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Machines/cloning.rsi
|
|
||||||
state: pod_0
|
|
||||||
requiredPoints: 20000
|
|
||||||
requiredTechnologies:
|
|
||||||
- MedicalMachinery
|
|
||||||
- Virology
|
|
||||||
unlockedRecipes:
|
|
||||||
- CloningPodMachineCircuitboard
|
|
||||||
- MedicalScannerMachineCircuitboard
|
|
||||||
- StasisBedMachineCircuitboard
|
|
||||||
- CloningConsoleComputerCircuitboard
|
|
||||||
- CryoPodMachineCircuitboard
|
|
||||||
|
|
||||||
# Security Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-surveillance
|
|
||||||
id: SurveillanceTechnology
|
|
||||||
description: technologies-surveillance-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Wallmounts/camera.rsi
|
|
||||||
state: cameracase
|
|
||||||
requiredPoints: 12500
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- SurveillanceCameraRouterCircuitboard
|
|
||||||
- SurveillanceCameraWirelessRouterCircuitboard
|
|
||||||
- SurveillanceWirelessCameraMovableCircuitboard
|
|
||||||
- SurveillanceWirelessCameraAnchoredCircuitboard
|
|
||||||
- SurveillanceCameraMonitorCircuitboard
|
|
||||||
- SurveillanceWirelessCameraMonitorCircuitboard
|
|
||||||
- ComputerTelevisionCircuitboard
|
|
||||||
|
|
||||||
#- type: technology
|
|
||||||
# name: "ballistic technology"
|
|
||||||
# id: BallisticTechnology
|
|
||||||
# description: Just a fancy term for guns.
|
|
||||||
# icon:
|
|
||||||
# sprite: Objects/Weapons/Guns/Pistols/mk58.rsi
|
|
||||||
# state: icon
|
|
||||||
# requiredPoints: 15000
|
|
||||||
# requiredTechnologies:
|
|
||||||
# - SecurityTechnology
|
|
||||||
#
|
|
||||||
# - type: technology
|
|
||||||
# name: "direct energy technology"
|
|
||||||
# id: DirectEnergyTechnology
|
|
||||||
# description: Basically laser guns.
|
|
||||||
# icon:
|
|
||||||
# sprite: Objects/Weapons/Guns/Battery/taser.rsi
|
|
||||||
# state: icon
|
|
||||||
# requiredPoints: 15000
|
|
||||||
# requiredTechnologies:
|
|
||||||
# - SecurityTechnology
|
|
||||||
#
|
|
||||||
# - type: technology
|
|
||||||
# name: "explosives technology"
|
|
||||||
# id: ExplosivesTechnology
|
|
||||||
# description: Let's just start with grenades for now.
|
|
||||||
# icon:
|
|
||||||
# sprite: Objects/Weapons/Grenades/flashbang.rsi
|
|
||||||
# state: icon
|
|
||||||
# requiredPoints: 15000
|
|
||||||
# requiredTechnologies:
|
|
||||||
# - SecurityTechnology
|
|
||||||
#
|
|
||||||
# - type: technology
|
|
||||||
# name: "armor technology"
|
|
||||||
# id: ArmorTechnology
|
|
||||||
# description: Basic protective gear for security personnel.
|
|
||||||
# icon:
|
|
||||||
# sprite: Clothing/OuterClothing/Vests/kevlar.rsi
|
|
||||||
# state: icon
|
|
||||||
# requiredPoints: 15000
|
|
||||||
# requiredTechnologies:
|
|
||||||
# - SecurityTechnology
|
|
||||||
|
|
||||||
# Salvage Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-salvage-equipment
|
|
||||||
id: SalvageEquipment
|
|
||||||
description: technologies-salvage-equipment-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Tools/handdrill.rsi
|
|
||||||
state: handdrill
|
|
||||||
requiredPoints: 7500
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- AppraisalTool
|
|
||||||
- MiningDrill
|
|
||||||
- OreProcessorMachineCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-spacefaring
|
|
||||||
id: SpacefaringTechnology
|
|
||||||
description: technologies-spacefaring-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Shuttles/gyroscope.rsi
|
|
||||||
state: base
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- SalvageEquipment
|
|
||||||
- IndustrialEngineering
|
|
||||||
unlockedRecipes:
|
|
||||||
- ShuttleConsoleCircuitboard
|
|
||||||
- RadarConsoleCircuitboard
|
|
||||||
- ThrusterMachineCircuitboard
|
|
||||||
- GyroscopeMachineCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-ripley-technology
|
|
||||||
id: RipleyTechnology
|
|
||||||
description: technologies-ripley-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Mech/mecha.rsi
|
|
||||||
state: ripley
|
|
||||||
requiredPoints: 30000
|
|
||||||
requiredTechnologies:
|
|
||||||
- SalvageEquipment
|
|
||||||
unlockedRecipes:
|
|
||||||
- RipleyCentralElectronics
|
|
||||||
- RipleyPeripheralsElectronics
|
|
||||||
- MechEquipmentGrabber
|
|
||||||
- RipleyHarness
|
|
||||||
- RipleyLArm
|
|
||||||
- RipleyRArm
|
|
||||||
- RipleyLLeg
|
|
||||||
- RipleyRLeg
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-clown-technology
|
|
||||||
id: ClownTechnology
|
|
||||||
description: technologies-clown-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Mech/mecha.rsi
|
|
||||||
state: honker
|
|
||||||
requiredPoints: 15000
|
|
||||||
requiredTechnologies:
|
|
||||||
- RipleyTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- HonkerCentralElectronics
|
|
||||||
- HonkerPeripheralsElectronics
|
|
||||||
- HonkerTargetingElectronics
|
|
||||||
- MechEquipmentHorn
|
|
||||||
- HonkerHarness
|
|
||||||
- HonkerLArm
|
|
||||||
- HonkerRArm
|
|
||||||
- HonkerLLeg
|
|
||||||
- HonkerRLeg
|
|
||||||
|
|
||||||
# Industrial Engineering Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-industrial-engineering
|
|
||||||
id: IndustrialEngineering
|
|
||||||
description: technologies-industrial-engineering-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Machines/protolathe.rsi
|
|
||||||
state: icon
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- IntercomElectronics
|
|
||||||
- ConveyorBeltAssembly
|
|
||||||
- FlashlightLantern
|
|
||||||
- FireExtinguisher
|
|
||||||
- FirelockElectronics
|
|
||||||
- DoorElectronics
|
|
||||||
- AutolatheMachineCircuitboard
|
|
||||||
- ProtolatheMachineCircuitboard
|
|
||||||
- CircuitImprinterMachineCircuitboard
|
|
||||||
- UniformPrinterMachineCircuitboard
|
|
||||||
- AirAlarmElectronics
|
|
||||||
- FireAlarmElectronics
|
|
||||||
- MailingUnitElectronics
|
|
||||||
- SignalTimerElectronics
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-material-sheet-printing
|
|
||||||
id: Sheets
|
|
||||||
description: technologies-material-sheet-printing-description
|
|
||||||
icon: Objects/Materials/Sheets/researchicon.png
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- IndustrialEngineering
|
|
||||||
unlockedRecipes:
|
|
||||||
- SheetSteel
|
|
||||||
- SheetPlastic
|
|
||||||
- SheetRGlass
|
|
||||||
- SheetGlass1
|
|
||||||
- MaterialReclaimerMachineCircuitboard
|
|
||||||
|
|
||||||
# Electromagnetic Theory Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-electromagnetic-theory
|
|
||||||
id: ElectromagneticTheory
|
|
||||||
description: technologies-electromagnetic-theory-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Power/apc.rsi
|
|
||||||
state: base
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- CableStack
|
|
||||||
- CableMVStack
|
|
||||||
- CableHVStack
|
|
||||||
- LightBulb
|
|
||||||
- LightTube
|
|
||||||
- APCElectronics
|
|
||||||
- SubstationMachineCircuitboard
|
|
||||||
- Signaller
|
|
||||||
- SignalTrigger
|
|
||||||
- VoiceTrigger
|
|
||||||
- TimerTrigger
|
|
||||||
- TelecomServerCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-electrical-engineering
|
|
||||||
id: ElectricalEngineering
|
|
||||||
description: technologies-electrical-engineering-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Power/Generation/Singularity/emitter.rsi
|
|
||||||
state: emitter1
|
|
||||||
requiredPoints: 15000
|
|
||||||
requiredTechnologies:
|
|
||||||
- ElectromagneticTheory
|
|
||||||
- IndustrialEngineering
|
|
||||||
unlockedRecipes:
|
|
||||||
- PowerDrill
|
|
||||||
- SMESMachineCircuitboard
|
|
||||||
- PowerComputerCircuitboard
|
|
||||||
- GeneratorPlasmaMachineCircuitboard
|
|
||||||
- GeneratorUraniumMachineCircuitboard
|
|
||||||
- SolarControlComputerCircuitboard
|
|
||||||
- EmitterCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-advanced-atmospherics-technology
|
|
||||||
id: AdvancedAtmosTechnology
|
|
||||||
description: technologies-advanced-atmospherics-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Piping/Atmospherics/thermomachine.rsi
|
|
||||||
state: freezerOff
|
|
||||||
requiredPoints: 7500
|
|
||||||
requiredTechnologies:
|
|
||||||
- ElectricalEngineering
|
|
||||||
unlockedRecipes:
|
|
||||||
- HolofanProjector
|
|
||||||
- ThermomachineFreezerMachineCircuitBoard
|
|
||||||
- PortableScrubberMachineCircuitBoard
|
|
||||||
- GasRecyclerMachineCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-rapid-upgrade
|
|
||||||
id: RapidUpgrade
|
|
||||||
description: technologies-rapid-upgrade-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Research/rped.rsi
|
|
||||||
state: icon
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- ElectricalEngineering
|
|
||||||
unlockedRecipes:
|
|
||||||
- RCD
|
|
||||||
- RCDAmmo
|
|
||||||
- RPED
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-compact-power-technology
|
|
||||||
id: CompactPowerTechnology
|
|
||||||
description: technologies-compact-power-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Power/Generation/wallmount_generator.rsi
|
|
||||||
state: panel
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- ElectromagneticTheory
|
|
||||||
unlockedRecipes:
|
|
||||||
- WallmountSubstationElectronics
|
|
||||||
- WallmountGeneratorElectronics
|
|
||||||
- WallmountGeneratorAPUElectronics
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-basic-powercell-printing
|
|
||||||
id: PowerCellBasic
|
|
||||||
description: technologies-basic-powercell-printing-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Power/power_cells.rsi
|
|
||||||
state: small
|
|
||||||
requiredPoints: 2500
|
|
||||||
requiredTechnologies:
|
|
||||||
- ElectromagneticTheory
|
|
||||||
unlockedRecipes:
|
|
||||||
- PowerCellSmall
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-advanced-powercell-printing
|
|
||||||
id: PowerCellAdvanced
|
|
||||||
description: technologies-advanced-powercell-printing-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Power/power_cells.rsi
|
|
||||||
state: medium
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- PowerCellBasic
|
|
||||||
unlockedRecipes:
|
|
||||||
- PowerCellMedium
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-super-powercell-printing
|
|
||||||
id: PowerCellSuper
|
|
||||||
description: technologies-super-powercell-printing-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Power/power_cells.rsi
|
|
||||||
state: high
|
|
||||||
requiredPoints: 7500
|
|
||||||
requiredTechnologies:
|
|
||||||
- PowerCellAdvanced
|
|
||||||
unlockedRecipes:
|
|
||||||
- PowerCellHigh
|
|
||||||
|
|
||||||
# Entertainment Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-applied-musicology
|
|
||||||
id: AppliedMusicology
|
|
||||||
description: technologies-applied-musicology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Fun/Instruments/h_synthesizer.rsi
|
|
||||||
state: icon
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- SynthesizerInstrument
|
|
||||||
- DawInstrumentMachineCircuitboard
|
|
||||||
|
|
||||||
# Science Technology Tree
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-scientific-technology
|
|
||||||
id: ScientificTechnology
|
|
||||||
description: technologies-scientific-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Misc/stock_parts.rsi
|
|
||||||
state: micro_mani
|
|
||||||
requiredPoints: 5000
|
|
||||||
requiredTechnologies:
|
|
||||||
- BasicResearch
|
|
||||||
unlockedRecipes:
|
|
||||||
- TechDiskComputerCircuitboard
|
|
||||||
- CapacitorStockPart
|
|
||||||
- MatterBinStockPart
|
|
||||||
- MicroManipulatorStockPart
|
|
||||||
- NodeScanner
|
|
||||||
- AnomalyScanner
|
|
||||||
- AnomalyLocator
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-anomaly-technology
|
|
||||||
id: AnomalyTechnology
|
|
||||||
description: technologies-anomaly-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Structures/Machines/Anomaly/ape.rsi
|
|
||||||
state: base
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- ScientificTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- AnomalyVesselCircuitboard
|
|
||||||
- APECircuitboard
|
|
||||||
- WeaponPistolCHIMP
|
|
||||||
- CartridgeAnomalousParticleDelta
|
|
||||||
- CartridgeAnomalousParticleEpsilon
|
|
||||||
- CartridgeAnomalousParticleZeta
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-robotics-technology
|
|
||||||
id: RoboticsTechnology
|
|
||||||
description: technologies-robotics-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Mobs/Silicon/Bots/honkbot.rsi
|
|
||||||
state: honkbot
|
|
||||||
requiredPoints: 7500
|
|
||||||
requiredTechnologies:
|
|
||||||
- ScientificTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- ProximitySensor
|
|
||||||
- LeftArmBorg
|
|
||||||
- LightHeadBorg
|
|
||||||
- RightArmBorg
|
|
||||||
- LeftLegBorg
|
|
||||||
- RightLegBorg
|
|
||||||
- Drone
|
|
||||||
- ExosuitFabricatorMachineCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-archaeology
|
|
||||||
id: ArchaeologicalEquipment
|
|
||||||
description: technologies-archaeology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Specific/Xenoarchaeology/xeno_artifacts.rsi
|
|
||||||
state: ano01
|
|
||||||
requiredPoints: 10000
|
|
||||||
requiredTechnologies:
|
|
||||||
- ScientificTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- AnalysisComputerCircuitboard
|
|
||||||
- ArtifactAnalyzerMachineCircuitboard
|
|
||||||
- TraversalDistorterMachineCircuitboard
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-adv-parts-technology
|
|
||||||
id: AdvancedPartsTechnology
|
|
||||||
description: technologies-adv-parts-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Misc/stock_parts.rsi
|
|
||||||
state: adv_capacitor
|
|
||||||
requiredPoints: 15000
|
|
||||||
requiredTechnologies:
|
|
||||||
- ScientificTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- AdvancedCapacitorStockPart
|
|
||||||
- AdvancedMatterBinStockPart
|
|
||||||
- NanoManipulatorStockPart
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-magboots-technology
|
|
||||||
id: MagbootsTechnology
|
|
||||||
description: technologies-magboots-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Clothing/Shoes/Boots/magboots.rsi
|
|
||||||
state: icon
|
|
||||||
requiredPoints: 8500
|
|
||||||
requiredTechnologies:
|
|
||||||
- ScientificTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- ClothingShoesBootsMag
|
|
||||||
|
|
||||||
- type: technology
|
|
||||||
name: technologies-super-parts-technology
|
|
||||||
id: SuperPartsTechnology
|
|
||||||
description: technologies-super-parts-technology-description
|
|
||||||
icon:
|
|
||||||
sprite: Objects/Misc/stock_parts.rsi
|
|
||||||
state: super_capacitor
|
|
||||||
requiredPoints: 20000
|
|
||||||
requiredTechnologies:
|
|
||||||
- AdvancedPartsTechnology
|
|
||||||
- CompactPowerTechnology
|
|
||||||
unlockedRecipes:
|
|
||||||
- SuperCapacitorStockPart
|
|
||||||
- SuperMatterBinStockPart
|
|
||||||
- PicoManipulatorStockPart
|
|
||||||
@@ -76,12 +76,37 @@
|
|||||||
- Multitool
|
- Multitool
|
||||||
- NetworkConfigurator
|
- NetworkConfigurator
|
||||||
- AirlockPainter
|
- AirlockPainter
|
||||||
|
- FlashlightLantern
|
||||||
- CableStack
|
- CableStack
|
||||||
|
- CableMVStack
|
||||||
|
- CableHVStack
|
||||||
- HandheldGPSBasic
|
- HandheldGPSBasic
|
||||||
- TRayScanner
|
- TRayScanner
|
||||||
- GasAnalyzer
|
- GasAnalyzer
|
||||||
- UtilityBelt
|
- UtilityBelt
|
||||||
- Pickaxe
|
- Pickaxe
|
||||||
|
- AppraisalTool
|
||||||
|
- SheetRGlass
|
||||||
|
- Beaker
|
||||||
|
- Syringe
|
||||||
|
- LightTube
|
||||||
|
- LightBulb
|
||||||
|
- Bucket
|
||||||
|
- SprayBottle
|
||||||
|
- PowerCellSmall
|
||||||
|
- MicroManipulatorStockPart
|
||||||
|
- MatterBinStockPart
|
||||||
|
- CapacitorStockPart
|
||||||
|
- ConveyorBeltAssembly
|
||||||
|
- IntercomElectronics
|
||||||
|
- FirelockElectronics
|
||||||
|
- DoorElectronics
|
||||||
|
- AirAlarmElectronics
|
||||||
|
- FireAlarmElectronics
|
||||||
|
- MailingUnitElectronics
|
||||||
|
- APCElectronics
|
||||||
|
- SMESMachineCircuitboard
|
||||||
|
- SubstationMachineCircuitboard
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 800
|
price: 800
|
||||||
|
|
||||||
@@ -159,29 +184,12 @@
|
|||||||
idleState: icon
|
idleState: icon
|
||||||
runningState: building
|
runningState: building
|
||||||
dynamicRecipes:
|
dynamicRecipes:
|
||||||
- LightTube
|
|
||||||
- LightBulb
|
|
||||||
- SheetSteel #these sheet recipe costs don't scale with upgrades
|
|
||||||
- SheetGlass1
|
|
||||||
- SheetRGlass
|
|
||||||
- SheetPlastic
|
|
||||||
- CableStack
|
|
||||||
- CableMVStack
|
|
||||||
- CableHVStack
|
|
||||||
- PowerDrill
|
- PowerDrill
|
||||||
- MiningDrill
|
- MiningDrill
|
||||||
- ConveyorBeltAssembly
|
|
||||||
- AppraisalTool
|
|
||||||
- AnomalyScanner
|
- AnomalyScanner
|
||||||
- AnomalyLocator
|
- AnomalyLocator
|
||||||
- RCD
|
- RCD
|
||||||
- RCDAmmo
|
- RCDAmmo
|
||||||
- HydroponicsToolScythe
|
|
||||||
- HydroponicsToolHatchet
|
|
||||||
- Clippers
|
|
||||||
- MiniHoe
|
|
||||||
- Shovel
|
|
||||||
- Spade
|
|
||||||
- HandheldCrewMonitor
|
- HandheldCrewMonitor
|
||||||
- Scalpel
|
- Scalpel
|
||||||
- Retractor
|
- Retractor
|
||||||
@@ -198,42 +206,28 @@
|
|||||||
- PillCanister
|
- PillCanister
|
||||||
- ChemistryEmptyBottle01
|
- ChemistryEmptyBottle01
|
||||||
- Drone
|
- Drone
|
||||||
- Flash
|
|
||||||
- MicroManipulatorStockPart
|
|
||||||
- MatterBinStockPart
|
|
||||||
- CapacitorStockPart
|
|
||||||
- AdvancedCapacitorStockPart
|
- AdvancedCapacitorStockPart
|
||||||
- AdvancedMatterBinStockPart
|
- AdvancedMatterBinStockPart
|
||||||
- NanoManipulatorStockPart
|
- NanoManipulatorStockPart
|
||||||
- SuperCapacitorStockPart
|
- SuperCapacitorStockPart
|
||||||
- SuperMatterBinStockPart
|
- SuperMatterBinStockPart
|
||||||
- PicoManipulatorStockPart
|
- PicoManipulatorStockPart
|
||||||
- FirelockElectronics
|
|
||||||
- DoorElectronics
|
|
||||||
- APCElectronics
|
|
||||||
- AirAlarmElectronics
|
|
||||||
- FireAlarmElectronics
|
|
||||||
- IntercomElectronics
|
|
||||||
- MailingUnitElectronics
|
|
||||||
- SignalTimerElectronics
|
- SignalTimerElectronics
|
||||||
- Bucket
|
|
||||||
- MopItem
|
- MopItem
|
||||||
|
- Holoprojector
|
||||||
|
- Mousetrap
|
||||||
|
- LightReplacer
|
||||||
|
- TrashBag
|
||||||
- AdvMopItem
|
- AdvMopItem
|
||||||
- WeaponSprayNozzle
|
- WeaponSprayNozzle
|
||||||
- ClothingBackpackWaterTank
|
- ClothingBackpackWaterTank
|
||||||
- SprayBottle
|
|
||||||
- MegaSprayBottle
|
- MegaSprayBottle
|
||||||
- FireExtinguisher
|
|
||||||
- KitchenKnife
|
|
||||||
- ButchCleaver
|
|
||||||
- FlashlightLantern
|
|
||||||
- TimerTrigger
|
- TimerTrigger
|
||||||
- ChemicalPayload
|
- ChemicalPayload
|
||||||
- FlashPayload
|
- FlashPayload
|
||||||
- Signaller
|
- Signaller
|
||||||
- SignalTrigger
|
- SignalTrigger
|
||||||
- VoiceTrigger
|
- VoiceTrigger
|
||||||
- PowerCellSmall
|
|
||||||
- PowerCellMedium
|
- PowerCellMedium
|
||||||
- PowerCellHigh
|
- PowerCellHigh
|
||||||
- WeaponPistolCHIMP
|
- WeaponPistolCHIMP
|
||||||
@@ -245,7 +239,9 @@
|
|||||||
- ClothingShoesBootsMag
|
- ClothingShoesBootsMag
|
||||||
- NodeScanner
|
- NodeScanner
|
||||||
- HolofanProjector
|
- HolofanProjector
|
||||||
- Vape
|
- ClothingBackpackHolding
|
||||||
|
- ClothingBackpackSatchelHolding
|
||||||
|
- ClothingBackpackDuffelHolding
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: Protolathe
|
parent: Protolathe
|
||||||
@@ -271,16 +267,7 @@
|
|||||||
idleState: icon
|
idleState: icon
|
||||||
runningState: building
|
runningState: building
|
||||||
dynamicRecipes:
|
dynamicRecipes:
|
||||||
- FirelockElectronics
|
|
||||||
- DoorElectronics
|
|
||||||
- APCElectronics
|
|
||||||
- AirAlarmElectronics
|
|
||||||
- FireAlarmElectronics
|
|
||||||
- MailingUnitElectronics
|
|
||||||
- IntercomElectronics
|
|
||||||
- SignalTimerElectronics
|
- SignalTimerElectronics
|
||||||
- SMESMachineCircuitboard
|
|
||||||
- SubstationMachineCircuitboard
|
|
||||||
- ThermomachineFreezerMachineCircuitBoard
|
- ThermomachineFreezerMachineCircuitBoard
|
||||||
- PortableScrubberMachineCircuitBoard
|
- PortableScrubberMachineCircuitBoard
|
||||||
- CloningPodMachineCircuitboard
|
- CloningPodMachineCircuitboard
|
||||||
@@ -492,16 +479,7 @@
|
|||||||
- ClothingHandsGlovesLatex
|
- ClothingHandsGlovesLatex
|
||||||
- ClothingMaskSterile
|
- ClothingMaskSterile
|
||||||
- DiseaseSwab
|
- DiseaseSwab
|
||||||
- Scalpel
|
|
||||||
- Retractor
|
|
||||||
- Cautery
|
|
||||||
- Drill
|
|
||||||
- Saw
|
|
||||||
- Hemostat
|
|
||||||
- Beaker
|
- Beaker
|
||||||
- LargeBeaker
|
|
||||||
- CryostasisBeaker
|
|
||||||
- Dropper
|
|
||||||
- Syringe
|
- Syringe
|
||||||
- Implanter
|
- Implanter
|
||||||
- PillCanister
|
- PillCanister
|
||||||
@@ -518,6 +496,15 @@
|
|||||||
dynamicRecipes:
|
dynamicRecipes:
|
||||||
- HandheldCrewMonitor
|
- HandheldCrewMonitor
|
||||||
- ClothingHandsGlovesNitrile
|
- ClothingHandsGlovesNitrile
|
||||||
|
- CryostasisBeaker
|
||||||
|
- LargeBeaker
|
||||||
|
- Dropper
|
||||||
|
- Scalpel
|
||||||
|
- Retractor
|
||||||
|
- Cautery
|
||||||
|
- Drill
|
||||||
|
- Saw
|
||||||
|
- Hemostat
|
||||||
- type: Machine
|
- type: Machine
|
||||||
board: MedicalTechFabCircuitboard
|
board: MedicalTechFabCircuitboard
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,11 @@
|
|||||||
state: server
|
state: server
|
||||||
- type: ResearchServer
|
- type: ResearchServer
|
||||||
- type: TechnologyDatabase
|
- type: TechnologyDatabase
|
||||||
|
supportedDisciplines:
|
||||||
|
- Industrial
|
||||||
|
- Biochemical
|
||||||
|
- Experimental
|
||||||
|
- CivilianServices
|
||||||
- type: ApcPowerReceiver
|
- type: ApcPowerReceiver
|
||||||
powerLoad: 200
|
powerLoad: 200
|
||||||
priority: Low
|
priority: Low
|
||||||
|
|||||||
@@ -72,3 +72,30 @@
|
|||||||
materials:
|
materials:
|
||||||
Steel: 500
|
Steel: 500
|
||||||
Glass: 400
|
Glass: 400
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: ClothingBackpackHolding
|
||||||
|
result: ClothingBackpackHolding
|
||||||
|
completetime: 5
|
||||||
|
materials:
|
||||||
|
Steel: 1500
|
||||||
|
Plastic: 750
|
||||||
|
Plasma: 1000
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: ClothingBackpackSatchelHolding
|
||||||
|
result: ClothingBackpackSatchelHolding
|
||||||
|
completetime: 5
|
||||||
|
materials:
|
||||||
|
Steel: 1500
|
||||||
|
Plastic: 750
|
||||||
|
Plasma: 1000
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: ClothingBackpackDuffelHolding
|
||||||
|
result: ClothingBackpackDuffelHolding
|
||||||
|
completetime: 5
|
||||||
|
materials:
|
||||||
|
Steel: 1500
|
||||||
|
Plastic: 750
|
||||||
|
Plasma: 1000
|
||||||
|
|||||||
@@ -56,6 +56,22 @@
|
|||||||
Steel: 100
|
Steel: 100
|
||||||
Glass: 500
|
Glass: 500
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: Mousetrap
|
||||||
|
result: Mousetrap
|
||||||
|
completetime: 1
|
||||||
|
materials:
|
||||||
|
Wood: 100
|
||||||
|
Steel: 50
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: Holoprojector
|
||||||
|
result: Holoprojector
|
||||||
|
completetime: 3
|
||||||
|
materials:
|
||||||
|
Plastic: 250
|
||||||
|
Glass: 150
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: AdvMopItem
|
id: AdvMopItem
|
||||||
result: AdvMopItem
|
result: AdvMopItem
|
||||||
|
|||||||
117
Resources/Prototypes/Research/biochemical.yml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# Tier 1
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: Chemistry
|
||||||
|
name: research-technology-chemistry
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Chemistry/beaker_large.rsi
|
||||||
|
state: beakerlarge
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 1
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- LargeBeaker
|
||||||
|
- Dropper
|
||||||
|
- HotplateMachineCircuitboard
|
||||||
|
- ChemicalPayload
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: SurgicalTools
|
||||||
|
name: research-technology-surgical-tools
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Medical/Surgery/saw.rsi
|
||||||
|
state: saw
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- Scalpel
|
||||||
|
- Retractor
|
||||||
|
- Cautery
|
||||||
|
- Drill
|
||||||
|
- Saw
|
||||||
|
- Hemostat
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: BiochemicalStasis
|
||||||
|
name: research-technology-biochemical-stasis
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/stasis_bed.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 1
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- CryostasisBeaker
|
||||||
|
- StasisBedMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: Virology
|
||||||
|
name: research-technology-virology
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/diagnoser.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- VaccinatorMachineCircuitboard
|
||||||
|
- DiagnoserMachineCircuitboard
|
||||||
|
|
||||||
|
# Tier 2
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: Cryopod
|
||||||
|
name: research-technology-cryogenics
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/cryogenics.rsi
|
||||||
|
state: pod-on
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 2
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- CryoPodMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: ChemicalDispensary
|
||||||
|
name: research-technology-chemical-dispensary
|
||||||
|
icon:
|
||||||
|
sprite: Structures/dispensers.rsi
|
||||||
|
state: industrial-working
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- ChemMasterMachineCircuitboard
|
||||||
|
- ChemDispenserMachineCircuitboard
|
||||||
|
technologyPrerequisites:
|
||||||
|
- Chemistry
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: CrewMonitoring
|
||||||
|
name: research-technology-crew-monitoring
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Medical/handheldcrewmonitor.rsi
|
||||||
|
state: scanner
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- HandheldCrewMonitor
|
||||||
|
|
||||||
|
# Tier 3
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: Cloning
|
||||||
|
name: research-technology-cloning
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/cloning.rsi
|
||||||
|
state: pod_0
|
||||||
|
discipline: Biochemical
|
||||||
|
tier: 3
|
||||||
|
cost: 15000
|
||||||
|
recipeUnlocks:
|
||||||
|
- CloningPodMachineCircuitboard
|
||||||
|
- MedicalScannerMachineCircuitboard
|
||||||
|
- CloningConsoleComputerCircuitboard
|
||||||
|
- BiomassReclaimerMachineCircuitboard
|
||||||
153
Resources/Prototypes/Research/civilianservices.yml
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
# Tier 1
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: JanitorialEquipment
|
||||||
|
name: research-technology-janitorial-equipment
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Janitorial/mop.rsi
|
||||||
|
state: mop
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- MopItem
|
||||||
|
- Holoprojector
|
||||||
|
- Mousetrap
|
||||||
|
- LightReplacer
|
||||||
|
- TrashBag
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: LaundryTech
|
||||||
|
name: research-technology-laundry-tech
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/uniform_printer.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- UniformPrinterMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: Hydroponics
|
||||||
|
name: research-technology-basic-hydroponics
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/seed_extractor.rsi
|
||||||
|
state: seedextractor
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- SeedExtractorMachineCircuitboard
|
||||||
|
- HydroponicsTrayMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: FoodService
|
||||||
|
name: research-technology-food-service
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/juicer.rsi
|
||||||
|
state: juicer1
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 1
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks: #remove all of these once we have more kitchen equipment
|
||||||
|
- MicrowaveMachineCircuitboard
|
||||||
|
- ReagentGrinderMachineCircuitboard
|
||||||
|
- BoozeDispenserMachineCircuitboard
|
||||||
|
- SodaDispenserMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AudioVisualCommunication
|
||||||
|
name: research-technology-audio-visual-communication
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Wallmounts/camera.rsi
|
||||||
|
state: cameracase
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 1
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- SurveillanceCameraRouterCircuitboard
|
||||||
|
- SurveillanceCameraWirelessRouterCircuitboard
|
||||||
|
- SurveillanceWirelessCameraMovableCircuitboard
|
||||||
|
- SurveillanceWirelessCameraAnchoredCircuitboard
|
||||||
|
- SurveillanceCameraMonitorCircuitboard
|
||||||
|
- SurveillanceWirelessCameraMonitorCircuitboard
|
||||||
|
- TelecomServerCircuitboard
|
||||||
|
|
||||||
|
# Tier 2
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AdvancedCleaning
|
||||||
|
name: research-technology-advanced-cleaning
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Janitorial/advmop.rsi
|
||||||
|
state: advmop
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- AdvMopItem
|
||||||
|
- MegaSprayBottle
|
||||||
|
technologyPrerequisites:
|
||||||
|
- JanitorialEquipment
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: MeatManipulation
|
||||||
|
name: research-technology-meat-manipulation
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/fat_sucker.rsi
|
||||||
|
state: display
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 2
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- FatExtractorMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: HONKMech
|
||||||
|
name: research-technology-honk-mech
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Mech/mecha.rsi
|
||||||
|
state: honker
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- HonkerHarness
|
||||||
|
- HonkerLArm
|
||||||
|
- HonkerRArm
|
||||||
|
- HonkerLLeg
|
||||||
|
- HonkerRLeg
|
||||||
|
- HonkerCentralElectronics
|
||||||
|
- HonkerPeripheralsElectronics
|
||||||
|
- HonkerTargetingElectronics
|
||||||
|
- MechEquipmentHorn
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AdvancedEntertainment
|
||||||
|
name: research-technology-advanced-entertainment
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/computers.rsi
|
||||||
|
state: television
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 2
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- ComputerTelevisionCircuitboard
|
||||||
|
- SynthesizerInstrument
|
||||||
|
- DawInstrumentMachineCircuitboard
|
||||||
|
|
||||||
|
# Tier 3
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AdvancedSpray
|
||||||
|
name: research-technology-advanced-spray
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Weapons/Guns/Basic/spraynozzle.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: CivilianServices
|
||||||
|
tier: 3
|
||||||
|
cost: 15000
|
||||||
|
recipeUnlocks:
|
||||||
|
- WeaponSprayNozzle
|
||||||
|
- ClothingBackpackWaterTank
|
||||||
47
Resources/Prototypes/Research/disciplines.yml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
- type: techDiscipline
|
||||||
|
id: Industrial
|
||||||
|
name: research-discipline-industrial
|
||||||
|
color: "#eeac34"
|
||||||
|
icon:
|
||||||
|
sprite: Interface/Misc/research_disciplines.rsi
|
||||||
|
state: industrial
|
||||||
|
tierPrerequisites:
|
||||||
|
1: 0
|
||||||
|
2: 0.75
|
||||||
|
3: 0.75
|
||||||
|
|
||||||
|
- type: techDiscipline
|
||||||
|
id: Biochemical
|
||||||
|
name: research-discipline-biochemical
|
||||||
|
color: "#449ae6"
|
||||||
|
icon:
|
||||||
|
sprite: Interface/Misc/research_disciplines.rsi
|
||||||
|
state: biochemical
|
||||||
|
tierPrerequisites:
|
||||||
|
1: 0
|
||||||
|
2: 0.75
|
||||||
|
3: 0.75
|
||||||
|
|
||||||
|
- type: techDiscipline
|
||||||
|
id: Experimental
|
||||||
|
name: research-discipline-experimental
|
||||||
|
color: "#9a6ef0"
|
||||||
|
icon:
|
||||||
|
sprite: Interface/Misc/research_disciplines.rsi
|
||||||
|
state: experimental
|
||||||
|
tierPrerequisites:
|
||||||
|
1: 0
|
||||||
|
2: 0.75
|
||||||
|
3: 0.75
|
||||||
|
|
||||||
|
- type: techDiscipline
|
||||||
|
id: CivilianServices
|
||||||
|
name: research-discipline-civilian-services
|
||||||
|
color: "#7ecd48"
|
||||||
|
icon:
|
||||||
|
sprite: Interface/Misc/research_disciplines.rsi
|
||||||
|
state: civilianservices
|
||||||
|
tierPrerequisites:
|
||||||
|
1: 0
|
||||||
|
2: 0.75
|
||||||
|
3: 0.75
|
||||||
162
Resources/Prototypes/Research/experimental.yml
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
# Tier 1
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: BasicRobotics
|
||||||
|
name: research-technology-basic-robotics
|
||||||
|
icon:
|
||||||
|
sprite: Mobs/Silicon/drone.rsi
|
||||||
|
state: drone
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- ProximitySensor
|
||||||
|
- LeftArmBorg
|
||||||
|
- LightHeadBorg
|
||||||
|
- RightArmBorg
|
||||||
|
- LeftLegBorg
|
||||||
|
- RightLegBorg
|
||||||
|
- Drone
|
||||||
|
- ExosuitFabricatorMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: SignallingTech
|
||||||
|
name: research-technology-signalling-tech
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Devices/signaller.rsi
|
||||||
|
state: signaller
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 1
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- Signaller
|
||||||
|
- SignalTrigger
|
||||||
|
- VoiceTrigger
|
||||||
|
- TimerTrigger
|
||||||
|
- SignalTimerElectronics
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: BasicAnomalousResearch
|
||||||
|
name: research-technology-basic-anomalous-research
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Research/anomalyscanner.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 1
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- AnomalyScanner
|
||||||
|
- AnomalyLocator
|
||||||
|
- APECircuitboard
|
||||||
|
- AnomalyVesselCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: BasicXenoArcheology
|
||||||
|
name: research-technology-basic-xenoarcheology
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/artifact_analyzer.rsi
|
||||||
|
state: display
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 1
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- NodeScanner
|
||||||
|
- AnalysisComputerCircuitboard
|
||||||
|
- ArtifactAnalyzerMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AlternativeResearch
|
||||||
|
name: research-technology-alternative-research
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/tech_disk_printer.rsi
|
||||||
|
state: display
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- TechDiskComputerCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: MagnetsTech
|
||||||
|
name: research-technology-magnets-tech
|
||||||
|
icon:
|
||||||
|
sprite: Clothing/Shoes/Boots/magboots.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 1
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- ClothingShoesBootsMag
|
||||||
|
|
||||||
|
# Tier 2
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AdvancedParts
|
||||||
|
name: research-technology-advanced-parts
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Misc/stock_parts.rsi
|
||||||
|
state: advanced_matter_bin
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 2
|
||||||
|
cost: 15000
|
||||||
|
recipeUnlocks:
|
||||||
|
- AdvancedCapacitorStockPart
|
||||||
|
- AdvancedMatterBinStockPart
|
||||||
|
- NanoManipulatorStockPart
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AbnormalArtifactManipulation
|
||||||
|
name: research-technology-abnormal-artifact-manipulation
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/traversal_distorter.rsi
|
||||||
|
state: display
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 2
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- TraversalDistorterMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: MobileAnomalyTech
|
||||||
|
name: research-technology-mobile-anomaly-tech
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Weapons/Guns/Revolvers/chimp.rsi
|
||||||
|
state: base
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- WeaponPistolCHIMP
|
||||||
|
- CartridgeAnomalousParticleDelta
|
||||||
|
- CartridgeAnomalousParticleEpsilon
|
||||||
|
- CartridgeAnomalousParticleZeta
|
||||||
|
technologyPrerequisites:
|
||||||
|
- BasicAnomalousResearch
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: RapidPartExchange
|
||||||
|
name: research-technology-rped
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Research/rped.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 2
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- RPED
|
||||||
|
|
||||||
|
# Tier 3
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: SuperParts
|
||||||
|
name: research-technology-super-parts
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Misc/stock_parts.rsi
|
||||||
|
state: super_matter_bin
|
||||||
|
discipline: Experimental
|
||||||
|
tier: 3
|
||||||
|
cost: 15000
|
||||||
|
recipeUnlocks:
|
||||||
|
- SuperCapacitorStockPart
|
||||||
|
- SuperMatterBinStockPart
|
||||||
|
- PicoManipulatorStockPart
|
||||||
177
Resources/Prototypes/Research/industrial.yml
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
# Tier 1
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: SalvageEquipment
|
||||||
|
name: research-technology-salvage-equipment
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Tools/handdrill.rsi
|
||||||
|
state: handdrill
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 1
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- PowerDrill #todo remove this once we have advanced tools
|
||||||
|
- MiningDrill
|
||||||
|
- OreProcessorMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AdvancedPowercells
|
||||||
|
name: research-technology-advanced-powercells
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Power/power_cells.rsi
|
||||||
|
state: medium
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 1
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- PowerCellMedium
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: CompactPower
|
||||||
|
name: research-technology-compact-power
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Power/Generation/wallmount_generator.rsi
|
||||||
|
state: panel
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 1
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- WallmountSubstationElectronics
|
||||||
|
- WallmountGeneratorElectronics
|
||||||
|
- WallmountGeneratorAPUElectronics
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: IndustrialEngineering
|
||||||
|
name: research-technology-industrial-engineering
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Machines/protolathe.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 1
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- ProtolatheMachineCircuitboard
|
||||||
|
- AutolatheMachineCircuitboard
|
||||||
|
- CircuitImprinterMachineCircuitboard
|
||||||
|
- MaterialReclaimerMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: PowerGeneration
|
||||||
|
name: research-technology-power-generation
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Power/Generation/portable_generator.rsi
|
||||||
|
state: portgen0_1
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 1
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- GeneratorPlasmaMachineCircuitboard
|
||||||
|
- GeneratorUraniumMachineCircuitboard
|
||||||
|
- PowerComputerCircuitboard #the actual solar panel itself should be in here
|
||||||
|
- SolarControlComputerCircuitboard
|
||||||
|
- EmitterCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AtmosphericTech
|
||||||
|
name: research-technology-atmospheric-tech
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Piping/Atmospherics/thermomachine.rsi
|
||||||
|
state: freezerOff
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 1
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- ThermomachineFreezerMachineCircuitBoard
|
||||||
|
- GasRecyclerMachineCircuitboard
|
||||||
|
|
||||||
|
# Tier 2
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: RapidConstruction
|
||||||
|
name: research-technology-rapid-construction
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Tools/rcd.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- RCD
|
||||||
|
- RCDAmmo
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: Shuttlecraft
|
||||||
|
name: research-technology-shuttlecraft
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Shuttles/gyroscope.rsi
|
||||||
|
state: base
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- ShuttleConsoleCircuitboard
|
||||||
|
- RadarConsoleCircuitboard
|
||||||
|
- ThrusterMachineCircuitboard
|
||||||
|
- GyroscopeMachineCircuitboard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: RipleyAPLU
|
||||||
|
name: research-technology-ripley-aplu
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Specific/Mech/mecha.rsi
|
||||||
|
state: ripley
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 2
|
||||||
|
cost: 10000
|
||||||
|
recipeUnlocks:
|
||||||
|
- RipleyHarness
|
||||||
|
- RipleyLArm
|
||||||
|
- RipleyRArm
|
||||||
|
- RipleyLLeg
|
||||||
|
- RipleyRLeg
|
||||||
|
- RipleyCentralElectronics
|
||||||
|
- RipleyPeripheralsElectronics
|
||||||
|
- MechEquipmentGrabber
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: AdvancedAtmospherics
|
||||||
|
name: research-technology-advanced-atmospherics
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Devices/Holoprojectors/atmos.rsi
|
||||||
|
state: icon
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 2
|
||||||
|
cost: 5000
|
||||||
|
recipeUnlocks:
|
||||||
|
- HolofanProjector
|
||||||
|
- PortableScrubberMachineCircuitBoard
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: SuperPowercells
|
||||||
|
name: research-technology-super-powercells
|
||||||
|
icon:
|
||||||
|
sprite: Objects/Power/power_cells.rsi
|
||||||
|
state: high
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 2
|
||||||
|
cost: 7500
|
||||||
|
recipeUnlocks:
|
||||||
|
- PowerCellHigh
|
||||||
|
technologyPrerequisites:
|
||||||
|
- AdvancedPowercells
|
||||||
|
|
||||||
|
# Tier 3
|
||||||
|
|
||||||
|
- type: technology
|
||||||
|
id: BluespaceStorage
|
||||||
|
name: research-technology-bluespace-storage
|
||||||
|
icon:
|
||||||
|
sprite: Clothing/Back/Backpacks/holding.rsi
|
||||||
|
state: holding
|
||||||
|
discipline: Industrial
|
||||||
|
tier: 3
|
||||||
|
cost: 15000
|
||||||
|
recipeUnlocks:
|
||||||
|
- ClothingBackpackHolding
|
||||||
|
- ClothingBackpackSatchelHolding
|
||||||
|
- ClothingBackpackDuffelHolding
|
||||||
|
After Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 546 B |
|
After Width: | Height: | Size: 177 B |
|
After Width: | Height: | Size: 160 B |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC0-1.0",
|
||||||
|
"copyright": "Created by EmoGarbage404 (github) for Space Station 14.",
|
||||||
|
"size": {
|
||||||
|
"x": 8,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "biochemical"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "civilianservices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "experimental"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "industrial"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 390 B |
@@ -7,6 +7,9 @@
|
|||||||
"y": 32
|
"y": 32
|
||||||
},
|
},
|
||||||
"states": [
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "display"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "icon"
|
"name": "icon"
|
||||||
},
|
},
|
||||||
|
|||||||
|
After Width: | Height: | Size: 943 B |
@@ -7,6 +7,9 @@
|
|||||||
"y": 32
|
"y": 32
|
||||||
},
|
},
|
||||||
"states": [
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "display"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "fat"
|
"name": "fat"
|
||||||
},
|
},
|
||||||
|
|||||||
|
After Width: | Height: | Size: 785 B |
@@ -7,6 +7,9 @@
|
|||||||
"y": 32
|
"y": 32
|
||||||
},
|
},
|
||||||
"states": [
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "display"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "icon"
|
"name": "icon"
|
||||||
},
|
},
|
||||||
|
|||||||
|
After Width: | Height: | Size: 735 B |
@@ -7,6 +7,9 @@
|
|||||||
"y": 32
|
"y": 32
|
||||||
},
|
},
|
||||||
"states": [
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "display"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "icon"
|
"name": "icon"
|
||||||
},
|
},
|
||||||
|
|||||||