Objectives (#2459)
* temp commit to save progress * adds objectives * refactors mind.addobjective a bit * better names for my testobjectives which i'll remove later on anyways * nullable errors * some misc fixes * no sorted or set, what was i thinking here? * removes unused imports * added commands * fully implements stealcondition * started uiwork * moved prototypeicon to engine * removes objective class & uiwork * refactors ui to only update when opened adds progresstexturerect * adds some margin * removes some testing code * ignores objectiveprototypes on clientside * fixes * removes using statements for exp * gets the job * always show issuer * locs & _ * giving commands some love * Update Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterBar.cs Co-authored-by: Exp <theexp111@gmail.com> * makes commands use new thingy * string interpolation * good catch exp * loc'd * linq gone * runtime * moves function from engine * oopsie * Update Content.Server/Objectives/Conditions/StealCondition.cs Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * makes messages directed * base call & validation * shuffle once * No? Money down! Co-authored-by: Paul <ritter.paul1+git@googlemail.com> Co-authored-by: Exp <theexp111@gmail.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
@@ -79,6 +79,7 @@ namespace Content.Client
|
|||||||
prototypes.RegisterIgnore("gasReaction");
|
prototypes.RegisterIgnore("gasReaction");
|
||||||
prototypes.RegisterIgnore("seed"); // Seeds prototypes are server-only.
|
prototypes.RegisterIgnore("seed"); // Seeds prototypes are server-only.
|
||||||
prototypes.RegisterIgnore("barSign");
|
prototypes.RegisterIgnore("barSign");
|
||||||
|
prototypes.RegisterIgnore("objective");
|
||||||
|
|
||||||
ClientContentIoC.Register();
|
ClientContentIoC.Register();
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Drawing;
|
||||||
using Content.Client.GameObjects.Components.Mobs;
|
using Content.Client.GameObjects.Components.Mobs;
|
||||||
using Content.Client.UserInterface;
|
using Content.Client.UserInterface;
|
||||||
using Content.Client.UserInterface.Stylesheets;
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
|
using Content.Shared.GameObjects.Components.Actor;
|
||||||
using Robust.Client.Interfaces.GameObjects.Components;
|
using Robust.Client.Interfaces.GameObjects.Components;
|
||||||
using Robust.Client.Interfaces.ResourceManagement;
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.Utility;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Network;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Players;
|
||||||
|
|
||||||
namespace Content.Client.GameObjects.Components.Actor
|
namespace Content.Client.GameObjects.Components.Actor
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class CharacterInfoComponent : Component, ICharacterUI
|
public sealed class CharacterInfoComponent : SharedCharacterInfoComponent, ICharacterUI
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||||
|
|
||||||
private CharacterInfoControl _control;
|
private CharacterInfoControl _control = default!;
|
||||||
|
|
||||||
public override string Name => "CharacterInfo";
|
public Control Scene { get; private set; } = default!;
|
||||||
|
|
||||||
public Control Scene { get; private set; }
|
|
||||||
public UIPriority Priority => UIPriority.Info;
|
public UIPriority Priority => UIPriority.Info;
|
||||||
|
|
||||||
public override void OnAdd()
|
public override void OnAdd()
|
||||||
@@ -30,18 +34,29 @@ namespace Content.Client.GameObjects.Components.Actor
|
|||||||
Scene = _control = new CharacterInfoControl(_resourceCache);
|
Scene = _control = new CharacterInfoControl(_resourceCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public void Opened()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
SendNetworkMessage(new RequestCharacterInfoMessage());
|
||||||
|
}
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out ISpriteComponent spriteComponent))
|
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null)
|
||||||
|
{
|
||||||
|
base.HandleNetworkMessage(message, netChannel, session);
|
||||||
|
|
||||||
|
if(session?.AttachedEntity != Owner) return;
|
||||||
|
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case CharacterInfoMessage characterInfoMessage:
|
||||||
|
_control.UpdateUI(characterInfoMessage);
|
||||||
|
if (Owner.TryGetComponent(out ISpriteComponent? spriteComponent))
|
||||||
{
|
{
|
||||||
_control.SpriteView.Sprite = spriteComponent;
|
_control.SpriteView.Sprite = spriteComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
_control.NameLabel.Text = Owner.Name;
|
_control.NameLabel.Text = Owner.Name;
|
||||||
// ReSharper disable once StringLiteralTypo
|
break;
|
||||||
_control.SubText.Text = Loc.GetString("Professional Greyshirt");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class CharacterInfoControl : VBoxContainer
|
private sealed class CharacterInfoControl : VBoxContainer
|
||||||
@@ -50,8 +65,12 @@ namespace Content.Client.GameObjects.Components.Actor
|
|||||||
public Label NameLabel { get; }
|
public Label NameLabel { get; }
|
||||||
public Label SubText { get; }
|
public Label SubText { get; }
|
||||||
|
|
||||||
|
public VBoxContainer ObjectivesContainer { get; }
|
||||||
|
|
||||||
public CharacterInfoControl(IResourceCache resourceCache)
|
public CharacterInfoControl(IResourceCache resourceCache)
|
||||||
{
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
AddChild(new HBoxContainer
|
AddChild(new HBoxContainer
|
||||||
{
|
{
|
||||||
Children =
|
Children =
|
||||||
@@ -66,7 +85,8 @@ namespace Content.Client.GameObjects.Components.Actor
|
|||||||
(SubText = new Label
|
(SubText = new Label
|
||||||
{
|
{
|
||||||
SizeFlagsVertical = SizeFlags.None,
|
SizeFlagsVertical = SizeFlags.None,
|
||||||
StyleClasses = {StyleNano.StyleClassLabelSubText}
|
StyleClasses = {StyleNano.StyleClassLabelSubText},
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,16 +98,65 @@ namespace Content.Client.GameObjects.Components.Actor
|
|||||||
PlaceholderText = Loc.GetString("Health & status effects")
|
PlaceholderText = Loc.GetString("Health & status effects")
|
||||||
});
|
});
|
||||||
|
|
||||||
AddChild(new Placeholder(resourceCache)
|
AddChild(new Label
|
||||||
{
|
{
|
||||||
PlaceholderText = Loc.GetString("Objectives")
|
Text = Loc.GetString("Objectives"),
|
||||||
|
SizeFlagsHorizontal = SizeFlags.ShrinkCenter
|
||||||
});
|
});
|
||||||
|
ObjectivesContainer = new VBoxContainer();
|
||||||
|
AddChild(ObjectivesContainer);
|
||||||
|
|
||||||
AddChild(new Placeholder(resourceCache)
|
AddChild(new Placeholder(resourceCache)
|
||||||
{
|
{
|
||||||
PlaceholderText = Loc.GetString("Antagonist Roles")
|
PlaceholderText = Loc.GetString("Antagonist Roles")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateUI(CharacterInfoMessage characterInfoMessage)
|
||||||
|
{
|
||||||
|
SubText.Text = characterInfoMessage.JobTitle;
|
||||||
|
|
||||||
|
ObjectivesContainer.RemoveAllChildren();
|
||||||
|
foreach (var (groupId, objectiveConditions) in characterInfoMessage.Objectives)
|
||||||
|
{
|
||||||
|
var vbox = new VBoxContainer
|
||||||
|
{
|
||||||
|
Modulate = Color.Gray
|
||||||
|
};
|
||||||
|
|
||||||
|
vbox.AddChild(new Label
|
||||||
|
{
|
||||||
|
Text = groupId,
|
||||||
|
Modulate = Color.LightSkyBlue
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var objectiveCondition in objectiveConditions)
|
||||||
|
{
|
||||||
|
var hbox = new HBoxContainer();
|
||||||
|
hbox.AddChild(new ProgressTextureRect
|
||||||
|
{
|
||||||
|
Texture = objectiveCondition.SpriteSpecifier.Frame0(),
|
||||||
|
Progress = objectiveCondition.Progress,
|
||||||
|
SizeFlagsVertical = SizeFlags.ShrinkCenter
|
||||||
|
});
|
||||||
|
hbox.AddChild(new Control
|
||||||
|
{
|
||||||
|
CustomMinimumSize = (10,0)
|
||||||
|
});
|
||||||
|
hbox.AddChild(new VBoxContainer
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Label{Text = objectiveCondition.Title},
|
||||||
|
new Label{Text = objectiveCondition.Description}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
vbox.AddChild(hbox);
|
||||||
|
}
|
||||||
|
ObjectivesContainer.AddChild(vbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ namespace Content.Client.GameObjects.Components.Actor
|
|||||||
public class CharacterWindow : SS14Window
|
public class CharacterWindow : SS14Window
|
||||||
{
|
{
|
||||||
private readonly VBoxContainer _contentsVBox;
|
private readonly VBoxContainer _contentsVBox;
|
||||||
|
private readonly List<ICharacterUI> _windowComponents;
|
||||||
|
|
||||||
public CharacterWindow(List<ICharacterUI> windowComponents)
|
public CharacterWindow(List<ICharacterUI> windowComponents)
|
||||||
{
|
{
|
||||||
@@ -129,6 +130,17 @@ namespace Content.Client.GameObjects.Components.Actor
|
|||||||
{
|
{
|
||||||
_contentsVBox.AddChild(element.Scene);
|
_contentsVBox.AddChild(element.Scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_windowComponents = windowComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Opened()
|
||||||
|
{
|
||||||
|
base.Opened();
|
||||||
|
foreach (var windowComponent in _windowComponents)
|
||||||
|
{
|
||||||
|
windowComponent.Opened();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Client.GameObjects.EntitySystems.DoAfter;
|
||||||
|
using Robust.Client.Graphics.Drawing;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Actor
|
||||||
|
{
|
||||||
|
public class ProgressTextureRect : TextureRect
|
||||||
|
{
|
||||||
|
public float Progress;
|
||||||
|
|
||||||
|
protected override void Draw(DrawingHandleScreen handle)
|
||||||
|
{
|
||||||
|
var dims = Texture != null ? GetDrawDimensions(Texture) : UIBox2.FromDimensions(Vector2.Zero, PixelSize);
|
||||||
|
dims.Top = Math.Max(dims.Bottom - dims.Bottom * Progress,0);
|
||||||
|
handle.DrawRect(dims, DoAfterHelpers.GetProgressColor(Progress));
|
||||||
|
|
||||||
|
base.Draw(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,5 +17,10 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
/// The order it will appear in the character UI, higher is lower
|
/// The order it will appear in the character UI, higher is lower
|
||||||
/// </summary>
|
/// </summary>
|
||||||
UIPriority Priority { get; }
|
UIPriority Priority { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the CharacterUi was opened
|
||||||
|
/// </summary>
|
||||||
|
void Opened(){}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using Robust.Client.Graphics.Drawing;
|
using Robust.Client.Graphics.Drawing;
|
||||||
using Robust.Client.Graphics.Shaders;
|
using Robust.Client.Graphics.Shaders;
|
||||||
@@ -106,15 +106,9 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
|||||||
|
|
||||||
color = new Color(1.0f, 0.0f, 0.0f, _flash ? 1.0f : 0.0f);
|
color = new Color(1.0f, 0.0f, 0.0f, _flash ? 1.0f : 0.0f);
|
||||||
}
|
}
|
||||||
else if (Ratio >= 1.0f)
|
|
||||||
{
|
|
||||||
color = new Color(0f, 1f, 0f);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// lerp
|
color = DoAfterHelpers.GetProgressColor(Ratio);
|
||||||
var hue = (5f / 18f) * Ratio;
|
|
||||||
color = Color.FromHsv((hue, 1f, 0.75f, 1f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handle.UseShader(_shader);
|
handle.UseShader(_shader);
|
||||||
@@ -128,4 +122,18 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
|
|||||||
handle.DrawRect(box, color);
|
handle.DrawRect(box, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class DoAfterHelpers
|
||||||
|
{
|
||||||
|
public static Color GetProgressColor(float progress)
|
||||||
|
{
|
||||||
|
if (progress >= 1.0f)
|
||||||
|
{
|
||||||
|
return new Color(0f, 1f, 0f);
|
||||||
|
}
|
||||||
|
// lerp
|
||||||
|
var hue = (5f / 18f) * progress;
|
||||||
|
return Color.FromHsv((hue, 1f, 0.75f, 1f));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.Mobs.Roles;
|
||||||
|
using Content.Shared.GameObjects.Components.Actor;
|
||||||
|
using Content.Shared.Objectives;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Network;
|
||||||
|
using Robust.Shared.Players;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Actor
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class CharacterInfoComponent : SharedCharacterInfoComponent
|
||||||
|
{
|
||||||
|
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null)
|
||||||
|
{
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case RequestCharacterInfoMessage _:
|
||||||
|
var conditions = new Dictionary<string, List<ConditionInfo>>();
|
||||||
|
var jobTitle = "No Profession";
|
||||||
|
if (Owner.TryGetComponent(out MindComponent? mindComponent))
|
||||||
|
{
|
||||||
|
var mind = mindComponent.Mind;
|
||||||
|
|
||||||
|
if (mind != null)
|
||||||
|
{
|
||||||
|
// getting conditions
|
||||||
|
foreach (var objective in mind.AllObjectives)
|
||||||
|
{
|
||||||
|
if (!conditions.ContainsKey(objective.Issuer))
|
||||||
|
conditions[objective.Issuer] = new List<ConditionInfo>();
|
||||||
|
foreach (var condition in objective.Conditions)
|
||||||
|
{
|
||||||
|
conditions[objective.Issuer].Add(new ConditionInfo(condition.GetTitle(),
|
||||||
|
condition.GetDescription(), condition.GetIcon(), condition.GetProgress(mindComponent.Mind)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getting jobtitle
|
||||||
|
foreach (var role in mind.AllRoles)
|
||||||
|
{
|
||||||
|
if (role.GetType() == typeof(Job))
|
||||||
|
{
|
||||||
|
jobTitle = role.Name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SendNetworkMessage(new CharacterInfoMessage(jobTitle, conditions));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.ContainerExt
|
||||||
|
{
|
||||||
|
public static class ContainerExt
|
||||||
|
{
|
||||||
|
public static int CountPrototypeOccurencesRecursive(this ContainerManagerComponent mgr, string prototypeId)
|
||||||
|
{
|
||||||
|
int total = 0;
|
||||||
|
foreach (var container in mgr.GetAllContainers())
|
||||||
|
{
|
||||||
|
foreach (var entity in container.ContainedEntities)
|
||||||
|
{
|
||||||
|
if (entity.Prototype?.ID == prototypeId) total++;
|
||||||
|
if(!entity.TryGetComponent<ContainerManagerComponent>(out var component)) continue;
|
||||||
|
total += component.CountPrototypeOccurencesRecursive(prototypeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@ using Robust.Shared.IoC;
|
|||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Timers;
|
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"SubFloorHide",
|
"SubFloorHide",
|
||||||
"LowWall",
|
"LowWall",
|
||||||
"ReinforcedWall",
|
"ReinforcedWall",
|
||||||
"CharacterInfo",
|
|
||||||
"InteractionOutline",
|
"InteractionOutline",
|
||||||
"MeleeWeaponArcAnimation",
|
"MeleeWeaponArcAnimation",
|
||||||
"AnimationsTest",
|
"AnimationsTest",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.Mobs.Roles;
|
using Content.Server.Mobs.Roles;
|
||||||
|
using Content.Server.Objectives;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
@@ -27,6 +28,8 @@ namespace Content.Server.Mobs
|
|||||||
{
|
{
|
||||||
private readonly ISet<Role> _roles = new HashSet<Role>();
|
private readonly ISet<Role> _roles = new HashSet<Role>();
|
||||||
|
|
||||||
|
private readonly List<ObjectivePrototype> _objectives = new List<ObjectivePrototype>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the new mind attached to a specific player session.
|
/// Creates the new mind attached to a specific player session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -74,6 +77,12 @@ namespace Content.Server.Mobs
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IEnumerable<Role> AllRoles => _roles;
|
public IEnumerable<Role> AllRoles => _roles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An enumerable over all the objectives this mind has.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public IEnumerable<ObjectivePrototype> AllObjectives => _objectives;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The session of the player owning this mind.
|
/// The session of the player owning this mind.
|
||||||
/// Can be null, in which case the player is currently not logged in.
|
/// Can be null, in which case the player is currently not logged in.
|
||||||
@@ -144,6 +153,32 @@ namespace Content.Server.Mobs
|
|||||||
return _roles.Any(role => role.GetType() == t);
|
return _roles.Any(role => role.GetType() == t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an objective to this mind.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryAddObjective(ObjectivePrototype objective)
|
||||||
|
{
|
||||||
|
if (!objective.CanBeAssigned(this))
|
||||||
|
return false;
|
||||||
|
_objectives.Add(objective);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes an objective to this mind.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns true if the removal succeeded.</returns>
|
||||||
|
public bool TryRemoveObjective(int index)
|
||||||
|
{
|
||||||
|
if (_objectives.Count >= index) return false;
|
||||||
|
|
||||||
|
var objective = _objectives[index];
|
||||||
|
_objectives.Remove(objective);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transfer this mind's control over to a new entity.
|
/// Transfer this mind's control over to a new entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
139
Content.Server/Objectives/Commands.cs
Normal file
139
Content.Server/Objectives/Commands.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Administration;
|
||||||
|
using Content.Server.Players;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Robust.Server.Interfaces.Console;
|
||||||
|
using Robust.Server.Interfaces.Player;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives
|
||||||
|
{
|
||||||
|
[AdminCommand(AdminFlags.Admin)]
|
||||||
|
public class AddObjectiveCommand : IClientCommand
|
||||||
|
{
|
||||||
|
public string Command => "addobjective";
|
||||||
|
public string Description => "Adds an objective to the player's mind.";
|
||||||
|
public string Help => "addobjective <username> <objectiveID>";
|
||||||
|
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length != 2)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Expected exactly 2 arguments.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mgr = IoCManager.Resolve<IPlayerManager>();
|
||||||
|
if (!mgr.TryGetPlayerDataByUsername(args[0], out var data))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Can't find the playerdata.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var mind = data.ContentData()?.Mind;
|
||||||
|
if (mind == null)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Can't find the mind.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IoCManager.Resolve<IPrototypeManager>()
|
||||||
|
.TryIndex<ObjectivePrototype>(args[1], out var objectivePrototype))
|
||||||
|
{
|
||||||
|
shell.SendText(player, $"Can't find matching ObjectivePrototype {objectivePrototype}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mind.TryAddObjective(objectivePrototype))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Objective requirements dont allow that objective to be added.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AdminCommand(AdminFlags.Admin)]
|
||||||
|
public class ListObjectivesCommand : IClientCommand
|
||||||
|
{
|
||||||
|
public string Command => "lsobjectives";
|
||||||
|
public string Description => "Lists all objectives in a players mind.";
|
||||||
|
public string Help => "lsobjectives [<username>]";
|
||||||
|
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||||
|
{
|
||||||
|
IPlayerData? data;
|
||||||
|
if (args.Length == 0 && player != null)
|
||||||
|
{
|
||||||
|
data = player.Data;
|
||||||
|
}
|
||||||
|
else if (player == null || !IoCManager.Resolve<IPlayerManager>().TryGetPlayerDataByUsername(args[0], out data))
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Can't find the playerdata.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mind = data.ContentData()?.Mind;
|
||||||
|
if (mind == null)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Can't find the mind.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shell.SendText(player, $"Objectives for player {data.UserId}:");
|
||||||
|
var objectives = mind.AllObjectives.ToList();
|
||||||
|
if (objectives.Count == 0)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "None.");
|
||||||
|
}
|
||||||
|
for (var i = 0; i < objectives.Count; i++)
|
||||||
|
{
|
||||||
|
shell.SendText(player, $"- [{i}] {objectives[i]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AdminCommand(AdminFlags.Admin)]
|
||||||
|
public class RemoveObjectiveCommand : IClientCommand
|
||||||
|
{
|
||||||
|
public string Command => "rmobjective";
|
||||||
|
public string Description => "Removes an objective from the player's mind.";
|
||||||
|
public string Help => "rmobjective <username> <index>";
|
||||||
|
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length != 2)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Expected exactly 2 arguments.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mgr = IoCManager.Resolve<IPlayerManager>();
|
||||||
|
if (mgr.TryGetPlayerDataByUsername(args[0], out var data))
|
||||||
|
{
|
||||||
|
var mind = data.ContentData()?.Mind;
|
||||||
|
if (mind == null)
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Can't find the mind.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int.TryParse(args[1], out var i))
|
||||||
|
{
|
||||||
|
shell.SendText(player,
|
||||||
|
mind.TryRemoveObjective(i)
|
||||||
|
? "Objective successfully removed!"
|
||||||
|
: "Objective removing failed. Maybe the index is out of bounds? Check lsobjectives!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shell.SendText(player, $"Invalid index {args[1]}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shell.SendText(player, "Can't find the playerdata.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
57
Content.Server/Objectives/Conditions/StealCondition.cs
Normal file
57
Content.Server/Objectives/Conditions/StealCondition.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#nullable enable
|
||||||
|
using Content.Server.GameObjects.Components.ContainerExt;
|
||||||
|
using Content.Server.Mobs;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Log;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives.Conditions
|
||||||
|
{
|
||||||
|
public class StealCondition : IObjectiveCondition
|
||||||
|
{
|
||||||
|
public string PrototypeId { get; private set; } = default!;
|
||||||
|
public int Amount { get; private set; }
|
||||||
|
|
||||||
|
public void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
serializer.DataField(this, x => x.PrototypeId, "prototype", "");
|
||||||
|
serializer.DataField(this, x => x.Amount, "amount", 1);
|
||||||
|
|
||||||
|
if (Amount < 1)
|
||||||
|
{
|
||||||
|
Logger.Error("StealCondition has an amount less than 1 ({0})", Amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string PrototypeName =>
|
||||||
|
IoCManager.Resolve<IPrototypeManager>().TryIndex<EntityPrototype>(PrototypeId, out var prototype)
|
||||||
|
? prototype.Name
|
||||||
|
: "[CANNOT FIND NAME]";
|
||||||
|
|
||||||
|
public string GetTitle() => Loc.GetString("Steal {0} {1}", Amount > 1 ? $"{Amount}x" : "", Loc.GetString(PrototypeName));
|
||||||
|
|
||||||
|
public string GetDescription() => Loc.GetString("We need you to steal {0}. Don't get caught.", Loc.GetString(PrototypeName));
|
||||||
|
|
||||||
|
public SpriteSpecifier GetIcon()
|
||||||
|
{
|
||||||
|
return new SpriteSpecifier.EntityPrototype(PrototypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetProgress(Mind? mind)
|
||||||
|
{
|
||||||
|
if (mind?.OwnedEntity == null) return 0f;
|
||||||
|
if (!mind.OwnedEntity.TryGetComponent<ContainerManagerComponent>(out var containerManagerComponent)) return 0f;
|
||||||
|
|
||||||
|
float count = containerManagerComponent.CountPrototypeOccurencesRecursive(PrototypeId);
|
||||||
|
return count/Amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetDifficulty() => 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
Content.Server/Objectives/Interfaces/IObjectiveCondition.cs
Normal file
35
Content.Server/Objectives/Interfaces/IObjectiveCondition.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using Content.Server.Mobs;
|
||||||
|
using Robust.Shared.Interfaces.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives.Interfaces
|
||||||
|
{
|
||||||
|
public interface IObjectiveCondition : IExposeData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the title of the condition.
|
||||||
|
/// </summary>
|
||||||
|
string GetTitle();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the description of the condition.
|
||||||
|
/// </summary>
|
||||||
|
string GetDescription();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a SpriteSpecifier to be used as an icon for the condition.
|
||||||
|
/// </summary>
|
||||||
|
SpriteSpecifier GetIcon();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current progress of the condition in %.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Current progress in %.</returns>
|
||||||
|
float GetProgress(Mind mind);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a difficulty of the condition.
|
||||||
|
/// </summary>
|
||||||
|
float GetDifficulty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Content.Server.Mobs;
|
||||||
|
using Robust.Shared.Interfaces.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives.Interfaces
|
||||||
|
{
|
||||||
|
public interface IObjectiveRequirement : IExposeData
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether or not the entity & its surroundings are valid to be given the objective.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns true if objective can be given.</returns>
|
||||||
|
bool CanBeAssigned(Mind mind);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Content.Server/Objectives/Interfaces/IObjectivesManager.cs
Normal file
17
Content.Server/Objectives/Interfaces/IObjectivesManager.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Content.Server.Mobs;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives.Interfaces
|
||||||
|
{
|
||||||
|
public interface IObjectivesManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all objectives the provided mind is valid for.
|
||||||
|
/// </summary>
|
||||||
|
ObjectivePrototype[] GetAllPossibleObjectives(Mind mind);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a randomly picked (no pop) collection of objectives the provided mind is valid for.
|
||||||
|
/// </summary>
|
||||||
|
ObjectivePrototype[] GetRandomObjectives(Mind mind, float maxDifficulty = 3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
60
Content.Server/Objectives/ObjectivePrototype.cs
Normal file
60
Content.Server/Objectives/ObjectivePrototype.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Mobs;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
using YamlDotNet.RepresentationModel;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives
|
||||||
|
{
|
||||||
|
[Prototype("objective")]
|
||||||
|
public class ObjectivePrototype : IPrototype, IIndexedPrototype
|
||||||
|
{
|
||||||
|
[ViewVariables]
|
||||||
|
public string ID { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string Issuer { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public float Probability { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public IReadOnlyList<IObjectiveCondition> Conditions => _conditions;
|
||||||
|
[ViewVariables]
|
||||||
|
public IReadOnlyList<IObjectiveRequirement> Requirements => _requirements;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public float Difficulty => _difficultyOverride ?? _conditions.Sum(c => c.GetDifficulty());
|
||||||
|
|
||||||
|
private List<IObjectiveCondition> _conditions = new List<IObjectiveCondition>();
|
||||||
|
private List<IObjectiveRequirement> _requirements = new List<IObjectiveRequirement>();
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
private float? _difficultyOverride = null;
|
||||||
|
|
||||||
|
public bool CanBeAssigned(Mind mind)
|
||||||
|
{
|
||||||
|
foreach (var requirement in _requirements)
|
||||||
|
{
|
||||||
|
if (!requirement.CanBeAssigned(mind)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadFrom(YamlMappingNode mapping)
|
||||||
|
{
|
||||||
|
var ser = YamlObjectSerializer.NewReader(mapping);
|
||||||
|
|
||||||
|
ser.DataField(this, x => x.ID, "id", string.Empty);
|
||||||
|
ser.DataField(this, x => x.Issuer, "issuer", "Unknown");
|
||||||
|
ser.DataField(this, x => x.Probability, "prob", 0.3f);
|
||||||
|
ser.DataField(this, x => x._conditions, "conditions", new List<IObjectiveCondition>());
|
||||||
|
ser.DataField(this, x => x._requirements, "requirements", new List<IObjectiveRequirement>());
|
||||||
|
ser.DataField(this, x => x._difficultyOverride, "difficultyOverride", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Content.Server/Objectives/ObjectivesManager.cs
Normal file
53
Content.Server/Objectives/ObjectivesManager.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Mobs;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Robust.Shared.Interfaces.Random;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives
|
||||||
|
{
|
||||||
|
public class ObjectivesManager : IObjectivesManager
|
||||||
|
{
|
||||||
|
[Dependency] private IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private IRobustRandom _random = default!;
|
||||||
|
|
||||||
|
public ObjectivePrototype[] GetAllPossibleObjectives(Mind mind)
|
||||||
|
{
|
||||||
|
return _prototypeManager.EnumeratePrototypes<ObjectivePrototype>().Where(objectivePrototype => objectivePrototype.CanBeAssigned(mind)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectivePrototype[] GetRandomObjectives(Mind mind, float maxDifficulty = 3)
|
||||||
|
{
|
||||||
|
var objectives = GetAllPossibleObjectives(mind);
|
||||||
|
|
||||||
|
//to prevent endless loops
|
||||||
|
if(objectives.Length == 0 || objectives.Sum(o => o.Difficulty) == 0f) return objectives;
|
||||||
|
|
||||||
|
var result = new List<ObjectivePrototype>();
|
||||||
|
var currentDifficulty = 0f;
|
||||||
|
_random.Shuffle(objectives);
|
||||||
|
while (currentDifficulty < maxDifficulty)
|
||||||
|
{
|
||||||
|
foreach (var objective in objectives)
|
||||||
|
{
|
||||||
|
if (!_random.Prob(objective.Probability)) continue;
|
||||||
|
|
||||||
|
result.Add(objective);
|
||||||
|
currentDifficulty += objective.Difficulty;
|
||||||
|
if (currentDifficulty >= maxDifficulty) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentDifficulty > maxDifficulty) //will almost always happen
|
||||||
|
{
|
||||||
|
result.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Content.Server.Mobs;
|
||||||
|
using Content.Server.Mobs.Roles.Suspicion;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Server.Objectives.Requirements
|
||||||
|
{
|
||||||
|
public class SuspicionTraitorRequirement : IObjectiveRequirement
|
||||||
|
{
|
||||||
|
public void ExposeData(ObjectSerializer serializer){}
|
||||||
|
|
||||||
|
public bool CanBeAssigned(Mind mind)
|
||||||
|
{
|
||||||
|
return mind.HasRole<SuspicionTraitorRole>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ using Content.Server.Interfaces;
|
|||||||
using Content.Server.Interfaces.Chat;
|
using Content.Server.Interfaces.Chat;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Interfaces.PDA;
|
using Content.Server.Interfaces.PDA;
|
||||||
|
using Content.Server.Objectives;
|
||||||
|
using Content.Server.Objectives.Interfaces;
|
||||||
using Content.Server.PDA;
|
using Content.Server.PDA;
|
||||||
using Content.Server.Preferences;
|
using Content.Server.Preferences;
|
||||||
using Content.Server.Sandbox;
|
using Content.Server.Sandbox;
|
||||||
@@ -49,6 +51,7 @@ namespace Content.Server
|
|||||||
IoCManager.Register<ConsiderationsManager, ConsiderationsManager>();
|
IoCManager.Register<ConsiderationsManager, ConsiderationsManager>();
|
||||||
IoCManager.Register<IAccentManager, AccentManager>();
|
IoCManager.Register<IAccentManager, AccentManager>();
|
||||||
IoCManager.Register<IConnectionManager, ConnectionManager>();
|
IoCManager.Register<IConnectionManager, ConnectionManager>();
|
||||||
|
IoCManager.Register<IObjectivesManager, ObjectivesManager>();
|
||||||
IoCManager.Register<IAdminManager, AdminManager>();
|
IoCManager.Register<IAdminManager, AdminManager>();
|
||||||
IoCManager.Register<IDeviceNetwork, DeviceNetwork>();
|
IoCManager.Register<IDeviceNetwork, DeviceNetwork>();
|
||||||
IoCManager.Register<EuiManager, EuiManager>();
|
IoCManager.Register<EuiManager, EuiManager>();
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Shared.Objectives;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components.Actor
|
||||||
|
{
|
||||||
|
public class SharedCharacterInfoComponent : Component
|
||||||
|
{
|
||||||
|
public override string Name => "CharacterInfo";
|
||||||
|
public override uint? NetID => ContentNetIDs.CHARACTERINFO;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
protected class RequestCharacterInfoMessage : ComponentMessage
|
||||||
|
{
|
||||||
|
public RequestCharacterInfoMessage()
|
||||||
|
{
|
||||||
|
Directed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
protected class CharacterInfoMessage : ComponentMessage
|
||||||
|
{
|
||||||
|
public readonly Dictionary<string, List<ConditionInfo>> Objectives;
|
||||||
|
public readonly string JobTitle;
|
||||||
|
|
||||||
|
public CharacterInfoMessage(string jobTitle, Dictionary<string, List<ConditionInfo>> objectives)
|
||||||
|
{
|
||||||
|
Directed = true;
|
||||||
|
JobTitle = jobTitle;
|
||||||
|
Objectives = objectives;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -84,6 +84,7 @@
|
|||||||
public const uint PULLABLE = 1078;
|
public const uint PULLABLE = 1078;
|
||||||
public const uint GAS_TANK = 1079;
|
public const uint GAS_TANK = 1079;
|
||||||
public const uint SINGULARITY = 1080;
|
public const uint SINGULARITY = 1080;
|
||||||
|
public const uint CHARACTERINFO = 1081;
|
||||||
|
|
||||||
// Net IDs for integration tests.
|
// Net IDs for integration tests.
|
||||||
public const uint PREDICTION_TEST = 10001;
|
public const uint PREDICTION_TEST = 10001;
|
||||||
|
|||||||
23
Content.Shared/Objectives/ConditionInfo.cs
Normal file
23
Content.Shared/Objectives/ConditionInfo.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Shared.Objectives
|
||||||
|
{
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class ConditionInfo
|
||||||
|
{
|
||||||
|
public string Title { get; }
|
||||||
|
public string Description { get; }
|
||||||
|
public SpriteSpecifier SpriteSpecifier { get; }
|
||||||
|
public float Progress { get; }
|
||||||
|
|
||||||
|
public ConditionInfo(string title, string description, SpriteSpecifier spriteSpecifier, float progress)
|
||||||
|
{
|
||||||
|
Title = title;
|
||||||
|
Description = description;
|
||||||
|
SpriteSpecifier = spriteSpecifier;
|
||||||
|
Progress = progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Resources/Prototypes/Objectives/traitorObjectives.yml
Normal file
9
Resources/Prototypes/Objectives/traitorObjectives.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- type: objective
|
||||||
|
id: SoapDeluxeStealObjective
|
||||||
|
prob: 0.3
|
||||||
|
issuer: The Syndicate
|
||||||
|
requirements:
|
||||||
|
- !type:SuspicionTraitorRequirement {}
|
||||||
|
conditions:
|
||||||
|
- !type:StealCondition
|
||||||
|
prototype: SoapDeluxe
|
||||||
Reference in New Issue
Block a user