From a1bd277c9bec59cb270bf5ad8f43c2a075769efd Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Sun, 12 Jul 2026 17:49:34 -0700 Subject: [PATCH 01/14] Ughhh part 1 why isn't it working uhhghhghg --- .../ScoreThiefConditionComponent.cs | 25 +++ .../ScoreThiefPriceModifierComponent.cs | 13 ++ .../Systems/ScoreThiefConditionSystem.cs | 150 ++++++++++++++++++ .../Prototypes/GameRules/subgamemodes.yml | 19 ++- .../_Funkystation/Objectives/scoreThief.yml | 13 ++ 5 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 Content.Server/_Funkystation/Objectives/Components/ScoreThiefConditionComponent.cs create mode 100644 Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs create mode 100644 Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs create mode 100644 Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml diff --git a/Content.Server/_Funkystation/Objectives/Components/ScoreThiefConditionComponent.cs b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefConditionComponent.cs new file mode 100644 index 00000000000..cd8a7ee2b18 --- /dev/null +++ b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefConditionComponent.cs @@ -0,0 +1,25 @@ +using Content.Server._Funkystation.Objectives.Systems; + +namespace Content.Server._Funkystation.Objectives.Components; + +/// +/// Requires that you steal enough to fill a speso quota +/// +[RegisterComponent, Access(typeof(ScoreThiefConditionSystem))] +public sealed partial class ScoreThiefConditionComponent : Component +{ + [DataField(required: true)] + public int AmountSpesos; + + [DataField(required: true)] + public int AmountSpesosVariance; + + [DataField] + public int AmountSpesosVarianceInterval = 1000; + + [DataField] + public bool CheckStealAreas = true; + + public int TargetScore = 0; + public int CurrentScore = 0; +} diff --git a/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs new file mode 100644 index 00000000000..5f114daa06d --- /dev/null +++ b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Server._Funkystation.Objectives.Components; + +/// +/// Modifies the price of an entity for scorethief, including possibly making it worthless +/// +public sealed partial class ScoreThiefPriceModifierComponent : Component +{ + [DataField(required: true)] + public string Reason; + + [DataField(required: true)] + public string Multiplier; +} diff --git a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs new file mode 100644 index 00000000000..250de4f2250 --- /dev/null +++ b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs @@ -0,0 +1,150 @@ +using Content.Server._Funkystation.Objectives.Components; +using Content.Server.Cargo.Systems; +using Content.Shared.Interaction; +using Content.Shared.Objectives.Components; +using Content.Shared.Objectives.Systems; +using Robust.Shared.Containers; +using Robust.Shared.Random; +using Robust.Shared.Utility; + +namespace Content.Server._Funkystation.Objectives.Systems; + +/// +/// The objective system for scorethief +/// +// Large portions of this were taken from https://github.com/funky-station/forky-station/blob/22a547c7c8aa1f0f6ac5f8c3e9941f2dfc25bd17/Content.Server/Objectives/Systems/StealConditionSystem.cs +public sealed partial class ScoreThiefConditionSystem : EntitySystem +{ + [Dependency] private IRobustRandom _random = default!; + [Dependency] private MetaDataSystem _metaData = default!; + [Dependency] private SharedObjectivesSystem _objectives = default!; + [Dependency] private EntityLookupSystem _lookup = default!; + [Dependency] private SharedInteractionSystem _interaction = default!; + [Dependency] private IEntityManager _entManager = default!; + [Dependency] private EntityQuery _containerQuery = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAssigned); + SubscribeLocalEvent(OnAfterAssign); + SubscribeLocalEvent(OnGetProgress); + + } + + private void OnAssigned(Entity condition, ref ObjectiveAssignedEvent args) + { + condition.Comp.TargetScore = _random.Next( + (condition.Comp.AmountSpesos - condition.Comp.AmountSpesosVariance)/condition.Comp.AmountSpesosVarianceInterval, + (condition.Comp.AmountSpesos + condition.Comp.AmountSpesosVariance)/condition.Comp.AmountSpesosVarianceInterval + ) * condition.Comp.AmountSpesosVarianceInterval; + } + + private void OnAfterAssign(Entity condition, ref ObjectiveAfterAssignEvent args) + { + string rsiState; + switch(condition.Comp.TargetScore) + { + case 1: + rsiState = "cash"; + break; + case <= 10: + rsiState = "cash_10"; + break; + case <= 100: + rsiState = "cash_100"; + break; + case <= 500: + rsiState = "cash_500"; + break; + case <= 1000: + rsiState = "cash_1000"; + break; + case <= 5000: + rsiState = "cash_5000"; + break; + case <= 10000: + rsiState = "cash_10000"; + break; + case <= 25000: + rsiState = "cash_25000"; + break; + case <= 50000: + rsiState = "cash_50000"; + break; + case <= 100000: + rsiState = "cash_100000"; + break; + default: + rsiState = "cash_1000000"; + break; + } + var sprite = new SpriteSpecifier.Rsi(new ResPath("/Textures/Objects/Economy/cash.rsi"), rsiState); + + _metaData.SetEntityName(condition.Owner, + Loc.GetString("scorethief-objective-title-one") + condition.Comp.TargetScore + Loc.GetString("scorethief-objective-title-two"), + args.Meta); + _metaData.SetEntityDescription(condition.Owner, condition.Comp.CurrentScore + "/" + condition.Comp.TargetScore, args.Meta); + _objectives.SetIcon(condition.Owner, sprite, args.Objective); + } + + private void OnGetProgress(Entity condition, ref ObjectiveGetProgressEvent args) + { + if (!_containerQuery.TryGetComponent(args.MindId, out var currentManager)) + return; + + var containerStack = new Stack(); + var priceSystem = _entManager.System(); + condition.Comp.CurrentScore = 0; + + // Check steal areas + if (condition.Comp.CheckStealAreas) + { + var areasQuery = AllEntityQuery(); + while (areasQuery.MoveNext(out var uid, out var area, out var xform)) + { + if (!area.Owners.Contains(args.MindId)) + continue; + + HashSet> nearestEnts = new(); + + _lookup.GetEntitiesInRange(xform.Coordinates, area.Range, nearestEnts); + foreach (var ent in nearestEnts) + { + if (!_interaction.InRangeUnobstructed((uid, xform), (ent, ent.Comp), range: area.Range)) + continue; + + //TODO: use ScoreThiefPriceModifierComponent + condition.Comp.CurrentScore += (int)priceSystem.GetPrice(ent, false); + + //If it's a container, check it later + if (_containerQuery.TryGetComponent(ent, out var containerManager)) + { + containerStack.Push(containerManager); + } + } + } + } + + // recursively check each container + // checks inventory, bag, implants, etc. + //TODO: use ScoreThiefPriceModifierComponent + do + { + foreach (var container in currentManager.Containers.Values) + { + foreach (var entity in container.ContainedEntities) + { + condition.Comp.CurrentScore += (int)priceSystem.GetPrice(entity, false); + + // if it's a container check its contents + if (_containerQuery.TryGetComponent(entity, out var containerManager)) + containerStack.Push(containerManager); + } + } + } while (containerStack.TryPop(out currentManager)); + + args.Progress = Math.Clamp((float)condition.Comp.CurrentScore / condition.Comp.TargetScore, 0f, 1f); + } +} diff --git a/Resources/Prototypes/GameRules/subgamemodes.yml b/Resources/Prototypes/GameRules/subgamemodes.yml index dfe815cf13c..748d68b2d91 100644 --- a/Resources/Prototypes/GameRules/subgamemodes.yml +++ b/Resources/Prototypes/GameRules/subgamemodes.yml @@ -5,15 +5,18 @@ - type: ThiefRule - type: AntagObjectives objectives: + - ScoreThiefObjective # Funky change - EscapeThiefShuttleObjective - - type: AntagRandomObjectives - sets: - - groups: ThiefBigObjectiveGroups - prob: 0.7 - maxPicks: 1 - - groups: ThiefObjectiveGroups - maxPicks: 10 - maxDifficulty: 2.5 + # Funky changes start + #- type: AntagRandomObjectives + # sets: + # - groups: ThiefBigObjectiveGroups + # prob: 0.7 + # maxPicks: 1 + # - groups: ThiefObjectiveGroups + # maxPicks: 10 + # maxDifficulty: 2.5 + # Funky changes end - type: AntagSelection agentName: thief-round-end-agent-name selectionTime: PrePlayerSpawn diff --git a/Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml b/Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml new file mode 100644 index 00000000000..76ef9d33af8 --- /dev/null +++ b/Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml @@ -0,0 +1,13 @@ +- type: entity + abstract: true + parent: BaseThiefObjective + id: ScoreThiefObjective + components: + - type: Objective + difficulty: 0.0 + - type: RoleRequirement + roles: + - ThiefRole + - type: ScoreThiefCondition + amountSpesos: 35000 + amountSpesosVariance: 10000 From 9a509cc27fd03761b4adc0dbd1b8fed526b52e23 Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Sun, 12 Jul 2026 20:15:37 -0700 Subject: [PATCH 02/14] OH MY FUCKING GOD IT WAS ABSTRACT --- Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml b/Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml index 76ef9d33af8..8ad802e2caa 100644 --- a/Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml +++ b/Resources/Prototypes/_Funkystation/Objectives/scoreThief.yml @@ -1,5 +1,4 @@ - type: entity - abstract: true parent: BaseThiefObjective id: ScoreThiefObjective components: From 6960fa32ca50e025ef91eb0d1dd8bf4222faec7a Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Sun, 12 Jul 2026 23:05:13 -0700 Subject: [PATCH 03/14] It works --- .../Objectives/Systems/ScoreThiefConditionSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs index 250de4f2250..ec1f5622cb2 100644 --- a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs +++ b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs @@ -85,12 +85,12 @@ private void OnAfterAssign(Entity condition, ref O _metaData.SetEntityName(condition.Owner, Loc.GetString("scorethief-objective-title-one") + condition.Comp.TargetScore + Loc.GetString("scorethief-objective-title-two"), args.Meta); - _metaData.SetEntityDescription(condition.Owner, condition.Comp.CurrentScore + "/" + condition.Comp.TargetScore, args.Meta); _objectives.SetIcon(condition.Owner, sprite, args.Objective); } private void OnGetProgress(Entity condition, ref ObjectiveGetProgressEvent args) { + _metaData.SetEntityDescription(condition.Owner, (int)((float)condition.Comp.CurrentScore/condition.Comp.TargetScore*100) + "%"); if (!_containerQuery.TryGetComponent(args.MindId, out var currentManager)) return; From dded32ddd250840ac795058cc8a768311f7b219b Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Thu, 16 Jul 2026 16:23:27 -0700 Subject: [PATCH 04/14] it works! --- .../ScoreThiefPriceModifierComponent.cs | 9 ++- .../Systems/ScoreThiefConditionSystem.cs | 71 +++++++++++++------ .../Components/InnateAppraisalComponent.cs | 17 +++++ .../Systems/InnateAppraisalSystem.cs | 67 +++++++++++++++++ .../objectives/conditions/scorethief.ftl | 10 +++ .../Entities/Mobs/Player/silicon.yml | 5 ++ .../Entities/Objects/Misc/dat_fukken_disk.yml | 5 ++ .../Objects/Misc/identification_cards.yml | 17 ++++- .../Machines/Computers/computers.yml | 10 +++ .../Structures/Machines/anomaly_equipment.yml | 5 ++ .../Structures/Machines/gravity_generator.yml | 5 ++ .../Entities/Structures/Machines/nuke.yml | 5 ++ .../Structures/Machines/telecomms.yml | 5 ++ .../Entities/Structures/Power/smes.yml | 6 ++ .../Structures/Shuttles/station_anchor.yml | 5 ++ Resources/Prototypes/Roles/Antags/thief.yml | 3 + .../FissionGenerator/nuclear_reactor.yml | 5 ++ 17 files changed, 228 insertions(+), 22 deletions(-) create mode 100644 Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs create mode 100644 Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs create mode 100644 Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl diff --git a/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs index 5f114daa06d..1cf4b0b4d37 100644 --- a/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs +++ b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs @@ -1,13 +1,20 @@ +using Content.Server._Funkystation.Objectives.Systems; +using Robust.Shared.Serialization.TypeSerializers.Implementations; + namespace Content.Server._Funkystation.Objectives.Components; /// /// Modifies the price of an entity for scorethief, including possibly making it worthless /// +[RegisterComponent, Access(typeof(ScoreThiefConditionSystem))] public sealed partial class ScoreThiefPriceModifierComponent : Component { + /// + /// Must be a Loc string + /// [DataField(required: true)] public string Reason; [DataField(required: true)] - public string Multiplier; + public double Multiplier; } diff --git a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs index ec1f5622cb2..dac0036481f 100644 --- a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs +++ b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs @@ -1,8 +1,10 @@ using Content.Server._Funkystation.Objectives.Components; using Content.Server.Cargo.Systems; using Content.Shared.Interaction; +using Content.Shared.Mind.Components; using Content.Shared.Objectives.Components; using Content.Shared.Objectives.Systems; +using JetBrains.Annotations; using Robust.Shared.Containers; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -13,6 +15,7 @@ namespace Content.Server._Funkystation.Objectives.Systems; /// The objective system for scorethief /// // Large portions of this were taken from https://github.com/funky-station/forky-station/blob/22a547c7c8aa1f0f6ac5f8c3e9941f2dfc25bd17/Content.Server/Objectives/Systems/StealConditionSystem.cs +[UsedImplicitly] public sealed partial class ScoreThiefConditionSystem : EntitySystem { [Dependency] private IRobustRandom _random = default!; @@ -22,8 +25,10 @@ public sealed partial class ScoreThiefConditionSystem : EntitySystem [Dependency] private SharedInteractionSystem _interaction = default!; [Dependency] private IEntityManager _entManager = default!; [Dependency] private EntityQuery _containerQuery = default!; + [Dependency] private EntityQuery _modifierQuery = default!; + [Dependency] private EntityQuery _mindQuery = default!; - public override void Initialize() + public override void Initialize() { base.Initialize(); @@ -83,19 +88,16 @@ private void OnAfterAssign(Entity condition, ref O var sprite = new SpriteSpecifier.Rsi(new ResPath("/Textures/Objects/Economy/cash.rsi"), rsiState); _metaData.SetEntityName(condition.Owner, - Loc.GetString("scorethief-objective-title-one") + condition.Comp.TargetScore + Loc.GetString("scorethief-objective-title-two"), + Loc.GetString("scorethief-objective-title-one") + " " + condition.Comp.TargetScore + " " + Loc.GetString("scorethief-objective-title-two"), args.Meta); _objectives.SetIcon(condition.Owner, sprite, args.Objective); } private void OnGetProgress(Entity condition, ref ObjectiveGetProgressEvent args) { - _metaData.SetEntityDescription(condition.Owner, (int)((float)condition.Comp.CurrentScore/condition.Comp.TargetScore*100) + "%"); - if (!_containerQuery.TryGetComponent(args.MindId, out var currentManager)) + if (!_containerQuery.TryGetComponent(args.Mind.CurrentEntity, out var currentManager)) return; - var containerStack = new Stack(); - var priceSystem = _entManager.System(); condition.Comp.CurrentScore = 0; // Check steal areas @@ -115,36 +117,65 @@ private void OnGetProgress(Entity condition, ref O if (!_interaction.InRangeUnobstructed((uid, xform), (ent, ent.Comp), range: area.Range)) continue; - //TODO: use ScoreThiefPriceModifierComponent - condition.Comp.CurrentScore += (int)priceSystem.GetPrice(ent, false); - - //If it's a container, check it later - if (_containerQuery.TryGetComponent(ent, out var containerManager)) - { - containerStack.Push(containerManager); - } + condition.Comp.CurrentScore += GetValue(ent, out _, out _); } } } + args.Progress = Math.Clamp((float)condition.Comp.CurrentScore / condition.Comp.TargetScore, 0f, 1f); + _metaData.SetEntityDescription(condition.Owner, Math.Clamp((int)((float)condition.Comp.CurrentScore/condition.Comp.TargetScore*100), 0, 100) + "%"); + } + + /// Get the price of an item (not including contained items) taking into account ScoreThiefPriceModifierComponent + public int GetValue(EntityUid entity, out bool alive, out string? reason) + { + reason = null; + alive = false; + var priceSystem = _entManager.System(); + double multiplier = 1; + if (_modifierQuery.TryGetComponent(entity, out var modifier)) + { + multiplier = modifier.Multiplier; + reason = Loc.GetString(modifier.Reason); + } + else if (_mindQuery.TryGetComponent(entity, out _)) + { + multiplier = 0; + alive = true; + reason = Loc.GetString("scorethief-modifier-alive"); + } + var price = (int)(priceSystem.GetPrice(entity, false)*multiplier); + //If it's a container and not alive, check it + if (_containerQuery.TryGetComponent(entity, out var containerManager) && !alive) + { + price += GetValueRecursive(containerManager); + } + + return price; + } + + private int GetValueRecursive(ContainerManagerComponent? currentManager) + { + if (currentManager == null) + return 0; + var value = 0; + var containerStack = new Stack(); // recursively check each container // checks inventory, bag, implants, etc. - //TODO: use ScoreThiefPriceModifierComponent do { foreach (var container in currentManager.Containers.Values) { foreach (var entity in container.ContainedEntities) { - condition.Comp.CurrentScore += (int)priceSystem.GetPrice(entity, false); + value += GetValue(entity, out var alive, out _); - // if it's a container check its contents - if (_containerQuery.TryGetComponent(entity, out var containerManager)) + // if it's a container and not alive check its contents + if (_containerQuery.TryGetComponent(entity, out var containerManager) && !alive) containerStack.Push(containerManager); } } } while (containerStack.TryPop(out currentManager)); - - args.Progress = Math.Clamp((float)condition.Comp.CurrentScore / condition.Comp.TargetScore, 0f, 1f); + return value; } } diff --git a/Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs b/Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs new file mode 100644 index 00000000000..ab78d2e0f74 --- /dev/null +++ b/Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs @@ -0,0 +1,17 @@ +using Content.Server._Funkystation.ScoreThief.Systems; + +namespace Content.Server._Funkystation.ScoreThief.Components; + +/// +/// Gives an entity the innate ability to appraise items it looks at +/// +[RegisterComponent, Access(typeof(InnateAppraisalSystem))] +public sealed partial class InnateAppraisalComponent : Component +{ + // Use ScoreThiefPriceModifierComponent? + [DataField] + public bool BlackMarket = false; + + [DataField] + public bool Precise = true; +} diff --git a/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs b/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs new file mode 100644 index 00000000000..a7d3b7aab75 --- /dev/null +++ b/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs @@ -0,0 +1,67 @@ +using Content.Server._Funkystation.ScoreThief.Components; +using Content.Shared.Examine; +using Content.Shared.Verbs; +using JetBrains.Annotations; +using Robust.Shared.Utility; +using Content.Server._Funkystation.Objectives.Systems; +using Content.Server.Cargo.Systems; +using Robust.Shared.Containers; + +namespace Content.Server._Funkystation.ScoreThief.Systems; + +[UsedImplicitly] +public sealed partial class InnateAppraisalSystem : EntitySystem +{ + + [Dependency] private EntityQuery _appraisalQuery = default!; + [Dependency] private ExamineSystemShared _examineSystem = default!; + [Dependency] private IEntityManager _entManager = default!; + + public override void Initialize() + { + base.Initialize(); + // Transform component because everything you can examine has it. We can't make args ref without this. + // Jank solution but it works sooooo whatever + SubscribeLocalEvent>(OnExamineVerb); + } + + // Parts of this method were taken from https://github.com/funky-station/forky-station/blob/272393a35fb0a88097f7041c49356fb595aac138/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs + private void OnExamineVerb(Entity _, ref GetVerbsEvent args) + { + if (!_appraisalQuery.TryComp(args.User, out var comp)) + return; + var target = args.Target; + var user = args.User; + var verb = new ExamineVerb() + { + Act = () => + { + var pricingSystem = _entManager.System(); + var scoreThiefConditionSystem = _entManager.System(); + var price = 0; + string? reason = null; + if (comp.BlackMarket) + { + price = scoreThiefConditionSystem.GetValue(target, out var _, out reason); + } + else + { + price = (int)pricingSystem.GetPrice(target); + } + var markup = new FormattedMessage(); + markup.AddMarkupOrThrow(Loc.GetString("scorethief-inspect-one") + " [color=green]" + price + "[/color] " + Loc.GetString("scorethief-inspect-two")); + if (reason != null) + { + markup.AddMarkupOrThrow("\n\n[color=gold]" + reason + "[/color]"); + } + _examineSystem.SendExamineTooltip(user, target, markup, false, false); + }, + Text = Loc.GetString("scorethief-appraise"), + Message = Loc.GetString("scorethief-appraise"), + Category = VerbCategory.Examine, + Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Objects/Tools/appraisal-tool.rsi"), "icon"), + }; + + args.Verbs.Add(verb); + } +} diff --git a/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl new file mode 100644 index 00000000000..b9c2341087e --- /dev/null +++ b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl @@ -0,0 +1,10 @@ +scorethief-objective-title-one = Steal +scorethief-objective-title-two = worth of spesos of items +scorethief-inspect-one = This is worth +scorethief-inspect-two = spesos. +scorethief-appraise = Estimate the price of the item +scorethief-modifier-alive = Living things are too hard to transport to be worth it and dead things spoil. +scorethief-modifier-id = Basic ID cards are too traceable to be worth anything. +scorethief-modifier-cap-id = Certain people are willing to pay a lot for all-access on a Nanotrasen station. +scorethief-modifier-hop-id = Certain people are willing to pay a lot for near all-access on a Nanotrasen station. +scorethief-modifier-critical-infrastructure = Critical station infrastructure is too high profile and easily traceable to be worth anything. diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 6175c19d531..af570fb7057 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -331,6 +331,11 @@ - StationAiCoreElectronics - type: StaticPrice price: 5000 + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes # The job-ready version of an AI spawn. - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml index 523385788ba..dc5ee13c35a 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml @@ -26,6 +26,11 @@ - GhostOnlyWarp - type: StealTarget stealGroup: NukeDisk + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes - type: entity name: nuclear authentication disk diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 189982ff7d1..7b64045f1a5 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -25,6 +25,11 @@ - WhitelistChameleonIdCard - type: StealTarget stealGroup: IDCard + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-id" + multiplier: 0 + # End funky changes #IDs with layers @@ -71,6 +76,11 @@ - HighRiskItem - type: StealTarget stealGroup: CaptainIDCard + # Funky changes start + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-cap-id" + multiplier: 1000 + # Funky changes end - type: entity parent: IDCardStandard @@ -91,6 +101,11 @@ heldPrefix: silver - type: PresetIdCard job: HeadOfPersonnel + # Funky changes start + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-hop-id" + multiplier: 8000 + # Funky changes end - type: entity parent: IDCardStandard @@ -1295,7 +1310,7 @@ parent: IDCardStandard id: UniversalIDCard name: universal ID card - suffix: Admin + suffix: AdminA description: An ID card that gives you access beyond your wildest dreams. components: - type: Sprite diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index fd4a6711c3a..d1a218d846b 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -236,6 +236,11 @@ board: CargoShuttleConsoleCircuitboard - type: StealTarget stealGroup: CargoShuttleConsoleCircuitboard + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes - type: entity parent: BaseComputerAiAccess @@ -683,6 +688,11 @@ damageModifierSet: StructuralMetallicStrong - type: Injurable damageContainer: StructuralInorganic + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes - type: entity parent: ComputerComms diff --git a/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml b/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml index 519f3ff165f..82bdba9d0c4 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml @@ -331,3 +331,8 @@ - type: GuideHelp guides: - AnomalousResearch + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes diff --git a/Resources/Prototypes/Entities/Structures/Machines/gravity_generator.yml b/Resources/Prototypes/Entities/Structures/Machines/gravity_generator.yml index 84948f38fb4..7fdff40ccdd 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/gravity_generator.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/gravity_generator.yml @@ -79,6 +79,11 @@ color: "#a8ffd9" - type: StaticPrice price: 5000 + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes - type: entity parent: [ GravityGenerator, ConstructibleMachine ] diff --git a/Resources/Prototypes/Entities/Structures/Machines/nuke.yml b/Resources/Prototypes/Entities/Structures/Machines/nuke.yml index ae163cfacce..9eda328d50f 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/nuke.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/nuke.yml @@ -117,6 +117,11 @@ tags: - GhostOnlyWarp - type: FTLSmashImmune + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes - type: entity parent: NuclearBomb diff --git a/Resources/Prototypes/Entities/Structures/Machines/telecomms.yml b/Resources/Prototypes/Entities/Structures/Machines/telecomms.yml index 3caa56d3f8f..bacc217352a 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/telecomms.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/telecomms.yml @@ -184,6 +184,11 @@ key_slots: !type:Container machine_board: !type:Container machine_parts: !type:Container + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes - type: entity parent: TelecomServer diff --git a/Resources/Prototypes/Entities/Structures/Power/smes.yml b/Resources/Prototypes/Entities/Structures/Power/smes.yml index 9cccff3df77..fe8e83b83e8 100644 --- a/Resources/Prototypes/Entities/Structures/Power/smes.yml +++ b/Resources/Prototypes/Entities/Structures/Power/smes.yml @@ -102,6 +102,11 @@ - PowerStorage - VoltageNetworks - Power + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes # Interface - type: BatteryInterface @@ -116,6 +121,7 @@ - type: ActivatableUI key: enum.BatteryUiKey.Key + # SMES' in use - type: entity diff --git a/Resources/Prototypes/Entities/Structures/Shuttles/station_anchor.yml b/Resources/Prototypes/Entities/Structures/Shuttles/station_anchor.yml index 1467cf52ed9..2c36c0fdb70 100644 --- a/Resources/Prototypes/Entities/Structures/Shuttles/station_anchor.yml +++ b/Resources/Prototypes/Entities/Structures/Shuttles/station_anchor.yml @@ -45,6 +45,11 @@ - LargeMobMask layer: - WallLayer + # Start funky changes + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # End funky changes - type: entity id: StationAnchorIndestructible diff --git a/Resources/Prototypes/Roles/Antags/thief.yml b/Resources/Prototypes/Roles/Antags/thief.yml index 7584a164c61..5524988161a 100644 --- a/Resources/Prototypes/Roles/Antags/thief.yml +++ b/Resources/Prototypes/Roles/Antags/thief.yml @@ -22,6 +22,9 @@ - type: Thieving stripTimeReduction: 2 stealthy: true + - type: InnateAppraisal + blackMarket: True + precise: False mindRoles: - MindRoleThief briefing: diff --git a/Resources/Prototypes/_FarHorizons/Entities/Structures/Power/Generation/FissionGenerator/nuclear_reactor.yml b/Resources/Prototypes/_FarHorizons/Entities/Structures/Power/Generation/FissionGenerator/nuclear_reactor.yml index d0cb19ab072..26313583c73 100644 --- a/Resources/Prototypes/_FarHorizons/Entities/Structures/Power/Generation/FissionGenerator/nuclear_reactor.yml +++ b/Resources/Prototypes/_FarHorizons/Entities/Structures/Power/Generation/FissionGenerator/nuclear_reactor.yml @@ -143,6 +143,11 @@ guides: - NuclearReactor - Power + # Funky changes begin + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-critical-infrastructure" + multiplier: 0 + # Funky changes end # Crew nuclear reactors - type: entity From a68e3ca23646725a3b90a0003199b75d103b5e17 Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Thu, 16 Jul 2026 16:47:10 -0700 Subject: [PATCH 05/14] Encryption keys :) --- .../objectives/conditions/scorethief.ftl | 4 ++++ .../Objects/Devices/encryption_keys.yml | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl index b9c2341087e..d8abec71fba 100644 --- a/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl +++ b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl @@ -7,4 +7,8 @@ scorethief-modifier-alive = Living things are too hard to transport to be worth scorethief-modifier-id = Basic ID cards are too traceable to be worth anything. scorethief-modifier-cap-id = Certain people are willing to pay a lot for all-access on a Nanotrasen station. scorethief-modifier-hop-id = Certain people are willing to pay a lot for near all-access on a Nanotrasen station. +scorethief-modifier-master-comms = Certain people are willing to pay a lot for all-comms on a Nanotrasen station. +scorethief-modifier-centcomm-comms = Certain people are willing to pay a lot to snoop on Central Command. +scorethief-modifier-command-comms = Certain people are willing to pay a lot for command comms. +scorethief-modifier-sec-comms = Certain people are willing to pay for security comms. scorethief-modifier-critical-infrastructure = Critical station infrastructure is too high profile and easily traceable to be worth anything. diff --git a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml index 0ad24174705..775dca55fe9 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml @@ -10,6 +10,10 @@ sprite: Objects/Devices/encryption_keys.rsi - type: Sprite sprite: Objects/Devices/encryption_keys.rsi + # Funky changes start + - type: StaticPrice + price: 10 + # Funky changes end - type: entity parent: EncryptionKey @@ -61,6 +65,11 @@ layers: - state: crypt_blue - state: nano_label + # Funky changes start + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-centcomm-comms" + multiplier: 1500 + # Funky changes end - type: entity parent: [ EncryptionKey, BaseCentcommCommandContraband ] @@ -83,6 +92,11 @@ layers: - state: crypt_gold - state: cap_label + # Funky changes start + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-command-comms" + multiplier: 1200 + # Funky changes end - type: entity parent: [ EncryptionKey, BaseCommandContraband ] @@ -101,6 +115,11 @@ - type: Tag tags: - EncryptionCommand + # Funky changes start + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-command-comms" + multiplier: 1000 + # Funky changes end - type: entity parent: [ EncryptionKey, BaseEngineeringContraband ] @@ -204,6 +223,11 @@ - type: Tag tags: - EncryptionSecurity + # Funky changes start + - type: ScoreThiefPriceModifier + reason: "scorethief-modifier-sec-comms" + multiplier: 100 + # Funky changes end - type: entity parent: [ EncryptionKey, BaseCivilianContraband ] From 3d82ce6f819f89e9b614ab23c20aff33768898a0 Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Thu, 16 Jul 2026 16:54:34 -0700 Subject: [PATCH 06/14] Update roundstart role text --- Content.Server/GameTicking/Rules/ThiefRuleSystem.cs | 6 +++--- .../objectives/conditions/scorethief.ftl | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs b/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs index d6239449a25..690d991f50d 100644 --- a/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ThiefRuleSystem.cs @@ -40,11 +40,11 @@ private string MakeBriefing(EntityUid ent) { var isHuman = HasComp(ent); var briefing = isHuman - ? Loc.GetString("thief-role-greeting-human") - : Loc.GetString("thief-role-greeting-animal"); + ? Loc.GetString("scorethief-role-greeting-human") // Funky change + : Loc.GetString("scorethief-role-greeting-animal"); // Funky change if (isHuman) - briefing += "\n \n" + Loc.GetString("thief-role-greeting-equipment") + "\n"; + briefing += "\n \n" + Loc.GetString("scorethief-role-greeting-equipment") + "\n"; // Funky change return briefing; } diff --git a/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl index d8abec71fba..7b31d5beeaa 100644 --- a/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl +++ b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl @@ -12,3 +12,14 @@ scorethief-modifier-centcomm-comms = Certain people are willing to pay a lot to scorethief-modifier-command-comms = Certain people are willing to pay a lot for command comms. scorethief-modifier-sec-comms = Certain people are willing to pay for security comms. scorethief-modifier-critical-infrastructure = Critical station infrastructure is too high profile and easily traceable to be worth anything. + +scorethief-role-greeting-human = + You are criminal scum, a professional thief previously arrested and on parole for grand theft. You are back to steal again. + You were forcibly given a pacifism implant after your last arrest, but that won't stop you from getting meeting the market's demands. + +scorethief-role-greeting-animal = + You are a kleptomaniac animal. + Steal things that you like. + +scorethief-role-greeting-equipment = + You have a satchel of thieves' tools and possess the innate ability to steal without notice. Choose your starting equipment, and do your work stealthily. From 61036f319f81173f815d0c97433831a6d8c3aa06 Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Thu, 16 Jul 2026 18:58:31 -0700 Subject: [PATCH 07/14] Wahoo! I fixed it! --- .../ScoreThiefPriceModifierComponent.cs | 4 +- .../Systems/ScoreThiefConditionSystem.cs | 70 +++++++++++-------- .../Systems/InnateAppraisalSystem.cs | 2 +- Resources/Prototypes/Roles/Antags/thief.yml | 2 + 4 files changed, 46 insertions(+), 32 deletions(-) diff --git a/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs index 1cf4b0b4d37..80e11b7d172 100644 --- a/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs +++ b/Content.Server/_Funkystation/Objectives/Components/ScoreThiefPriceModifierComponent.cs @@ -12,8 +12,8 @@ public sealed partial class ScoreThiefPriceModifierComponent : Component /// /// Must be a Loc string /// - [DataField(required: true)] - public string Reason; + [DataField] + public string? Reason = null; [DataField(required: true)] public double Multiplier; diff --git a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs index dac0036481f..f80ee1147a8 100644 --- a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs +++ b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs @@ -95,10 +95,8 @@ private void OnAfterAssign(Entity condition, ref O private void OnGetProgress(Entity condition, ref ObjectiveGetProgressEvent args) { - if (!_containerQuery.TryGetComponent(args.Mind.CurrentEntity, out var currentManager)) - return; - condition.Comp.CurrentScore = 0; + var checkPlayer = true; // Check steal areas if (condition.Comp.CheckStealAreas) @@ -117,65 +115,79 @@ private void OnGetProgress(Entity condition, ref O if (!_interaction.InRangeUnobstructed((uid, xform), (ent, ent.Comp), range: area.Range)) continue; - condition.Comp.CurrentScore += GetValue(ent, out _, out _); + condition.Comp.CurrentScore += GetValue(ent, out _, area: true); + if (ent == args.Mind.CurrentEntity) + { + checkPlayer = false; + } } } } + // Check thief's inventory + if (args.Mind.CurrentEntity != null && checkPlayer) + { + condition.Comp.CurrentScore += GetValue(args.Mind.CurrentEntity.Value, out _, self: true); + } + args.Progress = Math.Clamp((float)condition.Comp.CurrentScore / condition.Comp.TargetScore, 0f, 1f); _metaData.SetEntityDescription(condition.Owner, Math.Clamp((int)((float)condition.Comp.CurrentScore/condition.Comp.TargetScore*100), 0, 100) + "%"); } /// Get the price of an item (not including contained items) taking into account ScoreThiefPriceModifierComponent - public int GetValue(EntityUid entity, out bool alive, out string? reason) + public int GetValue(EntityUid entity, out string? reason, bool area = false, bool self = false) { reason = null; - alive = false; var priceSystem = _entManager.System(); double multiplier = 1; if (_modifierQuery.TryGetComponent(entity, out var modifier)) { multiplier = modifier.Multiplier; - reason = Loc.GetString(modifier.Reason); + if (modifier.Reason != null) + { + reason = Loc.GetString(modifier.Reason); + } } - else if (_mindQuery.TryGetComponent(entity, out _)) + + if (_mindQuery.HasComp(entity)) { + if (!self) + { + return 0; + } multiplier = 0; - alive = true; - reason = Loc.GetString("scorethief-modifier-alive"); } - var price = (int)(priceSystem.GetPrice(entity, false)*multiplier); - //If it's a container and not alive, check it - if (_containerQuery.TryGetComponent(entity, out var containerManager) && !alive) + + var price = 0; + + price = (int)(priceSystem.GetPrice(entity, false)*multiplier); + + if (_containerQuery.TryComp(entity, out var containerManager) && !area) { - price += GetValueRecursive(containerManager); + foreach (var container in containerManager.Containers.Values) + { + foreach (var ent in container.ContainedEntities) + { + price += GetValue(ent, out _); + } + } } return price; } - private int GetValueRecursive(ContainerManagerComponent? currentManager) + private int GetValueRecursive(ContainerManagerComponent currentManager) { - if (currentManager == null) - return 0; var value = 0; - var containerStack = new Stack(); // recursively check each container // checks inventory, bag, implants, etc. - do + foreach (var container in currentManager.Containers.Values) { - foreach (var container in currentManager.Containers.Values) + foreach (var entity in container.ContainedEntities) { - foreach (var entity in container.ContainedEntities) - { - value += GetValue(entity, out var alive, out _); - - // if it's a container and not alive check its contents - if (_containerQuery.TryGetComponent(entity, out var containerManager) && !alive) - containerStack.Push(containerManager); - } + value += GetValue(entity, out _); } - } while (containerStack.TryPop(out currentManager)); + } return value; } } diff --git a/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs b/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs index a7d3b7aab75..f8888bfb852 100644 --- a/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs +++ b/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs @@ -42,7 +42,7 @@ private void OnExamineVerb(Entity _, ref GetVerbsEvent Date: Thu, 16 Jul 2026 19:13:22 -0700 Subject: [PATCH 08/14] fix HoP ID multiplier --- .../Prototypes/Entities/Objects/Misc/identification_cards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 7b64045f1a5..4b8e31e3acf 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -104,7 +104,7 @@ # Funky changes start - type: ScoreThiefPriceModifier reason: "scorethief-modifier-hop-id" - multiplier: 8000 + multiplier: 800 # Funky changes end - type: entity From f9dd792ee15550c1a3d26cab67dbe247112493fb Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Thu, 16 Jul 2026 19:22:50 -0700 Subject: [PATCH 09/14] Restore innate appraisal ability --- .../Objectives/Systems/ScoreThiefConditionSystem.cs | 1 + .../_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs index f80ee1147a8..89fb8e5d85a 100644 --- a/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs +++ b/Content.Server/_Funkystation/Objectives/Systems/ScoreThiefConditionSystem.cs @@ -153,6 +153,7 @@ public int GetValue(EntityUid entity, out string? reason, bool area = false, boo { if (!self) { + reason = Loc.GetString("scorethief-modifier-alive"); return 0; } multiplier = 0; diff --git a/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs b/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs index f8888bfb852..2784e436b18 100644 --- a/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs +++ b/Content.Server/_Funkystation/ScoreThief/Systems/InnateAppraisalSystem.cs @@ -42,7 +42,7 @@ private void OnExamineVerb(Entity _, ref GetVerbsEvent Date: Thu, 16 Jul 2026 19:52:27 -0700 Subject: [PATCH 10/14] Rebalance multipliers --- .../Prototypes/Entities/Objects/Devices/encryption_keys.yml | 4 ++-- .../Prototypes/Entities/Objects/Misc/identification_cards.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml index 775dca55fe9..2d0a1d5d0bf 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml @@ -95,7 +95,7 @@ # Funky changes start - type: ScoreThiefPriceModifier reason: "scorethief-modifier-command-comms" - multiplier: 1200 + multiplier: 400 # Funky changes end - type: entity @@ -118,7 +118,7 @@ # Funky changes start - type: ScoreThiefPriceModifier reason: "scorethief-modifier-command-comms" - multiplier: 1000 + multiplier: 200 # Funky changes end - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 4b8e31e3acf..5c992d7108d 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -79,7 +79,7 @@ # Funky changes start - type: ScoreThiefPriceModifier reason: "scorethief-modifier-cap-id" - multiplier: 1000 + multiplier: 500 # Funky changes end - type: entity @@ -104,7 +104,7 @@ # Funky changes start - type: ScoreThiefPriceModifier reason: "scorethief-modifier-hop-id" - multiplier: 800 + multiplier: 400 # Funky changes end - type: entity From 5986d3268fa2cce9babfa51cf29838514b4708ec Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Thu, 16 Jul 2026 23:05:41 -0700 Subject: [PATCH 11/14] Update the guidebook --- .../Guidebook/Antagonist/Thieves.xml | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/Resources/ServerInfo/Guidebook/Antagonist/Thieves.xml b/Resources/ServerInfo/Guidebook/Antagonist/Thieves.xml index 6dd6278334c..609ef555416 100644 --- a/Resources/ServerInfo/Guidebook/Antagonist/Thieves.xml +++ b/Resources/ServerInfo/Guidebook/Antagonist/Thieves.xml @@ -8,7 +8,10 @@ - Thieves are petty yet crafty [color=green]criminals[/color] who can't keep their hands to themselves. You were forcefully given a [bold]pacifism implant[/bold] after your last arrest, but you won't let that stop you from trying to add to your collection. + Thieves are the source of most of the world's black market goods. You were given a [bold]pacifism implant[/bold] after your last arrest, but that won't stop you from meeting the market's demands. + + ## The Black Market + Your goal is to sell items on the [color=cyan]black market[/color]. Anything you have on you or near your [color=cyan]thieving beacon[/color] at the end of the shift will count towards your speso goal. ## Art of the Steal Unlike other antagonists, [bold]staying out of trouble is almost a requirement for you[/bold] because of your implant. @@ -51,22 +54,10 @@ - ## Centerpiece of the Collection - Your kleptomania will take you places. One day, you'll feel like stealing a few figurines. Another day, you'll feel like stealing an industrial machine. - - No matter. They'll all be a part of your collection within a matter of time. - - You can steal items by [bold]having them on your person[/bold] when you get to CentComm. Failing this, you can steal larger items by [bold]leaving them by your beacon.[/bold] - - Some of the more [italic]animate[/italic] objectives may not cooperate with you. Make sure they're alive and with you or your beacon when the shift ends. - - Things that you may desire include but are not limited to: - + ## Eyes on the Price + Your many years of thieving have given you a good idea of the price that anything you look at will go for on the black market. Some items, like pieces of critical station infrastructure, are basically impossible to offload, while others, like the captain's ID card, will fetch a very high price. - - - - + + - From cc5b2dcf64ca4cce8944eed95cf323a255022114 Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Fri, 17 Jul 2026 14:03:31 -0700 Subject: [PATCH 12/14] Spesos cost zero spesos :godo: --- .../en-US/_Funkystation/objectives/conditions/scorethief.ftl | 1 + Resources/Prototypes/Entities/Objects/Misc/space_cash.yml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl index 7b31d5beeaa..aca651e9125 100644 --- a/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl +++ b/Resources/Locale/en-US/_Funkystation/objectives/conditions/scorethief.ftl @@ -12,6 +12,7 @@ scorethief-modifier-centcomm-comms = Certain people are willing to pay a lot to scorethief-modifier-command-comms = Certain people are willing to pay a lot for command comms. scorethief-modifier-sec-comms = Certain people are willing to pay for security comms. scorethief-modifier-critical-infrastructure = Critical station infrastructure is too high profile and easily traceable to be worth anything. +scorethief-modifier-money = Spesos' microdots make them easily traceable. scorethief-role-greeting-human = You are criminal scum, a professional thief previously arrested and on parole for grand theft. You are back to steal again. diff --git a/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml b/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml index 24dab4f562c..f18f36af744 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/space_cash.yml @@ -52,6 +52,10 @@ mask: - ItemMask - type: Appearance + # Funky changes start + - type: ScoreThiefPriceModifier + multiplier: 0 + reason: "scorethief-modifier-money" - type: material id: Credit From f46ffbd173a73a8bb7ffdfafbb66dac7a9ea10df Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Fri, 17 Jul 2026 14:03:53 -0700 Subject: [PATCH 13/14] Remove unused precise component for InnateAppraisalComponent --- .../ScoreThief/Components/InnateAppraisalComponent.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs b/Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs index ab78d2e0f74..fffba92eecc 100644 --- a/Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs +++ b/Content.Server/_Funkystation/ScoreThief/Components/InnateAppraisalComponent.cs @@ -11,7 +11,4 @@ public sealed partial class InnateAppraisalComponent : Component // Use ScoreThiefPriceModifierComponent? [DataField] public bool BlackMarket = false; - - [DataField] - public bool Precise = true; } From 47ae5dcd56d980cf43383b3eee93df25a22275ef Mon Sep 17 00:00:00 2001 From: PopUpPup Date: Fri, 17 Jul 2026 14:06:18 -0700 Subject: [PATCH 14/14] Fix yaml from the removed precise field from earlier --- Resources/Prototypes/Roles/Antags/thief.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/Roles/Antags/thief.yml b/Resources/Prototypes/Roles/Antags/thief.yml index a20490d52b5..c3befa942ff 100644 --- a/Resources/Prototypes/Roles/Antags/thief.yml +++ b/Resources/Prototypes/Roles/Antags/thief.yml @@ -25,7 +25,6 @@ # Funky changes start - type: InnateAppraisal blackMarket: True - precise: False # Funky changes end mindRoles: - MindRoleThief