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 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 TechnologyDatabaseComponent? _technologyDatabase;
|
||||
private readonly IEntityManager _entityManager;
|
||||
private readonly SharedResearchSystem _research;
|
||||
|
||||
|
||||
public ResearchConsoleBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
SendMessage(new ConsoleServerSyncMessage());
|
||||
_entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
_research = _entityManager.System<SharedResearchSystem>();
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
if (!_entityManager.TryGetComponent(Owner.Owner, out _technologyDatabase))
|
||||
return;
|
||||
var owner = Owner.Owner;
|
||||
|
||||
_consoleMenu = new ResearchConsoleMenu(this);
|
||||
_consoleMenu = new ResearchConsoleMenu(owner);
|
||||
|
||||
_consoleMenu.OnClose += Close;
|
||||
|
||||
_consoleMenu.ServerSyncButton.OnPressed += (_) =>
|
||||
_consoleMenu.OnTechnologyCardPressed += id =>
|
||||
{
|
||||
SendMessage(new ConsoleServerSyncMessage());
|
||||
SendMessage(new ConsoleUnlockTechnologyMessage(id));
|
||||
};
|
||||
|
||||
_consoleMenu.ServerSelectionButton.OnPressed += (_) =>
|
||||
_consoleMenu.OnServerButtonPressed += () =>
|
||||
{
|
||||
SendMessage(new ConsoleServerSelectionMessage());
|
||||
};
|
||||
|
||||
_consoleMenu.UnlockButton.OnPressed += (_) =>
|
||||
_consoleMenu.OnSyncButtonPressed += () =>
|
||||
{
|
||||
if (_consoleMenu.TechnologySelected != null)
|
||||
{
|
||||
SendMessage(new ConsoleUnlockTechnologyMessage(_consoleMenu.TechnologySelected.ID));
|
||||
}
|
||||
SendMessage(new ConsoleServerSyncMessage());
|
||||
};
|
||||
|
||||
_consoleMenu.OnClose += Close;
|
||||
|
||||
_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)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
var castState = (ResearchConsoleBoundInterfaceState)state;
|
||||
Points = castState.Points;
|
||||
PointsPerSecond = castState.PointsPerSecond;
|
||||
// We update the user interface here.
|
||||
_consoleMenu?.PopulatePoints();
|
||||
_consoleMenu?.Populate();
|
||||
if (state is not ResearchConsoleBoundInterfaceState castState)
|
||||
return;
|
||||
_consoleMenu?.UpdatePanels(castState);
|
||||
_consoleMenu?.UpdateInformationPanel(castState);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
@@ -90,5 +63,4 @@ namespace Content.Client.Research.UI
|
||||
return;
|
||||
_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'}"
|
||||
MinSize="800 400"
|
||||
SetSize="800 400">
|
||||
MinSize="625 400"
|
||||
SetSize="700 550">
|
||||
<BoxContainer Orientation="Vertical"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True">
|
||||
<BoxContainer Orientation="Horizontal"
|
||||
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"
|
||||
HorizontalExpand="True"
|
||||
SizeFlagsStretchRatio="2"
|
||||
SeparationOverride="10">
|
||||
<BoxContainer Orientation="Vertical"
|
||||
Margin="10 0 10 10"
|
||||
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"
|
||||
VerticalExpand="True">
|
||||
<Label Text="{Loc 'research-console-menu-unlocked-technologies-label'}" />
|
||||
<ItemList Name="UnlockedTechnologies"
|
||||
SelectMode="Button"
|
||||
<BoxContainer
|
||||
Name="AvailableCardsContainer"
|
||||
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"
|
||||
VerticalExpand="True">
|
||||
<!-- Unlocked technologies are added here by code -->
|
||||
</ItemList>
|
||||
<BoxContainer
|
||||
Name="UnlockedCardsContainer"
|
||||
Orientation="Vertical"
|
||||
VerticalExpand="True">
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
<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"
|
||||
SizeFlagsStretchRatio="1">
|
||||
<TextureRect Name="TechnologyIcon"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True"
|
||||
SizeFlagsStretchRatio="1"
|
||||
Stretch="KeepAspectCentered" />
|
||||
<BoxContainer Orientation="Vertical"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True"
|
||||
SizeFlagsStretchRatio="3">
|
||||
<Label Name="TechnologyName" />
|
||||
<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"
|
||||
SizeFlagsStretchRatio="3"
|
||||
Margin="0 0 10 10">
|
||||
<PanelContainer VerticalExpand="True" MinSize="0 200">
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
|
||||
</PanelContainer.PanelOverride>
|
||||
<ScrollContainer
|
||||
HScrollEnabled="False"
|
||||
HorizontalExpand="True"
|
||||
SizeFlagsStretchRatio="2"
|
||||
VerticalExpand="True">
|
||||
<Button Name="ServerSelectionButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'research-console-menu-server-selection-button'}" />
|
||||
<Button Name="ServerSyncButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'research-console-menu-server-sync-button'}" />
|
||||
<Button Name="UnlockButton"
|
||||
Access="Public"
|
||||
Disabled="True" />
|
||||
<BoxContainer
|
||||
Name="TechnologyCardsContainer"
|
||||
MinSize="100 256"
|
||||
Orientation="Vertical"
|
||||
SizeFlagsStretchRatio="2"
|
||||
VerticalExpand="True">
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
</controls:FancyWindow>
|
||||
|
||||
@@ -1,195 +1,167 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Research.Components;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
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.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
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 sealed partial class ResearchConsoleMenu : DefaultWindow
|
||||
{
|
||||
public ResearchConsoleBoundUserInterface Owner { get; }
|
||||
public Action<string>? OnTechnologyCardPressed;
|
||||
public Action? OnServerButtonPressed;
|
||||
public Action? OnSyncButtonPressed;
|
||||
|
||||
private readonly List<TechnologyPrototype> _unlockedTechnologyPrototypes = new();
|
||||
private readonly List<TechnologyPrototype> _unlockableTechnologyPrototypes = new();
|
||||
private readonly List<TechnologyPrototype> _futureTechnologyPrototypes = new();
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
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);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
Owner = owner;
|
||||
_research = _entity.System<ResearchSystem>();
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
Entity = entity;
|
||||
|
||||
UnlockedTechnologies.OnItemSelected += UnlockedTechnologySelected;
|
||||
UnlockableTechnologies.OnItemSelected += UnlockableTechnologySelected;
|
||||
FutureTechnologies.OnItemSelected += FutureTechnologySelected;
|
||||
ServerButton.OnPressed += _ => OnServerButtonPressed?.Invoke();
|
||||
SyncButton.OnPressed += _ => OnSyncButtonPressed?.Invoke();
|
||||
|
||||
PointLabel.Text = Loc.GetString("research-console-menu-research-points-text", ("points", 0));
|
||||
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();
|
||||
_entity.TryGetComponent(entity, out _technologyDatabase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans the selected technology controls to blank.
|
||||
/// </summary>
|
||||
private void CleanSelectedTechnology()
|
||||
public void UpdatePanels(ResearchConsoleBoundInterfaceState state)
|
||||
{
|
||||
UnlockButton.Disabled = true;
|
||||
TechnologyIcon.Texture = Texture.Transparent;
|
||||
TechnologyName.Text = string.Empty;
|
||||
TechnologyDescription.Text = string.Empty;
|
||||
TechnologyRequirements.Text = string.Empty;
|
||||
var allTech = _research.GetAvailableTechnologies(Entity);
|
||||
AvailableCardsContainer.Children.Clear();
|
||||
TechnologyCardsContainer.Children.Clear();
|
||||
UnlockedCardsContainer.Children.Clear();
|
||||
|
||||
foreach (var tech in allTech)
|
||||
{
|
||||
var mini = new MiniTechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech, false));
|
||||
AvailableCardsContainer.AddChild(mini);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
if (_technologyDatabase == null)
|
||||
return;
|
||||
}
|
||||
|
||||
TechnologyIcon.Texture = TechnologySelected.Icon.Frame0();
|
||||
TechnologyName.Text = GetTechName(TechnologySelected);
|
||||
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++)
|
||||
// i can't figure out the spacing so here you go
|
||||
TechnologyCardsContainer.AddChild(new Control
|
||||
{
|
||||
var requiredId = TechnologySelected.RequiredTechnologies[i];
|
||||
if (!prototypeMan.TryIndex(requiredId, out TechnologyPrototype? prototype)) continue;
|
||||
var protoName = GetTechName(prototype);
|
||||
if (i == 0)
|
||||
TechnologyRequirements.Text = Loc.GetString("research-console-tech-requirements-prototype-name", ("prototypeName", protoName));
|
||||
else
|
||||
TechnologyRequirements.Text += $", {protoName}";
|
||||
MinHeight = 10
|
||||
});
|
||||
foreach (var techId in _technologyDatabase.CurrentTechnologyCards)
|
||||
{
|
||||
var tech = _prototype.Index<TechnologyPrototype>(techId);
|
||||
var cardControl = new TechnologyCardControl(tech, _prototype, _sprite, GetTechnologyDescription(tech), state.Points);
|
||||
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>
|
||||
/// Updates the research point labels.
|
||||
/// </summary>
|
||||
public void PopulatePoints()
|
||||
public FormattedMessage GetTechnologyDescription(TechnologyPrototype technology, bool includeCost = true)
|
||||
{
|
||||
PointLabel.Text = Loc.GetString("research-console-menu-research-points-text", ("points", Owner.Points));
|
||||
PointsPerSecondLabel.Text = Loc.GetString("research-console-menu-points-per-second-text", ("pointsPerSecond", Owner.PointsPerSecond));
|
||||
var description = new FormattedMessage();
|
||||
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>
|
||||
/// Updates the whole user interface.
|
||||
/// </summary>
|
||||
public void Populate()
|
||||
return description;
|
||||
}
|
||||
|
||||
public void UpdateInformationPanel(ResearchConsoleBoundInterfaceState state)
|
||||
{
|
||||
PopulatePoints();
|
||||
PopulateSelectedTechnology();
|
||||
PopulateItemLists();
|
||||
var amountMsg = new FormattedMessage();
|
||||
amountMsg.AddMarkup(Loc.GetString("research-console-menu-research-points-text",
|
||||
("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(Control.StylePropertyModulateSelf, Color.FromHex("#111111")),
|
||||
|
||||
Element<RichTextLabel>().Class("LabelSubText")
|
||||
.Prop(Label.StylePropertyFont, notoSans10)
|
||||
.Prop(Label.StylePropertyFontColor, Color.DarkGray),
|
||||
|
||||
Element<LineEdit>().Class("PaperLineEdit")
|
||||
.Prop(LineEdit.StylePropertyStyleBox, new StyleBoxEmpty()),
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
@@ -10,6 +11,40 @@ namespace Content.IntegrationTests.Tests;
|
||||
[TestFixture]
|
||||
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]
|
||||
public async Task AllTechPrintableTest()
|
||||
{
|
||||
@@ -40,14 +75,13 @@ public sealed class ResearchTest
|
||||
|
||||
foreach (var recipe in lathe.DynamicRecipes)
|
||||
{
|
||||
if (!latheTechs.Contains(recipe))
|
||||
latheTechs.Add(recipe);
|
||||
}
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace Content.Server.Lathe
|
||||
if (uid != args.Lathe || !TryComp<LatheComponent>(uid, out var latheComponent) || latheComponent.DynamicRecipes == null)
|
||||
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)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Content.Server.Research.Disk
|
||||
if (!TryComp<ResearchServerComponent>(args.Target, out var server))
|
||||
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);
|
||||
EntityManager.QueueDeleteEntity(uid);
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace Content.Server.Research.Disk
|
||||
return;
|
||||
|
||||
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="component">The client's Researchclient component</param>
|
||||
/// <returns>If the server was successfully retrieved.</returns>
|
||||
public bool TryGetClientServer(EntityUid uid, [NotNullWhen(returnValue: true)] out EntityUid? server,
|
||||
[NotNullWhen(returnValue: true)] out ResearchServerComponent? serverComponent, ResearchClientComponent? component = null)
|
||||
public bool TryGetClientServer(EntityUid uid,
|
||||
[NotNullWhen(returnValue: true)] out EntityUid? server,
|
||||
[NotNullWhen(returnValue: true)] out ResearchServerComponent? serverComponent,
|
||||
ResearchClientComponent? component = null)
|
||||
{
|
||||
server = null;
|
||||
serverComponent = null;
|
||||
@@ -117,11 +119,10 @@ public sealed partial class ResearchSystem
|
||||
if (component.Server == null)
|
||||
return false;
|
||||
|
||||
if (!TryComp<ResearchServerComponent>(component.Server, out var sc))
|
||||
if (!TryComp(component.Server, out serverComponent))
|
||||
return false;
|
||||
|
||||
server = component.Server;
|
||||
serverComponent = sc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,18 +33,17 @@ public sealed partial class ResearchSystem
|
||||
|
||||
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 pointsPerSecond = clientComponent.ConnectedToServer ? PointsPerSecond(server.Value, serverComponent) : 0;
|
||||
state = new ResearchConsoleBoundInterfaceState(points, pointsPerSecond);
|
||||
state = new ResearchConsoleBoundInterfaceState(points);
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -49,7 +49,7 @@ public sealed partial class ResearchSystem
|
||||
|
||||
if (!CanRun(uid))
|
||||
return;
|
||||
AddPointsToServer(uid, PointsPerSecond(uid, component) * time, component);
|
||||
ModifyServerPoints(uid, GetPointsPerSecond(uid, component) * time, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,15 +60,14 @@ public sealed partial class ResearchSystem
|
||||
/// <param name="clientComponent"></param>
|
||||
/// <param name="serverComponent"></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 bool RegisterClient(EntityUid client, EntityUid server, ResearchClientComponent? clientComponent = null,
|
||||
public void RegisterClient(EntityUid client, EntityUid server, ResearchClientComponent? clientComponent = null,
|
||||
ResearchServerComponent? serverComponent = null, bool dirtyServer = true)
|
||||
{
|
||||
if (!Resolve(client, ref clientComponent) || !Resolve(server, ref serverComponent))
|
||||
return false;
|
||||
return;
|
||||
|
||||
if (serverComponent.Clients.Contains(client))
|
||||
return false;
|
||||
return;
|
||||
|
||||
serverComponent.Clients.Add(client);
|
||||
clientComponent.Server = server;
|
||||
@@ -78,7 +77,6 @@ public sealed partial class ResearchSystem
|
||||
|
||||
var ev = new ResearchRegistrationChangedEvent(server);
|
||||
RaiseLocalEvent(client, ref ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -130,7 +128,7 @@ public sealed partial class ResearchSystem
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="component"></param>
|
||||
/// <returns></returns>
|
||||
public int PointsPerSecond(EntityUid uid, ResearchServerComponent? component = null)
|
||||
public int GetPointsPerSecond(EntityUid uid, ResearchServerComponent? component = null)
|
||||
{
|
||||
var points = 0;
|
||||
|
||||
@@ -154,7 +152,7 @@ public sealed partial class ResearchSystem
|
||||
/// <param name="uid">The server</param>
|
||||
/// <param name="points">The amount of points being added</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)
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Research.Components;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Server.Research.Systems;
|
||||
|
||||
@@ -13,13 +14,16 @@ public sealed partial class ResearchSystem
|
||||
if (!Resolve(primaryUid, ref primaryDb) || !Resolve(otherUid, ref otherDb))
|
||||
return;
|
||||
|
||||
primaryDb.TechnologyIds = otherDb.TechnologyIds;
|
||||
primaryDb.RecipeIds = otherDb.RecipeIds;
|
||||
primaryDb.MainDiscipline = otherDb.MainDiscipline;
|
||||
primaryDb.CurrentTechnologyCards = otherDb.CurrentTechnologyCards;
|
||||
primaryDb.SupportedDisciplines = otherDb.SupportedDisciplines;
|
||||
primaryDb.UnlockedTechnologies = otherDb.UnlockedTechnologies;
|
||||
primaryDb.UnlockedRecipes = otherDb.UnlockedRecipes;
|
||||
|
||||
Dirty(primaryDb);
|
||||
|
||||
var ev = new TechnologyDatabaseModifiedEvent();
|
||||
RaiseLocalEvent(primaryDb.Owner, ref ev);
|
||||
RaiseLocalEvent(primaryUid, ref ev);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -28,16 +32,15 @@ public sealed partial class ResearchSystem
|
||||
/// syncs against the research server, and the server against the local database.
|
||||
/// </summary>
|
||||
/// <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))
|
||||
return false;
|
||||
return;
|
||||
|
||||
if (!TryComp<TechnologyDatabaseComponent>(clientComponent.Server, out var serverDatabase))
|
||||
return false;
|
||||
return;
|
||||
|
||||
Sync(uid, clientComponent.Server.Value, databaseComponent, serverDatabase);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -45,45 +48,49 @@ public sealed partial class ResearchSystem
|
||||
/// </summary>
|
||||
/// <returns>If the technology was successfully added</returns>
|
||||
public bool UnlockTechnology(EntityUid client, string prototypeid, ResearchClientComponent? component = null,
|
||||
TechnologyDatabaseComponent? databaseComponent = null)
|
||||
TechnologyDatabaseComponent? clientDatabase = null)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<TechnologyPrototype>(prototypeid, out var prototype))
|
||||
{
|
||||
Logger.Error("invalid technology prototype");
|
||||
if (!PrototypeManager.TryIndex<TechnologyPrototype>(prototypeid, out var prototype))
|
||||
return false;
|
||||
}
|
||||
return UnlockTechnology(client, prototype, component, databaseComponent);
|
||||
|
||||
return UnlockTechnology(client, prototype, component, clientDatabase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to add a technology to a database, checking if it is able to
|
||||
/// </summary>
|
||||
/// <returns>If the technology was successfully added</returns>
|
||||
public bool UnlockTechnology(EntityUid client, TechnologyPrototype prototype, ResearchClientComponent? component = null,
|
||||
TechnologyDatabaseComponent? databaseComponent = null)
|
||||
public bool UnlockTechnology(EntityUid client,
|
||||
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;
|
||||
|
||||
if (!CanUnlockTechnology(client, prototype, databaseComponent))
|
||||
if (!TryGetClientServer(client, out var serverEnt, out _, component))
|
||||
return false;
|
||||
|
||||
if (component.Server is not { } server)
|
||||
if (!CanServerUnlockTechnology(client, prototype, clientDatabase, component))
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a technology to the database without checking if it could be unlocked.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public void AddTechnology(EntityUid uid, string technology, TechnologyDatabaseComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
if (!_prototypeManager.TryIndex<TechnologyPrototype>(technology, out var prototype))
|
||||
if (!PrototypeManager.TryIndex<TechnologyPrototype>(technology, out var prototype))
|
||||
return;
|
||||
AddTechnology(uid, prototype, component);
|
||||
}
|
||||
@@ -96,12 +103,19 @@ public sealed partial class ResearchSystem
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
component.TechnologyIds.Add(technology.ID);
|
||||
foreach (var unlock in technology.UnlockedRecipes)
|
||||
//todo this needs to support some other stuff, too
|
||||
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;
|
||||
component.RecipeIds.Add(unlock);
|
||||
component.UnlockedRecipes.Add(unlock);
|
||||
}
|
||||
Dirty(component);
|
||||
|
||||
@@ -113,16 +127,15 @@ public sealed partial class ResearchSystem
|
||||
/// Adds a lathe recipe to the specified technology database
|
||||
/// without checking if it can be unlocked.
|
||||
/// </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))
|
||||
return;
|
||||
|
||||
if (component.RecipeIds.Contains(recipe))
|
||||
if (component.UnlockedRecipes.Contains(recipe))
|
||||
return;
|
||||
|
||||
component.RecipeIds.Add(recipe);
|
||||
if (dirty)
|
||||
component.UnlockedRecipes.Add(recipe);
|
||||
Dirty(component);
|
||||
|
||||
var ev = new TechnologyDatabaseModifiedEvent();
|
||||
@@ -134,34 +147,36 @@ public sealed partial class ResearchSystem
|
||||
/// taking parent technologies into account.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
/// 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))
|
||||
if (!Resolve(uid, ref client, ref database, false))
|
||||
return false;
|
||||
|
||||
if (!TryGetClientServer(uid, out _, out var serverComponent, client))
|
||||
if (!TryGetClientServer(uid, out _, out var serverComp, client))
|
||||
return false;
|
||||
|
||||
if (serverComponent.Points < technology.RequiredPoints)
|
||||
if (!IsTechnologyAvailable(database, technology))
|
||||
return false;
|
||||
|
||||
if (IsTechnologyUnlocked(uid, technology, database))
|
||||
if (technology.Cost > serverComp.Points)
|
||||
return false;
|
||||
|
||||
if (!ArePrerequesitesUnlocked(uid, technology, database))
|
||||
return false;
|
||||
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 JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Research.Systems
|
||||
@@ -13,7 +12,6 @@ namespace Content.Server.Research.Systems
|
||||
public sealed partial class ResearchSystem : SharedResearchSystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -23,6 +21,8 @@ namespace Content.Server.Research.Systems
|
||||
InitializeConsole();
|
||||
InitializeSource();
|
||||
InitializeServer();
|
||||
|
||||
SubscribeLocalEvent<TechnologyDatabaseComponent, ResearchRegistrationChangedEvent>(OnDatabaseRegistrationChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -51,7 +51,7 @@ public sealed class DiskConsoleSystem : EntitySystem
|
||||
if (serverComp.Points < component.PricePerDisk)
|
||||
return;
|
||||
|
||||
_research.AddPointsToServer(server.Value, -component.PricePerDisk, serverComp);
|
||||
_research.ModifyServerPoints(server.Value, -component.PricePerDisk, serverComp);
|
||||
_audio.PlayPvs(component.PrintSound, uid);
|
||||
|
||||
var printing = EnsureComp<DiskConsolePrintingComponent>(uid);
|
||||
|
||||
@@ -38,12 +38,11 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
||||
{
|
||||
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);
|
||||
EntityManager.DeleteEntity(uid);
|
||||
Del(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -71,7 +70,7 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
||||
var allTechs = new List<string>();
|
||||
foreach (var tech in _prototype.EnumeratePrototypes<TechnologyPrototype>())
|
||||
{
|
||||
allTechs.AddRange(tech.UnlockedRecipes);
|
||||
allTechs.AddRange(tech.RecipeUnlocks);
|
||||
}
|
||||
allTechs = allTechs.Distinct().ToList();
|
||||
|
||||
@@ -79,7 +78,7 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
||||
var allUnlocked = new List<string>();
|
||||
foreach (var database in EntityQuery<TechnologyDatabaseComponent>())
|
||||
{
|
||||
allUnlocked.AddRange(database.RecipeIds);
|
||||
allUnlocked.AddRange(database.UnlockedRecipes);
|
||||
}
|
||||
allUnlocked = allUnlocked.Distinct().ToList();
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
||||
if (pointValue == 0)
|
||||
return;
|
||||
|
||||
_research.AddPointsToServer(server.Value, pointValue, serverComponent);
|
||||
_research.ModifyServerPoints(server.Value, pointValue, serverComponent);
|
||||
_artifact.AdjustConsumedPoints(artifact.Value, pointValue);
|
||||
|
||||
_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.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>
|
||||
/// The name of the server
|
||||
/// </summary>
|
||||
[DataField("servername"), ViewVariables(VVAccess.ReadWrite)]
|
||||
[AutoNetworkedField]
|
||||
[DataField("serverName"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public string ServerName = "RDSERVER";
|
||||
|
||||
/// <summary>
|
||||
/// The amount of points on the server.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[DataField("points"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int Points;
|
||||
|
||||
/// <summary>
|
||||
/// A unique numeric id representing the server
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public int Id;
|
||||
|
||||
@@ -39,36 +42,22 @@ namespace Content.Shared.Research.Components
|
||||
|
||||
[DataField("researchConsoleUpdateTime"), ViewVariables(VVAccess.ReadWrite)]
|
||||
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 int Points;
|
||||
public int PointsPerSecond;
|
||||
public ResearchConsoleBoundInterfaceState(int points, int pointsPerSecond)
|
||||
public ResearchConsoleBoundInterfaceState(int points)
|
||||
{
|
||||
Points = points;
|
||||
PointsPerSecond = pointsPerSecond;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,56 @@
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using Content.Shared.Research.Systems;
|
||||
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;
|
||||
|
||||
namespace Content.Shared.Research.Components
|
||||
namespace Content.Shared.Research.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedResearchSystem)), AutoGenerateComponentState]
|
||||
public sealed partial class TechnologyDatabaseComponent : Component
|
||||
{
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed class TechnologyDatabaseComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// The ids of all the technologies which have been unlocked.
|
||||
/// </summary>
|
||||
[DataField("technologyIds", customTypeSerializer: typeof(PrototypeIdListSerializer<TechnologyPrototype>))]
|
||||
public List<string> TechnologyIds = new();
|
||||
[AutoNetworkedField(true)]
|
||||
[DataField("unlockedTechnologies", customTypeSerializer: typeof(PrototypeIdListSerializer<TechnologyPrototype>))]
|
||||
public List<string> UnlockedTechnologies = new();
|
||||
|
||||
/// <summary>
|
||||
/// The ids of all the lathe recipes which have been unlocked.
|
||||
/// This is maintained alongside the TechnologyIds
|
||||
/// </summary>
|
||||
[DataField("recipeIds", customTypeSerializer: typeof(PrototypeIdListSerializer<LatheRecipePrototype>))]
|
||||
public List<string> RecipeIds = 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;
|
||||
}
|
||||
}
|
||||
/// todo: if you unlock all the recipes in a tech, it doesn't count as unlocking the tech. sadge
|
||||
[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;
|
||||
|
||||
@@ -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.Serialization;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
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")]
|
||||
public sealed class TechnologyPrototype : IPrototype
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of this technology prototype.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
/// <inheritdoc/>
|
||||
[IdDataField]
|
||||
public string ID { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The name this technology will have on user interfaces.
|
||||
/// The name of the technology.
|
||||
/// Supports locale strings
|
||||
/// </summary>
|
||||
[DataField("name")]
|
||||
public string? Name { get; private set; }
|
||||
[DataField("name", required: true)]
|
||||
public readonly string Name = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// An icon that represent this technology.
|
||||
/// An icon used to visually represent the technology in UI.
|
||||
/// </summary>
|
||||
[DataField("icon")]
|
||||
public SpriteSpecifier Icon { get; } = SpriteSpecifier.Invalid;
|
||||
[DataField("icon", required: true)]
|
||||
public readonly SpriteSpecifier Icon = default!;
|
||||
|
||||
/// <summary>
|
||||
/// A short description of the technology.
|
||||
/// What research discipline this technology belongs to.
|
||||
/// </summary>
|
||||
[DataField("description")]
|
||||
public string Description { get; private set; } = "";
|
||||
[DataField("discipline", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<TechDisciplinePrototype>))]
|
||||
public readonly string Discipline = default!;
|
||||
|
||||
/// <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>
|
||||
[DataField("requiredPoints")]
|
||||
public int RequiredPoints { get; }
|
||||
[DataField("tier", required: true)]
|
||||
public readonly int Tier;
|
||||
|
||||
/// <summary>
|
||||
/// A list of technology IDs required to unlock this technology.
|
||||
/// Hidden tech is not ever available at the research console.
|
||||
/// </summary>
|
||||
[DataField("requiredTechnologies", customTypeSerializer: typeof(PrototypeIdListSerializer<TechnologyPrototype>))]
|
||||
public List<string> RequiredTechnologies { get; } = new();
|
||||
[DataField("hidden")]
|
||||
public readonly bool Hidden;
|
||||
|
||||
/// <summary>
|
||||
/// A list of recipe IDs this technology unlocks.
|
||||
/// How much research is needed to unlock.
|
||||
/// </summary>
|
||||
[DataField("unlockedRecipes", customTypeSerializer:typeof(PrototypeIdListSerializer<LatheRecipePrototype>))]
|
||||
public List<string> UnlockedRecipes { get; } = new();
|
||||
}
|
||||
[DataField("cost")]
|
||||
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 Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared.Research.Systems;
|
||||
|
||||
public abstract class SharedResearchSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ResearchServerComponent, ComponentGetState>(OnServerGetState);
|
||||
SubscribeLocalEvent<ResearchServerComponent, ComponentHandleState>(OnServerHandleState);
|
||||
SubscribeLocalEvent<TechnologyDatabaseComponent, ComponentGetState>(OnTechnologyGetState);
|
||||
SubscribeLocalEvent<TechnologyDatabaseComponent, ComponentHandleState>(OnTechnologyHandleState);
|
||||
SubscribeLocalEvent<TechnologyDatabaseComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
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;
|
||||
component.ServerName = state.ServerName;
|
||||
component.Points = state.Points;
|
||||
component.Id = state.Id;
|
||||
|
||||
var availableTechnology = GetAvailableTechnologies(uid, component);
|
||||
_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)
|
||||
return;
|
||||
component.TechnologyIds = new (state.Technologies);
|
||||
component.RecipeIds = new(state.Recipes);
|
||||
if (!Resolve(uid, ref component, false))
|
||||
return new List<TechnologyPrototype>();
|
||||
|
||||
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>
|
||||
@@ -58,26 +157,18 @@ public abstract class SharedResearchSystem : EntitySystem
|
||||
/// <returns>Whether it is unlocked or not</returns>
|
||||
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>
|
||||
/// 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)
|
||||
public void TrySetMainDiscipline(TechnologyPrototype prototype, EntityUid uid, TechnologyDatabaseComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
foreach (var technologyId in prototype.RequiredTechnologies)
|
||||
{
|
||||
if (!IsTechnologyUnlocked(uid, technologyId, component))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
|
||||
var discipline = PrototypeManager.Index<TechDisciplinePrototype>(prototype.Discipline);
|
||||
if (prototype.Tier < discipline.LockoutTier)
|
||||
return;
|
||||
component.MainDiscipline = prototype.Discipline;
|
||||
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
|
||||
|
||||
research-console-menu-title = R&D Console
|
||||
research-console-menu-unlocked-technologies-label = Unlocked technologies
|
||||
research-console-menu-unlockable-technologies-label = Unlockable technologies
|
||||
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-research-points-text = Research: [color=orchid]{$points}[/color]
|
||||
research-console-menu-main-discipline = Main Discipline: [color={$color}]{$name}[/color]
|
||||
research-console-menu-server-selection-button = Server list
|
||||
research-console-menu-server-sync-button = Sync
|
||||
research-console-menu-server-unlock-button = Unlock
|
||||
research-console-tech-requirements-none = No technology requirements.
|
||||
research-console-tech-requirements-prototype-name = Requires: {$prototypeName}
|
||||
research-console-menu-server-research-button = Research
|
||||
research-console-available-text = Researchable Technologies
|
||||
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
|
||||
- NetworkConfigurator
|
||||
- AirlockPainter
|
||||
- FlashlightLantern
|
||||
- CableStack
|
||||
- CableMVStack
|
||||
- CableHVStack
|
||||
- HandheldGPSBasic
|
||||
- TRayScanner
|
||||
- GasAnalyzer
|
||||
- UtilityBelt
|
||||
- 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
|
||||
price: 800
|
||||
|
||||
@@ -159,29 +184,12 @@
|
||||
idleState: icon
|
||||
runningState: building
|
||||
dynamicRecipes:
|
||||
- LightTube
|
||||
- LightBulb
|
||||
- SheetSteel #these sheet recipe costs don't scale with upgrades
|
||||
- SheetGlass1
|
||||
- SheetRGlass
|
||||
- SheetPlastic
|
||||
- CableStack
|
||||
- CableMVStack
|
||||
- CableHVStack
|
||||
- PowerDrill
|
||||
- MiningDrill
|
||||
- ConveyorBeltAssembly
|
||||
- AppraisalTool
|
||||
- AnomalyScanner
|
||||
- AnomalyLocator
|
||||
- RCD
|
||||
- RCDAmmo
|
||||
- HydroponicsToolScythe
|
||||
- HydroponicsToolHatchet
|
||||
- Clippers
|
||||
- MiniHoe
|
||||
- Shovel
|
||||
- Spade
|
||||
- HandheldCrewMonitor
|
||||
- Scalpel
|
||||
- Retractor
|
||||
@@ -198,42 +206,28 @@
|
||||
- PillCanister
|
||||
- ChemistryEmptyBottle01
|
||||
- Drone
|
||||
- Flash
|
||||
- MicroManipulatorStockPart
|
||||
- MatterBinStockPart
|
||||
- CapacitorStockPart
|
||||
- AdvancedCapacitorStockPart
|
||||
- AdvancedMatterBinStockPart
|
||||
- NanoManipulatorStockPart
|
||||
- SuperCapacitorStockPart
|
||||
- SuperMatterBinStockPart
|
||||
- PicoManipulatorStockPart
|
||||
- FirelockElectronics
|
||||
- DoorElectronics
|
||||
- APCElectronics
|
||||
- AirAlarmElectronics
|
||||
- FireAlarmElectronics
|
||||
- IntercomElectronics
|
||||
- MailingUnitElectronics
|
||||
- SignalTimerElectronics
|
||||
- Bucket
|
||||
- MopItem
|
||||
- Holoprojector
|
||||
- Mousetrap
|
||||
- LightReplacer
|
||||
- TrashBag
|
||||
- AdvMopItem
|
||||
- WeaponSprayNozzle
|
||||
- ClothingBackpackWaterTank
|
||||
- SprayBottle
|
||||
- MegaSprayBottle
|
||||
- FireExtinguisher
|
||||
- KitchenKnife
|
||||
- ButchCleaver
|
||||
- FlashlightLantern
|
||||
- TimerTrigger
|
||||
- ChemicalPayload
|
||||
- FlashPayload
|
||||
- Signaller
|
||||
- SignalTrigger
|
||||
- VoiceTrigger
|
||||
- PowerCellSmall
|
||||
- PowerCellMedium
|
||||
- PowerCellHigh
|
||||
- WeaponPistolCHIMP
|
||||
@@ -245,7 +239,9 @@
|
||||
- ClothingShoesBootsMag
|
||||
- NodeScanner
|
||||
- HolofanProjector
|
||||
- Vape
|
||||
- ClothingBackpackHolding
|
||||
- ClothingBackpackSatchelHolding
|
||||
- ClothingBackpackDuffelHolding
|
||||
|
||||
- type: entity
|
||||
parent: Protolathe
|
||||
@@ -271,16 +267,7 @@
|
||||
idleState: icon
|
||||
runningState: building
|
||||
dynamicRecipes:
|
||||
- FirelockElectronics
|
||||
- DoorElectronics
|
||||
- APCElectronics
|
||||
- AirAlarmElectronics
|
||||
- FireAlarmElectronics
|
||||
- MailingUnitElectronics
|
||||
- IntercomElectronics
|
||||
- SignalTimerElectronics
|
||||
- SMESMachineCircuitboard
|
||||
- SubstationMachineCircuitboard
|
||||
- ThermomachineFreezerMachineCircuitBoard
|
||||
- PortableScrubberMachineCircuitBoard
|
||||
- CloningPodMachineCircuitboard
|
||||
@@ -492,16 +479,7 @@
|
||||
- ClothingHandsGlovesLatex
|
||||
- ClothingMaskSterile
|
||||
- DiseaseSwab
|
||||
- Scalpel
|
||||
- Retractor
|
||||
- Cautery
|
||||
- Drill
|
||||
- Saw
|
||||
- Hemostat
|
||||
- Beaker
|
||||
- LargeBeaker
|
||||
- CryostasisBeaker
|
||||
- Dropper
|
||||
- Syringe
|
||||
- Implanter
|
||||
- PillCanister
|
||||
@@ -518,6 +496,15 @@
|
||||
dynamicRecipes:
|
||||
- HandheldCrewMonitor
|
||||
- ClothingHandsGlovesNitrile
|
||||
- CryostasisBeaker
|
||||
- LargeBeaker
|
||||
- Dropper
|
||||
- Scalpel
|
||||
- Retractor
|
||||
- Cautery
|
||||
- Drill
|
||||
- Saw
|
||||
- Hemostat
|
||||
- type: Machine
|
||||
board: MedicalTechFabCircuitboard
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
state: server
|
||||
- type: ResearchServer
|
||||
- type: TechnologyDatabase
|
||||
supportedDisciplines:
|
||||
- Industrial
|
||||
- Biochemical
|
||||
- Experimental
|
||||
- CivilianServices
|
||||
- type: ApcPowerReceiver
|
||||
powerLoad: 200
|
||||
priority: Low
|
||||
|
||||
@@ -72,3 +72,30 @@
|
||||
materials:
|
||||
Steel: 500
|
||||
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
|
||||
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
|
||||
id: 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
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "display"
|
||||
},
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
|
||||
|
After Width: | Height: | Size: 943 B |
@@ -7,6 +7,9 @@
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "display"
|
||||
},
|
||||
{
|
||||
"name": "fat"
|
||||
},
|
||||
|
||||
|
After Width: | Height: | Size: 785 B |
@@ -7,6 +7,9 @@
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "display"
|
||||
},
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
|
||||
|
After Width: | Height: | Size: 735 B |
@@ -7,6 +7,9 @@
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "display"
|
||||
},
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
|
||||