Предательский нож (#112)
* - add: Add betrayal knife. * - tweak: Small size.
This commit is contained in:
@@ -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<BlinkComponent>(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;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,8 @@ public sealed class MeleeHitEvent : HandledEntityEventArgs
|
||||
/// </remarks>
|
||||
public bool IsHit = true;
|
||||
|
||||
public bool PenetrateArmor = false;
|
||||
|
||||
public MeleeHitEvent(List<EntityUid> hitEntities, EntityUid user, EntityUid weapon, DamageSpecifier baseDamage, Vector2? direction)
|
||||
{
|
||||
HitEntities = hitEntities;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
14
Content.Shared/_White/BetrayalDagger/BackstabComponent.cs
Normal file
14
Content.Shared/_White/BetrayalDagger/BackstabComponent.cs
Normal file
@@ -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);
|
||||
}
|
||||
56
Content.Shared/_White/BetrayalDagger/BackstabSystem.cs
Normal file
56
Content.Shared/_White/BetrayalDagger/BackstabSystem.cs
Normal file
@@ -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<BackstabComponent, MeleeHitEvent>(HandleHit);
|
||||
}
|
||||
|
||||
private void HandleHit(Entity<BackstabComponent> ent, ref MeleeHitEvent args)
|
||||
{
|
||||
if (args.HitEntities.Count != 1)
|
||||
return;
|
||||
|
||||
var target = args.HitEntities[0];
|
||||
|
||||
if (target == args.User || !HasComp<MobStateComponent>(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<DamageTypePrototype>("Slash"),
|
||||
damage - args.BaseDamage.GetTotal());
|
||||
|
||||
args.PenetrateArmor = ent.Comp.PenetrateArmor;
|
||||
|
||||
if (_net.IsServer)
|
||||
_popup.PopupEntity($@"Backstab! {damage}", args.User, PopupType.MediumCaution);
|
||||
}
|
||||
}
|
||||
21
Content.Shared/_White/BetrayalDagger/BlinkComponent.cs
Normal file
21
Content.Shared/_White/BetrayalDagger/BlinkComponent.cs
Normal file
@@ -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)
|
||||
};
|
||||
}
|
||||
81
Content.Shared/_White/BetrayalDagger/BlinkSystem.cs
Normal file
81
Content.Shared/_White/BetrayalDagger/BlinkSystem.cs
Normal file
@@ -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<BlinkEvent>(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<OccluderComponent>(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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 388 B |
Binary file not shown.
|
After Width: | Height: | Size: 334 B |
Binary file not shown.
|
After Width: | Height: | Size: 339 B |
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user