Knowledge system (#770)
* remove all requirements * clean up and renaming to knowledge * update code * add admin knowledge verbs * move shoes under pants * knowledge based recipes * clean up * sewing knowledges * knowledge dependencies * knowledge learning objects * more knowledge * metallforging skill * knowledge books * start knowledges, T1 and T2 books in demiplanes * remove coins from demiplanes * roundstart knowledge
This commit is contained in:
@@ -95,5 +95,11 @@ namespace Content.Shared.Verbs
|
||||
public static readonly VerbCategory CP14RitualBook = new("cp14-verb-categories-ritual-book", null); //CP14
|
||||
|
||||
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 CP14KnowledgeRemove = new("cp14-verb-categories-knowledge-remove", null); //CP14
|
||||
|
||||
public static readonly VerbCategory CP14KnowledgeLearn = new("cp14-verb-categories-knowledge-learn", null); //CP14
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// The ability to add a skill 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 = new();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
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>> Knowledges { get; private set; } = new();
|
||||
|
||||
[DataField]
|
||||
public TimeSpan DoAfter = TimeSpan.FromSeconds(5f);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
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
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge.Components;
|
||||
|
||||
/// <summary>
|
||||
/// a list of skills learned by this entity
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14KnowledgeSystem))]
|
||||
public sealed partial class CP14KnowledgeStorageComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Knowledges { get; private set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
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
|
||||
{
|
||||
[ViewVariables]
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId Name { get; private set; } = default!;
|
||||
|
||||
[DataField]
|
||||
public LocId Desc{ get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// to study this knowledge, other knowledge on which it is based may be necessary.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CP14KnowledgePrototype>> Dependencies = new();
|
||||
}
|
||||
94
Content.Shared/_CP14/Knowledge/SharedCP14KnowledgeSystem.cs
Normal file
94
Content.Shared/_CP14/Knowledge/SharedCP14KnowledgeSystem.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using System.Text;
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.MagicMirror;
|
||||
using Content.Shared.Paper;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._CP14.Knowledge;
|
||||
|
||||
public abstract partial class SharedCP14KnowledgeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = 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 paper))
|
||||
return;
|
||||
if (!TryComp<CP14KnowledgeLearningSourceComponent>(ent, out var knowledge))
|
||||
return;
|
||||
if (knowledge.Knowledges.Count <= 0)
|
||||
return;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append(Loc.GetString("cp14-knowledge-book-pre-text"));
|
||||
foreach (var k in knowledge.Knowledges)
|
||||
{
|
||||
if (!_proto.TryIndex(k, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
sb.Append($"\n{Loc.GetString(indexedKnowledge.Desc)}");
|
||||
}
|
||||
|
||||
sb.Append($"\n\n{Loc.GetString("cp14-knowledge-book-post-text")}");
|
||||
|
||||
_paper.SetContent((ent, paper), sb.ToString());
|
||||
paper.EditingDisabled = true;
|
||||
}
|
||||
|
||||
public bool UseKnowledge(EntityUid uid,
|
||||
ProtoId<CP14KnowledgePrototype> knowledge,
|
||||
float factor = 1f,
|
||||
CP14KnowledgeStorageComponent? knowledgeStorage = null)
|
||||
{
|
||||
if (!Resolve(uid, ref knowledgeStorage, false))
|
||||
return false;
|
||||
|
||||
if (!knowledgeStorage.Knowledges.Contains(knowledge))
|
||||
return false;
|
||||
|
||||
var ev = new CP14KnowledgeUsedEvent(uid, knowledge, factor);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool HasKnowledge(EntityUid uid,
|
||||
ProtoId<CP14KnowledgePrototype> knowledge,
|
||||
CP14KnowledgeStorageComponent? knowledgeStorage = null)
|
||||
{
|
||||
if (!Resolve(uid, ref knowledgeStorage, false))
|
||||
return false;
|
||||
|
||||
return knowledgeStorage.Knowledges.Contains(knowledge);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class CP14KnowledgeLearnDoAfterEvent : DoAfterEvent
|
||||
{
|
||||
public ProtoId<CP14KnowledgePrototype> Knowledge;
|
||||
public override DoAfterEvent Clone() => this;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using Content.Shared._CP14.Skills.Prototypes;
|
||||
using Content.Shared.Roles;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skills.Components;
|
||||
|
||||
/// <summary>
|
||||
/// a component that can be hung on an entity to immediately teach it some skills
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed partial class CP14AddSkillSpecial : JobSpecial
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public List<ProtoId<CP14SkillPrototype>> Skills = new();
|
||||
|
||||
public override void AfterEquip(EntityUid mob)
|
||||
{
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
var skillSystem = entMan.System<SharedCP14SkillSystem>();
|
||||
foreach (var skill in Skills)
|
||||
{
|
||||
skillSystem.TryLearnSkill(mob, skill);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Content.Shared._CP14.Skills.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skills.Components;
|
||||
|
||||
/// <summary>
|
||||
/// The ability to add a skill to an entity and quickly teach it some skills
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14SkillSystem))]
|
||||
public sealed partial class CP14AutoAddSkillComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public List<ProtoId<CP14SkillPrototype>> Skills = new();
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using Content.Shared._CP14.Skills.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skills.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Limits the use of this entity behind certain skills
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14SkillSystem))]
|
||||
public sealed partial class CP14SkillRequirementComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Is it necessary to have ALL the skills on the list to be able to use this entity?
|
||||
/// If not, one of any skill will suffice
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool NeedAll = false;
|
||||
|
||||
/// <summary>
|
||||
/// the chances of something going wrong when using wihout skill
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float FuckupChance = 0.5f;
|
||||
|
||||
[DataField(required: true)]
|
||||
public List<ProtoId<CP14SkillPrototype>> RequiredSkills = new();
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Content.Shared._CP14.Skills.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skills.Components;
|
||||
|
||||
/// <summary>
|
||||
/// a list of skills learned by this entity
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCP14SkillSystem))]
|
||||
public sealed partial class CP14SkillsStorageComponent : Component
|
||||
{
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public List<ProtoId<CP14SkillPrototype>> Skills { get; private set; }= new();
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._CP14.Skills.Prototypes;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Prototype("CP14Skill")]
|
||||
public sealed partial class CP14SkillPrototype : IPrototype
|
||||
{
|
||||
[ViewVariables]
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField(required: true)]
|
||||
public LocId? Name{ get; private set; }
|
||||
|
||||
[DataField]
|
||||
public LocId? Desc{ get; private set; }
|
||||
|
||||
[DataField]
|
||||
public ComponentRegistry Components = new();
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
using Content.Shared._CP14.Skills.Components;
|
||||
using Content.Shared._CP14.Skills.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared._CP14.Skills;
|
||||
|
||||
public partial class SharedCP14SkillSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<CP14SkillsStorageComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<CP14AutoAddSkillComponent, MapInitEvent>(AutoAddSkill);
|
||||
}
|
||||
|
||||
private void AutoAddSkill(Entity<CP14AutoAddSkillComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
foreach (var skill in ent.Comp.Skills)
|
||||
{
|
||||
TryLearnSkill(ent, skill);
|
||||
}
|
||||
|
||||
RemComp(ent, ent.Comp);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<CP14SkillsStorageComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
foreach (var skill in ent.Comp.Skills)
|
||||
{
|
||||
TryLearnSkill(ent, skill, force: true);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasEnoughSkillToUse(EntityUid user, EntityUid target, out List<ProtoId<CP14SkillPrototype>> missingSkills)
|
||||
{
|
||||
missingSkills = new();
|
||||
if (!TryComp<CP14SkillRequirementComponent>(target, out var requirement) || requirement.RequiredSkills.Count == 0)
|
||||
return true;
|
||||
|
||||
if (!TryComp<CP14SkillsStorageComponent>(user, out var skillStorage))
|
||||
{
|
||||
missingSkills = requirement.RequiredSkills;
|
||||
return false;
|
||||
}
|
||||
|
||||
var success = requirement.NeedAll;
|
||||
foreach (var skill in requirement.RequiredSkills)
|
||||
{
|
||||
var hasSkill = skillStorage.Skills.Contains(skill);
|
||||
|
||||
if (requirement.NeedAll && !hasSkill)
|
||||
{
|
||||
missingSkills.Add(skill);
|
||||
success = false;
|
||||
}
|
||||
else if (!requirement.NeedAll && hasSkill)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
else if (!requirement.NeedAll && !hasSkill)
|
||||
{
|
||||
missingSkills.Add(skill);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public bool TryLearnSkill(EntityUid uid, ProtoId<CP14SkillPrototype> skill, bool force = false)
|
||||
{
|
||||
if (!TryComp<CP14SkillsStorageComponent>(uid, out var skillStorage))
|
||||
return false;
|
||||
|
||||
if (!skillStorage.Skills.Contains(skill))
|
||||
{
|
||||
skillStorage.Skills.Add(skill);
|
||||
if (!force)
|
||||
return false;
|
||||
}
|
||||
|
||||
var proto = _proto.Index(skill);
|
||||
EntityManager.AddComponents(uid, proto.Components);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryForgotSkill(EntityUid uid, ProtoId<CP14SkillPrototype> skill)
|
||||
{
|
||||
if (!TryComp<CP14SkillsStorageComponent>(uid, out var skillStorage))
|
||||
return false;
|
||||
|
||||
if (!skillStorage.Skills.Contains(skill))
|
||||
return false;
|
||||
|
||||
skillStorage.Skills.Remove(skill);
|
||||
|
||||
var proto = _proto.Index(skill);
|
||||
EntityManager.RemoveComponents(uid, proto.Components);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class CP14TrySkillIssueEvent : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid User;
|
||||
|
||||
public CP14TrySkillIssueEvent(EntityUid uid)
|
||||
{
|
||||
User = uid;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
* https://github.com/space-wizards/space-station-14/blob/master/LICENSE.TXT
|
||||
*/
|
||||
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Audio;
|
||||
@@ -39,4 +40,10 @@ public sealed class CP14WorkbenchRecipePrototype : IPrototype
|
||||
|
||||
[DataField]
|
||||
public string Solution = "food";
|
||||
|
||||
/// <summary>
|
||||
/// If the player does not have this knowledge, the recipe will not be displayed in the workbench.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ProtoId<CP14KnowledgePrototype>? KnowledgeRequired;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user