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:
rolfero
2022-12-20 03:53:36 +01:00
committed by GitHub
parent f09097ccd7
commit 7259acfb18
13 changed files with 303 additions and 28 deletions

View File

@@ -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)

View File

@@ -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;
}
}

View 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);
}
}
}

View File

@@ -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!;

View 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;
}
}
}

View File

@@ -130,3 +130,4 @@
modifiers:
coefficients:
Heat: 0.95
- type: GroupExamine

View File

@@ -142,6 +142,7 @@
Piercing: 0.95
Heat: 0.90
Radiation: 0.25
- type: GroupExamine
- type: IngestionBlocker
- type: Tag
tags:

View File

@@ -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,7 +180,8 @@
Heat: 0.5
- type: ExplosionResistance
damageCoefficient: 0.65
- type: GroupExamine
- type: entity
parent: ClothingOuterBaseLarge
id: ClothingOuterArmorChangeling
@@ -200,3 +205,4 @@
sprintModifier: 0.65
- type: ExplosionResistance
damageCoefficient: 0.5
- type: GroupExamine

View File

@@ -73,6 +73,7 @@
- type: ContainerContainer
containers:
toggleable-clothing: !type:ContainerSlot {}
- type: GroupExamine
- type: entity
abstract: true

View File

@@ -481,6 +481,7 @@
Slash: 0.95
Heat: 0.90
Radiation: 0.75
- type: GroupExamine
- type: entity
parent: ClothingOuterHardsuitBase

View File

@@ -16,7 +16,8 @@
Piercing: 0.9
Heat: 0.75
- type: ExplosionResistance
damageCoefficient: 0.65
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

View File

@@ -0,0 +1,2 @@
sample:
filter: true