New Thief minor antagonist (#21520)

* start working

* add right-click thief antagins
some architecture restruct

* add meh thief greeting audio

* add thief subgamemode to Traitors gamemode

* add late join thief (not tested yet)
add briefing

* add pacifism

* add Steal tasks to thief

* fix crash thief+traitor on person

* add new condition: collection steal

* add tracking of succes collection objective

* add stamp collection target
remove some boring steal target
add check pulling entity to collection target

* finalize first 2 group objective

* start merging stealing objective systems

* merging

* finish merging. Now traitor steal objective work better

* we don't check the items of pullable sentient entity

* clear naming, enable thief signle item objective start

* objective pack add

* finish with steal item objectives

* convert string to ProtoId<>

* some clean up

* add thieves to revolution game mode

* Update Resources/Locale/en-US/game-ticking/game-presets/preset-thief.ftl

Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>

* Update Resources/Locale/en-US/game-ticking/game-presets/preset-thief.ftl

Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>

* update pacifism: fix crashing, monkey-thief without pacified

* adaptive animal briefing, cleaning locales

* add structure steal objectives

* remove RCD target

* add thiefs to manifest, but bug with traitor duplications

* add escape objective

* add chat briefing

* setup animal objective group system

* add animal steal objectives

* add animal objectives notroleconditions

* add morty

* now thief mode has a chance of not launching Now there are a random number of thieves per round from 1 to 3

* 6 hours of trying to fix duplicate tasks. Failure

* added thief pinpointer (buggy)

* start thief backpack UI work

* revert pinpointer for scope reason

* UI continue work

* add thief starter kits content

* remove ERP kit :trollface:

* finally! giving starting items to thief. Now it playable, but still need more work

* clean up

* fix

* fox

* add merged items into thief
new Starting Kit (buggy)

* fix YES antag menu

* objection tweaks

* remove hearts objective, working on spawning things from toolbox

* smug

* fixes

* add race specifier objective condition LAMPS

* meh

* fix fix fix

* the alive

* Adding stamps

* Update backpack.ftl

* Revert1

* Revert ftl

* add voice mask to communicator kit

* Update Resources/Locale/en-US/administration/antag.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/game-ticking/game-presets/preset-thief.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/thief/backpack.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/objectives/conditions/steal.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/thief/backpack.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/thief/backpack.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/thief/backpack.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/thief/backpack.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/prototypes/roles/antags.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* Update Resources/Locale/en-US/thief/backpack.ftl

Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>

* update

* fix

* more reusable function, add documentation

* fix doc

* faint fixes

---------

Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>
Co-authored-by: Colin-Tel <113523727+Colin-Tel@users.noreply.github.com>
This commit is contained in:
Ed
2023-12-24 12:58:28 +03:00
committed by GitHub
parent 82349d46ae
commit 144af233c4
94 changed files with 2545 additions and 129 deletions

View File

@@ -0,0 +1,52 @@
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());
}
}

View File

@@ -0,0 +1,39 @@
<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>

View File

@@ -0,0 +1,56 @@
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;
}
}

View File

@@ -0,0 +1,23 @@
<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>

View File

@@ -0,0 +1,22 @@
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);
}
}

View File

@@ -1,5 +1,6 @@
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;
@@ -15,6 +16,7 @@ namespace Content.Server.Administration.Systems;
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!;
@@ -119,5 +121,22 @@ public sealed partial class AdminVerbSystem
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);
}
}

View File

@@ -25,6 +25,7 @@ using Robust.Server.Audio;
using Robust.Server.Containers;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Content.Server.Shuttles.Components;
namespace Content.Server.Antag;
@@ -149,6 +150,72 @@ public sealed class AntagSelectionSystem : GameRuleSystem<GameRuleComponent>
}
}
/// <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>

View File

@@ -0,0 +1,54 @@
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");
}

View File

@@ -0,0 +1,194 @@
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");
}
}

View File

@@ -1,4 +1,5 @@
using System.Linq;
using Content.Server.Antag;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Mind;
@@ -30,6 +31,7 @@ namespace Content.Server.GameTicking.Rules;
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!;
@@ -117,8 +119,8 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
}
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)
{
@@ -153,61 +155,6 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
}
}
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();

View File

@@ -0,0 +1,15 @@
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();
}

View File

@@ -1,28 +1,64 @@
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;
}

View File

@@ -0,0 +1,18 @@
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;
}

View File

