Knowledge UI (#779)

* knowledge button in HUD

* ui controller

* bugfixes

* finish

* all-knowing ghosts

* Create knowledge-ui.ftl
This commit is contained in:
Ed
2025-01-18 14:43:11 +03:00
committed by GitHub
parent 734d12cfac
commit 68ab77d4d4
17 changed files with 308 additions and 1 deletions

View File

@@ -123,6 +123,10 @@ namespace Content.Client.Input
common.AddFunction(ContentKeyFunctions.OpenDecalSpawnWindow);
common.AddFunction(ContentKeyFunctions.OpenAdminMenu);
common.AddFunction(ContentKeyFunctions.OpenGuidebook);
//CP14 Keys
human.AddFunction(ContentKeyFunctions.CP14OpenKnowledgeMenu);
//CP14 Keys end
}
}
}

View File

@@ -265,6 +265,11 @@ namespace Content.Client.Options.UI.Tabs
AddButton(EngineKeyFunctions.HideUI);
AddButton(ContentKeyFunctions.InspectEntity);
//CP14
AddHeader("ui-options-header-cp14");
AddButton(ContentKeyFunctions.CP14OpenKnowledgeMenu);
//CP14 end
foreach (var control in _keyControls.Values)
{
UpdateKeyControl(control);

View File

@@ -24,6 +24,7 @@ public sealed class GameTopMenuBarUIController : UIController
[Dependency] private readonly SandboxUIController _sandbox = default!;
[Dependency] private readonly GuidebookUIController _guidebook = default!;
[Dependency] private readonly EmotesUIController _emotes = default!;
[Dependency] private readonly CP14KnowledgeUIController _knowledge = default!; //CP14
private GameTopMenuBar? GameTopMenuBar => UIManager.GetActiveUIWidgetOrNull<GameTopMenuBar>();
@@ -47,6 +48,7 @@ public sealed class GameTopMenuBarUIController : UIController
_action.UnloadButton();
_sandbox.UnloadButton();
_emotes.UnloadButton();
_knowledge.UnloadButton(); //CP14
}
public void LoadButtons()
@@ -60,5 +62,6 @@ public sealed class GameTopMenuBarUIController : UIController
_action.LoadButton();
_sandbox.LoadButton();
_emotes.LoadButton();
_knowledge.LoadButton(); //CP14
}
}

View File

@@ -33,6 +33,18 @@
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/>
<!-- CP14 UI part -->
<ui:MenuButton
Name="CP14KnowledgeButton"
Access="Internal"
Icon="{xe:Tex '/Textures/Interface/students-cap.svg.192dpi.png'}"
ToolTip="{Loc 'cp14-game-hud-open-knowledge-menu-button-tooltip'}"
BoundKey = "{x:Static is:ContentKeyFunctions.CP14OpenKnowledgeMenu}"
MinSize="42 64"
HorizontalExpand="True"
AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}"
/>
<!-- CP14 UI part end -->
<ui:MenuButton
Name="CharacterButton"
Access="Internal"

View File

@@ -1,7 +1,42 @@
using Content.Shared._CP14.Knowledge;
using Content.Shared._CP14.Knowledge.Prototypes;
using Robust.Client.Player;
using Robust.Shared.Prototypes;
namespace Content.Client._CP14.Knowledge;
public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSystem
{
[Dependency] private readonly IPlayerManager _players = default!;
public event Action<KnowledgeData>? OnKnowledgeUpdate;
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<CP14KnowledgeInfoEvent>(OnCharacterKnowledgeEvent);
}
public void RequestKnowledgeInfo()
{
var entity = _players.LocalEntity;
if (entity is null)
return;
RaiseNetworkEvent(new RequestKnowledgeInfoEvent(GetNetEntity(entity.Value)));
}
private void OnCharacterKnowledgeEvent(CP14KnowledgeInfoEvent msg, EntitySessionEventArgs args)
{
var entity = GetEntity(msg.NetEntity);
var data = new KnowledgeData(entity, msg.AllKnowledge);
OnKnowledgeUpdate?.Invoke(data);
}
public readonly record struct KnowledgeData(
EntityUid Entity,
HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledges
);
}

View File

@@ -0,0 +1,158 @@
using Content.Client._CP14.Knowledge;
using Content.Client._CP14.UserInterface.Systems.Knowledge.Windows;
using Content.Client.Gameplay;
using Content.Client.UserInterface.Controls;
using Content.Shared.Input;
using JetBrains.Annotations;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controllers;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input.Binding;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Client.UserInterface.Systems.Character;
[UsedImplicitly]
public sealed class CP14KnowledgeUIController : UIController, IOnStateEntered<GameplayState>, IOnStateExited<GameplayState>,
IOnSystemChanged<ClientCP14KnowledgeSystem>
{
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[UISystemDependency] private readonly ClientCP14KnowledgeSystem _knowledge = default!;
private CP14KnowledgeWindow? _window;
private MenuButton? KnowledgeButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.CP14KnowledgeButton;
public void OnStateEntered(GameplayState state)
{
DebugTools.Assert(_window == null);
_window = UIManager.CreateWindow<CP14KnowledgeWindow>();
LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.CenterTop);
CommandBinds.Builder
.Bind(ContentKeyFunctions.CP14OpenKnowledgeMenu,
InputCmdHandler.FromDelegate(_ => ToggleWindow()))
.Register<CP14KnowledgeUIController>();
}
public void OnStateExited(GameplayState state)
{
if (_window != null)
{
_window.Dispose();
_window = null;
}
CommandBinds.Unregister<CP14KnowledgeUIController>();
}
public void OnSystemLoaded(ClientCP14KnowledgeSystem system)
{
system.OnKnowledgeUpdate += KnowledgeUpdated;
_player.LocalPlayerDetached += CharacterDetached;
}
public void OnSystemUnloaded(ClientCP14KnowledgeSystem system)
{
system.OnKnowledgeUpdate -= KnowledgeUpdated;
_player.LocalPlayerDetached -= CharacterDetached;
}
public void UnloadButton()
{
if (KnowledgeButton is null)
return;
KnowledgeButton.OnPressed -= KnowledgeButtonPressed;
}
public void LoadButton()
{
if (KnowledgeButton is null)
return;
KnowledgeButton.OnPressed += KnowledgeButtonPressed;
if (_window is null)
return;
_window.OnClose += DeactivateButton;
_window.OnOpen += ActivateButton;
}
private void DeactivateButton()
{
KnowledgeButton!.Pressed = false;
}
private void ActivateButton()
{
KnowledgeButton!.Pressed = true;
}
private void KnowledgeUpdated(ClientCP14KnowledgeSystem.KnowledgeData data)
{
if (_window is null)
return;
_window.KnowledgeContent.RemoveAllChildren();
var (entity, allKnowledge) = data;
foreach (var knowledge in allKnowledge)
{
if (!_proto.TryIndex(knowledge, out var indexedKnowledge))
continue;
var knowledgeButton = new Button()
{
Access = AccessLevel.Public,
Text = Loc.GetString(indexedKnowledge.Name),
ToolTip = Loc.GetString(indexedKnowledge.Desc),
TextAlign = Label.AlignMode.Center,
};
_window.KnowledgeContent.AddChild(knowledgeButton);
}
}
private void CharacterDetached(EntityUid uid)
{
CloseWindow();
}
private void KnowledgeButtonPressed(BaseButton.ButtonEventArgs args)
{
ToggleWindow();
}
private void CloseWindow()
{
_window?.Close();
}
private void ToggleWindow()
{
if (_window == null)
return;
if (KnowledgeButton != null)
{
KnowledgeButton.SetClickPressed(!_window.IsOpen);
}
if (_window.IsOpen)
{
CloseWindow();
}
else
{
_knowledge.RequestKnowledgeInfo();
_window.Open();
}
}
}

View File

@@ -0,0 +1,13 @@
<windows:CP14KnowledgeWindow
xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:windows="clr-namespace:Content.Client._CP14.UserInterface.Systems.Knowledge.Windows"
Title="{Loc 'cp14-knowledge-info-title'}"
MinWidth="400"
MinHeight="200">
<ScrollContainer>
<BoxContainer Name="KnowledgeContent" Margin="5" Access="Public" Orientation="Vertical">
</BoxContainer>
</ScrollContainer>
</windows:CP14KnowledgeWindow>

View File

@@ -0,0 +1,14 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client._CP14.UserInterface.Systems.Knowledge.Windows;
[GenerateTypedNameReferences]
public sealed partial class CP14KnowledgeWindow : DefaultWindow
{
public CP14KnowledgeWindow()
{
RobustXamlLoader.Load(this);
}
}

View File

