Examine throwable damage (#18580)

This commit is contained in:
Slava0135
2023-08-07 12:09:35 +03:00
committed by GitHub
parent 88b3417c3d
commit 53db6bc265
11 changed files with 125 additions and 108 deletions

View File

@@ -3,6 +3,8 @@ using Content.Server.Damage.Components;
using Content.Server.Weapons.Ranged.Systems; using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Camera; using Content.Shared.Camera;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Damage.Events;
using Content.Shared.Damage.Systems;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Effects; using Content.Shared.Effects;
using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Components;
@@ -15,21 +17,23 @@ namespace Content.Server.Damage.Systems
{ {
public sealed class DamageOtherOnHitSystem : EntitySystem public sealed class DamageOtherOnHitSystem : EntitySystem
{ {
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly GunSystem _guns = default!; [Dependency] private readonly GunSystem _guns = default!;
[Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!; [Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!;
[Dependency] private readonly ThrownItemSystem _thrownItem = default!; [Dependency] private readonly ThrownItemSystem _thrownItem = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly DamageExamineSystem _damageExamine = default!;
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<DamageOtherOnHitComponent, ThrowDoHitEvent>(OnDoHit); SubscribeLocalEvent<DamageOtherOnHitComponent, ThrowDoHitEvent>(OnDoHit);
SubscribeLocalEvent<DamageOtherOnHitComponent, DamageExamineEvent>(OnDamageExamine);
} }
private void OnDoHit(EntityUid uid, DamageOtherOnHitComponent component, ThrowDoHitEvent args) private void OnDoHit(EntityUid uid, DamageOtherOnHitComponent component, ThrowDoHitEvent args)
{ {
var dmg = _damageableSystem.TryChangeDamage(args.Target, component.Damage, component.IgnoreResistances, origin: args.Component.Thrower); var dmg = _damageable.TryChangeDamage(args.Target, component.Damage, component.IgnoreResistances, origin: args.Component.Thrower);
// Log damage only for mobs. Useful for when people throw spears at each other, but also avoids log-spam when explosions send glass shards flying. // Log damage only for mobs. Useful for when people throw spears at each other, but also avoids log-spam when explosions send glass shards flying.
if (dmg != null && HasComp<MobStateComponent>(args.Target)) if (dmg != null && HasComp<MobStateComponent>(args.Target))
@@ -49,5 +53,10 @@ namespace Content.Server.Damage.Systems
_physics.ResetDynamics(physics); _physics.ResetDynamics(physics);
} }
} }
private void OnDamageExamine(EntityUid uid, DamageOtherOnHitComponent component, ref DamageExamineEvent args)
{
_damageExamine.AddDamageExamine(args.Message, component.Damage, Loc.GetString("damage-throw"));
}
} }
} }

View File

