16
Content.Server/White/Other/CritSystem/CritComponent.cs
Normal file
16
Content.Server/White/Other/CritSystem/CritComponent.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Content.Server.White.Other.CritSystem;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class CritComponent : Component
|
||||
{
|
||||
[DataField("critChance", required: true)]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int CritChance = 25;
|
||||
|
||||
[DataField("critMultiplier", required: true)]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float CritMultiplier = 2.5f;
|
||||
|
||||
[DataField("workingChance")]
|
||||
public int? WorkingChance;
|
||||
}
|
||||
65
Content.Server/White/Other/CritSystem/CritSystem.cs
Normal file
65
Content.Server/White/Other/CritSystem/CritSystem.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.White.Other.CritSystem;
|
||||
|
||||
public sealed class CritSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<CritComponent, MeleeHitEvent>(HandleHit);
|
||||
}
|
||||
|
||||
private void HandleHit(EntityUid uid, CritComponent component, MeleeHitEvent args)
|
||||
{
|
||||
foreach (var target in args.HitEntities)
|
||||
{
|
||||
if (!IsCriticalHit(component))
|
||||
return;
|
||||
|
||||
if (!TryComp<MobStateComponent>(target, out _))
|
||||
continue;
|
||||
|
||||
var damage = args.BaseDamage.Total * component.CritMultiplier;
|
||||
var ohio = _random.Next(1, 20);
|
||||
|
||||
args.BonusDamage = new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Blunt"), damage);
|
||||
|
||||
_popup.PopupEntity($@"Crit! {damage}", args.User, PopupType.MediumCaution);
|
||||
|
||||
_bloodstream.TryModifyBloodLevel(target, -ohio);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCriticalHit(CritComponent component)
|
||||
{
|
||||
var roll = _random.Next(1, 101);
|
||||
|
||||
var critChance = component.CritChance;
|
||||
|
||||
component.WorkingChance ??= component.CritChance;
|
||||
|
||||
var isCritical = roll <= component.WorkingChance;
|
||||
|
||||
if (isCritical)
|
||||
component.WorkingChance = critChance;
|
||||
else
|
||||
component.WorkingChance++;
|
||||
|
||||
return isCritical;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user