diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index c1c0ae93ec..0d06e0b5b6 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -7,6 +7,7 @@ using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Shared.Enums; using System.Numerics; +using Content.Client.StatusIcon; using Content.Shared.StatusIcon.Components; using Content.Client.UserInterface.Systems; using Robust.Shared.Prototypes; @@ -24,6 +25,7 @@ public sealed class EntityHealthBarOverlay : Overlay private readonly MobStateSystem _mobStateSystem; private readonly MobThresholdSystem _mobThresholdSystem; private readonly ProgressColorSystem _progressColor; + private readonly StatusIconSystem _statusIcon; public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; public HashSet DamageContainers = new(); @@ -34,6 +36,7 @@ public sealed class EntityHealthBarOverlay : Overlay _mobStateSystem = _entManager.System(); _mobThresholdSystem = _entManager.System(); _progressColor = _entManager.System(); + _statusIcon = entManager.System(); } protected override void Draw(in OverlayDrawArgs args) @@ -70,6 +73,9 @@ public sealed class EntityHealthBarOverlay : Overlay continue; } + if (!_statusIcon.IsVisible(uid)) + continue; + // we use the status icon component bounds if specified otherwise use sprite var bounds = _entManager.GetComponentOrNull(uid)?.Bounds ?? spriteComponent.Bounds; var worldPos = _transform.GetWorldPosition(xform, xformQuery); diff --git a/Content.Client/Popups/PopupSystem.cs b/Content.Client/Popups/PopupSystem.cs index d9f47c0799..d24e2aff72 100644 --- a/Content.Client/Popups/PopupSystem.cs +++ b/Content.Client/Popups/PopupSystem.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Client.UserInterface.Systems.Chat; using Content.Shared.Examine; using Content.Shared.Chat; using Content.Shared.GameTicking; @@ -10,7 +11,6 @@ using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Shared.Configuration; using Robust.Shared.Map; -using Robust.Shared.Network; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Replays; @@ -31,7 +31,6 @@ namespace Content.Client.Popups [Dependency] private readonly IReplayRecordingManager _replayRecording = default!; [Dependency] private readonly ExamineSystemShared _examine = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; - [Dependency] private readonly IClientNetManager _clientNet = default!; public IReadOnlyList WorldLabels => _aliveWorldLabels; public IReadOnlyList CursorLabels => _aliveCursorLabels; @@ -94,6 +93,13 @@ namespace Content.Client.Popups _aliveWorldLabels.Add(label); + // START WhiteDream + if (!_isLogging) + return; + + if (!_examine.InRangeUnOccluded(_playerManager.LocalEntity!.Value, coordinates, 10)) + return; + var fontSizeDict = new Dictionary { { PopupType.Medium, "12" }, @@ -103,14 +109,16 @@ namespace Content.Client.Popups }; var fontsize = fontSizeDict.GetValueOrDefault(type, "10"); - var fontcolor = type is PopupType.LargeCaution or PopupType.MediumCaution or PopupType.SmallCaution ? "c62828" : "aeabc4"; + var fontcolor = type is PopupType.LargeCaution or PopupType.MediumCaution or PopupType.SmallCaution + ? "c62828" + : "aeabc4"; - if (_isLogging) - { - var wrappedMEssage = $"[font size={fontsize}][color=#{fontcolor}]{message}[/color][/font]"; - var chatMsg = new ChatMessage(ChatChannel.Emotes, message, wrappedMEssage, GetNetEntity(EntityUid.Invalid), null); - _clientNet.DispatchLocalNetMessage(new MsgChatMessage { Message = chatMsg }); - } + var wrappedMEssage = $"[font size={fontsize}][color=#{fontcolor}]{message}[/color][/font]"; + var chatMsg = new ChatMessage(ChatChannel.Emotes, message, wrappedMEssage, + GetNetEntity(EntityUid.Invalid), null); + _uiManager.GetUIController().ProcessChatMessage(chatMsg); + + // END WhiteDream } #region Abstract Method Implementations diff --git a/Content.Client/SSDIndicator/SSDIndicatorSystem.cs b/Content.Client/SSDIndicator/SSDIndicatorSystem.cs index 587450a2f6..5757f74213 100644 --- a/Content.Client/SSDIndicator/SSDIndicatorSystem.cs +++ b/Content.Client/SSDIndicator/SSDIndicatorSystem.cs @@ -1,4 +1,6 @@ using Content.Shared.CCVar; +using Content.Shared.Ghost; +using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Mobs.Systems; using Content.Shared.NPC; @@ -34,9 +36,18 @@ public sealed class SSDIndicatorSystem : EntitySystem !_mobState.IsDead(uid) && !HasComp(uid) && TryComp(uid, out var mindContainer) && - mindContainer.ShowExamineInfo) + mindContainer.ShowExamineInfo && + !IsAghosted(mindContainer)) // WD EDIT { args.StatusIcons.Add(_prototype.Index(component.Icon)); } } + + private bool IsAghosted(MindContainerComponent mindContainer) // WD + { + if (!TryComp(mindContainer.Mind, out MindComponent? mindComp)) + return false; + + return TryComp(mindComp.VisitingEntity, out GhostComponent? ghost) && ghost.CanGhostInteract; + } } diff --git a/Content.Client/StatusIcon/StatusIconOverlay.cs b/Content.Client/StatusIcon/StatusIconOverlay.cs index 471f0b8753..dc3f3c6bb3 100644 --- a/Content.Client/StatusIcon/StatusIconOverlay.cs +++ b/Content.Client/StatusIcon/StatusIconOverlay.cs @@ -59,6 +59,9 @@ public sealed class StatusIconOverlay : Overlay if (icons.Count == 0) continue; + if (!_statusIcon.IsVisible(uid)) + continue; + var worldMatrix = Matrix3.CreateTranslation(worldPos); Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld); Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty); diff --git a/Content.Client/StatusIcon/StatusIconSystem.cs b/Content.Client/StatusIcon/StatusIconSystem.cs index 980fd9f2a9..1eec788387 100644 --- a/Content.Client/StatusIcon/StatusIconSystem.cs +++ b/Content.Client/StatusIcon/StatusIconSystem.cs @@ -1,7 +1,10 @@ using Content.Shared.CCVar; +using Content.Shared.Ghost; using Content.Shared.StatusIcon; using Content.Shared.StatusIcon.Components; +using Robust.Client.GameObjects; using Robust.Client.Graphics; +using Robust.Client.Player; using Robust.Shared.Configuration; namespace Content.Client.StatusIcon; @@ -13,6 +16,10 @@ public sealed class StatusIconSystem : SharedStatusIconSystem { [Dependency] private readonly IConfigurationManager _configuration = default!; [Dependency] private readonly IOverlayManager _overlay = default!; + [Dependency] private readonly IPlayerManager _playerMan = default!; + + private EntityQuery _ghostQuery; + private EntityQuery _spriteQuery; private bool _globalEnabled; private bool _localEnabled; @@ -20,6 +27,9 @@ public sealed class StatusIconSystem : SharedStatusIconSystem /// public override void Initialize() { + _ghostQuery = GetEntityQuery(); + _spriteQuery = GetEntityQuery(); + Subs.CVar(_configuration, CCVars.LocalStatusIconsEnabled, OnLocalStatusIconChanged, true); Subs.CVar(_configuration, CCVars.GlobalStatusIconsEnabled, OnGlobalStatusIconChanged, true); } @@ -59,5 +69,29 @@ public sealed class StatusIconSystem : SharedStatusIconSystem RaiseLocalEvent(uid, ref ev); return ev.StatusIcons; } + + /// + /// For overlay to check if an entity can be seen. + /// + public bool IsVisible(EntityUid uid) + { + // ghosties can always see them + var viewer = _playerMan.LocalSession?.AttachedEntity; + if (_ghostQuery.HasComponent(viewer)) + return true; + + if (_spriteQuery.TryGetComponent(uid, out var sprite) && !sprite.Visible) + return false; + + var ev = new StatusIconVisibleEvent(true); + RaiseLocalEvent(uid, ref ev); + return ev.Visible; + } } +/// +/// Raised on an entity to check if it should draw hud icons. +/// Used to check invisibility etc inside the screen bounds. +/// +[ByRefEvent] +public record struct StatusIconVisibleEvent(bool Visible); diff --git a/Content.Client/Stealth/StealthSystem.cs b/Content.Client/Stealth/StealthSystem.cs index b60ffc2a40..3e5df79192 100644 --- a/Content.Client/Stealth/StealthSystem.cs +++ b/Content.Client/Stealth/StealthSystem.cs @@ -1,4 +1,5 @@ using Content.Client.Interactable.Components; +using Content.Client.StatusIcon; using Content.Shared.Stealth; using Content.Shared.Stealth.Components; using Robust.Client.GameObjects; @@ -18,9 +19,12 @@ public sealed class StealthSystem : SharedStealthSystem base.Initialize(); _shader = _protoMan.Index("Stealth").InstanceUnique(); + SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnShaderRender); + + SubscribeLocalEvent(OnStatusIconVisible); } public override void SetEnabled(EntityUid uid, bool value, StealthComponent? component = null) @@ -92,5 +96,12 @@ public sealed class StealthSystem : SharedStealthSystem visibility = MathF.Max(0, visibility); args.Sprite.Color = new Color(visibility, visibility, 1, 1); } + + private void OnStatusIconVisible(EntityUid uid, StealthComponent comp, ref StatusIconVisibleEvent args) + { + // no sechud seing invisible ninjas + if (comp.Enabled) + args.Visible = false; + } } diff --git a/Content.Client/Storage/Systems/EntityStorageSystem.cs b/Content.Client/Storage/Systems/EntityStorageSystem.cs index dd3f8d3860..05962b4e32 100644 --- a/Content.Client/Storage/Systems/EntityStorageSystem.cs +++ b/Content.Client/Storage/Systems/EntityStorageSystem.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Content.Client.StatusIcon; using Content.Client.Storage.Components; using Content.Shared.Destructible; using Content.Shared.Foldable; @@ -29,6 +30,8 @@ public sealed class EntityStorageSystem : SharedEntityStorageSystem SubscribeLocalEvent(OnGetState); SubscribeLocalEvent(OnHandleState); + + SubscribeLocalEvent(OnStatusIconVisible); } public override bool ResolveStorage(EntityUid uid, [NotNullWhen(true)] ref SharedEntityStorageComponent? component) @@ -40,4 +43,9 @@ public sealed class EntityStorageSystem : SharedEntityStorageSystem component = storage; return component != null; } + + private void OnStatusIconVisible(EntityUid uid, InsideEntityStorageComponent comp, ref StatusIconVisibleEvent args) + { + args.Visible = false; + } } diff --git a/Content.Server/Administration/Commands/AGhost.cs b/Content.Server/Administration/Commands/AGhost.cs index 4f0c49bd95..77f2c028ab 100644 --- a/Content.Server/Administration/Commands/AGhost.cs +++ b/Content.Server/Administration/Commands/AGhost.cs @@ -85,6 +85,8 @@ public sealed class AGhost : LocalizedCommands return; } + _entities.Dirty(mindId, mind); // WD + if (mind.VisitingEntity != default && _entities.TryGetComponent(mind.VisitingEntity, out var oldGhostComponent)) { mindSystem.UnVisit(mindId, mind); diff --git a/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs b/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs index 3123e251af..5135211fd0 100644 --- a/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs +++ b/Content.Server/Damage/Components/DamageOtherOnHitComponent.cs @@ -1,5 +1,6 @@ using Content.Server.Damage.Systems; using Content.Shared.Damage; +using Robust.Shared.Audio; namespace Content.Server.Damage.Components { @@ -15,5 +16,7 @@ namespace Content.Server.Damage.Components [ViewVariables(VVAccess.ReadWrite)] public DamageSpecifier Damage = default!; + [DataField, ViewVariables(VVAccess.ReadWrite)] // WD + public SoundSpecifier? Sound; } } diff --git a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs index 8d5f1687b9..406ad69a3b 100644 --- a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs +++ b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs @@ -11,6 +11,7 @@ using Content.Shared.Effects; using Content.Shared.Mobs.Components; using Content.Shared.Projectiles; using Content.Shared.Throwing; +using Content.Shared.Weapons.Melee; using Robust.Shared.Physics.Components; using Robust.Shared.Player; @@ -28,7 +29,8 @@ namespace Content.Server.Damage.Systems public override void Initialize() { - SubscribeLocalEvent(OnDoHit); + SubscribeLocalEvent(OnDoHit, + before: new[] {typeof(MeleeThrowOnHitSystem)}); // WD EDIT SubscribeLocalEvent(OnDamageExamine); } @@ -55,7 +57,7 @@ namespace Content.Server.Damage.Systems _color.RaiseEffect(Color.Red, new List() { args.Target }, Filter.Pvs(args.Target, entityManager: EntityManager)); } - _guns.PlayImpactSound(args.Target, dmg, null, false); + _guns.PlayImpactSound(args.Target, dmg, component.Sound, component.Sound != null); // WD EDIT if (TryComp(uid, out var body) && body.LinearVelocity.LengthSquared() > 0f) { var direction = body.LinearVelocity.Normalized(); diff --git a/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs b/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs index 2c4153514b..5ef0ce6407 100644 --- a/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs +++ b/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs @@ -3,15 +3,12 @@ using Content.Server._Miracle.GulagSystem; using Content.Server.Actions; using Content.Server.Antag; using Content.Server.Bible.Components; -using Content.Server.Chat.Managers; using Content.Server.GameTicking; using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; -using Content.Server.NPC.Systems; +using Content.Server.Objectives.Components; using Content.Server.Roles; -using Content.Server.Roles.Jobs; using Content.Server.RoundEnd; -using Content.Server.Shuttles.Components; using Content.Server.StationEvents.Components; using Content.Server.Storage.EntitySystems; using Content.Shared.Body.Systems; @@ -29,6 +26,7 @@ using Content.Shared._White; using Content.Shared._White.Cult.Components; using Content.Shared._White.Cult.Systems; using Content.Shared._White.Mood; +using Content.Shared.Cloning; using Content.Shared.Mind; using Content.Shared.NPC.Systems; using Robust.Server.Player; @@ -72,10 +70,16 @@ public sealed class CultRuleSystem : GameRuleSystem SubscribeLocalEvent(OnCultistComponentInit); SubscribeLocalEvent(OnCultistComponentRemoved); SubscribeLocalEvent(OnCultistsStateChanged); + SubscribeLocalEvent(OnClone); SubscribeLocalEvent(OnGetBriefing); } + private void OnClone(Entity ent, ref CloningEvent args) + { + RemoveObjectiveAndRole(ent); + } + protected override void Added(EntityUid uid, CultRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args) { base.Added(uid, component, gameRule, args); @@ -178,6 +182,21 @@ public sealed class CultRuleSystem : GameRuleSystem } } + public void RemoveObjectiveAndRole(EntityUid uid) + { + if (!_mindSystem.TryGetMind(uid, out var mindId, out var mind)) + return; + + var objectives = mind.Objectives.FindAll(HasComp); + foreach (var obj in objectives) + { + _mindSystem.TryRemoveObjective(mindId, mind, mind.Objectives.IndexOf(obj)); + } + + if (_roleSystem.MindHasRole(mindId)) + _roleSystem.MindRemoveRole(mindId); + } + private void OnCultistComponentRemoved(EntityUid uid, CultistComponent component, ComponentRemove args) { var query = QueryActiveRules(); diff --git a/Content.Server/_White/Cult/HolyWater/DeconvertCultist.cs b/Content.Server/_White/Cult/HolyWater/DeconvertCultist.cs index 8989d11435..4ceb407cd0 100644 --- a/Content.Server/_White/Cult/HolyWater/DeconvertCultist.cs +++ b/Content.Server/_White/Cult/HolyWater/DeconvertCultist.cs @@ -1,4 +1,5 @@ using System.Threading; +using Content.Server._White.Cult.GameRule; using Content.Server.Objectives.Components; using Content.Server.Popups; using Content.Server.Roles; @@ -8,6 +9,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Inventory; using Content.Shared._White.Cult.Components; using Content.Shared._White.Mood; +using Content.Shared.Jittering; using Content.Shared.Mind; using JetBrains.Annotations; using Robust.Server.Containers; @@ -40,6 +42,8 @@ public sealed partial class DeconvertCultist : ReagentEffect args.EntityManager.System() .TryParalyze(uid, TimeSpan.FromSeconds(component.HolyConvertTime + 5f), true); + args.EntityManager.System() + .DoJitter(uid, TimeSpan.FromSeconds(component.HolyConvertTime + 5f), true); var target = Identity.Name(uid, args.EntityManager); args.EntityManager.System() .PopupEntity(Loc.GetString("holy-water-started-converting", ("target", target)), uid); @@ -73,20 +77,8 @@ public sealed partial class DeconvertCultist : ReagentEffect entityManager.RemoveComponent(uid); entityManager.RemoveComponent(uid); - var mindSystem = entityManager.System(); - var roleSystem = entityManager.System(); - - if (!mindSystem.TryGetMind(uid, out var mindId, out var mind)) - return; - - var objectives = mind.Objectives.FindAll(entityManager.HasComponent); - foreach (var obj in objectives) - { - mindSystem.TryRemoveObjective(mindId, mind, mind.Objectives.IndexOf(obj)); - } - - if (roleSystem.MindHasRole(mindId)) - roleSystem.MindRemoveRole(mindId); + var cultRuleSystem = entityManager.System(); + cultRuleSystem.RemoveObjectiveAndRole(uid); entityManager.EventBus.RaiseLocalEvent(uid, new MoodRemoveEffectEvent("CultFocused")); } diff --git a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs index 6c0dec15af..3e0ac10fa8 100644 --- a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs +++ b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs @@ -159,6 +159,7 @@ public sealed class WizardSpellsSystem : EntitySystem _handsSystem.TryForcePickupAnyHand(msg.Performer, recallComponent.Item.Value); msg.Handled = true; + Speak(msg); return; } diff --git a/Content.Server/_White/Wizard/WizardRuleComponent.cs b/Content.Server/_White/Wizard/WizardRuleComponent.cs index 271dffcbca..3bdda39bbd 100644 --- a/Content.Server/_White/Wizard/WizardRuleComponent.cs +++ b/Content.Server/_White/Wizard/WizardRuleComponent.cs @@ -50,7 +50,7 @@ public sealed partial class WizardRuleComponent : Component [DataField] public ProtoId Faction = "Wizard"; - public RoundEndBehavior RoundEndBehavior = RoundEndBehavior.Nothing; + public RoundEndBehavior RoundEndBehavior = RoundEndBehavior.ShuttleCall; [DataField] public string RoundEndTextSender = "comms-console-announcement-title-centcom"; diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index 059e6c6c79..1e22ed8068 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -545,7 +545,7 @@ namespace Content.Shared.Cuffs BreakOnWeightlessMove = false, BreakOnDamage = true, NeedHand = true, - DistanceThreshold = 0.3f + DistanceThreshold = 1f // shorter than default but still feels good }; if (!_doAfter.TryStartDoAfter(doAfterEventArgs)) @@ -650,7 +650,7 @@ namespace Content.Shared.Cuffs BreakOnDamage = true, NeedHand = true, RequireCanInteract = false, // Trust in UncuffAttemptEvent - DistanceThreshold = 0.3f + DistanceThreshold = 1f // shorter than default but still feels good }; if (!_doAfter.TryStartDoAfter(doAfterEventArgs)) diff --git a/Content.Shared/Ninja/Systems/DashAbilitySystem.cs b/Content.Shared/Ninja/Systems/DashAbilitySystem.cs index 011b6f9f66..50319ae651 100644 --- a/Content.Shared/Ninja/Systems/DashAbilitySystem.cs +++ b/Content.Shared/Ninja/Systems/DashAbilitySystem.cs @@ -5,8 +5,8 @@ using Content.Shared.Charges.Systems; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Ninja.Components; -using Content.Shared.Physics; using Content.Shared.Popups; +using Content.Shared.Examine; using Robust.Shared.Audio.Systems; using Robust.Shared.Timing; @@ -21,7 +21,7 @@ public sealed class DashAbilitySystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedChargesSystem _charges = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; - [Dependency] private readonly SharedInteractionSystem _interaction = default!; + [Dependency] private readonly ExamineSystemShared _examine = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly ActionContainerSystem _actionContainer = default!; @@ -81,11 +81,10 @@ public sealed class DashAbilitySystem : EntitySystem _popup.PopupClient(Loc.GetString("dash-ability-no-charges", ("item", uid)), user, user); return; } - - var origin = Transform(user).MapPosition; + var origin = _transform.GetMapCoordinates(user); var target = args.Target.ToMap(EntityManager, _transform); // prevent collision with the user duh - if (!_interaction.InRangeUnobstructed(origin, target, 0f, CollisionGroup.Opaque, uid => uid == user)) + if (!_examine.InRangeUnOccluded(origin, target, SharedInteractionSystem.MaxRaycastRange, null)) { // can only dash if the destination is visible on screen _popup.PopupClient(Loc.GetString("dash-ability-cant-see", ("item", uid)), user, user); diff --git a/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs b/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs index b4ac2cde75..d81ad754d1 100644 --- a/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs +++ b/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs @@ -59,7 +59,7 @@ public sealed class StepTriggerSystem : EntitySystem if (component.Blacklist != null && TryComp(transform.GridUid, out var grid)) { - var positon = _map.LocalToTile(uid, grid, transform.Coordinates); + var positon = _map.LocalToTile(transform.GridUid.Value, grid, transform.Coordinates); var anch = _map.GetAnchoredEntitiesEnumerator(uid, grid, positon); while (anch.MoveNext(out var ent)) diff --git a/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs b/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs index 82ffc5e51f..43425ad798 100644 --- a/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs +++ b/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs @@ -47,6 +47,16 @@ public sealed partial class MeleeThrowOnHitComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] [AutoNetworkedField] public bool Enabled = true; + + // WD START + [DataField, ViewVariables(VVAccess.ReadWrite)] + [AutoNetworkedField] + public float StunTime; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + [AutoNetworkedField] + public bool ThrowOnThrowHit; + // WD END } /// diff --git a/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs b/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs index 7886356233..8b76d14a02 100644 --- a/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs +++ b/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs @@ -1,5 +1,7 @@ using System.Numerics; using Content.Shared.Construction.Components; +using Content.Shared.Stunnable; +using Content.Shared.Throwing; using Content.Shared.Weapons.Melee.Components; using Content.Shared.Weapons.Melee.Events; using Robust.Shared.Physics; @@ -18,22 +20,67 @@ public sealed class MeleeThrowOnHitSystem : EntitySystem [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly SharedStunSystem _stun = default!; // WD + [Dependency] private readonly ThrownItemSystem _thrownItem = default!; // WD /// public override void Initialize() { + SubscribeLocalEvent(OnDoHit); // WD + SubscribeLocalEvent(OnMeleeHit); SubscribeLocalEvent(OnThrownStartup); SubscribeLocalEvent(OnThrownShutdown); SubscribeLocalEvent(OnStartCollide); } + private void OnDoHit(Entity ent, ref ThrowDoHitEvent args) // WD + { + if (!ent.Comp.ThrowOnThrowHit) + return; + + if (!CanThrowOnHit(ent, args.Target)) + return; + + if (!TryComp(ent, out PhysicsComponent? physics)) + return; + + var velocity = physics.LinearVelocity.Normalized() * ent.Comp.Speed; + + RemComp(args.Target); + var thrownComp = new MeleeThrownComponent + { + Velocity = velocity, + Lifetime = ent.Comp.Lifetime, + MinLifetime = ent.Comp.MinLifetime + }; + AddComp(args.Target, thrownComp); + if (ent.Comp.StunTime != 0f) + _stun.TryParalyze(args.Target, TimeSpan.FromSeconds(ent.Comp.StunTime), true); + + _thrownItem.LandComponent(ent, args.Component, physics, false); + _physics.SetLinearVelocity(ent, Vector2.Zero); + } + private void OnMeleeHit(Entity ent, ref MeleeHitEvent args) { var (_, comp) = ent; if (!args.IsHit) return; + // WD START + var stunTime = comp.StunTime; + var speed = comp.Speed; + var lifetime = comp.Lifetime; + + if (args.Direction != null) // Heavy attack + { + stunTime = 0f; + speed *= 0.5f; + lifetime *= 0.5f; + } + // WD END + var mapPos = _transform.GetMapCoordinates(args.User).Position; foreach (var hit in args.HitEntities) { @@ -55,11 +102,13 @@ public sealed class MeleeThrowOnHitSystem : EntitySystem RaiseLocalEvent(hit, ref ev); var thrownComp = new MeleeThrownComponent { - Velocity = angle.Normalized() * comp.Speed, - Lifetime = comp.Lifetime, + Velocity = angle.Normalized() * speed, // WD EDIT + Lifetime = lifetime, // WD EDIT MinLifetime = comp.MinLifetime }; AddComp(hit, thrownComp); + if (stunTime != 0f) + _stun.TryParalyze(hit, TimeSpan.FromSeconds(stunTime), true); } } diff --git a/Resources/Audio/White/Magic/Mjolnir/hit.ogg b/Resources/Audio/White/Magic/Mjolnir/hit.ogg new file mode 100644 index 0000000000..17abf06675 Binary files /dev/null and b/Resources/Audio/White/Magic/Mjolnir/hit.ogg differ diff --git a/Resources/Audio/White/Magic/Mjolnir/swing.ogg b/Resources/Audio/White/Magic/Mjolnir/swing.ogg new file mode 100644 index 0000000000..43a2ea9790 Binary files /dev/null and b/Resources/Audio/White/Magic/Mjolnir/swing.ogg differ diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index a4397d2086..b00b2d6fd6 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -4271,3 +4271,140 @@ id: 298 time: '2024-06-12T20:28:18.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/349 +- author: Aviu + changes: + - message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D \u043C\u044C\u0451\u043B\ + \u044C\u043D\u0438\u0440 \u0432 \u043A\u043D\u0438\u0433\u0443 \u0437\u0430\u043A\ + \u043B\u0438\u043D\u0430\u043D\u0438\u0439." + type: Add + id: 299 + time: '2024-06-13T23:56:59.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/350 +- author: Remuchi + changes: + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0432\u0441\u043F\u043B\u044B\u0432\ + \u0430\u044E\u0449\u0438\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\ + \u044F \u043D\u0435 \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u044E\u0442\ + \u0441\u044F \u0432 \u0447\u0430\u0442\u0435, \u0435\u0441\u043B\u0438 \u0438\ + \u0433\u0440\u043E\u043A \u0438\u0445 \u043D\u0435 \u0432\u0438\u0434\u0438\u0442" + type: Fix + id: 300 + time: '2024-06-14T11:47:15.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/354 +- author: Aviu + changes: + - message: "\u0423\u0431\u0440\u0430\u043D\u044B \u0431\u043E\u0442\u0438\u043D\u043A\ + \u0438 \u043A\u043E\u0441\u043C\u043E\u043D\u0438\u043D\u0434\u0437\u044F \u0441\ + \ \u0432\u0430\u0439\u0442\u0431\u043E\u043A\u0441\u0430." + type: Remove + id: 301 + time: '2024-06-14T14:01:37.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/353 +- author: Aviu + changes: + - message: "\u0411\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\u043B\u044C\u0437\u044F\ + \ \u0441\u0433\u043E\u0440\u0435\u0442\u044C, \u0441\u0442\u043E\u044F \u043D\ + \u0430 \u043C\u043E\u0441\u0442\u0438\u043A\u0435 \u043D\u0430\u0434 \u043B\u0430\ + \u0432\u043E\u0439." + type: Fix + - message: "\u0423\u0432\u0435\u043B\u0438\u0447\u0435\u043D\u0430 \u0434\u0430\u043B\ + \u044C\u043D\u043E\u0441\u0442\u044C \u043D\u0430\u0434\u0435\u0432\u0430\u043D\ + \u0438\u044F \u043D\u0430\u0440\u0443\u0447\u043D\u0438\u043A\u043E\u0432." + type: Tweak + id: 302 + time: '2024-06-14T14:01:02.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/356 +- author: Aviu + changes: + - message: "\u041A\u0443\u043B\u044C\u0442\u0438\u0441\u0442\u044B \u0442\u0435\u043F\ + \u0435\u0440\u044C \u0442\u0440\u044F\u0441\u0443\u0442\u0441\u044F \u043F\u0440\ + \u0438 \u0434\u0435\u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0430\u0446\u0438\ + \u0438." + type: Add + - message: "\u041F\u043E\u0441\u043B\u0435 \u043A\u043B\u043E\u043D\u0438\u0440\u043E\ + \u0432\u0430\u043D\u0438\u044F \u0443 \u043A\u0443\u043B\u044C\u0442\u0438\u0441\ + \u0442\u043E\u0432 \u043F\u0440\u043E\u043F\u0430\u0434\u0430\u0435\u0442 \u0446\ + \u0435\u043B\u044C, \u0440\u043E\u043B\u044C, \u0438 \u0438\u0445 \u043C\u043E\ + \u0436\u043D\u043E \u0441\u043D\u043E\u0432\u0430 \u0441\u043A\u043E\u043D\u0432\ + \u0435\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C." + type: Fix + - message: "\u0414\u0432\u0435\u0440\u044C \u043A\u0443\u043B\u044C\u0442\u0430\ + \ \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\u043B\u044C\u0437\u044F\ + \ \u0440\u0430\u0437\u043E\u0431\u0440\u0430\u0442\u044C \u0420\u0426\u0414." + type: Fix + - message: "\u0423\u043C\u0435\u043D\u044C\u0448\u0435\u043D \u0441\u0442\u0440\u0443\ + \u043A\u0442\u0443\u0440\u043D\u044B\u0439 \u0443\u0440\u043E\u043D \u0443 \u0447\ + \u0435\u043B\u044E\u0441\u0442\u0435\u0439 \u0436\u0438\u0437\u043D\u0438." + type: Tweak + - message: "\u0423\u043C\u0435\u043D\u044C\u0448\u0435\u043D\u043E \u043A\u043E\u043B\ + \u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0434\u0440\u043E\u0431\u0438\u043B\ + \u043E\u043A \u0438 \u043F\u043A\u0430 \u0432 \u0430\u0432\u0442\u043E\u043C\ + \u0430\u0442\u0435 \u0443\u0442\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\ + \u043E\u0432." + type: Tweak + - message: "\u0421\u0442\u044F\u0436\u043A\u0438 \u0442\u0435\u043F\u0435\u0440\u044C\ + \ \u043D\u0435 \u0441\u043D\u0438\u043C\u0430\u044E\u0442\u0441\u044F \u0437\ + \u0430 3 \u0441\u0435\u043A\u0443\u043D\u0434\u044B." + type: Tweak + - message: "\u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u043E \u043C\u0430\ + \u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u0445\u0440\u0430\ + \u043D\u0438\u043B\u0438\u0449\u0435 \u0440\u0435\u0430\u0433\u0435\u043D\u0442\ + \u043E\u0432 \u0432 \u043A\u043E\u043F\u044C\u044F\u0445 5 \u0435\u0434\u0438\ + \u043D\u0438\u0446." + type: Tweak + - message: "\u041A\u0440\u043E\u0432\u0430\u0432\u043E\u0435 \u043A\u043E\u043F\u044C\ + \u0451 \u043C\u043E\u0436\u043D\u043E \u043F\u043E\u0432\u0435\u0441\u0438\u0442\ + \u044C \u043D\u0430 \u0431\u0440\u043E\u043D\u044E, \u043A\u0430\u043A \u0438\ + \ \u043E\u0441\u0442\u0430\u043B\u044C\u043D\u044B\u0435 \u043A\u043E\u043F\u044C\ + \u044F." + type: Tweak + id: 303 + time: '2024-06-14T14:01:26.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/355 +- author: Aviu + changes: + - message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B \u043E\u043F\u0438\ + \u0441\u0430\u043D\u0438\u044F \u0432\u0441\u0435\u043C \u0437\u0430\u043A\u043B\ + \u0438\u043D\u0430\u043D\u0438\u044F\u043C \u043C\u0430\u0433\u0430." + type: Add + - message: "\u0420\u0435\u0436\u0438\u043C \u043C\u0430\u0433\u0430 \u0434\u043E\ + \u0431\u0430\u0432\u043B\u0435\u043D \u0432 \u0441\u0435\u043A\u0440\u0435\u0442\ + ." + type: Add + - message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0430 \u0431\u0440\u043E\ + \u043D\u044F \u043C\u0430\u0433\u0443\u0441\u0430 \u043D\u0430 \u0448\u0430\u0442\ + \u0442\u043B \u043C\u0430\u0433\u0430, \u043D\u043E \u0432 \u043D\u0435\u0439\ + \ \u043D\u0435\u043B\u044C\u0437\u044F \u043A\u0430\u0441\u0442\u043E\u0432\u0430\ + \u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0438\u043D\u0441\u0442\u0432\u043E\ + \ \u0437\u0430\u043A\u043B\u0438\u043D\u0430\u043D\u0438\u0439." + type: Add + id: 304 + time: '2024-06-15T00:47:50.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/352 +- author: Aviu + changes: + - message: "\u041D\u0438\u043D\u0434\u0437\u044E \u0432 \u0441\u0442\u0435\u043B\ + \u0441\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u043E\u043A\ + \u0430\u0437\u044B\u0432\u0430\u044E\u0442 \u0445\u0443\u0434\u044B." + type: Fix + - message: "\u041F\u0440\u0438 \u0430\u0433\u043E\u0441\u0442\u0435 \u0443 \u043F\ + \u0435\u0440\u0441\u043E\u043D\u0430\u0436\u0430 \u0431\u043E\u043B\u044C\u0448\ + \u0435 \u043D\u0435 \u043E\u0442\u043E\u0431\u0440\u0430\u0436\u0430\u0435\u0442\ + \u0441\u044F \u0421\u0421\u0414 \u0438\u043D\u0434\u0438\u043A\u0430\u0442\u043E\ + \u0440." + type: Fix + - message: "\u041D\u0438\u043D\u0434\u0437\u044F \u0432 \u0441\u0442\u0435\u043B\ + \u0441\u0435 \u0442\u0435\u043F\u0435\u0440\u044C \u043C\u0435\u043D\u0435\u0435\ + \ \u0437\u0430\u043C\u0435\u0442\u0435\u043D." + type: Tweak + id: 305 + time: '2024-06-15T13:11:59.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/357 +- author: ThereDrD + changes: + - message: "\u0420\u0435\u0441\u043F\u0440\u0430\u0439\u0442 \u0441\u0432\u0438\u0442\ + \u043A\u0430" + type: Add + id: 306 + time: '2024-06-15T13:37:17.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/358 diff --git a/Resources/Locale/ru-RU/_white/wizard/spellbook.ftl b/Resources/Locale/ru-RU/_white/wizard/spellbook.ftl new file mode 100644 index 0000000000..1d3f6e353e --- /dev/null +++ b/Resources/Locale/ru-RU/_white/wizard/spellbook.ftl @@ -0,0 +1,53 @@ +spellbook-fireball-name = { ent-ActionFireballSpell } +spellbook-fireball-desc = { ent-ActionFireballSpell.desc } + +spellbook-forcewall-name = { ent-ActionForcewallSpell } +spellbook-forcewall-desc = { ent-ActionForcewallSpell.desc } + +spellbook-knock-name = { ent-ActionKnock } +spellbook-knock-desc = { ent-ActionKnock.desc } + +spellbook-arc-name = { ent-ActionElectricArcSpell } +spellbook-arc-desc = { ent-ActionElectricArcSpell.desc } + +spellbook-force-name = { ent-ActionForceSpell } +spellbook-force-desc = { ent-ActionForceSpell.desc } + +spellbook-cards-name = { ent-ActionCardSpell } +spellbook-cards-desc = { ent-ActionCardSpell.desc } + +spellbook-blink-name = { ent-ActionBlinkSpell } +spellbook-blink-desc = { ent-ActionBlinkSpell.desc } + +spellbook-jaunt-name = { ent-ActionEtherealJauntSpell } +spellbook-jaunt-desc = { ent-ActionEtherealJauntSpell.desc } + +spellbook-emp-name = { ent-ActionEmpSpell } +spellbook-emp-desc = { ent-ActionEmpSpell.desc } + +spellbook-cluwne-name = { ent-ActionCluwneCurseSpell } +spellbook-cluwne-desc = { ent-ActionCluwneCurseSpell.desc } + +spellbook-clown-name = { ent-ActionBananaTouchSpell } +spellbook-clown-desc = { ent-ActionBananaTouchSpell.desc } + +spellbook-mime-name = { ent-ActionMimeTouchSpell } +spellbook-mime-desc = { ent-ActionMimeTouchSpell.desc } + +spellbook-recall-name = { ent-ActionInstantRecallSpell } +spellbook-recall-desc = { ent-ActionInstantRecallSpell.desc } + +spellbook-smite-name = { ent-ActionSmite } +spellbook-smite-desc = { ent-ActionSmite.desc } + +spellbook-hardsuit-name = Скафандр волшебника +spellbook-hardsuit-desc = Украшенный магическими драгоценными камнями скафандр, функционирующий так же, как и обычная мантия волшебника, но в то же время является пригодным для использования в космосе и бронированным. Небольшое замедление. Теперь вы можете произносить заклинания в космосе и местах с низкой температурой! Имеет функцию энергетического щита,который защищает от всех снарядов. Щит разряжается при получении урона и автоматически заряжается. + +spellbook-hfrequency-name = Высокочастотный клинок +spellbook-hfrequency-desc = Невероятно мощный клинок, способный атаковать очень, ОЧЕНЬ быстро. Также клинок способен отражать выстрелы. + +spellbook-spellblade-name = Клинок заклинаний +spellbook-spellblade-desc = Клинок, наполненный магией, можно усилить, выбрав один из пяти аспектов. + +spellbook-mjolnir-name = Мьёльнир +spellbook-mjolnir-desc = Могучий двуручный молот Тора. Ударив им по врагам, вы заставите их отлететь от вас, а также оглушить на 1,5 секунды. Вы можете его бросить для достижения того же эффекта. diff --git a/Resources/Locale/ru-RU/_white/wizard/spells.ftl b/Resources/Locale/ru-RU/_white/wizard/spells.ftl new file mode 100644 index 0000000000..075acfc6c4 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/wizard/spells.ftl @@ -0,0 +1,44 @@ +ent-ActionElectricArcSpell = Электрическая дуга + .desc = Выпускает из ваших рук мощную молнию, способную сразить любого члена экипажа. Альтернативный каст: выпускает взрывающуюся шаровую молнию. При зарядке: выпускает несколько молний вокруг вас. Не работает без волшебной мантии и шляпы. + +ent-ActionForceSpell = Сила + .desc = Притягивает все объекты и сущности в указанную точку. Альтернативный каст: Прицельно притягивает к вам предмет или сущность. При зарядке: Вместо притяжение в выбранную точку, отталкивает все объекты от заклинателя. С каждым уровнем повышается мощность отталкивания. + +ent-ActionFireballSpell = Огненный шар + .desc = Создает огненный шар, наносящий огромный урон при взрыве. Альтернативный каст: Поджигает одну цель на любом расстоянии, навешивая проклятие, при котором смерть от огня уничтожит тело. При зарядке: Поджигает все сущности вокруг, с каждым уровнем повышается сила поджога и радиус поражения. Не работает без волшебной мантии и шляпы. + +ent-ActionCardSpell = Карты + .desc = Настоящий козырь в рукаве! Вернее, целая колода таких. Выпускает несколько смертельных карт в одном направлении. Карты способны оглушить цель. Альтернативный каст: Превращает в карту любой предмет. В карту можно превратить только предметы. При зарядке: Выпускает карты вокруг вас, с каждым уровнем зарядки количество выпускаемых карт повышается. + +ent-ActionForcewallSpell = Силовой барьер + .desc = Создает перед заклинателем 3 барьера. Альтернативный каст: Позволяет поставить барьер 3x3 в любой точке. При зарядке: Барьеры появляются не перед магом, а вокруг него, с каждым уровнем будет повышаться количество барьеров. Не работает без волшебной мантии и шляпы. + +ent-ActionBlinkSpell = Прыжок + .desc = Переносит на несколько тайлов вперед. + +ent-ActionEtherealJauntSpell = Потустороннее путешествие + .desc = Создаёт вашу астральную форму, временно делая вас невидимым и способным проходить сквозь стены. Не работает без волшебной мантии и шляпы. + +ent-ActionEmpSpell = ЭМИ + .desc = Создаёт ЭМИ взрыв в огромном радиусе вокруг мага. Не работает без волшебной мантии и шляпы. + +ent-ActionCluwneCurseSpell = Проклятье клувна + .desc = Ужаснейшее проклятие, превращает цель в толстого и уродливого тупицу - клувень. + +ent-ActionBananaTouchSpell = Банановое касание + .desc = Превращает цель в клоуна. + +ent-ActionMimeTouchSpell = Касание мима + .desc = Превращает в мима любого члена экипажа, без возможности нарушить обет молчания. + +ent-ActionInstantRecallSpell = Мгновенный призыв + .desc = Привязывает к вашей душе отдельный предмет. Используйте это заклинание, удерживая предмет, чтобы пометить его. Снова примените заклинание и привязанный предмет телепортируется к вам в руку. Если вы отметили предмет и произнесли это заклинание, удерживая другой предмет, вы удалите исходную метку. + +ent-ActionTeleportSpell = Телепортация + .desc = Позволяет телепортироваться в любое место на станции! Переносит вас в выбранное место. + +ent-ActionKnock = Стук + .desc = Открывает все двери и шлюзы в радиусе 4 тайлов. + +ent-ActionSmite = Кара + .desc = Заряжает вашу руку мерзкой энергией, которую можно использовать для взрыва жертв. Заклинание требует, чтобы вы коснулись своей цели, поэтому вы не сможете использовать его в наручниках или будучи оглушённым. Не работает без волшебной мантии и шляпы. diff --git a/Resources/Locale/ru-RU/_white/wizard/wizard.ftl b/Resources/Locale/ru-RU/_white/wizard/wizard.ftl index 4809f22c27..8b692fa09b 100644 --- a/Resources/Locale/ru-RU/_white/wizard/wizard.ftl +++ b/Resources/Locale/ru-RU/_white/wizard/wizard.ftl @@ -24,6 +24,18 @@ ent-WizardSurviveObjective = Переживете смену, устроив к ent-SpellBook = книга заклинаний .desc = Неземной фолиант, излучающий силу. +ent-ClothingHeadHatRealWizardFancy = волшебная шляпа + .desc = Странный головной убор, который наверняка принадлежит настоящему магу. + +ent-ClothingHeadHatRealWizardFancyAlt = волшебная шляпа + .desc = Странный головной убор, который наверняка принадлежит настоящему магу. + +ent-ClothingOuterRealWizardFancy = мантия волшебника + .desc = Великолепная, украшенная драгоценными камнями мантия, которая, кажется, излучает силу. + +ent-ClothingHeadHelmetWizardHelmArmored = шлем мага + .desc = Странный головной убор, который наверняка принадлежит настоящему магу. Не обладает свойствами волшебной шляпы. + store-currency-display-spell-point = Очки заклинаний store-category-spells-attack = Атакующие заклинания diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/armor.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/armor.ftl index 2ddbb404bc..b44670be46 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/armor.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/clothing/outerclothing/armor.ftl @@ -17,10 +17,10 @@ ent-ClothingOuterArmorHeavyRed = красный тяжелый бронекос .desc = Тяжело бронированный костюм с красными вставками, способный защитить от высокого урона. .suffix = { "" } ent-ClothingOuterArmorMagusblue = синие доспехи магуса - .desc = Синий бронекостюм, обеспечивающий хорошую защиту. + .desc = Синий бронекостюм, обеспечивающий хорошую защиту. Не обладает свойствами волшебной мантии. .suffix = { "" } ent-ClothingOuterArmorMagusred = красные доспехи магуса - .desc = Красный бронекостюм, обеспечивающий хорошую защиту. + .desc = Красный бронекостюм, обеспечивающий хорошую защиту. Не обладает свойствами волшебной мантии. .suffix = { "" } ent-ClothingOuterArmorRiot = противоударный костюм .desc = Бронежилет с тяжелыми накладками для защиты в ближнем бою, идеально подходит для борьбы с правонарушителями на станции. diff --git a/Resources/Maps/White/Shuttles/wizard.yml b/Resources/Maps/White/Shuttles/wizard.yml index 0efc2f61c2..0ec7a8e005 100644 --- a/Resources/Maps/White/Shuttles/wizard.yml +++ b/Resources/Maps/White/Shuttles/wizard.yml @@ -2050,6 +2050,18 @@ entities: - type: Transform pos: -5.52865,-9.359842 parent: 2 +- proto: ClothingHeadHelmetWizardHelmArmored + entities: + - uid: 772 + components: + - type: Transform + pos: -2.5,-1.5 + parent: 2 + - uid: 773 + components: + - type: Transform + pos: 1.5,-1.5 + parent: 2 - proto: ClothingMaskGasChameleon entities: - uid: 275 @@ -2057,6 +2069,20 @@ entities: - type: Transform pos: -9.537922,-3.3987489 parent: 2 +- proto: ClothingOuterArmorMagusblue + entities: + - uid: 771 + components: + - type: Transform + pos: -2.505693,-1.8391577 + parent: 2 +- proto: ClothingOuterArmorMagusred + entities: + - uid: 770 + components: + - type: Transform + pos: 1.4998147,-1.8497881 + parent: 2 - proto: ClothingUniformJumpskirtColorBlack entities: - uid: 276 diff --git a/Resources/Maps/White/Whitebox.yml b/Resources/Maps/White/Whitebox.yml index a24b109827..c186e781a5 100644 --- a/Resources/Maps/White/Whitebox.yml +++ b/Resources/Maps/White/Whitebox.yml @@ -76640,13 +76640,6 @@ entities: - type: Transform pos: -15.657842,47.202713 parent: 2 -- proto: ClothingShoesSpaceNinja - entities: - - uid: 10939 - components: - - type: Transform - pos: 30.33621,-71.6811 - parent: 2 - proto: ClothingUnderSocksBee entities: - uid: 10940 diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml index 11f1f26aa8..07e145e636 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml @@ -1,8 +1,8 @@ - type: vendingMachineInventory id: SalvageEquipmentInventory startingInventory: - WeaponProtoKineticAccelerator: 4 - WeaponCrusher: 4 + WeaponProtoKineticAccelerator: 2 + WeaponCrusher: 2 WeaponCrusherDagger: 4 WeaponGrapplingGun: 3 HandheldGPSBasic: 10 diff --git a/Resources/Prototypes/Entities/Clothing/Head/helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/helmets.yml index 9e8a140be3..63ea974c47 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/helmets.yml @@ -203,6 +203,18 @@ - type: IngestionBlocker - type: IdentityBlocker +- type: entity + parent: ClothingHeadHelmetWizardHelm + id: ClothingHeadHelmetWizardHelmArmored + components: + - type: Armor + modifiers: + coefficients: + Blunt: 0.8 + Slash: 0.8 + Piercing: 0.85 + Heat: 0.8 + #Fire Helmet - type: entity parent: ClothingHeadLightBase diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index 58a1674b4a..6dc1eb2a83 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -200,7 +200,7 @@ sprite: Clothing/OuterClothing/Armor/heavyred.rsi - type: entity - parent: ClothingOuterArmorHeavy + parent: ClothingOuterBaseLarge id: ClothingOuterArmorMagusblue name: blue magus armor description: An blue armored suit that provides good protection. @@ -209,9 +209,22 @@ sprite: Clothing/OuterClothing/Armor/magusblue.rsi - type: Clothing sprite: Clothing/OuterClothing/Armor/magusblue.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.5 + Slash: 0.5 + Piercing: 0.6 + Heat: 0.5 + - type: ExplosionResistance + damageCoefficient: 0.5 + - type: GroupExamine + - type: ClothingSpeedModifier + walkModifier: 1 + sprintModifier: 1 - type: entity - parent: ClothingOuterArmorHeavy + parent: ClothingOuterArmorMagusblue id: ClothingOuterArmorMagusred name: red magus armor description: A red armored suit that provides good protection. diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index 5e82959c4e..db00905ea6 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -113,7 +113,7 @@ - type: ContainerContainer containers: toggleable-clothing: !type:ContainerSlot {} - + - type: entity parent: ClothingOuterBaseLarge id: ClothingOuterSuitSpaceNinja @@ -125,7 +125,7 @@ - type: Clothing sprite: Clothing/OuterClothing/Suits/spaceninja.rsi - type: StealthClothing - visibility: 1.1 + visibility: 0.5 toggleAction: ActionTogglePhaseCloak - type: PressureProtection highPressureMultiplier: 0.6 diff --git a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml index f1c9f5acb3..09cff8ee0e 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml @@ -36,7 +36,6 @@ parent: Handcuffs components: - type: Handcuff - breakoutTime: 3 cuffedRSI: Objects/Misc/cablecuffs.rsi bodyIconState: body-overlay color: forestgreen @@ -79,7 +78,6 @@ size: Tiny storedRotation: 0 - type: Handcuff - breakoutTime: 3 cuffedRSI: Objects/Misc/cablecuffs.rsi # cablecuffs will look fine bodyIconState: body-overlay breakOnRemove: true diff --git a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml index 508254d5bb..203b13c38f 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/jaws_of_life.yml @@ -47,7 +47,7 @@ damage: types: Blunt: 15 - Structural: 40 + Structural: 10 soundHit: path: "/Audio/Weapons/smash.ogg" @@ -89,4 +89,4 @@ damage: types: Blunt: 20 - Structural: 60 + Structural: 20 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml index 8bfec739cc..0579964727 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/spear.yml @@ -60,7 +60,7 @@ - type: SolutionContainerManager solutions: melee: - maxVol: 2 + maxVol: 5 - type: MeleeChemicalInjector solution: melee - type: RefillableSolution diff --git a/Resources/Prototypes/Entities/Structures/Walls/walls.yml b/Resources/Prototypes/Entities/Structures/Walls/walls.yml index 44ffa057aa..84550cfa7a 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/walls.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/walls.yml @@ -136,7 +136,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -284,7 +284,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -320,7 +320,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -441,7 +441,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -686,7 +686,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -722,7 +722,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -893,7 +893,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -1244,7 +1244,7 @@ name: force wall components: - type: TimedDespawn - lifetime: 20 + lifetime: 9 - type: Tag tags: - Wall @@ -1284,7 +1284,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: diff --git a/Resources/Prototypes/Magic/white.yml b/Resources/Prototypes/Magic/white.yml index 19f55b7f49..92be6e994f 100644 --- a/Resources/Prototypes/Magic/white.yml +++ b/Resources/Prototypes/Magic/white.yml @@ -281,6 +281,7 @@ sprite: Objects/Magic/magicactions.rsi state: summons event: !type:InstantRecallSpellEvent + speech: "GAR YOK!" - type: entity id: ActionTeleportSpell diff --git a/Resources/Prototypes/_White/Entities/Cult/Weapons/blood_spear.yml b/Resources/Prototypes/_White/Entities/Cult/Weapons/blood_spear.yml index dfcdfc7c9b..14de56bd1a 100644 --- a/Resources/Prototypes/_White/Entities/Cult/Weapons/blood_spear.yml +++ b/Resources/Prototypes/_White/Entities/Cult/Weapons/blood_spear.yml @@ -46,6 +46,7 @@ - type: Clothing slots: - back + - suitStorage - type: Wieldable - type: IncreaseDamageOnWield damage: diff --git a/Resources/Prototypes/_White/Entities/Cult/other_structures.yml b/Resources/Prototypes/_White/Entities/Cult/other_structures.yml index 09bb9842d6..e30892d7ca 100644 --- a/Resources/Prototypes/_White/Entities/Cult/other_structures.yml +++ b/Resources/Prototypes/_White/Entities/Cult/other_structures.yml @@ -44,6 +44,8 @@ - type: Construction graph: AirlockGlassCult node: airlock + - type: RCDDeconstructable + deconstructable: false - type: PlacementReplacement key: walls - type: Appearance diff --git a/Resources/Prototypes/_White/Wizard/magic_items.yml b/Resources/Prototypes/_White/Wizard/magic_items.yml index c1555ee2c7..ab79803482 100644 --- a/Resources/Prototypes/_White/Wizard/magic_items.yml +++ b/Resources/Prototypes/_White/Wizard/magic_items.yml @@ -36,6 +36,7 @@ types: Slash: 30 - type: Clothing + quickEquip: false sprite: White/Objects/Weapons/Chaplain/spellblade.rsi slots: - back @@ -51,3 +52,55 @@ inHandsOnly: true closeOnHandDeselect: true - type: SpellBlade + +- type: entity + name: мьёльнир + parent: BaseItem + id: Mjolnir + description: Могучий молот, заимствованный у Тора, бога грома. Он трещит от едва сдерживаемой силы. + components: + - type: Sprite + sprite: White/Objects/Weapons/mjolnir.rsi + state: icon + - type: MeleeWeapon + wideAnimationRotation: -135 + attackRate: 0.75 + damage: + types: + Blunt: 25 + Structural: 20 + soundHit: + path: /Audio/White/Magic/Mjolnir/hit.ogg + soundSwing: + path: /Audio/White/Magic/Mjolnir/swing.ogg + - type: Wieldable + - type: IncreaseDamageOnWield + damage: + types: + Blunt: 15 + Structural: 60 + - type: Item + size: Huge + sprite: White/Objects/Weapons/mjolnir.rsi + - type: Clothing + quickEquip: false + sprite: White/Objects/Weapons/mjolnir.rsi + slots: + - back + - suitStorage + - type: DisarmMalus + - type: MeleeThrowOnHit + lifetime: 0.05 + minLifetime: 0.01 + speed: 20 + stunTime: 1.5 + throwOnThrowHit: true + - type: DamageOtherOnHit + sound: + path: /Audio/White/Magic/Mjolnir/hit.ogg + damage: + types: + Blunt: 40 + Structural: 80 + - type: ChangeThrowForce + throwForce: 20 diff --git a/Resources/Prototypes/_White/Wizard/spellblade.yml b/Resources/Prototypes/_White/Wizard/spellblade.yml index 635f32a704..fc0fea59a7 100644 --- a/Resources/Prototypes/_White/Wizard/spellblade.yml +++ b/Resources/Prototypes/_White/Wizard/spellblade.yml @@ -10,7 +10,7 @@ - type: entity name: Холод - description: Клинок заклинаний наделяется замораживать врагов. И тот, кто удерживает клинок в руках, становится неуязвимым к низкой температуре. + description: Клинок заклинаний наделяется способностью замораживать врагов. И тот, кто удерживает клинок в руках, становится неуязвимым к низкой температуре. id: AspectFrost noSpawn: true components: diff --git a/Resources/Prototypes/_White/Wizard/spellbook_catalog.yml b/Resources/Prototypes/_White/Wizard/spellbook_catalog.yml index 1d891bba02..a9cd7016b0 100644 --- a/Resources/Prototypes/_White/Wizard/spellbook_catalog.yml +++ b/Resources/Prototypes/_White/Wizard/spellbook_catalog.yml @@ -260,3 +260,16 @@ conditions: - !type:ListingLimitedStockCondition stock: 1 + +- type: listing + id: SpellBookMjolnir + name: spellbook-mjolnir-name + description: spellbook-mjolnir-desc + productEntity: Mjolnir + cost: + SpellPoint: 2 + categories: + - MagicItems + conditions: + - !type:ListingLimitedStockCondition + stock: 1 diff --git a/Resources/Prototypes/secret_weights.yml b/Resources/Prototypes/secret_weights.yml index 882d0b16ae..1e624b6b4e 100644 --- a/Resources/Prototypes/secret_weights.yml +++ b/Resources/Prototypes/secret_weights.yml @@ -1,10 +1,11 @@ - type: weightedRandom id: Secret weights: - Traitor: 0.35 - Changeling: 0.15 - Nukeops: 0.15 + Traitor: 0.3 + Changeling: 0.14 + Nukeops: 0.14 Cult: 0.15 - Revolutionary: 0.1 - Zombie: 0.05 - Survival: 0.05 + Wizard: 0.15 + Revolutionary: 0.04 + Zombie: 0.04 + Survival: 0.04 diff --git a/Resources/Textures/White/Misc/scrolls.rsi/scroll.png b/Resources/Textures/White/Misc/scrolls.rsi/scroll.png index 2f00a23401..1b923d489a 100644 Binary files a/Resources/Textures/White/Misc/scrolls.rsi/scroll.png and b/Resources/Textures/White/Misc/scrolls.rsi/scroll.png differ diff --git a/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/equipped-BACKPACK.png b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/equipped-BACKPACK.png new file mode 100644 index 0000000000..22d7516625 Binary files /dev/null and b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/equipped-BACKPACK.png differ diff --git a/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/icon.png b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/icon.png new file mode 100644 index 0000000000..420a46f29a Binary files /dev/null and b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/icon.png differ diff --git a/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/inhand-left.png b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/inhand-left.png new file mode 100644 index 0000000000..2b5216cc45 Binary files /dev/null and b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/inhand-left.png differ diff --git a/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/inhand-right.png b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/inhand-right.png new file mode 100644 index 0000000000..3c4128442b Binary files /dev/null and b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/inhand-right.png differ diff --git a/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/meta.json b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/meta.json new file mode 100644 index 0000000000..8d768337e6 --- /dev/null +++ b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/meta.json @@ -0,0 +1,46 @@ +{ + "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", + "delays": [ + [ + 2, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "wielded-inhand-left", + "directions": 4 + }, + { + "name": "wielded-inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/wielded-inhand-left.png b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/wielded-inhand-left.png new file mode 100644 index 0000000000..499a827bc9 Binary files /dev/null and b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/wielded-inhand-left.png differ diff --git a/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/wielded-inhand-right.png b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/wielded-inhand-right.png new file mode 100644 index 0000000000..5ef1c92af2 Binary files /dev/null and b/Resources/Textures/White/Objects/Weapons/mjolnir.rsi/wielded-inhand-right.png differ