@@ -129,6 +129,9 @@ public sealed class ObjectivesSystem : SharedObjectivesSystem
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)

View File

@@ -0,0 +1,34 @@
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;
}
}
}

View File

@@ -1,76 +1,136 @@
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));
var group = _proto.Index(condition.Comp.StealGroup);
_metaData.SetEntityName(uid, title, args.Meta);
_metaData.SetEntityDescription(uid, description, args.Meta);
_objectives.SetIcon(uid, new SpriteSpecifier.EntityPrototype(comp.Prototype), args.Objective);
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, condition);
}
private void OnGetProgress(EntityUid uid, StealConditionComponent comp, ref ObjectiveGetProgressEvent args)
private float GetProgress(MindComponent mind, StealConditionComponent condition)
{
args.Progress = GetProgress(args.Mind, comp.Prototype);
}
private float GetProgress(MindComponent mind, string prototype)
{
// 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)
@@ -78,16 +138,38 @@ public sealed class StealConditionSystem : EntitySystem
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;
}
}

View File

@@ -1,4 +1,4 @@
using Content.Shared.Roles;
using Content.Shared.Roles;
namespace Content.Server.Roles;
@@ -17,6 +17,7 @@ public sealed class RoleSystem : SharedRoleSystem
SubscribeAntagEvents<SubvertedSiliconRoleComponent>();
SubscribeAntagEvents<TraitorRoleComponent>();
SubscribeAntagEvents<ZombieRoleComponent>();
SubscribeAntagEvents<ThiefRoleComponent>();
}
public string? MindGetBriefing(EntityUid? mindId)

View File

@@ -0,0 +1,8 @@
using Content.Shared.Roles;
namespace Content.Server.Roles;
[RegisterComponent]
public sealed partial class ThiefRoleComponent : AntagonistRoleComponent
{
}

View File

@@ -0,0 +1,25 @@
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");
}

View File

@@ -0,0 +1,79 @@
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));
}
}

View File

@@ -0,0 +1,15 @@
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;
}

View File

@@ -0,0 +1,63 @@
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;
}
}

View File

@@ -0,0 +1,18 @@
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();
}

View File

@@ -8,6 +8,11 @@
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."

Binary file not shown.

View File

@@ -4,9 +4,11 @@ admin-verb-make-zombie = Zombifies the target immediately.
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

View File

@@ -0,0 +1,20 @@
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

View File

@@ -1,6 +1,11 @@
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.

View File

@@ -27,3 +27,6 @@ roles-antag-subverted-silicon-objective = Follow your new laws and do bad unto t
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.

View File

@@ -0,0 +1,62 @@
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.

View File

@@ -0,0 +1,107 @@
- 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

View File

@@ -96,6 +96,8 @@
sprite: Clothing/Ears/Headsets/medical.rsi
- type: Clothing
sprite: Clothing/Ears/Headsets/medical.rsi
- type: StealTarget
stealGroup: ClothingHeadsetAltMedical
- type: entity
parent: ClothingHeadsetAlt

View File

@@ -43,6 +43,8 @@
- type: Clothing
sprite: Clothing/Eyes/Hud/beergoggles.rsi
- type: ShowThirstIcons
- type: StealTarget
stealGroup: ClothingEyesHudBeer
- type: SolutionScanner
- type: entity

View File

@@ -471,6 +471,8 @@
sprite: Clothing/Head/Hats/warden.rsi
- type: Clothing
sprite: Clothing/Head/Hats/warden.rsi
- type: StealTarget
stealGroup: ClothingHeadHatWarden
- type: entity
parent: ClothingHeadBase

View File

@@ -6,6 +6,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/cap.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -15,6 +17,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/hos.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -24,6 +28,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/ce.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -33,6 +39,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/cmo.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -42,6 +50,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/rd.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -51,6 +61,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/qm.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -60,6 +72,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/hop.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -87,6 +101,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/capcloakformal.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase
@@ -96,6 +112,8 @@
components:
- type: Sprite
sprite: Clothing/Neck/Cloaks/admin.rsi
- type: StealTarget
stealGroup: HeadCloak
- type: entity
parent: ClothingNeckBase

View File

@@ -20,6 +20,8 @@
sprite: Clothing/Neck/Medals/gold.rsi
- type: Clothing
sprite: Clothing/Neck/Medals/gold.rsi
- type: StealTarget
stealGroup: ClothingNeckGoldmedal
- type: entity
parent: ClothingNeckBase
@@ -86,3 +88,5 @@
sprite: Clothing/Neck/Medals/clownmedal.rsi
- type: Clothing
sprite: Clothing/Neck/Medals/clownmedal.rsi
- type: StealTarget
stealGroup: ClothingNeckClownmedal

