-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Описание PR <!-- Что вы изменили в этом пулл реквесте? --> Была добавлена новая механика - граб. Когда игрок тащит кого-либо, он может усилить захват с лёгкого до удушающего. Всего у граба присутствует три стадии - слабый, сильный и удушающий. Переход со стадии на стадию производится через DoAfter. Чтобы выбраться из захвата требуется так же дождаться завершения DoAfter'а. Каждая стадия имеет настройку количества требуемых рук, скорости захвата, скорости попытки выбраться и число этих попыток для успеха. Когда игрок держит сущность в захвате, он может: - Ударить его головой об стол, перетащив модельку оппонента на него - Кинуть оппонента в сторону, сбивая им всех, кто находится на пути (учитывая самого инициатора!) ## Почему / Баланс <!-- Почему оно было изменено? Ссылайтесь на любые обсуждения или вопросы здесь. Пожалуйста, обсудите, как это повлияет на игровой баланс. --> 1. Было в сс13 2. Сырость и скука нынешней боёвки 3. Старый мой проект, на который официальные разработчики положили большой и толстый ## TODO - [x] Убедиться, что критических багов нет - [x] _Возможно_ добавить урон при столкновении со стеной после броска грабом - [x] Локализация и доделать попапы - [x] Тесты на деве для спонсоров - [x] Запрет разговора на удушающем - [x] Выпадение предметов из рук на удушающем ## Техническая информация если б вы знали, как мне впадлу, вы бы расплакались. ## Медиа ыы ## Требования - [ ] Я прочитал(а) и следую [Руководство по созданию пулл реквестов](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html). Я понимаю, что в противном случае мой ПР может быть закрыт по усмотрению мейнтейнера. - [ ] Я добавил скриншоты/видео к этому пулл реквесту, демонстрирующие его изменения в игре, **или** этот пулл реквест не требует демонстрации в игре ## Критические изменения мяу. Тут был Шрёдя @Schrodinger71 **Чейнджлог** :cl: Котя - add: Добавлена механика граба! Ctrl+ЛКМ в комбат моде ещё никогда не был так полезен... - tweak: Дизарм больше не является зависящей от рандома атакой. Каждые 3 удара на ПКМ (подряд!) происходит дизарм/толчок. --------- Co-authored-by: Schrödinger <[email protected]>
- Loading branch information
1 parent
c9c679e
commit e040fa1
Showing
43 changed files
with
1,424 additions
and
42 deletions.
There are no files selected for viewing
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,72 @@ | ||
using Content.Client.Effects; | ||
using Content.Client.Popups; | ||
using Content.Shared.IdentityManagement; | ||
using Content.Shared.Movement.Pulling.Components; | ||
using Content.Shared.Movement.Pulling.Systems; | ||
using Content.Shared.Popups; | ||
using Robust.Client.Audio; | ||
using Robust.Shared.Audio; | ||
using Robust.Shared.Player; | ||
|
||
namespace Content.Client.ADT.Pulling.Systems; | ||
|
||
/// <summary> | ||
/// Allows one entity to pull another behind them via a physics distance joint. | ||
/// </summary> | ||
public sealed partial class ClientPullingSystem : PullingSystem | ||
{ | ||
[Dependency] private readonly PopupSystem _popup = default!; | ||
[Dependency] private readonly AudioSystem _audio = default!; | ||
[Dependency] private readonly ColorFlashEffectSystem _color = default!; | ||
|
||
public override bool TryIncreaseGrabStage(Entity<PullerComponent> puller, Entity<PullableComponent> pullable) | ||
{ | ||
if (!base.TryIncreaseGrabStage(puller, pullable)) | ||
return false; | ||
|
||
var targetStage = puller.Comp.Stage + 1; | ||
// Switch the popup type based on the new grab stage | ||
var popupType = targetStage switch | ||
{ | ||
GrabStage.Soft => PopupType.Small, | ||
GrabStage.Hard => PopupType.SmallCaution, | ||
GrabStage.Choke => PopupType.MediumCaution, | ||
_ => PopupType.Small, | ||
}; | ||
|
||
// Do grab stage change effects | ||
_popup.PopupPredicted( | ||
Loc.GetString($"grab-increase-{targetStage.ToString().ToLower()}-popup-self", | ||
("target", Identity.Entity(pullable, EntityManager))), | ||
Loc.GetString($"grab-increase-{targetStage.ToString().ToLower()}-popup-others", | ||
("target", Identity.Entity(pullable, EntityManager)), | ||
("puller", Identity.Entity(pullable, EntityManager))), | ||
pullable, puller, popupType); | ||
_audio.PlayPredicted(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), pullable, puller); | ||
_color.RaiseEffect(Color.Yellow, new List<EntityUid>() { pullable.Owner }, Filter.Pvs(pullable.Owner)); | ||
|
||
return true; | ||
} | ||
|
||
public override bool TryLowerGrabStage(Entity<PullerComponent> puller, Entity<PullableComponent> pullable, EntityUid user) | ||
{ | ||
if (!base.TryLowerGrabStage(puller, pullable, user)) | ||
return false; | ||
|
||
var targetStage = puller.Comp.Stage - 1; | ||
// Do grab stage change effects | ||
if (user != pullable.Owner) | ||
{ | ||
_popup.PopupPredicted( | ||
Loc.GetString($"grab-lower-{targetStage.ToString().ToLower()}-popup-self", | ||
("target", Identity.Entity(pullable, EntityManager))), | ||
Loc.GetString($"grab-lower-{targetStage.ToString().ToLower()}-popup-others", | ||
("target", Identity.Entity(pullable, EntityManager)), | ||
("puller", Identity.Entity(pullable, EntityManager))), | ||
pullable, puller, PopupType.Small); | ||
_audio.PlayPredicted(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), pullable, puller); | ||
} | ||
|
||
return true; | ||
} | ||
} |
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,127 @@ | ||
using System.Numerics; | ||
using Content.Server.Administration.Logs; | ||
using Content.Server.Popups; | ||
using Content.Shared.ADT.Grab; | ||
using Content.Shared.Database; | ||
using Content.Shared.IdentityManagement; | ||
using Content.Shared.Movement.Pulling.Components; | ||
using Content.Shared.Movement.Pulling.Systems; | ||
using Content.Shared.Popups; | ||
using Content.Shared.Speech; | ||
using Content.Shared.Tag; | ||
using Content.Shared.Throwing; | ||
using Robust.Server.Audio; | ||
using Robust.Server.GameObjects; | ||
using Robust.Shared.Audio; | ||
using Robust.Shared.Map; | ||
using Robust.Shared.Player; | ||
|
||
namespace Content.Server.ADT.Pulling.Systems; | ||
|
||
/// <summary> | ||
/// Allows one entity to pull another behind them via a physics distance joint. | ||
/// </summary> | ||
public sealed partial class ServerPullingSystem : PullingSystem | ||
{ | ||
[Dependency] private readonly PopupSystem _popup = default!; | ||
[Dependency] private readonly AudioSystem _audio = default!; | ||
[Dependency] private readonly ThrowingSystem _throwing = default!; | ||
[Dependency] private readonly TransformSystem _transform = default!; | ||
[Dependency] private readonly IAdminLogManager _adminLogger = default!; | ||
[Dependency] private readonly TagSystem _tag = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<PullableComponent, SpeakAttemptEvent>(OnPullableSpeakAttempt); | ||
} | ||
|
||
private void OnPullableSpeakAttempt(EntityUid uid, PullableComponent comp, SpeakAttemptEvent args) | ||
{ | ||
if (!TryComp<PullerComponent>(comp.Puller, out var puller) || puller.Stage < GrabStage.Choke) | ||
return; | ||
if (_tag.HasTag(uid, "ADTIgnoreChokeSpeechBlocking")) | ||
return; | ||
|
||
// Ran only on server so we dont care about prediction | ||
_popup.PopupEntity(Loc.GetString("grab-speech-attempt-choke"), uid, uid, PopupType.SmallCaution); | ||
args.Cancel(); | ||
} | ||
|
||
public override bool TryIncreaseGrabStage(Entity<PullerComponent> puller, Entity<PullableComponent> pullable) | ||
{ | ||
if (!base.TryIncreaseGrabStage(puller, pullable)) | ||
return false; | ||
|
||
puller.Comp.Stage++; | ||
// Switch the popup type based on the new grab stage | ||
var popupType = puller.Comp.Stage switch | ||
{ | ||
GrabStage.Soft => PopupType.Small, | ||
GrabStage.Hard => PopupType.SmallCaution, | ||
GrabStage.Choke => PopupType.MediumCaution, | ||
_ => PopupType.Small, | ||
}; | ||
|
||
// Do grab stage change effects | ||
_popup.PopupPredicted( | ||
Loc.GetString($"grab-increase-{puller.Comp.Stage.ToString().ToLower()}-popup-self", | ||
("target", Identity.Entity(pullable, EntityManager))), | ||
Loc.GetString($"grab-increase-{puller.Comp.Stage.ToString().ToLower()}-popup-others", | ||
("target", Identity.Entity(pullable, EntityManager)), | ||
("puller", Identity.Entity(pullable, EntityManager))), | ||
pullable, puller, popupType); | ||
_audio.PlayPredicted(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), pullable, puller); | ||
Dirty(puller); | ||
|
||
_adminLogger.Add(LogType.Grab, LogImpact.Low, | ||
$"{ToPrettyString(puller):user} increased grab stage to {puller.Comp.Stage} while grabbing {ToPrettyString(pullable):target}"); | ||
|
||
return true; | ||
} | ||
|
||
public override bool TryLowerGrabStage(Entity<PullerComponent> puller, Entity<PullableComponent> pullable, EntityUid user) | ||
{ | ||
if (!base.TryLowerGrabStage(puller, pullable, user)) | ||
return false; | ||
puller.Comp.Stage--; | ||
|
||
// Do grab stage change effects | ||
if (user != pullable.Owner) | ||
{ | ||
_popup.PopupPredicted( | ||
Loc.GetString($"grab-lower-{puller.Comp.Stage.ToString().ToLower()}-popup-self", | ||
("target", Identity.Entity(pullable, EntityManager))), | ||
Loc.GetString($"grab-lower-{puller.Comp.Stage.ToString().ToLower()}-popup-others", | ||
("target", Identity.Entity(pullable, EntityManager)), | ||
("puller", Identity.Entity(pullable, EntityManager))), | ||
pullable, puller, PopupType.Small); | ||
_audio.PlayPredicted(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), pullable, puller); | ||
} | ||
|
||
Dirty(puller); | ||
|
||
return true; | ||
} | ||
|
||
public override void Throw(Entity<PullerComponent> puller, Entity<PullableComponent> pullable, EntityCoordinates coords) | ||
{ | ||
base.Throw(puller, pullable, coords); | ||
|
||
var xform = Transform(pullable); | ||
var startCoords = _transform.ToMapCoordinates(xform.Coordinates); | ||
var targCoords = _transform.ToMapCoordinates(coords); | ||
Vector2 vector = Vector2.Clamp(targCoords.Position - startCoords.Position, new(-2.5f), new(2.5f)); | ||
Vector2 selfVec = Vector2.Clamp(new(-vector.X, -vector.Y), new(-0.25f), new(0.25f)); | ||
|
||
|
||
_audio.PlayPvs(new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"), pullable); | ||
EnsureComp<GrabThrownComponent>(pullable); | ||
_throwing.TryThrow(pullable, vector, 8, animated: false, playSound: false, doSpin: false); | ||
_throwing.TryThrow(puller, selfVec, 5, animated: false, playSound: false, doSpin: false); | ||
|
||
_adminLogger.Add(LogType.Grab, LogImpact.Low, | ||
$"{ToPrettyString(puller):user} thrown {ToPrettyString(pullable):target} by grab"); | ||
} | ||
} |
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
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
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
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
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 Robust.Shared.GameStates; | ||
|
||
namespace Content.Shared.ADT.Grab; | ||
|
||
[RegisterComponent, NetworkedComponent] | ||
public sealed partial class GrabThrownComponent : Component | ||
{ | ||
public int MaxCollides = 2; | ||
public int CollideCounter = 0; | ||
|
||
public List<EntityUid> HitEntities = new(); | ||
} |
11 changes: 11 additions & 0 deletions
11
Content.Shared/ADT/Grab/Components/ModifyGrabStageTimeComponent.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 @@ | ||
using Content.Shared.Movement.Pulling.Components; | ||
using Robust.Shared.GameStates; | ||
|
||
namespace Content.Shared.ADT.Grab; | ||
|
||
[RegisterComponent, NetworkedComponent] | ||
public sealed partial class ModifyGrabStageTimeComponent : Component | ||
{ | ||
[DataField(required: true)] | ||
public Dictionary<GrabStage, float> Modifiers = new(); | ||
} |
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,8 @@ | ||
using Content.Shared.DoAfter; | ||
using Content.Shared.Movement.Pulling.Components; | ||
using Robust.Shared.Serialization; | ||
|
||
namespace Content.Shared.ADT.Grab; | ||
|
||
[Serializable, NetSerializable] | ||
public sealed partial class GrabEscapeDoAfterEvent : SimpleDoAfterEvent; |
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,6 @@ | ||
using Content.Shared.Movement.Pulling.Components; | ||
|
||
namespace Content.Shared.ADT.Grab; | ||
|
||
[ByRefEvent] | ||
public record struct GrabStageChangedEvent(Entity<PullerComponent> Puller, Entity<PullableComponent> Pulling, GrabStage OldStage, GrabStage NewStage); |
10 changes: 10 additions & 0 deletions
10
Content.Shared/ADT/Grab/Events/ModifyGrabStageTimeEvent.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,10 @@ | ||
using Content.Shared.Inventory; | ||
using Content.Shared.Movement.Pulling.Components; | ||
|
||
namespace Content.Shared.ADT.Grab; | ||
|
||
[ByRefEvent] | ||
public record struct ModifyGrabStageTimeEvent(GrabStage Stage, float Modifier = 1f) : IInventoryRelayEvent | ||
{ | ||
public SlotFlags TargetSlots => SlotFlags.WITHOUT_POCKET; | ||
} |
16 changes: 16 additions & 0 deletions
16
Content.Shared/ADT/Grab/Events/SetGrabStageDoAfterEvent.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,16 @@ | ||
using Content.Shared.DoAfter; | ||
using Content.Shared.Movement.Pulling.Components; | ||
using Robust.Shared.Serialization; | ||
|
||
namespace Content.Shared.ADT.Grab; | ||
|
||
[Serializable, NetSerializable] | ||
public sealed partial class SetGrabStageDoAfterEvent : SimpleDoAfterEvent | ||
{ | ||
public int Direction; | ||
|
||
public SetGrabStageDoAfterEvent(int direction) | ||
{ | ||
Direction = direction; | ||
} | ||
} |
Oops, something went wrong.