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.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/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/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/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..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) @@ -106,15 +116,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) @@ -123,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); @@ -150,61 +144,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) @@ -429,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; } @@ -451,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; @@ -497,4 +477,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.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/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.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.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/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/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/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/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/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/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/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; +} + diff --git a/Resources/Audio/White/Cult/rites.ogg b/Resources/Audio/White/Cult/rites.ogg new file mode 100644 index 0000000000..486940a414 Binary files /dev/null and b/Resources/Audio/White/Cult/rites.ogg differ diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index 4c1d563e03..a6b8ab4fd2 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -6970,3 +6970,142 @@ 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 +- 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 +- 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 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/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/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/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/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 54d98f6fd1..db80d2a9fc 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -235,8 +235,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/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/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/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/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..233306405e 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 @@ -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/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/felinid.yml b/Resources/Prototypes/_White/Mobs/Species/felinid.yml index 6a8a01b0f4..4f8f8afb0a 100644 --- a/Resources/Prototypes/_White/Mobs/Species/felinid.yml +++ b/Resources/Prototypes/_White/Mobs/Species/felinid.yml @@ -143,6 +143,9 @@ min: 0.74 max: 0.85 starting: 0.8 + - type: Carriable + doAfterLength: 2 + - type: PseudoItem - type: entity save: false diff --git a/Resources/Prototypes/_White/Mobs/Species/harpy.yml b/Resources/Prototypes/_White/Mobs/Species/harpy.yml index 7e876e311d..55cdb97c7e 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/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 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 0000000000..e21b111ab7 Binary files /dev/null and b/Resources/Textures/Effects/rcd.rsi/construct_red.png differ 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 ] ] } 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 0000000000..e7df415ac8 Binary files /dev/null and b/Resources/Textures/White/Cult/Entities/rites.rsi/icon.png differ 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 0000000000..516c310227 Binary files /dev/null and b/Resources/Textures/White/Cult/Entities/rites.rsi/inhand-left.png differ 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 0000000000..a159a468a0 Binary files /dev/null and b/Resources/Textures/White/Cult/Entities/rites.rsi/inhand-right.png differ 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 19acec50cf..1c2504631f 100644 Binary files a/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-left.png and b/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-left.png differ diff --git a/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-right.png b/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-right.png index 12410f5e0b..1c05259688 100644 Binary files a/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-right.png and b/Resources/Textures/White/Cult/Entities/stun.rsi/inhand-right.png differ