-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #293 from AserCreator/master
"Нести на руках" и звуки для вульп
- Loading branch information
Showing
78 changed files
with
1,406 additions
and
1,783 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
Content.Server/Damage/Components/DamageOnTriggerComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Content.Shared.Damage; | ||
|
||
namespace Content.Server.Damage.Components; | ||
|
||
[RegisterComponent] | ||
public sealed partial class DamageOnTriggerComponent : Component | ||
{ | ||
[DataField("ignoreResistances")] public bool IgnoreResistances; | ||
|
||
[DataField("damage", required: true)] | ||
public DamageSpecifier Damage = default!; | ||
} |
11 changes: 11 additions & 0 deletions
11
Content.Server/Nyanotrasen/Carrying/BeingCarriedComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace Content.Server.Carrying | ||
{ | ||
/// <summary> | ||
/// Stores the carrier of an entity being carried. | ||
/// </summary> | ||
[RegisterComponent] | ||
public sealed partial class BeingCarriedComponent : Component | ||
{ | ||
public EntityUid Carrier = default!; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System.Threading; | ||
|
||
namespace Content.Server.Carrying | ||
{ | ||
[RegisterComponent] | ||
public sealed partial class CarriableComponent : Component | ||
{ | ||
/// <summary> | ||
/// Number of free hands required | ||
/// to carry the entity | ||
/// </summary> | ||
[DataField("freeHandsRequired")] | ||
public int FreeHandsRequired = 2; | ||
|
||
public CancellationTokenSource? CancelToken; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace Content.Server.Carrying | ||
{ | ||
/// <summary> | ||
/// Added to an entity when they are carrying somebody. | ||
/// </summary> | ||
[RegisterComponent] | ||
public sealed partial class CarryingComponent : Component | ||
{ | ||
public EntityUid Carried = default!; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,315 @@ | ||
using System.Threading; | ||
using Content.Server.DoAfter; | ||
using Content.Server.Body.Systems; | ||
using Content.Server.Hands.Systems; | ||
using Content.Server.Resist; | ||
using Content.Server.Popups; | ||
using Content.Server.Contests; | ||
using Content.Shared.Climbing; // Shared instead of Server | ||
using Content.Shared.Mobs; | ||
using Content.Shared.DoAfter; | ||
using Content.Shared.Buckle.Components; | ||
using Content.Shared.Hands.Components; | ||
using Content.Shared.Hands; | ||
using Content.Shared.Stunnable; | ||
using Content.Shared.Interaction.Events; | ||
using Content.Shared.Verbs; | ||
using Content.Shared.Climbing.Events; // Added this. | ||
using Content.Shared.Carrying; | ||
using Content.Shared.Movement.Events; | ||
using Content.Shared.Movement.Systems; | ||
using Content.Shared.Pulling; | ||
using Content.Shared.Pulling.Components; | ||
using Content.Shared.Standing; | ||
using Content.Shared.ActionBlocker; | ||
using Content.Shared.Throwing; | ||
using Content.Shared.Physics.Pull; | ||
using Content.Shared.Mobs.Systems; | ||
using Robust.Shared.Map.Components; | ||
|
||
namespace Content.Server.Carrying | ||
{ | ||
public sealed class CarryingSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!; | ||
[Dependency] private readonly CarryingSlowdownSystem _slowdown = default!; | ||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!; | ||
[Dependency] private readonly StandingStateSystem _standingState = default!; | ||
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; | ||
[Dependency] private readonly SharedPullingSystem _pullingSystem = default!; | ||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!; | ||
[Dependency] private readonly EscapeInventorySystem _escapeInventorySystem = default!; | ||
[Dependency] private readonly PopupSystem _popupSystem = default!; | ||
[Dependency] private readonly ContestsSystem _contests = default!; | ||
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!; | ||
[Dependency] private readonly RespiratorSystem _respirator = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
SubscribeLocalEvent<CarriableComponent, GetVerbsEvent<AlternativeVerb>>(AddCarryVerb); | ||
SubscribeLocalEvent<CarryingComponent, VirtualItemDeletedEvent>(OnVirtualItemDeleted); | ||
SubscribeLocalEvent<CarryingComponent, BeforeThrowEvent>(OnThrow); | ||
SubscribeLocalEvent<CarryingComponent, EntParentChangedMessage>(OnParentChanged); | ||
SubscribeLocalEvent<CarryingComponent, MobStateChangedEvent>(OnMobStateChanged); | ||
SubscribeLocalEvent<BeingCarriedComponent, InteractionAttemptEvent>(OnInteractionAttempt); | ||
SubscribeLocalEvent<BeingCarriedComponent, MoveInputEvent>(OnMoveInput); | ||
SubscribeLocalEvent<BeingCarriedComponent, UpdateCanMoveEvent>(OnMoveAttempt); | ||
SubscribeLocalEvent<BeingCarriedComponent, StandAttemptEvent>(OnStandAttempt); | ||
SubscribeLocalEvent<BeingCarriedComponent, GettingInteractedWithAttemptEvent>(OnInteractedWith); | ||
SubscribeLocalEvent<BeingCarriedComponent, PullAttemptEvent>(OnPullAttempt); | ||
SubscribeLocalEvent<BeingCarriedComponent, StartClimbEvent>(OnStartClimb); | ||
SubscribeLocalEvent<BeingCarriedComponent, BuckleChangeEvent>(OnBuckleChange); | ||
SubscribeLocalEvent<CarriableComponent, CarryDoAfterEvent>(OnDoAfter); | ||
} | ||
|
||
|
||
private void AddCarryVerb(EntityUid uid, CarriableComponent component, GetVerbsEvent<AlternativeVerb> args) | ||
{ | ||
if (!args.CanInteract || !args.CanAccess) | ||
return; | ||
|
||
if (!CanCarry(args.User, uid, component)) | ||
return; | ||
|
||
if (HasComp<CarryingComponent>(args.User)) // yeah not dealing with that | ||
return; | ||
|
||
if (HasComp<BeingCarriedComponent>(args.User) || HasComp<BeingCarriedComponent>(args.Target)) | ||
return; | ||
|
||
if (!_mobStateSystem.IsAlive(args.User)) | ||
return; | ||
|
||
if (args.User == args.Target) | ||
return; | ||
|
||
AlternativeVerb verb = new() | ||
{ | ||
Act = () => | ||
{ | ||
StartCarryDoAfter(args.User, uid, component); | ||
}, | ||
Text = Loc.GetString("carry-verb"), | ||
Priority = 2 | ||
}; | ||
args.Verbs.Add(verb); | ||
} | ||
|
||
/// <summary> | ||
/// Since the carried entity is stored as 2 virtual items, when deleted we want to drop them. | ||
/// </summary> | ||
private void OnVirtualItemDeleted(EntityUid uid, CarryingComponent component, VirtualItemDeletedEvent args) | ||
{ | ||
if (!HasComp<CarriableComponent>(args.BlockingEntity)) | ||
return; | ||
|
||
DropCarried(uid, args.BlockingEntity); | ||
} | ||
|
||
/// <summary> | ||
/// Basically using virtual item passthrough to throw the carried person. A new age! | ||
/// Maybe other things besides throwing should use virt items like this... | ||
/// </summary> | ||
private void OnThrow(EntityUid uid, CarryingComponent component, BeforeThrowEvent args) | ||
{ | ||
if (!TryComp<HandVirtualItemComponent>(args.ItemUid, out var virtItem) || !HasComp<CarriableComponent>(virtItem.BlockingEntity)) | ||
return; | ||
|
||
args.ItemUid = virtItem.BlockingEntity; | ||
|
||
var multiplier = _contests.MassContest(uid, virtItem.BlockingEntity); | ||
args.ThrowStrength = 5f * multiplier; | ||
} | ||
|
||
private void OnParentChanged(EntityUid uid, CarryingComponent component, ref EntParentChangedMessage args) | ||
{ | ||
if (Transform(uid).MapID != args.OldMapId) | ||
return; | ||
|
||
DropCarried(uid, component.Carried); | ||
} | ||
|
||
private void OnMobStateChanged(EntityUid uid, CarryingComponent component, MobStateChangedEvent args) | ||
{ | ||
DropCarried(uid, component.Carried); | ||
} | ||
|
||
/// <summary> | ||
/// Only let the person being carried interact with their carrier and things on their person. | ||
/// </summary> | ||
private void OnInteractionAttempt(EntityUid uid, BeingCarriedComponent component, InteractionAttemptEvent args) | ||
{ | ||
if (args.Target == null) | ||
return; | ||
|
||
var targetParent = Transform(args.Target.Value).ParentUid; | ||
|
||
if (args.Target.Value != component.Carrier && targetParent != component.Carrier && targetParent != uid) | ||
args.Cancel(); | ||
} | ||
|
||
/// <summary> | ||
/// Try to escape via the escape inventory system. | ||
/// </summary> | ||
private void OnMoveInput(EntityUid uid, BeingCarriedComponent component, ref MoveInputEvent args) | ||
{ | ||
if (!TryComp<CanEscapeInventoryComponent>(uid, out var escape)) | ||
return; | ||
|
||
if (_actionBlockerSystem.CanInteract(uid, component.Carrier)) | ||
{ | ||
_escapeInventorySystem.AttemptEscape(uid, component.Carrier, escape, _contests.MassContest(uid, component.Carrier)); | ||
} | ||
} | ||
|
||
private void OnMoveAttempt(EntityUid uid, BeingCarriedComponent component, UpdateCanMoveEvent args) | ||
{ | ||
args.Cancel(); | ||
} | ||
|
||
private void OnStandAttempt(EntityUid uid, BeingCarriedComponent component, StandAttemptEvent args) | ||
{ | ||
args.Cancel(); | ||
} | ||
|
||
private void OnInteractedWith(EntityUid uid, BeingCarriedComponent component, GettingInteractedWithAttemptEvent args) | ||
{ | ||
if (args.Uid != component.Carrier) | ||
args.Cancel(); | ||
} | ||
|
||
private void OnPullAttempt(EntityUid uid, BeingCarriedComponent component, PullAttemptEvent args) | ||
{ | ||
args.Cancelled = true; | ||
} | ||
|
||
private void OnStartClimb(EntityUid uid, BeingCarriedComponent component, ref StartClimbEvent args) | ||
{ | ||
DropCarried(component.Carrier, uid); | ||
} | ||
|
||
private void OnBuckleChange(EntityUid uid, BeingCarriedComponent component, ref BuckleChangeEvent args) | ||
{ | ||
DropCarried(component.Carrier, uid); | ||
} | ||
|
||
private void OnDoAfter(EntityUid uid, CarriableComponent component, CarryDoAfterEvent args) | ||
{ | ||
component.CancelToken = null; | ||
if (args.Handled || args.Cancelled) | ||
return; | ||
|
||
if (!CanCarry(args.Args.User, uid, component)) | ||
return; | ||
|
||
Carry(args.Args.User, uid); | ||
args.Handled = true; | ||
} | ||
private void StartCarryDoAfter(EntityUid carrier, EntityUid carried, CarriableComponent component) | ||
{ | ||
TimeSpan length = TimeSpan.FromSeconds(3); | ||
|
||
var mod = _contests.MassContest(carrier, carried); | ||
|
||
if (mod != 0) | ||
length /= mod; | ||
|
||
if (length >= TimeSpan.FromSeconds(9)) | ||
{ | ||
_popupSystem.PopupEntity(Loc.GetString("carry-too-heavy"), carried, carrier, Shared.Popups.PopupType.SmallCaution); | ||
return; | ||
} | ||
|
||
if (!HasComp<KnockedDownComponent>(carried)) | ||
length *= 2f; | ||
|
||
component.CancelToken = new CancellationTokenSource(); | ||
|
||
var ev = new CarryDoAfterEvent(); | ||
var args = new DoAfterArgs(EntityManager, carrier, length, ev, carried, target: carried) | ||
{ | ||
BreakOnTargetMove = true, | ||
BreakOnUserMove = true, | ||
NeedHand = true | ||
}; | ||
|
||
_doAfterSystem.TryStartDoAfter(args); | ||
} | ||
|
||
private void Carry(EntityUid carrier, EntityUid carried) | ||
{ | ||
if (TryComp<SharedPullableComponent>(carried, out var pullable)) | ||
_pullingSystem.TryStopPull(pullable); | ||
|
||
Transform(carrier).AttachToGridOrMap(); | ||
Transform(carried).AttachToGridOrMap(); | ||
Transform(carried).Coordinates = Transform(carrier).Coordinates; | ||
Transform(carried).AttachParent(Transform(carrier)); | ||
_virtualItemSystem.TrySpawnVirtualItemInHand(carried, carrier); | ||
_virtualItemSystem.TrySpawnVirtualItemInHand(carried, carrier); | ||
var carryingComp = EnsureComp<CarryingComponent>(carrier); | ||
ApplyCarrySlowdown(carrier, carried); | ||
var carriedComp = EnsureComp<BeingCarriedComponent>(carried); | ||
EnsureComp<KnockedDownComponent>(carried); | ||
|
||
carryingComp.Carried = carried; | ||
carriedComp.Carrier = carrier; | ||
|
||
_actionBlockerSystem.UpdateCanMove(carried); | ||
} | ||
|
||
public void DropCarried(EntityUid carrier, EntityUid carried) | ||
{ | ||
RemComp<CarryingComponent>(carrier); // get rid of this first so we don't recusrively fire that event | ||
RemComp<CarryingSlowdownComponent>(carrier); | ||
RemComp<BeingCarriedComponent>(carried); | ||
RemComp<KnockedDownComponent>(carried); | ||
_actionBlockerSystem.UpdateCanMove(carried); | ||
_virtualItemSystem.DeleteInHandsMatching(carrier, carried); | ||
Transform(carried).AttachToGridOrMap(); | ||
_standingState.Stand(carried); | ||
_movementSpeed.RefreshMovementSpeedModifiers(carrier); | ||
} | ||
|
||
private void ApplyCarrySlowdown(EntityUid carrier, EntityUid carried) | ||
{ | ||
var massRatio = _contests.MassContest(carrier, carried); | ||
|
||
if (massRatio == 0) | ||
massRatio = 1; | ||
|
||
var massRatioSq = Math.Pow(massRatio, 2); | ||
var modifier = (1 - (0.15 / massRatioSq)); | ||
modifier = Math.Max(0.1, modifier); | ||
var slowdownComp = EnsureComp<CarryingSlowdownComponent>(carrier); | ||
_slowdown.SetModifier(carrier, (float) modifier, (float) modifier, slowdownComp); | ||
} | ||
|
||
public bool CanCarry(EntityUid carrier, EntityUid carried, CarriableComponent? carriedComp = null) | ||
{ | ||
if (!Resolve(carried, ref carriedComp, false)) | ||
return false; | ||
|
||
if (carriedComp.CancelToken != null) | ||
return false; | ||
|
||
if (!HasComp<MapGridComponent>(Transform(carrier).ParentUid)) | ||
return false; | ||
|
||
if (HasComp<BeingCarriedComponent>(carrier) || HasComp<BeingCarriedComponent>(carried)) | ||
return false; | ||
|
||
// if (_respirator.IsReceivingCPR(carried)) | ||
// return false; | ||
|
||
if (!TryComp<HandsComponent>(carrier, out var hands)) | ||
return false; | ||
|
||
if (hands.CountFreeHands() < carriedComp.FreeHandsRequired) | ||
return false; | ||
|
||
return true; | ||
} | ||
} | ||
} |
Oops, something went wrong.