diff --git a/Content.Server/_White/RandomArtifacts/RandomArtifactsSystem.cs b/Content.Server/_White/RandomArtifacts/RandomArtifactsSystem.cs index 69053520ad..f97fd93f9a 100644 --- a/Content.Server/_White/RandomArtifacts/RandomArtifactsSystem.cs +++ b/Content.Server/_White/RandomArtifacts/RandomArtifactsSystem.cs @@ -23,7 +23,7 @@ public sealed class RandomArtifactsSystem : EntitySystem [Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly IComponentFactory _componentFactory = default!; - private float _itemToArtifactRatio; // from 0 to 100. In % percents. Default is 0.4% + private float _itemToArtifactRatio; // from 0 to 100. In % percents. Default is 0.5% private bool _artifactsEnabled; public override void Initialize() @@ -76,7 +76,7 @@ public sealed class RandomArtifactsSystem : EntitySystem continue; // var artifactComponent = EnsureComp(entity); - var comp = (ArtifactComponent) _componentFactory.GetComponent("Artifact"); + var comp = (ArtifactComponent)_componentFactory.GetComponent("Artifact"); comp.Owner = entity; _artifactsSystem.SafeRandomizeArtifact(entity, ref comp); AddComp(entity, comp); @@ -88,7 +88,7 @@ public sealed class RandomArtifactsSystem : EntitySystem private HashSet GetPercentageOfHashSet(List sourceList, float percentage) { - var countToAdd = (int) Math.Round((double) sourceList.Count * percentage / 100); + var countToAdd = (int)Math.Round((double)sourceList.Count * percentage / 100); return sourceList.Where(x => !Transform(x.Owner).Anchored).Take(countToAdd).ToHashSet(); } diff --git a/Content.Server/_White/_Engi/DirectBallsHit/DirectBallsHitComponent.cs b/Content.Server/_White/_Engi/DirectBallsHit/DirectBallsHitComponent.cs new file mode 100644 index 0000000000..8c7d981789 --- /dev/null +++ b/Content.Server/_White/_Engi/DirectBallsHit/DirectBallsHitComponent.cs @@ -0,0 +1,22 @@ +using Content.Shared.Standing.Systems; + +namespace Content.Server._White._Engi.DirectBallsHit; + +[RegisterComponent] +public sealed partial class DirectBallsHitComponent : Component +{ + [DataField] + public TimeSpan KnockdownTime = TimeSpan.FromSeconds(2.0f); + + [DataField] + public TimeSpan JitterTime = TimeSpan.FromSeconds(2.0f); + + [DataField] + public TimeSpan StutterTime = TimeSpan.FromSeconds(2.0f); + + [DataField] + public SharedStandingStateSystem.DropHeldItemsBehavior KnockDownBehavior = SharedStandingStateSystem.DropHeldItemsBehavior.AlwaysDrop; + + [DataField] + public bool RequireWield = true; +} diff --git a/Content.Server/_White/_Engi/DirectBallsHit/DirectBallsHitSystem.cs b/Content.Server/_White/_Engi/DirectBallsHit/DirectBallsHitSystem.cs new file mode 100644 index 0000000000..49d2feb519 --- /dev/null +++ b/Content.Server/_White/_Engi/DirectBallsHit/DirectBallsHitSystem.cs @@ -0,0 +1,68 @@ +using Content.Shared.Stunnable; +using Content.Shared.Weapons.Melee.Events; +using Content.Shared.Wieldable.Components; +using Content.Shared.Jittering; +using Content.Shared.Speech.EntitySystems; +using Content.Shared.StatusEffect; +using Content.Shared.Standing; +using Content.Shared.Electrocution; +using Content.Shared.Popups; +using Content.Shared._White.Implants.NeuroControl; +using Robust.Shared.Timing; +using Content.Server.Chat.Systems; + +namespace Content.Server._White._Engi.DirectBallsHit; + +public sealed class DirectBallsHitSystem : EntitySystem +{ + [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly SharedJitteringSystem _jitter = default!; + [Dependency] private readonly SharedStutteringSystem _stutter = default!; + [Dependency] private readonly SharedElectrocutionSystem _electrocution = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly ChatSystem _chat = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnHit); + } + + private void OnHit(Entity ent, ref MeleeHitEvent args) + { + if (ent.Comp.RequireWield) + { + if (!TryComp(args.Weapon, out var weapon)) + return; + + if (!weapon.Wielded) + return; + } + + foreach (var uid in args.HitEntities) + { + _popupSystem.PopupEntity( + Loc.GetString("direct-balls-hit", ("uid", uid)), + uid, + PopupType.SmallCaution); + + Timer.Spawn(TimeSpan.FromSeconds(0.5f), () => _chat.TryEmoteWithChat(uid, "Scream")); + + if (HasComp(uid)) + { + _electrocution.TryDoElectrocution(uid, null, 30, TimeSpan.FromSeconds(1), false, 0.5f, null, true); + continue; + } + + if (TryComp(uid, out StandingStateComponent? standingState) && standingState.CanLieDown) + _stun.TryKnockdown(uid, ent.Comp.KnockdownTime, true, behavior: ent.Comp.KnockDownBehavior); + + if (TryComp(uid, out StatusEffectsComponent? statusEffects)) + { + _jitter.DoJitter(uid, ent.Comp.JitterTime, true, status: statusEffects); + _stutter.DoStutter(uid, ent.Comp.StutterTime, true, statusEffects); + } + } + } +} diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 7b3866791d..1c453c82d8 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.Database; using Content.Shared.Hands; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Events; using Content.Shared.Movement.Systems; using Content.Shared.Standing; @@ -29,6 +30,7 @@ public abstract class SharedStunSystem : EntitySystem [Dependency] private readonly SharedStandingStateSystem _standingState = default!; [Dependency] private readonly StatusEffectsSystem _statusEffect = default!; [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; // WD /// /// Friction modifier for knocked down players. @@ -117,7 +119,7 @@ public abstract class SharedStunSystem : EntitySystem if (!TryComp(uid, out StandingStateComponent? standing) || !(!standing.CanLieDown || standing.AutoGetUp)) // WD edit return; - if (standing.AutoGetUp && !_container.IsEntityInContainer(uid)) // WD edit + if (standing.AutoGetUp && !_container.IsEntityInContainer(uid) && _mobStateSystem.IsAlive(uid)) // WD edit { _standingState.TryStandUp(uid, standing); return; diff --git a/Content.Shared/_White/Item/KnockDownOnHit/KnockDownOnHitSystem.cs b/Content.Shared/_White/Item/KnockDownOnHit/KnockDownOnHitSystem.cs index 891049ae98..912d1867e3 100644 --- a/Content.Shared/_White/Item/KnockDownOnHit/KnockDownOnHitSystem.cs +++ b/Content.Shared/_White/Item/KnockDownOnHit/KnockDownOnHitSystem.cs @@ -26,17 +26,17 @@ public sealed class KnockDownOnHitSystem : EntitySystem if (time <= TimeSpan.Zero) return; + if (ent.Comp.RequireWield) + { + if (!TryComp(args.Weapon, out var weapon)) + return; + + if (!weapon.Wielded) + return; + } + foreach (var uid in args.HitEntities) { - if (ent.Comp.RequireWield) - { - if (!TryComp(args.Weapon, out var weapon)) - continue; - - if (!weapon.Wielded) - continue; - } - _stun.TryKnockdown(uid, time, true, behavior: ent.Comp.KnockDownBehavior); } } diff --git a/Content.Shared/_White/WhiteCVars.cs b/Content.Shared/_White/WhiteCVars.cs index 851d84167c..842b5524d2 100644 --- a/Content.Shared/_White/WhiteCVars.cs +++ b/Content.Shared/_White/WhiteCVars.cs @@ -418,7 +418,7 @@ public sealed class WhiteCVars CVarDef.Create("white.random_artifacts_enabled", true, CVar.SERVERONLY); public static readonly CVarDef ItemToArtifactRatio = - CVarDef.Create("white.random_artifacts_ratio", 0.4f, CVar.SERVERONLY); + CVarDef.Create("white.random_artifacts_ratio", 0.5f, CVar.SERVERONLY); public static readonly CVarDef ACWebhook = CVarDef.Create("ac.webhook", "", CVar.SERVERONLY); diff --git a/Content.Shared/_White/_Engi/Limping/LimpingComponent.cs b/Content.Shared/_White/_Engi/Limping/LimpingComponent.cs new file mode 100644 index 0000000000..67188e6325 --- /dev/null +++ b/Content.Shared/_White/_Engi/Limping/LimpingComponent.cs @@ -0,0 +1,27 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared._White._Engi.Limping; + +/// +/// WD. +/// This is used for the Limping trait. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class LimpingComponent : Component +{ + [DataField] + public float SpeedModifier = 0.3f; + +} + +[Serializable, NetSerializable] +public sealed class LimpingComponentState : ComponentState +{ + public float SpeedModifier; + + public LimpingComponentState(float speedModifier) + { + SpeedModifier = speedModifier; + } +} diff --git a/Content.Shared/_White/_Engi/Limping/LimpingHelperComponent.cs b/Content.Shared/_White/_Engi/Limping/LimpingHelperComponent.cs new file mode 100644 index 0000000000..403337d538 --- /dev/null +++ b/Content.Shared/_White/_Engi/Limping/LimpingHelperComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Shared._White._Engi.Limping; + +/// +/// WD. +/// This is used for the Limping trait to reduce it. +/// +[RegisterComponent] +public sealed partial class LimpingHelperComponent : Component +{ + +} diff --git a/Content.Shared/_White/_Engi/Limping/LimpingSystem.cs b/Content.Shared/_White/_Engi/Limping/LimpingSystem.cs new file mode 100644 index 0000000000..c16de5cfc0 --- /dev/null +++ b/Content.Shared/_White/_Engi/Limping/LimpingSystem.cs @@ -0,0 +1,80 @@ +using Content.Shared.Hands; +using Content.Shared.Movement.Systems; +using Robust.Shared.Timing; +using Robust.Shared.GameStates; +using Robust.Shared.Containers; + +namespace Content.Shared._White._Engi.Limping; + +public sealed class LimpingSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnGotEquipped); + SubscribeLocalEvent(OnGotUnequipped); + + SubscribeLocalEvent(OnRefreshMoveSpeed); + SubscribeLocalEvent(OnShutdown); + + SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnHandleState); + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + _movementSpeed.RefreshMovementSpeedModifiers(ent); + } + + private void OnRefreshMoveSpeed(EntityUid uid, LimpingComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.SpeedModifier, component.SpeedModifier); + } + + private void OnGotEquipped(Entity ent, ref GotEquippedHandEvent args) + { + if (_gameTiming.ApplyingState) + return; + + if (!TryComp(args.User, out var comp)) + return; + + if (_gameTiming.IsFirstTimePredicted) + comp.SpeedModifier = 0.5f; + + _movementSpeed.RefreshMovementSpeedModifiers(args.User); + } + + private void OnGotUnequipped(Entity ent, ref GotUnequippedHandEvent args) + { + if (!TryComp(args.User, out var comp)) + return; + + if (_gameTiming.IsFirstTimePredicted) + comp.SpeedModifier = 0.3f; + + _movementSpeed.RefreshMovementSpeedModifiers(args.User); + } + + private void OnGetState(EntityUid uid, LimpingComponent component, ref ComponentGetState args) + { + args.State = new LimpingComponentState(component.SpeedModifier); + } + + private void OnHandleState(EntityUid uid, LimpingComponent component, ref ComponentHandleState args) + { + if (args.Current is not LimpingComponentState state) + return; + + var diff = !MathHelper.CloseTo(component.SpeedModifier, state.SpeedModifier); + + if (diff && _container.TryGetContainingContainer(uid, out var container)) + { + component.SpeedModifier = state.SpeedModifier; + _movementSpeed.RefreshMovementSpeedModifiers(container.Owner); + } + } +} diff --git a/Resources/Locale/ru-RU/_Engi/direct-balls-hit.ftl b/Resources/Locale/ru-RU/_Engi/direct-balls-hit.ftl new file mode 100644 index 0000000000..08d01b81a3 --- /dev/null +++ b/Resources/Locale/ru-RU/_Engi/direct-balls-hit.ftl @@ -0,0 +1 @@ +direct-balls-hit = { CAPITALIZE($uid) } получает точный удар в пах! diff --git a/Resources/Locale/ru-RU/_white/changeling/changeling-entities.ftl b/Resources/Locale/ru-RU/_white/changeling/changeling-entities.ftl index 89f3a8eb2e..a03e0dc94c 100644 --- a/Resources/Locale/ru-RU/_white/changeling/changeling-entities.ftl +++ b/Resources/Locale/ru-RU/_white/changeling/changeling-entities.ftl @@ -81,3 +81,6 @@ ent-TentacleArmGun = рука-щупальце ent-AbsorbMoreDnaObjective = Поглотите больше людей, чем кто-либо еще в Улье .desc = Поглотите столько, сколько сможете. + +ent-ChangelingShopImplant = неестественный орган + .desc = Магазин генокрада реализован как имплант и при попытке его извлечь пусть игроки видят имя - неестественный орган. diff --git a/Resources/Locale/ru-RU/alerts/alerts.ftl b/Resources/Locale/ru-RU/alerts/alerts.ftl index eae57111eb..79d4449e29 100644 --- a/Resources/Locale/ru-RU/alerts/alerts.ftl +++ b/Resources/Locale/ru-RU/alerts/alerts.ftl @@ -91,7 +91,10 @@ alerts-pulling-name = Вы тянете alerts-pulling-desc = Вы что-то тянете. Щелкните по иконке, чтобы перестать. alerts-bleed-name = [color=red]Кровотечение[/color] -alerts-bleeding-desc = У вас [color=#C10000]кровотечение[/color], вколите [color=#3D9CBF]экстренный медипен[/color] или перебинтуйтесь. +alerts-bleed-desc = У вас [color=#C10000]кровотечение[/color], вколите [color=#3D9CBF]экстренный медипен[/color] или перебинтуйтесь. + +alerts-bleeding-name = { alerts-bleed-name } +alerts-bleeding-desc = { alerts-bleed-desc } alerts-pacified-name = [color=green]Пацифизм[/color] alerts-pacified-desc = Вы чувствуете себя умиротворенно и не можете вредить живым существам. diff --git a/Resources/Locale/ru-RU/chemistry/components/solution-scanner-component.ftl b/Resources/Locale/ru-RU/chemistry/components/solution-scanner-component.ftl index a5fa5fb2f2..37df4c8230 100644 --- a/Resources/Locale/ru-RU/chemistry/components/solution-scanner-component.ftl +++ b/Resources/Locale/ru-RU/chemistry/components/solution-scanner-component.ftl @@ -3,3 +3,4 @@ scannable-solution-verb-message = Изучить химический соста scannable-solution-main-text = Содержит следующие химикаты: scannable-solution-empty-container = Не содержит химических веществ. scannable-solution-chemical = - {$amount}ед. [color={$color}]{$type}[/color] +scannable-solution-temperature = Температура раствора: { $temperature }K diff --git a/Resources/Locale/ru-RU/damage/damage-examine.ftl b/Resources/Locale/ru-RU/damage/damage-examine.ftl index b466601c2e..8d498a2854 100644 --- a/Resources/Locale/ru-RU/damage/damage-examine.ftl +++ b/Resources/Locale/ru-RU/damage/damage-examine.ftl @@ -1,9 +1,12 @@ # Damage examines damage-examinable-verb-text = Повреждения damage-examinable-verb-message = Изучить показатели урона. + damage-hitscan = хитскан damage-projectile = снаряд damage-melee = ближний бой +damage-throw = метательное + damage-examine = Наносит следующие повреждения: damage-examine-type = Наносит следующие повреждения ({ $type }): damage-value = diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml index 9f5c32efdc..91339686d3 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml @@ -28,6 +28,7 @@ Blunt: 3 - type: UseDelay delay: 1 + - type: LimpingHelper # WD - type: entity name: cane blade diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml index 04b5dbf346..311ce36a0a 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml @@ -179,7 +179,7 @@ - type: DamageOtherOnHit damage: types: - Piercing: 10 # WD + Slash: 10 # WD - type: Sprite sprite: Clothing/Head/Hats/greyflatcap.rsi - type: Clothing diff --git a/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml b/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml index 11d85d6138..03f5c13fb8 100644 --- a/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml +++ b/Resources/Prototypes/Roles/Jobs/Justice/inspector.yml @@ -14,17 +14,28 @@ time: 36000 #10 hrs - !type:AgeRequirement requiredAge: 20 + - !type:SpeciesRequirement + species: + - Human + - Felinid + weight: 10 icon: "JobIconInspector" arrivalNotificationPrototype: InspectorArrivalNotification supervisors: job-supervisors-captain whitelistedSpecies: - Human + - Felinid + canBeAntag: true access: - Service - Lawyer - Brig - Maintenance - Command + special: + - !type:AddComponentSpecial + components: + - type: CommandStaff - type: startingGear id: InspectorGear diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index be1e981549..2cd77b880e 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -79,3 +79,14 @@ description: trait-snoring-desc components: - type: Snoring + +- type: trait # WD + id: Limping + traitGear: Cane + name: Хромота + description: Слабость в ногах мешает вам нормально передвигаться, трость может немного помочь. + blacklist: + components: + - BorgChassis + components: + - type: Limping diff --git a/Resources/Prototypes/_White/_Engi/Entities/Objects/Misc/cane.yml b/Resources/Prototypes/_White/_Engi/Entities/Objects/Misc/cane.yml new file mode 100644 index 0000000000..c73b9acaa6 --- /dev/null +++ b/Resources/Prototypes/_White/_Engi/Entities/Objects/Misc/cane.yml @@ -0,0 +1,31 @@ +- type: entity + parent: Cane + id: OldCane + name: трость старика + description: Изношенная деревянная трость. + components: + - type: MeleeWeapon + wideAnimationRotation: 45 + damage: + types: + Blunt: 5 + - type: StaminaDamageOnHit + damage: 25 + - type: Wieldable + - type: IncreaseDamageOnWield + damage: + types: + Blunt: 5 + - type: DirectBallsHit + - type: MeleeThrowOnHit + lifetime: 0.1 + speed: 3 + requireWield: true + - type: UseDelay + delay: 1 + - type: Prying + - type: Tool + qualities: + - Prying + useSound: + path: /Audio/Items/crowbar.ogg