View File

@@ -371,6 +371,8 @@
clothingPrototype: ClothingHeadHelmetHardsuitRd
- type: StaticPrice
price: 750
- type: StealTarget
stealGroup: ClothingOuterHardsuitRd
#Head of Security's Hardsuit
- type: entity

View File

@@ -115,3 +115,5 @@
Radiation: 0.75
Caustic: 0.5
- type: GroupExamine
- type: StealTarget
stealGroup: ClothingOuterHardsuitVoidParamed

View File

@@ -53,6 +53,8 @@
- HighRiskItem
- type: StaticPrice
price: 750
- type: StealTarget
stealGroup: ClothingShoesBootsMagAdv
- type: entity
parent: ClothingShoesBootsMag

View File

@@ -34,6 +34,8 @@
tags:
- CannotSuicide
- VimPilot
- type: StealTarget
stealGroup: AnimalIan
- type: entity
name: Old Ian
@@ -238,6 +240,8 @@
tags:
- CannotSuicide
- VimPilot
- type: StealTarget
stealGroup: AnimalBingus
- type: entity
name: McGriff
@@ -301,6 +305,8 @@
tags:
- CannotSuicide
- VimPilot
- type: StealTarget
stealGroup: AnimalMcGriff
- type: entity
name: Paperwork
@@ -398,6 +404,8 @@
tags:
- CannotSuicide
- VimPilot
- type: StealTarget
stealGroup: AnimalWalter
- type: entity
name: Morty
@@ -420,6 +428,8 @@
tags:
- CannotSuicide
- VimPilot
- type: StealTarget
stealGroup: AnimalMorty
- type: entity
name: Morty
@@ -534,6 +544,8 @@
tags:
- CannotSuicide
- VimPilot
- type: StealTarget
stealGroup: AnimalRenault
- type: entity
name: Hamlet
@@ -574,6 +586,8 @@
- CannotSuicide
- Hamster
- VimPilot
- type: StealTarget
stealGroup: AnimalHamlet
- type: entity
name: Shiva
@@ -649,6 +663,8 @@
tags:
- CannotSuicide
- VimPilot
- type: StealTarget
stealGroup: AnimalShiva
- type: entity
name: Willow
@@ -747,6 +763,8 @@
attributes:
proper: true
gender: female
- type: StealTarget
stealGroup: AnimalSmile
- type: entity
name: Pun Pun
@@ -781,3 +799,5 @@
attributes:
proper: true
gender: male
- type: StealTarget
stealGroup: AnimalPunPun

View File

@@ -307,6 +307,8 @@
Quantity: 20
- type: StaticPrice
price: 750
- type: StealTarget
stealGroup: FoodMeatCorgi
- type: entity
name: raw crab meat

View File

@@ -27,6 +27,8 @@
color: "#cc6600"
radius: 2.0
energy: 4.0
- type: StealTarget
stealGroup: LAMP
- type: entity
parent: CarvedPumpkin

View File

@@ -61,6 +61,8 @@
requirements:
MatterBin: 1
Manipulator: 1
- type: StealTarget
stealGroup: AmmoTechFabCircuitboard
- type: entity
id: MedicalTechFabCircuitboard
@@ -80,6 +82,8 @@
Amount: 2
DefaultPrototype: Beaker
ExamineName: Glass Beaker
- type: StealTarget
stealGroup: MedicalTechFabCircuitboard
- type: entity
id: CircuitImprinterMachineCircuitboard

View File

@@ -124,6 +124,8 @@
state: cpu_supply
- type: ComputerBoard
prototype: ComputerSalvageExpedition
- type: StealTarget
stealGroup: SalvageExpeditionsComputerCircuitboard
- type: entity
parent: BaseComputerCircuitboard
@@ -133,6 +135,8 @@
components:
- type: ComputerBoard
prototype: ComputerShuttleCargo
- type: StealTarget
stealGroup: CargoShuttleConsoleCircuitboard
- type: entity
parent: BaseComputerCircuitboard
@@ -142,6 +146,8 @@
components:
- type: ComputerBoard
prototype: ComputerShuttleSalvage
- type: StealTarget
stealGroup: SalvageShuttleConsoleCircuitboard
- type: entity
parent: BaseComputerCircuitboard

