Skill progression system [Draft] (#1056)
* fuck all * clean up * remove knowledge books * Update base.yml * cl * fix #991 * fix * Update subgamemodes.yml * manual migration + recipes fix * Update comoss.yml * setup data * setup skills systems * more blacksmithing skills * Update base.yml * Create CP14SkillEffectAction.cs * skill button returns * base graph UI window * skill tree drawing * UI improve * pyro setup * skill trees selection, dragging control * refactor skill system: rename Skills to LearnedSkills, add experience tracking and learning logic * Create available.png * skill description generation setup * auto parsing skill names and descriptions * Hydrosophistry * water light fire and metamagic ported to skill tre * ice dagger spell returns * Update ice_dagger.yml * delete old files * Update modular_garde.yml * ice arrow spell * link graph with parallax * show experience counter * polish * puf * p * pipap * finally ready to merg? * fix * fix 2
This commit is contained in:
@@ -118,7 +118,7 @@ namespace Content.Shared.Input
|
||||
public static readonly BoundKeyFunction MappingOpenContextMenu = "MappingOpenContextMenu";
|
||||
|
||||
//CP14 keys
|
||||
public static readonly BoundKeyFunction CP14OpenKnowledgeMenu = "CP14OpenKnowledgeMenu";
|
||||
public static readonly BoundKeyFunction CP14OpenSkillMenu = "CP14OpenSkillMenu";
|
||||
//CP14 keys end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Preferences.Loadouts.Effects;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -50,4 +52,10 @@ public sealed partial class LoadoutPrototype : IPrototype, IEquipmentLoadout
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<EntProtoId> Actions { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// CP14 - it is possible to give skill trees to players who have taken this loadout
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<CP14SkillTreePrototype>, FixedPoint2> SkillTree = new();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Shared._CP14.Skill;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
@@ -25,6 +26,7 @@ public abstract class SharedStationSpawningSystem : EntitySystem
|
||||
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _action = default!; //CP14
|
||||
[Dependency] private readonly CP14SharedSkillSystem _skill = default!; //CP14
|
||||
|
||||
private EntityQuery<HandsComponent> _handsQuery;
|
||||
private EntityQuery<InventoryComponent> _inventoryQuery;
|
||||
@@ -90,7 +92,7 @@ public abstract class SharedStationSpawningSystem : EntitySystem
|
||||
{
|
||||
EquipStartingGear(entity, loadout.StartingGear, raiseEvent);
|
||||
EquipStartingGear(entity, (IEquipmentLoadout) loadout, raiseEvent);
|
||||
CP14EquipStartingActions(entity, loadout);
|
||||
CP14EquipStartingActions(entity, loadout); //CP14
|
||||
}
|
||||
|
||||
private void CP14EquipStartingActions(EntityUid entity, LoadoutPrototype loadout)
|
||||
@@ -99,6 +101,11 @@ public abstract class SharedStationSpawningSystem : EntitySystem
|
||||
{
|
||||
_action.AddAction(entity, action);
|
||||
}
|
||||
|
||||
foreach (var tree in loadout.SkillTree)
|
||||
{
|
||||
_skill.TryAddExperience(entity, tree.Key, tree.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -96,10 +96,10 @@ namespace Content.Shared.Verbs
|
||||
|
||||
public static readonly VerbCategory CP14CurrencyConvert = new("cp14-verb-categories-currency-converter", null); //CP14
|
||||
|
||||
public static readonly VerbCategory CP14KnowledgeAdd = new("cp14-verb-categories-knowledge-add", null); //CP14
|
||||
public static readonly VerbCategory CP14AdminSkillAdd =
|
||||
new ("cp14-verb-categories-admin-skill-add", null, iconsOnly: true) { Columns = 6 }; //CP14
|
||||
|
||||
public static readonly VerbCategory CP14KnowledgeRemove = new("cp14-verb-categories-knowledge-remove", null); //CP14
|
||||
|
||||
public static readonly VerbCategory CP14KnowledgeLearn = new("cp14-verb-categories-knowledge-learn", null); //CP14
|
||||
public static readonly VerbCategory CP14AdminSkillRemove =
|
||||
new ("cp14-verb-categories-admin-skill-remove", null, iconsOnly: true) { Columns = 6 }; //CP14
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared.Paper;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge;
|
||||
|
||||
public sealed class CP14KnowledgePaperTextSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly PaperSystem _paper = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<CP14KnowledgePaperTextComponent, MapInitEvent>(OnPaperMapInit);
|
||||
}
|
||||
|
||||
private void OnPaperMapInit(Entity<CP14KnowledgePaperTextComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
if (!TryComp<PaperComponent>(ent, out var paperComponent))
|
||||
return;
|
||||
|
||||
var paper = new Entity<PaperComponent>(ent, paperComponent);
|
||||
|
||||
if (!TryComp<CP14KnowledgeLearningSourceComponent>(ent, out var knowledge))
|
||||
return;
|
||||
|
||||
if (knowledge.Knowledge.Count == 0)
|
||||
return;
|
||||
|
||||
var content = GenerateText(knowledge);
|
||||
|
||||
_paper.SetContent(paper, content);
|
||||
paper.Comp.EditingDisabled = true;
|
||||
|
||||
// Yes we need to do synchronization after such changes,
|
||||
// yes predict, but we need to
|
||||
Dirty(paper);
|
||||
}
|
||||
|
||||
private string GenerateText(CP14KnowledgeLearningSourceComponent source)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
|
||||
// Header
|
||||
stringBuilder.Append(Loc.GetString("cp14-knowledge-book-pre-text"));
|
||||
|
||||
// Main body
|
||||
foreach (var prototypeId in source.Knowledge)
|
||||
{
|
||||
if (!_prototype.TryIndex(prototypeId, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
stringBuilder.Append($"\n{Loc.GetString(indexedKnowledge.Desc)}");
|
||||
}
|
||||
|
||||
// Footer
|
||||
stringBuilder.Append($"\n\n{Loc.GetString("cp14-knowledge-book-post-text")}");
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class CP14AllKnowingComponent : Component;
|
||||
@@ -1,15 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// The ability to add a <see cref="CP14KnowledgePrototype"/> to an entity
|
||||
/// and quickly teach it some skills.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14AutoAddKnowledgeComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public List<ProtoId<CP14KnowledgePrototype>> Knowledge = [];
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows new knowledge to be learnt through interactions with an object.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14KnowledgeLearningSourceComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Knowledge { get; private set; } = [];
|
||||
|
||||
[DataField]
|
||||
public TimeSpan DoAfter = TimeSpan.FromSeconds(5f);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Automatically generates content for PaperComponent,
|
||||
/// based on the knowledge that can be learnt from this object.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14KnowledgePaperTextComponent : Component;
|
||||
@@ -1,14 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// A list of <see cref="CP14KnowledgePrototype"/> learned by this entity.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14KnowledgeStorageComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Knowledge { get; private set; } = [];
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14KnowledgeInfoEvent : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity NetEntity;
|
||||
public readonly HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledge;
|
||||
|
||||
public CP14KnowledgeInfoEvent(NetEntity netEntity, HashSet<ProtoId<CP14KnowledgePrototype>> allKnowledge)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
AllKnowledge = allKnowledge;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class CP14KnowledgeLearnDoAfterEvent : DoAfterEvent
|
||||
{
|
||||
public ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
|
||||
public override DoAfterEvent Clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
public sealed class CP14KnowledgeUsedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid User;
|
||||
public readonly ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
public readonly float Factor;
|
||||
|
||||
public CP14KnowledgeUsedEvent(EntityUid uid, ProtoId<CP14KnowledgePrototype> knowledge, float factor)
|
||||
{
|
||||
User = uid;
|
||||
Knowledge = knowledge;
|
||||
Factor = factor;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Events;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14RequestKnowledgeInfoEvent : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity NetEntity;
|
||||
|
||||
public CP14RequestKnowledgeInfoEvent(NetEntity netEntity)
|
||||
{
|
||||
NetEntity = netEntity;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Prototypes;
|
||||
|
||||
/// <summary>
|
||||
/// Abstract knowledge that may be required to use items or crafts.
|
||||
/// </summary>
|
||||
[Prototype("CP14Knowledge")]
|
||||
public sealed partial class CP14KnowledgePrototype : IPrototype
|
||||
{
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name { get; private set; }
|
||||
|
||||
[DataField]
|
||||
public LocId Desc { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// To study this knowledge, other knowledge on which it is based may be necessary.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Dependencies = [];
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared._CP14.Knowledge.Events;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge;
|
||||
|
||||
public abstract class SharedCP14KnowledgeSystem : EntitySystem
|
||||
{
|
||||
public bool HasKnowledge(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> knowledge)
|
||||
{
|
||||
if (HasComp<CP14AllKnowingComponent>(entity))
|
||||
return true;
|
||||
|
||||
return Resolve(entity, ref entity.Comp, false) && entity.Comp.Knowledge.Contains(knowledge);
|
||||
}
|
||||
|
||||
public bool TryUseKnowledge(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> knowledge, float factor = 1f)
|
||||
{
|
||||
if (!Resolve(entity, ref entity.Comp, false))
|
||||
return false;
|
||||
|
||||
if (!entity.Comp.Knowledge.Contains(knowledge))
|
||||
return false;
|
||||
|
||||
var ev = new CP14KnowledgeUsedEvent(entity, knowledge, factor);
|
||||
RaiseLocalEvent(entity, ev);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
230
Content.Shared/_CP14/Skill/CP14SharedSkillSystem.cs
Normal file
230
Content.Shared/_CP14/Skill/CP14SharedSkillSystem.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill;
|
||||
|
||||
public abstract partial class CP14SharedSkillSystem : EntitySystem
|
||||
{
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
InitializeAdmin();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Directly adds the skill to the player, bypassing any checks.
|
||||
/// </summary>
|
||||
public bool TryAddSkill(EntityUid target,
|
||||
ProtoId<CP14SkillPrototype> skill,
|
||||
CP14SkillStorageComponent? component = null)
|
||||
{
|
||||
if (!Resolve(target, ref component, false))
|
||||
return false;
|
||||
|
||||
if (component.LearnedSkills.Contains(skill))
|
||||
return false;
|
||||
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return false;
|
||||
|
||||
if (indexedSkill.Effect is not null)
|
||||
{
|
||||
indexedSkill.Effect.AddSkill(EntityManager, target);
|
||||
}
|
||||
|
||||
component.SkillsSumExperience += indexedSkill.LearnCost;
|
||||
|
||||
component.LearnedSkills.Add(skill);
|
||||
Dirty(target, component);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the skill from the player, bypassing any checks.
|
||||
/// </summary>
|
||||
public bool TryRemoveSkill(EntityUid target,
|
||||
ProtoId<CP14SkillPrototype> skill,
|
||||
CP14SkillStorageComponent? component = null)
|
||||
{
|
||||
if (!Resolve(target, ref component, false))
|
||||
return false;
|
||||
|
||||
if (!component.LearnedSkills.Remove(skill))
|
||||
return false;
|
||||
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return false;
|
||||
|
||||
if (indexedSkill.Effect is not null)
|
||||
{
|
||||
indexedSkill.Effect.RemoveSkill(EntityManager, target);
|
||||
}
|
||||
|
||||
component.SkillsSumExperience -= indexedSkill.LearnCost;
|
||||
|
||||
Dirty(target, component);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the player has the skill.
|
||||
/// </summary>
|
||||
public bool HaveSkill(EntityUid target,
|
||||
ProtoId<CP14SkillPrototype> skill,
|
||||
CP14SkillStorageComponent? component = null)
|
||||
{
|
||||
if (!Resolve(target, ref component, false))
|
||||
return false;
|
||||
|
||||
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>
|
||||
public bool CanLearnSkill(EntityUid target,
|
||||
ProtoId<CP14SkillPrototype> skill,
|
||||
CP14SkillStorageComponent? component = null)
|
||||
{
|
||||
if (!Resolve(target, ref component, false))
|
||||
return false;
|
||||
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return false;
|
||||
|
||||
//Already learned
|
||||
if (HaveSkill(target, skill, component))
|
||||
return false;
|
||||
|
||||
//Check max cap
|
||||
if (component.SkillsSumExperience + indexedSkill.LearnCost >= component.ExperienceMaxCap)
|
||||
return false;
|
||||
|
||||
//Prerequisite check
|
||||
foreach (var prerequisite in indexedSkill.Prerequisites)
|
||||
{
|
||||
if (!HaveSkill(target, prerequisite, component))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Experience check
|
||||
if (!component.Progress.TryGetValue(indexedSkill.Tree, out var currentExp))
|
||||
return false;
|
||||
if (currentExp < indexedSkill.LearnCost)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to learn the specified skill for the player.
|
||||
/// </summary>
|
||||
public bool TryLearnSkill(EntityUid target,
|
||||
ProtoId<CP14SkillPrototype> skill,
|
||||
CP14SkillStorageComponent? component = null)
|
||||
{
|
||||
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;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to get the skill name for a given skill prototype.
|
||||
/// </summary>
|
||||
public string GetSkillName(ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return string.Empty;
|
||||
|
||||
if (indexedSkill.Name != null)
|
||||
return Loc.GetString(indexedSkill.Name);
|
||||
|
||||
if (indexedSkill.Effect != null)
|
||||
return indexedSkill.Effect.GetName(EntityManager, _proto) ?? string.Empty;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to get the skill description for a given skill prototype.
|
||||
/// </summary>
|
||||
public string GetSkillDescription(ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
return string.Empty;
|
||||
|
||||
if (indexedSkill.Desc != null)
|
||||
return Loc.GetString(indexedSkill.Desc);
|
||||
|
||||
if (indexedSkill.Effect != null)
|
||||
return indexedSkill.Effect.GetDescription(EntityManager, _proto) ?? string.Empty;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
67
Content.Shared/_CP14/Skill/CP14SkillSystem.Admin.cs
Normal file
67
Content.Shared/_CP14/Skill/CP14SkillSystem.Admin.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill;
|
||||
|
||||
public abstract partial class CP14SharedSkillSystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminManager _admin = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
private void InitializeAdmin()
|
||||
{
|
||||
SubscribeLocalEvent<CP14SkillStorageComponent, GetVerbsEvent<Verb>>(OnGetAdminVerbs);
|
||||
}
|
||||
|
||||
private void OnGetAdminVerbs(Entity<CP14SkillStorageComponent> ent, ref GetVerbsEvent<Verb> args)
|
||||
{
|
||||
if (!_admin.HasAdminFlag(args.User, AdminFlags.Admin))
|
||||
return;
|
||||
|
||||
|
||||
var target = args.Target;
|
||||
|
||||
//Add Skill
|
||||
foreach (var skill in _proto.EnumeratePrototypes<CP14SkillPrototype>())
|
||||
{
|
||||
if (ent.Comp.LearnedSkills.Contains(skill))
|
||||
continue;
|
||||
|
||||
var name = Loc.GetString(GetSkillName(skill));
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = name,
|
||||
Message = name + ": " + Loc.GetString(GetSkillDescription(skill)),
|
||||
Category = VerbCategory.CP14AdminSkillAdd,
|
||||
Icon = skill.Icon,
|
||||
Act = () =>
|
||||
{
|
||||
TryAddSkill(target, skill);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
//Remove Skill
|
||||
foreach (var skill in ent.Comp.LearnedSkills)
|
||||
{
|
||||
if (!_proto.TryIndex(skill, out var indexedSkill))
|
||||
continue;
|
||||
|
||||
var name = Loc.GetString(GetSkillName(skill));
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = name,
|
||||
Message = name + ": " + Loc.GetString(GetSkillDescription(skill)),
|
||||
Category = VerbCategory.CP14AdminSkillRemove,
|
||||
Icon = indexedSkill.Icon,
|
||||
Act = () =>
|
||||
{
|
||||
TryRemoveSkill(target, skill);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Content.Shared/_CP14/Skill/CP14SkillSystem.Learning.cs
Normal file
48
Content.Shared/_CP14/Skill/CP14SkillSystem.Learning.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
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,46 @@
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
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 CP14SkillStorageComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public List<ProtoId<CP14SkillPrototype>> LearnedSkills = 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a player attempts to learn a skill. This is sent from the client to the server.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CP14TryLearnSkillMessage(NetEntity entity, ProtoId<CP14SkillPrototype> skill) : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity Entity = entity;
|
||||
public readonly ProtoId<CP14SkillPrototype> Skill = skill;
|
||||
}
|
||||
64
Content.Shared/_CP14/Skill/Prototypes/CP14SkillPrototype.cs
Normal file
64
Content.Shared/_CP14/Skill/Prototypes/CP14SkillPrototype.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared._CP14.Skill.Specials;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Prototypes;
|
||||
|
||||
/// <summary>
|
||||
/// A skill that can be learned by the player. Skills are grouped into trees, and each skill has a cost to learn, prerequisites, and an effect.
|
||||
/// </summary>
|
||||
[Prototype("cp14Skill")]
|
||||
public sealed partial class CP14SkillPrototype : IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Skill Title. If you leave null, the name will try to generate from Effect.GetName()
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? Name;
|
||||
|
||||
/// <summary>
|
||||
/// Skill Description. If you leave null, the description will try to generate from Effect.GetDescription()
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? Desc;
|
||||
|
||||
/// <summary>
|
||||
/// The tree this skill belongs to. This is used to group skills together in the UI.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ProtoId<CP14SkillTreePrototype> Tree = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The cost to learn this skill. This is used to determine how many progress points are needed to learn the skill.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float LearnCost = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Prerequisites for this skill. This is used to determine if the player can learn the skill. If the player does not have all the prerequisites, they cannot learn the skill.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14SkillPrototype>> Prerequisites = new();
|
||||
|
||||
/// <summary>
|
||||
/// Skill UI position. This is used to determine where the skill will be displayed in the skill tree UI.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public Vector2 SkillUiPosition = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Icon for the skill. This is used to display the skill in the skill tree UI.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public SpriteSpecifier Icon = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Skill effect. This is used to determine what happens when the player learns the skill. If you leave null, the skill will not have any effect.
|
||||
/// But the presence of the skill itself can affect some systems that check for the presence of certain skills.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public CP14SkillEffect? Effect;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Prototypes;
|
||||
|
||||
/// <summary>
|
||||
/// A group of skills combined into one “branch”
|
||||
/// </summary>
|
||||
[Prototype("cp14SkillTree")]
|
||||
public sealed partial class CP14SkillTreePrototype : IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name;
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier FrameIcon = new SpriteSpecifier.Rsi(new ResPath("/Textures/_CP14/Interface/Skills/default.rsi"), "frame");
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier HoveredIcon = new SpriteSpecifier.Rsi(new ResPath("/Textures/_CP14/Interface/Skills/default.rsi"), "hovered");
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier SelectedIcon = new SpriteSpecifier.Rsi(new ResPath("/Textures/_CP14/Interface/Skills/default.rsi"), "selected");
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier LearnedIcon = new SpriteSpecifier.Rsi(new ResPath("/Textures/_CP14/Interface/Skills/default.rsi"), "learned");
|
||||
|
||||
[DataField]
|
||||
public SpriteSpecifier AvailableIcon = new SpriteSpecifier.Rsi(new ResPath("/Textures/_CP14/Interface/Skills/default.rsi"), "available");
|
||||
|
||||
[DataField]
|
||||
public string Parallax = "AspidParallax";
|
||||
|
||||
[DataField]
|
||||
public LocId? Desc;
|
||||
|
||||
[DataField]
|
||||
public Color Color;
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier LearnSound = new SoundCollectionSpecifier("CP14LearnSkill");
|
||||
}
|
||||
52
Content.Shared/_CP14/Skill/Specials/AddAction.cs
Normal file
52
Content.Shared/_CP14/Skill/Specials/AddAction.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Specials;
|
||||
|
||||
public sealed partial class AddAction : CP14SkillEffect
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public EntProtoId Action;
|
||||
|
||||
public override void AddSkill(EntityManager entManager, EntityUid target)
|
||||
{
|
||||
var actionsSystem = entManager.System<SharedActionsSystem>();
|
||||
|
||||
actionsSystem.AddAction(target, Action);
|
||||
}
|
||||
|
||||
public override void RemoveSkill(EntityManager entManager, EntityUid target)
|
||||
{
|
||||
var actionsSystem = entManager.System<SharedActionsSystem>();
|
||||
|
||||
foreach (var (uid, _) in actionsSystem.GetActions(target))
|
||||
{
|
||||
if (!entManager.TryGetComponent<MetaDataComponent>(uid, out var metaData))
|
||||
continue;
|
||||
|
||||
if (metaData.EntityPrototype == null)
|
||||
continue;
|
||||
|
||||
if (metaData.EntityPrototype != Action)
|
||||
continue;
|
||||
|
||||
actionsSystem.RemoveAction(target, uid);
|
||||
}
|
||||
}
|
||||
|
||||
public override string? GetName(EntityManager entMagager, IPrototypeManager protoManager)
|
||||
{
|
||||
if (!protoManager.TryIndex(Action, out var indexedAction))
|
||||
return String.Empty;
|
||||
|
||||
return indexedAction.Name;
|
||||
}
|
||||
|
||||
public override string? GetDescription(EntityManager entMagager, IPrototypeManager protoManager)
|
||||
{
|
||||
if (!protoManager.TryIndex(Action, out var indexedAction))
|
||||
return String.Empty;
|
||||
|
||||
return indexedAction.Description;
|
||||
}
|
||||
}
|
||||
17
Content.Shared/_CP14/Skill/Specials/CP14SkillEffect.cs
Normal file
17
Content.Shared/_CP14/Skill/Specials/CP14SkillEffect.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skill.Specials;
|
||||
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class CP14SkillEffect
|
||||
{
|
||||
public abstract void AddSkill(EntityManager entManager, EntityUid target);
|
||||
|
||||
public abstract void RemoveSkill(EntityManager entManager, EntityUid target);
|
||||
|
||||
public abstract string? GetName(EntityManager entMagager, IPrototypeManager protoManager);
|
||||
|
||||
public abstract string? GetDescription(EntityManager entMagager, IPrototypeManager protoManager);
|
||||
}
|
||||
@@ -1,39 +1,46 @@
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared._CP14.Skill;
|
||||
using Content.Shared._CP14.Skill.Prototypes;
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._CP14.Workbench.Requirements;
|
||||
|
||||
public sealed partial class KnowledgeRequired : CP14WorkbenchCraftRequirement
|
||||
public sealed partial class SkillRequired : CP14WorkbenchCraftRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// If the player does not have this knowledge, the recipe will not be displayed in the workbench.
|
||||
/// </summary>
|
||||
public override bool HideRecipe { get; set; } = true;
|
||||
|
||||
[DataField(required: true)]
|
||||
public ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
public List<ProtoId<CP14SkillPrototype>> Skills = new();
|
||||
|
||||
public override bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user)
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
{
|
||||
var knowledgeSystem = entManager.System<SharedCP14KnowledgeSystem>();
|
||||
var knowledgeSystem = entManager.System<CP14SharedSkillSystem>();
|
||||
|
||||
return knowledgeSystem.HasKnowledge(user, Knowledge);
|
||||
var haveAllSkills = true;
|
||||
foreach (var skill in Skills)
|
||||
{
|
||||
if (!knowledgeSystem.HaveSkill(user, skill))
|
||||
{
|
||||
haveAllSkills = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return haveAllSkills;
|
||||
}
|
||||
|
||||
public override void PostCraft(EntityManager entManager, HashSet<EntityUid> placedEntities, EntityUid user)
|
||||
{
|
||||
var knowledgeSystem = entManager.System<SharedCP14KnowledgeSystem>();
|
||||
knowledgeSystem.TryUseKnowledge(user, Knowledge);
|
||||
}
|
||||
|
||||
public override string GetRequirementTitle(IPrototypeManager protoManager)
|
||||
{
|
||||
return !protoManager.TryIndex(Knowledge, out var indexedKnowledge)
|
||||
? "Error knowledge"
|
||||
: $"{Loc.GetString("cp14-knowledge")}: {Loc.GetString(indexedKnowledge.Name)}";
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public override EntityPrototype? GetRequirementEntityView(IPrototypeManager protoManager)
|
||||
@@ -41,8 +48,8 @@ public sealed partial class KnowledgeRequired : CP14WorkbenchCraftRequirement
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SpriteSpecifier GetRequirementTexture(IPrototypeManager protoManager)
|
||||
public override SpriteSpecifier? GetRequirementTexture(IPrototypeManager protoManager)
|
||||
{
|
||||
return new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/students-cap.svg.192dpi.png"));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Material;
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -13,13 +14,20 @@ namespace Content.Shared._CP14.Workbench.Requirements;
|
||||
|
||||
public sealed partial class MaterialResource : CP14WorkbenchCraftRequirement
|
||||
{
|
||||
public override bool HideRecipe { get; set; } = false;
|
||||
|
||||
[DataField(required: true)]
|
||||
public ProtoId<MaterialPrototype> Material;
|
||||
|
||||
[DataField]
|
||||
public int Count = 1;
|
||||
|
||||
public override bool CheckRequirement(EntityManager entManager, IPrototypeManager protoManager, HashSet<EntityUid> placedEntities, EntityUid user)
|
||||
public override bool CheckRequirement(
|
||||
EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var ent in placedEntities)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* https://github.com/space-wizards/space-station-14/blob/master/LICENSE.TXT
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -10,6 +11,8 @@ namespace Content.Shared._CP14.Workbench.Requirements;
|
||||
|
||||
public sealed partial class ProtoIdResource : CP14WorkbenchCraftRequirement
|
||||
{
|
||||
public override bool HideRecipe { get; set; } = false;
|
||||
|
||||
[DataField(required: true)]
|
||||
public EntProtoId ProtoId;
|
||||
|
||||
@@ -19,7 +22,8 @@ public sealed partial class ProtoIdResource : CP14WorkbenchCraftRequirement
|
||||
public override bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user)
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
{
|
||||
var indexedIngredients = IndexIngredients(entManager, placedEntities);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* https://github.com/space-wizards/space-station-14/blob/master/LICENSE.TXT
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -11,6 +12,8 @@ namespace Content.Shared._CP14.Workbench.Requirements;
|
||||
|
||||
public sealed partial class StackResource : CP14WorkbenchCraftRequirement
|
||||
{
|
||||
public override bool HideRecipe { get; set; } = false;
|
||||
|
||||
[DataField(required: true)]
|
||||
public ProtoId<StackPrototype> Stack;
|
||||
|
||||
@@ -20,7 +23,8 @@ public sealed partial class StackResource : CP14WorkbenchCraftRequirement
|
||||
public override bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user)
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var ent in placedEntities)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* https://github.com/space-wizards/space-station-14/blob/master/LICENSE.TXT
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -11,6 +12,8 @@ namespace Content.Shared._CP14.Workbench.Requirements;
|
||||
|
||||
public sealed partial class TagResource : CP14WorkbenchCraftRequirement
|
||||
{
|
||||
public override bool HideRecipe { get; set; } = false;
|
||||
|
||||
[DataField(required: true)]
|
||||
public ProtoId<TagPrototype> Tag;
|
||||
|
||||
@@ -23,7 +26,12 @@ public sealed partial class TagResource : CP14WorkbenchCraftRequirement
|
||||
[DataField(required: true)]
|
||||
public SpriteSpecifier? Texture;
|
||||
|
||||
public override bool CheckRequirement(EntityManager entManager, IPrototypeManager protoManager, HashSet<EntityUid> placedEntities, EntityUid user)
|
||||
public override bool CheckRequirement(
|
||||
EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe)
|
||||
{
|
||||
var tagSystem = entManager.System<TagSystem>();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* https://github.com/space-wizards/space-station-14/blob/master/LICENSE.TXT
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -13,6 +14,11 @@ namespace Content.Shared._CP14.Workbench;
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class CP14WorkbenchCraftRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, failure to fulfill this condition will hide recipes from the possible craft workbench menu
|
||||
/// </summary>
|
||||
public abstract bool HideRecipe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Here a check is made that the recipe as a whole can be fulfilled at the current moment. Do not add anything that affects gameplay here, and only perform checks here.
|
||||
/// </summary>
|
||||
@@ -20,7 +26,8 @@ public abstract partial class CP14WorkbenchCraftRequirement
|
||||
public abstract bool CheckRequirement(EntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HashSet<EntityUid> placedEntities,
|
||||
EntityUid user);
|
||||
EntityUid user,
|
||||
CP14WorkbenchRecipePrototype recipe);
|
||||
|
||||
/// <summary>
|
||||
/// An event that is triggered after crafting. This is the place to put important things like removing items, spending stacks or other things.
|
||||
|
||||
Reference in New Issue
Block a user