--- /dev/null
+using Content.Shared.Thief;
+using JetBrains.Annotations;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.Thief;
+
+[UsedImplicitly]
+public sealed class ThiefBackpackBoundUserInterface : BoundUserInterface
+{
+ private ThiefBackpackMenu? _window;
+
+ public ThiefBackpackBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { }
+
+ protected override void Open()
+ {
+ base.Open();
+
+ _window = new ThiefBackpackMenu(this);
+ _window.OnClose += Close;
+ _window.OpenCentered();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (!disposing)
+ return;
+
+ _window?.Dispose();
+ _window = null;
+ }
+
+ protected override void UpdateState(BoundUserInterfaceState state)
+ {
+ base.UpdateState(state);
+
+ if (state is not ThiefBackpackBoundUserInterfaceState current)
+ return;
+
+ _window?.UpdateState(current);
+ }
+
+ public void SendChangeSelected(int setNumber)
+ {
+ SendMessage(new ThiefBackpackChangeSetMessage(setNumber));
+ }
+
+ public void SendApprove()
+ {
+ SendMessage(new ThiefBackpackApproveMessage());
+ }
+}
--- /dev/null
+<controls:FancyWindow xmlns="https://spacestation14.io"
+ xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
+ xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
+ Title="{Loc 'thief-backpack-window-title'}"
+ MinSize="700 700">
+ <BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
+ <!-- First Informational panel -->
+ <Label Text="{Loc 'thief-backpack-window-description'}" Margin="5 5"/>
+ <controls:HLine Color="#404040" Thickness="2" Margin="0 5"/>
+ <Label Name="SelectedSets" Text="{Loc 'thief-backpack-window-selected'}" Margin="5 5"/>
+
+ <!-- Second sets panel -->
+ <PanelContainer Margin="5 5">
+ <PanelContainer.PanelOverride>
+ <gfx:StyleBoxFlat BackgroundColor="#050505" />
+ </PanelContainer.PanelOverride>
+ <ScrollContainer
+ HScrollEnabled="False"
+ MinSize="0 600"
+ SizeFlagsStretchRatio="2"
+ VerticalExpand="True">
+ <BoxContainer Name="SetsGrid" Orientation="Vertical" MinSize="460 200">
+ <!-- Sets is filled by code -->
+
+ </BoxContainer>
+ </ScrollContainer>
+ </PanelContainer>
+
+ <!-- Third approve button panel -->
+ <PanelContainer Margin="10">
+ <Button Name="ApproveButton"
+ Text="{Loc 'thief-backpack-window-approve-button'}"
+ Margin="0 5"
+ Access="Public"
+ HorizontalAlignment ="Right"
+ StyleClasses="OpenRight"/>
+ </PanelContainer>
+ </BoxContainer>
+</controls:FancyWindow>
--- /dev/null
+using Content.Client.UserInterface.Controls;
+using Content.Shared.Thief;
+using Robust.Client.AutoGenerated;
+using Robust.Client.GameObjects;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.Thief;
+
+[GenerateTypedNameReferences]
+public sealed partial class ThiefBackpackMenu : FancyWindow
+{
+ [Dependency] private readonly IEntitySystemManager _sysMan = default!;
+ private readonly SpriteSystem _spriteSystem;
+
+ private readonly ThiefBackpackBoundUserInterface _owner;
+
+ public ThiefBackpackMenu(ThiefBackpackBoundUserInterface owner)
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+ _spriteSystem = _sysMan.GetEntitySystem<SpriteSystem>();
+
+ _owner = owner;
+
+ ApproveButton.OnButtonDown += (args) =>
+ {
+ _owner.SendApprove();
+ };
+ }
+
+ public void UpdateState(ThiefBackpackBoundUserInterfaceState state)
+ {
+ SetsGrid.RemoveAllChildren();
+ int count = 0;
+ int selectedNumber = 0;
+ foreach (var set in state.Sets)
+ {
+ var child = new ThiefBackpackSet(set.Value, _spriteSystem);
+
+ child.SetButton.OnButtonDown += (args) =>
+ {
+ _owner.SendChangeSelected(set.Key);
+ };
+
+ SetsGrid.AddChild(child);
+
+ count++;
+
+ if (set.Value.Selected)
+ selectedNumber++;
+ }
+
+ SelectedSets.Text = Loc.GetString("thief-backpack-window-selected", ("selectedCount", selectedNumber), ("maxCount", state.MaxSelectedSets));
+ ApproveButton.Disabled = selectedNumber == state.MaxSelectedSets ? false : true;
+ }
+}
--- /dev/null
+<Control xmlns="https://spacestation14.io"
+ xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
+ xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client">
+ <!-- Name and button -->
+ <PanelContainer Margin="5 5 0 5">
+ <PanelContainer.PanelOverride>
+ <gfx:StyleBoxFlat BackgroundColor="#18211b" />
+ </PanelContainer.PanelOverride>
+ <BoxContainer Orientation="Vertical" HorizontalExpand="True">
+ <GridContainer Margin="5" Columns="2" MinSize="600 0">
+ <Label Name="SetName" Text="Set" StyleClasses="StatusFieldTitle"></Label>
+ <Button Margin="0 10" Name="SetButton" Text="Select" StyleClasses="OpenRight" Access="Public" HorizontalAlignment="Right"/>
+ </GridContainer>
+ <controls:HLine Color="#404040" Thickness="1" Margin="0 5"/>
+ <!-- Icon and Description -->
+ <GridContainer Margin="0 5" Columns="2">
+ <TextureRect Name="Icon" Margin="10" Stretch="KeepAspectCentered"
+ VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="64 64"/>
+ <Label Name="SetDescription" Text="Description"></Label>
+ </GridContainer>
+ </BoxContainer>
+ </PanelContainer>
+</Control>
--- /dev/null
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.XAML;
+using Content.Shared.Thief;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.Thief;
+
+[GenerateTypedNameReferences]
+public sealed partial class ThiefBackpackSet : Control
+{
+ public ThiefBackpackSet(ThiefBackpackSetInfo set, SpriteSystem spriteSystem)
+ {
+ RobustXamlLoader.Load(this);
+
+ Icon.Texture = spriteSystem.Frame0(set.Sprite);
+ SetName.Text = Loc.GetString(set.Name);
+ SetDescription.Text = Loc.GetString(set.Description);
+ SetButton.Text = Loc.GetString(set.Selected ? "thief-backpack-button-deselect" : "thief-backpack-button-select");
+ SetButton.ModulateSelfOverride = set.Selected ? new Color(40, 84, 35) : new Color(68, 75, 103);
+ }
+}
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
+using Content.Server.StationEvents.Events;
using Content.Server.Zombies;
using Content.Shared.Administration;
using Content.Shared.Database;
public sealed partial class AdminVerbSystem
{
[Dependency] private readonly ZombieSystem _zombie = default!;
+ [Dependency] private readonly ThiefRuleSystem _thief = default!;
[Dependency] private readonly TraitorRuleSystem _traitorRule = default!;
[Dependency] private readonly NukeopsRuleSystem _nukeopsRule = default!;
[Dependency] private readonly PiratesRuleSystem _piratesRule = default!;
Message = Loc.GetString("admin-verb-make-head-rev"),
};
args.Verbs.Add(headRev);
+
+ Verb thief = new()
+ {
+ Text = Loc.GetString("admin-verb-text-make-thief"),
+ Category = VerbCategory.Antag,
+ Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Clothing/Hands/Gloves/ihscombat.rsi"), "icon"),
+ Act = () =>
+ {
+ if (!_minds.TryGetSession(targetMindComp.Mind, out var session))
+ return;
+
+ _thief.MakeThief(session);
+ },
+ Impact = LogImpact.High,
+ Message = Loc.GetString("admin-verb-make-thief"),
+ };
+ args.Verbs.Add(thief);
}
}
using Robust.Server.Containers;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
+using Content.Server.Shuttles.Components;
namespace Content.Server.Antag;
}
}
+ /// <summary>
+ /// The function walks through all players, checking their role and preferences to generate a list of players who can become antagonists.
+ /// </summary>
+ /// <param name="candidates">a list of players to check out</param>
+ /// <param name="antagPreferenceId">antagonist's code id</param>
+ /// <returns></returns>
+ public List<ICommonSession> FindPotentialAntags(in Dictionary<ICommonSession, HumanoidCharacterProfile> candidates, string antagPreferenceId)
+ {
+ var list = new List<ICommonSession>();
+ var pendingQuery = GetEntityQuery<PendingClockInComponent>();
+
+ foreach (var player in candidates.Keys)
+ {
+ // Role prevents antag.
+ if (!_jobs.CanBeAntag(player))
+ continue;
+
+ // Latejoin
+ if (player.AttachedEntity != null && pendingQuery.HasComponent(player.AttachedEntity.Value))
+ continue;
+
+ list.Add(player);
+ }
+
+ var prefList = new List<ICommonSession>();
+
+ foreach (var player in list)
+ {
+ //player preferences to play as this antag
+ var profile = candidates[player];
+ if (profile.AntagPreferences.Contains(antagPreferenceId))
+ {
+ prefList.Add(player);
+ }
+ }
+ if (prefList.Count == 0)
+ {
+ Log.Info($"Insufficient preferred antag:{antagPreferenceId}, picking at random.");
+ prefList = list;
+ }
+ return prefList;
+ }
+
+ /// <summary>
+ /// selects the specified number of players from the list
+ /// </summary>
+ /// <param name="antagCount">how many players to take</param>
+ /// <param name="prefList">a list of players from which to draw</param>
+ /// <returns></returns>
+ public List<ICommonSession> PickAntag(int antagCount, List<ICommonSession> prefList)
+ {
+ var results = new List<ICommonSession>(antagCount);
+ if (prefList.Count == 0)
+ {
+ Log.Info("Insufficient ready players to fill up with antags, stopping the selection.");
+ return results;
+ }
+
+ for (var i = 0; i < antagCount; i++)
+ {
+ results.Add(_random.PickAndTake(prefList));
+ Log.Info("Selected a preferred antag.");
+ }
+ return results;
+ }
+
/// <summary>
/// Will take a group of entities and check if they are all alive or dead
/// </summary>
--- /dev/null
+using Robust.Shared.Audio;
+using Robust.Shared.Prototypes;
+using Content.Shared.Roles;
+using Robust.Shared.Player;
+using Content.Shared.Preferences;
+
+namespace Content.Server.GameTicking.Rules.Components;
+
+/// <summary>
+/// Stores data for <see cref="ThiefRuleSystem/">.
+/// </summary>
+[RegisterComponent, Access(typeof(ThiefRuleSystem))]
+public sealed partial class ThiefRuleComponent : Component
+{
+ /// <summary>
+ /// A chance for this mode to be added to the game.
+ /// </summary>
+ [DataField]
+ public float RuleChance = 1f;
+
+ [DataField]
+ public ProtoId<AntagPrototype> ThiefPrototypeId = "Thief";
+
+ public Dictionary<ICommonSession, HumanoidCharacterProfile> StartCandidates = new();
+
+ [DataField]
+ public float MaxObjectiveDifficulty = 2.5f;
+
+ [DataField]
+ public int MaxStealObjectives = 10;
+
+ /// <summary>
+ /// Things that will be given to thieves
+ /// </summary>
+ [DataField]
+ public List<EntProtoId> StarterItems = new List<EntProtoId> { "ToolboxThief", "ClothingHandsChameleonThief" }; //TO DO - replace to chameleon thieving gloves whem merg
+
+ /// <summary>
+ /// All Thiefes created by this rule
+ /// </summary>
+ public readonly List<EntityUid> ThiefMinds = new();
+
+ /// <summary>
+ /// Max Thiefs created by rule on roundstart
+ /// </summary>
+ [DataField]
+ public int MaxAllowThief = 3;
+
+ /// <summary>
+ /// Sound played when making the player a thief via antag control or ghost role
+ /// </summary>
+ [DataField]
+ public SoundSpecifier? GreetingSound = new SoundPathSpecifier("/Audio/Misc/thief_greeting.ogg");
+}
--- /dev/null
+using Content.Server.Chat.Managers;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Server.Mind;
+using Content.Server.Objectives;
+using Content.Server.Shuttles.Components;
+using Content.Server.Roles;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Components;
+using Content.Shared.Preferences;
+using Content.Shared.Roles;
+using Content.Shared.Roles.Jobs;
+using Robust.Shared.Player;
+using Robust.Shared.Random;
+using Robust.Shared.Prototypes;
+using System.Linq;
+using Content.Shared.Humanoid;
+using Content.Server.Antag;
+using Robust.Server.Audio;
+
+namespace Content.Server.GameTicking.Rules;
+
+public sealed class ThiefRuleSystem : GameRuleSystem<ThiefRuleComponent>
+{
+ [Dependency] private readonly IChatManager _chatManager = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly AntagSelectionSystem _antagSelection = default!;
+ [Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly MindSystem _mindSystem = default!;
+ [Dependency] private readonly SharedRoleSystem _roleSystem = default!;
+ [Dependency] private readonly SharedJobSystem _jobs = default!;
+ [Dependency] private readonly ObjectivesSystem _objectives = default!;
+
+ const string bigObjectiveGroup = "ThiefBigObjectiveGroups";
+ const string smallObjectiveGroup = "ThiefObjectiveGroups";
+ const string escapeObjectiveGroup = "ThiefEscapeObjectiveGroups";
+
+ private const float BigObjectiveChance = 0.7f;
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<RulePlayerJobsAssignedEvent>(OnPlayersSpawned);
+
+ SubscribeLocalEvent<ThiefRoleComponent, GetBriefingEvent>(OnGetBriefing);
+ SubscribeLocalEvent<ThiefRuleComponent, ObjectivesTextGetInfoEvent>(OnObjectivesTextGetInfo);
+ }
+
+ private void OnPlayersSpawned(RulePlayerJobsAssignedEvent ev)
+ {
+ var query = EntityQueryEnumerator<ThiefRuleComponent, GameRuleComponent>();
+ while (query.MoveNext(out var uid, out var thief, out var gameRule))
+ {
+ //Chance to not lauch gamerule
+ if (!_random.Prob(thief.RuleChance))
+ {
+ RemComp<ThiefRuleComponent>(uid);
+ continue;
+ }
+
+ if (!GameTicker.IsGameRuleAdded(uid, gameRule))
+ continue;
+
+ foreach (var player in ev.Players)
+ {
+ if (!ev.Profiles.ContainsKey(player.UserId))
+ continue;
+
+ thief.StartCandidates[player] = ev.Profiles[player.UserId];
+ }
+ DoThiefStart(thief);
+ }
+ }
+
+ private void DoThiefStart(ThiefRuleComponent component)
+ {
+ if (!component.StartCandidates.Any())
+ {
+ Log.Error("There are no players who can become thieves.");
+ return;
+ }
+
+ var startThiefCount = Math.Min(component.MaxAllowThief, component.StartCandidates.Count);
+ var thiefPool = _antagSelection.FindPotentialAntags(component.StartCandidates, component.ThiefPrototypeId);
+ //TO DO: When voxes specifies are added, increase their chance of becoming a thief by 4 times >:)
+ var selectedThieves = _antagSelection.PickAntag(_random.Next(1, startThiefCount), thiefPool);
+
+ foreach(var thief in selectedThieves)
+ {
+ MakeThief(thief);
+ }
+ }
+
+ public bool MakeThief(ICommonSession thief)
+ {
+ var thiefRule = EntityQuery<ThiefRuleComponent>().FirstOrDefault();
+ if (thiefRule == null)
+ {
+ GameTicker.StartGameRule("Thief", out var ruleEntity);
+ thiefRule = Comp<ThiefRuleComponent>(ruleEntity);
+ }
+
+ //checks
+ if (!_mindSystem.TryGetMind(thief, out var mindId, out var mind))
+ {
+ Log.Info("Failed getting mind for picked thief.");
+ return false;
+ }
+ if (HasComp<ThiefRoleComponent>(mindId))
+ {
+ Log.Error($"Player {thief.Name} is already a thief.");
+ return false;
+ }
+ if (mind.OwnedEntity is not { } entity)
+ {
+ Log.Error("Mind picked for thief did not have an attached entity.");
+ return false;
+ }
+
+ // Assign thief roles
+ _roleSystem.MindAddRole(mindId, new ThiefRoleComponent
+ {
+ PrototypeId = thiefRule.ThiefPrototypeId
+ });
+
+ // Notificate player about new role assignment
+ if (_mindSystem.TryGetSession(mindId, out var session))
+ {
+ _audio.PlayGlobal(thiefRule.GreetingSound, session);
+ _chatManager.DispatchServerMessage(session, MakeBriefing(mind.OwnedEntity.Value));
+ }
+
+ // Give thieves their objectives
+ var difficulty = 0f;
+
+ if (_random.Prob(BigObjectiveChance)) // 70% chance to 1 big objective (structure or animal)
+ {
+ var objective = _objectives.GetRandomObjective(mindId, mind, bigObjectiveGroup);
+ if (objective != null)
+ {
+ _mindSystem.AddObjective(mindId, mind, objective.Value);
+ difficulty += Comp<ObjectiveComponent>(objective.Value).Difficulty;
+ }
+ }
+
+ for (var i = 0; i < thiefRule.MaxStealObjectives && thiefRule.MaxObjectiveDifficulty > difficulty; i++) // Many small objectives
+ {
+ var objective = _objectives.GetRandomObjective(mindId, mind, smallObjectiveGroup);
+ if (objective == null)
+ continue;
+
+ _mindSystem.AddObjective(mindId, mind, objective.Value);
+ difficulty += Comp<ObjectiveComponent>(objective.Value).Difficulty;
+ }
+
+ //Escape target
+ var escapeObjective = _objectives.GetRandomObjective(mindId, mind, escapeObjectiveGroup);
+ if (escapeObjective != null)
+ _mindSystem.AddObjective(mindId, mind, escapeObjective.Value);
+
+ // Give starting items
+ _antagSelection.GiveAntagBagGear(mind.OwnedEntity.Value, thiefRule.StarterItems);
+
+ thiefRule.ThiefMinds.Add(mindId);
+ return true;
+ }
+
+ //Add mind briefing
+ private void OnGetBriefing(Entity<ThiefRoleComponent> thief, ref GetBriefingEvent args)
+ {
+ if (!TryComp<MindComponent>(thief.Owner, out var mind) || mind.OwnedEntity == null)
+ return;
+
+ args.Append(MakeBriefing(mind.OwnedEntity.Value));
+ }
+
+ private string MakeBriefing(EntityUid thief)
+ {
+ var isHuman = HasComp<HumanoidAppearanceComponent>(thief);
+ var briefing = "\n";
+ briefing = isHuman
+ ? Loc.GetString("thief-role-greeting-human")
+ : Loc.GetString("thief-role-greeting-animal");
+
+ briefing += "\n \n" + Loc.GetString("thief-role-greeting-equipment") + "\n";
+ return briefing;
+ }
+
+ private void OnObjectivesTextGetInfo(Entity<ThiefRuleComponent> thiefs, ref ObjectivesTextGetInfoEvent args)
+ {
+ args.Minds = thiefs.Comp.ThiefMinds;
+ args.AgentName = Loc.GetString("thief-round-end-agent-name");
+ }
+}
using System.Linq;
+using Content.Server.Antag;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Mind;
public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
{
+ [Dependency] private readonly AntagSelectionSystem _antagSelection = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
}
var numTraitors = MathHelper.Clamp(component.StartCandidates.Count / PlayersPerTraitor, 1, MaxTraitors);
- var traitorPool = FindPotentialTraitors(component.StartCandidates, component);
- var selectedTraitors = PickTraitors(numTraitors, traitorPool);
+ var traitorPool = _antagSelection.FindPotentialAntags(component.StartCandidates, component.TraitorPrototypeId);
+ var selectedTraitors = _antagSelection.PickAntag(numTraitors, traitorPool);
foreach (var traitor in selectedTraitors)
{
}
}
- private List<ICommonSession> FindPotentialTraitors(in Dictionary<ICommonSession, HumanoidCharacterProfile> candidates, TraitorRuleComponent component)
- {
- var list = new List<ICommonSession>();
- var pendingQuery = GetEntityQuery<PendingClockInComponent>();
-
- foreach (var player in candidates.Keys)
- {
- // Role prevents antag.
- if (!_jobs.CanBeAntag(player))
- {
- continue;
- }
-
- // Latejoin
- if (player.AttachedEntity != null && pendingQuery.HasComponent(player.AttachedEntity.Value))
- continue;
-
- list.Add(player);
- }
-
- var prefList = new List<ICommonSession>();
-
- foreach (var player in list)
- {
- var profile = candidates[player];
- if (profile.AntagPreferences.Contains(component.TraitorPrototypeId))
- {
- prefList.Add(player);
- }
- }
- if (prefList.Count == 0)
- {
- Log.Info("Insufficient preferred traitors, picking at random.");
- prefList = list;
- }
- return prefList;
- }
-
- private List<ICommonSession> PickTraitors(int traitorCount, List<ICommonSession> prefList)
- {
- var results = new List<ICommonSession>(traitorCount);
- if (prefList.Count == 0)
- {
- Log.Info("Insufficient ready players to fill up with traitors, stopping the selection.");
- return results;
- }
-
- for (var i = 0; i < traitorCount; i++)
- {
- results.Add(_random.PickAndTake(prefList));
- Log.Info("Selected a preferred traitor.");
- }
- return results;
- }
-
public bool MakeTraitor(ICommonSession traitor, bool giveUplink = true, bool giveObjectives = true)
{
var traitorRule = EntityQuery<TraitorRuleComponent>().FirstOrDefault();
--- /dev/null
+using Content.Server.Objectives.Systems;
+using Content.Shared.Humanoid.Prototypes;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.Objectives.Components;
+
+/// <summary>
+/// Requires that the player's species matches a whitelist.
+/// </summary>
+[RegisterComponent, Access(typeof(SpeciesRequirementSystem))]
+public sealed partial class SpeciesRequirementComponent : Component
+{
+ [DataField(required: true), ViewVariables(VVAccess.ReadWrite)]
+ public List<ProtoId<SpeciesPrototype>> AllowedSpecies = new();
+}
using Content.Server.Objectives.Systems;
+using Content.Shared.Objectives;
using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Objectives.Components;
/// <summary>
-/// Requires that you steal a certain item.
+/// Requires that you steal a certain item (or several)
/// </summary>
[RegisterComponent, Access(typeof(StealConditionSystem))]
public sealed partial class StealConditionComponent : Component
{
/// <summary>
- /// The id of the item to steal.
+ /// A group of items to be stolen
/// </summary>
- /// <remarks>
- /// Works by prototype id not tags or anything so it has to be the exact item.
- /// </remarks>
- [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)), ViewVariables(VVAccess.ReadWrite)]
- public string Prototype = string.Empty;
+ [DataField(required: true)]
+ public ProtoId<StealTargetGroupPrototype> StealGroup;
+
+ /// <summary>
+ /// When enabled, disables generation of this target if there is no entity on the map (disable for objects that can be created mid-round).
+ /// </summary>
+ [DataField]
+ public bool VerifyMapExistance = true;
+
+ /// <summary>
+ /// If the target may be alive but has died, it will not be counted
+ /// </summary>
+ [DataField]
+ public bool CheckAlive = false;
+ /// <summary>
+ /// The minimum number of items you need to steal to fulfill a objective
+ /// </summary>
+ [DataField]
+ public int MinCollectionSize = 1;
+
+ /// <summary>
+ /// The maximum number of items you need to steal to fulfill a objective
+ /// </summary>
+ [DataField]
+ public int MaxCollectionSize = 1;
+
+ /// <summary>
+ /// Target collection size after calculation
+ /// </summary>
+ [DataField]
+ public int CollectionSize;
/// <summary>
/// Help newer players by saying e.g. "steal the chief engineer's advanced magboots"
/// instead of "steal advanced magboots. Should be a loc string.
/// </summary>
- [DataField("owner"), ViewVariables(VVAccess.ReadWrite)]
+ [DataField("owner")]
public string? OwnerText;
+
+ // All this need to be loc string
+ [DataField(required: true)]
+ public LocId ObjectiveText;
+ [DataField(required: true)]
+ public LocId ObjectiveNoOwnerText;
+ [DataField(required: true)]
+ public LocId DescriptionText;
+ [DataField(required: true)]
+ public LocId DescriptionMultiplyText;
}
--- /dev/null
+using Content.Server.Objectives.Systems;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+
+namespace Content.Server.Objectives.Components.Targets;
+
+/// <summary>
+/// Allows an object to become the target of a StealCollection objection
+/// </summary>
+[RegisterComponent]
+public sealed partial class StealTargetComponent : Component
+{
+ /// <summary>
+ /// The theft group to which this item belongs.
+ /// </summary>
+ [DataField(required: true), ViewVariables(VVAccess.ReadWrite)]
+ public string StealGroup;
+}
foreach (var objectiveGroup in objectives.GroupBy(o => Comp<ObjectiveComponent>(o).Issuer))
{
+ //TO DO:
+ //check for the right group here. Getting the target issuer is easy: objectiveGroup.Key
+ //It should be compared to the type of the group's issuer.
result += "\n" + Loc.GetString($"objective-issuer-{objectiveGroup.Key}");
foreach (var objective in objectiveGroup)
--- /dev/null
+using Content.Server.Objectives.Components;
+using Content.Shared.Humanoid;
+using Content.Shared.Objectives.Components;
+
+namespace Content.Server.Objectives.Systems;
+
+/// <summary>
+/// Handles species requirement for objectives that require a certain species.
+/// </summary>
+public sealed class SpeciesRequirementSystem : EntitySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<SpeciesRequirementComponent, RequirementCheckEvent>(OnCheck);
+ }
+
+ private void OnCheck(Entity<SpeciesRequirementComponent> requirement, ref RequirementCheckEvent args)
+ {
+ if (args.Cancelled)
+ return;
+
+ if (!TryComp<HumanoidAppearanceComponent>(args.Mind.OwnedEntity, out var appearance)) {
+ args.Cancelled = true;
+ return;
+ }
+ if (!requirement.Comp.AllowedSpecies.Contains(appearance.Species))
+ {
+ args.Cancelled = true;
+ return;
+ }
+ }
+}
using Content.Server.Objectives.Components;
+using Content.Server.Objectives.Components.Targets;
using Content.Shared.Mind;
using Content.Shared.Objectives.Components;
using Content.Shared.Objectives.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
-using Robust.Shared.Utility;
+using Robust.Shared.Random;
+using Content.Shared.Pulling.Components;
+using Content.Shared.Objectives;
+using Content.Shared.Mind.Components;
+using Content.Shared.Mobs.Systems;
+using Content.Shared.Mobs.Components;
namespace Content.Server.Objectives.Systems;
public sealed class StealConditionSystem : EntitySystem
{
+ [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
+ [Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedObjectivesSystem _objectives = default!;
- private EntityQuery<ContainerManagerComponent> containerQuery;
- private EntityQuery<MetaDataComponent> metaQuery;
+ private EntityQuery<ContainerManagerComponent> _containerQuery;
+ private EntityQuery<MetaDataComponent> _metaQuery;
public override void Initialize()
{
base.Initialize();
- containerQuery = GetEntityQuery<ContainerManagerComponent>();
- metaQuery = GetEntityQuery<MetaDataComponent>();
+ _containerQuery = GetEntityQuery<ContainerManagerComponent>();
+ _metaQuery = GetEntityQuery<MetaDataComponent>();
SubscribeLocalEvent<StealConditionComponent, ObjectiveAssignedEvent>(OnAssigned);
SubscribeLocalEvent<StealConditionComponent, ObjectiveAfterAssignEvent>(OnAfterAssign);
SubscribeLocalEvent<StealConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
}
- private void OnAssigned(EntityUid uid, StealConditionComponent comp, ref ObjectiveAssignedEvent args)
+ /// start checks of target acceptability, and generation of start values.
+ private void OnAssigned(Entity<StealConditionComponent> condition, ref ObjectiveAssignedEvent args)
{
- // cancel if the item to steal doesn't exist
- args.Cancelled |= !_proto.HasIndex<EntityPrototype>(comp.Prototype);
+ List<StealTargetComponent?> targetList = new();
+
+ // cancel if invalid TargetStealName
+ var group = _proto.Index<StealTargetGroupPrototype>(condition.Comp.StealGroup);
+ if (group == null)
+ {
+ args.Cancelled = true;
+ Log.Error("StealTargetGroup invalid prototype!");
+ return;
+ }
+
+ var query = EntityQueryEnumerator<StealTargetComponent>();
+ while (query.MoveNext(out var uid, out var target))
+ {
+ if (condition.Comp.StealGroup != target.StealGroup)
+ continue;
+
+ targetList.Add(target);
+ }
+
+ // cancel if the required items do not exist
+ if (targetList.Count == 0 && condition.Comp.VerifyMapExistance)
+ {
+ args.Cancelled = true;
+ return;
+ }
+
+ //setup condition settings
+ var maxSize = condition.Comp.VerifyMapExistance
+ ? Math.Min(targetList.Count, condition.Comp.MaxCollectionSize)
+ : condition.Comp.MaxCollectionSize;
+ var minSize = condition.Comp.VerifyMapExistance
+ ? Math.Min(targetList.Count, condition.Comp.MinCollectionSize)
+ : condition.Comp.MinCollectionSize;
+
+ condition.Comp.CollectionSize = _random.Next(minSize, maxSize);
}
- private void OnAfterAssign(EntityUid uid, StealConditionComponent comp, ref ObjectiveAfterAssignEvent args)
+ //Set the visual, name, icon for the objective.
+ private void OnAfterAssign(Entity<StealConditionComponent> condition, ref ObjectiveAfterAssignEvent args)
{
- var proto = _proto.Index<EntityPrototype>(comp.Prototype);
- var title = comp.OwnerText == null
- ? Loc.GetString("objective-condition-steal-title-no-owner", ("itemName", proto.Name))
- : Loc.GetString("objective-condition-steal-title", ("owner", Loc.GetString(comp.OwnerText)), ("itemName", proto.Name));
- var description = Loc.GetString("objective-condition-steal-description", ("itemName", proto.Name));
-
- _metaData.SetEntityName(uid, title, args.Meta);
- _metaData.SetEntityDescription(uid, description, args.Meta);
- _objectives.SetIcon(uid, new SpriteSpecifier.EntityPrototype(comp.Prototype), args.Objective);
- }
+ var group = _proto.Index(condition.Comp.StealGroup);
- private void OnGetProgress(EntityUid uid, StealConditionComponent comp, ref ObjectiveGetProgressEvent args)
+ var title =condition.Comp.OwnerText == null
+ ? Loc.GetString(condition.Comp.ObjectiveNoOwnerText, ("itemName", group.Name))
+ : Loc.GetString(condition.Comp.ObjectiveText, ("owner", Loc.GetString(condition.Comp.OwnerText)), ("itemName", group.Name));
+
+ var description = condition.Comp.CollectionSize > 1
+ ? Loc.GetString(condition.Comp.DescriptionMultiplyText, ("itemName", group.Name), ("count", condition.Comp.CollectionSize))
+ : Loc.GetString(condition.Comp.DescriptionText, ("itemName", group.Name));
+
+ _metaData.SetEntityName(condition.Owner, title, args.Meta);
+ _metaData.SetEntityDescription(condition.Owner, description, args.Meta);
+ _objectives.SetIcon(condition.Owner, group.Sprite, args.Objective);
+ }
+ private void OnGetProgress(Entity<StealConditionComponent> condition, ref ObjectiveGetProgressEvent args)
{
- args.Progress = GetProgress(args.Mind, comp.Prototype);
+ args.Progress = GetProgress(args.Mind, condition);
}
- private float GetProgress(MindComponent mind, string prototype)
+ private float GetProgress(MindComponent mind, StealConditionComponent condition)
{
- // TODO make this a container system function
- // or: just iterate through transform children, instead of containers?
-
- if (!metaQuery.TryGetComponent(mind.OwnedEntity, out var meta))
+ if (!_metaQuery.TryGetComponent(mind.OwnedEntity, out var meta))
+ return 0;
+ if (!_containerQuery.TryGetComponent(mind.OwnedEntity, out var currentManager))
return 0;
- // who added this check bruh
- if (meta.EntityPrototype?.ID == prototype)
- return 1;
+ var stack = new Stack<ContainerManagerComponent>();
+ var count = 0;
- if (!containerQuery.TryGetComponent(mind.OwnedEntity, out var currentManager))
- return 0;
+ //check pulling object
+ if (TryComp<SharedPullerComponent>(mind.OwnedEntity, out var pull)) //TO DO: to make the code prettier? don't like the repetition
+ {
+ var pullid = pull.Pulling;
+ if (pullid != null)
+ {
+ // check if this is the item
+ if (CheckStealTarget(pullid.Value, condition)) count++;
+
+ //we don't check the inventories of sentient entity
+ if (!TryComp<MindContainerComponent>(pullid, out var pullMind))
+ {
+ // if it is a container check its contents
+ if (_containerQuery.TryGetComponent(pullid, out var containerManager))
+ stack.Push(containerManager);
+ }
+ }
+ }
// recursively check each container for the item
// checks inventory, bag, implants, etc.
- var stack = new Stack<ContainerManagerComponent>();
do
{
foreach (var container in currentManager.Containers.Values)
foreach (var entity in container.ContainedEntities)
{
// check if this is the item
- if (metaQuery.GetComponent(entity).EntityPrototype?.ID == prototype)
- return 1;
+ if (CheckStealTarget(entity, condition)) count++; //To Do: add support for stackable items
// if it is a container check its contents
- if (containerQuery.TryGetComponent(entity, out var containerManager))
+ if (_containerQuery.TryGetComponent(entity, out var containerManager))
stack.Push(containerManager);
}
}
} while (stack.TryPop(out currentManager));
- return 0;
+ var result = (float) count / (float) condition.CollectionSize;
+ result = Math.Clamp(result, 0, 1);
+ return result;
+ }
+
+ private bool CheckStealTarget(EntityUid entity, StealConditionComponent condition)
+ {
+ // check if this is the target
+ if (!TryComp<StealTargetComponent>(entity, out var target))
+ return false;
+
+ if (target.StealGroup != condition.StealGroup)
+ return false;
+
+ // check if needed target alive
+ if (condition.CheckAlive)
+ {
+ if (TryComp<MobStateComponent>(entity, out var state))
+ {
+ if (!_mobState.IsAlive(entity))
+ return false;
+ }
+ }
+ return true;
}
}
-using Content.Shared.Roles;
+using Content.Shared.Roles;
namespace Content.Server.Roles;
SubscribeAntagEvents<SubvertedSiliconRoleComponent>();
SubscribeAntagEvents<TraitorRoleComponent>();
SubscribeAntagEvents<ZombieRoleComponent>();
+ SubscribeAntagEvents<ThiefRoleComponent>();
}
public string? MindGetBriefing(EntityUid? mindId)
--- /dev/null
+using Content.Shared.Roles;
+
+namespace Content.Server.Roles;
+
+[RegisterComponent]
+public sealed partial class ThiefRoleComponent : AntagonistRoleComponent
+{
+}
--- /dev/null
+using Content.Shared.Thief;
+using Robust.Shared.Audio;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.Thief.Components;
+
+/// <summary>
+/// This component stores the possible contents of the backpack,
+/// which can be selected via the interface.
+/// </summary>
+[RegisterComponent]
+public sealed partial class ThiefUndeterminedBackpackComponent : Component
+{
+ /// <summary>
+ /// List of sets available for selection
+ /// </summary>
+ [DataField]
+ public List<ProtoId<ThiefBackpackSetPrototype>> PossibleSets = new();
+
+ [DataField]
+ public List<int> SelectedSets = new();
+
+ [DataField]
+ public SoundSpecifier ApproveSound = new SoundPathSpecifier("/Audio/Effects/rustle1.ogg");
+}
--- /dev/null
+using Content.Server.Thief.Components;
+using Content.Shared.Item;
+using Content.Shared.Thief;
+using Robust.Server.GameObjects;
+using Robust.Server.Audio;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.Thief.Systems;
+public sealed class ThiefUndeterminedBackpackSystem : EntitySystem
+{
+ [Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly IPrototypeManager _proto = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly UserInterfaceSystem _ui = default!;
+
+ private const int MaxSelectedSets = 2;
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<ThiefUndeterminedBackpackComponent, BoundUIOpenedEvent>(OnUIOpened);
+ SubscribeLocalEvent<ThiefUndeterminedBackpackComponent, ThiefBackpackApproveMessage>(OnApprove);
+ SubscribeLocalEvent<ThiefUndeterminedBackpackComponent, ThiefBackpackChangeSetMessage>(OnChangeSet);
+ }
+
+ private void OnUIOpened(Entity<ThiefUndeterminedBackpackComponent> backpack, ref BoundUIOpenedEvent args)
+ {
+ UpdateUI(backpack.Owner, backpack.Comp);
+ }
+
+ private void OnApprove(Entity<ThiefUndeterminedBackpackComponent> backpack, ref ThiefBackpackApproveMessage args)
+ {
+ if (backpack.Comp.SelectedSets.Count != MaxSelectedSets)
+ return;
+
+ foreach (var i in backpack.Comp.SelectedSets)
+ {
+ var set = _proto.Index(backpack.Comp.PossibleSets[i]);
+ foreach (var item in set.Content)
+ {
+ var ent = Spawn(item, _transform.GetMapCoordinates(backpack.Owner));
+ if (TryComp<ItemComponent>(ent, out var itemComponent))
+ _transform.DropNextTo(ent, backpack.Owner);
+ }
+ }
+ _audio.PlayPvs(backpack.Comp.ApproveSound, backpack.Owner);
+ QueueDel(backpack); //hehe
+ }
+ private void OnChangeSet(Entity<ThiefUndeterminedBackpackComponent> backpack, ref ThiefBackpackChangeSetMessage args)
+ {
+ //Swith selecting set
+ if (!backpack.Comp.SelectedSets.Remove(args.SetNumber))
+ backpack.Comp.SelectedSets.Add(args.SetNumber);
+
+ UpdateUI(backpack.Owner, backpack.Comp);
+ }
+
+ private void UpdateUI(EntityUid uid, ThiefUndeterminedBackpackComponent? component = null)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ Dictionary<int, ThiefBackpackSetInfo> data = new();
+
+ for (int i = 0; i < component.PossibleSets.Count; i++)
+ {
+ var set = _proto.Index(component.PossibleSets[i]);
+ var selected = component.SelectedSets.Contains(i);
+ var info = new ThiefBackpackSetInfo(
+ set.Name,
+ set.Description,
+ set.Sprite,
+ selected);
+ data.Add(i, info);
+ }
+
+ _ui.TrySetUiState(uid, ThiefBackpackUIKey.Key, new ThiefBackpackBoundUserInterfaceState(data, MaxSelectedSets));
+ }
+}
--- /dev/null
+using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
+
+namespace Content.Shared.Objectives;
+
+/// <summary>
+/// General data about a group of items, such as icon, description, name. Used for Steal objective
+/// </summary>
+[Prototype("stealTargetGroup")]
+public sealed partial class StealTargetGroupPrototype : IPrototype
+{
+ [IdDataField] public string ID { get; private set; } = default!;
+ [DataField] public string Name { get; private set; } = string.Empty;
+ [DataField] public SpriteSpecifier Sprite { get; private set; } = SpriteSpecifier.Invalid;
+}
--- /dev/null
+using Robust.Shared.Serialization;
+using Robust.Shared.Utility;
+
+namespace Content.Shared.Thief;
+
+[Serializable, NetSerializable]
+public sealed class ThiefBackpackBoundUserInterfaceState : BoundUserInterfaceState
+{
+ public readonly Dictionary<int, ThiefBackpackSetInfo> Sets;
+ public int MaxSelectedSets;
+
+ public ThiefBackpackBoundUserInterfaceState(Dictionary<int, ThiefBackpackSetInfo> sets, int max)
+ {
+ Sets = sets;
+ MaxSelectedSets = max;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class ThiefBackpackChangeSetMessage : BoundUserInterfaceMessage
+{
+ public readonly int SetNumber;
+
+ public ThiefBackpackChangeSetMessage(int setNumber)
+ {
+ SetNumber = setNumber;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class ThiefBackpackApproveMessage : BoundUserInterfaceMessage
+{
+ public ThiefBackpackApproveMessage() { }
+}
+
+[Serializable, NetSerializable]
+public enum ThiefBackpackUIKey : byte
+{
+ Key
+};
+
+[Serializable, NetSerializable, DataDefinition]
+public partial struct ThiefBackpackSetInfo
+{
+ [DataField]
+ public string Name;
+
+ [DataField]
+ public string Description;
+
+ [DataField]
+ public SpriteSpecifier Sprite;
+
+ public bool Selected;
+
+ public ThiefBackpackSetInfo(string name, string desc, SpriteSpecifier sprite, bool selected)
+ {
+ Name = name;
+ Description = desc;
+ Sprite = sprite;
+ Selected = selected;
+ }
+}
--- /dev/null
+using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
+
+namespace Content.Shared.Thief;
+
+/// <summary>
+/// A prototype that defines a set of items and visuals in a specific starter set for the antagonist thief
+/// </summary>
+[Prototype("thiefBackpackSet")]
+public sealed partial class ThiefBackpackSetPrototype : IPrototype
+{
+ [IdDataField] public string ID { get; private set; } = default!;
+ [DataField] public string Name { get; private set; } = string.Empty;
+ [DataField] public string Description { get; private set; } = string.Empty;
+ [DataField] public SpriteSpecifier Sprite { get; private set; } = SpriteSpecifier.Invalid;
+
+ [DataField] public List<EntProtoId> Content = new();
+}
copyright: "Taken from TG station."
source: "https://github.com/tgstation/tgstation/blob/b02b93ce2ab891164511a973493cdf951b4120f7/sound/effects/ninja_greeting.ogg"
+- files: ["thief_greeting.ogg"]
+ license: "CC-BY-NC-4.0"
+ copyright: "Taken from SergeQuadrado via freesound.org, edit and mono by TheShuEd"
+ source: "https://freesound.org/people/SergeQuadrado/sounds/683504/"
+
- files: ["narsie_rises.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Taken from TG station."
admin-verb-make-nuclear-operative = Make target into a lone Nuclear Operative.
admin-verb-make-pirate = Make the target into a pirate. Note this doesn't configure the game rule.
admin-verb-make-head-rev = Make the target into a Head Revolutionary.
+admin-verb-make-thief = Make the target into a thief.
admin-verb-text-make-traitor = Make Traitor
admin-verb-text-make-zombie = Make Zombie
admin-verb-text-make-nuclear-operative = Make Nuclear Operative
admin-verb-text-make-pirate = Make Pirate
admin-verb-text-make-head-rev = Make Head Rev
+admin-verb-text-make-thief = Make Thief
\ No newline at end of file
--- /dev/null
+thief-role-greeting-human =
+ You are a criminal scum.
+ You want to add to your collection
+ some property of Nanotrasen station.
+ You're not a murderer.
+ You are forbidden to kill.
+
+thief-role-greeting-animal =
+ You are a kleptomaniaс animal.
+ Steal things you like.
+
+thief-role-greeting-equipment =
+ You have a toolbox of thief's
+ tools and chameleon thief's gloves.
+ Choose your starting equipment,
+ and do your work stealthily.
+
+objective-issuer-thief = [color=#746694]Criminal[/color]
+
+thief-round-end-agent-name = thief
\ No newline at end of file
objective-condition-steal-title-no-owner = Steal the {$itemName}.
+objective-condition-steal-title-alive-no-owner = Steal {$itemName}.
objective-condition-steal-title = Steal the {$owner}'s {$itemName}.
objective-condition-steal-description = We need you to steal {$itemName}. Don't get caught.
objective-condition-steal-station = station
objective-condition-steal-Ian = head of personnel's corgi
+
+objective-condition-thief-description = The {$itemName} would be a great addition to my collection!
+objective-condition-thief-animal-description = The {$itemName} would be a great addition to my collection! Most importantly, alive.
+objective-condition-thief-multiply-description = I need to get {$count} {$itemName} and take them with me.
\ No newline at end of file
roles-antag-space-ninja-name = Space Ninja
roles-antag-space-ninja-objective = Use your stealth to sabotage the station, nom on electrical wires.
+
+roles-antag-thief-name = Thief
+roles-antag-thief-objective = Add some NT property to your personal collection without using violence.
\ No newline at end of file
--- /dev/null
+thief-backpack-window-title = Thief toolbox
+
+thief-backpack-window-description =
+ This toolbox is filled with unspecified contents.
+ Now you need to remember what you put in it.
+ Choose up to two different sets from the list.
+
+thief-backpack-window-selected = Kits selected: ({$selectedCount}/{$maxCount})
+
+thief-backpack-window-approve-button = Approve
+thief-backpack-button-select = Select [ ]
+thief-backpack-button-deselect = Select [X]
+
+# Sets
+
+thief-backpack-category-chameleon-name = Chameleon's kit.
+thief-backpack-category-chameleon-description =
+ Includes a full set of clothing that contain
+ chameleon technology, allowing you to disguise
+ as pretty much anything on the station.
+
+thief-backpack-category-tools-name = Bearcatcher's kit
+thief-backpack-category-tools-description =
+ A set of tools for roughing up doors, walls, windows,
+ and anything else that for whatever reason doesn't
+ want to let you in where you need to go.
+ Includes two C4s, a multitool, jaws of life,
+ a pair of advanced welder meson glasses and some insulated gloves.
+
+thief-backpack-category-chemistry-name = Chemistry kit
+thief-backpack-category-chemistry-description =
+ A set for those who love to improve their body.
+ It includes a storage implanter,
+ a dna scrambler implanter,
+ and a set of chemicals for a rainy day.
+
+thief-backpack-category-syndie-name = Syndie kit
+thief-backpack-category-syndie-description =
+ A set of items from a syndicate agent you've robbed
+ in the past. Includes an Agent ID card, a syndicate pAI,
+ and some strange red crystals.
+
+thief-backpack-category-sleeper-name = Sleepwalker's kit
+thief-backpack-category-sleeper-description =
+ A set for those who like to sleep in,
+ or for everyone around you to sleep.
+ Includes a set of nocturine vials, a hypopen and
+ a tank of sleeping gas.
+
+thief-backpack-category-communicator-name = Communicator's kit
+thief-backpack-category-communicator-description =
+ A communication enthusiast's kit. Includes a master key
+ for all station channels, a radio jammer, a portable
+ crew monitor, a voice chameleon mask and lots of money for business deals.
+
+thief-backpack-category-smuggler-name = Smuggler's kit
+thief-backpack-category-smuggler-description =
+ A kit for those who like to have big pockets.
+ Includes a fulton beacon, ten fultons
+ and an invisible crate. You can't move in them,
+ but you can quickly hide or carry valuable loot.
+ This kit also has a cool void cloak to go along with it.
--- /dev/null
+- type: thiefBackpackSet
+ id: ChameleonSet
+ name: thief-backpack-category-chameleon-name
+ description: thief-backpack-category-chameleon-description
+ sprite:
+ sprite: /Textures/Clothing/OuterClothing/Misc/black_hoodie.rsi
+ state: icon
+ content:
+ - ClothingUniformJumpsuitChameleon
+ - ClothingOuterChameleon
+ - ClothingNeckChameleon
+ - ClothingMaskGasChameleon
+ - ClothingHeadHatChameleon
+ - ClothingEyesChameleon
+ - ClothingHeadsetChameleon
+ - ClothingShoesChameleon
+
+- type: thiefBackpackSet
+ id: ToolsSet
+ name: thief-backpack-category-tools-name
+ description: thief-backpack-category-tools-description
+ sprite:
+ sprite: Objects/Tools/jaws_of_life.rsi
+ state: jaws_pry
+ content:
+ - WelderIndustrialAdvanced
+ - ClothingEyesGlassesMeson
+ - ClothingHandsGlovesColorYellow
+ - JawsOfLife
+ - Multitool
+ - C4
+ - C4
+ - ClothingMaskClown
+
+- type: thiefBackpackSet
+ id: ChemistrySet
+ name: thief-backpack-category-chemistry-name
+ description: thief-backpack-category-chemistry-description
+ sprite:
+ sprite: Objects/Specific/Medical/implanter.rsi
+ state: implanter0
+ content:
+ - StorageImplanter
+ - DnaScramblerImplanter
+ - EphedrineChemistryBottle
+ - OmnizineChemistryBottle
+ - Syringe
+ - DrinkVodkaBottleFull
+
+- type: thiefBackpackSet
+ id: SyndieSet
+ name: thief-backpack-category-syndie-name
+ description: thief-backpack-category-syndie-description
+ sprite:
+ sprite: Objects/Specific/Syndicate/telecrystal.rsi
+ state: telecrystal
+ content:
+ - AgentIDCard
+ - SyndicatePersonalAI
+ - ClothingHeadHatSyndieMAA
+ - CigPackSyndicate
+ - Telecrystal10 #The thief cannot use them, but it may induce communication with traitors
+
+- type: thiefBackpackSet
+ id: SleeperSet
+ name: thief-backpack-category-sleeper-name
+ description: thief-backpack-category-sleeper-description
+ sprite:
+ sprite: Objects/Tanks/anesthetic.rsi
+ state: icon
+ content:
+ - ClothingHeadPyjamaSyndicateBlack
+ - ClothingUniformJumpsuitPyjamaSyndicateBlack
+ - NocturineChemistryBottle
+ - NocturineChemistryBottle
+ - NocturineChemistryBottle
+ - HypopenBox
+ - NitrousOxideTankFilled
+ - BedsheetSyndie
+
+- type: thiefBackpackSet
+ id: CommunicatorSet
+ name: thief-backpack-category-communicator-name
+ description: thief-backpack-category-communicator-description
+ sprite:
+ sprite: Objects/Tools/spy_device.rsi
+ state: icon
+ content:
+ - EncryptionKeyStationMaster
+ - RadioJammer
+ - SpyCrewMonitor
+ - BriefcaseSyndieLobbyingBundleFilled
+ - ClothingMaskGasVoiceChameleon
+ #- todo Chameleon Stamp
+
+- type: thiefBackpackSet
+ id: SmugglerSet
+ name: thief-backpack-category-smuggler-name
+ description: thief-backpack-category-smuggler-description
+ sprite:
+ sprite: Clothing/Neck/Cloaks/void.rsi
+ state: icon
+ content:
+ - InvisibleCrate
+ - ClothingNeckCloakVoid
+ - FultonBeacon
+ - Fulton
sprite: Clothing/Ears/Headsets/medical.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/medical.rsi
+ - type: StealTarget
+ stealGroup: ClothingHeadsetAltMedical
- type: entity
parent: ClothingHeadsetAlt
- type: Clothing
sprite: Clothing/Eyes/Hud/beergoggles.rsi
- type: ShowThirstIcons
+ - type: StealTarget
+ stealGroup: ClothingEyesHudBeer
- type: SolutionScanner
- type: entity
sprite: Clothing/Head/Hats/warden.rsi
- type: Clothing
sprite: Clothing/Head/Hats/warden.rsi
+ - type: StealTarget
+ stealGroup: ClothingHeadHatWarden
- type: entity
parent: ClothingHeadBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/cap.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/hos.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/ce.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/cmo.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/rd.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/qm.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/hop.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/capcloakformal.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/admin.rsi
+ - type: StealTarget
+ stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
sprite: Clothing/Neck/Medals/gold.rsi\r
- type: Clothing\r
sprite: Clothing/Neck/Medals/gold.rsi\r
+ - type: StealTarget\r
+ stealGroup: ClothingNeckGoldmedal\r
\r
- type: entity\r
parent: ClothingNeckBase\r
sprite: Clothing/Neck/Medals/clownmedal.rsi\r
- type: Clothing\r
sprite: Clothing/Neck/Medals/clownmedal.rsi\r
+ - type: StealTarget\r
+ stealGroup: ClothingNeckClownmedal\r
clothingPrototype: ClothingHeadHelmetHardsuitRd
- type: StaticPrice
price: 750
+ - type: StealTarget
+ stealGroup: ClothingOuterHardsuitRd
#Head of Security's Hardsuit
- type: entity
Radiation: 0.75
Caustic: 0.5
- type: GroupExamine
+ - type: StealTarget
+ stealGroup: ClothingOuterHardsuitVoidParamed
\ No newline at end of file
- HighRiskItem
- type: StaticPrice
price: 750
+ - type: StealTarget
+ stealGroup: ClothingShoesBootsMagAdv
- type: entity
parent: ClothingShoesBootsMag
tags:
- CannotSuicide
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalIan
- type: entity
name: Old Ian
tags:
- CannotSuicide
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalBingus
- type: entity
name: McGriff
tags:
- CannotSuicide
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalMcGriff
- type: entity
name: Paperwork
tags:
- CannotSuicide
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalWalter
- type: entity
name: Morty
tags:
- CannotSuicide
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalMorty
- type: entity
name: Morty
tags:
- CannotSuicide
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalRenault
- type: entity
name: Hamlet
- CannotSuicide
- Hamster
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalHamlet
- type: entity
name: Shiva
tags:
- CannotSuicide
- VimPilot
+ - type: StealTarget
+ stealGroup: AnimalShiva
- type: entity
name: Willow
attributes:
proper: true
gender: female
+ - type: StealTarget
+ stealGroup: AnimalSmile
- type: entity
name: Pun Pun
attributes:
proper: true
gender: male
+ - type: StealTarget
+ stealGroup: AnimalPunPun
Quantity: 20
- type: StaticPrice
price: 750
+ - type: StealTarget
+ stealGroup: FoodMeatCorgi
- type: entity
name: raw crab meat
color: "#cc6600"
radius: 2.0
energy: 4.0
+ - type: StealTarget
+ stealGroup: LAMP
- type: entity
parent: CarvedPumpkin
requirements:
MatterBin: 1
Manipulator: 1
+ - type: StealTarget
+ stealGroup: AmmoTechFabCircuitboard
- type: entity
id: MedicalTechFabCircuitboard
Amount: 2
DefaultPrototype: Beaker
ExamineName: Glass Beaker
+ - type: StealTarget
+ stealGroup: MedicalTechFabCircuitboard
- type: entity
id: CircuitImprinterMachineCircuitboard
state: cpu_supply
- type: ComputerBoard
prototype: ComputerSalvageExpedition
+ - type: StealTarget
+ stealGroup: SalvageExpeditionsComputerCircuitboard
- type: entity
parent: BaseComputerCircuitboard
components:
- type: ComputerBoard
prototype: ComputerShuttleCargo
+ - type: StealTarget
+ stealGroup: CargoShuttleConsoleCircuitboard
- type: entity
parent: BaseComputerCircuitboard
components:
- type: ComputerBoard
prototype: ComputerShuttleSalvage
+ - type: StealTarget
+ stealGroup: SalvageShuttleConsoleCircuitboard
- type: entity
parent: BaseComputerCircuitboard
sprite: Objects/Devices/door_remote.rsi
- type: Access
- type: DoorRemote
+ - type: StealTarget
+ stealGroup: DoorRemote
- type: entity
parent: DoorRemoteDefault
sprite: Objects/Devices/encryption_keys.rsi
- type: Sprite
sprite: Objects/Devices/encryption_keys.rsi
+ - type: StealTarget
+ stealGroup: EncryptionKey
- type: entity
parent: EncryptionKey
- type: GuideHelp
guides:
- DNA
+ - type: StealTarget
+ stealGroup: ForensicScanner
- type: entity
name: forensic scanner report
- type: Tag
tags:
- HighRiskItem
+ - type: StealTarget
+ stealGroup: HandTeleporter
- type: ContainerContainer
containers:
Nuke: !type:ContainerSlot
+ - type: StealTarget
+ stealGroup: NuclearBomb
- type: entity
parent: NuclearBomb
state: pinpointer-station
- type: Pinpointer
component: BecomesStation
- targetName: the station
+ targetName: the station
\ No newline at end of file
- type: Tag
tags:
- Figurine
+ - type: StealTarget
+ stealGroup: Figurines
- type: entity
parent: BaseFigurine
state: sheetcaptain
- type: Clothing
sprite: Clothing/Neck/Bedsheets/captain.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetCE
state: sheetce
- type: Clothing
sprite: Clothing/Neck/Bedsheets/ce.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetCentcom
state: sheetcentcom
- type: Clothing
sprite: Clothing/Neck/Bedsheets/centcom.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetClown
state: sheetcmo
- type: Clothing
sprite: Clothing/Neck/Bedsheets/cmo.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetCosmos
state: sheethop
- type: Clothing
sprite: Clothing/Neck/Bedsheets/hop.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetHOS
state: sheethos
- type: Clothing
sprite: Clothing/Neck/Bedsheets/hos.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetIan
state: sheetqm
- type: Clothing
sprite: Clothing/Neck/Bedsheets/qm.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetRainbow
state: sheetrd
- type: Clothing
sprite: Clothing/Neck/Bedsheets/rd.rsi
+ - type: StealTarget
+ stealGroup: HeadBedsheet
- type: entity
id: BedsheetBrigmedic
- type: Tag
tags:
- HighRiskItem
+ - type: StealTarget
+ stealGroup: NukeDisk
- type: entity
name: nuclear authentication disk
- type: Appearance
- type: Physics
canCollide: false
+ - type: StealTarget
+ stealGroup: LAMP
- type: entity
name: lamp
tags:
- DoorBumpOpener
- WhitelistChameleon
+ - type: StealTarget
+ stealGroup: IDCard
#IDs with layers
- DoorBumpOpener
- WhitelistChameleon
- HighRiskItem
+ - type: StealTarget
+ stealGroup: CaptainIDCard
- type: entity
parent: IDCardStandard
damage:
types:
Blunt: 10
+ - type: StealTarget
+ stealGroup: BoxFolderQmClipboard
# Stamps
- type: entity
state: stamp-mime
- type: Item
size: Tiny
+ - type: StealTarget
+ stealGroup: Stamp
- type: entity
name: alternate rubber stamp
tags:
- Book
- HighRiskItem
+ - type: StealTarget
+ stealGroup: BookSecretDocuments
- type: Tag
tags:
- DroneUsable
+ - type: StealTarget
+ stealGroup: AmePart
- type: Tag
tags:
- Book
+ - type: StealTarget
+ stealGroup: Bible
- type: entity
parent: Bible
reagents:
- ReagentId: THC
Quantity: 15
+ - type: StealTarget
+ stealGroup: Cannabis
- type: entity
name: dried cannabis leaves
- type: Sprite
sprite: Objects/Specific/Hydroponics/tobacco.rsi
state: dried
+ - type: StealTarget
+ stealGroup: Cannabis
- type: entity
name: ground cannabis
- Smokable
- type: Item
size: Tiny
+ - type: StealTarget
+ stealGroup: Cannabis
- type: entity
name: tobacco leaves
- type: Item
sprite: Objects/Tools/spy_device.rsi
- type: PowerCellDraw
- useRate: 40 #Should be weaker than the original
+ useRate: 10
+ - type: StaticPrice
+ price: 750
- type: entity
id: SpyCrewMonitorEmpty
- type: Tag
tags:
- HighRiskItem
+ - type: StealTarget
+ stealGroup: Hypospray
- type: entity
name: gorlex hypospray
- type: TechnologyDisk
- type: StaticPrice
price: 100
+ - type: StealTarget
+ stealGroup: TechnologyDisk
- type: entity
parent: TechnologyDisk
- type: GuideHelp
guides:
- Xenoarchaeology
+ - type: StealTarget
+ stealGroup: XenoArtifact
- type: entity
parent: BaseXenoArtifact
- type: Appearance
- type: StaticPrice
price: 40
+ - type: StealTarget
+ stealGroup: LAMP
- type: entity
name: seclite
- type: Tag
tags:
- HighRiskItem
+ - type: StealTarget
+ stealGroup: JetpackCaptainFilled
# Filled captain
- type: entity
- type: ContainerContainer
containers:
cell_slot: !type:ContainerSlot {}
+ - type: StealTarget
+ stealGroup: LAMP
- type: entity
parent: Lantern
state: icon
- type: Item
sprite: Objects/Tools/Toolboxes/toolbox_gold.rsi
+
+- type: entity
+ id: ToolboxThief
+ name: thief undetermined toolbox
+ description: This is where your favorite thief's supplies lie. Try to remember which ones.
+ parent: BaseItem
+ components:
+ - type: Sprite
+ sprite: Objects/Tools/Toolboxes/toolbox_thief.rsi
+ state: icon
+ - type: ThiefUndeterminedBackpack
+ transformAfterSelect: AlwaysPoweredWallLight
+ possibleSets:
+ # - TO DO Thief pinpointer needed
+ - ChemistrySet
+ - ToolsSet
+ - ChameleonSet # - TO DO Chameleon stump PR needed
+ - SyndieSet
+ - SleeperSet
+ - CommunicatorSet
+ - SmugglerSet
+ - type: ActivatableUI
+ key: enum.ThiefBackpackUIKey.Key
+ - type: UserInterface
+ interfaces:
+ - key: enum.ThiefBackpackUIKey.Key
+ type: ThiefBackpackBoundUserInterface
\ No newline at end of file
path: /Audio/Effects/Vehicle/vehiclestartup.ogg
params:
volume: -3
+ - type: StealTarget
+ stealGroup: VehicleSecway
- type: entity
parent: BaseVehicleRideable
- Sidearm
- type: StaticPrice
price: 750
+ - type: StealTarget
+ stealGroup: WeaponAntiqueLaser
- type: entity
name: advanced laser pistol
- type: Prying
- type: UseDelay
delay: 1
+ - type: StealTarget
+ stealGroup: FireAxe
- type: IgniteOnMeleeHit
fireStacks: -4
- type: GuideHelp
guides:
- Bartender
+ - type: StealTarget
+ stealGroup: BoozeDispenser
guides:
- Chemicals
- Chemist
+ - type: StealTarget
+ stealGroup: ChemDispenser
max: 3
- !type:DoActsBehavior
acts: [ "Destruction" ]
+ - type: StealTarget
+ stealGroup: AltarNanotrasen
- type: entity
id: AltarChaos
components:
- type: Sprite
state: plant-25
+ - type: StealTarget
+ stealGroup: PlantRD
- type: entity
id: PottedPlant26
- type: FaxMachine
name: "Captain's Office"
receiveNukeCodes: true
+ - type: StealTarget
+ stealGroup: FaxMachineCaptain
board: ThermomachineFreezerMachineCircuitBoard
- type: DeviceNetwork
prefix: device-address-prefix-freezer
+ - type: StealTarget
+ stealGroup: FreezerHeater
- type: entity
parent: GasThermoMachineFreezer
board: ThermomachineHeaterMachineCircuitBoard
- type: DeviceNetwork
prefix: device-address-prefix-heater
+ - type: StealTarget
+ stealGroup: FreezerHeater
- type: entity
parent: GasThermoMachineHeater
path: /Audio/Ambience/Objects/vending_machine_hum.ogg
- type: GuideHelp
guides: [ TEG, Power ]
+ - type: StealTarget
+ stealGroup: Teg
- type: entity
id: TegCirculator
- type: AtmosUnsafeUnanchor
- type: TegCirculator
+ - type: StealTarget
+ stealGroup: Teg
- # Spawned by the client-side circulator examine code to indicate the inlet/outlet direction.
type: entity
objectives:
- CarpRiftsObjective
- DragonSurviveObjective
+
+# need for admin panel antag create (because the rule doesn't have a roundstart entity like TraitorRule)
+- type: entity
+ id: Thief
+ parent: BaseGameRule
+ noSpawn: true
+ components:
+ - type: ThiefRule
\ No newline at end of file
noSpawn: true
components:
- type: TraitorRule
+ - type: ThiefRule #the thieves come as an extension of another gamemode
+ ruleChance: 0.5
- type: entity
id: Revolutionary
noSpawn: true
components:
- type: RevolutionaryRule
+ - type: ThiefRule #the thieves come as an extension of another gamemode
+ ruleChance: 0.5
- type: entity
id: Sandbox
id: BaseStealObjective
components:
- type: StealCondition
+ objectiveNoOwnerText: objective-condition-steal-title-no-owner
+ objectiveText: objective-condition-steal-title
+ descriptionText: objective-condition-steal-description
+ descriptionMultiplyText: objective-condition-thief-multiply-description
# requires that the player not die, ignores being on emergency shuttle or cuffed
- type: entity
RandomTraitorAliveObjective: 1
RandomTraitorProgressObjective: 1
+#Thief groups
+- type: weightedRandom
+ id: ThiefObjectiveGroups
+ weights:
+ ThiefObjectiveGroupCollection: 1
+ ThiefObjectiveGroupItem: 1
+
+- type: weightedRandom
+ id: ThiefBigObjectiveGroups
+ weights:
+ ThiefObjectiveGroupStructure: 1
+ ThiefObjectiveGroupAnimal: 2
+
+- type: weightedRandom
+ id: ThiefEscapeObjectiveGroups
+ weights:
+ ThiefObjectiveGroupEscape: 1
+
+
+
+- type: weightedRandom
+ id: ThiefObjectiveGroupCollection
+ weights:
+ HeadCloakStealCollectionObjective: 1 #command
+ HeadBedsheetStealCollectionObjective: 1
+ StampStealCollectionObjective: 1
+ DoorRemoteStealCollectionObjective: 1
+ TechnologyDiskStealCollectionObjective: 1 #rnd
+ FigurineStealCollectionObjective: 0.3 #service
+ IDCardsStealCollectionObjective: 1
+ EncryptionKeyStealCollectionObjective: 1
+ CannabisStealCollectionObjective: 1
+ LAMPStealCollectionObjective: 2 #only for moth
+
+- type: weightedRandom
+ id: ThiefObjectiveGroupItem
+ weights:
+ ForensicScannerStealObjective: 1 #sec
+ AmmoTechFabCircuitboardStealObjective: 1
+ ClothingHeadHatWardenStealObjective: 1
+ ClothingOuterHardsuitVoidParamedStealObjective: 1 #med
+ MedicalTechFabCircuitboardStealObjective: 1
+ ClothingHeadsetAltMedicalStealObjective: 1
+ FireAxeStealObjective: 1 #eng
+ AmePartStealObjective: 1
+ ExpeditionsCircuitboardStealObjective: 1 #sup
+ CargoShuttleCircuitboardStealObjective: 1
+ SalvageShuttleCircuitboardStealObjective: 1
+ ClothingEyesHudBeerStealObjective: 1 #srv
+ BibleStealObjective: 1
+ ClothingNeckGoldmedalStealObjective: 1 #other
+ ClothingNeckClownmedalStealObjective: 0.5
+
+- type: weightedRandom
+ id: ThiefObjectiveGroupStructure
+ weights:
+ NuclearBombStealObjective: 0.5
+ FaxMachineCaptainStealObjective: 1
+ VehicleSecwayStealObjective: 1
+ ChemDispenserStealObjective: 1
+ XenoArtifactStealObjective: 1
+ FreezerHeaterStealObjective: 1
+ TegStealObjective: 1
+ BoozeDispenserStealObjective: 1
+ AltarNanotrasenStealObjective: 1
+ PlantRDStealObjective: 1
+
+- type: weightedRandom
+ id: ThiefObjectiveGroupAnimal
+ weights:
+ IanStealObjective: 1
+ BingusStealObjective: 1
+ McGriffStealObjective: 1
+ WalterStealObjective: 1
+ MortyStealObjective: 1
+ RenaultStealObjective: 1
+ HamletStealObjective: 1
+ ShivaStealObjective: 1
+ SmileStealObjective: 1
+ PunPunStealObjective: 1
+
+- type: weightedRandom
+ id: ThiefObjectiveGroupEscape
+ weights:
+ EscapeThiefShuttleObjective: 1
#Changeling, crew, wizard, when you code it...
--- /dev/null
+# Traitor single items
+
+- type: stealTargetGroup
+ id: Hypospray
+ name: hypospray
+ sprite:
+ sprite: Objects/Specific/Medical/hypospray.rsi
+ state: hypo
+
+- type: stealTargetGroup
+ id: ClothingOuterHardsuitRd
+ name: experimental research hardsuit
+ sprite:
+ sprite: Clothing/OuterClothing/Hardsuits/rd.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: HandTeleporter
+ name: hand teleporter
+ sprite:
+ sprite: Objects/Devices/hand_teleporter.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: BookSecretDocuments
+ name: "emergency security orders"
+ sprite:
+ sprite: Objects/Misc/bureaucracy.rsi
+ state: folder-sec-doc
+
+- type: stealTargetGroup
+ id: ClothingShoesBootsMagAdv
+ name: advanced magboots
+ sprite:
+ sprite: Clothing/Shoes/Boots/magboots-advanced.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: BoxFolderQmClipboard
+ name: requisition digi-board
+ sprite:
+ sprite: Objects/Misc/qm_clipboard.rsi
+ state: qm_clipboard
+
+- type: stealTargetGroup
+ id: FoodMeatCorgi
+ name: prime-cut corgi meat
+ sprite:
+ sprite: Objects/Consumable/Food/meat.rsi
+ state: corgi
+ #
+- type: stealTargetGroup
+ id: CaptainIDCard
+ name: captain ID card
+ sprite:
+ sprite: Objects/Misc/id_cards.rsi
+ state: ert_commander #no one will know the difference.
+
+- type: stealTargetGroup
+ id: JetpackCaptainFilled
+ name: captain's jetpack
+ sprite:
+ sprite: Objects/Tanks/Jetpacks/captain.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: WeaponAntiqueLaser
+ name: antique laser pistol
+ sprite:
+ sprite: Objects/Weapons/Guns/Battery/antiquelasergun.rsi
+ state: base
+
+- type: stealTargetGroup
+ id: NukeDisk
+ name: nuclear authentication disk
+ sprite:
+ sprite: Objects/Misc/nukedisk.rsi
+ state: icon
+
+# Thief Collection
+
+- type: stealTargetGroup
+ id: Figurines
+ name: figurines (any)
+ sprite:
+ sprite: Objects/Fun/figurines.rsi
+ state: figurine_spawner
+
+- type: stealTargetGroup
+ id: HeadCloak
+ name: head's cloaks (any)
+ sprite:
+ sprite: Clothing/Neck/Cloaks/cap.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: HeadBedsheet
+ name: head's bedsheets (any)
+ sprite:
+ sprite: Objects/Misc/bedsheets.rsi
+ state: sheetNT
+
+- type: stealTargetGroup
+ id: Stamp
+ name: stamps (any)
+ sprite:
+ sprite: Objects/Misc/bureaucracy.rsi
+ state: stamp-cap
+
+- type: stealTargetGroup
+ id: DoorRemote
+ name: door remotes (any)
+ sprite:
+ sprite: Objects/Devices/door_remote.rsi
+ state: door_remotebase
+
+- type: stealTargetGroup
+ id: EncryptionKey
+ name: encryption keys (any)
+ sprite:
+ sprite: Objects/Devices/encryption_keys.rsi
+ state: crypt_gray
+
+- type: stealTargetGroup
+ id: TechnologyDisk
+ name: technology disks
+ sprite:
+ sprite: Objects/Misc/module.rsi
+ state: datadisk_base
+
+- type: stealTargetGroup
+ id: IDCard
+ name: ID Cards (any)
+ sprite:
+ sprite: Objects/Misc/id_cards.rsi
+ state: default
+
+- type: stealTargetGroup
+ id: Cannabis
+ name: cannabis
+ sprite:
+ sprite: Objects/Specific/Hydroponics/cannabis.rsi
+ state: produce
+
+- type: stealTargetGroup
+ id: LAMP
+ name: LAMPS
+ sprite:
+ sprite: Objects/Tools/lantern.rsi
+ state: lantern
+
+# Thief single item
+
+- type: stealTargetGroup
+ id: ForensicScanner
+ name: forensic scanner
+ sprite:
+ sprite: Objects/Devices/forensic_scanner.rsi
+ state: forensicnew
+
+- type: stealTargetGroup
+ id: AmmoTechFabCircuitboard
+ name: ammo techfab circuit board
+ sprite:
+ sprite: Objects/Misc/module.rsi
+ state: security
+
+- type: stealTargetGroup
+ id: ClothingHeadHatWarden
+ name: warden's cap
+ sprite:
+ sprite: Clothing/Head/Hats/warden.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: ClothingOuterHardsuitVoidParamed
+ name: paramedic Void Suit
+ sprite:
+ sprite: Clothing/OuterClothing/Hardsuits/paramed.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: MedicalTechFabCircuitboard
+ name: medical techfab machine board
+ sprite:
+ sprite: Objects/Misc/module.rsi
+ state: medical
+
+- type: stealTargetGroup
+ id: ClothingHeadsetAltMedical
+ name: chief medical officer's over-ear headset
+ sprite:
+ sprite: Clothing/Ears/Headsets/medical.rsi
+ state: icon_alt
+
+- type: stealTargetGroup
+ id: ResearchAndDevelopmentServerMachineCircuitboard
+ name: R&D server machine board
+ sprite:
+ sprite: Objects/Misc/module.rsi
+ state: science
+
+- type: stealTargetGroup
+ id: FireAxe
+ name: fireaxe
+ sprite:
+ sprite: Objects/Weapons/Melee/fireaxe.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: AmePart
+ name: AME part
+ sprite:
+ sprite: Objects/Power/AME/ame_part.rsi
+ state: box
+
+- type: stealTargetGroup
+ id: SalvageExpeditionsComputerCircuitboard
+ name: salvage expeditions computer board
+ sprite:
+ sprite: Objects/Misc/module.rsi
+ state: cpu_supply
+
+- type: stealTargetGroup
+ id: CargoShuttleConsoleCircuitboard
+ name: cargo shuttle console board
+ sprite:
+ sprite: Objects/Misc/module.rsi
+ state: cpuboard
+
+- type: stealTargetGroup
+ id: SalvageShuttleConsoleCircuitboard
+ name: salvage shuttle console board
+ sprite:
+ sprite: Objects/Misc/module.rsi
+ state: cpuboard
+
+- type: stealTargetGroup
+ id: ClothingEyesHudBeer
+ name: beer goggles
+ sprite:
+ sprite: Clothing/Eyes/Hud/beergoggles.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: Bible
+ name: bible
+ sprite:
+ sprite: Objects/Specific/Chapel/bible.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: ClothingNeckGoldmedal
+ name: gold medal of crewmanship
+ sprite:
+ sprite: Clothing/Neck/Medals/gold.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: ClothingNeckClownmedal
+ name: clown medal
+ sprite:
+ sprite: Clothing/Neck/Medals/clownmedal.rsi
+ state: icon
+
+#Thief structures
+
+- type: stealTargetGroup
+ id: NuclearBomb
+ name: nuclear fission explosive
+ sprite:
+ sprite: Objects/Devices/nuke.rsi
+ state: nuclearbomb_base
+
+- type: stealTargetGroup
+ id: FaxMachineCaptain
+ name: captain long range fax machine
+ sprite:
+ sprite: Structures/Machines/fax_machine.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: VehicleSecway
+ name: secway
+ sprite:
+ sprite: Objects/Vehicles/secway.rsi
+ state: icon
+
+- type: stealTargetGroup
+ id: ChemDispenser
+ name: chemical dispenser
+ sprite:
+ sprite: Structures/dispensers.rsi
+ state: industrial-working
+
+- type: stealTargetGroup
+ id: XenoArtifact
+ name: big alien artifact
+ sprite:
+ sprite: Objects/Specific/Xenoarchaeology/xeno_artifacts.rsi
+ state: ano28
+
+- type: stealTargetGroup
+ id: FreezerHeater
+ name: freezer or heater
+ sprite:
+ sprite: Structures/Piping/Atmospherics/thermomachine.rsi
+ state: heaterOff
+
+- type: stealTargetGroup
+ id: Teg
+ name: teg generator part
+ sprite:
+ sprite: Structures/Power/Generation/teg.rsi
+ state: teg
+
+- type: stealTargetGroup
+ id: BoozeDispenser
+ name: booze dispenser
+ sprite:
+ sprite: Structures/smalldispensers.rsi
+ state: booze
+
+- type: stealTargetGroup
+ id: AltarNanotrasen
+ name: nanotrasen altar (any)
+ sprite:
+ sprite: Structures/Furniture/Altars/Gods/nanotrasen.rsi
+ state: nanotrasen
+
+- type: stealTargetGroup
+ id: PlantRD
+ name: RD's potted plant
+ sprite:
+ sprite: Structures/Furniture/potted_plants.rsi
+ state: plant-25
+
+# Thief Animal
+
+- type: stealTargetGroup
+ id: AnimalIan
+ name: Ian
+ sprite:
+ sprite: Mobs/Pets/corgi.rsi
+ state: ian
+
+- type: stealTargetGroup
+ id: AnimalBingus
+ name: Bingus
+ sprite:
+ sprite: Mobs/Pets/bingus.rsi
+ state: bingus
+
+- type: stealTargetGroup
+ id: AnimalMcGriff
+ name: McGriff
+ sprite:
+ sprite: Mobs/Pets/mcgriff.rsi
+ state: mcgriff
+
+- type: stealTargetGroup
+ id: AnimalWalter
+ name: Walter
+ sprite:
+ sprite: Mobs/Pets/walter.rsi
+ state: walter
+
+- type: stealTargetGroup
+ id: AnimalMorty
+ name: Morty
+ sprite:
+ sprite: Mobs/Animals/possum.rsi
+ state: possum
+
+- type: stealTargetGroup
+ id: AnimalRenault
+ name: Renault
+ sprite:
+ sprite: Mobs/Animals/fox.rsi
+ state: fox
+
+- type: stealTargetGroup
+ id: AnimalHamlet
+ name: Hamlet
+ sprite:
+ sprite: Mobs/Pets/hamlet.rsi
+ state: hamster-0
+
+- type: stealTargetGroup
+ id: AnimalShiva
+ name: Shiva
+ sprite:
+ sprite: Mobs/Pets/shiva.rsi
+ state: shiva
+
+- type: stealTargetGroup
+ id: AnimalSmile
+ name: Smile
+ sprite:
+ sprite: Mobs/Aliens/slimes.rsi
+ state: rainbow_baby_slime
+
+- type: stealTargetGroup
+ id: AnimalPunPun
+ name: Pun Pun
+ sprite:
+ sprite: Mobs/Animals/monkey.rsi
+ state: monkey
\ No newline at end of file
--- /dev/null
+- type: entity
+ abstract: true
+ parent: BaseObjective
+ id: BaseThiefObjective
+ components:
+ - type: Objective
+ issuer: thief
+ - type: RoleRequirement
+ roles:
+ components:
+ - ThiefRole
+
+- type: entity
+ abstract: true
+ parent: [BaseThiefObjective, BaseStealObjective]
+ id: BaseThiefStealObjective
+ components:
+ - type: StealCondition
+ verifyMapExistance: false
+ descriptionText: objective-condition-thief-description
+
+- type: entity
+ abstract: true
+ parent: [BaseThiefObjective, BaseStealObjective]
+ id: BaseThiefStealCollectionObjective
+ components:
+ - type: StealCondition
+ verifyMapExistance: true
+ descriptionText: objective-condition-thief-description
+
+- type: entity
+ abstract: true
+ parent: [BaseThiefObjective, BaseStealObjective]
+ id: BaseThiefStealStructureObjective
+ components:
+ - type: StealCondition
+ verifyMapExistance: true
+ descriptionText: objective-condition-thief-description
+ - type: Objective
+ difficulty: 2 # it's hard to hide
+
+- type: entity
+ abstract: true
+ parent: [BaseThiefObjective, BaseStealObjective]
+ id: BaseThiefStealAnimalObjective
+ components:
+ - type: StealCondition
+ verifyMapExistance: false
+ checkAlive: true
+ objectiveNoOwnerText: objective-condition-steal-title-alive-no-owner
+ descriptionText: objective-condition-thief-animal-description
+ - type: Objective
+ difficulty: 2 # it's hard to hide
+
+# Collections
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: FigurineStealCollectionObjective
+ components:
+ - type: StealCondition
+ stealGroup: Figurines
+ minCollectionSize: 10
+ maxCollectionSize: 50 #will be limited to the number of figures on the station anyway.
+ - type: Objective
+ difficulty: 0.25
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: HeadCloakStealCollectionObjective
+ components:
+ - type: StealCondition
+ stealGroup: HeadCloak
+ minCollectionSize: 3
+ maxCollectionSize: 6
+ - type: Objective
+ difficulty: 1.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: HeadBedsheetStealCollectionObjective
+ components:
+ - type: StealCondition
+ stealGroup: HeadBedsheet
+ minCollectionSize: 3
+ maxCollectionSize: 6
+ - type: Objective
+ difficulty: 1.0
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: StampStealCollectionObjective
+ components:
+ - type: StealCondition
+ stealGroup: Stamp
+ minCollectionSize: 5
+ maxCollectionSize: 15
+ - type: Objective
+ difficulty: 1.0
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: DoorRemoteStealCollectionObjective
+ components:
+ - type: StealCondition
+ stealGroup: DoorRemote
+ minCollectionSize: 2
+ maxCollectionSize: 5
+ - type: Objective
+ difficulty: 1.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: TechnologyDiskStealCollectionObjective
+ components:
+ - type: NotJobRequirement
+ job: Scientist
+ - type: StealCondition
+ stealGroup: TechnologyDisk
+ minCollectionSize: 10
+ maxCollectionSize: 20
+ verifyMapExistance: false
+ - type: Objective
+ difficulty: 0.8
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: IDCardsStealCollectionObjective
+ components:
+ - type: StealCondition
+ stealGroup: IDCard
+ minCollectionSize: 10
+ maxCollectionSize: 20
+ verifyMapExistance: false
+ - type: Objective
+ difficulty: 0.7
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: EncryptionKeyStealCollectionObjective
+ components:
+ - type: StealCondition
+ stealGroup: EncryptionKey
+ minCollectionSize: 5
+ maxCollectionSize: 25
+ - type: Objective
+ difficulty: 0.7
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: CannabisStealCollectionObjective
+ components:
+ - type: NotJobRequirement
+ job: Botanist
+ - type: StealCondition
+ stealGroup: Cannabis
+ minCollectionSize: 20
+ maxCollectionSize: 30
+ verifyMapExistance: false
+ - type: Objective
+ difficulty: 0.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealCollectionObjective
+ id: LAMPStealCollectionObjective
+ components:
+ - type: SpeciesRequirement
+ allowedSpecies:
+ - Moth
+ - type: StealCondition
+ stealGroup: LAMP
+ minCollectionSize: 1
+ maxCollectionSize: 30
+ verifyMapExistance: true
+ - type: Objective
+ difficulty: 0.5 # just for fun, collectings LAMP on Moth
+
+# steal item
+
+- type: entity #Security subgroup
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ForensicScannerStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Detective
+ - type: StealCondition
+ stealGroup: ForensicScanner
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: AmmoTechFabCircuitboardStealObjective
+ components:
+ - type: StealCondition
+ stealGroup: AmmoTechFabCircuitboard
+ - type: Objective
+ difficulty: 1.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ClothingHeadHatWardenStealObjective
+ components:
+ - type: StealCondition
+ stealGroup: ClothingHeadHatWarden
+ - type: Objective
+ difficulty: 1.2
+
+- type: entity #Medical subgroup
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ClothingOuterHardsuitVoidParamedStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Paramedic
+ - type: StealCondition
+ stealGroup: ClothingOuterHardsuitVoidParamed
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: MedicalTechFabCircuitboardStealObjective
+ components:
+ - type: NotJobRequirement
+ job: MedicalDoctor
+ - type: StealCondition
+ stealGroup: MedicalTechFabCircuitboard
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ClothingHeadsetAltMedicalStealObjective
+ components:
+ - type: NotJobRequirement
+ job: ChiefMedicalOfficer
+ - type: StealCondition
+ stealGroup: ClothingHeadsetAltMedical
+ - type: Objective
+ difficulty: 1
+
+- type: entity #Engineering subgroup
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: FireAxeStealObjective
+ components:
+ - type: NotJobRequirement
+ job: AtmosphericTechnician
+ - type: StealCondition
+ stealGroup: FireAxe
+ - type: Objective
+ difficulty: 0.8
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: AmePartStealObjective
+ components:
+ - type: NotJobRequirement
+ job: StationEngineer
+ - type: StealCondition
+ stealGroup: AmePart
+ - type: Objective
+ difficulty: 1
+
+- type: entity #Cargo subgroup
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ExpeditionsCircuitboardStealObjective
+ components:
+ - type: NotJobRequirement
+ job: SalvageSpecialist
+ - type: StealCondition
+ stealGroup: SalvageExpeditionsComputerCircuitboard
+ - type: Objective
+ difficulty: 0.7
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: CargoShuttleCircuitboardStealObjective
+ components:
+ - type: NotJobRequirement
+ job: CargoTechnician
+ - type: StealCondition
+ stealGroup: CargoShuttleConsoleCircuitboard
+ - type: Objective
+ difficulty: 0.7
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: SalvageShuttleCircuitboardStealObjective
+ components:
+ - type: NotJobRequirement
+ job: SalvageSpecialist
+ - type: StealCondition
+ stealGroup: SalvageShuttleConsoleCircuitboard
+ - type: Objective
+ difficulty: 0.7
+
+- type: entity #Service subgroup
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ClothingEyesHudBeerStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Bartender
+ - type: StealCondition
+ stealGroup: ClothingEyesHudBeer
+ - type: Objective
+ difficulty: 0.3
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: BibleStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Chaplain
+ - type: StealCondition
+ stealGroup: Bible
+ - type: Objective
+ difficulty: 0.4
+
+- type: entity #Other subgroup
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ClothingNeckGoldmedalStealObjective
+ components:
+ - type: NotJobRequirement
+ job: HeadOfPersonnel
+ - type: StealCondition
+ stealGroup: ClothingNeckGoldmedal
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealObjective
+ id: ClothingNeckClownmedalStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Captain
+ - type: StealCondition
+ stealGroup: ClothingNeckClownmedal
+ - type: Objective
+ difficulty: 1
+
+# Structures
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: NuclearBombStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Captain
+ - type: StealCondition
+ stealGroup: NuclearBomb
+ - type: Objective
+ difficulty: 2.5 #Good luck
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: FaxMachineCaptainStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Captain
+ - type: StealCondition
+ stealGroup: FaxMachineCaptain
+ - type: Objective
+ difficulty: 2
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: VehicleSecwayStealObjective
+ components:
+ - type: NotJobRequirement
+ job: SecurityOfficer
+ - type: StealCondition
+ stealGroup: VehicleSecway
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: ChemDispenserStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Chemist
+ - type: StealCondition
+ stealGroup: ChemDispenser
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: XenoArtifactStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Scientist
+ - type: StealCondition
+ stealGroup: XenoArtifact
+ - type: Objective
+ difficulty: 0.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: FreezerHeaterStealObjective
+ components:
+ - type: NotJobRequirement
+ job: AtmosphericTechnician
+ - type: StealCondition
+ stealGroup: FreezerHeater
+ - type: Objective
+ difficulty: 0.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: TegStealObjective
+ components:
+ - type: NotJobRequirement
+ job: AtmosphericTechnician
+ - type: StealCondition
+ stealGroup: Teg
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: BoozeDispenserStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Bartender
+ - type: StealCondition
+ stealGroup: BoozeDispenser
+ - type: Objective
+ difficulty: 0.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: AltarNanotrasenStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Chaplain
+ - type: StealCondition
+ stealGroup: AltarNanotrasen
+ - type: Objective
+ difficulty: 0.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealStructureObjective
+ id: PlantRDStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Scientist
+ - type: StealCondition
+ stealGroup: PlantRD
+ - type: Objective
+ difficulty: 0.8
+
+# Animal
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: IanStealObjective
+ components:
+ - type: NotJobRequirement
+ job: HeadOfPersonnel
+ - type: StealCondition
+ stealGroup: AnimalIan
+ - type: Objective
+ difficulty: 2.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: BingusStealObjective
+ components:
+ - type: StealCondition
+ stealGroup: AnimalBingus
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: McGriffStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Detective
+ - type: StealCondition
+ stealGroup: AnimalMcGriff
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: WalterStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Chemist
+ - type: StealCondition
+ stealGroup: AnimalWalter
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: MortyStealObjective
+ components:
+ - type: StealCondition
+ stealGroup: AnimalMorty
+ - type: Objective
+ difficulty: 0.5
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: RenaultStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Captain
+ - type: StealCondition
+ stealGroup: AnimalRenault
+ - type: Objective
+ difficulty: 2
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: HamletStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Captain
+ - type: StealCondition
+ stealGroup: AnimalHamlet
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: ShivaStealObjective
+ components:
+ - type: NotJobRequirement
+ job: SecurityOfficer
+ - type: StealCondition
+ stealGroup: AnimalShiva
+ - type: Objective
+ difficulty: 2
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: SmileStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Scientist
+ - type: StealCondition
+ stealGroup: AnimalSmile
+ - type: Objective
+ difficulty: 1
+
+- type: entity
+ noSpawn: true
+ parent: BaseThiefStealAnimalObjective
+ id: PunPunStealObjective
+ components:
+ - type: NotJobRequirement
+ job: Bartender
+ - type: StealCondition
+ stealGroup: AnimalPunPun
+ - type: Objective
+ difficulty: 2
+
+# Escape
+
+- type: entity
+ noSpawn: true
+ parent: [BaseThiefObjective, BaseLivingObjective]
+ id: EscapeThiefShuttleObjective
+ name: Escape to centcom alive and unrestrained.
+ description: You don't want your illegal activities to be discovered by anyone, do you?
+ components:
+ - type: Objective
+ difficulty: 1.3
+ icon:
+ sprite: Structures/Furniture/chairs.rsi
+ state: shuttle
+ - type: EscapeShuttleCondition
parent: [BaseTraitorObjective, BaseStealObjective]
id: BaseTraitorStealObjective
components:
+ - type: StealCondition
+ verifyMapExistance: false
- type: Objective
difficulty: 2.75
- type: NotJobRequirement
job: ChiefMedicalOfficer
- type: StealCondition
- prototype: Hypospray
+ stealGroup: Hypospray
owner: job-name-cmo
## rd
-- type: entity
- abstract: true
- parent: BaseTraitorStealObjective
- id: BaseRDObjective
- components:
- - type: NotJobRequirement
- job: ResearchDirector
- - type: StealCondition
- owner: job-name-rd
-
- type: entity
noSpawn: true
- parent: BaseRDObjective
+ parent: BaseTraitorStealObjective
id: RDHardsuitStealObjective
components:
- type: StealCondition
- prototype: ClothingOuterHardsuitRd
+ stealGroup: ClothingOuterHardsuitRd
+ owner: job-name-rd
- type: entity
noSpawn: true
- parent: BaseRDObjective
+ parent: BaseTraitorStealObjective
id: HandTeleporterStealObjective
components:
- type: StealCondition
- prototype: HandTeleporter
+ stealGroup: HandTeleporter
+ owner: job-name-rd
## hos
- type: NotJobRequirement
job: HeadOfSecurity
- type: StealCondition
- prototype: BookSecretDocuments
+ stealGroup: BookSecretDocuments
owner: job-name-hos
## ce
- type: NotJobRequirement
job: ChiefEngineer
- type: StealCondition
- prototype: ClothingShoesBootsMagAdv
+ stealGroup: ClothingShoesBootsMagAdv
owner: job-name-ce
## qm
- type: NotJobRequirement
job: Quartermaster
- type: StealCondition
- prototype: BoxFolderQmClipboard
+ stealGroup: BoxFolderQmClipboard
owner: job-name-qm
## hop
- type: NotJobRequirement
job: HeadOfPersonnel
- type: StealCondition
- prototype: FoodMeatCorgi
+ stealGroup: FoodMeatCorgi
owner: objective-condition-steal-Ian
## cap
id: CaptainIDStealObjective
components:
- type: StealCondition
- prototype: CaptainIDCard
+ stealGroup: CaptainIDCard
- type: entity
noSpawn: true
id: CaptainJetpackStealObjective
components:
- type: StealCondition
- prototype: JetpackCaptainFilled
+ stealGroup: JetpackCaptainFilled
- type: entity
noSpawn: true
id: CaptainGunStealObjective
components:
- type: StealCondition
- prototype: WeaponAntiqueLaser
+ stealGroup: WeaponAntiqueLaser
owner: job-name-captain
- type: entity
difficulty: 4
- type: NotCommandRequirement
- type: StealCondition
- prototype: NukeDisk
+ stealGroup: NukeDisk
owner: objective-condition-steal-station
--- /dev/null
+- type: antag
+ id: Thief
+ name: roles-antag-thief-name
+ antagonist: true
+ setPreference: true
+ objective: roles-antag-space-ninja-objective
\ No newline at end of file
{
"name": "pinpointer-syndicate"
},
+ {
+ "name": "pinpointer_thief"
+ },
{
"name": "pinpointer-way"
},
--- /dev/null
+{
+ "version": 1,
+ "license": "CC0-1.0",
+ "copyright": "Created by TheShuEd(github) for ss14",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "icon"
+ }
+ ]
+}
},
{
"name": "keys"
+ },
+ {
+ "name": "icon"
}
]
}