Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Port] Melee Block / Блок В Ближнем Бою #10

Merged
merged 8 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Content.Server/Chemistry/EntitySystems/HypospraySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Robust.Shared.GameStates;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared._White.Blocking;
using Robust.Server.Audio;

namespace Content.Server.Chemistry.EntitySystems;
Expand All @@ -32,7 +33,8 @@ public override void Initialize()
base.Initialize();

SubscribeLocalEvent<HyposprayComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<HyposprayComponent, MeleeHitEvent>(OnAttack);
SubscribeLocalEvent<HyposprayComponent, MeleeHitEvent>(OnAttack,
after: new[] {typeof(MeleeBlockSystem)}); // WD EDIT
SubscribeLocalEvent<HyposprayComponent, UseInHandEvent>(OnUseInHand);
}

Expand Down Expand Up @@ -68,6 +70,9 @@ public void OnAfterInteract(Entity<HyposprayComponent> entity, ref AfterInteract

public void OnAttack(Entity<HyposprayComponent> entity, ref MeleeHitEvent args)
{
if (args.Handled) // WD EDIT
return;

if (!args.HitEntities.Any())
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared._White.Blocking;
using Content.Shared.Inventory;
using Content.Shared.Popups;
using Content.Shared.Projectiles;
Expand All @@ -28,7 +29,8 @@ public override void Initialize()
base.Initialize();
SubscribeLocalEvent<SolutionInjectOnProjectileHitComponent, ProjectileHitEvent>(HandleProjectileHit);
SubscribeLocalEvent<SolutionInjectOnEmbedComponent, EmbedEvent>(HandleEmbed);
SubscribeLocalEvent<MeleeChemicalInjectorComponent, MeleeHitEvent>(HandleMeleeHit);
SubscribeLocalEvent<MeleeChemicalInjectorComponent, MeleeHitEvent>(HandleMeleeHit,
after: new[] {typeof(MeleeBlockSystem)}); // WD EDIT
}

private void HandleProjectileHit(Entity<SolutionInjectOnProjectileHitComponent> entity, ref ProjectileHitEvent args)
Expand All @@ -43,6 +45,9 @@ private void HandleEmbed(Entity<SolutionInjectOnEmbedComponent> entity, ref Embe

private void HandleMeleeHit(Entity<MeleeChemicalInjectorComponent> entity, ref MeleeHitEvent args)
{
if (args.Handled) // WD EDIT
return;

// MeleeHitEvent is weird, so we have to filter to make sure we actually
// hit something and aren't just examining the weapon.
if (args.IsHit)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Fluids.Components;
using Content.Shared._White.Blocking;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reaction;
Expand Down Expand Up @@ -28,7 +29,8 @@ protected override void InitializeSpillable()

SubscribeLocalEvent<SpillableComponent, LandEvent>(SpillOnLand);
// Openable handles the event if it's closed
SubscribeLocalEvent<SpillableComponent, MeleeHitEvent>(SplashOnMeleeHit, after: [typeof(OpenableSystem)]);
SubscribeLocalEvent<SpillableComponent, MeleeHitEvent>(
SplashOnMeleeHit, before: new[] {typeof(MeleeBlockSystem)}, after:[typeof(OpenableSystem)]); // WD EDIT
SubscribeLocalEvent<SpillableComponent, GotEquippedEvent>(OnGotEquipped);
SubscribeLocalEvent<SpillableComponent, GotUnequippedEvent>(OnGotUnequipped);
SubscribeLocalEvent<SpillableComponent, SolutionContainerOverflowEvent>(OnOverflow);
Expand Down
7 changes: 6 additions & 1 deletion Content.Server/Forensics/Systems/ForensicsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Content.Server.Fluids.EntitySystems;
using Content.Server.Forensics.Components;
using Content.Server.Popups;
using Content.Shared._White.Blocking;
using Content.Shared.Chemistry.Components;
using Content.Shared.DoAfter;
using Content.Shared.Forensics;
Expand Down Expand Up @@ -31,7 +32,8 @@ public override void Initialize()
SubscribeLocalEvent<ScentComponent, MapInitEvent>(OnScentInit);

SubscribeLocalEvent<DnaComponent, BeingGibbedEvent>(OnBeingGibbed);
SubscribeLocalEvent<ForensicsComponent, MeleeHitEvent>(OnMeleeHit);
SubscribeLocalEvent<ForensicsComponent, MeleeHitEvent>(OnMeleeHit,
after: new[] {typeof(MeleeBlockSystem)}); // WD EDIT
SubscribeLocalEvent<ForensicsComponent, GotRehydratedEvent>(OnRehydrated);
SubscribeLocalEvent<CleansForensicsComponent, AfterInteractEvent>(OnAfterInteract, after: new[] { typeof(AbsorbentSystem) });
SubscribeLocalEvent<ForensicsComponent, CleanForensicsDoAfterEvent>(OnCleanForensicsDoAfter);
Expand Down Expand Up @@ -87,6 +89,9 @@ private void OnBeingGibbed(EntityUid uid, DnaComponent component, BeingGibbedEve

private void OnMeleeHit(EntityUid uid, ForensicsComponent component, MeleeHitEvent args)
{
if (args.Handled) // WD EDIT
return;

if ((args.BaseDamage.DamageDict.TryGetValue("Blunt", out var bluntDamage) && bluntDamage.Value > 0) ||
(args.BaseDamage.DamageDict.TryGetValue("Slash", out var slashDamage) && slashDamage.Value > 0) ||
(args.BaseDamage.DamageDict.TryGetValue("Piercing", out var pierceDamage) && pierceDamage.Value > 0))
Expand Down
7 changes: 6 additions & 1 deletion Content.Server/Zombies/ZombieSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Content.Server.Chat.Systems;
using Content.Server.Emoting.Systems;
using Content.Server.Speech.EntitySystems;
using Content.Shared._White.Blocking;
using Content.Shared.Bed.Sleep;
using Content.Shared.Cloning;
using Content.Shared.Damage;
Expand Down Expand Up @@ -56,7 +57,8 @@ public override void Initialize()
SubscribeLocalEvent<ZombieComponent, EmoteEvent>(OnEmote, before:
new[] { typeof(VocalSystem), typeof(BodyEmotesSystem) });

SubscribeLocalEvent<ZombieComponent, MeleeHitEvent>(OnMeleeHit);
SubscribeLocalEvent<ZombieComponent, MeleeHitEvent>(OnMeleeHit,
after: new[] {typeof(MeleeBlockSystem)}); // WD EDIT
SubscribeLocalEvent<ZombieComponent, MobStateChangedEvent>(OnMobState);
SubscribeLocalEvent<ZombieComponent, CloningEvent>(OnZombieCloning);
SubscribeLocalEvent<ZombieComponent, TryingToSleepEvent>(OnSleepAttempt);
Expand Down Expand Up @@ -209,6 +211,9 @@ private float GetZombieInfectionChance(EntityUid uid, ZombieComponent component)

private void OnMeleeHit(EntityUid uid, ZombieComponent component, MeleeHitEvent args)
{
if (args.Handled) // WD EDIT
return;

if (!TryComp<ZombieComponent>(args.User, out _))
return;

Expand Down
1 change: 1 addition & 0 deletions Content.Shared/Alert/AlertType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public enum AlertType : byte
BorgCrit,
BorgDead,
Offer,
RecentlyBlocked, // WD EDIT
}

}
27 changes: 27 additions & 0 deletions Content.Shared/Blocking/BlockingSystem.User.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Content.Shared._White.Blocking;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Item.ItemToggle.Components;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
Expand All @@ -20,7 +22,32 @@ private void InitializeUser()
SubscribeLocalEvent<BlockingUserComponent, ContainerGettingInsertedAttemptEvent>(OnInsertAttempt);
SubscribeLocalEvent<BlockingUserComponent, AnchorStateChangedEvent>(OnAnchorChanged);
SubscribeLocalEvent<BlockingUserComponent, EntityTerminatingEvent>(OnEntityTerminating);

SubscribeLocalEvent<BlockingUserComponent, MeleeBlockAttemptEvent>(OnMeleeBlockAttempt); // WD
}

// WD START
private void OnMeleeBlockAttempt(Entity<BlockingUserComponent> ent, ref MeleeBlockAttemptEvent args)
{
if (args.Handled)
return;

var uid = ent.Comp.BlockingItem;
if (!TryComp(uid, out BlockingComponent? blocking) || !blocking.IsBlocking)
return;

if (TryComp(uid.Value, out ItemToggleComponent? toggle) && !toggle.Activated)
return;

if (!TryComp(uid.Value, out DamageableComponent? damageable))
return;

_audio.PlayPredicted(blocking.BlockSound, ent, args.Attacker);
_popupSystem.PopupPredicted(Loc.GetString("melee-block-event-blocked"), ent, args.Attacker);
_damageable.TryChangeDamage(uid.Value, args.Damage, damageable: damageable);
args.Handled = true;
}
// WD END

private void OnParentChanged(EntityUid uid, BlockingUserComponent component, ref EntParentChangedMessage args)
{
Expand Down
3 changes: 3 additions & 0 deletions Content.Shared/Damage/Systems/StaminaSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ private void OnDisarmed(EntityUid uid, StaminaComponent component, DisarmedEvent

private void OnMeleeHit(EntityUid uid, StaminaDamageOnHitComponent component, MeleeHitEvent args)
{
if (args.Handled) // WD EDIT
return;

if (!args.IsHit ||
!args.HitEntities.Any() ||
component.Damage <= 0f)
Expand Down
3 changes: 3 additions & 0 deletions Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public override void Initialize()

private void OnMeleeHit(Entity<MeleeThrowOnHitComponent> ent, ref MeleeHitEvent args)
{
if (args.Handled) // WD EDIT
return;

var (_, comp) = ent;
if (!args.IsHit)
return;
Expand Down
5 changes: 5 additions & 0 deletions Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public sealed partial class MeleeWeaponComponent : Component
/// </summary>
[DataField, AutoNetworkedField]
public SoundSpecifier SoundNoDamage { get; set; } = new SoundCollectionSpecifier("WeakHit");

// WD EDIT START
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public bool CanBeBlocked = true;
// WD EDIT END
}

/// <summary>
Expand Down
6 changes: 6 additions & 0 deletions Content.Shared/_White/Blocking/BlockBlockerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Robust.Shared.GameStates;

namespace Content.Shared._White.Blocking;

[RegisterComponent, NetworkedComponent]
public sealed partial class BlockBlockerComponent : Component;
24 changes: 24 additions & 0 deletions Content.Shared/_White/Blocking/MeleeBlockComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Content.Shared.Damage;
using Robust.Shared.Audio;

namespace Content.Shared._White.Blocking;

[RegisterComponent]
public sealed partial class MeleeBlockComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite)]
public TimeSpan Delay = TimeSpan.FromSeconds(3.1);

[DataField]
public SoundSpecifier BlockSound = new SoundPathSpecifier("/Audio/Weapons/block_metal1.ogg")
{
Params = AudioParams.Default.WithVariation(0.25f)
};
}

public sealed class MeleeBlockAttemptEvent(EntityUid attacker, DamageSpecifier damage) : HandledEntityEventArgs
{
public EntityUid Attacker = attacker;

public DamageSpecifier Damage = damage;
}
95 changes: 95 additions & 0 deletions Content.Shared/_White/Blocking/MeleeBlockSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Content.Shared.Blocking;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Examine;
using Content.Shared.Hands.Components;
using Content.Shared.Item.ItemToggle.Components;
using Content.Shared.Popups;
using Content.Shared.StatusEffect;
using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Timing;

namespace Content.Shared._White.Blocking;

public sealed class MeleeBlockSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffect = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<HandsComponent, MeleeBlockAttemptEvent>(OnBlockAttempt,
after: new[] {typeof(BlockingSystem)});
SubscribeLocalEvent<MeleeWeaponComponent, MeleeHitEvent>(OnHit,
before: new[] {typeof(StaminaSystem), typeof(MeleeThrowOnHitSystem)});
SubscribeLocalEvent<MeleeBlockComponent, ExaminedEvent>(OnExamine);
}

private void OnExamine(Entity<MeleeBlockComponent> ent, ref ExaminedEvent args)
{
args.PushMarkup(Loc.GetString("melee-block-component-delay", ("delay", ent.Comp.Delay.TotalSeconds)));
}

private void OnHit(Entity<MeleeWeaponComponent> ent, ref MeleeHitEvent args)
{
if (!_timing.IsFirstTimePredicted)
return;

if (!ent.Comp.CanBeBlocked || !args.IsHit || args.Handled)
return;

if (args.Direction != null || args.HitEntities.Count != 1) // Heavy attacks are unblockable
return;

var hitEntity = args.HitEntities[0];

if (hitEntity == args.User)
return;

var ev = new MeleeBlockAttemptEvent(args.User, args.BaseDamage + args.BonusDamage);
RaiseLocalEvent(hitEntity, ev);

if (ev.Handled)
args.Handled = true;
}

private void OnBlockAttempt(Entity<HandsComponent> ent, ref MeleeBlockAttemptEvent args)
{
if (args.Handled || HasComp<BlockBlockerComponent>(ent))
return;

if (!TryComp(ent, out StatusEffectsComponent? statusEffects))
return;

var uid = ent.Comp.ActiveHandEntity;
if (!TryComp(uid, out MeleeBlockComponent? block))
return;

if (TryComp(uid.Value, out ItemToggleComponent? toggle) && !toggle.Activated)
return;

_audio.PlayPredicted(block.BlockSound, ent, args.Attacker);
_popupSystem.PopupPredicted(Loc.GetString("melee-block-event-blocked"), ent, args.Attacker);
_damageable.TryChangeDamage(uid.Value, args.Damage);
TryBlockBlocking(ent, block.Delay, true, statusEffects);
args.Handled = true;
}

public bool TryBlockBlocking(EntityUid uid, TimeSpan time, bool refresh, StatusEffectsComponent? status = null)
{
if (time <= TimeSpan.Zero)
return false;

if (!Resolve(uid, ref status, false))
return false;

return _statusEffect.TryAddStatusEffect<BlockBlockerComponent>(uid, "RecentlyBlocked", time, refresh);
}
}
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_white/alerts/alerts.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alerts-blocked-name = Recently blocked
alerts-blocked-desc = I can't block for a while!
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/_white/block/melee-block.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
melee-block-event-blocked = blocked!
melee-block-component-delay = Can block a melee attack every {$delay} seconds.
2 changes: 2 additions & 0 deletions Resources/Locale/ru-RU/_white/alerts/alerts.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alerts-blocked-name = Атака заблокирована
alerts-blocked-desc = Невозможно блокировать некоторое время.
2 changes: 2 additions & 0 deletions Resources/Locale/ru-RU/_white/block/melee-block.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
melee-block-event-blocked = заблокировал!
melee-block-component-delay = Может блокировать атаку ближнего боя каждые {$delay} секунд.
8 changes: 8 additions & 0 deletions Resources/Prototypes/Alerts/alerts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- alertType: Magboots
- alertType: Pacified
- alertType: Offer
- alertType: RecentlyBlocked # WD EDIT

- type: entity
id: AlertSpriteView
Expand Down Expand Up @@ -449,6 +450,13 @@
minSeverity: 0
maxSeverity: 1

# WD EDIT
- type: alert
id: RecentlyBlocked
icons: [ /Textures/Objects/Weapons/Melee/shields.rsi/buckler-icon.png ]
name: alerts-blocked-name
description: alerts-blocked-desc

- type: alert
id: Debug1
icons:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- type: Item
size: Small
- type: MeleeWeapon
canBeBlocked: false # WD EDIT
soundNoDamage:
path: "/Audio/Effects/Fluids/splat.ogg"
damage:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- type: Sprite
state: icon
- type: MeleeWeapon
canBeBlocked: false # WD EDIT
soundNoDamage:
path: "/Audio/Effects/Fluids/splat.ogg"
damage:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
- type: Spillable
solution: drink
- type: MeleeWeapon
canBeBlocked: false # WD EDIT
soundNoDamage:
path: "/Audio/Effects/Fluids/splat.ogg"
damage:
Expand Down
Loading
Loading