@@ -7,11 +7,11 @@ using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.CombatMode.Disarm; using Content.Server.CombatMode.Disarm;
using Content.Server.Contests; using Content.Server.Contests;
using Content.Server.Examine;
using Content.Server.Movement.Systems; using Content.Server.Movement.Systems;
using Content.Shared.Administration.Components; using Content.Shared.Administration.Components;
using Content.Shared.Actions.Events; using Content.Shared.Actions.Events;
using Content.Shared.CombatMode; using Content.Shared.CombatMode;
using Content.Shared.Damage.Events;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
@@ -21,7 +21,6 @@ using Content.Shared.Popups;
using Content.Shared.Speech.Components; using Content.Shared.Speech.Components;
using Content.Shared.StatusEffect; using Content.Shared.StatusEffect;
using Content.Shared.Tag; using Content.Shared.Tag;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Melee.Events; using Content.Shared.Weapons.Melee.Events;
using Robust.Server.Player; using Robust.Server.Player;
@@ -30,8 +29,8 @@ using Robust.Shared.Map;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Players; using Robust.Shared.Players;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Utility;
using Content.Shared.Effects; using Content.Shared.Effects;
using Content.Shared.Damage.Systems;
namespace Content.Server.Weapons.Melee; namespace Content.Server.Weapons.Melee;
@@ -40,24 +39,24 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly BloodstreamSystem _bloodstream = default!; [Dependency] private readonly BloodstreamSystem _bloodstream = default!;
[Dependency] private readonly ContestsSystem _contests = default!; [Dependency] private readonly ContestsSystem _contests = default!;
[Dependency] private readonly ExamineSystem _examine = default!;
[Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly LagCompensationSystem _lag = default!; [Dependency] private readonly LagCompensationSystem _lag = default!;
[Dependency] private readonly SolutionContainerSystem _solutions = default!; [Dependency] private readonly SolutionContainerSystem _solutions = default!;
[Dependency] private readonly TagSystem _tag = default!; [Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly DamageExamineSystem _damageExamine = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<MeleeChemicalInjectorComponent, MeleeHitEvent>(OnChemicalInjectorHit); SubscribeLocalEvent<MeleeChemicalInjectorComponent, MeleeHitEvent>(OnChemicalInjectorHit);
SubscribeLocalEvent<MeleeSpeechComponent, MeleeHitEvent>(OnSpeechHit); SubscribeLocalEvent<MeleeSpeechComponent, MeleeHitEvent>(OnSpeechHit);
SubscribeLocalEvent<MeleeWeaponComponent, GetVerbsEvent<ExamineVerb>>(OnMeleeExaminableVerb); SubscribeLocalEvent<MeleeWeaponComponent, DamageExamineEvent>(OnMeleeExamineDamage);
} }
private void OnMeleeExaminableVerb(EntityUid uid, MeleeWeaponComponent component, GetVerbsEvent<ExamineVerb> args) private void OnMeleeExamineDamage(EntityUid uid, MeleeWeaponComponent component, ref DamageExamineEvent args)
{ {
if (!args.CanInteract || !args.CanAccess || component.HideFromExamine) if (component.HideFromExamine)
return; return;
var damageSpec = GetDamage(uid, args.User, component); var damageSpec = GetDamage(uid, args.User, component);
@@ -65,20 +64,7 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
if (damageSpec.Total == FixedPoint2.Zero) if (damageSpec.Total == FixedPoint2.Zero)
return; return;
var verb = new ExamineVerb() _damageExamine.AddDamageExamine(args.Message, damageSpec, Loc.GetString("damage-melee"));
{
Act = () =>
{
var markup = Damageable.GetDamageExamine(damageSpec, Loc.GetString("damage-melee"));
_examine.SendExamineTooltip(args.User, uid, markup, false, false);
},
Text = Loc.GetString("damage-examinable-verb-text"),
Message = Loc.GetString("damage-examinable-verb-message"),
Category = VerbCategory.Examine,
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")),
};
args.Verbs.Add(verb);
} }
protected override bool ArcRaySuccessful(EntityUid targetUid, Vector2 position, Angle angle, Angle arcWidth, float range, MapId mapId, protected override bool ArcRaySuccessful(EntityUid targetUid, Vector2 position, Angle angle, Angle arcWidth, float range, MapId mapId,

View File

@@ -1,12 +1,11 @@
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Damage.Events;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Projectiles; using Content.Shared.Projectiles;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Ranged; using Content.Shared.Weapons.Ranged;
using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Server.Weapons.Ranged.Systems; namespace Content.Server.Weapons.Ranged.Systems;
@@ -19,12 +18,12 @@ public sealed partial class GunSystem
// Hitscan // Hitscan
SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, ComponentStartup>(OnBatteryStartup); SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, ComponentStartup>(OnBatteryStartup);
SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, ChargeChangedEvent>(OnBatteryChargeChange); SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, ChargeChangedEvent>(OnBatteryChargeChange);
SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, GetVerbsEvent<ExamineVerb>>(OnBatteryExaminableVerb); SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, DamageExamineEvent>(OnBatteryDamageExamine);
// Projectile // Projectile
SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, ComponentStartup>(OnBatteryStartup); SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, ComponentStartup>(OnBatteryStartup);
SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, ChargeChangedEvent>(OnBatteryChargeChange); SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, ChargeChangedEvent>(OnBatteryChargeChange);
SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, GetVerbsEvent<ExamineVerb>>(OnBatteryExaminableVerb); SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, DamageExamineEvent>(OnBatteryDamageExamine);
} }
private void OnBatteryStartup(EntityUid uid, BatteryAmmoProviderComponent component, ComponentStartup args) private void OnBatteryStartup(EntityUid uid, BatteryAmmoProviderComponent component, ComponentStartup args)
@@ -60,44 +59,21 @@ public sealed partial class GunSystem
UpdateBatteryAppearance(uid, component); UpdateBatteryAppearance(uid, component);
} }
private void OnBatteryExaminableVerb(EntityUid uid, BatteryAmmoProviderComponent component, GetVerbsEvent<ExamineVerb> args) private void OnBatteryDamageExamine(EntityUid uid, BatteryAmmoProviderComponent component, ref DamageExamineEvent args)
{ {
if (!args.CanInteract || !args.CanAccess)
return;
var damageSpec = GetDamage(component); var damageSpec = GetDamage(component);
if (damageSpec == null) if (damageSpec == null)
return; return;
string damageType; var damageType = component switch
switch (component)
{ {
case HitscanBatteryAmmoProviderComponent: HitscanBatteryAmmoProviderComponent => Loc.GetString("damage-hitscan"),
damageType = Loc.GetString("damage-hitscan"); ProjectileBatteryAmmoProviderComponent => Loc.GetString("damage-projectile"),
break; _ => throw new ArgumentOutOfRangeException(),
case ProjectileBatteryAmmoProviderComponent:
damageType = Loc.GetString("damage-projectile");
break;
default:
throw new ArgumentOutOfRangeException();
}
var verb = new ExamineVerb()
{
Act = () =>
{
var markup = Damageable.GetDamageExamine(damageSpec, damageType);
Examine.SendExamineTooltip(args.User, uid, markup, false, false);
},
Text = Loc.GetString("damage-examinable-verb-text"),
Message = Loc.GetString("damage-examinable-verb-message"),
Category = VerbCategory.Examine,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")),
}; };
args.Verbs.Add(verb); _damageExamine.AddDamageExamine(args.Message, damageSpec, damageType);
} }
private DamageSpecifier? GetDamage(BatteryAmmoProviderComponent component) private DamageSpecifier? GetDamage(BatteryAmmoProviderComponent component)

