diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index b6b5a3380c..e316faf141 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -251,6 +251,7 @@ namespace Content.Client.Entry "ExplosionLaunched", "BeingCloned", "Advertise", + "Bible", "PowerNetworkBattery", "BatteryCharger", "UnpoweredFlashlight", @@ -299,7 +300,7 @@ namespace Content.Client.Entry "ArtifactInteractionTrigger", "Artifact", "RandomArtifactSprite", - "EnergySword", + "EnergySword" }; } } diff --git a/Content.Server/Bible/BibleSystem.cs b/Content.Server/Bible/BibleSystem.cs new file mode 100644 index 0000000000..1c2883be08 --- /dev/null +++ b/Content.Server/Bible/BibleSystem.cs @@ -0,0 +1,92 @@ +using System; +using Robust.Shared.GameObjects; +using Content.Shared.Interaction; +using Content.Shared.Inventory; +using Content.Shared.MobState.Components; +using Content.Shared.Damage; +using Content.Shared.Popups; +using Content.Server.Cooldown; +using Content.Server.Inventory; +using Content.Server.Mind.Components; +using Content.Server.Bible.Components; +using Content.Server.Popups; +using Robust.Shared.IoC; +using Robust.Shared.Random; +using Robust.Shared.Audio; +using Robust.Shared.Player; +using Robust.Shared.Localization; +using Robust.Shared.Timing; + + +namespace Content.Server.Bible +{ + public class BibleSystem : EntitySystem + { + [Dependency] private readonly InventorySystem _invSystem = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAfterInteract); + } + + private void OnAfterInteract(EntityUid uid, BibleComponent component, AfterInteractEvent args) + { + var currentTime = _gameTiming.CurTime; + + if (currentTime < component.CooldownEnd) + { + return; + } + if (args.Target == null || args.Target == args.User || !HasComp(args.Target)) + { + return; + } + + component.LastAttackTime = currentTime; + component.CooldownEnd = component.LastAttackTime + TimeSpan.FromSeconds(component.CooldownTime); + RaiseLocalEvent(uid, new RefreshItemCooldownEvent(component.LastAttackTime, component.CooldownEnd), false); + + if (!HasComp(args.User)) + { + _popupSystem.PopupEntity(Loc.GetString("bible-sizzle"), args.User, Filter.Entities(args.User)); + + SoundSystem.Play(Filter.Pvs(args.User), "/Audio/Effects/lightburn.ogg"); + _damageableSystem.TryChangeDamage(args.User, component.DamageOnUntrainedUse, true); + + return; + } + + if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out var entityUid)) + { + if (_random.Prob(component.FailChance)) + { + var othersFailMessage = Loc.GetString("bible-heal-fail-others", ("user", args.User),("target", args.Target),("bible", uid)); + _popupSystem.PopupEntity(othersFailMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User)); + + var selfFailMessage = Loc.GetString("bible-heal-fail-self", ("target", args.Target),("bible", uid)); + _popupSystem.PopupEntity(selfFailMessage, args.User, Filter.Entities(args.User)); + + SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/hit_kick.ogg"); + _damageableSystem.TryChangeDamage(args.Target.Value, component.DamageOnFail, true); + return; + } + } + + var othersMessage = Loc.GetString("bible-heal-success-others", ("user", args.User),("target", args.Target),("bible", uid)); + _popupSystem.PopupEntity(othersMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User)); + + var selfMessage = Loc.GetString("bible-heal-success-self", ("target", args.Target),("bible", uid)); + _popupSystem.PopupEntity(selfMessage, args.User, Filter.Entities(args.User)); + + SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/holy.ogg"); + _damageableSystem.TryChangeDamage(args.Target.Value, component.Damage, true); + } + + } +} diff --git a/Content.Server/Bible/Components/BibleComponent.cs b/Content.Server/Bible/Components/BibleComponent.cs new file mode 100644 index 0000000000..5727f9171e --- /dev/null +++ b/Content.Server/Bible/Components/BibleComponent.cs @@ -0,0 +1,38 @@ +using System; +using Robust.Shared.Analyzers; +using Robust.Shared.GameObjects; +using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; +using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.ViewVariables; + +namespace Content.Server.Bible.Components +{ + [RegisterComponent, ComponentProtoName("Bible")] + public sealed class BibleComponent : Component + { + + // Damage that will be healed on a success + [DataField("damage", required: true)] + [ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier Damage = default!; + // Damage that will be dealt on a failure + [DataField("damageOnFail", required: true)] + [ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier DamageOnFail = default!; + // Damage that will be dealt when a non-chaplain attempts to heal + [DataField("damageOnUntrainedUse", required: true)] + [ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier DamageOnUntrainedUse = default!; + + //Chance the bible will fail to heal someone with no helmet + [DataField("failChance", required:true)] + [ViewVariables(VVAccess.ReadWrite)] + public float FailChance = 0.34f; + + public TimeSpan LastAttackTime; + public TimeSpan CooldownEnd; + public float CooldownTime { get; } = 1f; + } +} diff --git a/Content.Server/Bible/Components/BibleUserComponent.cs b/Content.Server/Bible/Components/BibleUserComponent.cs new file mode 100644 index 0000000000..e9cc7913cb --- /dev/null +++ b/Content.Server/Bible/Components/BibleUserComponent.cs @@ -0,0 +1,8 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.Analyzers; + +namespace Content.Server.Bible.Components +{ + [RegisterComponent, ComponentProtoName("BibleUser")] + public sealed class BibleUserComponent : Component {} +} diff --git a/Resources/Audio/Effects/holy.ogg b/Resources/Audio/Effects/holy.ogg new file mode 100644 index 0000000000..d3727adb3b Binary files /dev/null and b/Resources/Audio/Effects/holy.ogg differ diff --git a/Resources/Audio/Effects/license.txt b/Resources/Audio/Effects/license.txt index edac43a6ec..9612726429 100644 --- a/Resources/Audio/Effects/license.txt +++ b/Resources/Audio/Effects/license.txt @@ -16,3 +16,5 @@ poster_broken.ogg taken from https://github.com/tgstation/tgstation/blob/2834383 poster_being_set.ogg taken from https://github.com/tgstation/tgstation/blob/2834383245d2129a106acef3afd17b81e1e64777/sound/items/poster_ripped.ogg fire.ogg taken and edited from https://freesound.org/people/raremess/sounds/222557/ + +holy.ogg taken from https://freesound.org/people/random_intruder/sounds/392172/ and edited diff --git a/Resources/Locale/en-US/chapel/bible.ftl b/Resources/Locale/en-US/chapel/bible.ftl new file mode 100644 index 0000000000..d9547da2de --- /dev/null +++ b/Resources/Locale/en-US/chapel/bible.ftl @@ -0,0 +1,5 @@ +bible-heal-success-self = You hit {THE($target)} with {THE($bible)}, and their wounds close in a flash of holy light! +bible-heal-success-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and their wounds close in a flash of holy light! +bible-heal-fail-self = You hit {THE($target)} with {THE($bible)}, and it lands with a sad thwack, dazing them! +bible-heal-fail-others = {CAPITALIZE(THE$user))} hits {THE($target)} with {THE($bible)}, and it lands with a sad thack, dazing them! +bible-sizzle = The book sizzles in your hands! diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml index 7ee0b64107..94d0ef79fb 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/backpack.yml @@ -102,3 +102,13 @@ - type: StorageFill contents: - id: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpack + id: ClothingBackpackChaplainFilled + components: + - type: StorageFill + contents: + - id: BoxSurvival + - id: Bible diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml index 83ab58aa1c..2a68336e24 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/duffelbag.yml @@ -81,3 +81,13 @@ - type: StorageFill contents: - id: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpackDuffel + id: ClothingBackpackDuffelChaplainFilled + components: + - type: StorageFill + contents: + - id: BoxSurvival + - id: Bible diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml index 5824bb3adc..c99730d7af 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml @@ -81,3 +81,13 @@ - type: StorageFill contents: - id: BoxSurvival + +- type: entity + abstract: true + parent: ClothingBackpackSatchel + id: ClothingBackpackSatchelChaplainFilled + components: + - type: StorageFill + contents: + - id: BoxSurvival + - id: Bible diff --git a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml new file mode 100644 index 0000000000..58ae330e2a --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml @@ -0,0 +1,32 @@ +- type: entity + name: bible + description: New Interstellar Version 2340 + parent: BaseItem + id: Bible + components: + - type: Bible + damage: + groups: + Brute: -7 + Burn: -7 + damageOnFail: + groups: + Brute: 4 + Airloss: 6 + damageOnUntrainedUse: ## What a non-chaplain takes when attempting to heal someone + groups: + Burn: 10 + - type: ItemCooldown + - type: Sprite + netsync: false + sprite: Objects/Specific/Chapel/bible.rsi + state: icon + - type: Item + size: 15 + sprite: Objects/Specific/Chapel/bible.rsi + prefix: inhand + - type: Storage + capacity: 10 + storageSoundCollection: + collection: storageRustle + diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml index edb8c8e992..26c648e41e 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml @@ -9,15 +9,18 @@ access: - Chapel - Maintenance + special: + - !type:AddComponentSpecial + component: BibleUser #Lets them heal with bibles - type: startingGear id: ChaplainGear equipment: jumpsuit: ClothingUniformJumpsuitChaplain - back: ClothingBackpackFilled + back: ClothingBackpackChaplainFilled shoes: ClothingShoesColorBlack id: ChaplainPDA ears: ClothingHeadsetService innerclothingskirt: ClothingUniformJumpskirtChaplain - satchel: ClothingBackpackSatchelFilled - duffelbag: ClothingBackpackDuffelFilled + satchel: ClothingBackpackSatchelChaplainFilled + duffelbag: ClothingBackpackDuffelChaplainFilled diff --git a/Resources/Textures/Objects/Specific/Chapel/bible.rsi/icon.png b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/icon.png new file mode 100644 index 0000000000..3b757af0f3 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Specific/Chapel/bible.rsi/inhand-left.png b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/inhand-left.png new file mode 100644 index 0000000000..71aaa79558 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/inhand-left.png differ diff --git a/Resources/Textures/Objects/Specific/Chapel/bible.rsi/inhand-right.png b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/inhand-right.png new file mode 100644 index 0000000000..8a5776b54e Binary files /dev/null and b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/inhand-right.png differ diff --git a/Resources/Textures/Objects/Specific/Chapel/bible.rsi/meta.json b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/meta.json new file mode 100644 index 0000000000..a253b74d97 --- /dev/null +++ b/Resources/Textures/Objects/Specific/Chapel/bible.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/40d89d11ea4a5cb81d61dc1018b46f4e7d32c62a", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +}