From 216e5ddd5dc30618e8ea3595ee2e73228aafc4ff Mon Sep 17 00:00:00 2001 From: John <35928781+sporkyz@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:51:27 +0300 Subject: [PATCH] Job contraband rework (#33385) * contraband system rework to allow restriction by job, not just department * Fixing detective trenchcoat inheritance * removing unnecessary using declarations * trying to fix testing error by re-adding diagnostics using declaration * removing unecessary dependency, making allowedJobs nullable * Adding all of slarti's requested changes except for the hacky job icon method fix * removing accidental whitespace * choosing to use the non-localized version because we're comparing the string against the AllowedJobs field, and the contraband classes that fill that field are written in english * removing unneeded using dec, fixing nesting logic problem * didn't remove the old nesting, doing that now * using localized job title and localizing the allowed jobs string, removing usages of JobTitle field. Also networked the _jobTitle field instead. * rewrite some stuff * fixes * fix energy pen --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> (cherry picked from commit 796f59917283682a9671dcd68fc975f4245afb56) --- .../Access/Components/IdCardComponent.cs | 2 + .../Contraband/ContrabandComponent.cs | 10 +++- .../Contraband/ContrabandSeverityPrototype.cs | 4 +- Content.Shared/Contraband/ContrabandSystem.cs | 38 +++++++++----- .../Entities/Clothing/Belt/belts.yml | 2 +- .../Entities/Clothing/Ears/headsets.yml | 2 +- .../Entities/Clothing/OuterClothing/armor.yml | 51 +++++++++++-------- .../Entities/Clothing/OuterClothing/coats.yml | 2 +- .../Entities/Clothing/OuterClothing/vests.yml | 2 +- .../Entities/Clothing/Shoes/specific.yml | 2 +- .../Objects/Devices/encryption_keys.yml | 2 +- .../Guns/Ammunition/Cartridges/shotgun.yml | 40 +++++++-------- .../Weapons/Guns/Shotguns/shotguns.yml | 12 ++--- .../Objects/Weapons/Melee/e_sword.yml | 1 - .../Entities/Objects/base_contraband.yml | 32 ++++++++++-- .../Prototypes/contraband_severities.yml | 2 +- 16 files changed, 127 insertions(+), 77 deletions(-) diff --git a/Content.Shared/Access/Components/IdCardComponent.cs b/Content.Shared/Access/Components/IdCardComponent.cs index e80ced6464..3b8322671b 100644 --- a/Content.Shared/Access/Components/IdCardComponent.cs +++ b/Content.Shared/Access/Components/IdCardComponent.cs @@ -22,6 +22,8 @@ public sealed partial class IdCardComponent : Component [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)] public LocId? JobTitle; + [DataField] + [AutoNetworkedField] private string? _jobTitle; [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWriteExecute)] diff --git a/Content.Shared/Contraband/ContrabandComponent.cs b/Content.Shared/Contraband/ContrabandComponent.cs index a4ce652f2f..f758d91f0c 100644 --- a/Content.Shared/Contraband/ContrabandComponent.cs +++ b/Content.Shared/Contraband/ContrabandComponent.cs @@ -24,5 +24,13 @@ public sealed partial class ContrabandComponent : Component /// [DataField] [AutoNetworkedField] - public HashSet>? AllowedDepartments = ["Security"]; + public HashSet> AllowedDepartments = new(); + + /// + /// Which jobs is this item restricted to? + /// If empty, no jobs are allowed to use this beyond the allowed departments. + /// + [DataField] + [AutoNetworkedField] + public HashSet> AllowedJobs = new(); } diff --git a/Content.Shared/Contraband/ContrabandSeverityPrototype.cs b/Content.Shared/Contraband/ContrabandSeverityPrototype.cs index c1ab4b8292..094275a6fd 100644 --- a/Content.Shared/Contraband/ContrabandSeverityPrototype.cs +++ b/Content.Shared/Contraband/ContrabandSeverityPrototype.cs @@ -19,8 +19,8 @@ public sealed partial class ContrabandSeverityPrototype : IPrototype public LocId ExamineText; /// - /// When examining the contraband, should this take into account the viewer's departments? + /// When examining the contraband, should this take into account the viewer's departments and job? /// [DataField] - public bool ShowDepartments; + public bool ShowDepartmentsAndJobs; } diff --git a/Content.Shared/Contraband/ContrabandSystem.cs b/Content.Shared/Contraband/ContrabandSystem.cs index e6931f2860..811ea53567 100644 --- a/Content.Shared/Contraband/ContrabandSystem.cs +++ b/Content.Shared/Contraband/ContrabandSystem.cs @@ -40,6 +40,7 @@ public sealed class ContrabandSystem : EntitySystem contraband.Severity = other.Severity; contraband.AllowedDepartments = other.AllowedDepartments; + contraband.AllowedJobs = other.AllowedJobs; Dirty(uid, contraband); } @@ -54,11 +55,15 @@ public sealed class ContrabandSystem : EntitySystem using (args.PushGroup(nameof(ContrabandComponent))) { + // TODO shouldn't department prototypes have a localized name instead of just using the ID for this? + var localizedDepartments = ent.Comp.AllowedDepartments.Select(p => Loc.GetString($"department-{p.Id}")); + var localizedJobs = ent.Comp.AllowedJobs.Select(p => _proto.Index(p).LocalizedName); + var severity = _proto.Index(ent.Comp.Severity); - if (severity.ShowDepartments && ent.Comp is { AllowedDepartments: not null }) + if (severity.ShowDepartmentsAndJobs) { - // TODO shouldn't department prototypes have a localized name instead of just using the ID for this? - var list = ContentLocalizationManager.FormatList(ent.Comp.AllowedDepartments.Select(p => Loc.GetString($"department-{p.Id}")).ToList()); + //creating a combined list of jobs and departments for the restricted text + var list = ContentLocalizationManager.FormatList(localizedDepartments.Concat(localizedJobs).ToList()); // department restricted text args.PushMarkup(Loc.GetString("contraband-examine-text-Restricted-department", ("departments", list))); @@ -69,23 +74,30 @@ public sealed class ContrabandSystem : EntitySystem } // text based on ID card - List>? departments = null; + List> departments = new(); + var jobId = ""; + if (_id.TryFindIdCard(args.Examiner, out var id)) { departments = id.Comp.JobDepartments; + if (id.Comp.LocalizedJobTitle is not null) + { + jobId = id.Comp.LocalizedJobTitle; + } } - // either its fully restricted, you have no departments, or your departments dont intersect with the restricted departments - if (ent.Comp.AllowedDepartments is null - || departments is null - || !departments.Intersect(ent.Comp.AllowedDepartments).Any()) + // for the jobs we compare the localized string in case you use an agent ID or custom job name that is not a prototype + if (departments.Intersect(ent.Comp.AllowedDepartments).Any() + || localizedJobs.Contains(jobId)) { - args.PushMarkup(Loc.GetString("contraband-examine-text-avoid-carrying-around")); - return; + // you are allowed to use this! + args.PushMarkup(Loc.GetString("contraband-examine-text-in-the-clear")); + } + else + { + // straight to jail! + args.PushMarkup(Loc.GetString("contraband-examine-text-avoid-carrying-around")); } - - // otherwise fine to use :tm: - args.PushMarkup(Loc.GetString("contraband-examine-text-in-the-clear")); } } } diff --git a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml index ca0fd69fd0..1f39d530c5 100644 --- a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml @@ -598,7 +598,7 @@ # Belts without visualizers - type: entity - parent: [ClothingBeltAmmoProviderBase, BaseRestrictedContraband] + parent: [ClothingBeltAmmoProviderBase, BaseSecurityBartenderContraband] id: ClothingBeltBandolier name: bandolier description: A bandolier for holding shotgun ammunition. diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml index 5a0dec1442..e462af70fa 100644 --- a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml +++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml @@ -226,7 +226,7 @@ - EncryptionKeyCommon - type: entity - parent: [ClothingHeadset, BaseRestrictedContraband] + parent: [ClothingHeadset, BaseSecurityLawyerContraband] id: ClothingHeadsetSecurity name: security headset description: This is used by your elite security force. diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index 30986d92b9..1fa3703b5d 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -1,10 +1,12 @@ # Numbers for armor here largely taken from /tg/. # NOTE: Half of the kind of armor you're probably thinking of is in vests.yml. These should probably be merged some day. +#Basic armor vest for inheritance - type: entity parent: [ClothingOuterBaseMedium, AllowSuitStorageClothing, BaseRestrictedContraband] - id: ClothingOuterArmorBasic + id: ClothingOuterArmorBase name: armor vest + abstract: true description: A standard Type I armored vest that provides decent protection against most types of damage. components: - type: Sprite @@ -32,6 +34,11 @@ restitution: 0.3 friction: 0.2 +#Standard armor vest, allowed for security and bartenders +- type: entity + parent: [ BaseSecurityBartenderContraband, ClothingOuterArmorBase] + id: ClothingOuterArmorBasic + #Alternate / slim basic armor vest - type: entity parent: ClothingOuterArmorBasic @@ -97,7 +104,7 @@ - type: GroupExamine - type: entity - parent: ClothingOuterArmorBasic + parent: ClothingOuterArmorBase id: ClothingOuterArmorBulletproof name: bulletproof vest description: A Type III heavy bulletproof vest that provides superb protection against bullets, but is lackluster against anything else. @@ -117,7 +124,7 @@ Heat: 0.95 - type: entity - parent: ClothingOuterArmorBasic + parent: ClothingOuterArmorBase id: ClothingOuterArmorReflective name: reflective vest description: An armored vest with advanced shielding to protect against energy weapons. @@ -139,7 +146,7 @@ reflectProb: 0.65 # WD EDIT: 0.33 -> 0.65 innate: true # armor grants a passive shield that does not require concentration to maintain reflects: - - Energy + - Energy - type: entity parent: [ClothingOuterBaseLarge, AllowSuitStorageClothing, BaseSyndicateContraband ] @@ -191,21 +198,21 @@ netsync: false - type: LightBehaviour behaviours: - - !type:FadeBehaviour - id: radiating - interpolate: Linear - maxDuration: 2.0 - startValue: 3.0 - endValue: 2.0 - isLooped: true - reverseWhenFinished: true - - !type:PulseBehaviour - id: blinking - interpolate: Nearest - maxDuration: 1.0 - minValue: 0.1 - maxValue: 2.0 - isLooped: true + - !type:FadeBehaviour + id: radiating + interpolate: Linear + maxDuration: 2.0 + startValue: 3.0 + endValue: 2.0 + isLooped: true + reverseWhenFinished: true + - !type:PulseBehaviour + id: blinking + interpolate: Nearest + maxDuration: 1.0 + minValue: 0.1 + maxValue: 2.0 + isLooped: true - type: Battery maxCharge: 600 startingCharge: 600 @@ -256,7 +263,7 @@ slots: WITHOUT_POCKET - type: Tag tags: - - FullBodyOuter + - FullBodyOuter - type: GiftIgnore # WD EDIT - type: entity @@ -282,7 +289,7 @@ slots: WITHOUT_POCKET - type: Tag tags: - - FullBodyOuter + - FullBodyOuter - type: entity parent: ClothingOuterArmorHeavy @@ -383,7 +390,7 @@ slots: WITHOUT_POCKET - type: Tag tags: - - FullBodyOuter + - FullBodyOuter - type: entity parent: [ ClothingOuterBaseLarge, BaseMajorContraband, AllowSuitStorageClothing ] diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml index 6824012846..6847f5b5d8 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml @@ -13,7 +13,7 @@ coolingCoefficient: 0.7 # WD EDIT: 0.1 -> 0.7 - type: entity - parent: [ClothingOuterStorageBase, AllowSuitStorageClothing, ClothingOuterArmorBasic] + parent: [ClothingOuterStorageBase, AllowSuitStorageClothing, ClothingOuterArmorBase] id: ClothingOuterCoatDetective name: detective trenchcoat description: An 18th-century multi-purpose trenchcoat. Someone who wears this means serious business. diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml index a599f072a9..5b83e7baed 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml @@ -42,7 +42,7 @@ #Detective's vest - type: entity - parent: [ClothingOuterArmorBasic, BaseRestrictedContraband] + parent: [ClothingOuterArmorBase, BaseRestrictedContraband] id: ClothingOuterVestDetective name: detective's vest description: A hard-boiled private investigator's armored vest. diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml index ad92a6d7c6..7808576780 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml @@ -107,7 +107,7 @@ sprite: Clothing/Shoes/Specific/cult.rsi - type: entity - parent: ClothingShoesBase + parent: [ ClothingShoesBase, BaseJanitorContraband ] id: ClothingShoesGaloshes name: galoshes description: Rubber boots. diff --git a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml index 0c89785456..f03153a782 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml @@ -172,7 +172,7 @@ - state: robotics_label - type: entity - parent: [ EncryptionKey, BaseSecurityContraband ] + parent: [ EncryptionKey, BaseSecurityLawyerContraband ] id: EncryptionKeySecurity name: security encryption key description: An encryption key used by security. diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml index cd5a23af62..06061ed188 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml @@ -32,7 +32,7 @@ - type: entity id: ShellShotgunBeanbag name: shell (.50 beanbag) - parent: BaseShellShotgun + parent: [ BaseShellShotgun, BaseSecurityBartenderContraband ] components: - type: Tag tags: @@ -62,6 +62,25 @@ - type: SpentAmmoVisuals state: "slug" +- type: entity + id: ShellShotgunFlare + name: shell (.50 flare) + parent: [ BaseShellShotgun, BaseSecurityBartenderContraband ] + components: + - type: Tag + tags: + - Cartridge + - ShellShotgun + - ShellShotgunLight + - type: Sprite + layers: + - state: flare + map: [ "enum.AmmoVisualLayers.Base" ] + - type: CartridgeAmmo + proto: PelletShotgunFlare + - type: SpentAmmoVisuals + state: "flare" + - type: entity id: ShellShotgunLumen name: shell (.50 Lumenblast) @@ -220,22 +239,3 @@ map: [ "enum.AmmoVisualLayers.Base" ] - type: CartridgeAmmo proto: PelletShotgunSpread0000Buckshot - -- type: entity - id: ShellShotgunFlare - name: shell (.50 flare) - parent: BaseShellShotgun - components: - - type: Tag - tags: - - Cartridge - - ShellShotgun - - ShellShotgunLight - - type: Sprite - layers: - - state: flare - map: [ "enum.AmmoVisualLayers.Base" ] - - type: CartridgeAmmo - proto: PelletShotgunFlare - - type: SpentAmmoVisuals - state: "flare" diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml index 82ac011b77..65584f23fc 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml @@ -70,7 +70,7 @@ Blunt: 2.5 - type: DamageOtherOnHit staminaCost: 9.5 -# WD EDIT START + # WD EDIT START # Sounds - type: EmitSoundOnPickup sound: @@ -170,7 +170,7 @@ containers: gun_magazine: !type:ContainerSlot gun_chamber: !type:ContainerSlot - # WD EDIT START: MagazineAmmoProvider -> ChamberMagazineAmmoProvider + # WD EDIT START: MagazineAmmoProvider -> ChamberMagazineAmmoProvider - type: ChamberMagazineAmmoProvider soundRack: path: /Audio/Weapons/Guns/Cock/sf_rifle_cock.ogg @@ -241,8 +241,8 @@ stealGroup: HoSAntiqueWeapon - type: entity - name: double-barreled shotgunshotgun - parent: [BaseWeaponShotgun, BaseGunWieldable, BaseMinorContraband] + name: double-barreled shotgun + parent: [BaseWeaponShotgun, BaseGunWieldable, BaseSecurityBartenderContraband] id: WeaponShotgunDoubleBarreled description: An immortal classic. Uses .50 shotgun shells. components: @@ -364,7 +364,7 @@ - type: entity name: sawn-off shotgun - parent: BaseWeaponShotgunSmall # WD EDIT: BaseWeaponShotgun -> BaseWeaponShotgunSmall + parent: [ BaseWeaponShotgunSmall, BaseSecurityBartenderContraband ] # WD EDIT: BaseWeaponShotgun -> BaseWeaponShotgunSmall id: WeaponShotgunSawn description: Groovy! Uses .50 shotgun shells. components: @@ -444,7 +444,7 @@ fireOnDropChance: 1 - type: BallisticAmmoProvider capacity: 1 - # WD EDIT START + # WD EDIT START autoCycle: true # - type: Construction # graph: ShotgunSawn diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index 5fbe43afe4..e6b2f9f0f6 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -274,7 +274,6 @@ doAfterDuration: 4.0 - type: Contraband severity: Syndicate - allowedDepartments: null - type: Sprite sprite: Objects/Weapons/Melee/e_dagger.rsi layers: diff --git a/Resources/Prototypes/Entities/Objects/base_contraband.yml b/Resources/Prototypes/Entities/Objects/base_contraband.yml index 8a80733e01..8ee840e659 100644 --- a/Resources/Prototypes/Entities/Objects/base_contraband.yml +++ b/Resources/Prototypes/Entities/Objects/base_contraband.yml @@ -5,8 +5,6 @@ components: - type: Contraband severity: Syndicate - # no one should be carrying this around visibly! - allowedDepartments: null # minor contraband not departmentally restricted -- improvised weapons etc - type: entity @@ -15,8 +13,6 @@ components: - type: Contraband severity: Minor - # according to space law no dept is authorized to have - allowedDepartments: null # major contraband, for things like guns or weaponry that don't belong to any department and aren't syndicate specific - type: entity @@ -25,7 +21,6 @@ components: - type: Contraband severity: Major - allowedDepartments: null # minor contraband by default restricted to security only - type: entity @@ -157,6 +152,33 @@ - type: Contraband allowedDepartments: [ Medical, Epistemics ] +# contraband restricted by job by some degree +- type: entity + id: BaseSecurityBartenderContraband + parent: BaseRestrictedContraband + abstract: true + components: + - type: Contraband + allowedDepartments: [ Security ] + allowedJobs: [ Bartender ] + +- type: entity + id: BaseSecurityLawyerContraband + parent: BaseRestrictedContraband + abstract: true + components: + - type: Contraband + allowedDepartments: [ Security ] + allowedJobs: [ Lawyer ] + +- type: entity + id: BaseJanitorContraband + parent: BaseRestrictedContraband + abstract: true + components: + - type: Contraband + allowedJobs: [ Janitor ] + # for ~objective items - type: entity id: BaseGrandTheftContraband diff --git a/Resources/Prototypes/contraband_severities.yml b/Resources/Prototypes/contraband_severities.yml index 54f5cd62ef..c103af5e0a 100644 --- a/Resources/Prototypes/contraband_severities.yml +++ b/Resources/Prototypes/contraband_severities.yml @@ -14,7 +14,7 @@ - type: contrabandSeverity id: Restricted examineText: contraband-examine-text-Restricted - showDepartments: true + showDepartmentsAndJobs: true # Having this as a regular crew member is considered grand theft. (nuke disk, captain's gear, objective items, etc) - type: contrabandSeverity