View File

@@ -1,11 +1,10 @@
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Damage.Events;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Projectiles; using Content.Shared.Projectiles;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Server.Weapons.Ranged.Systems; namespace Content.Server.Weapons.Ranged.Systems;
@@ -15,33 +14,17 @@ public sealed partial class GunSystem
{ {
base.InitializeCartridge(); base.InitializeCartridge();
SubscribeLocalEvent<CartridgeAmmoComponent, ExaminedEvent>(OnCartridgeExamine); SubscribeLocalEvent<CartridgeAmmoComponent, ExaminedEvent>(OnCartridgeExamine);
SubscribeLocalEvent<CartridgeAmmoComponent, GetVerbsEvent<ExamineVerb>>(OnCartridgeVerbExamine); SubscribeLocalEvent<CartridgeAmmoComponent, DamageExamineEvent>(OnCartridgeDamageExamine);
} }
private void OnCartridgeVerbExamine(EntityUid uid, CartridgeAmmoComponent component, GetVerbsEvent<ExamineVerb> args) private void OnCartridgeDamageExamine(EntityUid uid, CartridgeAmmoComponent component, ref DamageExamineEvent args)
{ {
if (!args.CanInteract || !args.CanAccess)
return;
var damageSpec = GetProjectileDamage(component.Prototype); var damageSpec = GetProjectileDamage(component.Prototype);
if (damageSpec == null) if (damageSpec == null)
return; return;
var verb = new ExamineVerb() _damageExamine.AddDamageExamine(args.Message, damageSpec, Loc.GetString("damage-projectile"));
{
Act = () =>
{
var markup = Damageable.GetDamageExamine(damageSpec, Loc.GetString("damage-projectile"));
_examine.SendExamineTooltip(args.User, uid, markup, false, false);
},
Text = Loc.GetString("damage-examinable-verb-text"),
Message = Loc.GetString("damage-examinable-verb-message"),
Category = VerbCategory.Examine,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")),
};
args.Verbs.Add(verb);
} }
private DamageSpecifier? GetProjectileDamage(string proto) private DamageSpecifier? GetProjectileDamage(string proto)

View File

