From 6054c5bc53bb0e4acd0c7ca7fe86df2f4c030e17 Mon Sep 17 00:00:00 2001 From: Rane <60792108+Elijahrane@users.noreply.github.com> Date: Sat, 23 Apr 2022 22:27:19 -0400 Subject: [PATCH] Familiars respawn (#7640) --- .../Components/MovedByPressureComponent.cs | 1 + Content.Server/Bible/BibleSystem.cs | 81 ++++++++++++++++++- .../Bible/Components/FamiliarComponent.cs | 17 ++++ .../Bible/Components/SummonableComponent.cs | 15 +++- .../SummonableRespawningComponent.cs | 9 +++ .../Cargo/Components/CargoTelepadComponent.cs | 1 + .../Components/DiseaseMachineComponent.cs | 1 + .../Components/TriggerOnProximityComponent.cs | 1 + .../Fluids/Components/EvaporationComponent.cs | 1 + .../Lathe/Components/LatheComponent.cs | 2 + .../Components/ServerSingularityComponent.cs | 1 + .../Emag/Components/EmagComponent.cs | 2 + Resources/Locale/en-US/chapel/bible.ftl | 1 + .../Entities/Mobs/Player/familiars.yml | 2 - .../Objects/Specific/Chapel/bibles.yml | 1 + Resources/Prototypes/tags.yml | 3 - 16 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 Content.Server/Bible/Components/FamiliarComponent.cs create mode 100644 Content.Server/Bible/Components/SummonableRespawningComponent.cs diff --git a/Content.Server/Atmos/Components/MovedByPressureComponent.cs b/Content.Server/Atmos/Components/MovedByPressureComponent.cs index bae12d67bd..91169b9578 100644 --- a/Content.Server/Atmos/Components/MovedByPressureComponent.cs +++ b/Content.Server/Atmos/Components/MovedByPressureComponent.cs @@ -16,6 +16,7 @@ namespace Content.Server.Atmos.Components /// Accumulates time when yeeted by high pressure deltas. /// [ViewVariables] + [DataField("accumulator")] public float Accumulator = 0f; [ViewVariables(VVAccess.ReadWrite)] diff --git a/Content.Server/Bible/BibleSystem.cs b/Content.Server/Bible/BibleSystem.cs index e8bd43c930..e48871e39f 100644 --- a/Content.Server/Bible/BibleSystem.cs +++ b/Content.Server/Bible/BibleSystem.cs @@ -1,9 +1,9 @@ using Content.Shared.Interaction; using Content.Shared.Inventory; using Content.Shared.MobState.Components; +using Content.Shared.MobState; using Content.Shared.Damage; using Content.Shared.Verbs; -using Content.Shared.Tag; using Content.Shared.ActionBlocker; using Content.Shared.Actions; using Content.Server.Cooldown; @@ -23,7 +23,6 @@ namespace Content.Server.Bible [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; - [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly ActionBlockerSystem _blocker = default!; [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; @@ -35,6 +34,51 @@ namespace Content.Server.Bible SubscribeLocalEvent>(AddSummonVerb); SubscribeLocalEvent(GetSummonAction); SubscribeLocalEvent(OnSummon); + SubscribeLocalEvent(OnFamiliarDeath); + } + + private Queue AddQueue = new(); + private Queue RemQueue = new(); + + /// + /// This handles familiar respawning. + /// + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach(var entity in AddQueue) + { + EnsureComp(entity); + } + AddQueue.Clear(); + + foreach(var entity in RemQueue) + { + RemComp(entity); + } + RemQueue.Clear(); + + foreach (var (respawning, summonableComp) in EntityQuery()) + { + summonableComp.Accumulator += frameTime; + if (summonableComp.Accumulator < summonableComp.RespawnTime) + { + continue; + } + /// Clean up the old body + if (summonableComp.Summon != null) + { + EntityManager.DeleteEntity(summonableComp.Summon.Value); + summonableComp.Summon = null; + } + summonableComp.AlreadySummoned = false; + _popupSystem.PopupEntity(Loc.GetString("bible-summon-respawn-ready", ("book", summonableComp.Owner)), summonableComp.Owner, Filter.Pvs(summonableComp.Owner)); + SoundSystem.Play(Filter.Pvs(summonableComp.Owner), "/Audio/Effects/radpulse9.ogg", summonableComp.Owner, AudioParams.Default.WithVolume(-4f)); + /// Clean up the accumulator and respawn tracking component + summonableComp.Accumulator = 0; + RemQueue.Enqueue(respawning.Owner); + } } private void OnAfterInteract(EntityUid uid, BibleComponent component, AfterInteractEvent args) @@ -67,7 +111,8 @@ namespace Content.Server.Bible return; } - if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out var entityUid) && !_tagSystem.HasTag(args.Target.Value, "Familiar")) + // This only has a chance to fail if the target is not wearing anything on their head and is not a familiar. + if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out var entityUid) && !HasComp(args.Target.Value)) { if (_random.Prob(component.FailChance)) { @@ -125,6 +170,24 @@ namespace Content.Server.Bible { AttemptSummon(component, args.Performer, Transform(args.Performer)); } + + /// + /// Starts up the respawn stuff when + /// the chaplain's familiar dies. + /// + private void OnFamiliarDeath(EntityUid uid, FamiliarComponent component, MobStateChangedEvent args) + { + if (!args.Component.IsDead() || component.Source == null) + return; + + var source = component.Source; + if (source != null && TryComp(source, out var summonable)) + { + AddQueue.Enqueue(summonable.Owner); + } + } + + private void AttemptSummon(SummonableComponent component, EntityUid user, TransformComponent? position) { if (component.AlreadySummoned || component.SpecialItemPrototype == null) @@ -138,7 +201,17 @@ namespace Content.Server.Bible if (!_blocker.CanInteract(user, component.Owner)) return; - EntityManager.SpawnEntity(component.SpecialItemPrototype, position.Coordinates); + // Make this familiar the component's summon + var familiar = EntityManager.SpawnEntity(component.SpecialItemPrototype, position.Coordinates); + component.Summon = familiar; + + /// We only want to add the familiar component to mobs + if (HasComp(familiar)) + { + /// Make this Summon the familiar's source + var familiarComp = EnsureComp(familiar); + familiarComp.Source = component.Owner; + } component.AlreadySummoned = true; _actionsSystem.RemoveAction(user, component.SummonAction); } diff --git a/Content.Server/Bible/Components/FamiliarComponent.cs b/Content.Server/Bible/Components/FamiliarComponent.cs new file mode 100644 index 0000000000..f733fced70 --- /dev/null +++ b/Content.Server/Bible/Components/FamiliarComponent.cs @@ -0,0 +1,17 @@ +namespace Content.Server.Bible.Components +{ + /// + /// This component is for the chaplain's familiars, and mostly + /// used to track their current state and to give a component to check for + /// if any special behavior is needed. + /// + [RegisterComponent] + public sealed class FamiliarComponent : Component + { + /// + /// The entity this familiar was summoned from. + /// + [ViewVariables] + public EntityUid? Source = null; + } +} diff --git a/Content.Server/Bible/Components/SummonableComponent.cs b/Content.Server/Bible/Components/SummonableComponent.cs index cee7dcbdec..2012d8cedb 100644 --- a/Content.Server/Bible/Components/SummonableComponent.cs +++ b/Content.Server/Bible/Components/SummonableComponent.cs @@ -1,7 +1,6 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Prototypes; using Content.Shared.Actions.ActionTypes; -using Content.Server.Bible; using Robust.Shared.Utility; namespace Content.Server.Bible.Components @@ -22,6 +21,12 @@ namespace Content.Server.Bible.Components [DataField("requriesBibleUser")] public bool RequiresBibleUser = true; + /// + /// The specific creature this summoned, if the SpecialItemPrototype has a mobstate. + /// + [ViewVariables] + public EntityUid? Summon = null; + [DataField("summonAction")] public InstantAction SummonAction = new() { @@ -30,5 +35,13 @@ namespace Content.Server.Bible.Components Description = "bible-summon-verb-desc", Event = new SummonActionEvent(), }; + + /// Used for respawning + [ViewVariables] + [DataField("accumulator")] + public float Accumulator = 0f; + [ViewVariables] + [DataField("respawnTime")] + public float RespawnTime = 180f; } } diff --git a/Content.Server/Bible/Components/SummonableRespawningComponent.cs b/Content.Server/Bible/Components/SummonableRespawningComponent.cs new file mode 100644 index 0000000000..0e526e3ee4 --- /dev/null +++ b/Content.Server/Bible/Components/SummonableRespawningComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Bible.Components +{ + /// + /// EntityQuery Tracking Component for Summonables that are counting up a respawn. + /// + [RegisterComponent] + public sealed class SummonableRespawningComponent : Component + {} +} diff --git a/Content.Server/Cargo/Components/CargoTelepadComponent.cs b/Content.Server/Cargo/Components/CargoTelepadComponent.cs index cab5b63576..60fb585c3a 100644 --- a/Content.Server/Cargo/Components/CargoTelepadComponent.cs +++ b/Content.Server/Cargo/Components/CargoTelepadComponent.cs @@ -19,6 +19,7 @@ namespace Content.Server.Cargo.Components /// How much time we've accumulated until next teleport. /// [ViewVariables] + [DataField("accumulator")] public float Accumulator = 0f; [ViewVariables] diff --git a/Content.Server/Disease/Components/DiseaseMachineComponent.cs b/Content.Server/Disease/Components/DiseaseMachineComponent.cs index e0535635a9..cf78e5d9a0 100644 --- a/Content.Server/Disease/Components/DiseaseMachineComponent.cs +++ b/Content.Server/Disease/Components/DiseaseMachineComponent.cs @@ -16,6 +16,7 @@ namespace Content.Server.Disease.Components /// How much time we've accumulated processing /// [ViewVariables] + [DataField("accumulator")] public float Accumulator = 0f; /// /// The disease prototype currently being diagnosed diff --git a/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs b/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs index e174d853bd..f459cca8bb 100644 --- a/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs +++ b/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs @@ -47,6 +47,7 @@ namespace Content.Server.Explosion.Components /// /// How much cooldown has elapsed (if relevant). /// + [DataField("accumulator")] public float Accumulator = 0f; /// diff --git a/Content.Server/Fluids/Components/EvaporationComponent.cs b/Content.Server/Fluids/Components/EvaporationComponent.cs index 8aaaf122c0..89f4e13d60 100644 --- a/Content.Server/Fluids/Components/EvaporationComponent.cs +++ b/Content.Server/Fluids/Components/EvaporationComponent.cs @@ -42,6 +42,7 @@ namespace Content.Server.Fluids.Components /// /// The time accumulated since the start. /// + [DataField("accumulator")] public float Accumulator = 0f; } } diff --git a/Content.Server/Lathe/Components/LatheComponent.cs b/Content.Server/Lathe/Components/LatheComponent.cs index 2bf7e343ed..13ad772c79 100644 --- a/Content.Server/Lathe/Components/LatheComponent.cs +++ b/Content.Server/Lathe/Components/LatheComponent.cs @@ -32,11 +32,13 @@ namespace Content.Server.Lathe.Components /// /// Update accumulator for the insertion time /// + [DataField("insertionAccumulator")] public float InsertionAccumulator = 0f; /// /// Production accumulator for the production time. /// [ViewVariables] + [DataField("producingAccumulator")] public float ProducingAccumulator = 0f; /// diff --git a/Content.Server/Singularity/Components/ServerSingularityComponent.cs b/Content.Server/Singularity/Components/ServerSingularityComponent.cs index 81a7b0e496..c746defff6 100644 --- a/Content.Server/Singularity/Components/ServerSingularityComponent.cs +++ b/Content.Server/Singularity/Components/ServerSingularityComponent.cs @@ -60,6 +60,7 @@ namespace Content.Server.Singularity.Components _ => 0 }; + [DataField("moveAccumulator")] public float MoveAccumulator; // This is an interesting little workaround. diff --git a/Content.Shared/Emag/Components/EmagComponent.cs b/Content.Shared/Emag/Components/EmagComponent.cs index a40c20a261..4258a2b84e 100644 --- a/Content.Shared/Emag/Components/EmagComponent.cs +++ b/Content.Shared/Emag/Components/EmagComponent.cs @@ -11,6 +11,8 @@ namespace Content.Shared.Emag.Components [DataField("rechargeTime"), ViewVariables(VVAccess.ReadWrite)] public float RechargeTime = 90f; + + [DataField("accumulator")] public float Accumulator = 0f; } } diff --git a/Resources/Locale/en-US/chapel/bible.ftl b/Resources/Locale/en-US/chapel/bible.ftl index a7af825359..d96471525e 100644 --- a/Resources/Locale/en-US/chapel/bible.ftl +++ b/Resources/Locale/en-US/chapel/bible.ftl @@ -5,6 +5,7 @@ bible-heal-fail-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE( bible-sizzle = The book sizzles in your hands! bible-summon-verb = Summon familiar bible-summon-verb-desc = Summon a familiar that will aid you and gain humanlike intelligence once inhabited by a soul. +bible-summon-respawn-ready = {CAPITALIZE(THE($book))} surges with ethereal power. {CAPITALIZE(POSS-ADJ($book))} resident is home again. necro-heal-success-self = You hit {THE($target)} with {THE($bible)}, and {POSS-ADJ($target)} flesh warps as it melts! necro-heal-success-others = {CAPITALIZE(THE($user))} hits {THE($target)} with {THE($bible)}, and {POSS-ADJ($target)} flesh warps as it melts! necro-heal-fail-self = You hit {THE($target)} with {THE($bible)}, and it lands with a sad thwack, failing to smite {OBJECT($target)}. diff --git a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml index 887d58a48d..dc10a07788 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml @@ -15,7 +15,6 @@ proper: true - type: Tag tags: - - Familiar - DoorBumpOpener - type: Access tags: @@ -64,7 +63,6 @@ proper: true - type: Tag tags: - - Familiar - DoorBumpOpener - type: Access tags: diff --git a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml index 84a21579d6..ca86cf3afc 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml @@ -57,6 +57,7 @@ cooldownTime: 1.3 - type: Summonable specialItem: MobCorgiCerberus + respawnTime: 300 - type: Sprite netsync: false sprite: Objects/Specific/Chapel/necronomicon.rsi diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 17d19762fe..7945042b58 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -144,9 +144,6 @@ - type: Tag id: ExplosivePassable -- type: Tag - id: Familiar - - type: Tag id: FireAlarmElectronics