@@ -38,6 +38,8 @@ public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
SubscribeLocalEvent<CP14KnowledgeStorageComponent, GetVerbsEvent<Verb>>(AddKnowledgeAdminVerb);
SubscribeLocalEvent<CP14KnowledgeLearningSourceComponent, GetVerbsEvent<Verb>>(AddKnowledgeLearningVerb);
SubscribeLocalEvent<CP14KnowledgeStorageComponent, CP14KnowledgeLearnDoAfterEvent>(KnowledgeLearnedEvent);
SubscribeNetworkEvent<RequestKnowledgeInfoEvent>(OnRequestKnowledgeInfoEvent);
}
private void KnowledgeLearnedEvent(Entity<CP14KnowledgeStorageComponent> ent, ref CP14KnowledgeLearnDoAfterEvent args)
@@ -120,7 +122,7 @@ public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
Category = VerbCategory.CP14KnowledgeAdd,
Act = () =>
{
TryLearnKnowledge(ent, knowledge, false);
TryLearnKnowledge(ent, knowledge, true);
},
Impact = LogImpact.High,
});
@@ -251,4 +253,17 @@ public sealed partial class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
$"{EntityManager.ToPrettyString(uid):player} forgot knowledge: {Loc.GetString(indexedKnowledge.Name)}");
return true;
}
private void OnRequestKnowledgeInfoEvent(RequestKnowledgeInfoEvent 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.Knowledges), args.SenderSession);
}
}

View File

@@ -116,5 +116,9 @@ namespace Content.Shared.Input
public static readonly BoundKeyFunction MappingRemoveDecal = "MappingRemoveDecal";
public static readonly BoundKeyFunction MappingCancelEraseDecal = "MappingCancelEraseDecal";
public static readonly BoundKeyFunction MappingOpenContextMenu = "MappingOpenContextMenu";
//CP14 keys
public static readonly BoundKeyFunction CP14OpenKnowledgeMenu = "CP14OpenKnowledgeMenu";
//CP14 keys end
}
}

View File

@@ -2,6 +2,7 @@ using System.Text;
using Content.Shared._CP14.Knowledge.Components;
using Content.Shared._CP14.Knowledge.Prototypes;
using Content.Shared.DoAfter;
using Content.Shared.Ghost;
using Content.Shared.MagicMirror;
using Content.Shared.Paper;
using Robust.Shared.Prototypes;
@@ -65,6 +66,9 @@ public abstract partial class SharedCP14KnowledgeSystem : EntitySystem
ProtoId<CP14KnowledgePrototype> knowledge,
CP14KnowledgeStorageComponent? knowledgeStorage = null)
{
if (HasComp<GhostComponent>(uid)) //All-knowing ghosts
return true;
if (!Resolve(uid, ref knowledgeStorage, false))
return false;
@@ -92,3 +96,27 @@ public sealed partial class CP14KnowledgeLearnDoAfterEvent : DoAfterEvent
public ProtoId<CP14KnowledgePrototype> Knowledge;
public override DoAfterEvent Clone() => this;
}
[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;
}
}
[Serializable, NetSerializable]
public sealed class RequestKnowledgeInfoEvent : EntityEventArgs
{
public readonly NetEntity NetEntity;
public RequestKnowledgeInfoEvent(NetEntity netEntity)
{
NetEntity = netEntity;
}
}

View File

@@ -0,0 +1 @@
cp14-game-hud-open-knowledge-menu-button-tooltip = Open character knowledge menu.

View File

@@ -14,3 +14,9 @@ cp14-ui-options-postprocess-tooltip =
additive lighting will be present. This does not control
post-process effects that affect the game or otherwise
carry some form of gameplay-related meaning.
## Controls menu
ui-options-header-cp14 = CrystallEdge
ui-options-function-cp14-open-knowledge-menu = Open character knowledge menu.

View File

@@ -0,0 +1 @@
cp14-knowledge-info-title = Character knowledge

View File

@@ -0,0 +1 @@
cp14-game-hud-open-knowledge-menu-button-tooltip = Открыть меню знаний персонажа.

View File

@@ -14,3 +14,9 @@ cp14-ui-options-postprocess-tooltip =
такие как аддитивное освещение. Это не управляет эффеками постобработки, которые
влияют на игру или иным образом не контролирует эффекты постобработки, которые
влияют на игру или имеют какое-то значение для игрового процесса.
## Controls menu
ui-options-header-cp14 = CrystallEdge
ui-options-function-cp14-open-knowledge-menu = Открыть меню знаний персонажа

View File

@@ -0,0 +1 @@
cp14-knowledge-info-title = Знания персонажа