Skill progression system (#1263)
* delete skill trees
* Revert "delete skill trees"
This reverts commit 9d7fae73c4.
* learning refactor
* UI tweaks
* sword mastery skill
* telegraphy
* rapier mastery
* research table ui
* finish studing
* polish UI researching
* pyrokinetic
* more skill tree working
* heat adapt
* alchemist and metamagic update
* skill multiple effects support + metamagic bugg manapool
* impossible 😢
* skimitar gaming
* skimidi
* blacksmithing branch
* remove research restrictions
* remove species magic buff
* fix loc
* Update thaumaturgy.yml
* pip
* Delete skill_tree.yml
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<Button Name="Button">
|
||||
<GridContainer Columns="2">
|
||||
<TextureRect Name="View"
|
||||
Stretch="KeepAspectCentered"
|
||||
Margin="0,0,4,0"
|
||||
MinSize="48 48"
|
||||
MaxSize="48 48"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalExpand="True" />
|
||||
<Label Name="Name" />
|
||||
</GridContainer>
|
||||
</Button>
|
||||
</Control>
|
||||
@@ -0,0 +1,60 @@
|
||||
using Content.Shared._CP14.Skill;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._CP14.ResearchTable;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class CP14ResearchRecipeControl : Control
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
public event Action<CP14ResearchUiEntry, CP14SkillPrototype>? OnResearch;
|
||||
|
||||
private readonly SpriteSystem _sprite;
|
||||
private readonly CP14SharedSkillSystem _skillSystem;
|
||||
|
||||
private readonly CP14SkillPrototype _skillPrototype;
|
||||
private readonly bool _craftable;
|
||||
|
||||
public CP14ResearchRecipeControl(CP14ResearchUiEntry entry)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
_skillSystem = _entity.System<CP14SharedSkillSystem>();
|
||||
|
||||
_skillPrototype = _prototype.Index(entry.ProtoId);
|
||||
_craftable = entry.Craftable;
|
||||
|
||||
Button.OnPressed += _ => OnResearch?.Invoke(entry, _skillPrototype);
|
||||
|
||||
UpdateColor();
|
||||
UpdateName();
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void UpdateColor()
|
||||
{
|
||||
if (_craftable)
|
||||
return;
|
||||
|
||||
Button.ModulateSelfOverride = Color.FromHex("#302622");
|
||||
}
|
||||
|
||||
private void UpdateName()
|
||||
{
|
||||
Name.Text = $"{Loc.GetString(_skillSystem.GetSkillName(_skillPrototype))}" ;
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
{
|
||||
View.Texture =_sprite.Frame0(_skillPrototype.Icon);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Content.Shared._CP14.Skill;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client._CP14.ResearchTable;
|
||||
|
||||
public sealed class CP14ResearchTableBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
private CP14ResearchTableWindow? _window;
|
||||
|
||||
public CP14ResearchTableBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = this.CreateWindow<CP14ResearchTableWindow>();
|
||||
|
||||
_window.OnResearch += entry => SendMessage(new CP14ResearchMessage(entry.ProtoId));
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CP14ResearchTableUiState recipesState:
|
||||
_window?.UpdateState(recipesState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'cp14-research-table-title'}"
|
||||
SetSize="700 500"
|
||||
MinSize="700 300">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<!-- Main -->
|
||||
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Horizontal">
|
||||
<!-- Product list (left side UI) -->
|
||||
<BoxContainer MinWidth="350" HorizontalExpand="True" Orientation="Vertical" Margin="0 0 10 0">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<!-- Search Bar -->
|
||||
<LineEdit Name="SearchBar" Margin="4" PlaceHolder="Search" HorizontalExpand="True" />
|
||||
<OptionButton Name="OptionCategories" Access="Public" MinSize="130 0" />
|
||||
</BoxContainer>
|
||||
<!-- Crafts container -->
|
||||
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" MinSize="0 200">
|
||||
<BoxContainer Name="CraftsContainer" Orientation="Vertical" HorizontalExpand="True" />
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Craft view (right side UI) -->
|
||||
<BoxContainer MinWidth="350" Orientation="Vertical" HorizontalExpand="True"
|
||||
VerticalExpand="True">
|
||||
<PanelContainer HorizontalExpand="True" VerticalExpand="True">
|
||||
<!-- Background -->
|
||||
<PanelContainer.PanelOverride>
|
||||
<graphics:StyleBoxFlat BackgroundColor="#41332f" />
|
||||
</PanelContainer.PanelOverride>
|
||||
|
||||
<!-- Content -->
|
||||
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical">
|
||||
<!-- Item info -->
|
||||
<!-- icon -->
|
||||
<TextureRect Name="ItemView"
|
||||
Stretch="KeepAspectCentered"
|
||||
Margin="5"
|
||||
MinSize="64 64"
|
||||
MaxSize="64 64"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<!-- name & description -->
|
||||
<BoxContainer Margin="5 0 0 0" HorizontalExpand="True" VerticalExpand="True"
|
||||
Orientation="Vertical">
|
||||
<RichTextLabel Name="ItemName" Margin="5" />
|
||||
<RichTextLabel Name="ItemDescription" Margin="5" />
|
||||
</BoxContainer>
|
||||
|
||||
<controls:HLine Color="#404040" Thickness="2" Margin="0 5" />
|
||||
|
||||
<!-- Required title -->
|
||||
<Label Margin="5 0 0 0" Text="{Loc 'cp14-research-recipe-list'}" />
|
||||
|
||||
<!-- Craft requirements content -->
|
||||
<!-- Added by code -->
|
||||
<BoxContainer
|
||||
Margin="5 0 0 0"
|
||||
Name="ItemRequirements"
|
||||
Orientation="Vertical" VerticalExpand="True"
|
||||
HorizontalExpand="True" />
|
||||
|
||||
<controls:HLine Color="#404040" Thickness="5" Margin="0 5" />
|
||||
|
||||
<!-- Craft button -->
|
||||
<Button Name="CraftButton" Text="{Loc 'cp14-research-craft'}" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
@@ -0,0 +1,235 @@
|
||||
using Content.Client._CP14.Workbench;
|
||||
using Content.Shared._CP14.Skill;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared._CP14.Skill.Restrictions;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._CP14.ResearchTable;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class CP14ResearchTableWindow : DefaultWindow
|
||||
{
|
||||
private const int AllCategoryId = -1;
|
||||
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly ILogManager _log = default!;
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
|
||||
private readonly SpriteSystem _sprite;
|
||||
private readonly CP14SharedSkillSystem _skillSystem;
|
||||
|
||||
public event Action<CP14ResearchUiEntry>? OnResearch;
|
||||
|
||||
private readonly Dictionary<int, LocId> _categories = new();
|
||||
|
||||
private CP14ResearchTableUiState? _cachedState;
|
||||
private CP14ResearchUiEntry? _selectedEntry;
|
||||
private string _searchFilter = string.Empty;
|
||||
|
||||
private ISawmill Sawmill { get; init; }
|
||||
|
||||
public CP14ResearchTableWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
_skillSystem = _entity.System<CP14SharedSkillSystem>();
|
||||
|
||||
Sawmill = _log.GetSawmill("cp14_research_table_window");
|
||||
|
||||
SearchBar.OnTextChanged += OnSearchChanged;
|
||||
CraftButton.OnPressed += OnCraftPressed;
|
||||
OptionCategories.OnItemSelected += OnCategoryItemSelected;
|
||||
}
|
||||
|
||||
public void UpdateRecipesVisibility()
|
||||
{
|
||||
if (_cachedState is null)
|
||||
return;
|
||||
|
||||
CraftsContainer.RemoveAllChildren();
|
||||
|
||||
var recipes = new List<CP14ResearchUiEntry>();
|
||||
foreach (var entry in _cachedState.Skills)
|
||||
{
|
||||
if (!_prototype.TryIndex(entry.ProtoId, out var indexedEntry))
|
||||
{
|
||||
Sawmill.Error($"No recipe prototype {entry.ProtoId} retrieved from cache found");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ProcessSearchFilter(indexedEntry))
|
||||
continue;
|
||||
|
||||
if (!ProcessSearchCategoryFilter(indexedEntry))
|
||||
continue;
|
||||
|
||||
recipes.Add(entry);
|
||||
}
|
||||
|
||||
recipes.Sort(CP14ResearchUiEntry.CompareTo);
|
||||
|
||||
foreach (var recipe in recipes)
|
||||
{
|
||||
var control = new CP14ResearchRecipeControl(recipe);
|
||||
control.OnResearch += RecipeSelect;
|
||||
|
||||
CraftsContainer.AddChild(control);
|
||||
}
|
||||
|
||||
if (_selectedEntry is not null && !recipes.Contains(_selectedEntry.Value))
|
||||
RecipeSelectNull();
|
||||
}
|
||||
|
||||
public void UpdateState(CP14ResearchTableUiState recipesState)
|
||||
{
|
||||
_cachedState = recipesState;
|
||||
|
||||
_categories.Clear();
|
||||
OptionCategories.Clear();
|
||||
OptionCategories.AddItem(Loc.GetString("cp14-recipe-category-all"), AllCategoryId);
|
||||
|
||||
var categories = new List<LocId>();
|
||||
var count = 0;
|
||||
|
||||
foreach (var skill in recipesState.Skills)
|
||||
{
|
||||
if (!_prototype.TryIndex(skill.ProtoId, out var indexedSkill))
|
||||
continue;
|
||||
|
||||
if (!_prototype.TryIndex(indexedSkill.Tree, out var indexedTree))
|
||||
continue;
|
||||
|
||||
if (categories.Contains(indexedTree.Name))
|
||||
continue;
|
||||
|
||||
categories.Add(indexedTree.Name);
|
||||
}
|
||||
|
||||
categories.Sort((a, b) => string.Compare(Loc.GetString(a), Loc.GetString(b), StringComparison.Ordinal));
|
||||
|
||||
foreach (var category in categories)
|
||||
{
|
||||
OptionCategories.AddItem(Loc.GetString(category), count);
|
||||
_categories.Add(count, category);
|
||||
count++;
|
||||
}
|
||||
|
||||
UpdateRecipesVisibility();
|
||||
}
|
||||
|
||||
private void OnSearchChanged(LineEdit.LineEditEventArgs _)
|
||||
{
|
||||
_searchFilter = SearchBar.Text.Trim().ToLowerInvariant();
|
||||
UpdateRecipesVisibility();
|
||||
}
|
||||
|
||||
private void OnCraftPressed(BaseButton.ButtonEventArgs _)
|
||||
{
|
||||
if (_selectedEntry is null)
|
||||
return;
|
||||
|
||||
OnResearch?.Invoke(_selectedEntry.Value);
|
||||
}
|
||||
|
||||
private void OnCategoryItemSelected(OptionButton.ItemSelectedEventArgs obj)
|
||||
{
|
||||
OptionCategories.SelectId(obj.Id);
|
||||
UpdateRecipesVisibility();
|
||||
}
|
||||
|
||||
private bool ProcessSearchFilter(CP14SkillPrototype indexedEntry)
|
||||
{
|
||||
if (_searchFilter == string.Empty)
|
||||
return true;
|
||||
|
||||
return Loc.GetString(_skillSystem.GetSkillName(indexedEntry)).Contains(_searchFilter);
|
||||
}
|
||||
|
||||
private bool ProcessSearchCategoryFilter(CP14SkillPrototype indexedEntry)
|
||||
{
|
||||
// If we are searching through all categories, we simply skip the current filter
|
||||
if (OptionCategories.SelectedId == AllCategoryId)
|
||||
return true;
|
||||
|
||||
if (!_categories.TryGetValue(OptionCategories.SelectedId, out var selectedCategory))
|
||||
{
|
||||
Sawmill.Error($"Non-existent {OptionCategories.SelectedId} category id selected. Filter skipped");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_prototype.TryIndex(indexedEntry.Tree, out var indexedTree))
|
||||
{
|
||||
Sawmill.Error($"Non-existent {indexedEntry.Tree} category prototype id. Filter skipped");
|
||||
return true;
|
||||
}
|
||||
|
||||
return indexedTree.Name == selectedCategory;
|
||||
}
|
||||
|
||||
private void RecipeSelect(CP14ResearchTableUiState recipesState)
|
||||
{
|
||||
foreach (var skill in recipesState.Skills)
|
||||
{
|
||||
RecipeSelect(skill, _prototype.Index(skill.ProtoId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void RecipeSelect(CP14ResearchUiEntry cachedEntry)
|
||||
{
|
||||
if (_cachedState is null)
|
||||
return;
|
||||
|
||||
if (_cachedState.Skills.Contains(cachedEntry))
|
||||
{
|
||||
Sawmill.Warning($"The selected cache option {cachedEntry} isn't found in recipes");
|
||||
return;
|
||||
}
|
||||
|
||||
RecipeSelect(cachedEntry, _prototype.Index(cachedEntry.ProtoId));
|
||||
}
|
||||
|
||||
private void RecipeSelect(CP14ResearchUiEntry entry, CP14SkillPrototype skill)
|
||||
{
|
||||
_selectedEntry = entry;
|
||||
|
||||
ItemView.Texture = _sprite.Frame0(skill.Icon);
|
||||
ItemName.Text = _skillSystem.GetSkillName(skill);
|
||||
ItemDescription.Text = _skillSystem.GetSkillDescription(skill);
|
||||
ItemRequirements.RemoveAllChildren();
|
||||
|
||||
foreach (var restriction in skill.Restrictions)
|
||||
{
|
||||
switch (restriction)
|
||||
{
|
||||
case Researched researched:
|
||||
foreach (var requirement in researched.Requirements)
|
||||
{
|
||||
ItemRequirements.AddChild(new CP14WorkbenchRequirementControl(requirement));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CraftButton.Disabled = !entry.Craftable;
|
||||
}
|
||||
|
||||
private void RecipeSelectNull()
|
||||
{
|
||||
_selectedEntry = null;
|
||||
|
||||
ItemView.Texture = null;
|
||||
ItemName.Text = string.Empty;
|
||||
ItemDescription.Text = string.Empty;
|
||||
ItemRequirements.RemoveAllChildren();
|
||||
CraftButton.Disabled = true;
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,9 @@
|
||||
VerticalExpand="True"
|
||||
StyleClasses="OpenRight"
|
||||
Margin="0 0 -1 0">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
Margin="-5 0 0 0">
|
||||
<Label Name="SkillTreeLabel" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" HorizontalAlignment="Right">
|
||||
<TextureRect Name="SkillPointImage" VerticalAlignment="Center" Visible="False" HorizontalAlignment="Center" Margin="0 0 8 0" TextureScale="2, 2" TexturePath="/Textures/_CP14/Interface/Misc/skillpoint.png"/>
|
||||
<Label Name="SkillTreeLabel" Margin="-5 0 0 0"/>
|
||||
</BoxContainer>
|
||||
</Button>
|
||||
<PanelContainer Name="ColorPanel"
|
||||
|
||||
@@ -10,12 +10,21 @@ public sealed partial class CP14SkillTreeButtonControl : Control
|
||||
{
|
||||
public event Action? OnPressed;
|
||||
|
||||
public CP14SkillTreeButtonControl(Color color, string label)
|
||||
public CP14SkillTreeButtonControl(Color color, string label, float skillpoints)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = color };
|
||||
SkillTreeLabel.Text = label;
|
||||
if (skillpoints > 0)
|
||||
{
|
||||
SkillPointImage.Visible = true;
|
||||
SkillTreeLabel.Text = $"{skillpoints} {label}";
|
||||
}
|
||||
else
|
||||
{
|
||||
SkillPointImage.Visible = false;
|
||||
SkillTreeLabel.Text = $"{label}";
|
||||
}
|
||||
|
||||
MainButton.OnPressed += args => OnPressed?.Invoke();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public sealed class CP14SkillUIController : UIController, IOnStateEntered<Gamepl
|
||||
private EntityUid? _targetPlayer;
|
||||
|
||||
private IEnumerable<CP14SkillPrototype> _allSkills = [];
|
||||
private IEnumerable<CP14SkillTreePrototype> _allTrees = [];
|
||||
|
||||
private CP14SkillPrototype? _selectedSkill;
|
||||
private CP14SkillTreePrototype? _selectedSkillTree;
|
||||
@@ -70,9 +71,9 @@ public sealed class CP14SkillUIController : UIController, IOnStateEntered<Gamepl
|
||||
private void CacheSkillProto()
|
||||
{
|
||||
_allSkills = _proto.EnumeratePrototypes<CP14SkillPrototype>();
|
||||
_allTrees = _proto.EnumeratePrototypes<CP14SkillTreePrototype>().OrderBy(tree => Loc.GetString(tree.Name));
|
||||
}
|
||||
|
||||
|
||||
public void OnStateExited(GameplayState state)
|
||||
{
|
||||
if (_window != null)
|
||||
@@ -205,7 +206,7 @@ public sealed class CP14SkillUIController : UIController, IOnStateEntered<Gamepl
|
||||
//Restrictions
|
||||
foreach (var req in skill.Restrictions)
|
||||
{
|
||||
var color = req.Check(_entManager, _playerManager.LocalEntity.Value) ? "green" : "red";
|
||||
var color = req.Check(_entManager, _playerManager.LocalEntity.Value, skill) ? "green" : "red";
|
||||
|
||||
sb.Append($"- [color={color}]{req.GetDescription(_entManager, _proto)}[/color]\n");
|
||||
}
|
||||
@@ -284,14 +285,11 @@ public sealed class CP14SkillUIController : UIController, IOnStateEntered<Gamepl
|
||||
return;
|
||||
|
||||
//If tree not selected, select the first one
|
||||
if (_selectedSkillTree == null && storage.Progress.Count > 0)
|
||||
if (_selectedSkillTree == null)
|
||||
{
|
||||
var firstTree = storage.Progress.First().Key;
|
||||
var firstTree = _allTrees.First();
|
||||
|
||||
if (_proto.TryIndex(firstTree, out var indexedTree))
|
||||
{
|
||||
SelectTree(indexedTree, storage); // Set the first tree from the player's progress
|
||||
}
|
||||
SelectTree(firstTree, storage); // Set the first tree from the player's progress
|
||||
}
|
||||
|
||||
if (_selectedSkillTree == null)
|
||||
@@ -301,26 +299,26 @@ public sealed class CP14SkillUIController : UIController, IOnStateEntered<Gamepl
|
||||
SelectNode(_selectedSkill);
|
||||
UpdateGraphControl();
|
||||
|
||||
// Update the experience points for the selected tree
|
||||
var playerProgress = storage.Progress;
|
||||
if (playerProgress.TryGetValue(_selectedSkillTree, out var skillPoint))
|
||||
{
|
||||
_window.ExpPointLabel.Text = skillPoint.ToString();
|
||||
}
|
||||
|
||||
_window.LevelLabel.Text = $"{storage.SkillsSumExperience}/{storage.ExperienceMaxCap}";
|
||||
|
||||
_window.TreeTabsContainer.RemoveAllChildren();
|
||||
foreach (var (tree, _) in storage.Progress)
|
||||
foreach (var tree in _allTrees)
|
||||
{
|
||||
if (!_proto.TryIndex(tree, out var indexedTree))
|
||||
continue;
|
||||
float learnedPoints = 0;
|
||||
foreach (var skillId in storage.LearnedSkills)
|
||||
{
|
||||
//TODO: Loop indexing each skill is bad
|
||||
if (_proto.TryIndex(skillId, out var skill) && skill.Tree == tree)
|
||||
{
|
||||
learnedPoints += skill.LearnCost;
|
||||
}
|
||||
}
|
||||
|
||||
var treeButton2 = new CP14SkillTreeButtonControl(indexedTree.Color, Loc.GetString(indexedTree.Name));
|
||||
treeButton2.ToolTip = Loc.GetString(indexedTree.Desc ?? string.Empty);
|
||||
var treeButton2 = new CP14SkillTreeButtonControl(tree.Color, Loc.GetString(tree.Name), learnedPoints);
|
||||
treeButton2.ToolTip = Loc.GetString(tree.Desc ?? string.Empty);
|
||||
treeButton2.OnPressed += () =>
|
||||
{
|
||||
SelectTree(indexedTree, storage);
|
||||
SelectTree(tree, storage);
|
||||
};
|
||||
|
||||
_window.TreeTabsContainer.AddChild(treeButton2);
|
||||
@@ -336,9 +334,6 @@ public sealed class CP14SkillUIController : UIController, IOnStateEntered<Gamepl
|
||||
_window.ParallaxBackground.ParallaxPrototype = tree.Parallax;
|
||||
_window.TreeName.Text = Loc.GetString(tree.Name);
|
||||
|
||||
var playerProgress = storage.Progress;
|
||||
_window.ExpPointLabel.Text = playerProgress.TryGetValue(tree, out var skillpoint) ? skillpoint.ToString() : "0";
|
||||
|
||||
UpdateGraphControl();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
xmlns:parallax="clr-namespace:Content.Client.Parallax"
|
||||
xmlns:ui1="clr-namespace:Content.Client._CP14.Skill.Ui"
|
||||
xmlns:nodeTree="clr-namespace:Content.Client._CP14.UserInterface.Systems.NodeTree"
|
||||
Title="{Loc 'cp14-skill-info-title'}"
|
||||
MinSize="700 350"
|
||||
@@ -76,10 +75,6 @@
|
||||
</BoxContainer>
|
||||
<!-- Experience Data -->
|
||||
<BoxContainer Margin="10 10 10 10" VerticalAlignment="Bottom" HorizontalAlignment="Center" Orientation="Horizontal" VerticalExpand="True">
|
||||
<RichTextLabel VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Loc 'cp14-skill-menu-skillpoints'}" StyleClasses="LabelKeyText"/>
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2, 2" TexturePath="/Textures/_CP14/Interface/Misc/skillpoint.png"/>
|
||||
<RichTextLabel Margin="0 0 20 0" Name="ExpPointLabel" VerticalAlignment="Center" HorizontalAlignment="Left" Text="0" StyleClasses="LabelKeyText" Access="Public"/>
|
||||
|
||||
<RichTextLabel VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Loc 'cp14-skill-menu-level'}" StyleClasses="LabelKeyText"/>
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2, 2" TexturePath="/Textures/_CP14/Interface/Misc/skillpoint.png"/>
|
||||
<RichTextLabel Margin="0 0 0 0" Name="LevelLabel" VerticalAlignment="Center" HorizontalAlignment="Left" Text="0" StyleClasses="LabelKeyText" Access="Public"/>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Workbench;
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -13,37 +14,52 @@ using Robust.Shared.Prototypes;
|
||||
namespace Content.Client._CP14.Workbench;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class CP14WorkbenchRequirementControl : Control
|
||||
public sealed partial class CP14WorkbenchRecipeControl : Control
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
public event Action<CP14WorkbenchUiRecipesEntry, CP14WorkbenchRecipePrototype>? OnSelect;
|
||||
|
||||
private readonly SpriteSystem _sprite;
|
||||
|
||||
public CP14WorkbenchRequirementControl()
|
||||
private readonly CP14WorkbenchRecipePrototype _recipePrototype;
|
||||
private readonly bool _craftable;
|
||||
|
||||
public CP14WorkbenchRecipeControl(CP14WorkbenchUiRecipesEntry entry)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
|
||||
_recipePrototype = _prototype.Index(entry.ProtoId);
|
||||
_craftable = entry.Craftable;
|
||||
|
||||
Button.OnPressed += _ => OnSelect?.Invoke(entry, _recipePrototype);
|
||||
|
||||
UpdateColor();
|
||||
UpdateName();
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
public CP14WorkbenchRequirementControl(CP14WorkbenchCraftRequirement requirement) : this()
|
||||
private void UpdateColor()
|
||||
{
|
||||
Name.Text = requirement.GetRequirementTitle(_proto);
|
||||
if (_craftable)
|
||||
return;
|
||||
|
||||
var texture = requirement.GetRequirementTexture(_proto);
|
||||
if (texture is not null)
|
||||
{
|
||||
View.Visible = true;
|
||||
View.Texture = _sprite.Frame0(texture);
|
||||
}
|
||||
Button.ModulateSelfOverride = Color.FromHex("#302622");
|
||||
}
|
||||
|
||||
var entityView = requirement.GetRequirementEntityView(_proto);
|
||||
if (entityView is not null)
|
||||
{
|
||||
EntityView.Visible = true;
|
||||
EntityView.SetPrototype(entityView);
|
||||
}
|
||||
private void UpdateName()
|
||||
{
|
||||
var result = _prototype.Index(_recipePrototype.Result);
|
||||
var counter = _recipePrototype.ResultCount > 1 ? $" x{_recipePrototype.ResultCount}" : "";
|
||||
Name.Text = $"{Loc.GetString(result.Name)} {counter}" ;
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
{
|
||||
View.SetPrototype(_recipePrototype.Result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is sublicensed under MIT License
|
||||
* https://github.com/space-wizards/space-station-14/blob/master/LICENSE.TXT
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Workbench;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._CP14.Workbench;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class CP14WorkbenchRequirementControl : Control
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
private readonly SpriteSystem _sprite;
|
||||
|
||||
public CP14WorkbenchRequirementControl()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
}
|
||||
|
||||
public CP14WorkbenchRequirementControl(CP14WorkbenchCraftRequirement requirement) : this()
|
||||
{
|
||||
Name.Text = requirement.GetRequirementTitle(_proto);
|
||||
|
||||
var texture = requirement.GetRequirementTexture(_proto);
|
||||
if (texture is not null)
|
||||
{
|
||||
View.Visible = true;
|
||||
View.Texture = _sprite.Frame0(texture);
|
||||
}
|
||||
|
||||
var entityView = requirement.GetRequirementEntityView(_proto);
|
||||
if (entityView is not null)
|
||||
{
|
||||
EntityView.Visible = true;
|
||||
EntityView.SetPrototype(entityView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This file is sublicensed under MIT License
|
||||
* https://github.com/space-wizards/space-station-14/blob/master/LICENSE.TXT
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Workbench;
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._CP14.Workbench;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class CP14WorkbenchRecipeControl : Control
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
public event Action<CP14WorkbenchUiRecipesEntry, CP14WorkbenchRecipePrototype>? OnSelect;
|
||||
|
||||
private readonly SpriteSystem _sprite;
|
||||
|
||||
private readonly CP14WorkbenchRecipePrototype _recipePrototype;
|
||||
private readonly bool _craftable;
|
||||
|
||||
public CP14WorkbenchRecipeControl(CP14WorkbenchUiRecipesEntry entry)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
|
||||
_recipePrototype = _prototype.Index(entry.ProtoId);
|
||||
_craftable = entry.Craftable;
|
||||
|
||||
Button.OnPressed += _ => OnSelect?.Invoke(entry, _recipePrototype);
|
||||
|
||||
UpdateColor();
|
||||
UpdateName();
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void UpdateColor()
|
||||
{
|
||||
if (_craftable)
|
||||
return;
|
||||
|
||||
Button.ModulateSelfOverride = Color.FromHex("#302622");
|
||||
}
|
||||
|
||||
private void UpdateName()
|
||||
{
|
||||
var result = _prototype.Index(_recipePrototype.Result);
|
||||
var counter = _recipePrototype.ResultCount > 1 ? $" x{_recipePrototype.ResultCount}" : "";
|
||||
Name.Text = $"{Loc.GetString(result.Name)} {counter}" ;
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
{
|
||||
View.SetPrototype(_recipePrototype.Result);
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,9 @@
|
||||
<!-- icon -->
|
||||
<EntityPrototypeView Name="ItemView"
|
||||
Scale="2,2"
|
||||
Margin="0,0,4,0"
|
||||
MinSize="64 64"
|
||||
MaxSize="64 64"
|
||||
Margin="8"
|
||||
MinSize="96 96"
|
||||
MaxSize="96 96"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<!-- name & description -->
|
||||
|
||||
199
Content.Server/_CP14/ResearchTable/CP14ResearchSystem.cs
Normal file
199
Content.Server/_CP14/ResearchTable/CP14ResearchSystem.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Shared._CP14.ResearchTable;
|
||||
using Content.Shared._CP14.Skill;
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared._CP14.Skill.Restrictions;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.UserInterface;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.ResearchTable;
|
||||
|
||||
public sealed class CP14ResearchSystem : CP14SharedResearchSystem
|
||||
{
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly AudioSystem _audio = default!;
|
||||
|
||||
private IEnumerable<CP14SkillPrototype> _allSkills = [];
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_allSkills = _proto.EnumeratePrototypes<CP14SkillPrototype>();
|
||||
|
||||
SubscribeLocalEvent<CP14ResearchTableComponent, BeforeActivatableUIOpenEvent>(OnBeforeUIOpen);
|
||||
SubscribeLocalEvent<CP14ResearchTableComponent, CP14ResearchMessage>(OnResearch);
|
||||
SubscribeLocalEvent<CP14ResearchTableComponent, CP14ResearchDoAfterEvent>(OnResearchEnd);
|
||||
|
||||
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnReloadPrototypes);
|
||||
}
|
||||
|
||||
private void OnReloadPrototypes(PrototypesReloadedEventArgs ev)
|
||||
{
|
||||
_allSkills = _proto.EnumeratePrototypes<CP14SkillPrototype>();
|
||||
}
|
||||
|
||||
private void OnResearchEnd(Entity<CP14ResearchTableComponent> table, ref CP14ResearchDoAfterEvent args)
|
||||
{
|
||||
if (args.Cancelled || args.Handled)
|
||||
return;
|
||||
|
||||
if (!_proto.TryIndex(args.Skill, out var indexedSkill))
|
||||
return;
|
||||
|
||||
var placedEntities = _lookup.GetEntitiesInRange(Transform(table).Coordinates,
|
||||
table.Comp.ResearchRadius,
|
||||
LookupFlags.Uncontained);
|
||||
|
||||
if (!CanResearch(indexedSkill, placedEntities, args.User))
|
||||
return;
|
||||
|
||||
if (!TryComp<CP14SkillStorageComponent>(args.User, out var storage))
|
||||
return;
|
||||
if (storage.ResearchedSkills.Contains(args.Skill) || storage.LearnedSkills.Contains(args.Skill))
|
||||
return;
|
||||
storage.ResearchedSkills.Add(args.Skill);
|
||||
Dirty(args.User, storage);
|
||||
|
||||
foreach (var restriction in indexedSkill.Restrictions)
|
||||
{
|
||||
switch (restriction)
|
||||
{
|
||||
case Researched researched:
|
||||
foreach (var req in researched.Requirements)
|
||||
{
|
||||
req.PostCraft(EntityManager, _proto, placedEntities, args.User);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_audio.PlayPvs(table.Comp.ResearchSound, table);
|
||||
UpdateUI(table, args.User);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnResearch(Entity<CP14ResearchTableComponent> ent, ref CP14ResearchMessage args)
|
||||
{
|
||||
if (!TryComp<CP14SkillStorageComponent>(args.Actor, out var storage))
|
||||
return;
|
||||
|
||||
if (storage.ResearchedSkills.Contains(args.Skill) || storage.LearnedSkills.Contains(args.Skill))
|
||||
return;
|
||||
|
||||
if (!_proto.TryIndex(args.Skill, out var indexedSkill))
|
||||
return;
|
||||
|
||||
StartResearch(ent, args.Actor, indexedSkill);
|
||||
}
|
||||
|
||||
private void OnBeforeUIOpen(Entity<CP14ResearchTableComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
||||
{
|
||||
UpdateUI(ent, args.User);
|
||||
}
|
||||
|
||||
private void UpdateUI(Entity<CP14ResearchTableComponent> entity, EntityUid user)
|
||||
{
|
||||
var placedEntities = _lookup.GetEntitiesInRange(Transform(entity).Coordinates, entity.Comp.ResearchRadius);
|
||||
|
||||
if (!TryComp<CP14SkillStorageComponent>(user, out var storage))
|
||||
return;
|
||||
|
||||
var researches = new List<CP14ResearchUiEntry>();
|
||||
foreach (var skill in _allSkills)
|
||||
{
|
||||
var researchable = false;
|
||||
var canCraft = true;
|
||||
var hidden = false;
|
||||
|
||||
foreach (var restriction in skill.Restrictions)
|
||||
{
|
||||
if (storage.ResearchedSkills.Contains(skill) || storage.LearnedSkills.Contains(skill))
|
||||
continue;
|
||||
|
||||
switch (restriction)
|
||||
{
|
||||
case SpeciesWhitelist speciesWhitelist: //We cant change species of our character, so hide it
|
||||
if (!speciesWhitelist.Check(EntityManager, user, skill))
|
||||
hidden = true;
|
||||
break;
|
||||
|
||||
case NeedPrerequisite prerequisite:
|
||||
if (!storage.ResearchedSkills.Contains(prerequisite.Prerequisite))
|
||||
hidden = true;
|
||||
break;
|
||||
|
||||
case Researched researched:
|
||||
researchable = true;
|
||||
|
||||
foreach (var req in researched.Requirements)
|
||||
{
|
||||
if (!req.CheckRequirement(EntityManager, _proto, placedEntities, user))
|
||||
{
|
||||
canCraft = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!researchable || hidden)
|
||||
continue;
|
||||
|
||||
var entry = new CP14ResearchUiEntry(skill, canCraft);
|
||||
|
||||
researches.Add(entry);
|
||||
}
|
||||
|
||||
_userInterface.SetUiState(entity.Owner, CP14ResearchTableUiKey.Key, new CP14ResearchTableUiState(researches));
|
||||
}
|
||||
|
||||
private void StartResearch(Entity<CP14ResearchTableComponent> table, EntityUid user, CP14SkillPrototype skill)
|
||||
{
|
||||
var researchDoAfter = new CP14ResearchDoAfterEvent()
|
||||
{
|
||||
Skill = skill
|
||||
};
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager,
|
||||
user,
|
||||
TimeSpan.FromSeconds(table.Comp.ResearchSpeed),
|
||||
researchDoAfter,
|
||||
table,
|
||||
table)
|
||||
{
|
||||
BreakOnMove = true,
|
||||
BreakOnDamage = true,
|
||||
NeedHand = true,
|
||||
};
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||
_audio.PlayPvs(table.Comp.ResearchSound, table);
|
||||
}
|
||||
|
||||
private bool CanResearch(CP14SkillPrototype skill, HashSet<EntityUid> entities, EntityUid user)
|
||||
{
|
||||
foreach (var restriction in skill.Restrictions)
|
||||
{
|
||||
switch (restriction)
|
||||
{
|
||||
case Researched researched:
|
||||
foreach (var req in researched.Requirements)
|
||||
{
|
||||
if (!req.CheckRequirement(EntityManager, _proto, entities, user))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -35,10 +35,11 @@ public sealed partial class CP14WorkbenchSystem
|
||||
|
||||
foreach (var requirement in indexedRecipe.Requirements)
|
||||
{
|
||||
if (!requirement.CheckRequirement(EntityManager, _proto, placedEntities, user, indexedRecipe))
|
||||
if (!requirement.CheckRequirement(EntityManager, _proto, placedEntities, user))
|
||||
{
|
||||
canCraft = false;
|
||||
hidden = requirement.HideRecipe;
|
||||
if (requirement.HideRecipe)
|
||||
hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._CP14.Workbench;
|
||||
|
||||
public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
|
||||
public sealed partial class CP14WorkbenchSystem : CP14SharedWorkbenchSystem
|
||||
{
|
||||
[Dependency] private readonly AudioSystem _audio = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
@@ -139,7 +139,7 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
|
||||
{
|
||||
foreach (var req in recipe.Requirements)
|
||||
{
|
||||
if (!req.CheckRequirement(EntityManager, _proto, entities, user, recipe))
|
||||
if (!req.CheckRequirement(EntityManager, _proto, entities, user))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,5 +57,5 @@ public sealed partial class LoadoutPrototype : IPrototype, IEquipmentLoadout
|
||||
/// CP14 - it is possible to give skill trees to players who have taken this loadout
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<CP14SkillTreePrototype>, FixedPoint2> SkillTree = new();
|
||||
public HashSet<ProtoId<CP14SkillPrototype>> Skills = new();
|
||||
}
|
||||
|
||||
@@ -102,9 +102,9 @@ public abstract class SharedStationSpawningSystem : EntitySystem
|
||||
_action.AddAction(entity, action);
|
||||
}
|
||||
|
||||
foreach (var tree in loadout.SkillTree)
|
||||
foreach (var skill in loadout.Skills)
|
||||
{
|
||||
_skill.TryAddExperience(entity, tree.Key, tree.Value);
|
||||
_skill.TryAddSkill(entity, skill);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,19 @@ public abstract class SharedCP14MagicEnergySystem : EntitySystem
|
||||
_ambient.SetAmbience(ent, args.Powered);
|
||||
}
|
||||
|
||||
private void UpdateMagicAlert(Entity<CP14MagicEnergyContainerComponent> ent)
|
||||
{
|
||||
if (ent.Comp.MagicAlert is null)
|
||||
return;
|
||||
|
||||
var level = ContentHelpers.RoundToLevels(
|
||||
MathF.Max(0f, (float) ent.Comp.Energy),
|
||||
(float) ent.Comp.MaxEnergy,
|
||||
_alerts.GetMaxSeverity(ent.Comp.MagicAlert.Value));
|
||||
|
||||
_alerts.ShowAlert(ent, ent.Comp.MagicAlert.Value, (short) level);
|
||||
}
|
||||
|
||||
public void ChangeEnergy(Entity<CP14MagicEnergyContainerComponent?> ent,
|
||||
FixedPoint2 energy,
|
||||
out FixedPoint2 deltaEnergy,
|
||||
@@ -154,17 +167,14 @@ public abstract class SharedCP14MagicEnergySystem : EntitySystem
|
||||
("color", color));
|
||||
}
|
||||
|
||||
private void UpdateMagicAlert(Entity<CP14MagicEnergyContainerComponent> ent)
|
||||
public void ChangeMaximumEnergy(Entity<CP14MagicEnergyContainerComponent?> ent, FixedPoint2 energy)
|
||||
{
|
||||
if (ent.Comp.MagicAlert is null)
|
||||
if (!Resolve(ent, ref ent.Comp, false))
|
||||
return;
|
||||
|
||||
var level = ContentHelpers.RoundToLevels(
|
||||
MathF.Max(0f, (float) ent.Comp.Energy),
|
||||
(float) ent.Comp.MaxEnergy,
|
||||
_alerts.GetMaxSeverity(ent.Comp.MagicAlert.Value));
|
||||
ent.Comp.MaxEnergy += energy;
|
||||
|
||||
_alerts.ShowAlert(ent, ent.Comp.MagicAlert.Value, (short) level);
|
||||
ChangeEnergy(ent, energy, out _, out _);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,4 +15,7 @@ public sealed partial class CP14MagicManacostModifyComponent : Component
|
||||
|
||||
[DataField]
|
||||
public FixedPoint2 GlobalModifier = 1f;
|
||||
|
||||
[DataField]
|
||||
public bool Examinable = false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Content.Shared._CP14.MagicRitual.Prototypes;
|
||||
using Content.Shared._CP14.MagicSpell.Events;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -24,10 +25,10 @@ public sealed partial class CP14MagicManacostModifySystem : EntitySystem
|
||||
|
||||
private void OnVerbExamine(Entity<CP14MagicManacostModifyComponent> ent, ref GetVerbsEvent<ExamineVerb> args)
|
||||
{
|
||||
if (!args.CanInteract || !args.CanAccess)
|
||||
if (!args.CanInteract || !args.CanAccess || !ent.Comp.Examinable)
|
||||
return;
|
||||
|
||||
var markup = GetMagicClothingExamine(ent.Comp);
|
||||
var markup = GetManacostModifyMessage(ent.Comp.GlobalModifier, ent.Comp.Modifiers);
|
||||
_examine.AddDetailedExamineVerb(
|
||||
args,
|
||||
ent.Comp,
|
||||
@@ -37,21 +38,21 @@ public sealed partial class CP14MagicManacostModifySystem : EntitySystem
|
||||
Loc.GetString("cp14-magic-examinable-verb-message"));
|
||||
}
|
||||
|
||||
private FormattedMessage GetMagicClothingExamine(CP14MagicManacostModifyComponent comp)
|
||||
public FormattedMessage GetManacostModifyMessage(FixedPoint2 global, Dictionary<ProtoId<CP14MagicTypePrototype>, FixedPoint2> modifiers)
|
||||
{
|
||||
var msg = new FormattedMessage();
|
||||
msg.AddMarkupOrThrow(Loc.GetString("cp14-clothing-magic-examine"));
|
||||
|
||||
if (comp.GlobalModifier != 1)
|
||||
if (global != 1)
|
||||
{
|
||||
msg.PushNewline();
|
||||
|
||||
var plus = (float)comp.GlobalModifier > 1 ? "+" : "";
|
||||
var plus = (float)global > 1 ? "+" : "";
|
||||
msg.AddMarkupOrThrow(
|
||||
$"{Loc.GetString("cp14-clothing-magic-global")}: {plus}{MathF.Round((float)(comp.GlobalModifier - 1) * 100, MidpointRounding.AwayFromZero)}%");
|
||||
$"{Loc.GetString("cp14-clothing-magic-global")}: {plus}{MathF.Round((float)(global - 1) * 100, MidpointRounding.AwayFromZero)}%");
|
||||
}
|
||||
|
||||
foreach (var modifier in comp.Modifiers)
|
||||
foreach (var modifier in modifiers)
|
||||
{
|
||||
if (modifier.Value == 1)
|
||||
continue;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._CP14.ResearchTable;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class CP14ResearchTableComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public float ResearchSpeed = 3f;
|
||||
|
||||
[DataField]
|
||||
public float ResearchRadius = 0.5f;
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier ResearchSound = new SoundCollectionSpecifier("PaperScribbles");
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.ResearchTable;
|
||||
|
||||
public abstract class CP14SharedResearchSystem : EntitySystem
|
||||
{
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class CP14ResearchDoAfterEvent : DoAfterEvent
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ProtoId<CP14SkillPrototype> Skill = default!;
|
||||
|
||||
public override DoAfterEvent Clone() => this;
|
||||
}
|
||||
22
Content.Shared/_CP14/Skill/CP14LearnSkillsSpecial.cs
Normal file
22
Content.Shared/_CP14/Skill/CP14LearnSkillsSpecial.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill;
|
||||
|
||||
public sealed partial class CP14LearnSkillsSpecial : JobSpecial
|
||||
{
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14SkillPrototype>> Skills { get; private set; } = new();
|
||||
|
||||
public override void AfterEquip(EntityUid mob)
|
||||
{
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
var skillSys = entMan.System<CP14SharedSkillSystem>();
|
||||
|
||||
foreach (var skill in Skills)
|
||||
{
|
||||
skillSys.TryAddSkill(mob, skill);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
Content.Shared/_CP14/Skill/CP14ResearchTableUI.cs
Normal file
61
Content.Shared/_CP14/Skill/CP14ResearchTableUI.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Skill;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum CP14ResearchTableUiKey
|
||||
{
|
||||
Key,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14ResearchMessage(ProtoId<CP14SkillPrototype> skill) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly ProtoId<CP14SkillPrototype> Skill = skill;
|
||||
}
|
||||
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14ResearchTableUiState(List<CP14ResearchUiEntry> skills) : BoundUserInterfaceState
|
||||
{
|
||||
public readonly List<CP14ResearchUiEntry> Skills = skills;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public readonly struct CP14ResearchUiEntry(ProtoId<CP14SkillPrototype> protoId, bool craftable) : IEquatable<CP14ResearchUiEntry>
|
||||
{
|
||||
public readonly ProtoId<CP14SkillPrototype> ProtoId = protoId;
|
||||
public readonly bool Craftable = craftable;
|
||||
|
||||
public int CompareTo(CP14ResearchUiEntry other)
|
||||
{
|
||||
return Craftable.CompareTo(other.Craftable);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is CP14ResearchUiEntry other && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(CP14ResearchUiEntry other)
|
||||
{
|
||||
return ProtoId.Id == other.ProtoId.Id;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(ProtoId, Craftable);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ProtoId} ({Craftable})";
|
||||
}
|
||||
|
||||
public static int CompareTo(CP14ResearchUiEntry left, CP14ResearchUiEntry right)
|
||||
{
|
||||
return right.CompareTo(left);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
@@ -7,12 +9,16 @@ namespace Content.Shared._CP14.Skill;
|
||||
|
||||
public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
{
|
||||
private EntityQuery<CP14SkillStorageComponent> _skillStorageQuery = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_skillStorageQuery = GetEntityQuery<CP14SkillStorageComponent>();
|
||||
|
||||
InitializeAdmin();
|
||||
InitializeChecks();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -31,15 +37,19 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return false;
|
||||
|
||||
if (indexedSkill.Effect is not null)
|
||||
foreach (var effect in indexedSkill.Effects)
|
||||
{
|
||||
indexedSkill.Effect.AddSkill(EntityManager, target);
|
||||
effect.AddSkill(EntityManager, target);
|
||||
}
|
||||
|
||||
component.SkillsSumExperience += indexedSkill.LearnCost;
|
||||
|
||||
component.LearnedSkills.Add(skill);
|
||||
Dirty(target, component);
|
||||
|
||||
var learnEv = new CP14SkillLearnedEvent(skill, target);
|
||||
RaiseLocalEvent(target, ref learnEv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -59,9 +69,9 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return false;
|
||||
|
||||
if (indexedSkill.Effect is not null)
|
||||
foreach (var effect in indexedSkill.Effects)
|
||||
{
|
||||
indexedSkill.Effect.RemoveSkill(EntityManager, target);
|
||||
effect.RemoveSkill(EntityManager, target);
|
||||
}
|
||||
|
||||
component.SkillsSumExperience -= indexedSkill.LearnCost;
|
||||
@@ -83,55 +93,6 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
return component.LearnedSkills.Contains(skill);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds experience to the specified skill tree for the player.
|
||||
/// </summary>
|
||||
public bool TryAddExperience(EntityUid target,
|
||||
ProtoId<CP14SkillTreePrototype> tree,
|
||||
FixedPoint2 exp,
|
||||
CP14SkillStorageComponent? component = null)
|
||||
{
|
||||
if (!Resolve(target, ref component, false))
|
||||
return false;
|
||||
|
||||
if (component.Progress.TryGetValue(tree, out var currentExp))
|
||||
{
|
||||
// If the tree already exists, add experience to it
|
||||
component.Progress[tree] = currentExp + exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the tree doesn't exist, initialize it with the experience
|
||||
component.Progress[tree] = exp;
|
||||
}
|
||||
|
||||
Dirty(target, component);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes experience from the specified skill tree for the player.
|
||||
/// </summary>
|
||||
public bool TryRemoveExperience(EntityUid target,
|
||||
ProtoId<CP14SkillTreePrototype> tree,
|
||||
FixedPoint2 exp,
|
||||
CP14SkillStorageComponent? component = null)
|
||||
{
|
||||
if (!Resolve(target, ref component, false))
|
||||
return false;
|
||||
|
||||
if (!component.Progress.TryGetValue(tree, out var currentExp))
|
||||
return false;
|
||||
|
||||
if (currentExp < exp)
|
||||
return false;
|
||||
|
||||
component.Progress[tree] = FixedPoint2.Max(0, component.Progress[tree] - exp);
|
||||
|
||||
Dirty(target, component);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the player can learn the specified skill.
|
||||
/// </summary>
|
||||
@@ -158,12 +119,6 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
if (!AllowedToLearn(target, skill, component))
|
||||
return false;
|
||||
|
||||
//Experience check
|
||||
if (!component.Progress.TryGetValue(skill.Tree, out var currentExp))
|
||||
return false;
|
||||
if (currentExp < skill.LearnCost)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -182,13 +137,13 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
return false;
|
||||
|
||||
//Check max cap
|
||||
if (component.SkillsSumExperience + skill.LearnCost >= component.ExperienceMaxCap)
|
||||
if (component.SkillsSumExperience + skill.LearnCost > component.ExperienceMaxCap)
|
||||
return false;
|
||||
|
||||
//Restrictions check
|
||||
foreach (var req in skill.Restrictions)
|
||||
{
|
||||
if (!req.Check(EntityManager, target))
|
||||
if (!req.Check(EntityManager, target, skill))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -205,15 +160,9 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
if (!Resolve(target, ref component, false))
|
||||
return false;
|
||||
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return false;
|
||||
|
||||
if (!CanLearnSkill(target, skill, component))
|
||||
return false;
|
||||
|
||||
if (!TryRemoveExperience(target, indexedSkill.Tree, indexedSkill.LearnCost, component))
|
||||
return false;
|
||||
|
||||
if (!TryAddSkill(target, skill, component))
|
||||
return false;
|
||||
|
||||
@@ -228,11 +177,11 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return string.Empty;
|
||||
|
||||
if (indexedSkill.Name != null)
|
||||
if (indexedSkill.Name is not null)
|
||||
return Loc.GetString(indexedSkill.Name);
|
||||
|
||||
if (indexedSkill.Effect != null)
|
||||
return indexedSkill.Effect.GetName(EntityManager, _proto) ?? string.Empty;
|
||||
if (indexedSkill.Effects.Count > 0)
|
||||
return indexedSkill.Effects.First().GetName(EntityManager, _proto) ?? string.Empty;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -245,12 +194,19 @@ public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return string.Empty;
|
||||
|
||||
if (indexedSkill.Desc != null)
|
||||
if (indexedSkill.Desc is not null)
|
||||
return Loc.GetString(indexedSkill.Desc);
|
||||
|
||||
if (indexedSkill.Effect != null)
|
||||
return indexedSkill.Effect.GetDescription(EntityManager, _proto) ?? string.Empty;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
return string.Empty;
|
||||
foreach (var effect in indexedSkill.Effects)
|
||||
{
|
||||
sb.Append(effect.GetDescription(EntityManager, _proto, skill) + "\n");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
public record struct CP14SkillLearnedEvent(ProtoId<CP14SkillPrototype> Skill, EntityUid User);
|
||||
|
||||
@@ -50,27 +50,6 @@ public abstract partial class CP14SharedSkillSystem
|
||||
|
||||
var target = args.Target;
|
||||
|
||||
//Add skill points
|
||||
foreach (var tree in _allTrees)
|
||||
{
|
||||
FixedPoint2 current = 0;
|
||||
ent.Comp.Progress.TryGetValue(tree, out current);
|
||||
|
||||
var name = Loc.GetString(tree.Name);
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = name,
|
||||
Message = $"{name} EXP {current} -> {current + 1}",
|
||||
Category = VerbCategory.CP14AdminSkillAdd,
|
||||
Icon = tree.Icon,
|
||||
Act = () =>
|
||||
{
|
||||
TryAddExperience(target, tree.ID, 1);
|
||||
},
|
||||
Priority = 2,
|
||||
});
|
||||
}
|
||||
|
||||
//Add Skill
|
||||
foreach (var skill in _allSkills)
|
||||
{
|
||||
@@ -91,30 +70,6 @@ public abstract partial class CP14SharedSkillSystem
|
||||
});
|
||||
}
|
||||
|
||||
//Remove skill points
|
||||
foreach (var tree in _allTrees)
|
||||
{
|
||||
FixedPoint2 current = 0;
|
||||
ent.Comp.Progress.TryGetValue(tree, out current);
|
||||
|
||||
if (current < 1)
|
||||
continue;
|
||||
|
||||
var name = Loc.GetString(tree.Name);
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = name,
|
||||
Message = $"{name} EXP {current} -> {current - 1}",
|
||||
Category = VerbCategory.CP14AdminSkillRemove,
|
||||
Icon = tree.Icon,
|
||||
Act = () =>
|
||||
{
|
||||
TryRemoveExperience(target, tree.ID, 1);
|
||||
},
|
||||
Priority = 2,
|
||||
});
|
||||
}
|
||||
|
||||
//Remove Skill
|
||||
foreach (var skill in ent.Comp.LearnedSkills)
|
||||
{
|
||||
|
||||
75
Content.Shared/_CP14/Skill/CP14SkillSystem.Checks.cs
Normal file
75
Content.Shared/_CP14/Skill/CP14SkillSystem.Checks.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Throwing;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared._CP14.Skill;
|
||||
|
||||
public abstract partial class CP14SharedSkillSystem
|
||||
{
|
||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
private void InitializeChecks()
|
||||
{
|
||||
SubscribeLocalEvent<CP14MeleeWeaponSkillRequiredComponent, MeleeHitEvent>(OnMeleeAttack);
|
||||
SubscribeLocalEvent<CP14MeleeWeaponSkillRequiredComponent, ExaminedEvent>(OnExamined);
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<CP14MeleeWeaponSkillRequiredComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Loc.GetString("cp14-skill-issue-title") + "\n");
|
||||
|
||||
foreach (var skill in ent.Comp.Skills)
|
||||
{
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
continue;
|
||||
|
||||
if (indexedSkill.Name is null)
|
||||
continue;
|
||||
|
||||
var color = HaveSkill(args.Examiner, skill) ? Color.LimeGreen.ToHex() : Color.Red.ToHex();
|
||||
sb.Append($"[color={color}] - {Loc.GetString(indexedSkill.Name)} [/color]\n");
|
||||
}
|
||||
args.PushMarkup(sb.ToString());
|
||||
}
|
||||
|
||||
private void OnMeleeAttack(Entity<CP14MeleeWeaponSkillRequiredComponent> ent, ref MeleeHitEvent args)
|
||||
{
|
||||
if (!_skillStorageQuery.TryComp(args.User, out var skillStorage))
|
||||
return;
|
||||
|
||||
var passed = true;
|
||||
foreach (var reqSkill in ent.Comp.Skills)
|
||||
{
|
||||
if (!skillStorage.LearnedSkills.Contains(reqSkill))
|
||||
{
|
||||
passed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
args.BonusDamage *= ent.Comp.DamageMultiplier;
|
||||
|
||||
if (_net.IsClient)
|
||||
return;
|
||||
|
||||
if (passed || !_random.Prob(ent.Comp.DropProbability))
|
||||
return;
|
||||
|
||||
_hands.TryDrop(args.User, ent);
|
||||
_throwing.TryThrow(ent, _random.NextAngle().ToWorldVec() * 2, 2f, args.User);
|
||||
_damageable.TryChangeDamage(args.User, args.BaseDamage);
|
||||
_popup.PopupEntity(Loc.GetString("cp14-skill-issue"), args.User, args.User, PopupType.Medium);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill;
|
||||
|
||||
public abstract partial class CP14SharedSkillSystem
|
||||
{
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
|
||||
public void GiveExperienceInRadius(EntityCoordinates position, ProtoId<CP14SkillTreePrototype> tree, FixedPoint2 points, float radius = 5)
|
||||
{
|
||||
var entities = _lookup.GetEntitiesInRange<CP14SkillStorageComponent>(position, radius, LookupFlags.Uncontained);
|
||||
|
||||
foreach (var ent in entities)
|
||||
{
|
||||
//Cant learn if the position is not in range or obstructed
|
||||
if (!_examine.InRangeUnOccluded(ent, position, radius))
|
||||
continue;
|
||||
|
||||
//Cant learn when dead
|
||||
if (TryComp<MobStateComponent>(ent, out var mobState) && !_mobState.IsAlive(ent, mobState))
|
||||
continue;
|
||||
|
||||
//Cant learn if the entity is sleeping
|
||||
if (HasComp<SleepingComponent>(ent))
|
||||
continue;
|
||||
|
||||
TryAddExperience(ent, tree, points);
|
||||
}
|
||||
}
|
||||
|
||||
public void GiveExperienceInRadius(EntityUid uid,
|
||||
ProtoId<CP14SkillTreePrototype> tree,
|
||||
FixedPoint2 points,
|
||||
float radius = 5)
|
||||
{
|
||||
GiveExperienceInRadius(Transform(uid).Coordinates, tree, points, radius);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component that stores the skills learned by a player and their progress in the skill trees.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||
[Access(typeof(CP14SharedSkillSystem))]
|
||||
public sealed partial class CP14MeleeWeaponSkillRequiredComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// What skills does a character have to have to use this weapon?
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public HashSet<ProtoId<CP14SkillPrototype>> Skills = new();
|
||||
|
||||
/// <summary>
|
||||
/// The chances of dropping a weapon from your hands if the required skills are not learned by the character.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public float DropProbability = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Reduces outgoing damage if the required skills are not learned by the character
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public float DamageMultiplier = 0.5f;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._CP14.ResearchTable;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.GameStates;
|
||||
@@ -10,29 +11,29 @@ namespace Content.Shared._CP14.Skill.Components;
|
||||
/// Component that stores the skills learned by a player and their progress in the skill trees.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||
[Access(typeof(CP14SharedSkillSystem))]
|
||||
[Access(typeof(CP14SharedSkillSystem), typeof(CP14SharedResearchSystem))]
|
||||
public sealed partial class CP14SkillStorageComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public List<ProtoId<CP14SkillPrototype>> LearnedSkills = new();
|
||||
|
||||
/// <summary>
|
||||
/// skills that the player has learned on the research table, but has not yet learned in the skill tree.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public List<ProtoId<CP14SkillPrototype>> ResearchedSkills = new();
|
||||
|
||||
/// <summary>
|
||||
/// The number of experience points spent on skills. Technically this could be calculated via LearnedSkills, but this is a cached value for optimization.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public FixedPoint2 SkillsSumExperience = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Keeps track of progress points in the knowledge areas available to the player. Important: The absence of a specific area means that the player CANNOT progress in that area.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public Dictionary<ProtoId<CP14SkillTreePrototype>, FixedPoint2> Progress = new();
|
||||
|
||||
/// <summary>
|
||||
/// The maximum ceiling of experience points that can be spent on learning skills. Not tied to a category.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public FixedPoint2 ExperienceMaxCap = 10;
|
||||
public FixedPoint2 ExperienceMaxCap = 5;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -39,7 +40,7 @@ public sealed partial class AddAction : CP14SkillEffect
|
||||
return !protoManager.TryIndex(Action, out var indexedAction) ? string.Empty : indexedAction.Name;
|
||||
}
|
||||
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager)
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager, ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
return !protoManager.TryIndex(Action, out var indexedAction) ? string.Empty : indexedAction.Description;
|
||||
}
|
||||
|
||||
31
Content.Shared/_CP14/Skill/Effects/AddComponents.cs
Normal file
31
Content.Shared/_CP14/Skill/Effects/AddComponents.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Effects;
|
||||
|
||||
public sealed partial class AddComponents : CP14SkillEffect
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ComponentRegistry Components = new();
|
||||
|
||||
public override void AddSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
entManager.AddComponents(target, Components);
|
||||
}
|
||||
|
||||
public override void RemoveSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
entManager.RemoveComponents(target, Components);
|
||||
}
|
||||
|
||||
public override string? GetName(IEntityManager entMagager, IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager, ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
33
Content.Shared/_CP14/Skill/Effects/AddMaxMana.cs
Normal file
33
Content.Shared/_CP14/Skill/Effects/AddMaxMana.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Content.Shared._CP14.MagicEnergy;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Effects;
|
||||
|
||||
public sealed partial class AddManaMax : CP14SkillEffect
|
||||
{
|
||||
[DataField]
|
||||
public FixedPoint2 AdditionalMana = 0;
|
||||
public override void AddSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
var magicSystem = entManager.System<SharedCP14MagicEnergySystem>();
|
||||
magicSystem.ChangeMaximumEnergy(target, AdditionalMana);
|
||||
}
|
||||
|
||||
public override void RemoveSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
var magicSystem = entManager.System<SharedCP14MagicEnergySystem>();
|
||||
magicSystem.ChangeMaximumEnergy(target, -AdditionalMana);
|
||||
}
|
||||
|
||||
public override string? GetName(IEntityManager entMagager, IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager, ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
return Loc.GetString("cp14-skill-desc-add-mana", ("mana", AdditionalMana.ToString()));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -13,5 +14,5 @@ public abstract partial class CP14SkillEffect
|
||||
|
||||
public abstract string? GetName(IEntityManager entMagager, IPrototypeManager protoManager);
|
||||
|
||||
public abstract string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager);
|
||||
public abstract string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager, ProtoId<CP14SkillPrototype> skill);
|
||||
}
|
||||
|
||||
78
Content.Shared/_CP14/Skill/Effects/ModifyManacost.cs
Normal file
78
Content.Shared/_CP14/Skill/Effects/ModifyManacost.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.MagicManacostModify;
|
||||
using Content.Shared._CP14.MagicRitual.Prototypes;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Effects;
|
||||
|
||||
public sealed partial class ModifyManacost : CP14SkillEffect
|
||||
{
|
||||
[DataField]
|
||||
public FixedPoint2 Global = 0f;
|
||||
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<CP14MagicTypePrototype>, FixedPoint2> Modifiers = new();
|
||||
|
||||
public override void AddSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
entManager.EnsureComponent<CP14MagicManacostModifyComponent>(target, out var magicEffectManaCost);
|
||||
|
||||
foreach (var (magicType, modifier) in Modifiers)
|
||||
{
|
||||
if (!magicEffectManaCost.Modifiers.ContainsKey(magicType))
|
||||
magicEffectManaCost.Modifiers.Add(magicType, 1 + modifier);
|
||||
else
|
||||
magicEffectManaCost.Modifiers[magicType] += modifier;
|
||||
}
|
||||
magicEffectManaCost.GlobalModifier += Global;
|
||||
}
|
||||
|
||||
public override void RemoveSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
entManager.EnsureComponent<CP14MagicManacostModifyComponent>(target, out var magicEffectManaCost);
|
||||
|
||||
foreach (var (magicType, modifier) in Modifiers)
|
||||
{
|
||||
if (!magicEffectManaCost.Modifiers.ContainsKey(magicType))
|
||||
continue;
|
||||
|
||||
magicEffectManaCost.Modifiers[magicType] -= modifier;
|
||||
if (magicEffectManaCost.Modifiers[magicType] <= 0)
|
||||
magicEffectManaCost.Modifiers.Remove(magicType);
|
||||
}
|
||||
magicEffectManaCost.GlobalModifier -= Global;
|
||||
}
|
||||
|
||||
public override string? GetName(IEntityManager entMagager, IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager, ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Loc.GetString("cp14-clothing-magic-examine")+"\n");
|
||||
|
||||
if (Global != 0)
|
||||
{
|
||||
|
||||
var plus = (float)Global > 0 ? "+" : "";
|
||||
sb.Append(
|
||||
$"{Loc.GetString("cp14-clothing-magic-global")}: {plus}{MathF.Round((float)Global * 100, MidpointRounding.AwayFromZero)}%\n");
|
||||
}
|
||||
|
||||
foreach (var modifier in Modifiers)
|
||||
{
|
||||
if (modifier.Value == 0)
|
||||
continue;
|
||||
|
||||
var plus = modifier.Value > 1 ? "+" : "";
|
||||
var indexedType = protoManager.Index(modifier.Key);
|
||||
sb.Append($"- [color={indexedType.Color.ToHex()}]{Loc.GetString(indexedType.Name)}[/color]: {plus}{modifier.Value*100}%");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -62,7 +63,7 @@ public sealed partial class ReplaceAction : CP14SkillEffect
|
||||
return !protoManager.TryIndex(NewAction, out var indexedAction) ? string.Empty : indexedAction.Name;
|
||||
}
|
||||
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager)
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager, ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
return !protoManager.TryIndex(NewAction, out var indexedAction) ? string.Empty : indexedAction.Description;
|
||||
}
|
||||
|
||||
65
Content.Shared/_CP14/Skill/Effects/UnlockRecipes.cs
Normal file
65
Content.Shared/_CP14/Skill/Effects/UnlockRecipes.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Content.Shared._CP14.Workbench.Requirements;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Effects;
|
||||
|
||||
/// <summary>
|
||||
/// This effect only exists for parsing the description.
|
||||
/// </summary>
|
||||
public sealed partial class UnlockRecipes : CP14SkillEffect
|
||||
{
|
||||
public override void AddSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public override void RemoveSkill(IEntityManager entManager, EntityUid target)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public override string? GetName(IEntityManager entMagager, IPrototypeManager protoManager)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string? GetDescription(IEntityManager entMagager, IPrototypeManager protoManager, ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
var allRecipes = protoManager.EnumeratePrototypes<CP14WorkbenchRecipePrototype>();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Loc.GetString("cp14-skill-desc-unlock-recipes") + "\n");
|
||||
|
||||
var affectedRecipes = new List<CP14WorkbenchRecipePrototype>();
|
||||
foreach (var recipe in allRecipes)
|
||||
{
|
||||
foreach (var req in recipe.Requirements)
|
||||
{
|
||||
switch (req)
|
||||
{
|
||||
case SkillRequired skillReq:
|
||||
foreach (var skillReqSkill in skillReq.Skills)
|
||||
{
|
||||
if (skillReqSkill == skill)
|
||||
{
|
||||
affectedRecipes.Add(recipe);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var recipe in affectedRecipes)
|
||||
{
|
||||
if (!protoManager.TryIndex(recipe.Result, out var indexedResult))
|
||||
continue;
|
||||
sb.Append("- " + indexedResult.Name + "\n");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,13 @@ public sealed partial class CP14SkillPrototype : IPrototype
|
||||
/// Skill Title. If you leave null, the name will try to generate from Effect.GetName()
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? Name;
|
||||
public LocId? Name = null;
|
||||
|
||||
/// <summary>
|
||||
/// Skill Description. If you leave null, the description will try to generate from Effect.GetDescription()
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? Desc;
|
||||
public LocId? Desc = null;
|
||||
|
||||
/// <summary>
|
||||
/// The tree this skill belongs to. This is used to group skills together in the UI.
|
||||
@@ -55,7 +55,7 @@ public sealed partial class CP14SkillPrototype : IPrototype
|
||||
/// But the presence of the skill itself can affect some systems that check for the presence of certain skills.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public CP14SkillEffect? Effect;
|
||||
public List<CP14SkillEffect> Effects = new();
|
||||
|
||||
/// <summary>
|
||||
/// Skill restriction. Limiters on learning. Any reason why a player cannot learn this skill.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -7,7 +8,7 @@ namespace Content.Shared._CP14.Skill.Restrictions;
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class CP14SkillRestriction
|
||||
{
|
||||
public abstract bool Check(IEntityManager entManager, EntityUid target);
|
||||
public abstract bool Check(IEntityManager entManager, EntityUid target, CP14SkillPrototype skill);
|
||||
|
||||
public abstract string GetDescription(IEntityManager entManager, IPrototypeManager protoManager);
|
||||
}
|
||||
|
||||
18
Content.Shared/_CP14/Skill/Restrictions/Impossible.cs
Normal file
18
Content.Shared/_CP14/Skill/Restrictions/Impossible.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Restrictions;
|
||||
|
||||
public sealed partial class Impossible : CP14SkillRestriction
|
||||
{
|
||||
public override bool Check(IEntityManager entManager, EntityUid target, CP14SkillPrototype skill)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GetDescription(IEntityManager entManager, IPrototypeManager protoManager)
|
||||
{
|
||||
return Loc.GetString("cp14-skill-req-impossible");
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ public sealed partial class NeedPrerequisite : CP14SkillRestriction
|
||||
[DataField(required: true)]
|
||||
public ProtoId<CP14SkillPrototype> Prerequisite = new();
|
||||
|
||||
public override bool Check(IEntityManager entManager, EntityUid target)
|
||||
public override bool Check(IEntityManager entManager, EntityUid target, CP14SkillPrototype skill)
|
||||
{
|
||||
if (!entManager.TryGetComponent<CP14SkillStorageComponent>(target, out var skillStorage))
|
||||
return false;
|
||||
|
||||
26
Content.Shared/_CP14/Skill/Restrictions/Researched.cs
Normal file
26
Content.Shared/_CP14/Skill/Restrictions/Researched.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared._CP14.Workbench;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Restrictions;
|
||||
|
||||
public sealed partial class Researched : CP14SkillRestriction
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public List<CP14WorkbenchCraftRequirement> Requirements = new();
|
||||
|
||||
public override bool Check(IEntityManager entManager, EntityUid target, CP14SkillPrototype skill)
|
||||
{
|
||||
if (!entManager.TryGetComponent<CP14SkillStorageComponent>(target, out var skillStorage))
|
||||
return false;
|
||||
|
||||
var learned = skillStorage.ResearchedSkills;
|
||||
return learned.Contains(skill);
|
||||
}
|
||||
|
||||
public override string GetDescription(IEntityManager entManager, IPrototypeManager protoManager)
|
||||
{
|
||||
return Loc.GetString("cp14-skill-req-researched");
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -9,7 +10,7 @@ public sealed partial class SpeciesWhitelist : CP14SkillRestriction
|
||||
[DataField(required: true)]
|
||||
public ProtoId<SpeciesPrototype> Species = new();
|
||||
|
||||
public override bool Check(IEntityManager entManager, EntityUid target)
|
||||
public override bool Check(IEntityManager entManager, EntityUid target, CP14SkillPrototype skill)
|
||||
{
|
||||
if (!entManager.TryGetComponent<HumanoidAppearanceComponent>(target, out var appearance))
|
||||
return false;
|
||||
|
||||
@@ -10,7 +10,7 @@ using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Workbench;
|
||||
|
||||
public abstract class SharedCP14WorkbenchSystem : EntitySystem
|
||||
public abstract class CP14SharedWorkbenchSystem : EntitySystem
|
||||
{
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ public sealed partial class MaterialResource : CP14WorkbenchCraftRequirement
|
||||
EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
EntityUid user)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var ent in placedEntities)
|
||||
|
||||
@@ -22,8 +22,7 @@ public sealed partial class ProtoIdResource : CP14WorkbenchCraftRequirement
|
||||
public override bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
EntityUid user)
|
||||
{
|
||||
var indexedIngredients = IndexIngredients(entManager, placedEntities);
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ public sealed partial class SkillRequired : CP14WorkbenchCraftRequirement
|
||||
public override bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
EntityUid user)
|
||||
{
|
||||
var knowledgeSystem = entManager.System<CP14SharedSkillSystem>();
|
||||
|
||||
@@ -23,8 +23,7 @@ public sealed partial class StackGroupResource : CP14WorkbenchCraftRequirement
|
||||
public override bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
EntityUid user)
|
||||
{
|
||||
if (!protoManager.TryIndex(Group, out var indexedGroup))
|
||||
return false;
|
||||
|
||||
@@ -23,8 +23,7 @@ public sealed partial class StackResource : CP14WorkbenchCraftRequirement
|
||||
public override bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
EntityUid user)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var ent in placedEntities)
|
||||
|
||||
@@ -30,8 +30,7 @@ public sealed partial class TagResource : CP14WorkbenchCraftRequirement
|
||||
EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
EntityUid user)
|
||||
{
|
||||
var tagSystem = entManager.System<TagSystem>();
|
||||
|
||||
|
||||
@@ -26,8 +26,7 @@ public abstract partial class CP14WorkbenchCraftRequirement
|
||||
public abstract bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe);
|
||||
EntityUid user);
|
||||
|
||||
/// <summary>
|
||||
/// An event that is triggered after crafting. This is the place to put important things like removing items, spending stacks or other things.
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
cp14-recipe-title-meat = various pieces of raw meat
|
||||
cp14-recipe-title-energy-crystal = energycrystals
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
cp14-skill-req-prerequisite = Skill "{$name}" must be learned.
|
||||
cp14-skill-req-species = Available only to species "{$name}"
|
||||
cp14-skill-req-prerequisite = Skill "{$name}" must be learned
|
||||
cp14-skill-req-species = You must be the race of “{$name}”
|
||||
cp14-skill-req-researched = A study needs to be done on the research table
|
||||
cp14-skill-req-impossible = Unable to explore during a round at the current moment
|
||||
3
Resources/Locale/en-US/_CP14/skill/skill_issue.ftl
Normal file
3
Resources/Locale/en-US/_CP14/skill/skill_issue.ftl
Normal file
@@ -0,0 +1,3 @@
|
||||
cp14-skill-issue-title = In order to use these weapons effectively, you need to have skill:
|
||||
|
||||
cp14-skill-issue = Skill issue!
|
||||
34
Resources/Locale/en-US/_CP14/skill/skill_meta.ftl
Normal file
34
Resources/Locale/en-US/_CP14/skill/skill_meta.ftl
Normal file
@@ -0,0 +1,34 @@
|
||||
cp14-skill-mastery-desc = Mastering the art of this weapon, you will no longer clumsily drop it or cut yourself.
|
||||
|
||||
cp14-skill-sword-mastery-name = Sword mastery
|
||||
cp14-skill-parier-mastery-name = Rapier mastery
|
||||
cp14-skill-skimitar-mastery-name = Skimitar mastery
|
||||
|
||||
cp14-skill-pyro-t1-name = Basic pyrokinetics
|
||||
cp14-skill-pyro-t2-name = Advanced pyrokinetics
|
||||
cp14-skill-pyro-t3-name = Expert pyrokinetics
|
||||
|
||||
cp14-skill-illusion-t1-name = Basic illusion
|
||||
cp14-skill-illusion-t2-name = Advanced illusion
|
||||
cp14-skill-illusion-t3-name = Expert illusion
|
||||
|
||||
cp14-skill-water-t1-name = Basic hydrosophistry
|
||||
cp14-skill-water-t2-name = Advanced hydrosophistry
|
||||
cp14-skill-water-t3-name = Expert hydrosophistry
|
||||
|
||||
cp14-skill-life-t1-name = Basic lifecation
|
||||
cp14-skill-life-t2-name = Advanced lifecation
|
||||
cp14-skill-life-t3-name = Expert lifecation
|
||||
|
||||
cp14-skill-meta-t1-name = Basic metamagic
|
||||
cp14-skill-meta-t2-name = Advanced metamagic
|
||||
cp14-skill-meta-t3-name = Expert metamagic
|
||||
|
||||
cp14-skill-alchemy-vision-name = Alchemist's Vision
|
||||
cp14-skill-alchemy-vision-desc = You are able to understand what liquids are in containers by visually analyzing them.
|
||||
|
||||
cp14-skill-copper-melt-name = Copper melting
|
||||
cp14-skill-iron-melt-name = Iron melting
|
||||
cp14-skill-gold-melt-name = Gold melting
|
||||
cp14-skill-mithril-melt-name = Mithril melting
|
||||
cp14-skill-glass-melt-name = Glasswork
|
||||
@@ -1,25 +1,36 @@
|
||||
cp14-skill-tree-blaksmithing-name = Blacksmithing
|
||||
cp14-skill-tree-blaksmithing-desc = Explore and create new items from metal.
|
||||
|
||||
cp14-skill-tree-pyrokinetic-name = Pyrokinetic
|
||||
cp14-skill-tree-pyrokinetic-name = Pyrokinesis
|
||||
cp14-skill-tree-pyrokinetic-desc = Master the magic of fire, allowing you to warm, illuminate, and destroy.
|
||||
|
||||
cp14-skill-tree-hydrosophistry-name = Hydrosophistry
|
||||
cp14-skill-tree-hydrosophistry-name = Hydrosophy
|
||||
cp14-skill-tree-hydrosophistry-desc = Master the magic of water and frost to create items from water and ice, and freeze enemies.
|
||||
|
||||
cp14-skill-tree-metamagic-name = Metamagic
|
||||
cp14-skill-tree-metamagic-desc = Explore ways to subtly manipulate magic to affect spells and items.
|
||||
|
||||
cp14-skill-tree-illusion-name = Illusoriness
|
||||
cp14-skill-tree-illusion-name = Illusion
|
||||
cp14-skill-tree-illusion-desc = Explore the nature of light to create illusions, light sources and shadows.
|
||||
|
||||
cp14-skill-tree-healing-name = Lifecation
|
||||
cp14-skill-tree-healing-name = Vivification
|
||||
cp14-skill-tree-healing-desc = Explore the ways in which magic affects living creatures.
|
||||
|
||||
cp14-skill-tree-dimension-name = Dimensium
|
||||
cp14-skill-tree-dimension-name = Dimensionomy
|
||||
cp14-skill-tree-dimension-desc = Immerse yourself in the nature of space and void.
|
||||
|
||||
# Body
|
||||
|
||||
cp14-skill-tree-atlethic-name = Atlethic
|
||||
cp14-skill-tree-atlethic-name = Athletic
|
||||
cp14-skill-tree-atlethic-desc = Develop your body by pushing the boundaries of what is available.
|
||||
|
||||
cp14-skill-tree-martial-name = Martial arts
|
||||
cp14-skill-tree-martial-desc = Master the secrets of deadly weapons, or make your own body a weapon.
|
||||
|
||||
# Job
|
||||
|
||||
cp14-skill-tree-thaumaturgy-name = Alchemy
|
||||
cp14-skill-tree-thaumaturgy-desc = The art of creating magical potions that can kill, raise from the dead, or turn creatures into sheep.
|
||||
|
||||
cp14-skill-tree-blacksmithing-name = Blacksmithing
|
||||
cp14-skill-tree-blacksmithing-desc = The art of turning metal into various useful things.
|
||||
@@ -5,6 +5,12 @@ cp14-skill-info-title = Skills
|
||||
cp14-game-hud-open-skill-menu-button-tooltip = Skill tree
|
||||
|
||||
cp14-skill-menu-learn-button = Learn skill
|
||||
cp14-skill-menu-learncost = [color=yellow]Points required:[/color]
|
||||
cp14-skill-menu-skillpoints = Experience points:
|
||||
cp14-skill-menu-level = Level:
|
||||
cp14-skill-menu-learncost = [color=yellow]Memory required:[/color]
|
||||
cp14-skill-menu-level = Memory:
|
||||
|
||||
cp14-research-table-title = Research table
|
||||
cp14-research-recipe-list = Research costs:
|
||||
cp14-research-craft = Research
|
||||
|
||||
cp14-skill-desc-add-mana = Increases your character's mana amount by {$mana}.
|
||||
cp14-skill-desc-unlock-recipes = Opens up the possibility of crafting:
|
||||
@@ -1 +1,2 @@
|
||||
cp14-recipe-title-meat = разные кусочки сырого мяса
|
||||
cp14-recipe-title-energy-crystal = энергокристаллы
|
||||
@@ -1,2 +1,4 @@
|
||||
cp14-skill-req-prerequisite = Навык "{$name}" должен быть изучен.
|
||||
cp14-skill-req-species = Доступно только расе "{$name}"
|
||||
cp14-skill-req-prerequisite = Навык "{$name}" должен быть изучен
|
||||
cp14-skill-req-species = Вы должны быть расы "{$name}"
|
||||
cp14-skill-req-researched = Необходимо провести исследование на исследовательском столе
|
||||
cp14-skill-req-impossible = Невозможно изучить во время раунда на текузий момент
|
||||
3
Resources/Locale/ru-RU/_CP14/skill/skill_issue.ftl
Normal file
3
Resources/Locale/ru-RU/_CP14/skill/skill_issue.ftl
Normal file
@@ -0,0 +1,3 @@
|
||||
cp14-skill-issue-title = Чтобы эффективно пользовать этим оружием, необходимо владеть навыками:
|
||||
|
||||
cp14-skill-issue = Проблемы с навыком!
|
||||
34
Resources/Locale/ru-RU/_CP14/skill/skill_meta.ftl
Normal file
34
Resources/Locale/ru-RU/_CP14/skill/skill_meta.ftl
Normal file
@@ -0,0 +1,34 @@
|
||||
cp14-skill-mastery-desc = Овладев искусством этого оружия, вы больше не будете неуклюже ронять его, или резать сами себя.
|
||||
|
||||
cp14-skill-sword-mastery-name = Владение мечом
|
||||
cp14-skill-parier-mastery-name = Владение рапирой
|
||||
cp14-skill-skimitar-mastery-name = Владение скимитаром
|
||||
|
||||
cp14-skill-pyro-t1-name = Базовая пирокинетика
|
||||
cp14-skill-pyro-t2-name = Продвинутая пирокинетика
|
||||
cp14-skill-pyro-t3-name = Экспертная пирокинетика
|
||||
|
||||
cp14-skill-illusion-t1-name = Базовая иллюзия
|
||||
cp14-skill-illusion-t2-name = Продвинутая иллюзия
|
||||
cp14-skill-illusion-t3-name = Экспертная иллюзия
|
||||
|
||||
cp14-skill-water-t1-name = Базовая гидрософистика
|
||||
cp14-skill-water-t2-name = Продвинутая гидрософистика
|
||||
cp14-skill-water-t3-name = Экспертная гидрософистика
|
||||
|
||||
cp14-skill-life-t1-name = Базовое животворение
|
||||
cp14-skill-life-t2-name = Продвинутое животворение
|
||||
cp14-skill-life-t3-name = Экспертное животворение
|
||||
|
||||
cp14-skill-meta-t1-name = Базовая метамагия
|
||||
cp14-skill-meta-t2-name = Продвинутая метамагия
|
||||
cp14-skill-meta-t3-name = Экспертная метамагия
|
||||
|
||||
cp14-skill-alchemy-vision-name = Взор алхимика
|
||||
cp14-skill-alchemy-vision-desc = Вы способны понимать какие именно жидкости находятся в емкостях, при помощи визуального анализа.
|
||||
|
||||
cp14-skill-copper-melt-name = Плавка меди
|
||||
cp14-skill-iron-melt-name = Плавка железа
|
||||
cp14-skill-gold-melt-name = Плавка золота
|
||||
cp14-skill-mithril-melt-name = Плавка мифрила
|
||||
cp14-skill-glass-melt-name = Работа со стеклом
|
||||
@@ -25,3 +25,14 @@ cp14-skill-tree-dimension-desc = Погрузитесь в природу про
|
||||
|
||||
cp14-skill-tree-atlethic-name = Атлетика
|
||||
cp14-skill-tree-atlethic-desc = Развивайте свое тело, расширяя границы доступного.
|
||||
|
||||
cp14-skill-tree-martial-name = Боевые исскуства
|
||||
cp14-skill-tree-martial-desc = Овладейте секретами смертельного оружия, или сделайте оружием свое собственное тело.
|
||||
|
||||
# Job
|
||||
|
||||
cp14-skill-tree-thaumaturgy-name = Алхимия
|
||||
cp14-skill-tree-thaumaturgy-desc = Исскуство создания волшебных зелий, способных убивать, воскрешать из мертвых или превращать существ в овечек.
|
||||
|
||||
cp14-skill-tree-blacksmithing-name = Кузнечное дело
|
||||
cp14-skill-tree-blacksmithing-desc = Исскуство превращения металла в различные полезные вещи.
|
||||
@@ -5,6 +5,12 @@ cp14-skill-info-title = Навыки
|
||||
cp14-game-hud-open-skill-menu-button-tooltip = Деревья навыков
|
||||
|
||||
cp14-skill-menu-learn-button = Изучить навык
|
||||
cp14-skill-menu-learncost = [color=yellow]Требуется очков:[/color]
|
||||
cp14-skill-menu-skillpoints = Очков опыта:
|
||||
cp14-skill-menu-level = Уровень:
|
||||
cp14-skill-menu-learncost = [color=yellow]Требуется памяти:[/color]
|
||||
cp14-skill-menu-level = Память:
|
||||
|
||||
cp14-research-table-title = Стол исследований
|
||||
cp14-research-recipe-list = Затраты на исследование:
|
||||
cp14-research-craft = Исследовать
|
||||
|
||||
cp14-skill-desc-add-mana = Увеличивает объем маны вашего персонажа на {$mana}.
|
||||
cp14-skill-desc-unlock-recipes = Открывает возможность создания:
|
||||
@@ -51511,13 +51511,6 @@ entities:
|
||||
rot: 1.5707963267948966 rad
|
||||
pos: 102.332535,53.33797
|
||||
parent: 1
|
||||
- proto: CP14SpellScrollFireRune
|
||||
entities:
|
||||
- uid: 8072
|
||||
components:
|
||||
- type: Transform
|
||||
pos: -100.13099,21.66595
|
||||
parent: 1
|
||||
- proto: CP14SpellScrollFlameCreation
|
||||
entities:
|
||||
- uid: 8073
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: CP14Lighter
|
||||
- id: CP14ManaOperationGlove
|
||||
- id: CP14Syringe
|
||||
amount: 2
|
||||
- id: CP14Cauldron
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: CP14GuidebookAlchemy
|
||||
- id: CP14ClothingEyesAlchemyGlasses
|
||||
prob: 0.5
|
||||
- id: CP14ClothingEyesAlchemyMonocle
|
||||
prob: 0.2
|
||||
- id: CP14ClothingCloakAlchemist
|
||||
prob: 0.6
|
||||
- id: CP14ClothingHeadAlchemistBeret
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
- type: entity
|
||||
id: CP14ActionSpellFireRune
|
||||
name: Fire rune
|
||||
description: You create an area where a scalding stream of fire occurs with little delay.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/Spells/fire.rsi
|
||||
state: tiefling_revenge
|
||||
- type: CP14MagicEffectCastSlowdown
|
||||
speedMultiplier: 0.5
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 15
|
||||
- type: CP14MagicEffect
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
- CP14TelegraphyFireRune
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
- CP14AreaEntityEffectFireRune
|
||||
- type: CP14MagicEffectCastingVisual
|
||||
proto: CP14RuneEarthWall
|
||||
- type: CP14MagicEffectPacifiedBlock
|
||||
- type: EntityWorldTargetAction
|
||||
range: 10
|
||||
itemIconStyle: BigAction
|
||||
sound: !type:SoundPathSpecifier
|
||||
path: /Audio/Magic/rumble.ogg
|
||||
icon:
|
||||
sprite: _CP14/Actions/Spells/fire.rsi
|
||||
state: tiefling_revenge
|
||||
event: !type:CP14DelayedEntityWorldTargetActionEvent
|
||||
cooldown: 10
|
||||
|
||||
- type: entity
|
||||
id: CP14TelegraphyFireRune
|
||||
parent: CP14BaseMagicImpact
|
||||
categories: [ HideSpawnMenu ]
|
||||
save: false
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#eea911"
|
||||
- type: TimedDespawn
|
||||
lifetime: 0.8
|
||||
- type: Sprite
|
||||
noRot: true
|
||||
drawdepth: BelowFloor
|
||||
sprite: _CP14/Effects/Magic/area_impact.rsi
|
||||
layers:
|
||||
- state: area_impact_in
|
||||
color: "#eea911"
|
||||
scale: 2, 2
|
||||
shader: unshaded
|
||||
|
||||
- type: entity
|
||||
id: CP14AreaEntityEffectFireRune
|
||||
parent: CP14BaseMagicImpact
|
||||
categories: [ HideSpawnMenu ]
|
||||
save: false
|
||||
components:
|
||||
- type: PointLight
|
||||
color: "#eea911"
|
||||
- type: Sprite
|
||||
noRot: true
|
||||
drawdepth: BelowFloor
|
||||
sprite: _CP14/Effects/Magic/area_impact.rsi
|
||||
layers:
|
||||
- state: area_impact_out
|
||||
color: "#eea911"
|
||||
scale: 2, 2
|
||||
shader: unshaded
|
||||
- type: TimedDespawn
|
||||
lifetime: 0.8
|
||||
- type: CP14AreaEntityEffect
|
||||
range: 1
|
||||
whitelist:
|
||||
components:
|
||||
- Damageable
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
- CP14ImpactEffectTieflingRevenge
|
||||
- !type:CP14SpellApplyEntityEffect
|
||||
effects:
|
||||
- !type:HealthChange
|
||||
damage:
|
||||
types:
|
||||
Heat: 10
|
||||
|
||||
- type: entity
|
||||
parent: CP14BaseSpellScrollFire
|
||||
id: CP14SpellScrollFireRune
|
||||
name: fire rune spell scroll
|
||||
components:
|
||||
- type: CP14SpellStorage
|
||||
spells:
|
||||
- CP14ActionSpellFireRune
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 20
|
||||
- type: CP14MagicEffect
|
||||
magicType: Fire
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnUser
|
||||
spawns:
|
||||
@@ -36,7 +37,7 @@
|
||||
state: fireball
|
||||
event: !type:CP14DelayedEntityWorldTargetActionEvent
|
||||
cooldown: 25
|
||||
castDelay: 1.5
|
||||
castDelay: 2.5
|
||||
breakOnMove: false
|
||||
|
||||
- type: entity
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 5
|
||||
- type: CP14MagicEffect
|
||||
magicType: Fire
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 1
|
||||
- type: CP14MagicEffect
|
||||
magicType: Fire
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectCastingVisual
|
||||
proto: CP14RuneTieflingRevenge
|
||||
- type: CP14MagicEffect
|
||||
magicType: Fire
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 10
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 10
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 10
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 1
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 3
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 2
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 5
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -13,6 +13,7 @@
|
||||
- type: CP14MagicEffectAliveTargetRequired
|
||||
inverted: true
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 30
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 1
|
||||
- type: CP14MagicEffect
|
||||
magicType: Life
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -9,6 +9,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 10
|
||||
- type: CP14MagicEffect
|
||||
magicType: Light
|
||||
telegraphyEffects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -7,6 +7,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 5
|
||||
- type: CP14MagicEffect
|
||||
magicType: Light
|
||||
- type: CP14MagicEffectSomaticAspect
|
||||
- type: InstantAction
|
||||
itemIconStyle: BigAction
|
||||
@@ -9,6 +9,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 10
|
||||
- type: CP14MagicEffect
|
||||
magicType: Light
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -9,6 +9,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 20
|
||||
- type: CP14MagicEffect
|
||||
magicType: Water
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 7
|
||||
- type: CP14MagicEffect
|
||||
magicType: Water
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
sprite: _CP14/Actions/Spells/water.rsi
|
||||
state: ice_arrow
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 15
|
||||
manaCost: 7
|
||||
- type: CP14MagicEffect
|
||||
magicType: Water
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -30,7 +31,7 @@
|
||||
sprite: _CP14/Actions/Spells/water.rsi
|
||||
state: ice_arrow
|
||||
event: !type:CP14DelayedInstantActionEvent
|
||||
cooldown: 5
|
||||
cooldown: 10
|
||||
breakOnMove: false
|
||||
|
||||
- type: entity
|
||||
@@ -78,7 +79,7 @@
|
||||
onlyCollideWhenShot: true
|
||||
damage:
|
||||
types:
|
||||
Piercing: 17
|
||||
Piercing: 15
|
||||
Cold: 5
|
||||
- type: Damageable
|
||||
- type: Destructible
|
||||
@@ -93,7 +94,7 @@
|
||||
- !type:DoActsBehavior
|
||||
acts: ["Destruction"]
|
||||
- type: TimedDespawn
|
||||
lifetime: 60
|
||||
lifetime: 240
|
||||
- type: DamageOnLand
|
||||
damage:
|
||||
types:
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
sprite: _CP14/Actions/Spells/water.rsi
|
||||
state: ice_dagger
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 15
|
||||
manaCost: 25
|
||||
- type: CP14MagicEffect
|
||||
magicType: Water
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
@@ -30,7 +31,7 @@
|
||||
sprite: _CP14/Actions/Spells/water.rsi
|
||||
state: ice_dagger
|
||||
event: !type:CP14DelayedInstantActionEvent
|
||||
cooldown: 20
|
||||
cooldown: 10
|
||||
breakOnMove: false
|
||||
|
||||
- type: entity
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 5
|
||||
- type: CP14MagicEffect
|
||||
magicType: Water
|
||||
effects:
|
||||
- !type:CP14SpellProjectile
|
||||
prototype: CP14IceShard
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
- type: CP14MagicEffectManaCost
|
||||
manaCost: 10
|
||||
- type: CP14MagicEffect
|
||||
magicType: Water
|
||||
effects:
|
||||
- !type:CP14SpellSpawnEntityOnTarget
|
||||
spawns:
|
||||
|
||||
@@ -42,9 +42,6 @@
|
||||
- type: CP14NightVision #Night vision
|
||||
- type: FootstepModifier
|
||||
footstepSoundCollection: null # Silent footstep
|
||||
- type: CP14SkillStorage
|
||||
progress:
|
||||
Atlethic: 1
|
||||
- type: Inventory
|
||||
templateId: CP14Carcat # Cant wear shoes
|
||||
speciesId: carcat
|
||||
|
||||
@@ -35,9 +35,6 @@
|
||||
requiredLegs: 2
|
||||
- type: Bloodstream
|
||||
bloodReagent: CP14BloodElf
|
||||
- type: CP14SkillStorage
|
||||
progress:
|
||||
Metamagic: 1
|
||||
- type: CP14MagicEnergyContainer #Increased mana container
|
||||
maxEnergy: 200
|
||||
energy: 200
|
||||
|
||||
@@ -76,9 +76,6 @@
|
||||
#- type: CP14MagicEnergyPhotosynthesis # Silva special feature #Disabled until sunlight fixed
|
||||
#- type: CP14MagicEnergyDraw #Enabled default mana regen until sunlight fixed
|
||||
# enable: false
|
||||
- type: CP14SkillStorage
|
||||
progress:
|
||||
Healing: 1
|
||||
- type: Body
|
||||
prototype: CP14Silva
|
||||
requiredLegs: 2
|
||||
|
||||
@@ -48,9 +48,6 @@
|
||||
globalModifier: 1.2
|
||||
modifiers:
|
||||
Fire: 0.5
|
||||
- type: CP14SkillStorage
|
||||
progress:
|
||||
Pyrokinetic: 1
|
||||
- type: CP14SpellStorage
|
||||
#grantAccessToSelf: true
|
||||
#spells:
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: CP14ModularBladeSkimitarBase
|
||||
categories: [ ForkFiltered ]
|
||||
abstract: true
|
||||
description: A skimitar blade without a hilt. A blacksmith can use it as a spare part to create a weapon.
|
||||
components:
|
||||
- type: Item
|
||||
storedRotation: 45
|
||||
shape:
|
||||
- 0,0,0,1
|
||||
storedOffset: 0, 10
|
||||
|
||||
- type: entity
|
||||
parent: CP14ModularBladeSkimitarBase
|
||||
id: CP14ModularBladeIronSkimitar
|
||||
name: iron skimitar blade
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/ModularTools/Blade/Skimitar/metall_skimitar.rsi
|
||||
state: icon
|
||||
- type: CP14ModularCraftPart
|
||||
possibleParts:
|
||||
- BladeIronSkimitar
|
||||
- type: CP14Material
|
||||
materials:
|
||||
CP14Iron: 10
|
||||
|
||||
- type: entity
|
||||
parent: CP14ModularBladeSkimitarBase
|
||||
id: CP14ModularBladeGoldSkimitar
|
||||
name: golden skimitar blade
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/ModularTools/Blade/Skimitar/metall_skimitar.rsi
|
||||
layers:
|
||||
- state: icon
|
||||
color: "#ffe269"
|
||||
- type: CP14ModularCraftPart
|
||||
possibleParts:
|
||||
- BladeGoldSkimitar
|
||||
- type: CP14Material
|
||||
materials:
|
||||
CP14Gold: 10
|
||||
|
||||
- type: entity
|
||||
parent: CP14ModularBladeSkimitarBase
|
||||
id: CP14ModularBladeCopperSkimitar
|
||||
name: copper skimitar blade
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/ModularTools/Blade/Skimitar/metall_skimitar.rsi
|
||||
layers:
|
||||
- state: icon
|
||||
color: "#e28f08"
|
||||
- type: CP14ModularCraftPart
|
||||
possibleParts:
|
||||
- BladeCopperSkimitar
|
||||
- type: CP14Material
|
||||
materials:
|
||||
CP14Copper: 10
|
||||
|
||||
- type: entity
|
||||
parent: CP14ModularBladeSkimitarBase
|
||||
id: CP14ModularBladeMithrilSkimitar
|
||||
name: mithril skimitar blade
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/ModularTools/Blade/Skimitar/metall_skimitar.rsi
|
||||
layers:
|
||||
- state: icon
|
||||
color: "#38f0b3"
|
||||
- type: CP14ModularCraftPart
|
||||
possibleParts:
|
||||
- BladeMithrilSkimitar
|
||||
- type: CP14Material
|
||||
materials:
|
||||
CP14Mithril: 10
|
||||
@@ -12,6 +12,9 @@
|
||||
sprite: _CP14/Objects/Specific/Thaumaturgy/crystal.rsi
|
||||
- type: CP14MagicEnergyContainer
|
||||
- type: CP14MagicEnergyExaminable
|
||||
- type: Tag
|
||||
tags:
|
||||
- CP14EnergyCrystal
|
||||
|
||||
- type: entity
|
||||
id: CP14EnergyCrystalMedium
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
- type: entity
|
||||
parent:
|
||||
- BaseStructure
|
||||
id: CP14ResearchTable
|
||||
categories: [ ForkFiltered ]
|
||||
name: research table
|
||||
description: A place of research, experimentation and discovery that allows you to be smarter.
|
||||
components:
|
||||
- type: Sprite
|
||||
snapCardinals: true
|
||||
sprite: _CP14/Structures/Furniture/workbench.rsi
|
||||
state: research_table
|
||||
- type: Icon
|
||||
sprite: _CP14/Structures/Furniture/workbench.rsi
|
||||
state: research_table
|
||||
- type: ActivatableUI
|
||||
key: enum.CP14ResearchTableUiKey.Key
|
||||
requiresComplex: true
|
||||
singleUser: true
|
||||
- type: Climbable
|
||||
- type: Clickable
|
||||
- type: CP14ResearchTable
|
||||
- type: InteractionOutline
|
||||
- type: PlaceableSurface
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.CP14ResearchTableUiKey.Key:
|
||||
type: CP14ResearchTableBoundUserInterface
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: Wood
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTypeTrigger
|
||||
damageType: Heat
|
||||
damage: 40
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: ["Destruction"]
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
collection: WoodDestroy
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 60
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: ["Destruction"]
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
collection: WoodDestroy
|
||||
- !type:SpawnEntitiesBehavior
|
||||
spawn:
|
||||
CP14WoodenPlanks1:
|
||||
min: 1
|
||||
max: 2
|
||||
@@ -1,7 +1,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Adventurer
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14GeneralHead
|
||||
- CP14GeneralOuterClothing
|
||||
- CP14GeneralEyes
|
||||
@@ -18,7 +17,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Apprentice
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14GeneralHead
|
||||
- CP14GeneralOuterClothing
|
||||
- CP14GeneralEyes
|
||||
@@ -33,7 +31,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Alchemist
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14AlchemistHead #
|
||||
- CP14GeneralOuterClothing
|
||||
- CP14AlchemistEyes #
|
||||
@@ -49,7 +46,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Innkeeper
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14GeneralHead
|
||||
- CP14GeneralOuterClothing
|
||||
- CP14GeneralEyes
|
||||
@@ -64,7 +60,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Blacksmith
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14GeneralHead
|
||||
- CP14GeneralOuterClothing
|
||||
- CP14GeneralEyes
|
||||
@@ -79,7 +74,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14GuardCommander
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14GuardHead
|
||||
- CP14GeneralOuterClothing
|
||||
- CP14GeneralEyes
|
||||
@@ -95,7 +89,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Guard
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14GuardHead
|
||||
- CP14GeneralOuterClothing
|
||||
- CP14GeneralEyes
|
||||
@@ -111,7 +104,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Commandant
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14MerchantOuterClothing
|
||||
- CP14GeneralEyes
|
||||
- CP14MerchantShirt
|
||||
@@ -123,7 +115,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Guildmaster
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14GuildmasterOuterClothing
|
||||
- CP14GeneralEyes
|
||||
- CP14GuildmasterHead
|
||||
@@ -138,7 +129,6 @@
|
||||
- type: roleLoadout
|
||||
id: JobCP14Merchant
|
||||
groups:
|
||||
- CP14SkillTree
|
||||
- CP14MerchantHead
|
||||
- CP14MerchantOuterClothing
|
||||
- CP14GeneralEyes
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
- type: loadoutGroup
|
||||
id: CP14SkillTree
|
||||
name: cp14-loadout-skill-tree
|
||||
minLimit: 2
|
||||
maxLimit: 2
|
||||
loadouts:
|
||||
- CP14SkillTreeMetamagic
|
||||
- CP14SkillTreeHydrosophistry
|
||||
- CP14SkillTreePyrokinetic
|
||||
- CP14SkillTreeIllusion
|
||||
- CP14SkillTreeHealing
|
||||
- CP14SkillTreeAtlethic
|
||||
#- CP14SkillTreeDimension Disabled until teleport & grab collider fix
|
||||
|
||||
- type: entity
|
||||
id: CP14SkillTreePyrokineticLoadoutDummy
|
||||
name: Pyrokinetic
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/skill_tree.rsi
|
||||
state: pyro
|
||||
|
||||
- type: loadout
|
||||
id: CP14SkillTreePyrokinetic
|
||||
dummyEntity: CP14SkillTreePyrokineticLoadoutDummy
|
||||
skillTree:
|
||||
Pyrokinetic: 2
|
||||
|
||||
- type: entity
|
||||
id: CP14SkillTreeHydrosophistryLoadoutDummy
|
||||
name: Hydrosophistry
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/skill_tree.rsi
|
||||
state: water
|
||||
|
||||
- type: loadout
|
||||
id: CP14SkillTreeHydrosophistry
|
||||
dummyEntity: CP14SkillTreeHydrosophistryLoadoutDummy
|
||||
skillTree:
|
||||
Hydrosophistry: 2
|
||||
|
||||
- type: entity
|
||||
id: CP14SkillTreeIllusionLoadoutDummy
|
||||
name: Illusion
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/skill_tree.rsi
|
||||
state: light
|
||||
|
||||
- type: loadout
|
||||
id: CP14SkillTreeIllusion
|
||||
dummyEntity: CP14SkillTreeIllusionLoadoutDummy
|
||||
skillTree:
|
||||
Illusion: 2
|
||||
|
||||
- type: entity
|
||||
id: CP14SkillTreeMetamagicLoadoutDummy
|
||||
name: Metamagic
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/skill_tree.rsi
|
||||
state: meta
|
||||
|
||||
- type: loadout
|
||||
id: CP14SkillTreeMetamagic
|
||||
dummyEntity: CP14SkillTreeMetamagicLoadoutDummy
|
||||
skillTree:
|
||||
Metamagic: 2
|
||||
|
||||
- type: entity
|
||||
id: CP14SkillTreeHealingLoadoutDummy
|
||||
name: Healing
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/skill_tree.rsi
|
||||
state: heal
|
||||
|
||||
- type: loadout
|
||||
id: CP14SkillTreeHealing
|
||||
dummyEntity: CP14SkillTreeHealingLoadoutDummy
|
||||
skillTree:
|
||||
Healing: 2
|
||||
|
||||
- type: entity
|
||||
id: CP14SkillTreeAtlethicLoadoutDummy
|
||||
name: Atlethic
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/skill_tree.rsi
|
||||
state: atlethic
|
||||
|
||||
- type: loadout
|
||||
id: CP14SkillTreeAtlethic
|
||||
dummyEntity: CP14SkillTreeAtlethicLoadoutDummy
|
||||
skillTree:
|
||||
Atlethic: 2
|
||||
|
||||
- type: entity
|
||||
id: CP14SkillTreeDimensionLoadoutDummy
|
||||
name: Dimension
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _CP14/Actions/skill_tree.rsi
|
||||
state: dimension
|
||||
|
||||
- type: loadout
|
||||
id: CP14SkillTreeDimension
|
||||
dummyEntity: CP14SkillTreeDimensionLoadoutDummy
|
||||
skillTree:
|
||||
Dimension: 2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user