View File

@@ -9,6 +9,8 @@
sprite: Objects/Devices/door_remote.rsi
- type: Access
- type: DoorRemote
- type: StealTarget
stealGroup: DoorRemote
- type: entity
parent: DoorRemoteDefault

View File

@@ -10,6 +10,8 @@
sprite: Objects/Devices/encryption_keys.rsi
- type: Sprite
sprite: Objects/Devices/encryption_keys.rsi
- type: StealTarget
stealGroup: EncryptionKey
- type: entity
parent: EncryptionKey

View File

@@ -26,6 +26,8 @@
- type: GuideHelp
guides:
- DNA
- type: StealTarget
stealGroup: ForensicScanner
- type: entity
name: forensic scanner report

View File

@@ -12,3 +12,5 @@
- type: Tag
tags:
- HighRiskItem
- type: StealTarget
stealGroup: HandTeleporter

View File

@@ -67,6 +67,8 @@
- type: ContainerContainer
containers:
Nuke: !type:ContainerSlot
- type: StealTarget
stealGroup: NuclearBomb
- type: entity
parent: NuclearBomb

View File

@@ -17,6 +17,8 @@
- type: Tag
tags:
- Figurine
- type: StealTarget
stealGroup: Figurines
- type: entity
parent: BaseFigurine

View File

@@ -61,6 +61,8 @@
state: sheetcaptain
- type: Clothing
sprite: Clothing/Neck/Bedsheets/captain.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetCE
@@ -72,6 +74,8 @@
state: sheetce
- type: Clothing
sprite: Clothing/Neck/Bedsheets/ce.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetCentcom
@@ -83,6 +87,8 @@
state: sheetcentcom
- type: Clothing
sprite: Clothing/Neck/Bedsheets/centcom.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetClown
@@ -105,6 +111,8 @@
state: sheetcmo
- type: Clothing
sprite: Clothing/Neck/Bedsheets/cmo.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetCosmos
@@ -158,6 +166,8 @@
state: sheethop
- type: Clothing
sprite: Clothing/Neck/Bedsheets/hop.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetHOS
@@ -169,6 +179,8 @@
state: sheethos
- type: Clothing
sprite: Clothing/Neck/Bedsheets/hos.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetIan
@@ -242,6 +254,8 @@
state: sheetqm
- type: Clothing
sprite: Clothing/Neck/Bedsheets/qm.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetRainbow
@@ -263,6 +277,8 @@
state: sheetrd
- type: Clothing
sprite: Clothing/Neck/Bedsheets/rd.rsi
- type: StealTarget
stealGroup: HeadBedsheet
- type: entity
id: BedsheetBrigmedic

View File

@@ -20,6 +20,8 @@
- type: Tag
tags:
- HighRiskItem
- type: StealTarget
stealGroup: NukeDisk
- type: entity
name: nuclear authentication disk

View File

@@ -49,6 +49,8 @@
- type: Appearance
- type: Physics
canCollide: false
- type: StealTarget
stealGroup: LAMP
- type: entity
name: lamp

View File

@@ -22,6 +22,8 @@
tags:
- DoorBumpOpener
- WhitelistChameleon
- type: StealTarget
stealGroup: IDCard
#IDs with layers
@@ -115,6 +117,8 @@
- DoorBumpOpener
- WhitelistChameleon
- HighRiskItem
- type: StealTarget
stealGroup: CaptainIDCard
- type: entity
parent: IDCardStandard

View File

@@ -646,6 +646,8 @@
damage:
types:
Blunt: 10
- type: StealTarget
stealGroup: BoxFolderQmClipboard
# Stamps
- type: entity
@@ -669,6 +671,8 @@
state: stamp-mime
- type: Item
size: Tiny
- type: StealTarget
stealGroup: Stamp
- type: entity
name: alternate rubber stamp

View File

@@ -12,3 +12,5 @@
tags:
- Book
- HighRiskItem
- type: StealTarget
stealGroup: BookSecretDocuments

View File

@@ -18,3 +18,5 @@
- type: Tag
tags:
- DroneUsable
- type: StealTarget
stealGroup: AmePart

View File

@@ -46,6 +46,8 @@
- type: Tag
tags:
- Book
- type: StealTarget
stealGroup: Bible
- type: entity
parent: Bible

View File

