diff --git a/Content.Client/_White/Cult/UI/CultAltarSystem.cs b/Content.Client/_White/Cult/UI/CultAltarSystem.cs new file mode 100644 index 0000000000..89f4dadf55 --- /dev/null +++ b/Content.Client/_White/Cult/UI/CultAltarSystem.cs @@ -0,0 +1,24 @@ +using Content.Client._White.Cult.UI.CultistFactory; +using Content.Shared._White.Cult.Components; +using Content.Shared._White.Cult.UI; + +namespace Content.Client._White.Cult.UI; + +public sealed class CultAltarSystem : EntitySystem +{ + [Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAltarAfterState); + } + + private void OnAltarAfterState(Entity ent, ref AfterAutoHandleStateEvent args) + { + if (!_uiSystem.TryGetOpenUi(ent.Owner, CultistAltarUiKey.Key, out var bui)) + return; + + bui.Dispose(); + } +} diff --git a/Content.Client/_White/Cult/UI/CultistFactory/CultistFactoryBUI.cs b/Content.Client/_White/Cult/UI/CultistFactory/CultistFactoryBUI.cs index 74516d4ade..a9346b0319 100644 --- a/Content.Client/_White/Cult/UI/CultistFactory/CultistFactoryBUI.cs +++ b/Content.Client/_White/Cult/UI/CultistFactory/CultistFactoryBUI.cs @@ -1,6 +1,8 @@ using Content.Client._White.UserInterface.Radial; using Content.Shared._White.Cult; +using Content.Shared._White.Cult.Components; using Content.Shared._White.Cult.UI; +using Robust.Client.Player; using Robust.Shared.Prototypes; namespace Content.Client._White.Cult.UI.CultistFactory; @@ -8,6 +10,7 @@ namespace Content.Client._White.Cult.UI.CultistFactory; public sealed class CultistFactoryBUI : BoundUserInterface { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly EntityManager _entityManager = default!; private RadialContainer? _radialContainer; private bool _updated = false; @@ -18,7 +21,7 @@ public sealed class CultistFactoryBUI : BoundUserInterface } private void ResetUI() { - _radialContainer?.Close(); + _radialContainer?.Dispose(); _radialContainer = null; _updated = false; } @@ -30,6 +33,9 @@ public sealed class CultistFactoryBUI : BoundUserInterface if (_radialContainer != null) ResetUI(); + if(!CanOpen()) + return; + _radialContainer = new RadialContainer(); _radialContainer.Closed += Close; @@ -58,11 +64,20 @@ public sealed class CultistFactoryBUI : BoundUserInterface private void Select(string id) { - SendMessage(new CultistFactoryItemSelectedMessage(id)); + SendPredictedMessage(new CultistFactoryItemSelectedMessage(id)); ResetUI(); Close(); } + private bool CanOpen() + { + var localPlayer = IoCManager.Resolve().LocalPlayer; + + var uid = localPlayer?.ControlledEntity; + + return uid != null && _entityManager.HasComponent(uid); + } + protected override void Dispose(bool disposing) { base.Dispose(disposing); diff --git a/Content.Client/_White/Cult/UI/StructureRadial/StructureCraftBoundUserInterface.cs b/Content.Client/_White/Cult/UI/StructureRadial/StructureCraftBoundUserInterface.cs index d04ff37054..651de488d4 100644 --- a/Content.Client/_White/Cult/UI/StructureRadial/StructureCraftBoundUserInterface.cs +++ b/Content.Client/_White/Cult/UI/StructureRadial/StructureCraftBoundUserInterface.cs @@ -32,6 +32,8 @@ public sealed class StructureCraftBoundUserInterface : BoundUserInterface _radialContainer = new RadialContainer(); + _radialContainer.Closed += Close; + foreach (var prototype in _prototypeManager.EnumeratePrototypes()) { var radialButton = _radialContainer.AddButton(prototype.StructureName, prototype.Icon); diff --git a/Content.Client/_White/DeadWithoutMind/ShowDeadWithoutMindSystem.cs b/Content.Client/_White/DeadWithoutMind/ShowDeadWithoutMindSystem.cs new file mode 100644 index 0000000000..21db9ece1f --- /dev/null +++ b/Content.Client/_White/DeadWithoutMind/ShowDeadWithoutMindSystem.cs @@ -0,0 +1,42 @@ +using Content.Client.Overlays; +using Content.Shared._White.DeadWithoutMind; +using Content.Shared.Humanoid; +using Content.Shared.Mind.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.StatusIcon; +using Content.Shared.StatusIcon.Components; +using Robust.Shared.Prototypes; + +namespace Content.Client._White.DeadWithoutMind; + +public sealed class ShowDeadWithoutMindSystem : EquipmentHudSystem +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetStatusIconsEvent); + } + + private void OnGetStatusIconsEvent(Entity entity, ref GetStatusIconsEvent args) + { + if (!IsActive || args.InContainer) + return; + + if (!TryComp(entity.Owner, out var mindContainer)) + return; + + var dead = _mobStateSystem.IsDead(entity.Owner); + + if (!dead) + return; + + if (mindContainer.Mind != null) + return; + + if (_prototype.TryIndex(entity.Comp.DeadWithoutMindIcon.Id, out var iconPrototype)) + args.StatusIcons.Add(iconPrototype); + } +} diff --git a/Content.Client/_White/Radials/RadialUIController.cs b/Content.Client/_White/Radials/RadialUIController.cs index a3775723d9..dd976bcf2a 100644 --- a/Content.Client/_White/Radials/RadialUIController.cs +++ b/Content.Client/_White/Radials/RadialUIController.cs @@ -55,7 +55,8 @@ public sealed class RadialUIController : UIController, IOnStateEntered Close(); + OpenMenu.CloseButton.Controller.OnPressed += _ => + { + Close(); + }; foreach (var radial in CurrentRadials) { @@ -93,7 +97,7 @@ public sealed class RadialUIController : UIController, IOnStateEntered().FirstOrDefault(); + if (cultistRule?.CultTarget is null) { return; diff --git a/Content.Server/Shuttles/Components/ThrusterComponent.cs b/Content.Server/Shuttles/Components/ThrusterComponent.cs index 3bba9b5a7f..b3a4732354 100644 --- a/Content.Server/Shuttles/Components/ThrusterComponent.cs +++ b/Content.Server/Shuttles/Components/ThrusterComponent.cs @@ -1,8 +1,10 @@ using System.Numerics; using Content.Server.Shuttles.Systems; using Content.Shared.Damage; +using Content.Shared.DeviceLinking; using Robust.Shared.GameStates; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Shuttles.Components { @@ -55,6 +57,17 @@ namespace Content.Server.Shuttles.Components /// [ViewVariables(VVAccess.ReadWrite), DataField("nextFire", customTypeSerializer:typeof(TimeOffsetSerializer))] public TimeSpan NextFire; + + // Parsec edit start + [DataField("onPort", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string OnPort = "On"; + + [DataField("offPort", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string OffPort = "Off"; + + [DataField("togglePort", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string TogglePort = "Toggle"; + // Parsec edit end } public enum ThrusterType diff --git a/Content.Server/Shuttles/Systems/ThrusterSystem.cs b/Content.Server/Shuttles/Systems/ThrusterSystem.cs index 74c42ccbc5..d1561319c7 100644 --- a/Content.Server/Shuttles/Systems/ThrusterSystem.cs +++ b/Content.Server/Shuttles/Systems/ThrusterSystem.cs @@ -1,5 +1,6 @@ using System.Numerics; using Content.Server.Audio; +using Content.Server.DeviceLinking.Events; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.Shuttles.Components; @@ -48,6 +49,7 @@ public sealed class ThrusterSystem : EntitySystem SubscribeLocalEvent(OnIsHotEvent); SubscribeLocalEvent(OnStartCollide); SubscribeLocalEvent(OnEndCollide); + SubscribeLocalEvent(OnSignalReceived); SubscribeLocalEvent(OnThrusterExamine); @@ -576,4 +578,30 @@ public sealed class ThrusterSystem : EntitySystem { return (int) Math.Log2((int) flag); } + // Parsec edit start + private void OnSignalReceived(EntityUid uid, ThrusterComponent component, ref SignalReceivedEvent args) + { + if (args.Port == component.OffPort && component.IsOn) + { + DisableThruster(uid, component); + return; + } + + if (args.Port == component.OnPort && !component.IsOn) + { + EnableThruster(uid, component); + return; + } + + switch (component.IsOn && args.Port == component.TogglePort) + { + case true: + DisableThruster(uid, component); + break; + case false: + EnableThruster(uid, component); + break; + } + } + // Parsec edit end } diff --git a/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs b/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs index db9ac8e5ef..02cd5958b2 100644 --- a/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs +++ b/Content.Server/_White/Cult/GameRule/CultRuleSystem.cs @@ -42,8 +42,8 @@ public sealed class CultRuleSystem : GameRuleSystem [Dependency] private readonly ContainerSystem _container = default!; [Dependency] private readonly HandsSystem _hands = default!; [Dependency] private readonly GulagSystem _gulag = default!; - [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly AlertsSystem _alertsSystem = default!; + [Dependency] private readonly IRobustRandom _random = default!; public override void Initialize() { @@ -61,9 +61,6 @@ public sealed class CultRuleSystem : GameRuleSystem protected override void Added(EntityUid uid, CultRuleComponent rule, GameRuleComponent gameRule, GameRuleAddedEvent args) { base.Added(uid, rule, gameRule, args); - - var potentialTargets = FindPotentialTargets(); - rule.CultTarget = _random.PickAndTake(potentialTargets).Mind; } private void OnClone(Entity ent, ref CloningEvent args) @@ -266,6 +263,17 @@ public sealed class CultRuleSystem : GameRuleSystem private void AfterEntitySelected(Entity ent, ref AfterAntagEntitySelectedEvent args) { + if (ent.Comp.CultTarget == null) + { + var potentialTargets = FindPotentialTargets(); + if (potentialTargets.Count == 0) + { + ent.Comp.CultTarget = null; + return; + } + ent.Comp.CultTarget = _random.PickAndTake(potentialTargets).Mind; + } + MakeCultist(args.EntityUid, ent); } @@ -335,12 +343,11 @@ public sealed class CultRuleSystem : GameRuleSystem private List FindPotentialTargets() { - var querry = - EntityManager.EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); var potentialTargets = new List(); - while (querry.MoveNext(out var uid, out var mind, out _, out var actor)) + while (query.MoveNext(out var uid, out var mind, out _, out var actor)) { var entity = mind.Mind; @@ -350,7 +357,7 @@ public sealed class CultRuleSystem : GameRuleSystem if (_gulag.IsUserGulagged(actor.PlayerSession.UserId, out _)) continue; - if (HasComp(entity)) + if (HasComp(uid)) continue; potentialTargets.Add(mind); diff --git a/Content.Server/_White/Cult/Items/Systems/ReturnItemOnThrowSystem.cs b/Content.Server/_White/Cult/Items/Systems/ReturnItemOnThrowSystem.cs index 0b10b9d173..b19d4bbfa1 100644 --- a/Content.Server/_White/Cult/Items/Systems/ReturnItemOnThrowSystem.cs +++ b/Content.Server/_White/Cult/Items/Systems/ReturnItemOnThrowSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Stunnable; using Content.Server._White.Cult.Items.Components; using Content.Shared._White.Chaplain; +using Content.Shared.Humanoid; using Content.Shared.Mobs.Components; using Content.Shared.Throwing; using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent; @@ -25,12 +26,16 @@ public sealed class ReturnItemOnThrowSystem : EntitySystem { var isCultist = HasComp(args.Target); var thrower = args.Component.Thrower; + var isHumanoid = HasComp(args.Target); if (!HasComp(thrower)) return; if (!HasComp(args.Target)) return; + if(!isHumanoid) + return; + if (!isCultist && !_holyWeapon.IsHoldingHolyWeapon(args.Target)) { _stun.TryParalyze(args.Target, TimeSpan.FromSeconds(component.StunTime), true); diff --git a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs index c8e390d859..01d19094ee 100644 --- a/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs +++ b/Content.Server/_White/Cult/Runes/Systems/CultSystem.Rune.cs @@ -1327,13 +1327,15 @@ public sealed partial class CultSystem : EntitySystem if (transform == null) return false; - if (!mindComponent.Mind.HasValue) + if (mindComponent.Mind.HasValue == false) return false; var shard = _entityManager.SpawnEntity("SoulShard", transform.Value); + if (shard.Valid == false) + return false; + _mindSystem.TransferTo(mindComponent.Mind.Value, shard); - _mindSystem.UnVisit(mindComponent.Mind.Value); _bodySystem.GibBody(target); diff --git a/Content.Server/_White/Cult/Structures/CultStructureCraftSystem.cs b/Content.Server/_White/Cult/Structures/CultStructureCraftSystem.cs index e819563782..847d2926f9 100644 --- a/Content.Server/_White/Cult/Structures/CultStructureCraftSystem.cs +++ b/Content.Server/_White/Cult/Structures/CultStructureCraftSystem.cs @@ -24,7 +24,9 @@ public sealed class CultStructureCraftSystem : EntitySystem if (!HasComp(args.User)) return; - _uiSystem.CloseUi(uid, component.UserInterfaceKey, args.User); + if(_uiSystem.HasUi(args.User, component.UserInterfaceKey)) + _uiSystem.CloseUi(uid, component.UserInterfaceKey, args.User); + _uiSystem.OpenUi(uid, component.UserInterfaceKey, args.User); } } diff --git a/Content.Server/_White/Cult/TimedProduction/CultistFactorySystem.cs b/Content.Server/_White/Cult/TimedProduction/CultistFactorySystem.cs index 4223af58c0..1b87653eaa 100644 --- a/Content.Server/_White/Cult/TimedProduction/CultistFactorySystem.cs +++ b/Content.Server/_White/Cult/TimedProduction/CultistFactorySystem.cs @@ -4,9 +4,11 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared._White.Cult; +using Content.Shared._White.Cult.Components; using Content.Shared._White.Cult.Structures; using Content.Shared._White.Cult.Systems; using Content.Shared._White.Cult.UI; +using Content.Shared.UserInterface; using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; @@ -37,11 +39,12 @@ public sealed class CultistFactorySystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnInteract); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnSelected); SubscribeLocalEvent(TryToggleAnchor); + SubscribeLocalEvent((u, c, args) => UpdateUserInterfaceState(u, args, c)); + SubscribeLocalEvent((u, c, args) => OnActivatableUI(u, args, c)); SubscribeLocalEvent(OnAnchorDoAfter); SubscribeLocalEvent(OnExamine); SubscribeLocalEvent(OnConceal); @@ -70,28 +73,32 @@ public sealed class CultistFactorySystem : EntitySystem } } - private void OnInit(EntityUid uid, CultistFactoryComponent component, ComponentInit args) + public void UpdateUserInterfaceState(EntityUid uid, BeforeActivatableUIOpenEvent args, CultistFactoryComponent? component = null) { - UpdateAppearance(uid, component); - } - - private void OnInteract(EntityUid uid, CultistFactoryComponent component, InteractHandEvent args) - { - if (!HasComp(args.User)) - return; - - if (!HasComp(args.User)) - return; - - if (!CanCraft(uid, component, args.User)) - return; - - var xform = Transform(uid); - if (!xform.Anchored) + if (!Resolve(uid, ref component)) return; _ui.SetUiState(uid, CultistAltarUiKey.Key, new CultistFactoryBUIState(component.Products)); - _ui.OpenUi(uid, CultistAltarUiKey.Key, uid); + + Dirty(uid, component); + } + + private void OnActivatableUI(EntityUid uid, ActivatableUIOpenAttemptEvent args, CultistFactoryComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + var user = args.User; + + if (!HasComp(user)) + args.Cancel(); + + Dirty(uid, component); + } + + private void OnInit(EntityUid uid, CultistFactoryComponent component, ComponentInit args) + { + UpdateAppearance(uid, component); } private void OnSelected(EntityUid uid, CultistFactoryComponent component, CultistFactoryItemSelectedMessage args) diff --git a/Content.Server/_White/Executions/ExecutionSystem.cs b/Content.Server/_White/Executions/ExecutionSystem.cs new file mode 100644 index 0000000000..3d04fd3a09 --- /dev/null +++ b/Content.Server/_White/Executions/ExecutionSystem.cs @@ -0,0 +1,367 @@ +using Content.Server.DoAfter; +using Content.Server.Interaction; +using Content.Server.Kitchen.Components; +using Content.Server.Popups; +using Content.Shared._White.Executions; +using Content.Shared.ActionBlocker; +using Content.Shared.Damage; +using Content.Shared.Database; +using Content.Shared.DoAfter; +using Content.Shared.Interaction.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.Popups; +using Content.Shared.Projectiles; +using Content.Shared.Verbs; +using Content.Shared.Weapons.Melee; +using Content.Shared.Weapons.Ranged; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; + +namespace Content.Server._White.Executions; + +public sealed class ExecutionSystem : EntitySystem +{ + [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly InteractionSystem _interactionSystem = default!; + [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IComponentFactory _componentFactory = default!; + [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly SharedGunSystem _gunSystem = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + + private const float MeleeExecutionTimeModifier = 5.0f; + private const float GunExecutionTime = 6.0f; + private const float DamageModifier = 10.0f; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnGetInteractionVerbsMelee); + SubscribeLocalEvent>(OnGetInteractionVerbsGun); + + SubscribeLocalEvent(OnDoafterMelee); + SubscribeLocalEvent(OnDoafterGun); + } + + private void OnGetInteractionVerbsMelee( + EntityUid uid, + SharpComponent component, + GetVerbsEvent args) + { + if (args.Hands == null || args.Using == null || !args.CanAccess || !args.CanInteract) + return; + + var attacker = args.User; + var weapon = args.Using.Value; + var victim = args.Target; + + if (!CanExecute(weapon, victim, attacker, true)) + return; + + EnsureComp(weapon, out var comp); + + if (IsDelayed(comp)) + return; + + UtilityVerb verb = new() + { + Act = () => + { + TryStartMeleeExecutionDoafter(weapon, victim, attacker); + }, + Impact = LogImpact.High, + Text = Loc.GetString("execution-verb-name"), + Message = Loc.GetString("execution-verb-message"), + }; + + args.Verbs.Add(verb); + } + + private void OnGetInteractionVerbsGun( + EntityUid uid, + GunComponent component, + GetVerbsEvent args) + { + if (args.Hands == null || args.Using == null || !args.CanAccess || !args.CanInteract) + return; + + var attacker = args.User; + var weapon = args.Using!.Value; + var victim = args.Target; + + if (!CanExecute(weapon, victim, attacker, false)) + return; + + EnsureComp(weapon, out var comp); + + if (IsDelayed(comp)) + return; + + UtilityVerb verb = new() + { + Act = () => + { + TryStartGunExecutionDoafter(weapon, victim, attacker); + }, + Impact = LogImpact.High, + Text = Loc.GetString("execution-verb-name"), + Message = Loc.GetString("execution-verb-message"), + }; + + args.Verbs.Add(verb); + } + + private bool CanExecuteWithAny(EntityUid victim, EntityUid attacker) + { + if (!HasComp(victim)) + return false; + + if (!TryComp(victim, out var mobState)) + return false; + + if (_mobStateSystem.IsDead(victim, mobState)) + return false; + + if (!_actionBlockerSystem.CanAttack(attacker, victim)) + return false; + + return victim == attacker || !_actionBlockerSystem.CanInteract(victim, null); + } + + private bool CanExecute(EntityUid weapon, EntityUid victim, EntityUid user, bool isMelee) + { + if (!CanExecuteWithAny(victim, user)) + return false; + + if (isMelee) + { + return (TryComp(weapon, out var melee) || melee!.Damage.GetTotal() <= 0.0f); + } + + return (TryComp(weapon, out var gun) || !_gunSystem.CanShoot(gun!)); + } + + + private void TryStartMeleeExecutionDoafter(EntityUid weapon, EntityUid victim, EntityUid attacker) + { + if (!CanExecute(weapon, victim, attacker, true)) + return; + + var executionTime = (1.0f / Comp(weapon).AttackRate) * MeleeExecutionTimeModifier; + + ShowExecutionPopup( + attacker == victim ? "suicide-popup-melee-initial-external" : "execution-popup-melee-initial-external", + PopupType.Medium, + attacker, + victim, + weapon); + + var doAfter = + new DoAfterArgs(EntityManager, attacker, executionTime, new ExecutionDoAfterEvent(), weapon, target: victim, used: weapon) + { + BreakOnMove = true, + BreakOnHandChange = true, + BreakOnDamage = true, + NeedHand = true + }; + + _doAfterSystem.TryStartDoAfter(doAfter); + + EnsureComp(weapon, out var comp); + + comp.NextUse = _gameTiming.CurTime + comp.NextAttempt; + } + + private void TryStartGunExecutionDoafter(EntityUid weapon, EntityUid victim, EntityUid attacker) + { + if (!CanExecute(weapon, victim, attacker, false)) + return; + + ShowExecutionPopup( + attacker == victim ? "suicide-popup-gun-initial-external" : "execution-popup-gun-initial-external", + PopupType.Medium, + attacker, + victim, + weapon); + + var doAfter = + new DoAfterArgs(EntityManager, attacker, GunExecutionTime, new ExecutionDoAfterEvent(), weapon, target: victim, used: weapon) + { + BreakOnMove = true, + BreakOnHandChange = true, + BreakOnDamage = true, + NeedHand = true + }; + + _doAfterSystem.TryStartDoAfter(doAfter); + + EnsureComp(weapon, out var comp); + + comp.NextUse = _gameTiming.CurTime + comp.NextAttempt; + } + + private void OnDoafterMelee(EntityUid uid, SharpComponent component, DoAfterEvent args) + { + if (args.Handled || args.Cancelled || args.Used == null || args.Target == null) + return; + + var attacker = args.User; + var victim = args.Target.Value; + var weapon = args.Used.Value; + + if (!CanExecute(weapon, victim, attacker, true)) + return; + + if (!TryComp(weapon, out var melee) && melee!.Damage.GetTotal() > 0.0f) + return; + + _damageableSystem.TryChangeDamage(victim, melee.Damage * DamageModifier, true); + _audioSystem.PlayEntity(melee.HitSound, Filter.Pvs(weapon), weapon, true, AudioParams.Default); + + ShowExecutionPopup( + attacker == victim ? "suicide-popup-melee-complete-external" : "execution-popup-melee-complete-external", + PopupType.MediumCaution, + attacker, + victim, + weapon); + } + + private void OnDoafterGun(EntityUid uid, GunComponent component, DoAfterEvent args) + { + if (args.Handled || args.Cancelled || args.Used == null || args.Target == null) + return; + + var attacker = args.User; + var weapon = args.Used.Value; + var victim = args.Target.Value; + + if (!CanExecute(weapon, victim, attacker, false)) + return; + + var prevention = new ShotAttemptedEvent + { + User = attacker, + Used = weapon! + }; + + RaiseLocalEvent(weapon, ref prevention); + if (prevention.Cancelled) + return; + + RaiseLocalEvent(attacker, ref prevention); + if (prevention.Cancelled) + return; + + var attemptEv = new AttemptShootEvent(attacker, null); + RaiseLocalEvent(weapon, ref attemptEv); + + if (attemptEv is { Cancelled: true, Message: not null }) + { + _popupSystem.PopupClient(attemptEv.Message, weapon, attacker); + return; + } + + var fromCoordinates = Transform(attacker).Coordinates; + var ev = new TakeAmmoEvent(1, new List<(EntityUid? Entity, IShootable Shootable)>(), fromCoordinates, attacker); + RaiseLocalEvent(weapon, ev); + + if (ev.Ammo.Count <= 0) + { + _audioSystem.PlayEntity(component.SoundEmpty, Filter.Pvs(weapon), weapon, true, AudioParams.Default); + ShowExecutionPopup("execution-popup-gun-empty", PopupType.Medium, attacker, victim, weapon); + return; + } + + var damage = new DamageSpecifier(); + + var ammoUid = ev.Ammo[0].Entity; + switch (ev.Ammo[0].Shootable) + { + case CartridgeAmmoComponent cartridge: + var prototype = _prototypeManager.Index(cartridge.Prototype); + prototype.TryGetComponent(out var projectileA, _componentFactory); + if (projectileA != null) + { + damage = projectileA.Damage * cartridge.Count; + } + + cartridge.Spent = true; + _appearanceSystem.SetData(ammoUid!.Value, AmmoVisuals.Spent, true); + Dirty(ammoUid.Value, cartridge); + + break; + + case AmmoComponent: + TryComp(ammoUid, out var projectileB); + if (projectileB != null) + { + damage = projectileB.Damage; + } + Del(ammoUid); + break; + + case HitscanPrototype hitscan: + damage = hitscan.Damage!; + break; + + default: + throw new ArgumentOutOfRangeException(); + } + + if (TryComp(attacker, out var clumsy) && !component.ClumsyProof) + { + if (_interactionSystem.TryRollClumsy(attacker, 0.3F, clumsy)) + { + ShowExecutionPopup("execution-popup-gun-clumsy-external", PopupType.MediumCaution, attacker, victim, weapon); + + _damageableSystem.TryChangeDamage(attacker, damage, origin: attacker); + _audioSystem.PlayEntity(component.SoundGunshot, Filter.Pvs(weapon), weapon, true, AudioParams.Default); + return; + } + } + + _damageableSystem.TryChangeDamage(victim, damage * DamageModifier, true); + _audioSystem.PlayEntity(component.SoundGunshot, Filter.Pvs(weapon), weapon, false, AudioParams.Default); + + ShowExecutionPopup( + attacker != victim ? "execution-popup-gun-complete-external" : "suicide-popup-gun-complete-external", + PopupType.LargeCaution, + attacker, + victim, + weapon); + + args.Handled = true; + } + + private void ShowExecutionPopup(string locString, + PopupType type, + EntityUid attacker, + EntityUid victim, + EntityUid weapon) + { + var message = Loc.GetString(locString, + ("attacker", attacker), + ("victim", victim), + ("weapon", weapon)); + + _popupSystem.PopupEntity(message, attacker, type); + } + + private bool IsDelayed(ExecutionComponent comp) + { + return comp.NextUse > _gameTiming.CurTime; + } +} diff --git a/Content.Shared/Humanoid/HumanoidAppearanceComponent.cs b/Content.Shared/Humanoid/HumanoidAppearanceComponent.cs index 52d9704230..2e0f04b41f 100644 --- a/Content.Shared/Humanoid/HumanoidAppearanceComponent.cs +++ b/Content.Shared/Humanoid/HumanoidAppearanceComponent.cs @@ -1,6 +1,7 @@ using Content.Shared.Humanoid.Markings; using Content.Shared.Humanoid.Prototypes; using Content.Shared._White.TTS; +using Content.Shared.StatusIcon; using Robust.Shared.Enums; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -101,6 +102,10 @@ public sealed partial class HumanoidAppearanceComponent : Component /// [DataField] public HashSet HideLayersOnEquip = [HumanoidVisualLayers.Hair]; + + // Parsec + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId DeadWithoutMindIcon = "DeadWithoutMindIcon"; } [DataDefinition] @@ -127,4 +132,4 @@ public readonly partial struct CustomBaseLayerInfo /// [DataField] public Color? Color { get; init; } -} \ No newline at end of file +} diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index 3e53ab6ec7..9f3b0c6d24 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -1,4 +1,5 @@ using Content.Shared._White.BuffedFlashGrenade; +using Content.Shared._White.DeadWithoutMind; using Content.Shared._White.Events; using Content.Shared._White.StaminaProtection; using Content.Shared.Changeling; @@ -56,6 +57,7 @@ public partial class InventorySystem SubscribeLocalEvent>(RelayInventoryEvent); SubscribeLocalEvent>(RelayInventoryEvent); SubscribeLocalEvent>(RelayInventoryEvent); + SubscribeLocalEvent>(RelayInventoryEvent); // Parsec SubscribeLocalEvent>(OnGetEquipmentVerbs); } diff --git a/Content.Shared/Mobs/Components/MobStateComponent.cs b/Content.Shared/Mobs/Components/MobStateComponent.cs index 7cff0779cb..fd37bf8cce 100644 --- a/Content.Shared/Mobs/Components/MobStateComponent.cs +++ b/Content.Shared/Mobs/Components/MobStateComponent.cs @@ -1,7 +1,6 @@ using Content.Shared.Damage; using Content.Shared.Mobs.Systems; using Robust.Shared.GameStates; -using Robust.Shared.Serialization; namespace Content.Shared.Mobs.Components { diff --git a/Content.Server/_White/Cult/TimedProduction/CultistFactoryComponent.cs b/Content.Shared/_White/Cult/Components/CultistFactoryComponent.cs similarity index 76% rename from Content.Server/_White/Cult/TimedProduction/CultistFactoryComponent.cs rename to Content.Shared/_White/Cult/Components/CultistFactoryComponent.cs index a5ef56eca2..dee0ee474b 100644 --- a/Content.Server/_White/Cult/TimedProduction/CultistFactoryComponent.cs +++ b/Content.Shared/_White/Cult/Components/CultistFactoryComponent.cs @@ -1,12 +1,11 @@ -using Content.Server.UserInterface; -using Content.Shared._White.Cult; -using Content.Shared._White.Cult.UI; -using Robust.Server.GameObjects; +using Content.Shared._White.Cult.UI; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; -namespace Content.Server._White.Cult.TimedProduction; +namespace Content.Shared._White.Cult.Components; -[RegisterComponent] +[RegisterComponent, NetworkedComponent] public sealed partial class CultistFactoryComponent : Component { [ViewVariables(VVAccess.ReadOnly)] diff --git a/Content.Shared/_White/DeadWithoutMind/ShowDeadWithoutMindComponent.cs b/Content.Shared/_White/DeadWithoutMind/ShowDeadWithoutMindComponent.cs new file mode 100644 index 0000000000..2c92c6a399 --- /dev/null +++ b/Content.Shared/_White/DeadWithoutMind/ShowDeadWithoutMindComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._White.DeadWithoutMind; + +/// +/// PARSEC. This component adds hud to see no mind dead players. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class ShowDeadWithoutMindComponent : Component +{ +} diff --git a/Content.Shared/_White/Executions/DoafterEvent.cs b/Content.Shared/_White/Executions/DoafterEvent.cs new file mode 100644 index 0000000000..56adb08aed --- /dev/null +++ b/Content.Shared/_White/Executions/DoafterEvent.cs @@ -0,0 +1,9 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared._White.Executions; + +[Serializable, NetSerializable] +public sealed partial class ExecutionDoAfterEvent : SimpleDoAfterEvent +{ +} diff --git a/Content.Shared/_White/Executions/ExecutionComponent.cs b/Content.Shared/_White/Executions/ExecutionComponent.cs new file mode 100644 index 0000000000..bb0e3a5398 --- /dev/null +++ b/Content.Shared/_White/Executions/ExecutionComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._White.Executions; + +[RegisterComponent, NetworkedComponent] +public sealed partial class ExecutionComponent : Component +{ + [DataField] + public bool Enabled = true; + + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan NextAttempt = TimeSpan.FromSeconds(3); + + [ViewVariables(VVAccess.ReadOnly)] + public TimeSpan NextUse = TimeSpan.Zero; +} diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index bea04aa0d3..d2ad87bb46 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -1,65 +1,4 @@ Entries: -- author: Aviu - changes: - - message: "\u0421\u0432\u044F\u0442\u0430\u044F \u0432\u043E\u0434\u0430 \u0442\ - \u0435\u043F\u0435\u0440\u044C \u0443\u0442\u043E\u043B\u044F\u0435\u0442 \u0436\ - \u0430\u0436\u0434\u0443, \u0438\u0441\u043F\u0430\u0440\u044F\u0435\u0442\u0441\ - \u044F, \u0438 \u043D\u0430 \u043D\u0435\u0439 \u043C\u043E\u0436\u043D\u043E\ - \ \u043F\u043E\u0441\u043A\u043E\u043B\u044C\u0437\u043D\u0443\u0442\u044C\u0441\ - \u044F." - type: Fix - - message: "\u0420\u0443\u043D\u044B \u0432\u043D\u043E\u0432\u044C \u0441\u0442\ - \u0438\u0440\u0430\u044E\u0442\u0441\u044F \u0431\u0438\u0431\u043B\u0438\u0435\ - \u0439 \u0438 \u0431\u0440\u044B\u0437\u0433\u0430\u043D\u044C\u0435\u043C \u0441\ - \u0432\u044F\u0442\u043E\u0439 \u0432\u043E\u0434\u043E\u0439." - type: Fix - id: 174 - time: '2024-03-02T09:08:32.0000000+00:00' - url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/159 -- author: Aviu - changes: - - message: "\u0421\u043A\u0435\u043B\u0435\u0442 \u0438\u0437 \u0448\u043A\u0430\ - \u0444\u0430 \u0442\u0435\u043F\u0435\u0440\u044C \u0432\u044B\u0433\u043B\u044F\ - \u0434\u0438\u0442 \u043A\u0430\u043A \u0441\u043A\u0435\u043B\u0435\u0442." - type: Fix - id: 175 - time: '2024-03-02T09:10:00.0000000+00:00' - url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/160 -- author: Remuchi - changes: - - message: "\u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B \u043E\u0442\ - \u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F \u0430\u043D\u0442\u0430\ - \u0436\u043A\u0438, \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0438 \u043F\ - \u043E\u0434\u043E\u0431\u043D\u043E\u0433\u043E \u0432 \u0430\u0445\u0435\u043B\ - \u043F\u0435." - type: Fix - - message: "\u043D\u043E\u0442\u0435\u0441\u044B, \u043E\u0442\u043F\u0440\u0430\ - \u0432\u043B\u044F\u0435\u043C\u044B\u0435 \u0432 \u0447\u0430\u0442, \u0431\ - \u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\ - \u043B\u044F\u044E\u0442\u0441\u044F \u0435\u0449\u0451 \u0438 \u0432 \u043A\ - \u043E\u043D\u0441\u043E\u043B\u044C." - type: Fix - - message: "\u0442\u0435\u043A\u0441\u0442\u0443\u0440\u0430 \u0441\u0435\u043A\u0440\ - \u0435\u0442\u043D\u043E\u0439 \u0434\u0432\u0435\u0440\u0438 \u0431\u044B\u043B\ - \u0430 \u043F\u0435\u0440\u0435\u0440\u0438\u0441\u043E\u0432\u0430\u043D\u0430\ - \ \u0434\u043B\u044F \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\ - \u0438\u044F \u0441 \u0430\u043A\u0442\u0443\u0430\u043B\u044C\u043D\u044B\u043C\ - \u0438 \u0442\u0435\u043A\u0441\u0442\u0443\u0440\u0430\u043C\u0438 \u0441\u0442\ - \u0435\u043D" - type: Fix - - message: "\u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B \u043E\u0448\ - \u0438\u0431\u043A\u0438 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u043F\ - \u0440\u0438 \u0432\u044B\u043B\u0438\u0437\u044B\u0432\u0430\u043D\u0438\u0438\ - \ \u0440\u0430\u043D \u0437\u0430 \u0444\u0435\u043B\u0438\u043D\u0438\u0434\ - \u0430" - type: Fix - - message: "\u043F\u0435\u0440\u0435\u0432\u043E\u0434\u044B \u0434\u043B\u044F\ - \ \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u043E\u0439 \u0434\u0432\u0435\u0440\ - \u0438" - type: Add - id: 176 - time: '2024-03-02T14:16:27.0000000+00:00' - url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/161 - author: Remuchi changes: - message: "\u0418\u043C\u043F\u043B\u0430\u043D\u0442 \u043F\u043E\u0434\u0447\u0438\ @@ -9079,3 +9018,56 @@ id: 673 time: '2025-04-03T17:50:03.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/942 +- author: CaypenNow + changes: + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0432 \u043C\u0435\u0434\u0438\ + \u0446\u0438\u043D\u0441\u043A\u043E\u043C \u0432\u0438\u0437\u043E\u0440\u0435\ + \ \u0435\u0441\u0442\u044C \u0441\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\ + \u0430\u044F \u0432\u0438\u0437\u0443\u0430\u043B\u044C\u043D\u0430\u044F \u043F\ + \u043E\u043C\u0435\u0442\u043A\u0430, \u0432 \u0441\u043B\u0443\u0447\u0430\u0435\ + \ \u0435\u0441\u043B\u0438 \u0447\u0435\u043B\u043E\u0432\u0435\u043A \u043C\ + \u0435\u0440\u0442\u0432 \u0438 \u0432 \u043D\u0435\u043C \u043D\u0435\u0442\ + \ \u0434\u0443\u0448\u0438." + type: Add + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u043C\u043E\u0436\u043D\u043E\ + \ \u043F\u0440\u0438\u0432\u044F\u0437\u0430\u0442\u044C \u0434\u0432\u0438\u0433\ + \u0430\u0442\u0435\u043B\u0438 \u0448\u0430\u0442\u0442\u043B\u043E\u0432 \u043A\ + \ \u043F\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043A\u0443 \u0441\u0438\ + \u0433\u043D\u0430\u043B\u043E\u0432 \u0438 \u043A\u043D\u043E\u043F\u043A\u0430\ + \u043C." + type: Add + - message: "\u0417\u0430\u0449\u0438\u0442\u0430 \u0438 \u043C\u043E\u0434\u0438\ + \u0444\u0438\u043A\u0430\u0442\u043E\u0440\u044B \u0441\u043A\u043E\u0440\u043E\ + \u0441\u0442\u0438 \u0441\u043A\u0430\u0444\u0430\u043D\u0434\u0440\u0430 \u0413\ + \u0421\u0411 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u044B." + type: Tweak + id: 674 + time: '2025-04-13T11:46:23.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/934 +- author: CaypenNow + changes: + - message: "\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D \u043A\u0443\u043B\ + \u044C\u0442. \u041F\u043E\u043A\u0430 \u0432 \u0442\u0435\u0441\u0442\u043E\ + \u0432\u043E\u043C \u0440\u0435\u0436\u0438\u043C\u0435." + type: Add + - message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0449\u0438\u0442 \u043A\u0443\ + \u043B\u044C\u0442\u0430 \u043F\u0440\u043E\u043B\u0435\u0442\u0430\u0435\u0442\ + \ \u0441\u043A\u0432\u043E\u0437\u044C \u043C\u0430\u043B\u0435\u043D\u044C\u043A\ + \u0438\u0445 \u0436\u0438\u0432\u043E\u0442\u043D\u044B\u0445 (\u043C\u044B\u0448\ + \u0438, \u043A\u0440\u044B\u0441\u044B)." + type: Tweak + id: 675 + time: '2025-04-13T11:46:00.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/944 +- author: CaypenNow + changes: + - message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0430 \u0432\u043E\u0437\ + \u043C\u043E\u0436\u043D\u043E\u0441\u0442\u044C \u043A\u0430\u0437\u043D\u0438\ + \u0442\u044C/\u0441\u0430\u043C\u043E\u0443\u0431\u0438\u0439\u0442\u044C\u0441\ + \u044F \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u0431\u043B\u0438\u0436\ + \u043D\u0435\u0433\u043E/\u043E\u0433\u043D\u0435\u0441\u0442\u0440\u0435\u043B\ + \u044C\u043D\u043E\u0433\u043E \u043E\u0440\u0443\u0436\u0438\u044F." + type: Add + id: 676 + time: '2025-04-13T12:32:46.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/932 diff --git a/Resources/Locale/ru-RU/_white/executions/execution.ftl b/Resources/Locale/ru-RU/_white/executions/execution.ftl new file mode 100644 index 0000000000..6602cf4ad3 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/executions/execution.ftl @@ -0,0 +1,13 @@ +execution-verb-name = Казнить +execution-verb-message = Казнить кого-либо при помощи вашего оружия. + +execution-popup-gun-initial-external = {$attacker} приставляет {$weapon} к голове {$victim}. +execution-popup-gun-complete-external = {$attacker} стреляет в голову {$victim}! +execution-popup-gun-clumsy-external = {$attacker} промахивается в {$victim} и стреляет в себя! +execution-popup-gun-empty = {CAPITALIZE($weapon)} щелкает. +suicide-popup-gun-initial-external = {$attacker} направляет ствол {$weapon} в свой рот. +suicide-popup-gun-complete-external = {$attacker} стреляет {REFLEXIVE($attacker)} себе в голову! +execution-popup-melee-initial-external = {$attacker} приставляет {$weapon} к горлу {$victim}. +execution-popup-melee-complete-external = {$attacker} перерезает горло {$victim}! +suicide-popup-melee-initial-external = {$attacker} приставляет {$weapon} к своему горлу. +suicide-popup-melee-complete-external = {$attacker} перерезает себе горло с помощью {$weapon}! diff --git a/Resources/Locale/ru-RU/devices/device-network.ftl b/Resources/Locale/ru-RU/devices/device-network.ftl index 5aed1f43a3..0391703cca 100644 --- a/Resources/Locale/ru-RU/devices/device-network.ftl +++ b/Resources/Locale/ru-RU/devices/device-network.ftl @@ -5,6 +5,8 @@ device-frequency-prototype-name-crew-monitor = Отслеживатель эки device-frequency-prototype-name-lights = Умное освещение device-frequency-prototype-name-mailing-units = Почтовый блок device-frequency-prototype-name-pdas = ПДА +# Thrusters | Parsec +device-frequency-prototype-name-thrusters = Двигатели # prefixes for randomly generated device addresses device-address-prefix-vent = Вент- device-frequency-prototype-name-basic-device = Простые устройства diff --git a/Resources/Locale/ru-RU/execution/execution.ftl b/Resources/Locale/ru-RU/execution/execution.ftl deleted file mode 100644 index 1ecb239348..0000000000 --- a/Resources/Locale/ru-RU/execution/execution.ftl +++ /dev/null @@ -1,30 +0,0 @@ -execution-verb-name = Казнить -execution-verb-message = Казнить кого-либо при помощи вашего оружия. - -# All the below localisation strings have access to the following variables -# attacker (the person committing the execution) -# victim (the person being executed) -# weapon (the weapon used for the execution) - -execution-popup-gun-initial-internal = Вы направляете ствол {$weapon} на голову {$victim}. -execution-popup-gun-initial-external = {$attacker} направляет ствол {$weapon} на голову {$victim}. -execution-popup-gun-complete-internal = Вы выстреливаете в голову {$victim}! -execution-popup-gun-complete-external = {$attacker} выстреливает в голову {$victim}! -execution-popup-gun-clumsy-internal = Вы промахиваетесь мимо головы {$victim} и стреляете себе в ногу! -execution-popup-gun-clumsy-external = {$attacker} промахивается мимо головы {$victim} и стреляет в {POSS-ADJ($attacker)} ногу! -execution-popup-gun-empty = {CAPITALIZE($weapon)} щёлкает. - -suicide-popup-gun-initial-internal = Вы суёте ствол {$weapon} себе в рот. -suicide-popup-gun-initial-external = {$attacker} суёт ствол {$weapon} в {POSS-ADJ($attacker)} рот. -suicide-popup-gun-complete-internal = Вы стреляете себе в голову! -suicide-popup-gun-complete-external = {$attacker} стреляет {REFLEXIVE($attacker)} себе в голову! - -execution-popup-melee-initial-internal = Вы заносите {$weapon} над горлом {$victim}. -execution-popup-melee-initial-external = {$attacker} заносит {POSS-ADJ($attacker)} {$weapon} над горлом {$victim}. -execution-popup-melee-complete-internal = Вы перерезаете горло {$victim}! -execution-popup-melee-complete-external = {$attacker} перерезает горло {$victim}! - -suicide-popup-melee-initial-internal = Вы заносите {$weapon} над своим горлом. -suicide-popup-melee-initial-external = {$attacker} заносит {POSS-ADJ($attacker)} {$weapon} над горлом {POSS-ADJ($attacker)}. -suicide-popup-melee-complete-internal = Вы перерезаете себе горло при помощи {$weapon}! -suicide-popup-melee-complete-external = {$attacker} перерезает горло {POSS-ADJ($attacker)} при помощи {$weapon}! diff --git a/Resources/Prototypes/Device/devicenet_frequencies.yml b/Resources/Prototypes/Device/devicenet_frequencies.yml index c7335d942b..79dc22b678 100644 --- a/Resources/Prototypes/Device/devicenet_frequencies.yml +++ b/Resources/Prototypes/Device/devicenet_frequencies.yml @@ -131,4 +131,9 @@ - type: deviceFrequency id: SyndicateMessagesClient name: device-frequency-prototype-name-syndicate-messages-client - frequency: 2793 \ No newline at end of file + frequency: 2793 +# PARSEC +- type: deviceFrequency + id: Thruster #used by thrusters + name: device-frequency-prototype-name-thrusters + frequency: 1512 diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml b/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml index 26e434a2a8..67ad3fa2ee 100644 --- a/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml +++ b/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml @@ -12,6 +12,7 @@ abstract: true noSpawn: true components: + - type: ShowDeadWithoutMind - type: ShowHealthBars damageContainers: - Biological diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml index 9ac7f14d65..ba28256176 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml @@ -411,14 +411,15 @@ - type: Armor modifiers: coefficients: - Blunt: 0.6 - Slash: 0.5 - Piercing: 0.5 + Blunt: 0.55 + Slash: 0.55 + Piercing: 0.6 Radiation: 0.5 - Caustic: 0.6 + Caustic: 0.5 + Heat: 0.6 - type: ClothingSpeedModifier - walkModifier: 0.8 - sprintModifier: 0.8 + walkModifier: 0.9 + sprintModifier: 0.9 - type: HeldSpeedModifier - type: ToggleableClothing clothingPrototype: ClothingHeadHelmetHardsuitSecurityRed diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index f3b82cb06a..b759ca0662 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -89,6 +89,7 @@ - type: ShowRevIcons - type: ShowZombieIcons - type: ShowCultHud + - type: ShowDeadWithoutMind - type: Inventory templateId: aghost - type: InventorySlots diff --git a/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml b/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml index fa8b382ade..f003475ac8 100644 --- a/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml +++ b/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml @@ -35,6 +35,16 @@ - type: InteractionOutline - type: Sprite - type: Appearance + - type: DeviceNetwork # Parsec + deviceNetId: Wireless + receiveFrequencyId: Thruster + - type: WirelessNetworkConnection # Parsec + range: 200 + - type: DeviceLinkSink # Parsec + ports: + - Toggle + - On + - Off - type: ThrusterVisuals - type: ApcPowerReceiver powerLoad: 1500 diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index 8880128276..d52404cf6c 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -274,7 +274,7 @@ noSpawn: true components: - type: GameRule - minPlayers: 30 # Amour + minPlayers: 20 - type: CultRule - type: AntagSelection definitions: diff --git a/Resources/Prototypes/StatusIcon/antag.yml b/Resources/Prototypes/StatusIcon/antag.yml index 0dbdfce4f9..77c6e37278 100644 --- a/Resources/Prototypes/StatusIcon/antag.yml +++ b/Resources/Prototypes/StatusIcon/antag.yml @@ -43,3 +43,13 @@ icon: sprite: /Textures/Interface/Misc/job_icons.rsi state: Syndicate +# Parsec +- type: statusIcon + id: DeadWithoutMindIcon + priority: 10 + locationPreference: Left + layer: Mod + isShaded: true + icon: + sprite: /Textures/Interface/Misc/job_icons.rsi + state: DeadWithoutMind diff --git a/Resources/Prototypes/_White/Entities/Cult/Altars/cult_altars.yml b/Resources/Prototypes/_White/Entities/Cult/Altars/cult_altars.yml index 4a9cbabb8a..1c72dbd202 100644 --- a/Resources/Prototypes/_White/Entities/Cult/Altars/cult_altars.yml +++ b/Resources/Prototypes/_White/Entities/Cult/Altars/cult_altars.yml @@ -121,6 +121,8 @@ - FactoryCultShuttleCurse - FactoryCultClothingBlindfold - FactoryCultVeilShifter + - type: ActivatableUI + key: enum.CultistAltarUiKey.Key - type: UserInterface interfaces: enum.CultistAltarUiKey.Key: @@ -180,6 +182,8 @@ products: - FactoryWhetstone - FactoryConstructShell + - type: ActivatableUI + key: enum.CultistAltarUiKey.Key - type: UserInterface interfaces: enum.CultistAltarUiKey.Key: @@ -243,6 +247,8 @@ - FactoryUnholyHalberd - FactoryCultRobeModify - FactoryCultMirrorShield + - type: ActivatableUI + key: enum.CultistAltarUiKey.Key - type: UserInterface interfaces: enum.CultistAltarUiKey.Key: diff --git a/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml b/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml index fce7e0adae..0f5e6c3fa5 100644 --- a/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml +++ b/Resources/Prototypes/_White/Ghosts/custom_ghosts.yml @@ -141,11 +141,11 @@ size: 0.8, 0.8 - type: customGhost - id: hitpanda-ghost - ckey: hitpanda + id: caypennow-ghost + ckey: CaypenNow sprite: White/Ghosts/hitpanda_ghost.rsi alpha: 0.8 - ghostName: Панда + ghostName: Undefined ghostDescription: Полыхает... size: 1, 1 diff --git a/Resources/Prototypes/game_presets.yml b/Resources/Prototypes/game_presets.yml index e5f5ec24f3..f08e58e1d5 100644 --- a/Resources/Prototypes/game_presets.yml +++ b/Resources/Prototypes/game_presets.yml @@ -173,20 +173,20 @@ - BasicRoundstartVariation #WD EDIT START -# - type: gamePreset -# id: Cult -# alias: -# - cult -# name: cult-title -# description: cult-description -# showInVote: true -# minPlayers: 20 -# rules: -# - Cult -# - SubGamemodesRule -# - BasicStationEventScheduler -# - BasicRoundstartVariation -# - GameRuleMeteorScheduler +- type: gamePreset + id: Cult + alias: + - cult + name: cult-title + description: cult-description + showInVote: true + minPlayers: 20 + rules: + - Cult + - SubGamemodesRule + - BasicStationEventScheduler + - BasicRoundstartVariation + - GameRuleMeteorScheduler - type: gamePreset id: Changeling @@ -313,4 +313,18 @@ - BasicStationEventScheduler - BasicRoundstartVariation - GameRuleMeteorScheduler + +- type: gamePreset + id: SecretCult #For Admin Use: Runs Cult, but shows "Secret" in lobby. + alias: + - secretcult + name: secret-title + showInVote: false #Admin Use + description: secret-description + rules: + - Cult + - SubGamemodesRule + - BasicStationEventScheduler + - BasicRoundstartVariation + - GameRuleMeteorScheduler #WD EDIT END diff --git a/Resources/Prototypes/secret_weights.yml b/Resources/Prototypes/secret_weights.yml index 8405b4fc12..d38a7f9f75 100644 --- a/Resources/Prototypes/secret_weights.yml +++ b/Resources/Prototypes/secret_weights.yml @@ -4,7 +4,7 @@ Traitor: 0.35 Changeling: 0.14 Nukeops: 0.14 - # Cult: 0.15 + Cult: 0.15 Wizard: 0.09 Revolutionary: 0.1 Zombie: 0.09 diff --git a/Resources/Textures/Interface/Misc/job_icons.rsi/DeadWithoutMind.png b/Resources/Textures/Interface/Misc/job_icons.rsi/DeadWithoutMind.png new file mode 100644 index 0000000000..ae8e8724c0 Binary files /dev/null and b/Resources/Textures/Interface/Misc/job_icons.rsi/DeadWithoutMind.png differ diff --git a/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json b/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json index ef949a1ded..d30437c97e 100644 --- a/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json +++ b/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json @@ -180,6 +180,9 @@ [1.0,1.0] ] }, + { + "name": "DeadWithoutMind" + }, { "name": "Syndicate" },