using System.Linq;
using Content.Shared.Contests;
using Content.Shared._Shitmed.Targeting;
using Content.Shared.Actions.Events;
using Content.Shared.Climbing.Components;
using Content.Shared.CombatMode;
using Content.Shared.Coordinates;
using Content.Shared.Damage;
using Content.Shared.Damage.Events;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Standing;
using Content.Shared.StatusEffect;
using Content.Shared.Stunnable;
using Content.Shared.Throwing;
using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Content.Shared.Climbing.Systems;
namespace Content.Shared._Goobstation.TableSlam;
///
/// This handles...
///
public sealed class TableSlamSystem : EntitySystem
{
[Dependency] private readonly PullingSystem _pullingSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly StandingStateSystem _standing = default!;
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly StaminaSystem _staminaSystem = default!;
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ContestsSystem _contestsSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ClimbSystem _climbing = default!;
///
public override void Initialize()
{
SubscribeLocalEvent(OnMeleeHit);
}
private void OnMeleeHit(Entity ent, ref MeleeHitEvent args)
{
if (ent.Comp.GrabStage < GrabStage.Suffocate
|| ent.Comp.Pulling == null || (args.HitEntities.Count is > 1 or 0))
return;
if(!TryComp(ent.Comp.Pulling, out var pullableComponent))
return;
var massContest = _contestsSystem.MassContest(ent, ent.Comp.Pulling.Value);
var attemptChance = Math.Clamp(1 * massContest, 0, 1);
var attemptRoundedToNearestQuarter = Math.Round(attemptChance * 4, MidpointRounding.ToEven) / 4;
if(_random.Prob((float) attemptRoundedToNearestQuarter)) // base chance to table slam someone is 1 if your mass ratio is less than 1 then you're going to have a harder time slamming somebody.
TryTableSlam((ent.Comp.Pulling.Value, pullableComponent), ent, args.HitEntities.ElementAt(0));
}
public void TryTableSlam(Entity ent, Entity pullerEnt, EntityUid tableUid)
{
if (!_transformSystem.InRange(ent.Owner.ToCoordinates(), tableUid.ToCoordinates(), 2f)
|| !TryComp(tableUid, out var component)
|| !HasComp(tableUid))
return;
_stunSystem.TryKnockdown(ent, TimeSpan.FromSeconds(3), false);
_climbing.TryClimb(pullerEnt, ent, tableUid, out _, component, null, true);
_pullingSystem.TryStopPull(ent, ent.Comp, pullerEnt, ignoreGrab: true);
if (TryComp(tableUid, out var glassTableComponent))
{
_damageableSystem.TryChangeDamage(tableUid, glassTableComponent.TableDamage, origin: ent);
_damageableSystem.TryChangeDamage(ent, glassTableComponent.ClimberDamage, origin: ent, targetPart: TargetBodyPart.Torso);
_stunSystem.TryParalyze(ent, TimeSpan.FromSeconds(3), false);
}
else
{
_damageableSystem.TryChangeDamage(ent,
new DamageSpecifier()
{
DamageDict = new Dictionary { { "Blunt", ent.Comp.TabledDamage } },
},
targetPart: TargetBodyPart.Torso);
_damageableSystem.TryChangeDamage(ent,
new DamageSpecifier()
{
DamageDict = new Dictionary { { "Blunt", ent.Comp.TabledDamage } },
});
}
_staminaSystem.TakeStaminaDamage(ent, ent.Comp.TabledStaminaDamage);
pullerEnt.Comp.NextStageChange = _gameTiming.CurTime + pullerEnt.Comp.StageChangeCooldown * 2;
//_audioSystem.PlayPvs("/Audio/Effects/thudswoosh.ogg", uid);
}
}