@@ -17,6 +17,8 @@
reagents:
- ReagentId: THC
Quantity: 15
- type: StealTarget
stealGroup: Cannabis
- type: entity
name: dried cannabis leaves
@@ -36,6 +38,8 @@
- type: Sprite
sprite: Objects/Specific/Hydroponics/tobacco.rsi
state: dried
- type: StealTarget
stealGroup: Cannabis
- type: entity
name: ground cannabis
@@ -64,6 +68,8 @@
- Smokable
- type: Item
size: Tiny
- type: StealTarget
stealGroup: Cannabis
- type: entity
name: tobacco leaves

View File

@@ -52,7 +52,9 @@
- 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

View File

@@ -26,6 +26,8 @@
- type: Tag
tags:
- HighRiskItem
- type: StealTarget
stealGroup: Hypospray
- type: entity
name: gorlex hypospray

View File

@@ -59,6 +59,8 @@
- type: TechnologyDisk
- type: StaticPrice
price: 100
- type: StealTarget
stealGroup: TechnologyDisk
- type: entity
parent: TechnologyDisk

View File

@@ -58,6 +58,8 @@
- type: GuideHelp
guides:
- Xenoarchaeology
- type: StealTarget
stealGroup: XenoArtifact
- type: entity
parent: BaseXenoArtifact

View File

@@ -66,6 +66,8 @@
- type: Appearance
- type: StaticPrice
price: 40
- type: StealTarget
stealGroup: LAMP
- type: entity
name: seclite

View File

@@ -158,6 +158,8 @@
- type: Tag
tags:
- HighRiskItem
- type: StealTarget
stealGroup: JetpackCaptainFilled
# Filled captain
- type: entity

View File

@@ -53,6 +53,8 @@
- type: ContainerContainer
containers:
cell_slot: !type:ContainerSlot {}
- type: StealTarget
stealGroup: LAMP
- type: entity
parent: Lantern

View File

@@ -135,3 +135,30 @@
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

View File

@@ -215,6 +215,8 @@
path: /Audio/Effects/Vehicle/vehiclestartup.ogg
params:
volume: -3
- type: StealTarget
stealGroup: VehicleSecway
- type: entity
parent: BaseVehicleRideable

View File

@@ -472,6 +472,8 @@
- Sidearm
- type: StaticPrice
price: 750
- type: StealTarget
stealGroup: WeaponAntiqueLaser
- type: entity
name: advanced laser pistol

View File

@@ -42,6 +42,8 @@
- type: Prying
- type: UseDelay
delay: 1
- type: StealTarget
stealGroup: FireAxe
- type: IgniteOnMeleeHit
fireStacks: -4

View File

@@ -22,3 +22,5 @@
- type: GuideHelp
guides:
- Bartender
- type: StealTarget
stealGroup: BoozeDispenser

View File

@@ -35,3 +35,5 @@
guides:
- Chemicals
- Chemist
- type: StealTarget
stealGroup: ChemDispenser

View File

@@ -64,6 +64,8 @@
max: 3
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: StealTarget
stealGroup: AltarNanotrasen
- type: entity
id: AltarChaos

View File

@@ -234,6 +234,8 @@
components:
- type: Sprite
state: plant-25
- type: StealTarget
stealGroup: PlantRD
- type: entity
id: PottedPlant26

View File

@@ -105,3 +105,5 @@
- type: FaxMachine
name: "Captain's Office"
receiveNukeCodes: true
- type: StealTarget
stealGroup: FaxMachineCaptain

View File

@@ -298,6 +298,8 @@
board: ThermomachineFreezerMachineCircuitBoard
- type: DeviceNetwork
prefix: device-address-prefix-freezer
- type: StealTarget
stealGroup: FreezerHeater
- type: entity
parent: GasThermoMachineFreezer
@@ -341,6 +343,8 @@
board: ThermomachineHeaterMachineCircuitBoard
- type: DeviceNetwork
prefix: device-address-prefix-heater
- type: StealTarget
stealGroup: FreezerHeater
- type: entity
parent: GasThermoMachineHeater

View File

@@ -98,6 +98,8 @@
path: /Audio/Ambience/Objects/vending_machine_hum.ogg
- type: GuideHelp
guides: [ TEG, Power ]
- type: StealTarget
stealGroup: Teg
- type: entity
id: TegCirculator
@@ -175,6 +177,8 @@
- type: AtmosUnsafeUnanchor
- type: TegCirculator
- type: StealTarget
stealGroup: Teg
- # Spawned by the client-side circulator examine code to indicate the inlet/outlet direction.
type: entity

