From 382188d2d2e8e9dfaa9ab14155b84c3706b3ed8b Mon Sep 17 00:00:00 2001 From: Aviu00 <93730715+Aviu00@users.noreply.github.com> Date: Sat, 24 Feb 2024 07:59:03 +0900 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D1=81=D0=BA=D0=B8=D0=B9=20=D0=BD=D0=BE=D0=B6=20(#1?= =?UTF-8?q?12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * - add: Add betrayal knife. * - tweak: Small size. --- .../Weapons/Melee/MeleeWeaponSystem.cs | 23 +++++ .../Weapons/Melee/Events/MeleeHitEvent.cs | 2 + .../Weapons/Melee/SharedMeleeWeaponSystem.cs | 4 +- .../BetrayalDagger/BackstabComponent.cs | 14 +++ .../_White/BetrayalDagger/BackstabSystem.cs | 56 ++++++++++++ .../_White/BetrayalDagger/BlinkComponent.cs | 21 +++++ .../_White/BetrayalDagger/BlinkSystem.cs | 81 ++++++++++++++++++ .../Objects/Weapons/Melee/daggers.yml | 26 ++++++ Resources/Prototypes/White/Catalog/uplink.yml | 17 ++++ .../Weapons/betrayal_knife.rsi/icon.png | Bin 0 -> 388 bytes .../betrayal_knife.rsi/inhand-left.png | Bin 0 -> 334 bytes .../betrayal_knife.rsi/inhand-right.png | Bin 0 -> 339 bytes .../Weapons/betrayal_knife.rsi/meta.json | 22 +++++ 13 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 Content.Shared/_White/BetrayalDagger/BackstabComponent.cs create mode 100644 Content.Shared/_White/BetrayalDagger/BackstabSystem.cs create mode 100644 Content.Shared/_White/BetrayalDagger/BlinkComponent.cs create mode 100644 Content.Shared/_White/BetrayalDagger/BlinkSystem.cs create mode 100644 Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/icon.png create mode 100644 Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/inhand-left.png create mode 100644 Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/inhand-right.png create mode 100644 Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/meta.json diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 6b454c6901..c1064f62f7 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Client.Gameplay; +using Content.Shared._White.BetrayalDagger; using Content.Shared.CombatMode; using Content.Shared.Effects; using Content.Shared.Hands.Components; @@ -129,6 +130,28 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem return; } + // WD START + if (HasComp(weaponUid)) + { + if (!_xformQuery.TryGetComponent(entity, out var userXform) || + !Timing.IsFirstTimePredicted) + { + return; + } + + var targetMap = coordinates.ToMap(EntityManager, TransformSystem); + + if (targetMap.MapId != userXform.MapID) + return; + + var userPos = TransformSystem.GetWorldPosition(userXform); + var direction = targetMap.Position - userPos; + + RaiseNetworkEvent(new BlinkEvent(GetNetEntity(weaponUid), direction)); + return; + } + // WD END + ClientHeavyAttack(entity, coordinates, weaponUid, weapon); return; } diff --git a/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs b/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs index 4186f15efc..ee42fc2553 100644 --- a/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs +++ b/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs @@ -66,6 +66,8 @@ public sealed class MeleeHitEvent : HandledEntityEventArgs /// public bool IsHit = true; + public bool PenetrateArmor = false; + public MeleeHitEvent(List hitEntities, EntityUid user, EntityUid weapon, DamageSpecifier baseDamage, Vector2? direction) { HitEntities = hitEntities; diff --git a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs index a1e6c71834..6289b9ed21 100644 --- a/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs +++ b/Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs @@ -530,7 +530,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem RaiseLocalEvent(target.Value, attackedEvent); var modifiedDamage = DamageSpecifier.ApplyModifierSets(damage + hitEvent.BonusDamage + attackedEvent.BonusDamage, hitEvent.ModifiersList); - var damageResult = Damageable.TryChangeDamage(target, modifiedDamage, component.IgnoreResistances, origin:user); // WD EDIT + var damageResult = Damageable.TryChangeDamage(target, modifiedDamage, component.IgnoreResistances || hitEvent.PenetrateArmor, origin:user); // WD EDIT if (damageResult != null && damageResult.Any()) { @@ -687,7 +687,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem RaiseLocalEvent(entity, attackedEvent); var modifiedDamage = DamageSpecifier.ApplyModifierSets(damage + hitEvent.BonusDamage + attackedEvent.BonusDamage, hitEvent.ModifiersList); - var damageResult = Damageable.TryChangeDamage(entity, modifiedDamage, component.IgnoreResistances, origin:user); // WD EDIT + var damageResult = Damageable.TryChangeDamage(entity, modifiedDamage, component.IgnoreResistances || hitEvent.PenetrateArmor, origin:user); // WD EDIT if (damageResult != null && damageResult.GetTotal() > FixedPoint2.Zero) { diff --git a/Content.Shared/_White/BetrayalDagger/BackstabComponent.cs b/Content.Shared/_White/BetrayalDagger/BackstabComponent.cs new file mode 100644 index 0000000000..2b3c3e1f43 --- /dev/null +++ b/Content.Shared/_White/BetrayalDagger/BackstabComponent.cs @@ -0,0 +1,14 @@ +namespace Content.Shared._White.BetrayalDagger; + +[RegisterComponent] +public sealed partial class BackstabComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float DamageMultiplier = 2f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public bool PenetrateArmor = true; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public Angle Tolerance = Angle.FromDegrees(45d); +} diff --git a/Content.Shared/_White/BetrayalDagger/BackstabSystem.cs b/Content.Shared/_White/BetrayalDagger/BackstabSystem.cs new file mode 100644 index 0000000000..876c253216 --- /dev/null +++ b/Content.Shared/_White/BetrayalDagger/BackstabSystem.cs @@ -0,0 +1,56 @@ +using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; +using Content.Shared.Examine; +using Content.Shared.Mobs.Components; +using Content.Shared.Popups; +using Content.Shared.Weapons.Melee.Events; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; + +namespace Content.Shared._White.BetrayalDagger; + +public sealed class BackstabSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(HandleHit); + } + + private void HandleHit(Entity ent, ref MeleeHitEvent args) + { + if (args.HitEntities.Count != 1) + return; + + var target = args.HitEntities[0]; + + if (target == args.User || !HasComp(target) || + !TryComp(target, out TransformComponent? xform)) + return; + + var rot1 = _transform.GetWorldRotation(args.User).FlipPositive(); + var rot2 = _transform.GetWorldRotation(xform).FlipPositive(); + var tol = ent.Comp.Tolerance; + + if (!MathHelper.CloseTo(rot1, rot2, tol) && + !MathHelper.CloseTo(rot1, rot2 + MathHelper.TwoPi, tol) && + !MathHelper.CloseTo(rot1 + MathHelper.TwoPi, rot2, tol)) + return; + + var damage = args.BaseDamage.GetTotal() * ent.Comp.DamageMultiplier; + + args.BonusDamage = new DamageSpecifier(_prototypeManager.Index("Slash"), + damage - args.BaseDamage.GetTotal()); + + args.PenetrateArmor = ent.Comp.PenetrateArmor; + + if (_net.IsServer) + _popup.PopupEntity($@"Backstab! {damage}", args.User, PopupType.MediumCaution); + } +} diff --git a/Content.Shared/_White/BetrayalDagger/BlinkComponent.cs b/Content.Shared/_White/BetrayalDagger/BlinkComponent.cs new file mode 100644 index 0000000000..faa2f8eb3f --- /dev/null +++ b/Content.Shared/_White/BetrayalDagger/BlinkComponent.cs @@ -0,0 +1,21 @@ +using Robust.Shared.Audio; + +namespace Content.Shared._White.BetrayalDagger; + +[RegisterComponent] +public sealed partial class BlinkComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float Distance = 5f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float BlinkRate = 1f; + + public TimeSpan NextBlink; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier BlinkSound = new SoundPathSpecifier("/Audio/Magic/blink.ogg") + { + Params = AudioParams.Default.WithVolume(5f) + }; +} diff --git a/Content.Shared/_White/BetrayalDagger/BlinkSystem.cs b/Content.Shared/_White/BetrayalDagger/BlinkSystem.cs new file mode 100644 index 0000000000..6bcd682b19 --- /dev/null +++ b/Content.Shared/_White/BetrayalDagger/BlinkSystem.cs @@ -0,0 +1,81 @@ +using System.Numerics; +using Content.Shared.Mobs.Components; +using Content.Shared.Physics; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Systems; +using Robust.Shared.Serialization; +using Robust.Shared.Timing; +using Robust.Shared.Utility; + +namespace Content.Shared._White.BetrayalDagger; + +public sealed class BlinkSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeAllEvent(OnBlink); + } + + private void OnBlink(BlinkEvent msg, EntitySessionEventArgs args) + { + if (args.SenderSession.AttachedEntity == null) + return; + + var user = args.SenderSession.AttachedEntity.Value; + + if (!TryComp(user, out TransformComponent? xform)) + return; + + if (!TryComp(GetEntity(msg.Weapon), out BlinkComponent? blink)) + return; + + if (blink.NextBlink > _timing.CurTime) + return; + + var blinkRate = TimeSpan.FromSeconds(1f / blink.BlinkRate); + + blink.NextBlink = _timing.CurTime + blinkRate; + + var coords = _transform.GetWorldPosition(xform); + var dir = msg.Direction.Normalized(); + var range = blink.Distance; + + var ray = new CollisionRay(coords, dir, (int) CollisionGroup.Opaque); + var rayResults = _physics.IntersectRayWithPredicate(xform.MapID, ray, range, + x => x == user || !HasComp(x)).FirstOrNull(); + + Vector2 targetPos; + if (rayResults != null) + { + targetPos = rayResults.Value.HitPos - dir; + } + else + { + targetPos = coords + (msg.Direction.Length() > range ? dir * range : msg.Direction); + } + + _transform.SetWorldPosition(user, targetPos); + _audio.PlayPvs(blink.BlinkSound, user); + } +} + +[Serializable, NetSerializable] +public sealed class BlinkEvent : EntityEventArgs +{ + public readonly NetEntity Weapon; + public readonly Vector2 Direction; + + public BlinkEvent(NetEntity weapon, Vector2 direction) + { + Weapon = weapon; + Direction = direction; + } +} diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/daggers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/daggers.yml index ce67743443..639dcea520 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/daggers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/daggers.yml @@ -8,6 +8,8 @@ sprite: Objects/Weapons/Melee/blood_dagger.rsi state: icon - type: MeleeWeapon + wideAnimationRotation: 135 + swingLeft: true attackRate: 1.3 damage: types: @@ -25,3 +27,27 @@ critChance: 40 critMultiplier: 2 isBloodDagger: true + +- type: entity + name: предательский нож + description: Берегите спину. + parent: BaseItem + id: BetrayalKnife + components: + - type: Sharp + - type: Sprite + sprite: White/Objects/Weapons/betrayal_knife.rsi + state: icon + - type: MeleeWeapon + wideAnimationRotation: 180 + attackRate: 1 + damage: + types: + Slash: 30 + soundHit: + path: /Audio/Weapons/bladeslice.ogg + - type: Item + size: Small + - type: DisarmMalus + - type: Backstab + - type: Blink diff --git a/Resources/Prototypes/White/Catalog/uplink.yml b/Resources/Prototypes/White/Catalog/uplink.yml index d2be787c1b..38cceb5a44 100644 --- a/Resources/Prototypes/White/Catalog/uplink.yml +++ b/Resources/Prototypes/White/Catalog/uplink.yml @@ -112,6 +112,23 @@ # - UplinkWeapons # saleLimit: 1 +- type: listing + id: UplinkBetrayalKnife + name: Предательский нож + description: Предательский нож позволяет пользователю телепортироваться на короткое расстояние, а также наносит значительные повреждения, пробивая броню противника, при ударе в спину. + icon: { sprite: /Textures/White/Objects/Weapons/betrayal_knife.rsi, state: icon } + productEntity: BetrayalKnife + cost: + Telecrystal: 10 + categories: + - UplinkWeapons + conditions: + - !type:StoreWhitelistCondition + blacklist: + tags: + - NukeOpsUplink + saleLimit: 1 + - type: listing id: UplinkMagazineShotgun name: uplink-magazine-bulldog-name diff --git a/Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/icon.png b/Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..99d2f8453fedf5d41eb8e52e62f935713ca808be GIT binary patch literal 388 zcmV-~0ek+5P)-Rm=OUWB@?0}mvDFbt0vi_zr* iQ4~p8mTh~?Bk&JE#)-0qoticP0000;TVCQh)P!ecjs0j&Hk3BPsq1N}r-t^eIU#cyx z_r*W*G*qxT*f1;1V-z^g(2>q?#F*icac_%&gxmdKI;Vst0M-S0yZ`_I literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/inhand-right.png b/Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8fff278de291f0f3e7baeac1dfb440fcf0cd0bbe GIT binary patch literal 339 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|O(g zr;B4q#hkadF7moKh`2qB-_&mv(7+_JfSFapMUX47!R|_m@ub?rT**TJisj5V720$1 z7uy^0Gt6XfIK%Alj8Wk;!-PtP6E+Mfatzt_e1{FT=gxkq`u6N*u7K-bvjq;xB+gqK z#@My!#Inp;^ZNwe?bkV-I&W>Z*?q>)(A38k=W6etkG*cor+BA)-t*Hk)z{zdW0}3I z^3H?(eRd}Mm~dExD%|lieWU;6;5mNo%sX(UBa|JT=%{e?@^XR-osSS&te@Ne5 u?f=loq3da<^>>jUToBhn4cW~8gXzwV;B@b6ED69+V(@hJb6Mw<&;$V4#D1{= literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/meta.json b/Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/meta.json new file mode 100644 index 0000000000..0b2fd88c33 --- /dev/null +++ b/Resources/Textures/White/Objects/Weapons/betrayal_knife.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/pull/49264/commits/d0dffe7ca643db2624424fdcebf45863f85c0448", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +}