From d9318386492391d26c26978caf5593172208bb67 Mon Sep 17 00:00:00 2001 From: ThereDrD0 <88589686+ThereDrD0@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:33:46 +0300 Subject: [PATCH 1/8] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D1=8B=20=D0=A0?= =?UTF-8?q?=D0=A6=D0=94=20=D0=B8=20=D0=A0=D0=9F=D0=94=20(#511)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix rcd and rpd crafting with full capacity * Lets atmos build gas pipes in walls (#28707) Co-authored-by: plykiya * slower disposal units building with rpd * allow build pipes in walls --------- Co-authored-by: Plykiya <58439124+Plykiya@users.noreply.github.com> Co-authored-by: plykiya --- .../Entities/Objects/Tools/tools.yml | 8 ++++ .../Recipes/Construction/utilities.yml | 10 ++--- Resources/Prototypes/_White/RPD/rpd.yml | 42 +++++++++---------- .../_White/Recipes/lathe_recipes.yml | 12 +++--- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index 640a5e435e..f55add8db2 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -524,6 +524,14 @@ - MailingUnit - ToiletEmpty +- type: entity # WD + id: RapidPipeDispenserEmpty + parent: RapidPipeDispenser + suffix: Empty + components: + - type: LimitedCharges + charges: 0 + - type: entity id: RCDRecharging parent: RCD diff --git a/Resources/Prototypes/Recipes/Construction/utilities.yml b/Resources/Prototypes/Recipes/Construction/utilities.yml index ce4c1c13a2..87389cdb09 100644 --- a/Resources/Prototypes/Recipes/Construction/utilities.yml +++ b/Resources/Prototypes/Recipes/Construction/utilities.yml @@ -394,7 +394,7 @@ targetNode: half category: construction-category-utilities placementMode: SnapgridCenter - canBuildInImpassable: false + canBuildInImpassable: true icon: sprite: Structures/Piping/Atmospherics/pipe.rsi state: pipeHalf @@ -408,7 +408,7 @@ targetNode: straight category: construction-category-utilities placementMode: SnapgridCenter - canBuildInImpassable: false + canBuildInImpassable: true icon: sprite: Structures/Piping/Atmospherics/pipe.rsi state: pipeStraight @@ -422,7 +422,7 @@ targetNode: bend category: construction-category-utilities placementMode: SnapgridCenter - canBuildInImpassable: false + canBuildInImpassable: true icon: sprite: Structures/Piping/Atmospherics/pipe.rsi state: pipeBend @@ -436,7 +436,7 @@ targetNode: tjunction category: construction-category-utilities placementMode: SnapgridCenter - canBuildInImpassable: false + canBuildInImpassable: true icon: sprite: Structures/Piping/Atmospherics/pipe.rsi state: pipeTJunction @@ -450,7 +450,7 @@ targetNode: fourway category: construction-category-utilities placementMode: SnapgridCenter - canBuildInImpassable: false + canBuildInImpassable: true icon: sprite: Structures/Piping/Atmospherics/pipe.rsi state: pipeFourway diff --git a/Resources/Prototypes/_White/RPD/rpd.yml b/Resources/Prototypes/_White/RPD/rpd.yml index d2ef3481dd..7ffe804cf0 100644 --- a/Resources/Prototypes/_White/RPD/rpd.yml +++ b/Resources/Prototypes/_White/RPD/rpd.yml @@ -10,7 +10,7 @@ prototype: GasPipeStraight cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -26,7 +26,7 @@ prototype: GasPipeBend cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -42,7 +42,7 @@ prototype: GasPipeTJunction cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -58,7 +58,7 @@ prototype: GasPipeFourway cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -270,7 +270,7 @@ prototype: DisposalPipe cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -286,7 +286,7 @@ prototype: DisposalBend cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -302,7 +302,7 @@ prototype: DisposalJunction cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -318,7 +318,7 @@ prototype: DisposalJunctionFlipped cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -334,7 +334,7 @@ prototype: DisposalYJunction cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -350,7 +350,7 @@ prototype: DisposalRouter cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -366,7 +366,7 @@ prototype: DisposalRouterFlipped cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -382,7 +382,7 @@ prototype: DisposalTagger cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -398,7 +398,7 @@ prototype: DisposalSignalRouter cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -414,7 +414,7 @@ prototype: DisposalSignalRouterFlipped cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -430,7 +430,7 @@ prototype: DisposalTrunk cost: 1 delay: 0 - collisionMask: InteractImpassable + collisionMask: None rules: - MustBuildOnSubfloor rotation: User @@ -447,10 +447,10 @@ mode: ConstructObject prototype: DisposalUnit cost: 2 - delay: 1 + delay: 2 collisionMask: InteractImpassable rotation: User - fx: EffectRCDConstruct1 + fx: EffectRCDConstruct2 - type: rcd id: MailingUnit @@ -461,10 +461,10 @@ mode: ConstructObject prototype: MailingUnit cost: 2 - delay: 1 + delay: 2 collisionMask: InteractImpassable rotation: User - fx: EffectRCDConstruct1 + fx: EffectRCDConstruct2 - type: rcd id: ToiletEmpty @@ -475,8 +475,8 @@ mode: ConstructObject prototype: ToiletEmpty cost: 2 - delay: 1 + delay: 2 collisionMask: InteractImpassable rotation: User - fx: EffectRCDConstruct1 + fx: EffectRCDConstruct2 diff --git a/Resources/Prototypes/_White/Recipes/lathe_recipes.yml b/Resources/Prototypes/_White/Recipes/lathe_recipes.yml index 4cba462e3b..6032000928 100644 --- a/Resources/Prototypes/_White/Recipes/lathe_recipes.yml +++ b/Resources/Prototypes/_White/Recipes/lathe_recipes.yml @@ -170,16 +170,16 @@ - type: latheRecipe id: RapidPipeDispenserRecipe - result: RapidPipeDispenser + result: RapidPipeDispenserEmpty completetime: 1 materials: - Steel: 300 - Glass: 300 + Steel: 500 + Glass: 500 - type: latheRecipe id: RCDRecipe - result: RCD + result: RCDEmpty completetime: 1 materials: - Steel: 300 - Glass: 300 + Steel: 500 + Glass: 500 From 58b337a893a8e3186500c2ae9b030ad1d4428cf2 Mon Sep 17 00:00:00 2001 From: RavmorganButOnCocaine Date: Mon, 29 Jul 2024 12:34:51 +0000 Subject: [PATCH 2/8] Automatic changelog update --- Resources/Changelog/ChangelogWhite.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index 4c1d563e03..45eb8283da 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -6970,3 +6970,29 @@ id: 425 time: '2024-07-29T03:04:21.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/510 +- author: ThereDrD + changes: + - message: "\u0420\u041F\u0414 \u0442\u0435\u043F\u0435\u0440\u044C \u043C\u043E\ + \u0436\u0435\u0442 \u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0442\u0440\u0443\ + \u0431\u044B \u0432 \u0441\u0442\u0435\u043D\u0430\u0445" + type: Tweak + - message: "\u041A\u0440\u0430\u0444\u0442 \u043C\u0435\u043D\u044E \u0442\u0435\ + \u043F\u0435\u0440\u044C \u0442\u043E\u0436\u0435 \u043C\u043E\u0436\u0435\u0442\ + \ \u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0442\u0440\u0443\u0431\u044B\ + \ \u0432 \u0441\u0442\u0435\u043D\u0430\u0445" + type: Tweak + - message: "\u041F\u043E\u0444\u0438\u043A\u0448\u0435\u043D\u043E \u043F\u0435\u0447\ + \u0430\u0442\u0430\u043D\u0438\u0435 \u0437\u0430\u043F\u043E\u043B\u043D\u0435\ + \u043D\u043D\u044B\u0445 \u0420\u0426\u0414 \u0438 \u0420\u041F\u0414. \u0447\ + \u0442\u043E \u0434\u0430\u0432\u0430\u043B\u043E \u0432\u043E\u0437\u043C\u043E\ + \u0436\u043D\u043E\u0441\u0442\u044C \u0434\u044E\u043F\u0430\u0442\u044C \u043C\ + \u0430\u0442\u0435\u0440\u0438\u0430\u043B\u044B" + type: Fix + - message: "\u0412\u0440\u0435\u043C\u044F \u0441\u0442\u0440\u043E\u0438\u0442\u0435\ + \u043B\u044C\u0441\u0442\u0432\u0430 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\ + \u0442\u0432 \u0441\u043C\u044B\u0432\u0430 \u0432 \u0420\u041F\u0414 \u0441\ + \u0442\u0430\u043B\u043E \u043F\u043E\u0431\u043E\u043B\u044C\u0448\u0435" + type: Fix + id: 426 + time: '2024-07-29T12:33:46.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/511 From 74e1f3c6189a85fb670a1b62b5edc88d53e9ea03 Mon Sep 17 00:00:00 2001 From: Aviu00 <93730715+Aviu00@users.noreply.github.com> Date: Tue, 30 Jul 2024 00:12:49 +0000 Subject: [PATCH 3/8] More blood (#514) * - add: Some construct stuff. * - add: Some rune stuff. * - add: Unvisit. * - add: Better blood rites. --- .../Components/BaseMagicHandComponent.cs | 7 + .../Components/CultRitesHandComponent.cs | 25 ++ .../Items/Components/CultStunHandComponent.cs | 5 +- .../Cult/Items/Systems/CultStunHandSystem.cs | 56 ---- .../Cult/Items/Systems/MagicHandSystem.cs | 257 ++++++++++++++++++ .../Cult/Runes/Systems/CultSystem.Actions.cs | 79 +----- .../Systems/CultSystem.ConstructsAbilities.cs | 8 +- .../Cult/Runes/Systems/CultSystem.Rune.cs | 19 +- .../Cult/Runes/Systems/CultSystem.Verb.cs | 50 ---- .../Cult/Components/CultistComponent.cs | 8 - .../_White/Cult/Runes/CultRuneInvokeEvent.cs | 2 + Resources/Audio/White/Cult/rites.ogg | Bin 0 -> 20637 bytes .../Locale/ru-RU/_white/cult/entities.ftl | 3 + .../Locale/ru-RU/_white/cult/messages.ftl | 11 +- Resources/Locale/ru-RU/_white/cult/verb.ftl | 5 - .../Prototypes/Entities/Mobs/Species/base.yml | 2 - .../_White/Actions/cult_actions.yml | 1 - .../_White/Entities/Cult/Effects/effects.yml | 20 +- .../_White/Entities/Cult/Items/hands.yml | 74 +++++ .../_White/Entities/Cult/Items/stun_hand.yml | 34 --- .../_White/Entities/Cult/Runes/cult_runes.yml | 5 +- .../_White/Entities/Cult/constructs.yml | 10 +- .../Prototypes/_White/Mobs/Species/harpy.yml | 2 - .../White/Cult/Entities/rites.rsi/icon.png | Bin 0 -> 665 bytes .../Cult/Entities/rites.rsi/inhand-left.png | Bin 0 -> 543 bytes .../Cult/Entities/rites.rsi/inhand-right.png | Bin 0 -> 554 bytes .../White/Cult/Entities/rites.rsi/meta.json | 66 +++++ .../Cult/Entities/stun.rsi/inhand-left.png | Bin 845 -> 508 bytes .../Cult/Entities/stun.rsi/inhand-right.png | Bin 843 -> 504 bytes 29 files changed, 494 insertions(+), 255 deletions(-) create mode 100644 Content.Server/_White/Cult/Items/Components/BaseMagicHandComponent.cs create mode 100644 Content.Server/_White/Cult/Items/Components/CultRitesHandComponent.cs delete mode 100644 Content.Server/_White/Cult/Items/Systems/CultStunHandSystem.cs create mode 100644 Content.Server/_White/Cult/Items/Systems/MagicHandSystem.cs create mode 100644 Resources/Audio/White/Cult/rites.ogg create mode 100644 Resources/Prototypes/_White/Entities/Cult/Items/hands.yml delete mode 100644 Resources/Prototypes/_White/Entities/Cult/Items/stun_hand.yml create mode 100644 Resources/Textures/White/Cult/Entities/rites.rsi/icon.png create mode 100644 Resources/Textures/White/Cult/Entities/rites.rsi/inhand-left.png create mode 100644 Resources/Textures/White/Cult/Entities/rites.rsi/inhand-right.png create mode 100644 Resources/Textures/White/Cult/Entities/rites.rsi/meta.json diff --git a/Content.Server/_White/Cult/Items/Components/BaseMagicHandComponent.cs b/Content.Server/_White/Cult/Items/Components/BaseMagicHandComponent.cs new file mode 100644 index 0000000000..58c1dedd84 --- /dev/null +++ b/Content.Server/_White/Cult/Items/Components/BaseMagicHandComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Server._White.Cult.Items.Components; + +public abstract partial class BaseMagicHandComponent : Component +{ + [DataField] + public string Speech; +} diff --git a/Content.Server/_White/Cult/Items/Components/CultRitesHandComponent.cs b/Content.Server/_White/Cult/Items/Components/CultRitesHandComponent.cs new file mode 100644 index 0000000000..9ed2b0dad6 --- /dev/null +++ b/Content.Server/_White/Cult/Items/Components/CultRitesHandComponent.cs @@ -0,0 +1,25 @@ +using Content.Shared._White.Cult; +using Robust.Shared.Audio; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Server._White.Cult.Items.Components; + +[RegisterComponent] +public sealed partial class CultRitesHandComponent : BaseMagicHandComponent +{ + [DataField] + public SoundSpecifier HealSound = new SoundPathSpecifier("/Audio/White/Cult/rites.ogg"); + + [DataField] + public SoundSpecifier SuckSound = new SoundPathSpecifier("/Audio/White/Cult/enter_blood.ogg"); + + [DataField] + public float HealModifier = 0.5f; + + [DataField(customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List BloodRites = new () + { + "FactoryCultBloodSpear", + "FactoryCultBloodBarrage" + }; +} diff --git a/Content.Server/_White/Cult/Items/Components/CultStunHandComponent.cs b/Content.Server/_White/Cult/Items/Components/CultStunHandComponent.cs index e7e43a730e..26ad1ed723 100644 --- a/Content.Server/_White/Cult/Items/Components/CultStunHandComponent.cs +++ b/Content.Server/_White/Cult/Items/Components/CultStunHandComponent.cs @@ -1,7 +1,7 @@ namespace Content.Server._White.Cult.Items.Components; [RegisterComponent] -public sealed partial class CultStunHandComponent : Component +public sealed partial class CultStunHandComponent : BaseMagicHandComponent { [DataField] public TimeSpan Duration = TimeSpan.FromSeconds(16); @@ -14,7 +14,4 @@ public sealed partial class CultStunHandComponent : Component [DataField] public TimeSpan HaloMuteDuration = TimeSpan.FromSeconds(1); - - [DataField] - public string Speech = "Fuu ma'jin!"; } diff --git a/Content.Server/_White/Cult/Items/Systems/CultStunHandSystem.cs b/Content.Server/_White/Cult/Items/Systems/CultStunHandSystem.cs deleted file mode 100644 index 57b4006d7a..0000000000 --- a/Content.Server/_White/Cult/Items/Systems/CultStunHandSystem.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Content.Server._White.Cult.Items.Components; -using Content.Server.Body.Components; -using Content.Server.Body.Systems; -using Content.Server.Chat.Systems; -using Content.Server.Popups; -using Content.Server.Stunnable; -using Content.Shared._White.Chaplain; -using Content.Shared.Popups; -using Content.Shared.StatusEffect; -using Content.Shared.Weapons.Melee.Events; - -namespace Content.Server._White.Cult.Items.Systems; - -public sealed class CultStunHandSystem : EntitySystem -{ - [Dependency] private readonly StunSystem _stun = default!; - [Dependency] private readonly ChatSystem _chat = default!; - [Dependency] private readonly HolyWeaponSystem _holyWeapon = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; - [Dependency] private readonly BloodstreamSystem _bloodstream = default!; - [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnHit); - } - - private void OnHit(Entity ent, ref MeleeHitEvent args) - { - if (args.HitEntities.Count == 0) - return; - - var target = args.HitEntities[0]; - var (uid, comp) = ent; - - QueueDel(uid); - Spawn("CultStunFlashEffect", Transform(target).Coordinates); - _chat.TrySendInGameICMessage(args.User, comp.Speech, InGameICChatType.Whisper, false); - if (TryComp(args.User, out BloodstreamComponent? bloodstream)) - _bloodstream.TryModifyBloodLevel(args.User, -10, bloodstream, createPuddle: false); - - if (_holyWeapon.IsHoldingHolyWeapon(target)) - { - _popupSystem.PopupEntity(Loc.GetString("cult-magic-holy"), args.User, args.User, PopupType.MediumCaution); - return; - } - - var halo = HasComp(args.User); - - _statusEffects.TryAddStatusEffect(target, "Muted", halo ? comp.HaloMuteDuration : comp.MuteDuration, true, - "Muted"); - _stun.TryParalyze(target, halo ? comp.HaloDuration : comp.Duration, true); - } -} diff --git a/Content.Server/_White/Cult/Items/Systems/MagicHandSystem.cs b/Content.Server/_White/Cult/Items/Systems/MagicHandSystem.cs new file mode 100644 index 0000000000..1fb79ba403 --- /dev/null +++ b/Content.Server/_White/Cult/Items/Systems/MagicHandSystem.cs @@ -0,0 +1,257 @@ +using System.Linq; +using Content.Server._White.Cult.Items.Components; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Server.Chat.Systems; +using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Server.Hands.Systems; +using Content.Server.Popups; +using Content.Server.Stunnable; +using Content.Shared._White.Chaplain; +using Content.Shared._White.Cult; +using Content.Shared._White.Cult.Components; +using Content.Shared._White.Cult.UI; +using Content.Shared.Chemistry.Components; +using Content.Shared.Damage; +using Content.Shared.Examine; +using Content.Shared.FixedPoint; +using Content.Shared.Fluids.Components; +using Content.Shared.Interaction; +using Content.Shared.Mobs.Systems; +using Content.Shared.Popups; +using Content.Shared.StatusEffect; +using Content.Shared.UserInterface; +using Content.Shared.Weapons.Melee.Events; +using Robust.Server.Audio; +using Robust.Server.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.Server._White.Cult.Items.Systems; + +public sealed class MagicHandSystem : EntitySystem +{ + [Dependency] private readonly StunSystem _stun = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly HolyWeaponSystem _holyWeapon = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly BloodstreamSystem _bloodstream = default!; + [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; + [Dependency] private readonly HandsSystem _handsSystem = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStunHit); + SubscribeLocalEvent(OnRitesHit); + SubscribeLocalEvent(OnInteract); + SubscribeLocalEvent(OnBloodRitesSelected); + SubscribeLocalEvent(OnRitesSelectAttempt); + SubscribeLocalEvent(BeforeRitesSelect); + SubscribeLocalEvent(OnExamine); + } + + private void OnExamine(Entity ent, ref ExaminedEvent args) + { + var user = args.Examiner; + if (user != Transform(ent).ParentUid || !TryComp(user, out CultistComponent? cultist)) + return; + args.PushMarkup(Loc.GetString("cult-rites-examine", ("blood", cultist.RitesBloodAmount))); + } + + private void BeforeRitesSelect(Entity ent, ref BeforeActivatableUIOpenEvent args) + { + if (_ui.TryGetUi(ent, BloodRitesUi.Key, out var bui)) + _ui.SetUiState(bui, new CultistFactoryBUIState(ent.Comp.BloodRites)); + } + + private void OnRitesSelectAttempt(Entity ent, ref ActivatableUIOpenAttemptEvent args) + { + if (!HasComp(args.User)) + args.Cancel(); + } + + private void OnBloodRitesSelected(Entity ent, ref CultistFactoryItemSelectedMessage args) + { + var attachedEntity = args.Session.AttachedEntity; + + if (!TryComp(attachedEntity, out CultistComponent? cultist)) + return; + + if (!_prototypeManager.TryIndex(args.Item, out var prototype)) + return; + + var uid = attachedEntity.Value; + + if (cultist.RitesBloodAmount < prototype.BloodCost) + { + var message = Loc.GetString("cult-rites-no-blood", ("required", prototype.BloodCost), + ("blood", cultist.RitesBloodAmount)); + Popup(message, uid); + return; + } + + Speak(uid, ent.Comp); + Del(ent); + + var success = false; + foreach (var entity in prototype.Item.Select(item => Spawn(item, Transform(uid).Coordinates))) + { + if (_handsSystem.TryPickupAnyHand(uid, entity)) + { + success = true; + continue; + } + + Popup(Loc.GetString("cult-rites-no-hand"), uid); + QueueDel(entity); + break; + } + + if (!success) + return; + + cultist.RitesBloodAmount -= prototype.BloodCost; + } + + private void OnInteract(Entity ent, ref AfterInteractEvent args) + { + if (!args.CanReach || args.Target is not { } target) + return; + + var puddleQuery = GetEntityQuery(); + if (!puddleQuery.HasComp(target)) + return; + + if (!TryComp(args.User, out BloodstreamComponent? bloodstreamComponent) || + !TryComp(args.User, out CultistComponent? cultist)) + return; + + var xform = Transform(target); + + var entitiesInRange = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(xform), 1.5f); + + var totalBloodAmount = FixedPoint2.Zero; + + foreach (var solutionEntity in entitiesInRange.ToList()) + { + if (!puddleQuery.TryComp(solutionEntity, out var puddleComponent)) + continue; + + if (!_solutionSystem.TryGetSolution(solutionEntity, puddleComponent.SolutionName, out var solution)) + continue; + + var hasBlood = false; + foreach (var solutionContent in solution.Value.Comp.Solution.Contents.ToList() + .Where(solutionContent => solutionContent.Reagent.Prototype == "Blood")) + { + hasBlood = true; + totalBloodAmount += solutionContent.Quantity; + + _bloodstream.TryModifyBloodLevel(args.User, solutionContent.Quantity / 6f, bloodstreamComponent); + _solutionSystem.RemoveReagent((Entity) solution, "Blood", FixedPoint2.MaxValue); + } + + if (hasBlood) + Spawn("CultTileEffect", Transform(solutionEntity).Coordinates); + } + + if (totalBloodAmount <= FixedPoint2.Zero) + return; + + cultist.RitesBloodAmount += totalBloodAmount; + + _audio.PlayPvs(ent.Comp.SuckSound, args.User); + _popupSystem.PopupEntity(Loc.GetString("cult-rites-message", ("blood", cultist.RitesBloodAmount)), + args.User, args.User); + + args.Handled = true; + } + + private void OnRitesHit(Entity ent, ref MeleeHitEvent args) + { + if (args.HitEntities.Count == 0) + return; + + var target = args.HitEntities[0]; + var (uid, comp) = ent; + + QueueDel(uid); + + if (!TryComp(args.User, out CultistComponent? cultist) || !TryComp(target, out DamageableComponent? damageable)) + return; + + if (_mobState.IsDead(target)) + { + Popup(Loc.GetString("cult-rites-dead"), args.User); + return; + } + + if (cultist.RitesBloodAmount <= FixedPoint2.Zero) + { + Popup(Loc.GetString("cult-rites-heal-no-blood"), args.User); + return; + } + + var damage = damageable.Damage; + var totalDamage = damage.GetTotal(); + if (totalDamage <= FixedPoint2.Zero) + { + Popup(Loc.GetString("cult-rites-already-healed"), args.User); + return; + } + + var coef = FixedPoint2.Min(cultist.RitesBloodAmount * comp.HealModifier, totalDamage) / totalDamage; + cultist.RitesBloodAmount = + FixedPoint2.Max(FixedPoint2.Zero, cultist.RitesBloodAmount - totalDamage / comp.HealModifier); + _damageable.TryChangeDamage(target, -damage * coef, true, false, damageable, args.User); + Popup(Loc.GetString("cult-rites-after-heal", ("blood", cultist.RitesBloodAmount)), args.User); + _audio.PlayPvs(comp.HealSound, target); + Speak(args.User, comp); + } + + private void OnStunHit(Entity ent, ref MeleeHitEvent args) + { + if (args.HitEntities.Count == 0) + return; + + var target = args.HitEntities[0]; + var (uid, comp) = ent; + + QueueDel(uid); + Spawn("CultStunFlashEffect", Transform(target).Coordinates); + Speak(args.User, comp); + if (TryComp(args.User, out BloodstreamComponent? bloodstream)) + _bloodstream.TryModifyBloodLevel(args.User, -10, bloodstream, createPuddle: false); + + if (_holyWeapon.IsHoldingHolyWeapon(target)) + { + Popup(Loc.GetString("cult-magic-holy"), args.User, PopupType.MediumCaution); + return; + } + + var halo = HasComp(args.User); + + _statusEffects.TryAddStatusEffect(target, "Muted", halo ? comp.HaloMuteDuration : comp.MuteDuration, true, + "Muted"); + _stun.TryParalyze(target, halo ? comp.HaloDuration : comp.Duration, true); + } + + private void Popup(string msg, EntityUid user, PopupType type = PopupType.Small) + { + _popupSystem.PopupEntity(msg, user, user, type); + } + + private void Speak(EntityUid user, BaseMagicHandComponent comp) + { + _chat.TrySendInGameICMessage(user, comp.Speech, InGameICChatType.Whisper, false); + } +} diff --git a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs index 4e900eaae4..f1c700316b 100644 --- a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs +++ b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs @@ -106,15 +106,7 @@ public partial class CultSystem private void OnStun(EntityUid uid, CultistComponent component, CultStunActionEvent args) { - var entity = Spawn("StunHand", Transform(uid).Coordinates); - if (!_handsSystem.TryPickupAnyHand(uid, entity)) - { - _popupSystem.PopupEntity(Loc.GetString("cult-magic-no-empty-hand"), uid, uid); - QueueDel(entity); - _actionsSystem.SetCooldown(args.Action, TimeSpan.FromSeconds(1)); - return; - } - args.Handled = true; + GrantItem(uid, "StunHand", args); } private void OnTeleport(EntityUid uid, CultistComponent component, CultTeleportTargetActionEvent args) @@ -150,61 +142,7 @@ public partial class CultSystem private void OnBloodRites(EntityUid uid, CultistComponent component, CultBloodRitesInstantActionEvent args) { - if (!TryComp(args.Performer, out var bloodstreamComponent)) - return; - - var bruteDamageGroup = _prototypeManager.Index("Brute"); - var burnDamageGroup = _prototypeManager.Index("Burn"); - - var xform = Transform(uid); - - var entitiesInRange = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(xform), 1.5f); - - FixedPoint2 totalBloodAmount = 0f; - - var breakLoop = false; - foreach (var solutionEntity in entitiesInRange.ToList()) - { - if (breakLoop) - break; - - if (!TryComp(solutionEntity, out var puddleComponent)) - continue; - - if (!_solutionSystem.TryGetSolution(solutionEntity, puddleComponent.SolutionName, out var solution)) - continue; - - foreach (var solutionContent in solution.Value.Comp.Solution.Contents.ToList()) - { - if (solutionContent.Reagent.Prototype != "Blood") - continue; - - totalBloodAmount += solutionContent.Quantity; - - _bloodstreamSystem.TryModifyBloodLevel(uid, solutionContent.Quantity / 6f, bloodstreamComponent); - _solutionSystem.RemoveReagent((Entity) solution, "Blood", FixedPoint2.MaxValue); - - /*if (GetMissingBloodValue(bloodstreamComponent) == 0) - { - breakLoop = true; - }*/ - } - } - - if (totalBloodAmount == 0f) - return; - - component.RitesBloodAmount += totalBloodAmount; - - _audio.PlayPvs("/Audio/White/Cult/enter_blood.ogg", uid, AudioParams.Default); - _damageableSystem.TryChangeDamage(uid, new DamageSpecifier(bruteDamageGroup, -20)); - _damageableSystem.TryChangeDamage(uid, new DamageSpecifier(burnDamageGroup, -20)); - - _popupSystem.PopupEntity(Loc.GetString("verb-blood-rites-message", ("blood", component.RitesBloodAmount)), uid, - uid); - - Speak(args); - args.Handled = true; + GrantItem(uid, "RitesHand", args); } private static FixedPoint2 GetMissingBloodValue(BloodstreamComponent bloodstreamComponent) @@ -497,4 +435,17 @@ public partial class CultSystem { _spells.Speak(args, InGameICChatType.Whisper); } + + public void GrantItem(EntityUid uid, string proto, InstantActionEvent args) + { + var entity = Spawn(proto, Transform(uid).Coordinates); + if (!_handsSystem.TryPickupAnyHand(uid, entity)) + { + _popupSystem.PopupEntity(Loc.GetString("cult-magic-no-empty-hand"), uid, uid); + QueueDel(entity); + _actionsSystem.SetCooldown(args.Action, TimeSpan.FromSeconds(1)); + return; + } + args.Handled = true; + } } diff --git a/Content.Server/_White/Cult/Runes/Systems/CultSystem.ConstructsAbilities.cs b/Content.Server/_White/Cult/Runes/Systems/CultSystem.ConstructsAbilities.cs index 401e7fcba6..1b6d0d01b5 100644 --- a/Content.Server/_White/Cult/Runes/Systems/CultSystem.ConstructsAbilities.cs +++ b/Content.Server/_White/Cult/Runes/Systems/CultSystem.ConstructsAbilities.cs @@ -1,4 +1,5 @@ -using Content.Server.GameTicking; +using System.Linq; +using Content.Server.GameTicking; using Content.Server.GameTicking.Rules.Components; using Content.Server.Popups; using Content.Server._White.Cult.GameRule; @@ -46,9 +47,10 @@ public partial class CultSystem private void OnMapInit(EntityUid uid, ConstructComponent component, MapInitEvent args) { - foreach (var id in component.Actions) + foreach (var action in component.Actions.Select(id => _actionsSystem.AddAction(uid, id))) { - component.ActionEntities.Add(_actionsSystem.AddAction(uid, id)); + _actionsSystem.StartUseDelay(action); + component.ActionEntities.Add(action); } } diff --git a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs index 1c5ceb6e7e..c066b74872 100644 --- a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs +++ b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs @@ -99,7 +99,7 @@ public sealed partial class CultSystem : EntitySystem SubscribeLocalEvent(OnEmpowerSelected); SubscribeLocalEvent(OnUseInHand); - SubscribeLocalEvent(OnActiveInWorld); + SubscribeLocalEvent(OnActiveInWorld); // UI SubscribeLocalEvent(OnRuneDrawAttempt); @@ -396,19 +396,19 @@ public sealed partial class CultSystem : EntitySystem if (ev.Result) { - OnAfterInvoke(uid, cultists); + OnAfterInvoke(uid, cultists, ev.InvokePhraseOverride); } } - private void OnAfterInvoke(EntityUid rune, HashSet cultists) + private void OnAfterInvoke(EntityUid rune, HashSet cultists, string? invokePhraseOverride = null) { if (!_entityManager.TryGetComponent(rune, out var component)) return; foreach (var cultist in cultists) { - _chat.TrySendInGameICMessage(cultist, component.InvokePhrase, component.InvokeChatType, false, false, null, - null, null, false); + _chat.TrySendInGameICMessage(cultist, invokePhraseOverride ?? component.InvokePhrase, + component.InvokeChatType, false, false, null, null, null, false); } } @@ -455,16 +455,19 @@ public sealed partial class CultSystem : EntitySystem !HasComp(victim.Value)) { result = Convert(uid, victim.Value, args.User, args.Cultists); + args.InvokePhraseOverride = "Mah'weyh pleggh at e'ntrath!"; } else { result = Sacrifice(uid, victim.Value, args.User, args.Cultists); + args.InvokePhraseOverride = "Barhah hra zar'garis!"; } } else { // Жертва мертва, выполняется альтернативное действие result = SacrificeNonObjectiveDead(uid, victim.Value, args.User, args.Cultists); + args.InvokePhraseOverride = "Barhah hra zar'garis!"; } args.Result = result; @@ -1217,13 +1220,14 @@ public sealed partial class CultSystem : EntitySystem * Empower rune start ---- */ - private void OnActiveInWorld(EntityUid uid, CultEmpowerComponent component, ActivateInWorldEvent args) + private void OnActiveInWorld(EntityUid uid, CultEmpowerComponent component, CultRuneInvokeEvent args) { if (!component.IsRune || !TryComp(args.User, out _) || !TryComp(args.User, out var actor)) return; - _ui.TryOpen(uid, CultEmpowerUiKey.Key, actor.PlayerSession); + args.Result = !_ui.SessionHasOpenUi(uid, CultEmpowerUiKey.Key, actor.PlayerSession) && + _ui.TryOpen(uid, CultEmpowerUiKey.Key, actor.PlayerSession); } private void OnUseInHand(EntityUid uid, CultEmpowerComponent component, UseInHandEvent args) @@ -1377,6 +1381,7 @@ public sealed partial class CultSystem : EntitySystem var shard = _entityManager.SpawnEntity("SoulShard", transform.Value); _mindSystem.TransferTo(mindComponent.Mind.Value, shard); + _mindSystem.UnVisit(mindComponent.Mind.Value); _bodySystem.GibBody(target); diff --git a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Verb.cs b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Verb.cs index 1cd8efc886..0633eb0457 100644 --- a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Verb.cs +++ b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Verb.cs @@ -2,7 +2,6 @@ using System.Linq; using Content.Server.Body.Components; using Content.Shared._White.Cult; using Content.Shared._White.Cult.Components; -using Content.Shared._White.Cult.UI; using Content.Shared.DoAfter; using Content.Shared.Verbs; using Robust.Shared.Player; @@ -17,7 +16,6 @@ public sealed partial class CultSystem SubscribeLocalEvent(OnCultistEmpowerSelected); SubscribeLocalEvent(OnCultistEmpowerRemove); SubscribeLocalEvent(OnSpellCreated); - SubscribeLocalEvent(OnBloodRitesSelected); } private void OnCultistEmpowerRemove(Entity ent, ref CultEmpowerRemoveBuiMessage args) @@ -100,24 +98,8 @@ public sealed partial class CultSystem } }; - var bloodRitesVerb = new Verb - { - Text = Loc.GetString("verb-blood-rites-text"), - Message = Loc.GetString("verb-blood-rites-message", ("blood", ent.Comp.RitesBloodAmount)), - Category = VerbCategory.Cult, - Act = () => - { - if (!_ui.TryGetUi(ent, BloodRitesUi.Key, out var bui)) - return; - - _ui.SetUiState(bui, new CultistFactoryBUIState(ent.Comp.BloodRites)); - _ui.OpenUi(bui, actor.PlayerSession); - } - }; - args.Verbs.Add(createSpellVerb); args.Verbs.Add(removeSpellVerb); - args.Verbs.Add(bloodRitesVerb); } private void RemoveSpell(Entity ent, ICommonSession session) @@ -130,36 +112,4 @@ public sealed partial class CultSystem _ui.TryOpen(ent, CultEmpowerRemoveUiKey.Key, session); } - - private void OnBloodRitesSelected(Entity ent, ref CultistFactoryItemSelectedMessage args) - { - if (!_prototypeManager.TryIndex(args.Item, out var prototype)) - return; - - if (ent.Comp.RitesBloodAmount < prototype.BloodCost) - { - var message = Loc.GetString("verb-blood-rites-no-blood", ("required", prototype.BloodCost), - ("blood", ent.Comp.RitesBloodAmount)); - _popupSystem.PopupEntity(message, ent, ent); - return; - } - - var success = false; - foreach (var item in prototype.Item) - { - var entity = Spawn(item, Transform(ent).Coordinates); - if (_handsSystem.TryPickupAnyHand(ent, entity)) - { - success = true; - continue; - } - - _popupSystem.PopupEntity(Loc.GetString("verb-blood-rites-no-hand"), ent, ent); - QueueDel(entity); - break; - } - - if (success) - ent.Comp.RitesBloodAmount -= prototype.BloodCost; - } } diff --git a/Content.Shared/_White/Cult/Components/CultistComponent.cs b/Content.Shared/_White/Cult/Components/CultistComponent.cs index a61f3a5f83..006d2a000b 100644 --- a/Content.Shared/_White/Cult/Components/CultistComponent.cs +++ b/Content.Shared/_White/Cult/Components/CultistComponent.cs @@ -3,7 +3,6 @@ using Content.Shared.FixedPoint; using Content.Shared.Mind; using Robust.Shared.Audio; using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; namespace Content.Shared._White.Cult.Components; @@ -51,13 +50,6 @@ public sealed partial class CultistComponent : Component CultSummonCombatEquipmentAction, CultStunAction, EmpPulseAction, ConcealPresenceAction, CultShadowShacklesAction }; - [DataField("bloodRites", customTypeSerializer: typeof(PrototypeIdListSerializer))] - public List BloodRites = new () - { - "FactoryCultBloodSpear", - "FactoryCultBloodBarrage" - }; - [ViewVariables, NonSerialized] public Entity? BloodSpear; diff --git a/Content.Shared/_White/Cult/Runes/CultRuneInvokeEvent.cs b/Content.Shared/_White/Cult/Runes/CultRuneInvokeEvent.cs index 422057be06..db07f1d4e9 100644 --- a/Content.Shared/_White/Cult/Runes/CultRuneInvokeEvent.cs +++ b/Content.Shared/_White/Cult/Runes/CultRuneInvokeEvent.cs @@ -7,6 +7,8 @@ public sealed class CultRuneInvokeEvent : EntityEventArgs public HashSet Cultists { get; } public bool Result { get; set; } + public string? InvokePhraseOverride { get; set; } = null; + public CultRuneInvokeEvent(EntityUid rune, EntityUid user, HashSet cultists) { Rune = rune; diff --git a/Resources/Audio/White/Cult/rites.ogg b/Resources/Audio/White/Cult/rites.ogg new file mode 100644 index 0000000000000000000000000000000000000000..486940a414752e888d08f354ae26bf2e4a32103f GIT binary patch literal 20637 zcmafaWmsIxvgqItB)CIxCj@tQhrt;nxI2Se@ZjzcJh;0i!QI`1dvJojN%lVH-uvtI z*RxiwvhJ>~>aHcDY+<1WfCl_q*uIi#{{i9QQLLayq1+stjjde%AfN);|C|7T03N8n z=N2gCKa&3~e& zJQPnnR7;GEh^hkzF$Mq;!Y30^C=;_IlR%}DK>fGweJ*1fsry^m{))>004k~|l1|tN zf8|U80K{CLh$8KXBFl*V@EFA4&qGK1j{&T0JcV-`j~1fr?*jLV2_ zgg|hWRxug!wGc?A)f1R0{|D#tN7diMQQskP7S^B3lFrtY%*j3oq}+eFo`wEjmcM*| zjSLyD2zqF=(JDRS^u8sT6oxS&+o9;)!3QM5pe(VYsRPTxBtAsyWGA2;?LP*G28bY% zhhPI`{&O%6ClAGU9;W}A8z{$6T9O~dHo{at`uD(hQc;h_kHXrEF3wol3ske?oY%HF z78N~Kt@C2rDs(&;ahtq$}a(=^5@{c*m{!9%3pnOR@ zg+cN^^@4Z;gIX06QkiGiIA_!(HNa*IDPWyuU(jNR{+;g{q~3##v{TG<{!jg9=#W4s zgE;#?1EKH7cNyh9ph`mj&oChq3UI`h{_AhDbyV`xRAbXj%2yo9Sc0n9k~16{Q#ksn z+;*y5W;2}nYFzpnns!<#cAzHkN~+n)o$to~s`?0jhlmLP@Fh^vCs5EQZ1coW$%+L=lkNF@n`0Dr9;fbz$>#67H3lFm#c(;WYd zaSBTiVo)vDe-@2@CjbCI8LGh^nIcxiq@DvZYp5~L0VU_uH2!}@afU+?3u0KLKLIoQuI8Y6m8kvd3Mn7g3FyH~g{N*9>5kIrh6HUMN5N9j)y4NiiC7!4Mn3W+P$LDpVk z=W*F1D#>wP29lzFUg^?;Syj2(VqJc@q9%2l?JUUUFkO+Zd^t&xx=mRvLG$J+!@PUM#u2<9UiCd1Yu*>4c}`7n2}eUCMPq5sOd|zs z=&G@%slT+Kp)>EhG9O|%@B5>qtj&J7s;a!M;<4`iW83L*lI)DapAOAQsA?!`HQK3x z?Lb(P3pg5cDUxbnh!$T%u-Vdr#1vRkBiZavlgVcK?q*ue5D_~KH{T6cef?ChzP35& zE@TD_)=xIu&@$7xGt(cK2XEXd%rq%3%zDW-wf4v56JxI;N+8tfqY z)?D=sQ^9MN$89R=8v0shOLrPtx4w{0Y~A{9;A<@0K};Sxmy&IC=Ua4!oUG9l0_nki znw`G3-}b>%7n>^>1d**B?Wz)JcXACCg2X&LF#rIqKnD{NT7d}o2@Ajv&JtG;4aW|G zECuwzall^u;89+B0vDhdeQ5{~7>OSg$4f))q9jL`SEM2*pBFqYMqe8O)U~ag%g~MF z44&4dD{54ci!3c71le#(MTrh(B_{CF7A5^9jPf#M2SJul$U>*fMBk^)OG_OTBZoj< zlpv=-U4$>rP@9}&3?VG)+P3zkxzH8$CCJ%Q7iohOc$@HDV*WHv`?v9;Mj+58*#!tu zWrill08u3;#|r5cL=~Et97L6x9HdvqjP!Hba@MsFRr0L!D!@nxL0*m(qRPH@cV5(z zxe(KYj=CS$q^h!!P@Mjs#^-QNDm(u)PTij%7yYO4=vK&bs8qX~p5DJWXH_zUJH?j2(zO6tnBfuVlI6xk4PRlBUAuH z={NkMG-nh(Bzn#$UiiGEB#5PqqF51&3TJiYlU>l|WJ?-nfEue>DjGM+3G=RqO4h_c?u& zuFaU>Jz20y?VPU5uRqCTB02#V5WP-CGaR?bUgqs+$Inz-C|KiZZ5UEZ7gDXmk`iBpxC@JAzK1d$Hwx0`; zh2Vg4e`OK>K!^Xu(f`S8|5E9x{|glbqs!6#;e*%~T?}&g*UJCFCHxl$1pWsHnW}&J zl7O<16qJ|;;;Q(fv;-QsMg>TCqyc~ZR|EjS?$uQLoGm)aYEep#$XZe=CPyF2Dn3kB zOt1EaJcQgOf*d-pPgA}RvazGX0uUi4_#mS40S17AhAxC4N-N^n0LgB}OhaWjm|(*Y zk^va3H~=adx*cedkUq)fJ~&r`&A|6(eCT56f#|(I0dHi!eMjOJxCo_P-Gt4~2O|8v zIr#_xyafOT;LtIqh^0dN;iba{5M&_PFr>5qz99gI@)qbDax`4ujBq{$E zSXkJ<5X27wu(1E!;e6Bihxq3X=MUa(s)Ll8urha`sjP&IoZ=ldB?S!?0~sk91$9+b zS$=L!Sw%y2X>Dm?Y1AZvNR@*kKm=ehoc{jvQwzTx3_QWq7u+v=O{=FkZO@a7Fiw>+ zkc4PRjGEST^M?F8`6oCx!wvJMTTLxql6Q*O9eY`#W#be^Ae7<(e zG_axp__gRIzZL!1u_$L{y}!KWfP?NytaDr<4hW#a3nZ>bKM0fhabeEmeMvIY@0oM& zS(Drwc``o1~;n$0|);C>V?Ti;NhyoVZ5`}(Xptp#=amcs0WZF z#0#~qd{+FJh*(Dv>9l1wwovAb;W0_Fi3g*8XDp$5{w=+y5!dQAd|+TAv;Y0Cl{+NF z+PPydw@Y;~Xwu($vs#b*y&O_vCB-e>(3y7Ci%Qhd`PguxhtgYKk8Mpv)=>_^AeWKF z!F9A8)`*764(}C;Uzonk`yS`Js%_o1BIlc>eHQoMPkC;lS$luaiNyR^6$HoE=KUtXRcn=fDQHlAN!e=}?r zNEOJMs3tnQxYQTnQ|>7c+5qNXHlCj!@6I9I{$~(&kiI9#05BwRn05-3|8>_@*yzm3^%v z7y;ize?X@jy#-2<LP6hl|fu6}rVySHie)XahSDEPW~~3zF6Py!!6j{fKw#`R*|-`Am0RMaAQ86fF;N zR1!DEv)kMiGp@_9SF_pc>m9!e+S1{oH7i2|a~GVVkC`j2uDt;7Pc%HALkVaqfco~n zUZ_JEBUCOWHzuIvz*z%i2Sxl?^l63UHSEj~V7iav|I-P_0X`tRr$hm;S)+gYtS%Yg zQRxImPv_{I0jM8t`$1noQBV>Bv;ml{aY^roRH_wVi_&36CpHdu(*`L`4=IVoy=O>7 zpwlJ@#LMjgb2ARU_udDp1oLjO#{hvt5*Ae9fUy~NsBff9lXo0!&CgfC?T2_U1Tgoc zmC+ScI>J!4hcgE_=SpXU97fX6QC|9$!^+`fM1*9&#pj0`96a2r<^byZIM;jYu{-sE zTtl00#NJBjYQ!bSwC_eTH1uP-37pNKT=#g@m=H}5X{$auOM=JVAa*JNjxd$R3DkOJ@77t=0$OPX&-3(?^N>sr6SLYn zKcBN(e%yhXw6eaJi*|)eRYSV=Si{+Z-rZ)o-8AIGcSZ+7>+Rwk;+%KtiqJuQd-Nh+ z7|SY^$_mDQU^m|IA~3*)Qs1TgS~nmj;BXgo)RehXQ9r-#-9_Z(3t1cavpL{@=D+ot9q6LS0Aw7^9iZro z{>)iX5> zs))fjOPG1qpNC&tFbwWJ4`nj2<}??kA$!%c+`?%idPg_3RAs1<`Tg&P%AE0A{$;%j z=JR1`dQ;8?cq}-;3z5BXjJD|UyB7M4s#^~mZ|6MQ5-dprF=|vp*qQS*7l?eY5XbOU0$guXi;? zn`kO!Zu-_mq}H>v-SMKqmd_{om|D8g$}6vBm0N-?8TuRNUe(3YxrID)~fZ9I!%kj?t>-#487u}RSJGQiv)aWgA4)|&*0QR>!sGMUG*>odz z`fOKD_QrU|B6O4L1Z~+mfNxSRBAtXvC`R{JRzZE?Y_4NF&otA+`bc?2Wo`Y|q=cMr zk`*_TV=csHn-|+DE4_V`0 zYqtxQ;d)>41!jDKM0BNX-ZPD}2Fl3%8l9Iy`}d?PG5eD4R&ASnw8Riod$t0<03r7= z+3!y3+wA*~{V=Py^vs~Ltk>!>j?dP_pX)ZUg|G>cLnNq0u8ZC12iU@bvwpzy%4Vvj z&j!kUvmaA6<%=%?R7IAcKm4YY!fMV#K!#e)5S_4pVU#DKdwd^avDyEM#*F%d6KtSs zTR6T8v;L?!8FB*93O*WaY86wA=Bu}GYa*ef`?_*{mOc7PlyE&c>r+E)_uM-C!VGLy zVzGTZh#6?7RLyTwaIqp{SrMNTGC634CUA-1^4HW1ngH_J0YMV+sm9IUg(8pTKQ+URBR7 zlj2&7o^uLiFG>k&-Rh8cm6ewTam1R8Ck$-svqzv_-(Eh22qvocc%ifb>+*}X1)@Wr z8a`5T+D^#{_Ln~!YR24NWt8m8ybb5rLO5%O7J@5m|2hdTJcwa{65|!EfG&zBJa=~S z`E0$lAQMV7S2QghmZc9p3Hcxwp-X18yC6-mKHNH9NE+wS!!NJk; zb%@Vi*D3GTa!j3*b@uy*xSAtVP7e&QvF@WV1sa|L3L5{l1kv$6fstqxK&6blj2wit z`dyRi`>6kiXEo(SamV9XbIi%av`^{3moDa+rG-HzK2w&h+4>=+&qt;$?=XmH_z64d z6Hd(68M*4<4;SY>Yje16I@qcaNtkDPbF&jfJkK}Oc+GeQP76q~Ju09a47eTE*UFXE ztu-)rL++HK1}1UcXcUPJVkw5xm8_7QC|2st#w18Of1a^`)|i?=%`_ihaK#UT!u8kO z0QjmmRqkjAfalL=gBY|hn?={2xuKsF76rVn`4M9Xxs31h^Q?*Pco+3aRI?qatOdOt zhF_vBf1gq7>6`bG4GSjwl(XEAPjnr`+^A73Q$W3dykfdWHz6>KyqCBG7=iB zHlTVwUb%7alh6KIh%*RXog+q~im+;Eeqwn<##>GU@3U=pu9yX-VPU}1gIVSmM9z}oUxP>}raSGDA^vDa zGShIo9;ia|hHasxzX{l<-d>H`@N{`bv(CwevJ#6PdB%R%Dh%j*4pavva4c#tv+%n8 z8v1l8cD_gFr$=fcwjSlJIuuZ-C!FijgpSUkTMF+{xD48oZio5g;r?kz~?D3$J+eG1}h|5zOZf1!lc_C(q~j@ z-8y5Mn-xbbm)l7J-sR7%k>`~egx4i@n|n6HJ-A!v73P<_8iPzVjPeGGTSOE)Jw@~e zC^=DRUf&ABa*IugM7L-b=RiK-K03M&iheO!!l`i;*8v7$3#GNk^N3l|LO%*+ZOI~` z6*N6)bt~H)H5&v%tVv7ONjTyxH^p65h##%(*@Kr(CT(fxhY|4nX5vU}U)=R$I4jN9DFvj8OsS>oy_|7YlhlU=(i8}^_ zf8b#lbftc@eMsT{_wDMp&i{G#00RNtZ<1vRs!EHCzhvZOr)CxvX66*VoE7Kiiz@PN$j~s@leVUA@|CN$rnM;!zN@-H$={mA* zs8>ARl>05B*3#9(1#vB;s1N*V>jD@f=&5t4HAUY2%=6eOD&I728_UfupS$LrFhK1B zXZH@t?3Io)tYNep;lo5nJjVvi3sKA^BB6qD=h$rMIm-0dV!EOc5_%vU07}XnKaULN zuEAUGxIV^-7FW<%!J-$o-Nkj)N5^sMI0lyp8b73%oK9AZMeWeV>jr-H{#wI==8$vP z%6lKaGl2k#EzzwNIOq|p{&l8Tkmp*0UCzCt!1@N@D>8PNLZQr}-|)&6P)Cv3`krt| z4>6KjWbtl*4++$Jkuo27Yru#Zepi6YD3Wt088{#SvyNP4jAqmzZ}=+S8OF~@^jxXX z+Zt7yrh*xGQ@x_1wH-%&%S97zYmy4ncNRLmF0P?pL>Hy@P`2_cw7qYX^jT}z`b%WW zhFsin|R)UI}rYxZYOm{owM?^}3(D{|)OMY6>k zp^4o2F|Kw0RZ2_>233{Zz+&}r1eQ#p(x#HrVWLT0udcLr@5c(hKXOJwfh1GcT9`pC zG+_Oh1;YE$e9OHUBdxOP{0a9$0Db-!nYU(H_j3*#|;9nr-JN!b0f>a^C+k?y96+Xq1bN`xZjz=ho4fc5j=B>QbOw>j&5%1xc$$Jw^N z++J?k3*mKh@4d@gWt*)uj#P`XDYEvNvX|`X0%{D5=`FbB5rn$Y-c^r1mZf}M8ld_- zxchas-%D+eiI41FF}<(hBLJ57OG-m9+OaE$4n}{nJ21avpl1@M~}3%gkMM zg-~VNoba82JQLJ(gV3J1>yURpp$EA*!=8hed^2<%uOSnkN${+Hfh#>OrEb%#nqf~@ z)l4zmB*gjb_PE2JOq~6mgEB563g&0O!i>ykqXJqzgm5T=pv3O?Ng9J}6q;A(GHx28 zwJ)@sfBNaCcMKhAa0N+PX`g0hbAN)zg1p&uBw(C>(-R`8<4wM_=+s#^c8*aVu(Klq zwLfxtOX~fY;uVMf4i!;%+gp17#Y2dGyJThjh3f;=#c5Q(>>TzFTjk{xKOL5tWM(xh z0TcupdMwC23iC^L3iiu;3Jcrbp`I9}s)=Gm>D#WE0tk>^y8FUAd#GhhpG zOQ2OQTr=+gCOgDGI7#8xR_540V&PAhMO??v@9D>FCKrAjsNsfb1V%*Y10tE~QkOnU z0B~O-6dwrJ=*0ImR2YT$UFPB`ykVrFMJ8M~jio+(b7MSwVZ5Hpx;VKeL9al%MH9^2 zxYG1mcI7k=(9EUy>8)|rkhP6wD0y0KmA;E_N^R5OpsfFSMXRcPn0@Y`6Azh$F&(g%aonwkF4h8@XF=Pw3wCI_Wu?W2L5(2 z`-MmjCFzUD^OXbx#~@oLc(Mc3ls@s5rZ{KXI>iM9N{^G67Fp7w66+&fV?#;>ls^;a z-4s-&oPZYg-4fw)7)~FeMx#UzU&XT(-uE-btRn;u!itzqC{&4=)?Bp=bn?=y*Ht;6 z2!8#QU5?6WQ1eULQvkahJjEw@^y4kc`yOmO9K9TVlwO(-X}<~#3okH6`|`7H?{%*9 zQiqLj2aAVJYjfs&RU$LeI*dJuIAI=$e4ocE<_}frAGmf`ISI+aioP=*u!!9N8h}!u zv0`ge({W;!X~_*D4x?X{A}~w<1H#HnQm!{l4zM>LSJ8B_GpOq0Is-L=5$_dZl6Xe( z@|UK&LfoxymxU3AnS&Uu*GcnFqt=+Umkx2bww|K(qh#sUl%!yj2&>jDsHABp`iEng z$B8;Mb2U-bEbrQUm5i*v0$a{GDB&NL?j1Sbl$j1!)f=%FQRLE>Ph}2SQhzkj5Hx^t zNGYNy$aRt9SdY2Ol%M+yYw=<1KMn~PxI+(@Y?hi!-yqS&53SiS|A7HdU{!NOcl z$M|NLsRw~ayjP2IL{Wg#{cD*rmSd6)Hc@?VqwiIA4bHJO4Bd!iVfOn96B%sn68-QT#yG9g0mE9AxT|g2?vY@(AY}%!yi?7j_ATTim+B z&9DKE&jX3c95|;$L4EAJhWR78%%ptaOZNE0B~B~f4Ct-pU%r?PB*B%^p-_PITCKh) zMD>Ha?y0%KDTSvllP{&A7jkQ0slK7j#iPxs+Tz7)Z-4L6R~Pi?Oz9Pa2|Z@NXfpP$ zx76nNc=t8s>MTl{Bpsk;_kizl6S8)T8DfQJ8CO0=l2yB)e#SVMEr}-EA4%t)4rB31 zPUo(qgva4`AALJClIO1;JAv#Nv~L@GA}N_m*dA_)n-VKJ^JBm%@|ZI|KA9t$*_*Wopozq)w{X!F*& zKdx@5Ff#goV~;gK#PO4Ochu8f&I^6Ecsg(rL3x$I z>Swp`CAgp~Im5B@qUaV(8^5cnZ{i+05uAb7)?jzf!+A;QStAd&HH%%C;+g3*nkNuadR#QL)0ZB75U5x2Vz zps3e4Dhoe}-6AnJ z^|DCy%VN0z|7YUSq|Id_fa`XVwxdJ`Fx~r;3MtUJ({O}(tE6+Zhy~aeYdmeo2{(z$bI)~$?LkuTQ|s-u0pO$Dnn7TPcWj zX`jXE2df4Hc}=qYbc2yTgB!Q~&;$$jM)RSSkYUcjA3YKG^pa<|NWjEorIh|c8kc}G zQ4x*&5@=pBVm+-ZJb$k6z87}Ah2y%Ihu>I42~$;k2WtswiVaBYJqRbGqaY<~T%)UO zZdiTnYn85kCv#F*Tr!DikG}L{8?{ET`l?eO}nnVCZ&1zv{WUI96`yf=C~YbbnG_|%lX$xU5mY&lsAkS$Ty`JzZVc| zcxywrEG7VPMi;;Y^wIUKOBKUAg&uZVyU)$k^D_zB(`~o`BQshpxzQY~Q@Qh-zlkz5 zyC-6#k`^KXSo=f>W~P@R3x^Ae`hR3nh>sQqWOP2$qm^rar z9Pj*f>GM0b3n60K7>w(SI*b&>Lm_YE@9SnGx`TC7L-`UD4hAP)oXy4GMr705Kj5v? zRX(xXgjuGkF#Z;v3*d2k45woTm@0cFkU@)ib{mehNh@UTIp|DpmrT?{pW4PTv2&t` zOVsGLkds_*CJoK4^}P2G9&Y9To(qrBHC6T;`OtHAcW zd@Z$#4+&huw41&TXhMC$!}K+$?3-FiG@6IDVi$13xycc+s+ts71oa* zY*2q)DZ0N$aYrRx*FGIa*gK3h*(?oTc7y{Qzz_kZkJXzJzXh-W$kKlA)U2Cn6KSyH z6~&#Bn7iJ(qqy6(buCoe#piqxZ;mlzRKPP~1Rd?@y&IqxscH&i56MHD`4SC^l+^Em zA7$0GurEH+qq?k%x#^wKheM+f)$w+^0Lkd2%@}JrK^ND5&|=Q8JT6eYDYWO+mmjl! z#al)t`boW7I8;mT&IHQL#2mB3zT^V``xOKA-%ld|f4*Y)^NoXQsdh8r*P`sN<;A5% zIr(KpdAYd-xmmgS6-9X&g+=Rh*{%E?d+c}_L{6u_gq6j@QGX20VFIR;-qRwXe2AFX z!OraH-gWG7%}gnze0ZNe_}D|G>cvi3aGmkvMUds4QaZdjuJZA`Y7d3O!dh8mLp8;1XGC^ zU7^{SntCw2o>}q7n2_Br!xJW^6 zcGGgtthC#j!UM_S1ba3}*PnQHR5e*x9Ve^w3VG z<3sg)fZ$9&ka8(B9W&ovqt;3z5-Ay z3&ttD7FuKqi5U!>25;m2LzX|zPQytt1lKo`DJ7lrhibh>Zw@44yNKMBehy+Px(B}n ztTzjUQ=5*GTdJ_<9Ax9LvK{e?>y|^+#TF{)AU4_f`;JXLxaWZCawGLQL_?qTOceIo z-|uP&t-WDO*s!23_~kWBt)TotDad#-N4uM#PPAyD?Xr{edDVJst@XHNt4DrY#mGez zr@5wyo8&lG>AYM{4B!-4kiI}NR+?t?A`lWUxKfyLP^mVN5j~@(6(It77`uK?n<`Lh zVA*{}VB9wuJT^ZS3KoHWXNe6a%DvOTvLe?T7>nm1#On5bM^u*oACL@zgr?F z*Q5A6`BqDjxbV9a+T}_AyGxvk=QA*tyx)*-@yFa~ZJV41ncyd?s@ zV7*6`wXLXzP)x2<-x0!QB>EERj07(f5rmxPtb-y^iWVHK#-Du=d~hTUDz+1-lfeXp zvc{VNsg#+-Kz8F`TK|cG758Tw#qgJyke%FFznHFDoT)u0|JB&B zfwfOOt#xouoW^I~JYytIn>+nzU2G(CEga2;CC3E=y5QLVIjJ|)`evbaYJ$5m|F4Cr2IV&UueY-gT|=V zXdDZX`f7?sP+Qm+f%v8-li7ZI&KiR+wXJlzdbYKxRGsF-rzFT)YGIZ(_f_*aYyI$f zZ?AkOLw>C8N%wyBZ|vhrGUwby4W89(=k#W|(;aVrvFp=JE;a5b#ZTSy^qWS8baJ)7 zzBNr|I42@R_u`~WA_~7IbG{#X5S#jg9HO4!e0J=N&otRB?AsAN{4io@^q|P2&8K4qK{!z00LUt- zH{D3$E^(72AUo#KOMZ;PW=C?S14wU*tTQEdd|$dXf^p1@vFCnZUeWaa!egD_us{8Y z8ypFh%xj88*7oXa`PF9EJ!|nMw?hdQx%4)sXt6WB2c-&My8RKO6z(tv*q?fhIi2NT zmN*@ry-R-blbbEO!!V*5pDo^8lF9X4%F@4jNXDys2?y*h(MOn^9OMCA)!?1)Hg_$T z0V@YB)FLp#WhJfV%GgEDxxIc+hk)*~Zc&^cWDNV$uz8-DcT;WGV|!xJvvtiZ_5|D% zlA)Yq_liCgOvf{}KB*skhu5FFIN95i-Sm3;aSuy{;N3%BBOifCrG0na2@_#u6~c_{ z7Xhs!zi&3(DF-Vn9}5Ljr`AMvIw`z0&F^oVjlE4(wE9+SV}BS?=4mV~?C3mUcwWTD z2MNx@HWk-ty|deq)6=<15dio#uO2lHLN9xX*W=7a8M3DHeXlG&Yak>WVv|xb7Kx*b zU^%J)H{k9P5AaPmS9qj`HO4P|%^#j0k%Shs#crqOf%&S9jcWn&|L-dBXd?@b=xW4Ecb!M+`8+ zT6li53vQoxTb+S>(Q+m1yXh0r={AdRqOfTILd^n)0=Cj>4um;{#VvOcZ*uK+D=dns z4$u+LONgSlk1a?wM1Re%%#N|65wT^Jx~5KPYc)Vi%z2A~f7V@18s66`Za$t(C3f+h z*h%;+D6dxA;aHU#qv)A!6)sJP&uEvYxyaVR?=e}R^@55bZ};$c4Vr~emK#Sk`57h` zC{p>!Gq;}M8V-+f+!~q{z zFoEML`@5sq1@(+U8{qjjf*_e+As-jIvRmLjNeP!0cr zUz_Sa&+MJ%izNs3$P^*gV2#}ts!b7#X`%^!=1a7l8z=K?YA=SC5Y$VPz%Mq-$#1i{ znycQ^HC{ID@zL>=Ak3hpSLIJPX37(PItfMdQI(2LQw0RS`pnI`X5qOuyXb1Bw3dm_v zIAJpm%UIEJah{FZ0Cb8M;`3Ti0WwCDf-qt1k|}|BXFl7hwNaMi3*&`z=q+ywv#AJJ zXE2}L1=rlGCx-YgymPQuP!nd9G8zM%p;55>KPN@M8;|C{hFwd^#zLrD1xZ(beDZlk zI$y59XM3k*7wk?u^_ZZzRNaX_OKY}YZTlkyLs`DY*gn7YEGTZSAs&|0mc4n-M7$5q z67bR(d@{8ic7HXY!dyn;cl<3v=OB&>3fZsifGJ}1+p>P(!WXbzabRT+7S==}4OXwO zBi~qNHX`p8{-$y6j(w)e(c}1|g&~EM5}c8WG7UQa3hnROMoYe}`sgW}@VRS}hZA-i z5FM|rjaZBBPnTQbT~SXzhjaqr>;-|vlX@#Yqc_4^5*DMpB0M{xBr#b8CHP_LU)Dfx z0s!lcrk6P$WWP@?d+i9%1OWtN2?wdZ&*T+O^rz4*xO=q;ydIsn(`1wI5NSu*6)gHh(4v zGursk__N1~!2F5?Mc~&1X^Bn#sS55c#+7v^8_V+8B2u|Ty&h-Tnl9UVoYERnHlz@n z2;C7yM;VY`qv@~dePkzZB6I7$PN?jwozI zA|h23*KFW8mPur8B$8aD-_y*Rykf8_m;x6)Lk*PLoi%57Se`5orc6m_C2w`<2Qo67 z71w>#X=-EZ%37Np%buUUmLv6I>6|t)|o*Jf=aD-j>%oYJP_9qN#OHdHm6!pj%%@i~%w_d%>|zYjjq&HH%Z-hk0)r9iFn7~{ zHT$!uoh|HaNam(pymGV<@QFUVq|FZ#`LTJAHU1RJ zK3s47Qc&=08EP#b=>|ZP-fkS0SgyPEEg!+_bm~qkT9vw*$05q@GkI93WfO})RCJJ05*Ks6>?XuOS9uL>T;p+HRGz`h(TPrTu&nON-$Y#e->;XzH>z&HTaUX z7H>y+`)GhUD;bvX%34$}&gxu|R?yKjA=Ozus8JX)z*Ys6w|hft58Wu|x;Ig{qTKnj zvyjbXWs7I~eBr{;`nyP`eQLGwNHxhXU`N$y`}ljOaeFTM(;*oS4e$OW)5e{0N~(W%iI=rbkv4K^`^O)) zXKZ{p-&Z7zI1#{|m$2Gpx~#IMp=KRPn~Q7oSj7G;#kGk);mHsiyuNL8a&UrEX(YzM zdz5p*#y>HOJEOowrkF7tR6+igC&Y7Y8LwjAHu_Vg`DUGZjxa}-0LO1YS7XKAru~&g zH!P}kzsVUchKpeTAl&yov1}nlSzD+(mnq@o5}Q}+jxCQQbuew@#}4zMC0bA7=Wi=_5nLhB~d2Kx#= z#?L<3tQGxEkVcRGYG7y0xk1PHgl&hst%*2X4D=fkBBqFv{kazA8|>U~|HfzIkyb|> z%C9LahPgev+e>Q<5u9f(V2??V9?JI(lkmp@Pzn=f&V!Q0Zn2)3@+*h`0j7+1fn3@{ zSbZgBYV0Dg<;i}JFghpJ(#ISzzZXdnyyM9eU)G5&3XHc$j+3@YqVMNUsK=_sV%0J9 z;@>xR)h_aYCrR^SzgWPPdRx)%k{~@%{bF0zVp~`lj{h!CzYBkTxOEl7WFwvqgxWAC&M*9Ce$$Fp_&GizIUz1RCO#=WHZdVKCN4QHAt5p) zE-o^Dy;1KjWThe2*GR0=!|jY(+4yF;kU1dA2q>Eb_2Ka>KFZcYK2=UYANa*&&%>*_ zwoYG0!Ay)&f1dM8s>TeG#K&&i)$w&L?w_5_6(I125r+zgvWCf7N;!~qs{Y#J@eQuA z3-rhO(`g(L5!E-B@nO7{I+*QKT)4QjQa*xdt5hhOpiLVh4WrJ6A#Y7YrPnUeEPp}? z0jy{?ap?6%pD)RRCy~fl);-2z4Et2906@Lmgl*;o{qyPI%c5zfW@NV4`KZQnH7iC0 z*R=yp=nZB|zNPnS%>iv~qZGN9f*jgcVR6ew3=9LLSMBp^{ojkNhA_HrO5KsnW$n^C zHn-j-cS&8XT{CiuZKJ;yeV<-#tMgtZDM|AS=>S z2e!cua+(U!!x9f2Ei1H$!;8U-c2#O+6hT9EoPiDBl{T}XAk}$GkaI_)4UcJG@hy~K za{ELodFj`I;)e{E6<$m4*)hT&vk1~vTK>mUXwQiB4;zL4kEB;bncU+gCol@!HX*;Cm4&%GAU$y8L&dON0uda^Y^@=mvUKKeuRZU3-1eIWPz# z!Z|91UDp5)`h@$cIfwp=3t5}wrO`*9pSvRfsWC6rC`w5Q9cobs;q+DO^wM}??Bs@* zSnkX1dsecx8Q%E5Ho97VQGK)P+PLX+t-N;W36h?I0+jbgh1pF<1UMf9dnr3Gf2=C3f9foQzT&sBF6nt$(D7tNV3rj!yK!NDuk97G%0KbFBep*+$I{sQ5UbK3@SH!liA zWy6v-`55v!93U^M5TzJTyCn1i0*D7rJ^POJ(r20W3sM;?1#!@JT2;DnaPG`1f?fOz zSuLED0<7Bz?_5fgR)w@>RfftMxf^IV=NaiDhn{otH3er2SLfQFXsa*q3+o!U4zjuJ zVbJ!Tf2MeQ5kxAcO8;Q36}mlR!$i32%uiqnhH`f!^Ls*3H~rWb587l&VuS@i9H&Lo zp!cuiq}L)5$RPsqeAk6RUr)sCm15+2BC%Ba6po9DY?Ocg_=b7a?xzyQeVIw&y^)8{#jc5K0dfA5@8VW-D0jh0SoiZtDa5 z3W15yhQX;v^BL|U!ebwA>I-<}eyldpnxGa)oRX1XV?jK~M~~+07XmhxwYYPlfomWp z^kzJ>K^bVbahmJd>9k->Y|Le#a~Y*_&DpWsBF?-m=o~%rx#?@iRb()+^nO);82#=^kBbfIk0C#|0K|dBS=eW=lF7_g zMj)2Im8c?}Rhx30X7hbpq1|_Spl9GSrBs@?QStu*@eB_0B$?4HHcK4)$}{%pqL#KJ z4TiVO^t^P@ZTn-#o*{tB4xta`ApAx?OU&qD-^&$4+Cz7 zwgM__QfNe#z+4QY0-~*x4cou+okyiK_1jl^yc^yb5E`eONj#H37V3Y8UI>P|9xcuJ=}aI`2tyJ|949$QWcwGqV2*s@J@5OJXMVTSQp%8sk4H2UYk;3; zFRoD`GYRA%hX9UM2>u+y7&bQG?Ufvj8r z9=3d6I&bj;4%CKznv@)r7y$SwGzWA4DzMS5FvRU?a)V9(gX6Wzb)f?)U|#e@c9!!F zK@hPWFOg`@y3*qbb-sH!BsEXFe;bca@8Qa&uGy3bkFVwuAbi%yr`Of_QskdlZ zwx-QY7rP(cZ>^9Xzl#gElA%*(T5R{Z#bXOKbh|4(UEWa6O6$u603NpdxHTTk3)oN_ z`aRmBPJ#@8-z=%_>ah1xf~E;khE$iihk6s4JYAuT97cskhear955MJMF6Zf~8P%ggsTHm)YFM$aA5c(^X@=;j2fvRqC5HCMvf@$9RD}n7z;OY31+~ zTQ5kt$l0|jE0QL3PjGorg9!m1w*0y@UhD&yP#c!?!q8DcF#sSXJEca;zS50IFtv47 znfQ2k8hUGcyJo1rt^CFwNQN1kh}OD6+v_-Plda@QE0DCNXmGhk`Aft-LFiE&N7NK5 z1KVGT9AGM7v`q$idRVH7=zhDK=jn287HkNqDLGDRx+ll83(NJmC52)~Y7=aMD^@aX z+V55`n|z4C1OByqZbxp{7Y#!pYC}INV>)I=0GQESSi1e(GH-v?wSN|egPI-!wlH|3 zq^N6P9zsi*@-G5!e&5^wH2I;hq=r;R8ImL5G)mEEWpaI^se4U*=cmNY>L$4b{y(kF* zfHZBV!)Q2?TR!bpUN}<2a^(WH%g88%i~Y1Wzd`gQ#pYxE*#rq$YVY8tM7}qA1QnA5 zWem~rXAb@fPZv30rncK;rjK@nI#VC|jG;rezS2R*4$0nR$5@yGzJDO^Jz0>v;Bim5 zDy=@uLW*q^@y_kvAVn^vH*6dtbLvK0#(ZcV z(g3m0;i>fy(Jj#?9SQ&*w*0&n9(Vy8YDF(IB_}8Z07m@zt2TS~tJ57nau_?@n5%%U z!|+4L)v!MlZc!Dy*xXl12eDs9+Asmc?r(_n8M1adOx(R{(Pl@0>nuiP?4WOU2IW<<7s2l@qeEU#~yo z$O8=?w*0s@Uc?L7P%CD}n9)H&1OPZB^Kl18}Jbr4t_R~`ktz7 zz0Vk(p%m9_+iT69VSN2a099+hvC54&>eh7)PXYdi2m^gPon&vF$krMJ0RFXnUn)1^ z1#GAdJ+Fr`+L90eWHxd66wRg2J0-OGAg)FxitUF3aDBlO%qp0GswiC5?ww#+Mt0u3 zK|5I@8}Mgsm~#0SPFTPZO&_bmn^bk;V4D4EMLd>?oD^|MDqQO%eKM+7)xusyb$w%R zx`KT~vBUbe-rxmns13bLQ7V)W zfZloVVFF{&7uB=QIN{2MxZA~Fy;P6*0oObt4$*;0Sl!IITij>7jA9N1ap9+Y5}_q$ z9rW|6zil$NRGjq(AHKUdFFm%_>zkL&c-4)ec8oA$5Iq8xE{$u(%}ZfaB;4*I1KW=x zq@*v%iDpF&tO%6Mv*g_Jx(EKX{MZ(57ca;*)P{b~FhwOs0LT-bsdakK%1k}9a6Vgi zr>@-&InQPrZ(BCWbg{*4z@L(JV@jw<*@z$}Q#9v#yEV&d@kn70 zi%c0REXVsUt{UJ09=80rc0PCj18PGrdfmjxj0gb4M-95}=;EIez}>S;+TO0<|~iBDhx z9=80rHEwtT8)`$Z(3CR_Ap^kvv}wy8&yJ^mZ%D>6#;EQngZo?Q$7wV4$vVZ(N7u@P zKra^I16#DVN&|rQYyutTM;;+_vfU)PLT4syJzbxz}%r2ml1R{_+XhS)A=|d!N5%-Qps>fIc8CD%&#<>f3!%vhc+*(d$$1e19fB z`JxWBAgzgavSUB(kK}io!<9MimEnZqrdDbf2 zZ7Ce^<_j|0UC5=&=WI!!!p&pUYpt=vO1fc!E!<9&$U1lc9=80sR9?gbxS>`A&kR$N z7y-ETUR~7DxiiT{zt-3_?@v*9{J9w=6yYV1f?z4CwwC~NXxan1$`>`eeq<1VTGNeX zthp4SF#3YSD4VF}INb6-7fj?r({gE8G|Pn8B!2P9I5BO?jGNB!k literal 0 HcmV?d00001 diff --git a/Resources/Locale/ru-RU/_white/cult/entities.ftl b/Resources/Locale/ru-RU/_white/cult/entities.ftl index 1c16bb87ab..6f0853d15c 100644 --- a/Resources/Locale/ru-RU/_white/cult/entities.ftl +++ b/Resources/Locale/ru-RU/_white/cult/entities.ftl @@ -8,6 +8,9 @@ ent-SoulShardGhost = камень душ ent-StunHand = оглушающая аура .desc = Оглушит и обезмолвит жертву при ударе. +ent-RitesHand = аура кровавых обрядов + .desc = Впитывает кровь из всего, к чему прикасается. При ударе по культистам и конструктам может исцелить их. Используйте в руке, чтобы провести продвинутый обряд. + ent-ShadowShackles = теневые оковы .desc = Оковы, сковывающие запястья с помощью зловещей магии. diff --git a/Resources/Locale/ru-RU/_white/cult/messages.ftl b/Resources/Locale/ru-RU/_white/cult/messages.ftl index 560d37bedf..28ef024ebf 100644 --- a/Resources/Locale/ru-RU/_white/cult/messages.ftl +++ b/Resources/Locale/ru-RU/_white/cult/messages.ftl @@ -1,3 +1,12 @@ -cult-stun-component-extra-message = [color=darkgray]Выбросите ауру, чтобы навсегда избавиться от неё.[/color] +cult-hand-component-extra-message = [color=darkgray]Выбросите ауру, чтобы навсегда избавиться от неё.[/color] cult-magic-holy = Сила священного предмета в руках цели препятствует магии! cult-magic-no-empty-hand = Вам нужна свободная рука для использования заклинания! + +cult-rites-examine = [color=darkred]Всего высосано крови: { $blood }.[/color] +cult-rites-message = Всего высосано крови: { $blood }. +cult-rites-dead = Цель мертва. +cult-rites-heal-no-blood = Нет крови для лечения. +cult-rites-already-healed = Он не имеет повреждений. +cult-rites-after-heal = Осталось крови: { $blood }. +cult-rites-no-blood = Для обряда необходимо высосать { $required } крови с помощью заклинания Кровавые Обряды. Всего высосано: { $blood }. +cult-rites-no-hand = Вам нужна свободная рука для обряда. diff --git a/Resources/Locale/ru-RU/_white/cult/verb.ftl b/Resources/Locale/ru-RU/_white/cult/verb.ftl index 08f35fca69..cb1f9c275b 100644 --- a/Resources/Locale/ru-RU/_white/cult/verb.ftl +++ b/Resources/Locale/ru-RU/_white/cult/verb.ftl @@ -7,8 +7,3 @@ verb-spell-create-too-much = Начертите руну могущества, verb-spell-remove-text = Удалить заклинание крови verb-spell-remove-message = Убрать любое из созданных заклинаний крови. verb-spell-remove-no-spells = Заклинания крови отсутствуют. - -verb-blood-rites-text = Кровавые обряды -verb-blood-rites-message = Всего высосано крови: { $blood }. -verb-blood-rites-no-blood = Для обряда необходимо высосать { $required } крови с помощью заклинания Кровавые Обряды. Всего высосано: { $blood }. -verb-blood-rites-no-hand = Вам нужна свободная рука для обряда. diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 49d4b49dd4..4999048e76 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -221,8 +221,6 @@ type: SpellSelectorBUI - key: enum.CultEmpowerRemoveUiKey.Key type: SpellRemoverBUI - - key: enum.BloodRitesUi.Key - type: CultistFactoryBUI # WD-EDIT END - type: Puller - type: Butcherable diff --git a/Resources/Prototypes/_White/Actions/cult_actions.yml b/Resources/Prototypes/_White/Actions/cult_actions.yml index 864f0f93cd..415007c8eb 100644 --- a/Resources/Prototypes/_White/Actions/cult_actions.yml +++ b/Resources/Prototypes/_White/Actions/cult_actions.yml @@ -123,7 +123,6 @@ sprite: /Textures/White/Cult/actions_cult.rsi state: blood_rites event: !type:CultBloodRitesInstantActionEvent - speech: "Fel'th Dol Ab'orod!" charges: 5 temporary: true removeOnNoCharges: true diff --git a/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml b/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml index 885844e63b..5282cb3c7b 100644 --- a/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml +++ b/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml @@ -1,13 +1,11 @@ - type: entity - id: CultTileSpawnEffect - name: Sparkle + id: CultTileEffect + name: cult tile effect placement: mode: SnapgridCenter components: - # Animation is like 3 something seconds so we just need to despawn it before then. - type: TimedDespawn lifetime: 0.5 - - type: EvaporationSparkle - type: Transform noRot: true anchored: true @@ -19,6 +17,14 @@ netsync: false drawdepth: FloorObjects color: "#FF0000" + +- type: entity + parent: CultTileEffect + id: CultTileSpawnEffect + name: cult tile glow + placement: + mode: SnapgridCenter + components: - type: PointLight color: "#FF0000" @@ -26,10 +32,8 @@ id: CultTeleportInEffect name: Teleport in components: - # Animation is like 3 something seconds so we just need to despawn it before then. - type: TimedDespawn lifetime: 0.8 - - type: EvaporationSparkle - type: Transform noRot: true anchored: true @@ -47,10 +51,8 @@ id: CultTeleportOutEffect name: Teleport out components: - # Animation is like 3 something seconds so we just need to despawn it before then. - type: TimedDespawn lifetime: 0.8 - - type: EvaporationSparkle - type: Transform noRot: true anchored: true @@ -70,7 +72,6 @@ components: - type: TimedDespawn lifetime: 1 - - type: EvaporationSparkle - type: Transform noRot: true anchored: true @@ -90,7 +91,6 @@ components: - type: TimedDespawn lifetime: 1 - - type: EvaporationSparkle - type: Transform noRot: true anchored: true diff --git a/Resources/Prototypes/_White/Entities/Cult/Items/hands.yml b/Resources/Prototypes/_White/Entities/Cult/Items/hands.yml new file mode 100644 index 0000000000..d21ac1879d --- /dev/null +++ b/Resources/Prototypes/_White/Entities/Cult/Items/hands.yml @@ -0,0 +1,74 @@ +- type: entity + parent: BaseItem + id: BaseCultHand + abstract: true + noSpawn: true + name: magical aura + description: A sinister looking aura that distorts the flow of reality around it. + components: + - type: Item + size: Ginormous + - type: MeleeWeapon + canHeavyAttack: false + canMiss: false + attackRate: 2 + wideAnimationRotation: 180 + damage: + types: + Heat: 0 + - type: DeleteOnDropAttempt + message: cult-hand-component-extra-message + - type: Unremoveable + deleteOnDrop: true + - type: CultItem + canPickUp: false + +- type: entity + parent: BaseCultHand + id: StunHand + name: stunning aura + description: Will stun and mute a weak-minded victim on hit. + components: + - type: Sprite + sprite: White/Cult/Entities/stun.rsi + state: icon + - type: Item + sprite: White/Cult/Entities/stun.rsi + - type: MeleeWeapon + canAttackSelf: false + attackWhitelist: + components: + - StatusEffects + attackBlacklist: + components: + - Cultist + - Construct + - type: CultStunHand + speech: "Fuu ma'jin!" + +- type: entity + parent: BaseCultHand + id: RitesHand + name: blood rite aura + description: Absorbs blood from anything you touch. Touching cultists and constructs can heal them. Use in-hand to cast an advanced rite. + components: + - type: Sprite + sprite: White/Cult/Entities/rites.rsi + state: icon + - type: Item + sprite: White/Cult/Entities/rites.rsi + - type: MeleeWeapon + attackWhitelist: + components: + - Cultist + - Construct + - type: CultRitesHand + speech: "Fel'th Dol Ab'orod!" + - type: ActivatableUI + key: enum.BloodRitesUi.Key + inHandsOnly: true + closeOnHandDeselect: true + - type: UserInterface + interfaces: + - key: enum.BloodRitesUi.Key + type: CultistFactoryBUI diff --git a/Resources/Prototypes/_White/Entities/Cult/Items/stun_hand.yml b/Resources/Prototypes/_White/Entities/Cult/Items/stun_hand.yml deleted file mode 100644 index c73620a53f..0000000000 --- a/Resources/Prototypes/_White/Entities/Cult/Items/stun_hand.yml +++ /dev/null @@ -1,34 +0,0 @@ -- type: entity - parent: BaseItem - id: StunHand - name: stunning aura - description: Will stun and mute a weak-minded victim on hit. - components: - - type: Sprite - sprite: White/Cult/Entities/stun.rsi - state: icon - - type: Item - size: Ginormous - sprite: White/Cult/Entities/stun.rsi - - type: MeleeWeapon - canHeavyAttack: false - canAttackSelf: false - canMiss: false - attackWhitelist: - components: - - StatusEffects - attackBlacklist: - components: - - Cultist - - Construct - wideAnimationRotation: 180 - damage: - types: - Heat: 0 - - type: CultStunHand - - type: DeleteOnDropAttempt - message: cult-stun-component-extra-message - - type: Unremoveable - deleteOnDrop: true - - type: CultItem - canPickUp: false diff --git a/Resources/Prototypes/_White/Entities/Cult/Runes/cult_runes.yml b/Resources/Prototypes/_White/Entities/Cult/Runes/cult_runes.yml index 262acf8e10..f185afda37 100644 --- a/Resources/Prototypes/_White/Entities/Cult/Runes/cult_runes.yml +++ b/Resources/Prototypes/_White/Entities/Cult/Runes/cult_runes.yml @@ -30,6 +30,7 @@ - type: Appearance - type: CultRuneBase invokePhrase: "Qu'laris ver'don, thal'sorin mik'thar!" + gatherInvokers: false - type: CultRuneBuff - type: CultRune - type: Concealable @@ -47,6 +48,8 @@ color: '#F80000' - type: Appearance - type: CultRuneBase + invokePhrase: "H'drak v'loso, mir'kanas verbot!" + gatherInvokers: false - type: CultEmpower isRune: true - type: UserInterface @@ -55,7 +58,6 @@ type: SpellSelectorBUI - type: CultRune - type: Concealable - examinableWhileConcealed: true - type: entity parent: CollideRune @@ -91,7 +93,6 @@ - type: Appearance - type: CultRuneBase invokePhrase: "N'ath reth sh'yro eth d'rekkathnor!" - gatherInvokers: true - type: CultRuneSummoning - type: CultRune - type: Concealable diff --git a/Resources/Prototypes/_White/Entities/Cult/constructs.yml b/Resources/Prototypes/_White/Entities/Cult/constructs.yml index 44071134e3..e28c658f3d 100644 --- a/Resources/Prototypes/_White/Entities/Cult/constructs.yml +++ b/Resources/Prototypes/_White/Entities/Cult/constructs.yml @@ -7,8 +7,8 @@ context: "human" - type: InputMover - type: MovementSpeedModifier - baseWalkSpeed: 2.5 - baseSprintSpeed: 2.5 + baseWalkSpeed: 3 + baseSprintSpeed: 3 - type: DamageOnHighSpeedImpact damage: types: @@ -61,6 +61,8 @@ - type: ContentEye - type: Actions - type: Hands + - type: Puller + needsHands: false - type: ShowCultHud - type: IsDeadIC - type: NightVision @@ -138,8 +140,6 @@ baseWalkSpeed: 3 baseSprintSpeed: 3 - type: MovementIgnoreGravity - - type: Puller - needsHands: false - type: MeleeWeapon canHeavyAttack: false hidden: true @@ -202,8 +202,6 @@ 150: Dead - type: Sprite state: harvester - - type: Puller - needsHands: false - type: MeleeWeapon canHeavyAttack: false hidden: true diff --git a/Resources/Prototypes/_White/Mobs/Species/harpy.yml b/Resources/Prototypes/_White/Mobs/Species/harpy.yml index 1f16f43833..351a45d5ae 100644 --- a/Resources/Prototypes/_White/Mobs/Species/harpy.yml +++ b/Resources/Prototypes/_White/Mobs/Species/harpy.yml @@ -45,8 +45,6 @@ type: SpellSelectorBUI - key: enum.CultEmpowerRemoveUiKey.Key type: SpellRemoverBUI - - key: enum.BloodRitesUi.Key - type: CultistFactoryBUI # WD-EDIT END - type: Sprite scale: 0.9, 0.9 diff --git a/Resources/Textures/White/Cult/Entities/rites.rsi/icon.png b/Resources/Textures/White/Cult/Entities/rites.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e7df415ac853d944e1e648c30331e1c347dd4a47 GIT binary patch literal 665 zcmV;K0%rY*P)q;usqH`v~t zsznM30J_a6`iG!qJ&U-PJ02Ol9`&k4y`Z+3mn*Kr3 za1;QH#{SOx0Pw0+=I?)6fujKScKo!~Tvg#9X_!jYO#)Mfx7vUT>1v?0Ci!+J zvO3!V1C((_&q`tQ{4`!rCQt(yQvm>VKVDfa7r3a-sW*iWMaYqztj<_Azsf5r(GZ~) zIckvyqqw3HR7k9ri+h3xFrmQrFJA{{&S|Jcj*IG0QR$-PZy&tJ(Ysc(X(fWf;J)X) zGyF(XPA{qp*1qiA4XW3!aQ$)YesD#zLmyPgz;Wy_KI8T8KYtwoCdOUGBpiWtNdt)- z-`+=T$}k&9sSrD7FbN-TGRNMIe@w|5a4GOw@RoC*gpbv7fzA8=S*fvrd+kPYK%f!= zRAhiM;owjhI4!Y*7=He#kjYm3Sr&jE`!y)SbxFfko8;8m3F%01if;8d!%xAR9BusS zq8hjdK8bsrF{Z}we-mI5*Uqmwd*Fcw9!TLIKc-L$--Td900000NkvXXu0mjfvdt`4 literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Cult/Entities/rites.rsi/inhand-left.png b/Resources/Textures/White/Cult/Entities/rites.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..516c310227cfad6b71e7a2581df14ffac12f9dc8 GIT binary patch literal 543 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Py!3HG1+{xJmq*#ibJVQ8upoSx*gMoqZnx~6n zNX4ADcYTX4I|#5{aO*LC_@C`fL=pe|Bi4FHu5NlP!qMH)D!4RMM?3je-~HQ5f}UPl z{!*^;s+2p>I3T#55&p{Je|52WAt&pNsaAR?-=7oQ_x6;8;K#RTcTZuu;_IpVZ<}`V z-6^i~bMH0eh9A@4`tSGu-xv00%`Mcie{`XR=kl-Le>c4Nd{){(|DW^y?fd>b`cr3r zr2qK+%%6g%%^W|o*?g(}@>?;NJuay37+X)r;bew*5;`9|<_@%_V-H!r+d z{B5Pa#gW8K)#0xm1%5W|<9j~uH(TGz*+P-U(=Okd-ZyJ~;TFcy;79xJEfqA?383 zruxmTxed?S%hSabKF79oT)uvP52K{}vGYrP4gZ(EV#~PKaQ^P=Yt#3v`V)MAS!JRB zfwj+>VFn!FF5*o88y{V^`R0W;Oeyjk_iLBN1UIYk-Y8Su$}oA2?}hj6SKq7J>}I^Z zuIKW_caoD227mtjcfu_Bjd_24=QaGUD!&##Gh)*GmzJ;dFEz~nyIySi#QkC4B!6$8 d#}A5;$NWrUCmw1};4cDM>FMg{vd$@?2>_4t07(D< literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Cult/Entities/rites.rsi/inhand-right.png b/Resources/Textures/White/Cult/Entities/rites.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..a159a468a0a03d670275fbaa26382e8e5957dfa7 GIT binary patch literal 554 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Py!3HG1+{xJmq*#ibJVQ8upoSx*gMoqZp{I*u zNX4ADcYTYb3wtKax zWbXgTtUvbV$}jtVI_h$lfo@$`-R+#+=jz|{MQs1}qb@SL|Igk$xp#|mw`Km^ZM{DH zU;X#8*eMyabMM&PDVIEueJ*~x*y*U?=klu;_RRdx_WyuJLNzc;xz+;*S8kwNmipv~0!6Mxe65A52yBe%TYJZ#UF;`99-f9Cxv zKF&Mr*Y@5{r*}G?~T8HKdD!DWIyxK=LIE<%ci|v zlg{Piek(ne3i8 lewlA&K4&WrG~vO_e+@K@0VDtb literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Cult/Entities/rites.rsi/meta.json b/Resources/Textures/White/Cult/Entities/rites.rsi/meta.json new file mode 100644 index 0000000000..489466f74a --- /dev/null +++ b/Resources/Textures/White/Cult/Entities/rites.rsi/meta.json @@ -0,0 +1,66 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/pull/49264/commits/d0dffe7ca643db2624424fdcebf45863f85c0448", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-left.png b/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-left.png index 19acec50cf6c0180f88f2322de828310e3565266..1c2504631f652df82d8f2933796ab89034bdbe41 100644 GIT binary patch delta 482 zcmV<80UiF$2K)n%B!2{RLP=Bz2nYy#2xN!=00FZ}L_t(|obBDqZQDQ;1<>mtTLEq$ zEx3g=;1bdmTX6$vK@GSC11f-7$b`9x`SDOsG|$-x0tURCc|)xpM+pD`00026N9Uv; ze;)28?qLDWNk1q5#}?t;d+=+~0-RF2_+8SUW{z!MfG+8uM}Oa+l84qAQ~AlY2o;9; zUuKSPUV!o9zqG#ig8WO8zlHh9yiL%&057>tzG?^FQ+~w;Omck;yW-#ABj*DE00000 z0001R&#GI@x4wr@dqb=H>`Py8$hEWkyr9*5jmhTRt#4q;DIYE8w>HduZmanklLa^> zc}&eB4DIEAihuG4zc$SOv;gD&`se?Sx{ZqbTg?CG)PUjftLk+>dVYDY`_c0O00000 z00000s8-!lPO-ghfaZsHS1&;2y9~+l`8O{>#gXx2WnIkgmTrLN1^C_if;-D!`ZmqC zdjgK04*&oF00000007^}J)HHwx9n!Uq16jeeZ>Ab>08&VL6ZV>#S1W~+60%Ze=p(7 z1?ZA~INH6UGq@Z5$wFm*R^~T(0v@yNzf8=@uk@AqHz~kdi;Ku#ulkJrqvrzv0Kk6y Y1N#S!FBS!A)&Kwi07*qoM6N<$f>9*tSpWb4 literal 845 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Py!3HG1+{xJmq&N#aB8wRq_>O=u<5X=vX$A(S z|DG<6Ar*7p-rblL94OQ9vHoD_g;0TCEKMe}7wmSKe?VO$t)QT&sGz7|$D`&e57s>h z(|p3J!x5|fgJI+UDcUn9&Hggy_tRtVx4#hh@%+yFdD9M@e7jcQ6oUct0UicphBG)A z0SDha{QR?d^W^4l_e0mO6-$_GzR`bku=VcK*{fMH_}sf6+Q;vk`~T-Z(0l(Y)0G+f_xvmEVn6Y4?aMF4U)Ii@FaF^5 zQ&uzkr@jK|>e}(~HV$!L)XU$;^3VTP&sdgOH(h!|MZ?LTFCB%$?b+6e&Hvv&k2kk& zYW$%ihuW>~pJycCcC6mYdCnZ*er9_5^%{O{<_pi??4GxA{nFU#>CW43N9|_L+TU1O zR90MRsNN^NEqi_CncCcj8s_qOc7179ul_1M`S__&=4iM7d*#0P^DB+#f4{%C>)DQT zz8j1jsu_dkRnM=n;pH;i-~V;}UB+4=naFSkvqw==hy?LT#&pX0)XXTL2O(imniCa^U~lEw%#IiP3rx;|rbH><+@ zulu?CZ_Ibqxwb#ELy2+L;lQuY-;_JPZHoE6?e+e`hCM%iW_)*<;}h5Cf6o8*8U0Pn zpZIP5RDD*|u$+IV);zL)BE$auHQbjbJil*o;E~OrFTcbEzV`fAJP%ZYsI&yrdSeO8wAPSlY0`L+6Z=T3OmB4!iW`r3>!NtdvXrY~#lO0u5gIClmja+di~U z;mJR_u>9NMEA9XNAKreXl(Xv4K~gPXI*hh{{5b~pOaZ7*fyTOo^&TD_1`)R`;&#QL;ta@v6Tng10wp~EnWNX z_Pq=Dm|v{asxLkzS3YC@<)sXV8LDc&t8P1bUgS;jPbm}q17?;s&$6?>>*h{Ay#Mmo z?7)BbCI8>w!%+X&?pGJF$4_mWFmDcNPIlMRix;#YO{-@1_-K{rSC8E}?zNcv*lNnzs%=0;a z>i!J&H0!4B;^2w|o+|nymRnI=>H`&2FCSs!kl0Mrcx;lCJS*Y^Ld%Kp{@ O;(EIJxvXO=u<5X=vX$A(S zzn(6RAr*7p-Zjj-93a#1(OyVfC{|msu*pl~uGU0ZR=)#+9}Wmg%#did@Q~ivd}Xah zklqEq$nGPIPV*0jPE*_Xb>99Xf9tqs{(9Hb{!(dFDQ(ED;#B+beSo>+E=KQp|Bs0p%#J&v;)!qC1ylpkl z=k4nlUY-8F@yz#fhBFKX%m;WFj7ecg=QJE`%vr53lpz1@>w0v&-}5iY&;0j0KmO78@AFUey)yZK^m+f+Kd~wN z0rqD;$QLqRdoFxyUi~+Quk(I!6BF>=3 z9Sd9e9P%yYZyA{N^Y zVT>KuFRq{6c>CdGA#;b-438H-?wEbx!e{S2LjMxr4#e)z4*}Q$iB}-A-Y; From 397e74079bf38eb6611583caf639600db10938b2 Mon Sep 17 00:00:00 2001 From: Spatison <137375981+Spatison@users.noreply.github.com> Date: Tue, 30 Jul 2024 03:13:05 +0300 Subject: [PATCH 4/8] Fix (#513) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Ботинки клоуна сново работают * fix: Световое копье теперь исчезает если его передать --- .../Animations}/WaddleAnimationSystem.cs | 89 ++++--------------- .../Animations/WaddleAnimationSystem.cs | 16 ++++ .../_White/OfferItem/OfferItemSystem.cs | 12 ++- .../EntitySystems}/WaddleClothingSystem.cs | 6 +- .../SharedWaddledAnimationSystem.cs | 47 ++++++++++ .../Animations}/WaddleAnimationComponent.cs | 26 ++---- .../HardlightSpear/HardlightSpearSystem.cs | 7 ++ .../_White/OfferItem/SharedOfferItemSystem.cs | 8 ++ 8 files changed, 115 insertions(+), 96 deletions(-) rename Content.Client/{Movement/Systems => _White/Animations}/WaddleAnimationSystem.cs (50%) create mode 100644 Content.Server/_White/Animations/WaddleAnimationSystem.cs rename {Content.Client/Clothing/Systems => Content.Shared/Clothing/EntitySystems}/WaddleClothingSystem.cs (88%) create mode 100644 Content.Shared/_White/Animations/SharedWaddledAnimationSystem.cs rename Content.Shared/{Movement/Components => _White/Animations}/WaddleAnimationComponent.cs (70%) diff --git a/Content.Client/Movement/Systems/WaddleAnimationSystem.cs b/Content.Client/_White/Animations/WaddleAnimationSystem.cs similarity index 50% rename from Content.Client/Movement/Systems/WaddleAnimationSystem.cs rename to Content.Client/_White/Animations/WaddleAnimationSystem.cs index e6a88cb485..23657821f3 100644 --- a/Content.Client/Movement/Systems/WaddleAnimationSystem.cs +++ b/Content.Client/_White/Animations/WaddleAnimationSystem.cs @@ -1,89 +1,37 @@ using System.Numerics; -using Content.Client.Gravity; -using Content.Shared.Rotation; +using Content.Shared._White.Animations; using Content.Shared.Movement.Components; -using Content.Shared.Movement.Events; using Robust.Client.Animations; using Robust.Client.GameObjects; using Robust.Shared.Animations; -using Robust.Shared.Timing; -namespace Content.Client.Movement.Systems; +namespace Content.Client._White.Animations; -public sealed class WaddleAnimationSystem : EntitySystem +public sealed class WaddleAnimationSystem : SharedWaddledAnimationSystem { [Dependency] private readonly AnimationPlayerSystem _animation = default!; - [Dependency] private readonly GravitySystem _gravity = default!; - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly AppearanceSystem _appearance = default!; // WD EDIT public override void Initialize() { - SubscribeLocalEvent(OnMovementInput); - SubscribeLocalEvent(OnStartedWalking); - SubscribeLocalEvent(OnStoppedWalking); SubscribeLocalEvent(OnAnimationCompleted); + + SubscribeAllEvent(ev => PlayAnimation(GetEntity(ev.User))); + SubscribeAllEvent(ev => StopAnimation(GetEntity(ev.User))); } - private void OnMovementInput(EntityUid entity, WaddleAnimationComponent component, MoveInputEvent args) + protected override void PlayAnimation(EntityUid uid) { - // Prediction mitigation. Prediction means that MoveInputEvents are spammed repeatedly, even though you'd assume - // they're once-only for the user actually doing something. As such do nothing if we're just repeating this FoR. - if (!_timing.IsFirstTimePredicted) - { - return; - } - - // WD EDIT - _appearance.TryGetData(entity, RotationVisuals.RotationState, out var state); - if (state is RotationState.Horizontal) - return; - // WD EDIT - - if (!args.HasDirectionalMovement && component.IsCurrentlyWaddling) - { - component.IsCurrentlyWaddling = false; - - var stopped = new StoppedWaddlingEvent(entity); - - RaiseLocalEvent(entity, ref stopped); - - return; - } - - // Only start waddling if we're not currently AND we're actually moving. - if (component.IsCurrentlyWaddling || !args.HasDirectionalMovement) + if (!Timing.IsFirstTimePredicted) return; - component.IsCurrentlyWaddling = true; - - var started = new StartedWaddlingEvent(entity); - - RaiseLocalEvent(entity, ref started); - } - - private void OnStartedWalking(EntityUid uid, WaddleAnimationComponent component, StartedWaddlingEvent args) - { - if (_animation.HasRunningAnimation(uid, component.KeyName)) - { + if (!TryComp(uid, out var component)) return; - } if (!TryComp(uid, out var mover)) - { return; - } - if (_gravity.IsWeightless(uid)) - { + if (_animation.HasRunningAnimation(uid, component.KeyName)) return; - } - - // WD EDIT - _appearance.TryGetData(uid, RotationVisuals.RotationState, out var state); - if (TryComp(uid, out var sprite) && TryComp(uid, out var rotat) && state is RotationState.Horizontal) - return; - // WD EDIT var tumbleIntensity = component.LastStep ? 360 - component.TumbleIntensity : component.TumbleIntensity; var len = mover.Sprinting ? component.AnimationLength * component.RunAnimationLengthMultiplier : component.AnimationLength; @@ -126,14 +74,15 @@ public sealed class WaddleAnimationSystem : EntitySystem _animation.Play(uid, anim, component.KeyName); } - private void OnStoppedWalking(EntityUid uid, WaddleAnimationComponent component, StoppedWaddlingEvent args) + protected override void StopAnimation(EntityUid uid) { - _animation.Stop(uid, component.KeyName); + if (!TryComp(uid, out var component)) + return; if (!TryComp(uid, out var sprite)) - { return; - } + + _animation.Stop(uid, component.KeyName); sprite.Offset = new Vector2(); sprite.Rotation = Angle.FromDegrees(0); @@ -142,13 +91,9 @@ public sealed class WaddleAnimationSystem : EntitySystem private void OnAnimationCompleted(EntityUid uid, WaddleAnimationComponent component, AnimationCompletedEvent args) { - if (args.Key is not "Waddle") // WD EDIT - { - component.IsCurrentlyWaddling = false; + if (args.Key != component.KeyName) return; - } - var started = new StartedWaddlingEvent(uid); - RaiseLocalEvent(uid, ref started); + PlayAnimation(uid); } } diff --git a/Content.Server/_White/Animations/WaddleAnimationSystem.cs b/Content.Server/_White/Animations/WaddleAnimationSystem.cs new file mode 100644 index 0000000000..c7ebdf5d75 --- /dev/null +++ b/Content.Server/_White/Animations/WaddleAnimationSystem.cs @@ -0,0 +1,16 @@ +using Content.Shared._White.Animations; + +namespace Content.Server._White.Animations; + +public sealed class WaddleAnimationSystem : SharedWaddledAnimationSystem +{ + protected override void PlayAnimation(EntityUid user) + { + RaiseNetworkEvent(new StartedWaddlingEvent(GetNetEntity(user))); + } + + protected override void StopAnimation(EntityUid user) + { + RaiseNetworkEvent(new StoppedWaddlingEvent(GetNetEntity(user))); + } +} diff --git a/Content.Server/_White/OfferItem/OfferItemSystem.cs b/Content.Server/_White/OfferItem/OfferItemSystem.cs index 23df303bea..c4a10f7c3e 100644 --- a/Content.Server/_White/OfferItem/OfferItemSystem.cs +++ b/Content.Server/_White/OfferItem/OfferItemSystem.cs @@ -69,12 +69,18 @@ public sealed class OfferItemSystem : SharedOfferItemSystem _popup.PopupEntity(Loc.GetString("offer-item-give", ("item", Identity.Entity(offerItem.Item.Value, EntityManager)), - ("target", Identity.Entity(uid, EntityManager))), component.Target.Value, component.Target.Value); + ("target", Identity.Entity(uid, EntityManager))), + component.Target.Value, + component.Target.Value); _popup.PopupEntity(Loc.GetString("offer-item-give-other", ("user", Identity.Entity(component.Target.Value, EntityManager)), ("item", Identity.Entity(offerItem.Item.Value, EntityManager)), - ("target", Identity.Entity(uid, EntityManager))) - , component.Target.Value, Filter.PvsExcept(component.Target.Value, entityManager: EntityManager), true); + ("target", Identity.Entity(uid, EntityManager))), + component.Target.Value, + Filter.PvsExcept(component.Target.Value, entityManager: EntityManager), + true); + + RaiseLocalEvent(offerItem.Item.Value, new HandedEvent(component.Target.Value, uid)); } offerItem.Item = null; diff --git a/Content.Client/Clothing/Systems/WaddleClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/WaddleClothingSystem.cs similarity index 88% rename from Content.Client/Clothing/Systems/WaddleClothingSystem.cs rename to Content.Shared/Clothing/EntitySystems/WaddleClothingSystem.cs index b8ac3c207b..b9c3ae08a9 100644 --- a/Content.Client/Clothing/Systems/WaddleClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/WaddleClothingSystem.cs @@ -1,8 +1,8 @@ -using Content.Shared.Clothing.Components; -using Content.Shared.Movement.Components; +using Content.Shared._White.Animations; +using Content.Shared.Clothing.Components; using Content.Shared.Inventory.Events; -namespace Content.Client.Clothing.Systems; +namespace Content.Shared.Clothing.EntitySystems; public sealed class WaddleClothingSystem : EntitySystem { diff --git a/Content.Shared/_White/Animations/SharedWaddledAnimationSystem.cs b/Content.Shared/_White/Animations/SharedWaddledAnimationSystem.cs new file mode 100644 index 0000000000..2ade3a167a --- /dev/null +++ b/Content.Shared/_White/Animations/SharedWaddledAnimationSystem.cs @@ -0,0 +1,47 @@ +using Content.Shared.Movement.Events; +using Content.Shared.Standing.Systems; +using Robust.Shared.Timing; + +namespace Content.Shared._White.Animations; + +public abstract class SharedWaddledAnimationSystem : EntitySystem +{ + [Dependency] protected readonly IGameTiming Timing = default!; + [Dependency] private readonly SharedStandingStateSystem _standingState = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMovementInput); + } + + private void OnMovementInput(EntityUid uid, WaddleAnimationComponent component, MoveInputEvent args) + { + if (!Timing.IsFirstTimePredicted) + return; + + if (_standingState.IsDown(uid)) + return; + + if (!args.HasDirectionalMovement && component.IsCurrentlyWaddling) + { + component.IsCurrentlyWaddling = false; + + StopAnimation(uid); + + return; + } + + if (component.IsCurrentlyWaddling || !args.HasDirectionalMovement) + return; + + component.IsCurrentlyWaddling = true; + + PlayAnimation(uid); + } + + protected abstract void PlayAnimation(EntityUid user); + + protected abstract void StopAnimation(EntityUid user); +} diff --git a/Content.Shared/Movement/Components/WaddleAnimationComponent.cs b/Content.Shared/_White/Animations/WaddleAnimationComponent.cs similarity index 70% rename from Content.Shared/Movement/Components/WaddleAnimationComponent.cs rename to Content.Shared/_White/Animations/WaddleAnimationComponent.cs index c43ef3042e..b2cab95ad1 100644 --- a/Content.Shared/Movement/Components/WaddleAnimationComponent.cs +++ b/Content.Shared/_White/Animations/WaddleAnimationComponent.cs @@ -1,30 +1,20 @@ using System.Numerics; +using Robust.Shared.Serialization; -namespace Content.Shared.Movement.Components; +namespace Content.Shared._White.Animations; -/// -/// Declares that an entity has started to waddle like a duck/clown. -/// -/// The newly be-waddled. -[ByRefEvent] -public record struct StartedWaddlingEvent(EntityUid Entity) +[Serializable, NetSerializable] +public sealed class StartedWaddlingEvent(NetEntity user) : EntityEventArgs { - public EntityUid Entity = Entity; + public NetEntity User = user; } -/// -/// Declares that an entity has stopped waddling like a duck/clown. -/// -/// The former waddle-er. -[ByRefEvent] -public record struct StoppedWaddlingEvent(EntityUid Entity) +[Serializable, NetSerializable] +public sealed class StoppedWaddlingEvent(NetEntity user) : EntityEventArgs { - public EntityUid Entity = Entity; + public NetEntity User = user; } -/// -/// Defines something as having a waddle animation when it moves. -/// [RegisterComponent] public sealed partial class WaddleAnimationComponent : Component { diff --git a/Content.Shared/_White/HardlightSpear/HardlightSpearSystem.cs b/Content.Shared/_White/HardlightSpear/HardlightSpearSystem.cs index e75a2bed10..008d7780d0 100644 --- a/Content.Shared/_White/HardlightSpear/HardlightSpearSystem.cs +++ b/Content.Shared/_White/HardlightSpear/HardlightSpearSystem.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Shared._White.OfferItem; using Content.Shared.Body.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Implants.Components; @@ -30,6 +31,7 @@ public sealed class HardlightSpearSystem : EntitySystem SubscribeLocalEvent(OnLand); SubscribeLocalEvent(OnDrop); + SubscribeLocalEvent(OnHanded); SubscribeLocalEvent(OnInsert); SubscribeLocalEvent(OnPickupAttempt); SubscribeLocalEvent(OnPreventCollision); @@ -96,4 +98,9 @@ public sealed class HardlightSpearSystem : EntitySystem if (!HasComp(args.Container.Owner)) EnsureComp(uid); } + + private void OnHanded(EntityUid uid, HardlightSpearComponent component, ref HandedEvent args) + { + EnsureComp(uid); + } } diff --git a/Content.Shared/_White/OfferItem/SharedOfferItemSystem.cs b/Content.Shared/_White/OfferItem/SharedOfferItemSystem.cs index 4a471028cc..1c754c85cb 100644 --- a/Content.Shared/_White/OfferItem/SharedOfferItemSystem.cs +++ b/Content.Shared/_White/OfferItem/SharedOfferItemSystem.cs @@ -156,3 +156,11 @@ public abstract partial class SharedOfferItemSystem : EntitySystem return entity != null && Resolve(entity.Value, ref component, false) && component.IsInOfferMode; } } + +[Serializable] +public sealed class HandedEvent(EntityUid user, EntityUid target) : EntityEventArgs +{ + public EntityUid User = user; + public EntityUid Target = target; +} + From cd0701180c19b6503e3c19d19a32428f817e506f Mon Sep 17 00:00:00 2001 From: RavmorganButOnCocaine Date: Tue, 30 Jul 2024 00:14:09 +0000 Subject: [PATCH 5/8] Automatic changelog update --- Resources/Changelog/ChangelogWhite.yml | 64 ++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index 45eb8283da..810a560b2b 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -6996,3 +6996,67 @@ id: 426 time: '2024-07-29T12:33:46.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/511 +- author: Spatison + changes: + - message: "\u0411\u043E\u0442\u0438\u043D\u043A\u0438 \u043A\u043B\u043E\u0443\u043D\ + \u0430 \u0441\u043D\u043E\u0432\u0430 \u0440\u0430\u0431\u043E\u0442\u0430\u044E\ + \u0442" + type: Fix + - message: "\u0421\u0432\u0435\u0442\u043E\u0432\u043E\u0435 \u043A\u043E\u043F\u044C\ + \u0435 \u0442\u0435\u043F\u0435\u0440\u044C \u0438\u0441\u0447\u0435\u0437\u0430\ + \u0435\u0442 \u0435\u0441\u043B\u0438 \u0435\u0433\u043E \u043F\u0435\u0440\u0435\ + \u0434\u0430\u0442\u044C" + type: Fix + id: 427 + time: '2024-07-30T00:13:05.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/513 +- author: Aviu + changes: + - message: "\u041F\u0435\u0440\u0435\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u043E\ + \ \u0437\u0430\u043A\u043B\u0438\u043D\u0430\u043D\u0438\u0435 \u043A\u0440\u043E\ + \u0432\u0430\u0432\u044B\u0445 \u043E\u0431\u0440\u044F\u0434\u043E\u0432 \u043A\ + \u0443\u043B\u044C\u0442\u0430. \u0422\u0435\u043F\u0435\u0440\u044C \u043E\u043D\ + \u043E \u0434\u0430\u0451\u0442 \u0430\u0443\u0440\u0443, \u043A\u043E\u0442\ + \u043E\u0440\u043E\u0439 \u043D\u0430\u0434\u043E \u043A\u043B\u0438\u043A\u0430\ + \u0442\u044C \u043D\u0430 \u043A\u0440\u043E\u0432\u044C, \u0447\u0442\u043E\ + \u0431\u044B \u043F\u043E\u0433\u043B\u043E\u0442\u0438\u0442\u044C \u0435\u0451\ + . \u041F\u0440\u0438 \u043F\u043E\u0433\u043B\u043E\u0449\u0435\u043D\u0438\u0438\ + \ \u043E\u043D\u043E \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043B\ + \u0435\u0447\u0438\u0442, \u0442\u0435\u043F\u0435\u0440\u044C \u043D\u0443\u0436\ + \u043D\u043E \u0443\u0434\u0430\u0440\u0438\u0442\u044C \u0430\u0443\u0440\u043E\ + \u0439 \u043A\u0443\u043B\u044C\u0442\u0438\u0441\u0442\u0430 \u0438\u043B\u0438\ + \ \u043A\u043E\u043D\u0441\u0442\u0440\u0443\u043A\u0442\u0430 \u0434\u043B\u044F\ + \ \u043B\u0435\u0447\u0435\u043D\u0438\u044F, 1 \u0445\u043F \u0437\u0430 2\ + \ \u0432\u044B\u0441\u043E\u0441\u0430\u043D\u043D\u043E\u0439 \u043A\u0440\u043E\ + \u0432\u0438. \u0423\u0431\u0440\u0430\u043D\u044B \u043E\u0431\u0440\u044F\u0434\ + \u044B \u0438\u0437 \u0432\u0435\u0440\u0431\u0430, \u0442\u0435\u043F\u0435\ + \u0440\u044C \u043D\u0443\u0436\u043D\u043E \u0430\u043A\u0442\u0438\u0432\u0438\ + \u0440\u043E\u0432\u0430\u0442\u044C \u0430\u0443\u0440\u0443 \u0432 \u0440\u0443\ + \u043A\u0430\u0445, \u0447\u0442\u043E\u0431\u044B \u0432\u044B\u0431\u0440\u0430\ + \u0442\u044C \u043A\u043E\u043F\u044C\u0451 \u0438\u043B\u0438 \u0437\u0430\u043B\ + \u043F." + type: Add + - message: "\u0412\u0441\u0435 \u043A\u043E\u043D\u0441\u0442\u0440\u0443\u043A\u0442\ + \u044B \u043D\u0430\u0443\u0447\u0438\u043B\u0438\u0441\u044C \u0442\u0430\u0441\ + \u043A\u0430\u0442\u044C." + type: Tweak + - message: "\u0414\u0436\u0430\u0433\u0433\u0435\u0440\u043D\u0430\u0443\u0442 \u0438\ + \ \u0440\u0435\u043C\u0435\u0441\u043B\u0435\u043D\u043D\u0438\u043A \u0442\u0435\ + \u043F\u0435\u0440\u044C \u043D\u0435\u043C\u043D\u043E\u0433\u043E \u0431\u044B\ + \u0441\u0442\u0440\u0435\u0435." + type: Tweak + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043F\u0440\u0438 \u043F\u043E\ + \u044F\u0432\u043B\u0435\u043D\u0438\u0438 \u043A\u043E\u043D\u0441\u0442\u0440\ + \u0443\u043A\u0442\u0430 \u0432\u0441\u0435 \u0435\u0433\u043E \u0441\u043F\u043E\ + \u0441\u043E\u0431\u043D\u043E\u0441\u0442\u0438 \u0438\u0437\u043D\u0430\u0447\ + \u0430\u043B\u044C\u043D\u043E \u0432 \u043A\u0434." + type: Tweak + - message: "\u0421 \u0441\u043E\u043A\u0440\u044B\u0442\u043E\u0439 \u0440\u0443\ + \u043D\u043E\u0439 \u043C\u043E\u0433\u0443\u0449\u0435\u0441\u0442\u0432\u0430\ + \ \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\u043B\u044C\u0437\u044F\ + \ \u0432\u0437\u0430\u0438\u043C\u043E\u0434\u0435\u0439\u0441\u0442\u0432\u043E\ + \u0432\u0430\u0442\u044C." + type: Tweak + id: 428 + time: '2024-07-30T00:12:49.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/514 From 2b5838657d81a510f01f11959ec2bb39fe0cbd72 Mon Sep 17 00:00:00 2001 From: Aviu00 <93730715+Aviu00@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:31:34 +0000 Subject: [PATCH 6/8] Blood and more (#516) * - tweak: Teleport only works on cultists. * - add: Better twisted construction. * - tweak: Free engivend. --- .../Cult/Runes/Systems/CultSystem.Actions.cs | 82 +++++++++++++----- .../_White/Cult/Actions/CultActions.cs | 17 ++++ .../_White/Cult/Actions/CultEvents.cs | 30 +++++++ .../_White/Cult/Actions/ShacklesEvent.cs | 9 -- .../Locale/ru-RU/_white/cult/abilities.ftl | 4 +- Resources/Prototypes/Entities/Effects/rcd.yml | 18 ++-- .../Structures/Machines/vending_machines.yml | 1 + .../_White/Entities/Cult/Effects/effects.yml | 10 +++ .../Effects/rcd.rsi/construct_red.png | Bin 0 -> 5292 bytes Resources/Textures/Effects/rcd.rsi/meta.json | 69 +++++++++++++-- 10 files changed, 195 insertions(+), 45 deletions(-) create mode 100644 Content.Shared/_White/Cult/Actions/CultEvents.cs delete mode 100644 Content.Shared/_White/Cult/Actions/ShacklesEvent.cs create mode 100644 Resources/Textures/Effects/rcd.rsi/construct_red.png diff --git a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs index f1c700316b..b6c5b52081 100644 --- a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs +++ b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Actions.cs @@ -8,14 +8,9 @@ using Content.Server._White.Cult.UI; using Content.Server._White.Wizard.Magic; using Content.Server.Chat.Systems; using Content.Shared._White.Chaplain; -using Content.Shared.Chemistry.Components; -using Content.Shared.Damage; -using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; -using Content.Shared.Fluids.Components; using Content.Shared.Inventory; using Content.Shared.Stacks; -using Content.Shared.StatusEffect; using Content.Shared.Stunnable; using Content.Shared._White.Cult.Actions; using Content.Shared._White.Cult.Components; @@ -25,8 +20,8 @@ using Content.Shared.Actions; using Content.Shared.Cuffs; using Content.Shared.Cuffs.Components; using Content.Shared.DoAfter; +using Content.Shared.Doors.Components; using Content.Shared.Maps; -using Content.Shared.Mindshield.Components; using Content.Shared.Popups; using Robust.Server.GameObjects; using Robust.Shared.Audio; @@ -72,6 +67,21 @@ public partial class CultSystem SubscribeLocalEvent(OnStun); SubscribeLocalEvent(OnActionRemoved); SubscribeLocalEvent(OnShackles); + SubscribeLocalEvent(OnTwistedConstruction); + } + + private void OnTwistedConstruction(Entity ent, ref TwistedConstructionEvent args) + { + if (args.Cancelled) + QueueDel(GetEntity(args.Effect)); + + if (args.Handled || args.Cancelled) + return; + + args.Handled = true; + + Del(args.Target); + Spawn(args.RunicDoor, GetCoordinates(args.Location)); } private void OnShackles(Entity ent, ref ShacklesEvent args) @@ -115,22 +125,14 @@ public partial class CultSystem !TryComp(uid, out var actor)) return; - if (_holyWeapon.IsHoldingHolyWeapon(args.Target)) + if (!HasComp(args.Target)) { - _popupSystem.PopupEntity(Loc.GetString("cult-magic-holy"), args.Performer, args.Performer, + _popupSystem.PopupEntity("Цель должна быть культистом.", args.Performer, args.Performer, PopupType.MediumCaution); return; } - if (!HasComp(args.Target) && !HasComp(args.Target) && - _actionBlocker.CanInteract(args.Target, null)) - { - _popupSystem.PopupEntity("Цель должна быть культистом, быть скованной или парализованной.", args.Performer, - args.Performer, PopupType.MediumCaution); - return; - } - - _bloodstreamSystem.TryModifyBloodLevel(uid, -5, bloodstream, createPuddle: false); + _bloodstreamSystem.TryModifyBloodLevel(uid, -7, bloodstream, createPuddle: false); var eui = new CultTeleportSpellEui(args.Performer, args.Target); _euiManager.OpenEui(eui, actor.PlayerSession); @@ -367,13 +369,47 @@ public partial class CultSystem if (!TryComp(args.Target, out CuffableComponent? cuffs) || cuffs.Container.ContainedEntities.Count > 0) return; - _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Performer, TimeSpan.FromSeconds(2), - new ShacklesEvent(), args.Performer, args.Target) + var doAfterArgs = new DoAfterArgs(EntityManager, args.Performer, TimeSpan.FromSeconds(2), new ShacklesEvent(), + args.Performer, args.Target) { BreakOnMove = true, BreakOnDamage = true - }); + }; + if (!_doAfterSystem.TryStartDoAfter(doAfterArgs)) + return; + + Speak(args); + args.Handled = true; + } + + private void ConvertDoor(EntityUid uid, EntityUid target, BloodstreamComponent bloodstream, + CultTwistedConstructionActionEvent args) + { + var meta = MetaData(target); + if (meta.EntityPrototype?.ID == args.RunicDoor.Id) + return; + + var xform = Transform(target); + if (!xform.Anchored) + return; + + var effect = Spawn(args.Effect, xform.Coordinates); + var ev = new TwistedConstructionEvent(GetNetEntity(effect), args.RunicDoor, GetNetCoordinates(xform.Coordinates)); + var doAfterArgs = new DoAfterArgs(EntityManager, uid, args.Delay, ev, uid, target) + { + BreakOnDamage = true, + BreakOnMove = true, + }; + + if (!_doAfterSystem.TryStartDoAfter(doAfterArgs)) + { + QueueDel(effect); + return; + } + + _audio.PlayPvs(args.Sound, xform.Coordinates); + _bloodstreamSystem.TryModifyBloodLevel(uid, -12, bloodstream, createPuddle: false); Speak(args); args.Handled = true; } @@ -389,6 +425,12 @@ public partial class CultSystem if (!TryComp(args.Performer, out var bloodstreamComponent)) return; + if (HasComp(args.Target)) + { + ConvertDoor(uid, args.Target, bloodstreamComponent, args); + return; + } + if (!_entityManager.TryGetComponent(args.Target, out var stack)) return; diff --git a/Content.Shared/_White/Cult/Actions/CultActions.cs b/Content.Shared/_White/Cult/Actions/CultActions.cs index eedcf82029..87feaf9872 100644 --- a/Content.Shared/_White/Cult/Actions/CultActions.cs +++ b/Content.Shared/_White/Cult/Actions/CultActions.cs @@ -1,5 +1,7 @@ using Content.Shared.Actions; using Content.Shared.Magic; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; namespace Content.Shared._White.Cult.Actions; @@ -7,6 +9,21 @@ public sealed partial class CultTwistedConstructionActionEvent : EntityTargetAct { [DataField("speech")] public string? Speech { get; private set; } + + [DataField] + public EntProtoId RunicDoor = "AirlockGlassCult"; + + [DataField] + public EntProtoId Effect = "EffectConstructRed"; + + [DataField] + public TimeSpan Delay = TimeSpan.FromSeconds(4); + + [DataField] + public SoundSpecifier? Sound = new SoundPathSpecifier("/Audio/Machines/airlock_creaking.ogg") + { + Params = AudioParams.Default.WithVolume(-3f), + }; } public sealed partial class CultSummonDaggerActionEvent : InstantActionEvent, ISpeakSpell diff --git a/Content.Shared/_White/Cult/Actions/CultEvents.cs b/Content.Shared/_White/Cult/Actions/CultEvents.cs new file mode 100644 index 0000000000..5f584db374 --- /dev/null +++ b/Content.Shared/_White/Cult/Actions/CultEvents.cs @@ -0,0 +1,30 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._White.Cult.Actions; + +[Serializable, NetSerializable] +public sealed partial class ShacklesEvent : SimpleDoAfterEvent +{ +} + +[Serializable, NetSerializable] +public sealed partial class TwistedConstructionEvent : DoAfterEvent +{ + public NetEntity Effect { get; private set; } + + public EntProtoId RunicDoor { get; private set; } + + public NetCoordinates Location { get; private set; } + + public TwistedConstructionEvent(NetEntity effect, EntProtoId runicDoor, NetCoordinates location) + { + Effect = effect; + RunicDoor = runicDoor; + Location = location; + } + + public override DoAfterEvent Clone() => this; +} diff --git a/Content.Shared/_White/Cult/Actions/ShacklesEvent.cs b/Content.Shared/_White/Cult/Actions/ShacklesEvent.cs deleted file mode 100644 index 6c27ce1aab..0000000000 --- a/Content.Shared/_White/Cult/Actions/ShacklesEvent.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Content.Shared.DoAfter; -using Robust.Shared.Serialization; - -namespace Content.Shared._White.Cult.Actions; - -[Serializable, NetSerializable] -public sealed partial class ShacklesEvent : SimpleDoAfterEvent -{ -} diff --git a/Resources/Locale/ru-RU/_white/cult/abilities.ftl b/Resources/Locale/ru-RU/_white/cult/abilities.ftl index 11f07a834f..f16bf673d6 100644 --- a/Resources/Locale/ru-RU/_white/cult/abilities.ftl +++ b/Resources/Locale/ru-RU/_white/cult/abilities.ftl @@ -20,10 +20,10 @@ juggernaut-create-wall-action-name = Щит juggernaut-create-wall-action-description = Это заклинание создает временное невидимое силовое поле для защиты себя и союзников от подавляющего огня. ent-ActionCultTwistedConstruction = Искажённое Воздействие - .desc = Зловещее заклинание, которое используют для превращения металла в рунический металл. + .desc = Зловещее заклинание, которое используют для превращения металла в рунический металл и обычных дверей в рунические. ent-ActionCultTeleport = Телепорт - .desc = Полезное заклинание, которое телепортирует цель на выбранную руну телепотрации. Цель должна являются культистом или быть парализованной. + .desc = Полезное заклинание, которое телепортирует культиста на выбранную руну телепотрации. ent-ActionCultSummonCombatEquipment = Призыв Боевого Снаряжения .desc = Важное заклинание, которое позволяет вам вызвать полный набор боевого снаряжения. diff --git a/Resources/Prototypes/Entities/Effects/rcd.yml b/Resources/Prototypes/Entities/Effects/rcd.yml index 902429818e..5016bfbff7 100644 --- a/Resources/Prototypes/Entities/Effects/rcd.yml +++ b/Resources/Prototypes/Entities/Effects/rcd.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity id: EffectRCDBase abstract: true noSpawn: true @@ -15,7 +15,7 @@ tags: - HideContextMenu - type: AnimationPlayer - + - type: entity parent: EffectRCDBase id: EffectRCDDeconstructPreview @@ -23,7 +23,7 @@ components: - type: Sprite state: deconstructPreview - + - type: entity parent: EffectRCDBase id: EffectRCDConstruct0 @@ -33,7 +33,7 @@ state: construct0 - type: TimedDespawn lifetime: 1.2 - + - type: entity parent: EffectRCDBase id: EffectRCDConstruct1 @@ -43,7 +43,7 @@ state: construct1 - type: TimedDespawn lifetime: 2.2 - + - type: entity parent: EffectRCDBase id: EffectRCDConstruct2 @@ -53,7 +53,7 @@ state: construct2 - type: TimedDespawn lifetime: 3.2 - + - type: entity parent: EffectRCDBase id: EffectRCDConstruct3 @@ -63,7 +63,7 @@ state: construct3 - type: TimedDespawn lifetime: 4.2 - + - type: entity parent: EffectRCDBase id: EffectRCDConstruct4 @@ -83,7 +83,7 @@ state: deconstruct2 - type: TimedDespawn lifetime: 3.2 - + - type: entity parent: EffectRCDBase id: EffectRCDDeconstruct4 @@ -112,4 +112,4 @@ - type: Sprite state: deconstruct8 - type: TimedDespawn - lifetime: 9.2 \ No newline at end of file + lifetime: 9.2 diff --git a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml index 02d466667d..5d9df35b40 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml @@ -766,6 +766,7 @@ normalState: normal-unshaded ejectState: eject-unshaded denyState: deny-unshaded + priceMultiplier: 0.0 - type: Sprite sprite: Structures/Machines/VendingMachines/engivend.rsi layers: diff --git a/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml b/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml index 5282cb3c7b..233306405e 100644 --- a/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml +++ b/Resources/Prototypes/_White/Entities/Cult/Effects/effects.yml @@ -118,3 +118,13 @@ duration: 0.5 - type: TimedDespawn lifetime: 0.5 + +- type: entity + parent: EffectRCDBase + id: EffectConstructRed + noSpawn: true + components: + - type: Sprite + state: construct_red + - type: TimedDespawn + lifetime: 5.2 diff --git a/Resources/Textures/Effects/rcd.rsi/construct_red.png b/Resources/Textures/Effects/rcd.rsi/construct_red.png new file mode 100644 index 0000000000000000000000000000000000000000..e21b111ab7505c8cfbbafb8ab519815d3fe8bb4f GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Effects/rcd.rsi/meta.json b/Resources/Textures/Effects/rcd.rsi/meta.json index c9e8320c60..43a62a27fa 100644 --- a/Resources/Textures/Effects/rcd.rsi/meta.json +++ b/Resources/Textures/Effects/rcd.rsi/meta.json @@ -25,7 +25,7 @@ 0.1 ] ] - }, + }, { "name": "construct1", "delays": [ @@ -64,7 +64,7 @@ 0.1 ] ] - }, + }, { "name": "construct2", "delays": [ @@ -201,7 +201,66 @@ 0.1 ] ] - }, + }, + { + "name": "construct_red", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, { "name": "deconstruct2", "delays": [ @@ -358,7 +417,7 @@ 0.1 ] ] - }, + }, { "name": "deconstruct8", "delays": [ @@ -451,7 +510,7 @@ 0.05, 0.05, 0.05, - 0.05 + 0.05 ] ] } From 58574b8a70981a68cc4038d9cf7c6f11f538c668 Mon Sep 17 00:00:00 2001 From: Aviu00 <93730715+Aviu00@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:32:26 +0000 Subject: [PATCH 7/8] Felinids fit in duffelbags. (#515) * - add: Felinids fit in duffelbags. * - add: This is better. * - add: Move to shared. --- .../Items/PseudoItem/PseudoItemSystem.cs | 7 + .../_White/Carrying/CarriableComponent.cs | 11 +- .../_White/Carrying/CarryingSystem.cs | 23 ++- .../Items/PseudoItem/PseudoItemSystem.cs | 168 ++++++++++++++++++ .../_White/Wizard/Magic/WizardSpellsSystem.cs | 4 + .../VirtualItem/SharedVirtualItemSystem.cs | 4 +- .../EntitySystems/SharedStorageSystem.cs | 10 +- .../Weapons/Ranged/Systems/SharedGunSystem.cs | 1 + .../Item/PseudoItem/PseudoItemComponent.cs | 22 +++ .../Item/PseudoItem/SharedPseudoItemSystem.cs | 36 ++++ .../Item/PseudoItemInsertDoAfterEvent.cs | 10 -- Resources/Locale/ru-RU/_white/white-shit.ftl | 6 +- .../_White/Mobs/Species/felinid.yml | 3 + 13 files changed, 284 insertions(+), 21 deletions(-) create mode 100644 Content.Client/_White/Items/PseudoItem/PseudoItemSystem.cs create mode 100644 Content.Server/_White/Items/PseudoItem/PseudoItemSystem.cs create mode 100644 Content.Shared/_White/Item/PseudoItem/PseudoItemComponent.cs create mode 100644 Content.Shared/_White/Item/PseudoItem/SharedPseudoItemSystem.cs delete mode 100644 Content.Shared/_White/Item/PseudoItemInsertDoAfterEvent.cs diff --git a/Content.Client/_White/Items/PseudoItem/PseudoItemSystem.cs b/Content.Client/_White/Items/PseudoItem/PseudoItemSystem.cs new file mode 100644 index 0000000000..d1b1d61d3b --- /dev/null +++ b/Content.Client/_White/Items/PseudoItem/PseudoItemSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared._White.Item.PseudoItem; + +namespace Content.Client._White.Items.PseudoItem; + +public sealed class PseudoItemSystem : SharedPseudoItemSystem +{ +} diff --git a/Content.Server/_White/Carrying/CarriableComponent.cs b/Content.Server/_White/Carrying/CarriableComponent.cs index 3ae2335d47..eb8902f281 100644 --- a/Content.Server/_White/Carrying/CarriableComponent.cs +++ b/Content.Server/_White/Carrying/CarriableComponent.cs @@ -5,6 +5,15 @@ namespace Content.Server._White.Carrying; [RegisterComponent] public sealed partial class CarriableComponent : Component { + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan DoAfterLength = TimeSpan.FromSeconds(4); + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float WalkModifier = 0.7f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SprintModifier = 0.7f; + /// /// Number of free hands required /// to carry the entity @@ -13,4 +22,4 @@ public sealed partial class CarriableComponent : Component public int FreeHandsRequired = 2; public CancellationTokenSource? CancelToken; -} \ No newline at end of file +} diff --git a/Content.Server/_White/Carrying/CarryingSystem.cs b/Content.Server/_White/Carrying/CarryingSystem.cs index 959e58f295..2b0220e90f 100644 --- a/Content.Server/_White/Carrying/CarryingSystem.cs +++ b/Content.Server/_White/Carrying/CarryingSystem.cs @@ -207,9 +207,9 @@ public sealed class CarryingSystem : EntitySystem args.Handled = true; } - private void StartCarryDoAfter(EntityUid carrier, EntityUid carried, CarriableComponent component) + public void StartCarryDoAfter(EntityUid carrier, EntityUid carried, CarriableComponent component) { - var length = TimeSpan.FromSeconds(6); // т.к. удалили систему разницы масс увеличу время с 3 до 6 + var length = component.DoAfterLength; // т.к. удалили систему разницы масс увеличу время с 3 до 6 if (length >= TimeSpan.FromSeconds(9)) { _popupSystem.PopupEntity(Loc.GetString("carry-too-heavy"), carried, carrier, @@ -230,7 +230,11 @@ public sealed class CarryingSystem : EntitySystem NeedHand = true }; - _doAfterSystem.TryStartDoAfter(args); + if(_doAfterSystem.TryStartDoAfter(args)) + { + _popupSystem.PopupEntity(Loc.GetString("carry-start", ("carrier", carrier)), carried, carried, + Shared.Popups.PopupType.SmallCaution); + } } private void Carry(EntityUid carrier, EntityUid carried) @@ -260,17 +264,22 @@ public sealed class CarryingSystem : EntitySystem _actionBlockerSystem.UpdateCanMove(carried); } - public void DropCarried(EntityUid carrier, EntityUid carried) + public void DropCarried(EntityUid carrier, + EntityUid carried, + bool attachToGridOrMap = true, + bool removeCanEscape = true) { RemComp(carrier); // get rid of this first so we don't recusrively fire that event RemComp(carrier); RemComp(carried); RemComp(carried); - RemComp(carried); + if (removeCanEscape) + RemComp(carried); _actionBlockerSystem.UpdateCanMove(carried); _virtualItemSystem.DeleteInHandsMatching(carrier, carried); - _transform.AttachToGridOrMap(carried); + if (attachToGridOrMap) + _transform.AttachToGridOrMap(carried); _movementSpeed.RefreshMovementSpeedModifiers(carrier); } @@ -302,4 +311,4 @@ public sealed class CarryingSystem : EntitySystem return true; } -} \ No newline at end of file +} diff --git a/Content.Server/_White/Items/PseudoItem/PseudoItemSystem.cs b/Content.Server/_White/Items/PseudoItem/PseudoItemSystem.cs new file mode 100644 index 0000000000..b75ca9f652 --- /dev/null +++ b/Content.Server/_White/Items/PseudoItem/PseudoItemSystem.cs @@ -0,0 +1,168 @@ +using Content.Server._White.Carrying; +using Content.Shared.Verbs; +using Content.Shared.Item; +using Content.Shared.Hands; +using Content.Server.Storage.EntitySystems; +using Content.Server.Item; +using Content.Server.Popups; +using Content.Server.Resist; +using Content.Shared._White.Item.PseudoItem; +using Content.Shared.Resist; +using Content.Shared.Storage; +using Robust.Server.GameObjects; +using Robust.Shared.Containers; + +namespace Content.Server._White.Items.PseudoItem; + +public sealed class PseudoItemSystem : SharedPseudoItemSystem +{ + [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly StorageSystem _storageSystem = default!; + [Dependency] private readonly ItemSystem _itemSystem = default!; + [Dependency] private readonly CarryingSystem _carrying = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnEntRemoved); + SubscribeLocalEvent(OnDropAttempt); + SubscribeLocalEvent(OnEscape); + SubscribeLocalEvent>(AddAltVerb); + SubscribeLocalEvent>(AddVerb); + SubscribeLocalEvent(OnInteract); + } + + private void OnInteract(Entity ent, ref PseudoItemInteractEvent args) + { + if (!TryComp(args.Used, out PseudoItemComponent? pseudoItem)) + return; + + if (!TryInsert(ent.Owner, args.Used, args.User, pseudoItem, ent.Comp)) + return; + + _carrying.DropCarried(args.User, args.Used, false, false); + } + + private void OnEscape(Entity ent, ref EscapeInventoryEvent args) + { + NoLongerInContainer(ent.Owner, ent.Comp); + } + + private void AddAltVerb(Entity ent, ref GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + var user = args.User; + + var (uid, comp) = ent; + + if (!TryComp(user, out PseudoItemComponent? pseudoItem) || pseudoItem.Active) + return; + + if (Transform(uid).ParentUid == user) + return; + + AlternativeVerb verb = new() + { + Act = () => + { + TryInsert(uid, user, user, pseudoItem, comp); + }, + Text = Loc.GetString("action-name-insert-self"), + }; + args.Verbs.Add(verb); + } + + private void AddVerb(Entity ent, ref GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + var user = args.User; + + var (uid, comp) = ent; + + if (!TryComp(user, out CarryingComponent? carrying)) + return; + + var carried = carrying.Carried; + + if (!TryComp(carried, out PseudoItemComponent? pseudoItem)) + return; + + Verb verb = new() + { + Act = () => + { + if (TryInsert(uid, carried, user, pseudoItem, comp)) + _carrying.DropCarried(user, carried, false, false); + }, + Text = Loc.GetString("action-name-insert-other"), + }; + args.Verbs.Add(verb); + } + + private void OnEntRemoved(EntityUid uid, PseudoItemComponent component, EntGotRemovedFromContainerMessage args) + { + NoLongerInContainer(uid, component); + } + + protected override void OnGettingPickedUp(Entity ent, GettingPickedUpAttemptEvent args) + { + base.OnGettingPickedUp(ent, args); + + if (args.User == args.Item) + return; + + if (!TryComp(ent, out CarriableComponent? carriable)) + _transform.AttachToGridOrMap(ent); + else if (_carrying.CanCarry(args.User, ent)) + _carrying.StartCarryDoAfter(args.User, ent, carriable); + } + + private void OnDropAttempt(EntityUid uid, PseudoItemComponent component, DropAttemptEvent args) + { + if (component.Active) + args.Cancel(); + } + + public bool TryInsert(EntityUid storageUid, + EntityUid toInsert, + EntityUid user, + PseudoItemComponent component, + StorageComponent? storage = null) + { + if (!Resolve(storageUid, ref storage)) + return false; + + var item = EnsureComp(toInsert); + _itemSystem.SetSize(toInsert, component.Size, item); + _itemSystem.SetShape(toInsert, component.Shape, item); + + Dirty(toInsert, component); + if (!_storageSystem.Insert(storageUid, toInsert, out _, user, storage)) + { + _popupSystem.PopupEntity(Loc.GetString("comp-storage-cant-insert"), user, user); + component.Active = false; + RemComp(toInsert); + return false; + } + + component.Active = true; + EnsureComp(toInsert); + return true; + } + + private void NoLongerInContainer(EntityUid uid, PseudoItemComponent component) + { + if (!component.Active) + return; + + RemCompDeferred(uid); + RemCompDeferred(uid); + component.Active = false; + Dirty(uid, component); + } +} diff --git a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs index a08f8af110..b69540d738 100644 --- a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs +++ b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs @@ -24,6 +24,7 @@ using Content.Shared._White.Antag; using Content.Shared._White.BetrayalDagger; using Content.Shared._White.Cult.Components; using Content.Shared._White.Events; +using Content.Shared._White.Item.PseudoItem; using Content.Shared._White.Wizard; using Content.Shared._White.Wizard.Magic; using Content.Shared.Actions; @@ -854,6 +855,9 @@ public sealed class WizardSpellsSystem : EntitySystem public bool CanCast(BaseActionEvent msg) { + if (TryComp(msg.Performer, out PseudoItemComponent? pseudoItem) && pseudoItem.Active) + return false; + return !msg.Handled && CheckRequirements(msg.Action, msg.Performer) && !_statusEffectsSystem.HasStatusEffect(msg.Performer, "Incorporeal"); } diff --git a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs index e45530e458..06bbba7d58 100644 --- a/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs +++ b/Content.Shared/Inventory/VirtualItem/SharedVirtualItemSystem.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Content.Shared._White.Item.PseudoItem; using Content.Shared.Hands; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; @@ -67,7 +68,8 @@ public abstract class SharedVirtualItemSystem : EntitySystem private void OnBeforeRangedInteract(Entity ent, ref BeforeRangedInteractEvent args) { // No interactions with a virtual item, please. - args.Handled = true; + if (!HasComp(ent.Comp.BlockingEntity)) + args.Handled = true; } #region Hands diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index 9d364dded0..2a9b335c9f 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -1,6 +1,7 @@ using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Shared._White.Item.PseudoItem; using Content.Shared.ActionBlocker; using Content.Shared.Containers.ItemSlots; using Content.Shared.Coordinates; @@ -10,6 +11,7 @@ using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Implants.Components; using Content.Shared.Interaction; +using Content.Shared.Inventory.VirtualItem; using Content.Shared.Item; using Content.Shared.Lock; using Content.Shared.Materials; @@ -223,6 +225,12 @@ public abstract class SharedStorageSystem : EntitySystem if (HasComp(uid)) return; + if (TryComp(args.Used, out var virtualItem)) // WD + { + RaiseLocalEvent(uid, new PseudoItemInteractEvent(virtualItem.BlockingEntity, args.User)); + return; + } + PlayerInsertHeldEntity(uid, args.User, storageComp); // Always handle it, even if insertion fails. // We don't want to trigger any AfterInteract logic here. @@ -1072,7 +1080,7 @@ public abstract class SharedStorageSystem : EntitySystem for (int i = 0; i < list.Count; i++) { var saved = list[i]; - + if (saved == location) { list.Remove(location); diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index c760b400ae..944aba9dd2 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using System.Numerics; using Content.Shared._White.Containers; using Content.Shared._White.Events; +using Content.Shared._White.Item.PseudoItem; using Content.Shared._White.WeaponModules; using Content.Shared.ActionBlocker; using Content.Shared.Actions; diff --git a/Content.Shared/_White/Item/PseudoItem/PseudoItemComponent.cs b/Content.Shared/_White/Item/PseudoItem/PseudoItemComponent.cs new file mode 100644 index 0000000000..1ecbab1576 --- /dev/null +++ b/Content.Shared/_White/Item/PseudoItem/PseudoItemComponent.cs @@ -0,0 +1,22 @@ +using Content.Shared.Item; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._White.Item.PseudoItem; + +/// +/// For entities that behave like an item under certain conditions, +/// but not under most conditions. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class PseudoItemComponent : Component +{ + [DataField] + public ProtoId Size = "Huge"; + + [DataField] + public List? Shape = new() {new Box2i(0, 0, 4, 4)}; + + [AutoNetworkedField] + public bool Active; +} diff --git a/Content.Shared/_White/Item/PseudoItem/SharedPseudoItemSystem.cs b/Content.Shared/_White/Item/PseudoItem/SharedPseudoItemSystem.cs new file mode 100644 index 0000000000..5c7a1c4779 --- /dev/null +++ b/Content.Shared/_White/Item/PseudoItem/SharedPseudoItemSystem.cs @@ -0,0 +1,36 @@ +using Content.Shared.Interaction.Events; +using Content.Shared.Item; + +namespace Content.Shared._White.Item.PseudoItem; + +public abstract class SharedPseudoItemSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGettingPickedUpAttempt); + SubscribeLocalEvent(OnAttackAttempt); + } + + private void OnAttackAttempt(Entity ent, ref AttackAttemptEvent args) + { + if (ent.Comp.Active) + args.Cancel(); + } + + private void OnGettingPickedUpAttempt(Entity ent, ref GettingPickedUpAttemptEvent args) + { + args.Cancel(); + OnGettingPickedUp(ent, args); + } + + protected virtual void OnGettingPickedUp(Entity ent, GettingPickedUpAttemptEvent args) {} +} + +public sealed class PseudoItemInteractEvent(EntityUid used, EntityUid user) + : EntityEventArgs +{ + public EntityUid Used { get; } = used; + public EntityUid User { get; } = user; +} diff --git a/Content.Shared/_White/Item/PseudoItemInsertDoAfterEvent.cs b/Content.Shared/_White/Item/PseudoItemInsertDoAfterEvent.cs deleted file mode 100644 index c7c76fbd08..0000000000 --- a/Content.Shared/_White/Item/PseudoItemInsertDoAfterEvent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Robust.Shared.Serialization; -using Content.Shared.DoAfter; - -namespace Content.Shared.Item.PseudoItem -{ - [Serializable, NetSerializable] - public sealed partial class PseudoItemInsertDoAfterEvent : SimpleDoAfterEvent - { - } -} diff --git a/Resources/Locale/ru-RU/_white/white-shit.ftl b/Resources/Locale/ru-RU/_white/white-shit.ftl index 354000de95..c333a1dc3c 100644 --- a/Resources/Locale/ru-RU/_white/white-shit.ftl +++ b/Resources/Locale/ru-RU/_white/white-shit.ftl @@ -1,4 +1,4 @@ -# Cult +# Cult ent-CultBola = магическая { ent-Bola } .desc = { ent-Bola.desc } @@ -8,3 +8,7 @@ ent-CultBola = магическая { ent-Bola } ent-EnergyBola = энергобола .desc = Соверешенное слияние технологии и справедливости для отлова преступников. + +action-name-insert-self = Залезть внутрь. +action-name-insert-other = Засунуть внутрь. +carry-start = { $carrier } пытается взять вас на руки! diff --git a/Resources/Prototypes/_White/Mobs/Species/felinid.yml b/Resources/Prototypes/_White/Mobs/Species/felinid.yml index 0cd7d91cc7..ba70e372f5 100644 --- a/Resources/Prototypes/_White/Mobs/Species/felinid.yml +++ b/Resources/Prototypes/_White/Mobs/Species/felinid.yml @@ -125,6 +125,9 @@ path: /Audio/Effects/hit_kick.ogg - type: Stamina - type: Perishable + - type: Carriable + doAfterLength: 2 + - type: PseudoItem - type: entity save: false From 49d6736a3ee84c54737268c4c9e1139e82312095 Mon Sep 17 00:00:00 2001 From: RavmorganButOnCocaine Date: Tue, 30 Jul 2024 16:33:30 +0000 Subject: [PATCH 8/8] Automatic changelog update --- Resources/Changelog/ChangelogWhite.yml | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index 810a560b2b..a6b8ab4fd2 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -7060,3 +7060,52 @@ id: 428 time: '2024-07-30T00:12:49.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/514 +- author: Aviu + changes: + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0438\u0441\u043A\u0430\u0436\u0435\ + \u043D\u043D\u044B\u043C \u0432\u043E\u0437\u0434\u0435\u0439\u0441\u0442\u0432\ + \u0438\u0435\u043C \u043C\u043E\u0436\u043D\u043E \u043F\u0440\u0435\u0432\u0440\ + \u0430\u0442\u0438\u0442\u044C \u0448\u043B\u044E\u0437 \u0432 \u0440\u0443\u043D\ + \u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0448\u043B\u044E\u0437." + type: Add + - message: "\u0417\u0430\u043A\u043B\u0438\u043D\u0430\u043D\u0438\u0435 \u0442\u0435\ + \u043B\u0435\u043F\u043E\u0440\u0442\u0430 \u0442\u0435\u043F\u0435\u0440\u044C\ + \ \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\ + \u043E \u043D\u0430 \u043A\u0443\u043B\u044C\u0442\u0438\u0441\u0442\u043E\u0432\ + ." + type: Tweak + - message: "\u0422\u043E\u0432\u0430\u0440\u044B \u0432 \u0438\u043D\u0436\u0435\ + \u043C\u0430\u0442\u0435 \u0442\u0435\u043F\u0435\u0440\u044C \u0431\u0435\u0441\ + \u043F\u043B\u0430\u0442\u043D\u044B\u0435." + type: Tweak + id: 429 + time: '2024-07-30T16:31:34.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/516 +- author: Aviu + changes: + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0435\u0441\u043B\u0438 \u0432\ + \u0437\u044F\u0442\u044C \u043D\u0430 \u0440\u0443\u043A\u0438 \u0444\u0435\u043B\ + \u0438\u043D\u0438\u0434\u0430, \u0435\u0433\u043E \u043C\u043E\u0436\u043D\u043E\ + \ \u0437\u0430\u0441\u0443\u043D\u0443\u0442\u044C \u0432 \u0432\u0435\u0449\ + \u043C\u0435\u0448\u043E\u043A." + type: Add + - message: "\u0424\u0435\u043B\u0438\u043D\u0438\u0434\u044B \u043C\u043E\u0433\u0443\ + \u0442 \u0437\u0430\u043B\u0430\u0437\u0438\u0442\u044C \u0432 \u0432\u0435\u0449\ + \u043C\u0435\u0448\u043A\u0438." + type: Add + - message: "\u041F\u0440\u0438 \u043F\u043E\u043F\u044B\u0442\u043A\u0435 \u0432\ + \u0437\u044F\u0442\u044C \u043D\u0430 \u0440\u0443\u043A\u0438 \u0432\u044B\u0441\ + \u043A\u0430\u043A\u0438\u0432\u0430\u0435\u0442 \u043F\u043E\u043F\u0430\u043F\ + \ \u0443 \u0446\u0435\u043B\u0438." + type: Add + - message: "\u0424\u0435\u043B\u0438\u043D\u0438\u0434\u044B \u0431\u0435\u0440\u0443\ + \u0442\u0441\u044F \u043D\u0430 \u0440\u0443\u043A\u0438 \u0431\u044B\u0441\u0442\ + \u0440\u0435\u0435." + type: Add + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0432\u0437\u044F\u0442\u0438\u0435\ + \ \u043D\u0430 \u0440\u0443\u043A\u0438 \u043F\u0440\u043E\u0438\u0441\u0445\ + \u043E\u0434\u0438\u0442 \u0431\u044B\u0441\u0442\u0440\u0435\u0435." + type: Tweak + id: 430 + time: '2024-07-30T16:32:26.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/515