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:
@@ -1,7 +1,6 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared._CP14.Farming;
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
|
||||
@@ -81,6 +81,9 @@ public sealed partial class CP14DemiplaneSystem
|
||||
|
||||
while (query.MoveNext(out var uid, out var stabilizer, out var xform))
|
||||
{
|
||||
if (!stabilizer.Enabled)
|
||||
continue;
|
||||
|
||||
if (TryTeleportOutDemiplane(demiplane, uid))
|
||||
{
|
||||
if (!safe)
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Knowledge;
|
||||
|
||||
// TODO: Add UI
|
||||
public sealed class CP14KnowledgeAdminUtilitiesSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminManager _admin = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly CP14KnowledgeSystem _knowledge = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14KnowledgeStorageComponent, GetVerbsEvent<Verb>>(AddKnowledgeAdminVerb);
|
||||
}
|
||||
|
||||
private void AddKnowledgeAdminVerb(Entity<CP14KnowledgeStorageComponent> entity, ref GetVerbsEvent<Verb> args)
|
||||
{
|
||||
if (!_admin.HasAdminFlag(args.User, AdminFlags.Admin))
|
||||
return;
|
||||
|
||||
// Remove knowledge
|
||||
foreach (var knowledge in entity.Comp.Knowledge)
|
||||
{
|
||||
if (!_prototype.TryIndex(knowledge, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = $"{Loc.GetString(indexedKnowledge.Name)}",
|
||||
Message = Loc.GetString(indexedKnowledge.Desc),
|
||||
Category = VerbCategory.CP14KnowledgeRemove,
|
||||
Act = () =>
|
||||
{
|
||||
_knowledge.TryRemove(entity.Owner, knowledge);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
});
|
||||
}
|
||||
|
||||
// Add knowledge
|
||||
foreach (var knowledge in _prototype.EnumeratePrototypes<CP14KnowledgePrototype>())
|
||||
{
|
||||
// An entity with CP14AllKnowingComponent can't be taught anything,
|
||||
// it already knows everything
|
||||
if (_knowledge.HasKnowledge(entity.Owner, knowledge.ID))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = $"{Loc.GetString(knowledge.Name)}",
|
||||
Message = Loc.GetString(knowledge.Desc),
|
||||
Category = VerbCategory.CP14KnowledgeAdd,
|
||||
Act = () =>
|
||||
{
|
||||
_knowledge.TryAdd(entity.Owner, knowledge, true);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
using System.Text;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Mind;
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared._CP14.Knowledge.Components;
|
||||
using Content.Shared._CP14.Knowledge.Events;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Knowledge;
|
||||
|
||||
public sealed class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IChatManager _chat = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14AutoAddKnowledgeComponent, MapInitEvent>(AutoAddSkill);
|
||||
SubscribeLocalEvent<CP14KnowledgeStorageComponent, CP14KnowledgeLearnDoAfterEvent>(KnowledgeLearnedEvent);
|
||||
SubscribeLocalEvent<CP14KnowledgeLearningSourceComponent, GetVerbsEvent<Verb>>(AddKnowledgeLearningVerb);
|
||||
|
||||
SubscribeNetworkEvent<CP14RequestKnowledgeInfoEvent>(OnRequestKnowledgeInfoEvent);
|
||||
}
|
||||
|
||||
private void AddKnowledgeLearningVerb(Entity<CP14KnowledgeLearningSourceComponent> ent, ref GetVerbsEvent<Verb> args)
|
||||
{
|
||||
var user = args.User;
|
||||
foreach (var knowledge in ent.Comp.Knowledge)
|
||||
{
|
||||
if (!_prototype.TryIndex(knowledge, out var indexedKnowledge))
|
||||
continue;
|
||||
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = $"{Loc.GetString(indexedKnowledge.Name)}",
|
||||
Message = Loc.GetString(indexedKnowledge.Desc),
|
||||
Category = VerbCategory.CP14KnowledgeLearn,
|
||||
Act = () =>
|
||||
{
|
||||
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
|
||||
user,
|
||||
ent.Comp.DoAfter,
|
||||
new CP14KnowledgeLearnDoAfterEvent { Knowledge = knowledge },
|
||||
user,
|
||||
ent,
|
||||
ent)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnMove = true,
|
||||
});
|
||||
},
|
||||
Disabled = HasKnowledge(user, knowledge),
|
||||
Impact = LogImpact.Medium,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void KnowledgeLearnedEvent(Entity<CP14KnowledgeStorageComponent> ent, ref CP14KnowledgeLearnDoAfterEvent args)
|
||||
{
|
||||
if (args.Cancelled || args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
TryAdd(ent.Owner, args.Knowledge);
|
||||
}
|
||||
|
||||
private void AutoAddSkill(Entity<CP14AutoAddKnowledgeComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
foreach (var knowledge in ent.Comp.Knowledge)
|
||||
{
|
||||
TryAdd(ent.Owner, knowledge);
|
||||
}
|
||||
|
||||
RemComp(ent, ent.Comp);
|
||||
}
|
||||
|
||||
public bool TryAdd(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> knowledgeId, bool force = false, bool silent = false)
|
||||
{
|
||||
if (!Resolve(entity, ref entity.Comp, false))
|
||||
return false;
|
||||
|
||||
if (HasKnowledge(entity, knowledgeId))
|
||||
return false;
|
||||
|
||||
if (!_prototype.TryIndex(knowledgeId, out var knowledge))
|
||||
return false;
|
||||
|
||||
MindComponent? mindComponent;
|
||||
|
||||
foreach (var dependencyKnowledgeId in knowledge.Dependencies)
|
||||
{
|
||||
if (!_prototype.TryIndex(dependencyKnowledgeId, out var dependencyKnowledge))
|
||||
return false;
|
||||
|
||||
// If we teach by force - we automatically teach all the basics that are necessary for that skill.
|
||||
if (force && !TryAdd(entity, dependencyKnowledge, true))
|
||||
return false;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Loc.GetString("cp14-cant-learn-knowledge-dependencies", ("target", Loc.GetString(knowledge.Desc))));
|
||||
|
||||
// We cant learnt
|
||||
if (HasKnowledge(entity, dependencyKnowledge))
|
||||
continue;
|
||||
|
||||
sb.Append($"\n- {Loc.GetString(dependencyKnowledge.Desc)}");
|
||||
|
||||
if (silent)
|
||||
return false;
|
||||
|
||||
if (!_mind.TryGetMind(entity, out _, out mindComponent) || mindComponent.Session is null)
|
||||
return false;
|
||||
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", sb.ToString()));
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
sb.ToString(),
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComponent.Session.Channel);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!entity.Comp.Knowledge.Add(knowledgeId))
|
||||
return false;
|
||||
|
||||
_adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{EntityManager.ToPrettyString(entity):player} learned new knowledge: {Loc.GetString(knowledge.Name)}");
|
||||
|
||||
// TODO: coding on a sleepy head is a bad idea. Remove duplicate variables. >:(
|
||||
if (silent)
|
||||
return true;
|
||||
|
||||
if (!_mind.TryGetMind(entity, out _, out mindComponent) || mindComponent.Session is null)
|
||||
return false;
|
||||
|
||||
var message = Loc.GetString("cp14-learned-new-knowledge", ("name", Loc.GetString(knowledge.Name)));
|
||||
var wrappedMessage2 = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage2,
|
||||
default,
|
||||
false,
|
||||
mindComponent.Session.Channel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryRemove(Entity<CP14KnowledgeStorageComponent?> entity, ProtoId<CP14KnowledgePrototype> proto, bool silent = false)
|
||||
{
|
||||
if (!Resolve(entity, ref entity.Comp, false))
|
||||
return false;
|
||||
|
||||
if (!entity.Comp.Knowledge.Contains(proto))
|
||||
return false;
|
||||
|
||||
if (!_prototype.TryIndex(proto, out var indexedKnowledge))
|
||||
return false;
|
||||
|
||||
if (!entity.Comp.Knowledge.Remove(proto))
|
||||
return false;
|
||||
|
||||
_adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{EntityManager.ToPrettyString(entity):player} forgot knowledge: {Loc.GetString(indexedKnowledge.Name)}");
|
||||
|
||||
if (silent)
|
||||
return true;
|
||||
|
||||
if (!_mind.TryGetMind(entity, out _, out var mindComp) || mindComp.Session is null)
|
||||
return true;
|
||||
|
||||
var message = Loc.GetString("cp14-forgot-knowledge", ("name", Loc.GetString(indexedKnowledge.Name)));
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
|
||||
_chat.ChatMessageToOne(
|
||||
ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
mindComp.Session.Channel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnRequestKnowledgeInfoEvent(CP14RequestKnowledgeInfoEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
if (!args.SenderSession.AttachedEntity.HasValue || args.SenderSession.AttachedEntity != GetEntity(msg.NetEntity))
|
||||
return;
|
||||
|
||||
var entity = args.SenderSession.AttachedEntity.Value;
|
||||
|
||||
if (!TryComp<CP14KnowledgeStorageComponent>(entity, out var knowledgeComp))
|
||||
return;
|
||||
|
||||
RaiseNetworkEvent(new CP14KnowledgeInfoEvent(GetNetEntity(entity),knowledgeComp.Knowledge), args.SenderSession);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Content.Shared.Roles;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.Knowledge.Specials;
|
||||
|
||||
/// <summary>
|
||||
/// a component that can be hung on an entity to immediately teach it some skills
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed partial class CP14AddKnowledgeSpecial : JobSpecial
|
||||
{
|
||||
[DataField(required: true), ViewVariables(VVAccess.ReadOnly)]
|
||||
public List<ProtoId<CP14KnowledgePrototype>> Knowledge = [];
|
||||
|
||||
public override void AfterEquip(EntityUid mob)
|
||||
{
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
var knowledgeSystem = entMan.System<CP14KnowledgeSystem>();
|
||||
|
||||
foreach (var knowledge in Knowledge)
|
||||
{
|
||||
knowledgeSystem.TryAdd(mob, knowledge, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.MagicSpell;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14AutoLearnActionComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public HashSet<EntProtoId> Actions = new();
|
||||
}
|
||||
@@ -45,17 +45,6 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem
|
||||
SubscribeLocalEvent<CP14MagicEffectManaCostComponent, CP14MagicEffectConsumeResourceEvent>(OnManaConsume);
|
||||
|
||||
SubscribeLocalEvent<CP14MagicEffectRequiredMusicToolComponent, CP14CastMagicEffectAttemptEvent>(OnMusicCheck);
|
||||
|
||||
SubscribeLocalEvent<CP14AutoLearnActionComponent, MapInitEvent>(OnAutoLearnAction);
|
||||
}
|
||||
|
||||
private void OnAutoLearnAction(Entity<CP14AutoLearnActionComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
foreach (var action in ent.Comp.Actions)
|
||||
{
|
||||
_action.AddAction(ent, action);
|
||||
}
|
||||
RemCompDeferred<CP14AutoLearnActionComponent>(ent);
|
||||
}
|
||||
|
||||
private void OnProjectileHit(Entity<CP14SpellEffectOnHitComponent> ent, ref ThrowDoHitEvent args)
|
||||
|
||||
24
Content.Server/_CP14/Skill/CP14SkillSystem.cs
Normal file
24
Content.Server/_CP14/Skill/CP14SkillSystem.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Content.Shared._CP14.Skill;
|
||||
using Content.Shared._CP14.Skill.Components;
|
||||
|
||||
namespace Content.Server._CP14.Skill;
|
||||
|
||||
public sealed partial class CP14SkillSystem : CP14SharedSkillSystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeNetworkEvent<CP14TryLearnSkillMessage>(OnClientRequestLearnSkill);
|
||||
}
|
||||
|
||||
private void OnClientRequestLearnSkill(CP14TryLearnSkillMessage ev, EntitySessionEventArgs args)
|
||||
{
|
||||
var entity = GetEntity(ev.Entity);
|
||||
|
||||
if (args.SenderSession.AttachedEntity != entity)
|
||||
return;
|
||||
|
||||
TryLearnSkill(entity, ev.Skill);
|
||||
}
|
||||
}
|
||||
@@ -30,13 +30,22 @@ public sealed partial class CP14WorkbenchSystem
|
||||
if (!_proto.TryIndex(recipeId, out var indexedRecipe))
|
||||
continue;
|
||||
|
||||
//if (indexedRecipe.KnowledgeRequired is not null)
|
||||
//{
|
||||
// if (!_knowledge.HasKnowledge(user, indexedRecipe.KnowledgeRequired.Value))
|
||||
// continue;
|
||||
//}
|
||||
var canCraft = true;
|
||||
var hidden = false;
|
||||
|
||||
var entry = new CP14WorkbenchUiRecipesEntry(recipeId, CanCraftRecipe(indexedRecipe, placedEntities, user));
|
||||
foreach (var requirement in indexedRecipe.Requirements)
|
||||
{
|
||||
if (!requirement.CheckRequirement(EntityManager, _proto, placedEntities, user, indexedRecipe))
|
||||
{
|
||||
canCraft = false;
|
||||
hidden = requirement.HideRecipe;
|
||||
}
|
||||
}
|
||||
|
||||
if (hidden)
|
||||
continue;
|
||||
|
||||
var entry = new CP14WorkbenchUiRecipesEntry(recipeId, canCraft);
|
||||
|
||||
recipes.Add(entry);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared._CP14.Workbench;
|
||||
using Content.Shared._CP14.Workbench.Prototypes;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
@@ -30,7 +29,6 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedCP14KnowledgeSystem _knowledge = default!;
|
||||
|
||||
private EntityQuery<MetaDataComponent> _metaQuery;
|
||||
private EntityQuery<StackComponent> _stackQuery;
|
||||
@@ -138,7 +136,7 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
|
||||
{
|
||||
foreach (var req in recipe.Requirements)
|
||||
{
|
||||
if (!req.CheckRequirement(EntityManager, _proto, entities, user))
|
||||
if (!req.CheckRequirement(EntityManager, _proto, entities, user, recipe))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user