Files
wwdpublic/Content.Shared/Blocking/BlockingSystem.User.cs
SimpleStation14 21905859de Mirror: Fix shield absorbing asphyxiation damage (#140)
## Mirror of PR #25972: [Fix shield absorbing asphyxiation
damage](https://github.com/space-wizards/space-station-14/pull/25972)
from <img src="https://avatars.githubusercontent.com/u/10567778?v=4"
alt="space-wizards" width="22"/>
[space-wizards](https://github.com/space-wizards)/[space-station-14](https://github.com/space-wizards/space-station-14)

###### `b0ffed1607452a2d4186228fc2343d10035611e5`

PR opened by <img
src="https://avatars.githubusercontent.com/u/32041239?v=4"
width="16"/><a href="https://github.com/nikthechampiongr">
nikthechampiongr</a> at 2024-03-10 17:36:06 UTC
PR merged by <img
src="https://avatars.githubusercontent.com/u/19864447?v=4"
width="16"/><a href="https://github.com/web-flow"> web-flow</a> at
2024-03-11 01:55:19 UTC

---

PR changed 1 files with 12 additions and 2 deletions.

The PR had the following labels:


---

<details open="true"><summary><h1>Original Body</h1></summary>

> fixes #25966
> 
> <!-- Please read these guidelines before opening your PR:
https://docs.spacestation14.io/en/getting-started/pr-guideline -->
> <!-- The text between the arrows are comments - they will not be
visible on your PR. -->
> 
> ## About the PR
> <!-- What did you change in this PR? -->
> The shield will now only reduce damage itself can absorb.
> 
> ## Why / Balance
> <!-- Why was it changed? Link any discussions or issues here. Please
discuss how this would affect game balance. -->
> A shield should probably not oxygenate your blood supply.
> 
> ## Technical details
> <!-- If this is a code change, summarize at high level how your new
code works. This makes it easier to review. -->
> Instead of just multiplying the damage of the user, we now create a
damagemodiferset with all the damages that the shield can take. For that
we use the shield's damageable component. This does mean that shields
that cannot take damage will no longer absorb damage.
> 
> ## Media
> <!-- 
> PRs which make ingame changes (adding clothing, items, new features,
etc) are required to have media attached that showcase the changes.
> Small fixes/refactors are exempt.
> Any media may be used in SS14 progress reports, with clear credit
given.
> 
> If you're unsure whether your PR will require media, ask a maintainer.
> 
> Check the box below to confirm that you have in fact seen this (put an
X in the brackets, like [X]):
> -->
> 
> - [x] I have added screenshots/videos to this PR showcasing its
changes ingame, **or** this PR does not require an ingame showcase
> 
> ## Breaking changes
> <!--
> List any breaking changes, including namespace, public
class/method/field changes, prototype renames; and provide instructions
for fixing them. This will be pasted in #codebase-changes.
> -->
> 
> **Changelog**
> <!--
> Make players aware of new features and changes that could affect how
they play the game by adding a Changelog entry. Please read the
Changelog guidelines located at:
https://docs.spacestation14.io/en/getting-started/pr-guideline#changelog
> -->
> 
> <!--
> Make sure to take this Changelog template out of the comment block in
order for it to show up.
> 🆑
> - add: Added fun!
> - remove: Removed fun!
> - tweak: Changed fun!
> - fix: Fixed fun!
> -->
> 
> 🆑
> - fix: Shields will no longer absorb asphyxiation damage, or any other
damage they themselves can't take.


</details>

Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com>
2024-05-04 20:22:46 -04:00

105 lines
4.1 KiB
C#

using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
namespace Content.Shared.Blocking;
public sealed partial class BlockingSystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
private void InitializeUser()
{
SubscribeLocalEvent<BlockingUserComponent, DamageModifyEvent>(OnUserDamageModified);
SubscribeLocalEvent<BlockingComponent, DamageModifyEvent>(OnDamageModified);
SubscribeLocalEvent<BlockingUserComponent, EntParentChangedMessage>(OnParentChanged);
SubscribeLocalEvent<BlockingUserComponent, ContainerGettingInsertedAttemptEvent>(OnInsertAttempt);
SubscribeLocalEvent<BlockingUserComponent, AnchorStateChangedEvent>(OnAnchorChanged);
SubscribeLocalEvent<BlockingUserComponent, EntityTerminatingEvent>(OnEntityTerminating);
}
private void OnParentChanged(EntityUid uid, BlockingUserComponent component, ref EntParentChangedMessage args)
{
UserStopBlocking(uid, component);
}
private void OnInsertAttempt(EntityUid uid, BlockingUserComponent component, ContainerGettingInsertedAttemptEvent args)
{
UserStopBlocking(uid, component);
}
private void OnAnchorChanged(EntityUid uid, BlockingUserComponent component, ref AnchorStateChangedEvent args)
{
if (args.Anchored)
return;
UserStopBlocking(uid, component);
}
private void OnUserDamageModified(EntityUid uid, BlockingUserComponent component, DamageModifyEvent args)
{
if (TryComp<BlockingComponent>(component.BlockingItem, out var blocking))
{
if (args.Damage.GetTotal() <= 0)
return;
// A shield should only block damage it can itself absorb. To determine that we need the Damageable component on it.
if (!TryComp<DamageableComponent>(component.BlockingItem, out var dmgComp))
return;
var blockFraction = blocking.IsBlocking ? blocking.ActiveBlockFraction : blocking.PassiveBlockFraction;
blockFraction = Math.Clamp(blockFraction, 0, 1);
_damageable.TryChangeDamage(component.BlockingItem, blockFraction * args.OriginalDamage);
var modify = new DamageModifierSet();
foreach (var key in dmgComp.Damage.DamageDict.Keys)
{
modify.Coefficients.TryAdd(key, 1 - blockFraction);
}
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, modify);
if (blocking.IsBlocking && !args.Damage.Equals(args.OriginalDamage))
{
_audio.PlayPvs(blocking.BlockSound, uid);
}
}
}
private void OnDamageModified(EntityUid uid, BlockingComponent component, DamageModifyEvent args)
{
var modifier = component.IsBlocking ? component.ActiveBlockDamageModifier : component.PassiveBlockDamageModifer;
if (modifier == null)
{
return;
}
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, modifier);
}
private void OnEntityTerminating(EntityUid uid, BlockingUserComponent component, ref EntityTerminatingEvent args)
{
if (!TryComp<BlockingComponent>(component.BlockingItem, out var blockingComponent))
return;
StopBlockingHelper(component.BlockingItem.Value, blockingComponent, uid);
}
/// <summary>
/// Check for the shield and has the user stop blocking
/// Used where you'd like the user to stop blocking, but also don't want to remove the <see cref="BlockingUserComponent"/>
/// </summary>
/// <param name="uid">The user blocking</param>
/// <param name="component">The <see cref="BlockingUserComponent"/></param>
private void UserStopBlocking(EntityUid uid, BlockingUserComponent component)
{
if (TryComp<BlockingComponent>(component.BlockingItem, out var blockComp) && blockComp.IsBlocking)
StopBlocking(component.BlockingItem.Value, blockComp, uid);
}
}