mirror of
https://github.com/wega-team/ss14-wega.git
synced 2026-02-15 03:31:44 +01:00
324 lines
12 KiB
C#
324 lines
12 KiB
C#
using Content.Shared.ActionBlocker;
|
|
using Content.Shared.Chat;
|
|
using Content.Shared.CombatMode;
|
|
using Content.Shared.Damage.Components;
|
|
using Content.Shared.Database;
|
|
using Content.Shared.DoAfter;
|
|
using Content.Shared.IdentityManagement;
|
|
using Content.Shared.Mobs.Components;
|
|
using Content.Shared.Mobs.Systems;
|
|
using Content.Shared.Popups;
|
|
using Content.Shared.Verbs;
|
|
using Content.Shared.Weapons.Melee;
|
|
using Content.Shared.Weapons.Melee.Events;
|
|
using Content.Shared.Weapons.Ranged.Components; // Corvax-Wega-Suicide
|
|
using Content.Shared.Weapons.Ranged.Systems; // Corvax-Wega-Suicide
|
|
using Content.Shared.Projectiles; // Corvax-Wega-Suicide
|
|
using Content.Shared.Interaction.Events;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Audio.Systems;
|
|
using Robust.Shared.Timing; // Corvax-Wega-Suicide
|
|
|
|
namespace Content.Shared.Execution;
|
|
|
|
/// <summary>
|
|
/// Verb for violently murdering cuffed creatures.
|
|
/// </summary>
|
|
public sealed class SharedExecutionSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
|
[Dependency] private readonly SharedSuicideSystem _suicide = default!;
|
|
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
|
|
[Dependency] private readonly SharedGunSystem _gun = default!; // Corvax-Wega-Suicide
|
|
[Dependency] private readonly SharedMeleeWeaponSystem _melee = default!;
|
|
[Dependency] private readonly SharedTransformSystem _transform = default!; // Corvax-Wega-Suicide
|
|
|
|
/// <inheritdoc/>
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<ExecutionComponent, GetVerbsEvent<UtilityVerb>>(OnGetInteractionsVerbs);
|
|
SubscribeLocalEvent<ExecutionComponent, GetMeleeDamageEvent>(OnGetMeleeDamage);
|
|
SubscribeLocalEvent<ExecutionComponent, SuicideByEnvironmentEvent>(OnSuicideByEnvironment);
|
|
SubscribeLocalEvent<ExecutionComponent, ExecutionDoAfterEvent>(OnExecutionDoAfter);
|
|
SubscribeLocalEvent<ProjectileComponent, ProjectileHitEvent>(OnProjectileHit); // Corvax-Wega-Suicide
|
|
}
|
|
|
|
private void OnGetInteractionsVerbs(EntityUid uid, ExecutionComponent comp, GetVerbsEvent<UtilityVerb> args)
|
|
{
|
|
if (args.Hands == null || args.Using == null || !args.CanAccess || !args.CanInteract)
|
|
return;
|
|
|
|
var attacker = args.User;
|
|
var weapon = args.Using.Value;
|
|
var victim = args.Target;
|
|
|
|
if (!CanBeExecuted(victim, attacker))
|
|
return;
|
|
|
|
// Corvax-Wega-Suicide-start
|
|
if (HasComp<GunComponent>(weapon) && !comp.CanGunExecute)
|
|
return;
|
|
|
|
if (HasComp<MeleeWeaponComponent>(weapon) && !comp.CanMeleeExecute)
|
|
return;
|
|
// Corvax-Wega-Suicide-end
|
|
|
|
UtilityVerb verb = new()
|
|
{
|
|
Act = () => TryStartExecutionDoAfter(weapon, victim, attacker, comp),
|
|
Impact = LogImpact.High,
|
|
Text = Loc.GetString("execution-verb-name"),
|
|
Message = Loc.GetString("execution-verb-message"),
|
|
};
|
|
|
|
args.Verbs.Add(verb);
|
|
}
|
|
|
|
private void TryStartExecutionDoAfter(EntityUid weapon, EntityUid victim, EntityUid attacker, ExecutionComponent comp)
|
|
{
|
|
if (!CanBeExecuted(victim, attacker))
|
|
return;
|
|
|
|
// Corvax-Wega-Suicide-Edit-start
|
|
string internalMsg;
|
|
string externalMsg;
|
|
|
|
if (attacker == victim)
|
|
{
|
|
if (HasComp<GunComponent>(weapon))
|
|
{
|
|
internalMsg = comp.InternalSelfGunExecutionMessage;
|
|
externalMsg = comp.ExternalSelfGunExecutionMessage;
|
|
}
|
|
else
|
|
{
|
|
internalMsg = comp.InternalSelfExecutionMessage;
|
|
externalMsg = comp.ExternalSelfExecutionMessage;
|
|
}
|
|
}
|
|
else if (HasComp<GunComponent>(weapon))
|
|
{
|
|
internalMsg = comp.InternalGunExecutionMessage;
|
|
externalMsg = comp.ExternalGunExecutionMessage;
|
|
}
|
|
else
|
|
{
|
|
internalMsg = comp.InternalMeleeExecutionMessage;
|
|
externalMsg = comp.ExternalMeleeExecutionMessage;
|
|
}
|
|
|
|
ShowExecutionInternalPopup(internalMsg, attacker, victim, weapon);
|
|
ShowExecutionExternalPopup(externalMsg, attacker, victim, weapon);
|
|
|
|
var doAfter = new DoAfterArgs(
|
|
EntityManager,
|
|
attacker,
|
|
comp.DoAfterDuration,
|
|
new ExecutionDoAfterEvent(),
|
|
weapon,
|
|
target: victim,
|
|
used: weapon)
|
|
{
|
|
BreakOnMove = true,
|
|
BreakOnDamage = true,
|
|
NeedHand = true
|
|
};
|
|
// Corvax-Wega-Suicide-Edit-end
|
|
|
|
_doAfter.TryStartDoAfter(doAfter);
|
|
}
|
|
|
|
public bool CanBeExecuted(EntityUid victim, EntityUid attacker)
|
|
{
|
|
// Corvax-Wega-Suicide-start
|
|
if (victim == attacker)
|
|
return true;
|
|
|
|
if ((_transform.GetWorldPosition(victim) - _transform.GetWorldPosition(attacker)).Length() > 0.8f)
|
|
return false;
|
|
// Corvax-Wega-Suicide-end
|
|
|
|
// No point executing someone if they can't take damage
|
|
if (!HasComp<DamageableComponent>(victim))
|
|
return false;
|
|
|
|
// You can't execute something that cannot die
|
|
if (!TryComp<MobStateComponent>(victim, out var mobState))
|
|
return false;
|
|
|
|
// You're not allowed to execute dead people (no fun allowed)
|
|
if (_mobState.IsDead(victim, mobState))
|
|
return false;
|
|
|
|
// You must be able to attack people to execute
|
|
if (!_actionBlocker.CanAttack(attacker, victim))
|
|
return false;
|
|
|
|
// The victim must be incapacitated to be executed
|
|
if (victim != attacker && _actionBlocker.CanInteract(victim, null))
|
|
return false;
|
|
|
|
// All checks passed
|
|
return true;
|
|
}
|
|
|
|
private void OnGetMeleeDamage(Entity<ExecutionComponent> entity, ref GetMeleeDamageEvent args)
|
|
{
|
|
if (!TryComp<MeleeWeaponComponent>(entity, out var melee) || !entity.Comp.Executing)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var bonus = melee.Damage * entity.Comp.DamageMultiplier - melee.Damage;
|
|
args.Damage += bonus;
|
|
args.ResistanceBypass = true;
|
|
}
|
|
|
|
// Corvax-Wega-Suicide-start
|
|
private void OnProjectileHit(EntityUid entity, ProjectileComponent component, ref ProjectileHitEvent e)
|
|
{
|
|
if (!TryComp<ExecutionComponent>(component.Weapon, out var execution) || !execution.Executing)
|
|
return;
|
|
|
|
var bonus = component.Damage * execution.DamageMultiplier - component.Damage;
|
|
e.Damage += bonus;
|
|
}
|
|
// Corvax-Wega-Suicide-end
|
|
|
|
private void OnSuicideByEnvironment(Entity<ExecutionComponent> entity, ref SuicideByEnvironmentEvent args)
|
|
{
|
|
if (!TryComp<MeleeWeaponComponent>(entity, out var melee))
|
|
return;
|
|
|
|
string internalMsg = entity.Comp.CompleteInternalSelfExecutionMessage; // Corvax-Wega-Suicide
|
|
string externalMsg = entity.Comp.CompleteExternalSelfExecutionMessage; // Corvax-Wega-Suicide
|
|
|
|
if (!TryComp<DamageableComponent>(args.Victim, out var damageableComponent))
|
|
return;
|
|
|
|
ShowExecutionInternalPopup(internalMsg, args.Victim, args.Victim, entity, false);
|
|
ShowExecutionExternalPopup(externalMsg, args.Victim, args.Victim, entity);
|
|
_audio.PlayPredicted(melee.HitSound, args.Victim, args.Victim);
|
|
_suicide.ApplyLethalDamage((args.Victim, damageableComponent), melee.Damage * entity.Comp.DamageMultiplier); // Corvax-Wega-Suicide
|
|
args.Handled = true; // Corvax-Wega-Suicide
|
|
}
|
|
|
|
private void ShowExecutionInternalPopup(string locString, EntityUid attacker, EntityUid victim, EntityUid weapon, bool predict = true)
|
|
{
|
|
if (predict)
|
|
{
|
|
_popup.PopupClient(
|
|
Loc.GetString(locString, ("attacker", Identity.Entity(attacker, EntityManager)), ("victim", Identity.Entity(victim, EntityManager)), ("weapon", weapon)),
|
|
attacker,
|
|
attacker,
|
|
PopupType.MediumCaution
|
|
);
|
|
}
|
|
else
|
|
{
|
|
_popup.PopupEntity(
|
|
Loc.GetString(locString, ("attacker", Identity.Entity(attacker, EntityManager)), ("victim", Identity.Entity(victim, EntityManager)), ("weapon", weapon)),
|
|
attacker,
|
|
attacker,
|
|
PopupType.MediumCaution
|
|
);
|
|
}
|
|
}
|
|
|
|
private void ShowExecutionExternalPopup(string locString, EntityUid attacker, EntityUid victim, EntityUid weapon)
|
|
{
|
|
_popup.PopupEntity(
|
|
Loc.GetString(locString, ("attacker", Identity.Entity(attacker, EntityManager)), ("victim", Identity.Entity(victim, EntityManager)), ("weapon", weapon)),
|
|
attacker,
|
|
Filter.PvsExcept(attacker),
|
|
true,
|
|
PopupType.MediumCaution
|
|
);
|
|
}
|
|
|
|
private void OnExecutionDoAfter(Entity<ExecutionComponent> entity, ref ExecutionDoAfterEvent args)
|
|
{
|
|
if (args.Handled || args.Cancelled || args.Used == null || args.Target == null)
|
|
return;
|
|
|
|
// Corvax-Wega-Suicide-Edit-start
|
|
var attacker = args.User;
|
|
var victim = args.Target.Value;
|
|
var weapon = args.Used.Value;
|
|
|
|
if (!CanBeExecuted(victim, attacker))
|
|
return;
|
|
|
|
entity.Comp.Executing = true;
|
|
|
|
TimeSpan time = TimeSpan.FromSeconds(0.1);
|
|
if (TryComp<GunComponent>(weapon, out var gun))
|
|
{
|
|
var prev = _combat.IsInCombatMode(attacker);
|
|
_combat.SetInCombatMode(attacker, true);
|
|
|
|
if (!_gun.AttemptDirectShoot(attacker, weapon, victim, gun))
|
|
{
|
|
_combat.SetInCombatMode(attacker, prev);
|
|
return;
|
|
}
|
|
|
|
_combat.SetInCombatMode(attacker, prev);
|
|
|
|
if (attacker == victim)
|
|
{
|
|
ShowExecutionInternalPopup(entity.Comp.CompleteInternalSelfGunExecutionMessage, attacker, victim, weapon);
|
|
ShowExecutionExternalPopup(entity.Comp.CompleteExternalSelfGunExecutionMessage, attacker, victim, weapon);
|
|
}
|
|
else
|
|
{
|
|
ShowExecutionInternalPopup(entity.Comp.CompleteInternalGunExecutionMessage, attacker, victim, weapon);
|
|
ShowExecutionExternalPopup(entity.Comp.CompleteExternalGunExecutionMessage, attacker, victim, weapon);
|
|
}
|
|
}
|
|
else if (TryComp<MeleeWeaponComponent>(weapon, out var melee))
|
|
{
|
|
var prev = _combat.IsInCombatMode(attacker);
|
|
_combat.SetInCombatMode(attacker, true);
|
|
|
|
_melee.AttemptLightAttack(attacker, weapon, melee, victim);
|
|
|
|
_combat.SetInCombatMode(attacker, prev);
|
|
|
|
if (attacker == victim)
|
|
{
|
|
ShowExecutionInternalPopup(entity.Comp.CompleteInternalSelfExecutionMessage, attacker, victim, weapon);
|
|
ShowExecutionExternalPopup(entity.Comp.CompleteExternalSelfExecutionMessage, attacker, victim, weapon);
|
|
}
|
|
else
|
|
{
|
|
ShowExecutionInternalPopup(entity.Comp.CompleteInternalMeleeExecutionMessage, attacker, victim, weapon);
|
|
ShowExecutionExternalPopup(entity.Comp.CompleteExternalMeleeExecutionMessage, attacker, victim, weapon);
|
|
}
|
|
|
|
time = TimeSpan.Zero;
|
|
}
|
|
|
|
if (attacker == victim)
|
|
{
|
|
var suicideEvent = new SuicideEvent(victim);
|
|
RaiseLocalEvent(victim, suicideEvent);
|
|
|
|
var suicideGhostEvent = new SuicideGhostEvent(victim);
|
|
RaiseLocalEvent(victim, suicideGhostEvent);
|
|
}
|
|
|
|
// Temporarily increased weapon damage.
|
|
Timer.Spawn(time, () => { entity.Comp.Executing = false; });
|
|
|
|
args.Handled = true;
|
|
// Corvax-Wega-Suicide-Edit-end
|
|
}
|
|
}
|