@@ -2,7 +2,6 @@ using System.Linq;
using System.Numerics; using System.Numerics;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Cargo.Systems; using Content.Server.Cargo.Systems;
using Content.Server.Examine;
using Content.Server.Interaction; using Content.Server.Interaction;
using Content.Server.Power.EntitySystems; using Content.Server.Power.EntitySystems;
using Content.Server.Stunnable; using Content.Server.Stunnable;
@@ -35,13 +34,13 @@ public sealed partial class GunSystem : SharedGunSystem
{ {
[Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IComponentFactory _factory = default!; [Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly ExamineSystem _examine = default!;
[Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly InteractionSystem _interaction = default!;
[Dependency] private readonly PricingSystem _pricing = default!; [Dependency] private readonly PricingSystem _pricing = default!;
[Dependency] private readonly StaminaSystem _stamina = default!; [Dependency] private readonly StaminaSystem _stamina = default!;
[Dependency] private readonly StunSystem _stun = default!; [Dependency] private readonly StunSystem _stun = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly BatterySystem _battery = default!; [Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly DamageExamineSystem _damageExamine = default!;
public const float DamagePitchVariation = SharedMeleeWeaponSystem.DamagePitchVariation; public const float DamagePitchVariation = SharedMeleeWeaponSystem.DamagePitchVariation;
public const float GunClumsyChance = 0.5f; public const float GunClumsyChance = 0.5f;

View File

@@ -0,0 +1,8 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Damage.Components;
[RegisterComponent, NetworkedComponent]
public sealed class DamageExaminableComponent : Component
{
}

View File

@@ -0,0 +1,6 @@
using Robust.Shared.Utility;
namespace Content.Shared.Damage.Events;
[ByRefEvent]
public readonly record struct DamageExamineEvent(FormattedMessage Message, EntityUid User);

View File

@@ -0,0 +1,75 @@
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Events;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Verbs;
using Robust.Shared.Utility;
namespace Content.Shared.Damage.Systems;
public sealed class DamageExamineSystem : EntitySystem
{
[Dependency] private readonly ExamineSystemShared _examine = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DamageExaminableComponent, GetVerbsEvent<ExamineVerb>>(OnGetExamineVerbs);
}
private void OnGetExamineVerbs(EntityUid uid, DamageExaminableComponent component, GetVerbsEvent<ExamineVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
var ev = new DamageExamineEvent(new FormattedMessage(), args.User);
RaiseLocalEvent(uid, ref ev);
if (!ev.Message.IsEmpty)
{
_examine.AddDetailedExamineVerb(args, component, ev.Message,
Loc.GetString("damage-examinable-verb-text"),
"/Textures/Interface/VerbIcons/smite.svg.192dpi.png",
Loc.GetString("damage-examinable-verb-message")
);
}
}
public void AddDamageExamine(FormattedMessage message, DamageSpecifier damageSpecifier, string? type = null)
{
var markup = GetDamageExamine(damageSpecifier, type);
if (!message.IsEmpty)
{
message.PushNewline();
}
message.AddMessage(markup);
}
/// <summary>
/// Retrieves the damage examine values.
/// </summary>
private FormattedMessage GetDamageExamine(DamageSpecifier damageSpecifier, string? type = null)
{
var msg = new FormattedMessage();
if (string.IsNullOrEmpty(type))
{
msg.AddMarkup(Loc.GetString("damage-examine"));
}
else
{
msg.AddMarkup(Loc.GetString("damage-examine-type", ("type", type)));
}
foreach (var damage in damageSpecifier.DamageDict)
{
if (damage.Value != FixedPoint2.Zero)
{
msg.PushNewline();
msg.AddMarkup(Loc.GetString("damage-value", ("type", damage.Key), ("amount", damage.Value)));
}
}
return msg;
}
}

View File

@@ -29,34 +29,6 @@ namespace Content.Shared.Damage
SubscribeLocalEvent<DamageableComponent, RejuvenateEvent>(OnRejuvenate); SubscribeLocalEvent<DamageableComponent, RejuvenateEvent>(OnRejuvenate);
} }
/// <summary>
/// Retrieves the damage examine values.
/// </summary>
public FormattedMessage GetDamageExamine(DamageSpecifier damageSpecifier, string? type = null)
{
var msg = new FormattedMessage();
if (string.IsNullOrEmpty(type))
{
msg.AddMarkup(Loc.GetString("damage-examine"));
}
else
{
msg.AddMarkup(Loc.GetString("damage-examine-type", ("type", type)));
}
foreach (var damage in damageSpecifier.DamageDict)
{
if (damage.Value != FixedPoint2.Zero)
{
msg.PushNewline();
msg.AddMarkup(Loc.GetString("damage-value", ("type", damage.Key), ("amount", damage.Value)));
}
}
return msg;
}
/// <summary> /// <summary>
/// Initialize a damageable component /// Initialize a damageable component
/// </summary> /// </summary>

View File

@@ -5,6 +5,8 @@ damage-examinable-verb-message = Examine the damage values.
damage-hitscan = hitscan damage-hitscan = hitscan
damage-projectile = projectile damage-projectile = projectile
damage-melee = melee damage-melee = melee
damage-throw = throw
damage-examine = It does the following damage: damage-examine = It does the following damage:
damage-examine-type = It does the following {$type} damage: damage-examine-type = It does the following [color=cyan]{$type}[/color] damage:
damage-value = - [color=red]{$amount}[/color] units of [color=yellow]{$type}[/color]. damage-value = - [color=red]{$amount}[/color] units of [color=yellow]{$type}[/color].

View File

@@ -43,6 +43,7 @@
drawdepth: Items drawdepth: Items
noRot: false noRot: false
- type: Pullable - type: Pullable
- type: DamageExaminable
- type: entity - type: entity
name: "storage item" name: "storage item"