View File

@@ -27,3 +27,11 @@
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

View File

@@ -74,6 +74,8 @@
noSpawn: true
components:
- type: TraitorRule
- type: ThiefRule #the thieves come as an extension of another gamemode
ruleChance: 0.5
- type: entity
id: Revolutionary
@@ -81,6 +83,8 @@
noSpawn: true
components:
- type: RevolutionaryRule
- type: ThiefRule #the thieves come as an extension of another gamemode
ruleChance: 0.5
- type: entity
id: Sandbox

View File

@@ -91,6 +91,10 @@
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

View File

@@ -41,4 +41,89 @@
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...

View File

@@ -0,0 +1,408 @@
# 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

View File

@@ -0,0 +1,620 @@
- 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

View File

@@ -26,6 +26,8 @@
parent: [BaseTraitorObjective, BaseStealObjective]
id: BaseTraitorStealObjective
components:
- type: StealCondition
verifyMapExistance: false
- type: Objective
difficulty: 2.75
@@ -150,36 +152,28 @@
- type: NotJobRequirement
job: ChiefMedicalOfficer
- type: StealCondition
prototype: Hypospray
stealGroup: Hypospray
owner: job-name-cmo
## rd
- type: entity
abstract: true
noSpawn: true
parent: BaseTraitorStealObjective
id: BaseRDObjective
id: RDHardsuitStealObjective
components:
- type: NotJobRequirement
job: ResearchDirector
- type: StealCondition
stealGroup: ClothingOuterHardsuitRd
owner: job-name-rd
- type: entity
noSpawn: true
parent: BaseRDObjective
id: RDHardsuitStealObjective
components:
- type: StealCondition
prototype: ClothingOuterHardsuitRd
- type: entity
noSpawn: true
parent: BaseRDObjective
parent: BaseTraitorStealObjective
id: HandTeleporterStealObjective
components:
- type: StealCondition
prototype: HandTeleporter
stealGroup: HandTeleporter
owner: job-name-rd
## hos
@@ -194,7 +188,7 @@
- type: NotJobRequirement
job: HeadOfSecurity
- type: StealCondition
prototype: BookSecretDocuments
stealGroup: BookSecretDocuments
owner: job-name-hos
## ce
@@ -207,7 +201,7 @@
- type: NotJobRequirement
job: ChiefEngineer
- type: StealCondition
prototype: ClothingShoesBootsMagAdv
stealGroup: ClothingShoesBootsMagAdv
owner: job-name-ce
## qm
@@ -220,7 +214,7 @@
- type: NotJobRequirement
job: Quartermaster
- type: StealCondition
prototype: BoxFolderQmClipboard
stealGroup: BoxFolderQmClipboard
owner: job-name-qm
## hop
@@ -233,7 +227,7 @@
- type: NotJobRequirement
job: HeadOfPersonnel
- type: StealCondition
prototype: FoodMeatCorgi
stealGroup: FoodMeatCorgi
owner: objective-condition-steal-Ian
## cap
@@ -255,7 +249,7 @@
id: CaptainIDStealObjective
components:
- type: StealCondition
prototype: CaptainIDCard
stealGroup: CaptainIDCard
- type: entity
noSpawn: true
@@ -263,7 +257,7 @@
id: CaptainJetpackStealObjective
components:
- type: StealCondition
prototype: JetpackCaptainFilled
stealGroup: JetpackCaptainFilled
- type: entity
noSpawn: true
@@ -271,7 +265,7 @@
id: CaptainGunStealObjective
components:
- type: StealCondition
prototype: WeaponAntiqueLaser
stealGroup: WeaponAntiqueLaser
owner: job-name-captain
- type: entity
@@ -286,5 +280,5 @@
difficulty: 4
- type: NotCommandRequirement
- type: StealCondition
prototype: NukeDisk
stealGroup: NukeDisk
owner: objective-condition-steal-station

View File

@@ -0,0 +1,6 @@
- type: antag
id: Thief
name: roles-antag-thief-name
antagonist: true
setPreference: true
objective: roles-antag-space-ninja-objective

View File

@@ -147,6 +147,9 @@
{
"name": "pinpointer-syndicate"
},
{
"name": "pinpointer_thief"
},
{
"name": "pinpointer-way"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

View File

@@ -0,0 +1,22 @@
{
"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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

View File

@@ -35,6 +35,9 @@
},
{
"name": "keys"
},
{
"name": "icon"
}
]
}