Disarm 1984 (#8872)
This commit is contained in:
@@ -1,16 +1,20 @@
|
|||||||
using Content.Server.Actions.Events;
|
using Content.Server.Actions.Events;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
|
using Content.Server.CombatMode.Disarm;
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Weapon.Melee;
|
using Content.Server.Weapon.Melee;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.CombatMode;
|
using Content.Shared.CombatMode;
|
||||||
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.Stunnable;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Physics;
|
||||||
|
|
||||||
namespace Content.Server.CombatMode
|
namespace Content.Server.CombatMode
|
||||||
{
|
{
|
||||||
@@ -38,9 +42,17 @@ namespace Content.Server.CombatMode
|
|||||||
if (!_actionBlockerSystem.CanAttack(args.Performer))
|
if (!_actionBlockerSystem.CanAttack(args.Performer))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (TryComp<HandsComponent>(args.Performer, out var hands)
|
||||||
|
&& hands.ActiveHand != null
|
||||||
|
&& !hands.ActiveHand.IsEmpty)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("disarm-action-free-hand"), args.Performer, Filter.Entities(args.Performer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EntityUid? inTargetHand = null;
|
EntityUid? inTargetHand = null;
|
||||||
|
|
||||||
if (EntityManager.TryGetComponent<HandsComponent>(args.Target, out HandsComponent? targetHandsComponent)
|
if (TryComp<HandsComponent>(args.Target, out HandsComponent? targetHandsComponent)
|
||||||
&& targetHandsComponent.ActiveHand != null
|
&& targetHandsComponent.ActiveHand != null
|
||||||
&& !targetHandsComponent.ActiveHand.IsEmpty)
|
&& !targetHandsComponent.ActiveHand.IsEmpty)
|
||||||
{
|
{
|
||||||
@@ -64,8 +76,8 @@ namespace Content.Server.CombatMode
|
|||||||
var filterOther = filterAll.RemoveWhereAttachedEntity(e => e == args.Performer);
|
var filterOther = filterAll.RemoveWhereAttachedEntity(e => e == args.Performer);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
var chance = CalculateDisarmChance(args.Performer, args.Target, inTargetHand, component);
|
||||||
if (_random.Prob(component.DisarmFailChance))
|
if (_random.Prob(chance))
|
||||||
{
|
{
|
||||||
SoundSystem.Play(component.DisarmFailSound.GetSound(), Filter.Pvs(args.Performer), args.Performer, AudioHelpers.WithVariation(0.025f));
|
SoundSystem.Play(component.DisarmFailSound.GetSound(), Filter.Pvs(args.Performer), args.Performer, AudioHelpers.WithVariation(0.025f));
|
||||||
|
|
||||||
@@ -89,8 +101,40 @@ namespace Content.Server.CombatMode
|
|||||||
SoundSystem.Play(component.DisarmSuccessSound.GetSound(), filterAll, args.Performer, AudioHelpers.WithVariation(0.025f));
|
SoundSystem.Play(component.DisarmSuccessSound.GetSound(), filterAll, args.Performer, AudioHelpers.WithVariation(0.025f));
|
||||||
_adminLogger.Add(LogType.DisarmedAction, $"{ToPrettyString(args.Performer):user} used disarm on {ToPrettyString(args.Target):target}");
|
_adminLogger.Add(LogType.DisarmedAction, $"{ToPrettyString(args.Performer):user} used disarm on {ToPrettyString(args.Target):target}");
|
||||||
|
|
||||||
var eventArgs = new DisarmedEvent() { Target = args.Target, Source = args.Performer, PushProbability = component.DisarmPushChance };
|
var eventArgs = new DisarmedEvent() { Target = args.Target, Source = args.Performer, PushProbability = chance };
|
||||||
RaiseLocalEvent(args.Target, eventArgs);
|
RaiseLocalEvent(args.Target, eventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private float CalculateDisarmChance(EntityUid disarmer, EntityUid disarmed, EntityUid? inTargetHand, SharedCombatModeComponent disarmerComp)
|
||||||
|
{
|
||||||
|
float healthMod = 0;
|
||||||
|
if (TryComp<DamageableComponent>(disarmer, out var disarmerDamage) && TryComp<DamageableComponent>(disarmed, out var disarmedDamage))
|
||||||
|
{
|
||||||
|
// I wanted this to consider their mob state thresholds too but I'm not touching that shitcode after having a go at this.
|
||||||
|
healthMod = (((float) disarmedDamage.TotalDamage - (float) disarmerDamage.TotalDamage) / 200); // Ex. You have 0 damage, they have 90, you get a 45% chance increase
|
||||||
|
}
|
||||||
|
|
||||||
|
float massMod = 0;
|
||||||
|
|
||||||
|
if (TryComp<PhysicsComponent>(disarmer, out var disarmerPhysics) && TryComp<PhysicsComponent>(disarmed, out var disarmedPhysics))
|
||||||
|
{
|
||||||
|
if (disarmerPhysics.FixturesMass != 0) // yeah this will never happen but let's not kill the server if it does
|
||||||
|
massMod = (((disarmedPhysics.FixturesMass / disarmerPhysics.FixturesMass - 1 ) / 2)); // Ex, you weigh 120, they weigh 70, you get a 29% bonus
|
||||||
|
}
|
||||||
|
|
||||||
|
float chance = (disarmerComp.BaseDisarmFailChance - healthMod - massMod);
|
||||||
|
if (HasComp<SlowedDownComponent>(disarmer)) // might need to revisit this part after stamina damage, right now this is basically "pre-stun"
|
||||||
|
chance += 0.35f;
|
||||||
|
if (HasComp<SlowedDownComponent>(disarmed))
|
||||||
|
chance -= 0.35f;
|
||||||
|
|
||||||
|
if (inTargetHand != null && TryComp<DisarmMalusComponent>(inTargetHand, out var malus))
|
||||||
|
{
|
||||||
|
chance += malus.Malus;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.Clamp(chance, 0f, 1f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
Content.Server/CombatMode/Disarm/DisarmMalusComponent.cs
Normal file
16
Content.Server/CombatMode/Disarm/DisarmMalusComponent.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace Content.Server.CombatMode.Disarm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Applies a malus to disarm attempts against this item.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class DisarmMalusComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// So, disarm chances are a % chance represented as a value between 0 and 1.
|
||||||
|
/// This default would be a 30% penalty to that.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("malus")]
|
||||||
|
public float Malus = 0.3f;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,5 +36,8 @@ namespace Content.Server.Weapon.Melee.EnergySword
|
|||||||
|
|
||||||
[DataField("litDamageBonus", required: true)]
|
[DataField("litDamageBonus", required: true)]
|
||||||
public DamageSpecifier LitDamageBonus = default!;
|
public DamageSpecifier LitDamageBonus = default!;
|
||||||
|
|
||||||
|
[DataField("litDisarmMalus", required: true)]
|
||||||
|
public float litDisarmMalus = 0.6f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Shared.Light;
|
|||||||
using Content.Shared.Light.Component;
|
using Content.Shared.Light.Component;
|
||||||
using Content.Shared.Toggleable;
|
using Content.Shared.Toggleable;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
|
using Content.Server.CombatMode.Disarm;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
@@ -68,6 +69,11 @@ namespace Content.Server.Weapon.Melee.EnergySword
|
|||||||
item.Size = 5;
|
item.Size = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TryComp<DisarmMalusComponent>(comp.Owner, out var malus))
|
||||||
|
{
|
||||||
|
malus.Malus -= comp.litDisarmMalus;
|
||||||
|
}
|
||||||
|
|
||||||
SoundSystem.Play(comp.DeActivateSound.GetSound(), Filter.Pvs(comp.Owner, entityManager: EntityManager), comp.Owner);
|
SoundSystem.Play(comp.DeActivateSound.GetSound(), Filter.Pvs(comp.Owner, entityManager: EntityManager), comp.Owner);
|
||||||
|
|
||||||
comp.Activated = false;
|
comp.Activated = false;
|
||||||
@@ -85,6 +91,11 @@ namespace Content.Server.Weapon.Melee.EnergySword
|
|||||||
|
|
||||||
SoundSystem.Play(comp.ActivateSound.GetSound(), Filter.Pvs(comp.Owner, entityManager: EntityManager), comp.Owner);
|
SoundSystem.Play(comp.ActivateSound.GetSound(), Filter.Pvs(comp.Owner, entityManager: EntityManager), comp.Owner);
|
||||||
|
|
||||||
|
if (TryComp<DisarmMalusComponent>(comp.Owner, out var malus))
|
||||||
|
{
|
||||||
|
malus.Malus += comp.litDisarmMalus;
|
||||||
|
}
|
||||||
|
|
||||||
comp.Activated = true;
|
comp.Activated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ namespace Content.Shared.CombatMode
|
|||||||
private TargetingZone _activeZone;
|
private TargetingZone _activeZone;
|
||||||
|
|
||||||
[DataField("disarmFailChance")]
|
[DataField("disarmFailChance")]
|
||||||
public readonly float DisarmFailChance = 0.4f;
|
public readonly float BaseDisarmFailChance = 0.4f;
|
||||||
|
|
||||||
[DataField("pushChance")]
|
[DataField("pushChance")]
|
||||||
public readonly float DisarmPushChance = 0.4f;
|
public readonly float BasePushFailChance = 0.4f;
|
||||||
|
|
||||||
[DataField("disarmFailSound")]
|
[DataField("disarmFailSound")]
|
||||||
public readonly SoundSpecifier DisarmFailSound = new SoundPathSpecifier("/Audio/Weapons/punchmiss.ogg");
|
public readonly SoundSpecifier DisarmFailSound = new SoundPathSpecifier("/Audio/Weapons/punchmiss.ogg");
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
disarm-action-free-hand = You need to use a free hand to disarm!
|
||||||
|
|
||||||
disarm-action-popup-message-other-clients = {$performerName} fails to disarm {$targetName}!
|
disarm-action-popup-message-other-clients = {$performerName} fails to disarm {$targetName}!
|
||||||
disarm-action-popup-message-cursor = You fail to disarm {$targetName}!
|
disarm-action-popup-message-cursor = You fail to disarm {$targetName}!
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
Slash: 12.5
|
Slash: 12.5
|
||||||
Heat: 12.5
|
Heat: 12.5
|
||||||
Blunt: -7
|
Blunt: -7
|
||||||
|
litDisarmMalus: 0.6
|
||||||
- type: Sharp
|
- type: Sharp
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Weapons/Melee/e_sword.rsi
|
sprite: Objects/Weapons/Melee/e_sword.rsi
|
||||||
@@ -47,6 +48,8 @@
|
|||||||
right:
|
right:
|
||||||
- state: inhand-right-blade
|
- state: inhand-right-blade
|
||||||
shader: unshaded
|
shader: unshaded
|
||||||
|
- type: DisarmMalus
|
||||||
|
malus: 0
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: pen
|
name: pen
|
||||||
@@ -61,6 +64,7 @@
|
|||||||
Slash: 7.5
|
Slash: 7.5
|
||||||
Heat: 7.5
|
Heat: 7.5
|
||||||
Blunt: -1
|
Blunt: -1
|
||||||
|
litDisarmMalus: 0.4
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Weapons/Melee/e_dagger.rsi
|
sprite: Objects/Weapons/Melee/e_dagger.rsi
|
||||||
layers:
|
layers:
|
||||||
@@ -98,3 +102,5 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Write
|
- Write
|
||||||
|
- type: DisarmMalus
|
||||||
|
malus: 0
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
size: 10
|
size: 10
|
||||||
sprite: Objects/Weapons/Melee/combat_knife.rsi
|
sprite: Objects/Weapons/Melee/combat_knife.rsi
|
||||||
prefix: inhand
|
prefix: inhand
|
||||||
|
- type: DisarmMalus
|
||||||
|
malus: 0.225
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: survival knife
|
name: survival knife
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- CaptainSabre
|
- CaptainSabre
|
||||||
|
- type: DisarmMalus
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: katana
|
name: katana
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
size: 15
|
size: 15
|
||||||
sprite: Objects/Weapons/Melee/katana.rsi
|
sprite: Objects/Weapons/Melee/katana.rsi
|
||||||
|
- type: DisarmMalus
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: machete
|
name: machete
|
||||||
@@ -60,6 +62,7 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
size: 15
|
size: 15
|
||||||
sprite: Objects/Weapons/Melee/machete.rsi
|
sprite: Objects/Weapons/Melee/machete.rsi
|
||||||
|
- type: DisarmMalus
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: claymore
|
name: claymore
|
||||||
@@ -80,3 +83,4 @@
|
|||||||
sprite: Objects/Weapons/Melee/claymore.rsi
|
sprite: Objects/Weapons/Melee/claymore.rsi
|
||||||
Slots:
|
Slots:
|
||||||
- back
|
- back
|
||||||
|
- type: DisarmMalus
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
size: 20
|
size: 20
|
||||||
Slots:
|
Slots:
|
||||||
- Belt
|
- Belt
|
||||||
|
- type: DisarmMalus
|
||||||
|
malus: 0.225
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: flash
|
name: flash
|
||||||
|
|||||||
Reference in New Issue
Block a user