Examine Groups (#12400)
* new version * testy2 * working version * new GroupExamineSystem * restructure * restructure again * update icon * adding group examine to prototypes * change examine group title to a localized string Co-authored-by: CommieFlowers <rasmus.cedergren@hotmail.com>
This commit is contained in:
@@ -77,20 +77,11 @@ namespace Content.Server.Armor
|
||||
if (armorModifiers == null)
|
||||
return;
|
||||
|
||||
var verb = new ExamineVerb()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
var markup = GetArmorExamine(armorModifiers);
|
||||
_examine.SendExamineTooltip(args.User, uid, markup, false, false);
|
||||
},
|
||||
Text = Loc.GetString("armor-examinable-verb-text"),
|
||||
Message = Loc.GetString("armor-examinable-verb-message"),
|
||||
Category = VerbCategory.Examine,
|
||||
IconTexture = "/Textures/Interface/VerbIcons/dot.svg.192dpi.png"
|
||||
};
|
||||
var examineMarkup = GetArmorExamine(armorModifiers);
|
||||
|
||||
args.Verbs.Add(verb);
|
||||
_examine.AddDetailedExamineVerb(args, component, examineMarkup, Loc.GetString("armor-examinable-verb-text"), "/Textures/Interface/VerbIcons/dot.svg.192dpi.png", Loc.GetString("armor-examinable-verb-message"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private static FormattedMessage GetArmorExamine(DamageModifierSet armorModifiers)
|
||||
|
||||
@@ -118,18 +118,8 @@ public sealed class ClothingSpeedModifierSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
var verb = new ExamineVerb()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
_examine.SendExamineTooltip(args.User, uid, msg, false, false);
|
||||
},
|
||||
Text = Loc.GetString("clothing-speed-examinable-verb-text"),
|
||||
Message = Loc.GetString("clothing-speed-examinable-verb-message"),
|
||||
Category = VerbCategory.Examine,
|
||||
IconTexture = "/Textures/Interface/VerbIcons/outfit.svg.192dpi.png"
|
||||
};
|
||||
_examine.AddDetailedExamineVerb(args, component, msg, Loc.GetString("clothing-speed-examinable-verb-text"), "/Textures/Interface/VerbIcons/outfit.svg.192dpi.png", Loc.GetString("clothing-speed-examinable-verb-message"));
|
||||
|
||||
args.Verbs.Add(verb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
175
Content.Shared/Examine/ExamineSystemShared.Group.cs
Normal file
175
Content.Shared/Examine/ExamineSystemShared.Group.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Shared.Verbs;
|
||||
|
||||
namespace Content.Shared.Examine
|
||||
{
|
||||
public abstract partial class ExamineSystemShared : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||
|
||||
public const string DefaultIconTexture = "/Textures/Interface/examine-star.png";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GroupExamineComponent, GetVerbsEvent<ExamineVerb>>(OnGroupExamineVerb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when getting verbs on an object with the GroupExamine component. <br/>
|
||||
/// This checks if any of the ExamineGroups are relevant (has 1 or more of the relevant components on the entity)
|
||||
/// and if so, creates an ExamineVerb details button for the ExamineGroup.
|
||||
/// </summary>
|
||||
private void OnGroupExamineVerb(EntityUid uid, GroupExamineComponent component, GetVerbsEvent<ExamineVerb> args)
|
||||
{
|
||||
foreach (var group in component.ExamineGroups)
|
||||
{
|
||||
if (!EntityHasComponent(uid, group.Components))
|
||||
continue;
|
||||
|
||||
var examineVerb = new ExamineVerb()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
SendExamineGroup(args.User, args.Target, group);
|
||||
group.Entries.Clear();
|
||||
},
|
||||
Text = group.ContextText,
|
||||
Message = group.HoverMessage,
|
||||
Category = VerbCategory.Examine,
|
||||
IconTexture = group.Icon
|
||||
};
|
||||
|
||||
args.Verbs.Add(examineVerb);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity <paramref name="uid"/> has any of the listed <paramref name="components"/>.
|
||||
/// </summary>
|
||||
public bool EntityHasComponent(EntityUid uid, List<string> components)
|
||||
{
|
||||
foreach (var comp in components)
|
||||
{
|
||||
if (!_componentFactory.TryGetRegistration(comp, out var componentRegistration))
|
||||
continue;
|
||||
|
||||
if (!HasComp(uid, componentRegistration.Type))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends an ExamineTooltip based on the contents of <paramref name="group"/>
|
||||
/// </summary>
|
||||
public void SendExamineGroup(EntityUid user, EntityUid target, ExamineGroup group)
|
||||
{
|
||||
var message = new FormattedMessage();
|
||||
|
||||
if (group.Title != null)
|
||||
{
|
||||
message.AddMarkup(Loc.GetString(group.Title));
|
||||
message.PushNewline();
|
||||
}
|
||||
message.AddMessage(GetFormattedMessageFromExamineEntries(group.Entries));
|
||||
|
||||
SendExamineTooltip(user, target, message, false, false);
|
||||
}
|
||||
|
||||
/// <returns>A FormattedMessage based on all <paramref name="entries"/>, sorted.</returns>
|
||||
public static FormattedMessage GetFormattedMessageFromExamineEntries(List<ExamineEntry> entries)
|
||||
{
|
||||
var formattedMessage = new FormattedMessage();
|
||||
entries.Sort((a, b) => (b.Priority.CompareTo(a.Priority)));
|
||||
|
||||
var first = true;
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
formattedMessage.PushNewline();
|
||||
}
|
||||
else
|
||||
{
|
||||
first = false;
|
||||
}
|
||||
|
||||
formattedMessage.AddMessage(entry.Message);
|
||||
}
|
||||
|
||||
return formattedMessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Either sends the details to a GroupExamineComponent if it finds one, or adds a details examine verb itself.
|
||||
/// </summary>
|
||||
public void AddDetailedExamineVerb(GetVerbsEvent<ExamineVerb> verbsEvent, Component component, List<ExamineEntry> entries, string verbText, string iconTexture = DefaultIconTexture, string hoverMessage = "")
|
||||
{
|
||||
// If the entity has the GroupExamineComponent
|
||||
if (TryComp<GroupExamineComponent>(verbsEvent.Target, out var groupExamine))
|
||||
{
|
||||
// Make sure we have the component name as a string
|
||||
var componentName = _componentFactory.GetComponentName(component.GetType());
|
||||
|
||||
foreach (var examineGroup in groupExamine.ExamineGroups)
|
||||
{
|
||||
// If any of the examine groups list of components contain this componentname
|
||||
if (examineGroup.Components.Contains(componentName))
|
||||
{
|
||||
foreach (var entry in examineGroup.Entries)
|
||||
{
|
||||
// If any of the entries already are from your component, dont do anything else - no doubles!
|
||||
if (entry.ComponentName == componentName)
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
// Otherwise, just add all information to the examine groups entries, and stop there.
|
||||
examineGroup.Entries.Add(entry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var formattedMessage = GetFormattedMessageFromExamineEntries(entries);
|
||||
|
||||
var examineVerb = new ExamineVerb()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
SendExamineTooltip(verbsEvent.User, verbsEvent.Target, formattedMessage, false, false);
|
||||
},
|
||||
Text = verbText,
|
||||
Message = hoverMessage,
|
||||
Category = VerbCategory.Examine,
|
||||
IconTexture = iconTexture
|
||||
};
|
||||
|
||||
verbsEvent.Verbs.Add(examineVerb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Either adds a details examine verb, or sends the details to a GroupExamineComponent if it finds one.
|
||||
/// </summary>
|
||||
public void AddDetailedExamineVerb(GetVerbsEvent<ExamineVerb> verbsEvent, Component component, ExamineEntry entry, string verbText, string iconTexture = DefaultIconTexture, string hoverMessage = "")
|
||||
{
|
||||
AddDetailedExamineVerb(verbsEvent, component, new List<ExamineEntry> { entry }, verbText, iconTexture, hoverMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Either adds a details examine verb, or sends the details to a GroupExamineComponent if it finds one.
|
||||
/// </summary>
|
||||
public void AddDetailedExamineVerb(GetVerbsEvent<ExamineVerb> verbsEvent, Component component, FormattedMessage message, string verbText, string iconTexture = DefaultIconTexture, string hoverMessage = "")
|
||||
{
|
||||
var componentName = _componentFactory.GetComponentName(component.GetType());
|
||||
AddDetailedExamineVerb(verbsEvent, component, new ExamineEntry(componentName, 0f, message), verbText, iconTexture, hoverMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ using static Content.Shared.Interaction.SharedInteractionSystem;
|
||||
|
||||
namespace Content.Shared.Examine
|
||||
{
|
||||
public abstract class ExamineSystemShared : EntitySystem
|
||||
public abstract partial class ExamineSystemShared : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||
|
||||
103
Content.Shared/Examine/GroupExamineComponent.cs
Normal file
103
Content.Shared/Examine/GroupExamineComponent.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Examine
|
||||
{
|
||||
/// <summary>
|
||||
/// This component groups examine messages together
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class GroupExamineComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of ExamineGroups.
|
||||
/// </summary>
|
||||
[DataField("group")]
|
||||
public List<ExamineGroup> ExamineGroups = new()
|
||||
{
|
||||
new ExamineGroup()
|
||||
{
|
||||
Components = new()
|
||||
{
|
||||
"Armor",
|
||||
"ClothingSpeedModifier",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed class ExamineGroup
|
||||
{
|
||||
/// <summary>
|
||||
/// The title of the Examine Group, the .
|
||||
/// </summary>
|
||||
[DataField("title")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? Title;
|
||||
|
||||
/// <summary>
|
||||
/// A list of ExamineEntries, containing which component it belongs to, which priority it has, and what FormattedMessage it holds.
|
||||
/// </summary>
|
||||
[DataField("entries")]
|
||||
public List<ExamineEntry> Entries = new();
|
||||
|
||||
/// <summary>
|
||||
/// A list of all components this ExamineGroup encompasses.
|
||||
/// </summary>
|
||||
[DataField("components")]
|
||||
public List<string> Components = new();
|
||||
|
||||
/// <summary>
|
||||
/// The icon path for the Examine Group.
|
||||
/// </summary>
|
||||
[DataField("icon")]
|
||||
public string Icon = "/Textures/Interface/examine-star.png";
|
||||
|
||||
/// <summary>
|
||||
/// The text shown in the context verb menu.
|
||||
/// </summary>
|
||||
[DataField("contextText")]
|
||||
public string ContextText = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Details shown when hovering over the button.
|
||||
/// </summary>
|
||||
[DataField("hoverMessage")]
|
||||
public string HoverMessage = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An entry used when showing examine details
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ExamineEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Which component does this entry relate to?
|
||||
/// </summary>
|
||||
[DataField("component")]
|
||||
public string ComponentName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// What priority has this entry - entries are sorted high to low.
|
||||
/// </summary>
|
||||
[DataField("priority")]
|
||||
public float Priority = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The FormattedMessage of this entry.
|
||||
/// </summary>
|
||||
[DataField("message")]
|
||||
public FormattedMessage Message = new();
|
||||
|
||||
/// <param name="componentName">Should be set to _componentFactory.GetComponentName(component.GetType()) to properly function.</param>
|
||||
public ExamineEntry(string componentName, float priority, FormattedMessage message)
|
||||
{
|
||||
ComponentName = componentName;
|
||||
Priority = priority;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -130,3 +130,4 @@
|
||||
modifiers:
|
||||
coefficients:
|
||||
Heat: 0.95
|
||||
- type: GroupExamine
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
Piercing: 0.95
|
||||
Heat: 0.90
|
||||
Radiation: 0.25
|
||||
- type: GroupExamine
|
||||
- type: IngestionBlocker
|
||||
- type: Tag
|
||||
tags:
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
Slash: 0.5
|
||||
Piercing: 0.6
|
||||
Heat: 0.5
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterBaseLarge
|
||||
@@ -72,6 +73,7 @@
|
||||
Piercing: 0.2
|
||||
Heat: 0.5
|
||||
Radiation: 0
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterArmorHeavy
|
||||
@@ -136,6 +138,7 @@
|
||||
Heat: 0.9
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.9
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterBaseLarge
|
||||
@@ -156,6 +159,7 @@
|
||||
Heat: 0.9
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.8
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterBaseLarge
|
||||
@@ -176,6 +180,7 @@
|
||||
Heat: 0.5
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.65
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterBaseLarge
|
||||
@@ -200,3 +205,4 @@
|
||||
sprintModifier: 0.65
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.5
|
||||
- type: GroupExamine
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
toggleable-clothing: !type:ContainerSlot {}
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
abstract: true
|
||||
|
||||
@@ -481,6 +481,7 @@
|
||||
Slash: 0.95
|
||||
Heat: 0.90
|
||||
Radiation: 0.75
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterHardsuitBase
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
Heat: 0.75
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.65
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterEVASuitBase
|
||||
@@ -59,6 +60,7 @@
|
||||
sprintModifier: 0.7
|
||||
- type: TemperatureProtection
|
||||
coefficient: 0.01
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: [ClothingOuterBaseLarge, GeigerCounterClothing]
|
||||
@@ -75,6 +77,7 @@
|
||||
Radiation: 0.05
|
||||
- type: Clothing
|
||||
sprite: Clothing/OuterClothing/Suits/rad.rsi
|
||||
- type: GroupExamine
|
||||
|
||||
- type: entity
|
||||
parent: ClothingOuterBase
|
||||
@@ -150,3 +153,4 @@
|
||||
- type: ClothingSpeedModifier
|
||||
walkModifier: 0.7
|
||||
sprintModifier: 0.75
|
||||
- type: GroupExamine
|
||||
|
||||
BIN
Resources/Textures/Interface/examine-star.png
Normal file
BIN
Resources/Textures/Interface/examine-star.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 614 B |
2
Resources/Textures/Interface/examine-star.png.yml
Normal file
2
Resources/Textures/Interface/examine-star.png.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
sample:
|
||||
filter: true
|
||||
Reference in New Issue
Block a user