From 2ec981e9e6c7d387f5df8f14e1c17fe0369f795d Mon Sep 17 00:00:00 2001 From: Cinka Date: Fri, 23 Feb 2024 18:52:03 +0300 Subject: [PATCH] - add: interaction part 2 --- .../InteractionPanel/InteractionPanelEui.cs | 28 ++++- .../InteractionPanelWindow.xaml | 51 --------- .../InteractionPanelWindow.xaml.cs | 16 --- .../UI/InteractionPanelButton.xaml | 12 ++ .../UI/InteractionPanelButton.xaml.cs | 35 ++++++ .../UI/InteractionPanelWindow.xaml | 42 +++++++ .../UI/InteractionPanelWindow.xaml.cs | 40 +++++++ .../InteractionPanel/InteractionPanelEui.cs | 53 ++++++++- .../InteractionPanelSystem.cs | 105 ++++++++++++++++-- .../_Amour/InteractionPanel/Interactions.cs | 38 +++++++ .../InteractionPanel/Checks/Distance.cs | 18 +++ .../_Amour/InteractionPanel/Checks/Hole.cs | 83 ++++++++++++++ .../InteractionPanel/Checks/Interaction.cs | 17 +++ .../InteractionPanel/IInteractionCheck.cs | 18 +++ .../InteractionPanelComponent.cs | 18 +++ .../InteractionPanel/InteractionPanelEvent.cs | 33 ++++++ .../InteractionPanelMessages.cs | 35 ++++++ .../InteractionPanelSystem.cs | 11 ++ .../InteractionPanel/InteractionPrototype.cs | 23 ++++ .../Prototypes/Entities/Mobs/Species/base.yml | 3 + .../Prototypes/_Amour/Entities/Holes/base.yml | 2 +- .../_Amour/Interactions/interaction.yml | 6 + 22 files changed, 608 insertions(+), 79 deletions(-) delete mode 100644 Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml delete mode 100644 Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml.cs create mode 100644 Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml create mode 100644 Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml.cs create mode 100644 Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml create mode 100644 Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml.cs create mode 100644 Content.Server/_Amour/InteractionPanel/Interactions.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/Checks/Distance.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/Checks/Hole.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/Checks/Interaction.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/IInteractionCheck.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/InteractionPanelComponent.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/InteractionPanelEvent.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/InteractionPanelMessages.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/InteractionPanelSystem.cs create mode 100644 Content.Shared/_Amour/InteractionPanel/InteractionPrototype.cs create mode 100644 Resources/Prototypes/_Amour/Interactions/interaction.yml diff --git a/Content.Client/_Amour/InteractionPanel/InteractionPanelEui.cs b/Content.Client/_Amour/InteractionPanel/InteractionPanelEui.cs index bc6aa4c42d..e5fcefe426 100644 --- a/Content.Client/_Amour/InteractionPanel/InteractionPanelEui.cs +++ b/Content.Client/_Amour/InteractionPanel/InteractionPanelEui.cs @@ -1,16 +1,40 @@ using Content.Client.Eui; +using Content.Shared._Amour.InteractionPanel; using Content.Shared.Eui; namespace Content.Client._Amour.InteractionPanel; public sealed class InteractionPanelEui : BaseEui { - private InteractionPanelWindow _interactionPanelWindow; + private readonly IEntityManager _entityManager; + + private UI.InteractionPanelWindow _interactionPanelWindow; + private InteractionState _interactionState = default!; public InteractionPanelEui() { - _interactionPanelWindow = new InteractionPanelWindow(); + IoCManager.InjectDependencies(this); + _entityManager = IoCManager.Resolve(); + + _interactionPanelWindow = new UI.InteractionPanelWindow(); _interactionPanelWindow.OnClose += () => SendMessage(new CloseEuiMessage()); + _interactionPanelWindow.OnInteraction += InteractionPanelWindowOnInteraction; + } + + private void InteractionPanelWindowOnInteraction(string id) + { + SendMessage(new InteractionSelectedMessage(id)); + } + + public override void HandleState(EuiStateBase state) + { + base.HandleState(state); + + if(state is not InteractionState interactionState) + return; + + _interactionState = interactionState; + _interactionPanelWindow.Update(_interactionState); } public override void Closed() diff --git a/Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml b/Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml deleted file mode 100644 index 65bfbb025b..0000000000 --- a/Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml.cs b/Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml.cs deleted file mode 100644 index a0f59a42c9..0000000000 --- a/Content.Client/_Amour/InteractionPanel/InteractionPanelWindow.xaml.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Robust.Client.AutoGenerated; -using Robust.Client.UserInterface; -using Robust.Client.UserInterface.CustomControls; -using Robust.Client.UserInterface.XAML; - -namespace Content.Client._Amour.InteractionPanel; - -[GenerateTypedNameReferences] -public sealed partial class InteractionPanelWindow : DefaultWindow -{ - public InteractionPanelWindow() - { - RobustXamlLoader.Load(this); - } -} - diff --git a/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml new file mode 100644 index 0000000000..05f0875d0e --- /dev/null +++ b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml.cs b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml.cs new file mode 100644 index 0000000000..afe738a8ce --- /dev/null +++ b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelButton.xaml.cs @@ -0,0 +1,35 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._Amour.InteractionPanel.UI; + +[GenerateTypedNameReferences] +public sealed partial class InteractionPanelButton : ContainerButton +{ + public event Action? OnInteraction; + + private string _interactionId = "Interaction"; + public string InteractionId + { + get => _interactionId; + set + { + _interactionId = value; + InteractionName.Text = Loc.GetString($"interaction-name-{_interactionId.ToLower()}"); + } + } + + public InteractionPanelButton() + { + RobustXamlLoader.Load(this); + OnPressed += OnOnPressed; + } + + private void OnOnPressed(ButtonEventArgs obj) + { + OnInteraction?.Invoke(InteractionId); + } +} + diff --git a/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml new file mode 100644 index 0000000000..e96c2e42ab --- /dev/null +++ b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml.cs b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml.cs new file mode 100644 index 0000000000..5f93dbc3fa --- /dev/null +++ b/Content.Client/_Amour/InteractionPanel/UI/InteractionPanelWindow.xaml.cs @@ -0,0 +1,40 @@ +using Content.Shared._Amour.InteractionPanel; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._Amour.InteractionPanel.UI; + +[GenerateTypedNameReferences] +public sealed partial class InteractionPanelWindow : DefaultWindow +{ + public event Action? OnInteraction; + + public InteractionPanelWindow() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + } + + public void AddButton(string id) + { + var btn = new InteractionPanelButton(); + btn.InteractionId = id; + btn.OnInteraction += _id => OnInteraction?.Invoke(_id); + Interactions.AddChild(btn); + } + + public void Update(InteractionState state) + { + Interactions.Children.Clear(); + + TargetView.SetEntity(state.Target); + PerformerView.SetEntity(state.Performer); + + foreach (var interaction in state.AvailableInteractions) + { + AddButton(interaction); + } + } +} + diff --git a/Content.Server/_Amour/InteractionPanel/InteractionPanelEui.cs b/Content.Server/_Amour/InteractionPanel/InteractionPanelEui.cs index 5dc718272d..97471a14aa 100644 --- a/Content.Server/_Amour/InteractionPanel/InteractionPanelEui.cs +++ b/Content.Server/_Amour/InteractionPanel/InteractionPanelEui.cs @@ -1,11 +1,60 @@ -using Content.Server.EUI; +using System.Linq; +using Content.Server.EUI; +using Content.Server.Interaction; +using Content.Shared._Amour.Arousal; +using Content.Shared._Amour.InteractionPanel; +using Content.Shared.Eui; +using Robust.Shared.Prototypes; namespace Content.Server._Amour.InteractionPanel; public sealed class InteractionPanelEui : BaseEui { - public InteractionPanelEui() + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public readonly Entity User; + public readonly Entity Target; + + public InteractionPanelEui(Entity user, Entity target) { IoCManager.InjectDependencies(this); + + User = user; + Target = target; + } + + public override void Opened() + { + base.Opened(); + StateDirty(); + } + + public override EuiStateBase GetNewState() + { + byte? arousal = null; + if (_entityManager.TryGetComponent(User, out var arousalComponent)) + arousal = (byte) (arousalComponent.Arousal / 100 * 255); + + var availableActions = new HashSet(); + foreach (var protoId in Target.Comp.ActionPrototypes) + { + if(!_prototypeManager.TryIndex(protoId,out var prototype) + || !prototype.Checks.All(check => check.IsAvailable(User,Target,_entityManager))) + continue; + availableActions.Add(protoId); + } + + + return new InteractionState(_entityManager.GetNetEntity(User), _entityManager.GetNetEntity(Target),availableActions,arousal); + } + + public override void HandleMessage(EuiMessageBase msg) + { + base.HandleMessage(msg); + if (msg is InteractionSelectedMessage selectedMessage && Target.Comp.ActionPrototypes.Contains(selectedMessage.Id)) + { + _entityManager.System().Interact(User.Owner,Target.Owner,selectedMessage.Id); + } } } diff --git a/Content.Server/_Amour/InteractionPanel/InteractionPanelSystem.cs b/Content.Server/_Amour/InteractionPanel/InteractionPanelSystem.cs index df4d4f0a93..8fdb768aee 100644 --- a/Content.Server/_Amour/InteractionPanel/InteractionPanelSystem.cs +++ b/Content.Server/_Amour/InteractionPanel/InteractionPanelSystem.cs @@ -1,7 +1,17 @@ -using Content.Server.EUI; +using System.Linq; +using Content.Server.Chat.Systems; +using Content.Server.EUI; using Content.Shared._Amour.Hole; +using Content.Shared._Amour.InteractionPanel; +using Content.Shared.Emoting; +using Content.Shared.Random.Helpers; using Content.Shared.Verbs; +using Robust.Server.Audio; using Robust.Server.Player; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; namespace Content.Server._Amour.InteractionPanel; @@ -9,19 +19,100 @@ public sealed class InteractionPanelSystem : EntitySystem { [Dependency] private readonly EuiManager _eui = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly ChatSystem _chatSystem = default!; + [Dependency] private readonly AudioSystem _audioSystem = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + public override void Initialize() { - SubscribeLocalEvent>(OnVerb); + SubscribeLocalEvent>(OnVerb); + SubscribeLocalEvent(OnInit); } - private void OnVerb(EntityUid uid, HoleContainerComponent component, GetVerbsEvent args) + private void OnInit(EntityUid uid, InteractionPanelComponent component, ComponentInit args) + { + component.Timeout = _gameTiming.CurTime; + } + + private void OnVerb(EntityUid uid, InteractionPanelComponent component, GetVerbsEvent args) { - if(!_playerManager.TryGetSessionByEntity(uid, out var session)) - return; args.Verbs.Add(new Verb() { - Text = "MEOW", - Act = () => _eui.OpenEui(new InteractionPanelEui(), session) + Text = "Open funny panel", + Act = () => OpenPanel(args.User,args.User,uid) }); } + + public void OpenPanel(EntityUid panelOpener, Entity user, + Entity target) + { + if(!Resolve(user,ref user.Comp) || !Resolve(target,ref target.Comp) + || !_playerManager.TryGetSessionByEntity(panelOpener, out var session)) + return; + + _eui.OpenEui(new InteractionPanelEui( + new Entity(user,user.Comp), + new Entity(target,target.Comp)), + session); + } + + public void Interact(Entity user, + Entity target, ProtoId protoId) + { + //TODO: Пиздец... пиздец.... пиздец.... + if( !Resolve(user,ref user.Comp) + || !Resolve(target,ref target.Comp) + || user.Comp.IsActive || user.Comp.IsBlocked + || target.Comp.IsActive || target.Comp.IsBlocked + || !_prototypeManager.TryIndex(protoId, out var prototype) + || !prototype.Checks.All(check => check.IsAvailable(user!,target!,EntityManager))) + return; + + user.Comp.Timeout = _gameTiming.CurTime + prototype.Timeout; + user.Comp.IsActive = true; + user.Comp.CurrentAction = protoId; + user.Comp.CurrentPartner = new Entity(target,target.Comp); + + if(prototype.BeginningMessages.Count > 0) + _chatSystem.TrySendInGameICMessage(user,_robustRandom.Pick(prototype.BeginningMessages),InGameICChatType.Emote,false); + + if (prototype.BeginningSound is not null) + _audioSystem.PlayPvs(prototype.BeginningSound, user); + + + RaiseLocalEvent(user,new InteractionBeginningEvent(protoId,user!,target!)); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var component)) + { + if(component.Timeout > _gameTiming.CurTime || !component.IsActive) + continue; + + if (component.CurrentPartner is null) + { + continue; + } + + if (_prototypeManager.TryIndex(component.CurrentAction, out var prototype)) + { + if(prototype.EndingMessages.Count > 0) + _chatSystem.TrySendInGameICMessage(uid,_robustRandom.Pick(prototype.EndingMessages),InGameICChatType.Emote,false); + + if (prototype.EndingSound is not null) + _audioSystem.PlayPvs(prototype.EndingSound, uid); + } + + + component.IsActive = false; + RaiseLocalEvent(uid, new InteractionEndingEvent(component.CurrentAction, + new Entity(uid,component), + component.CurrentPartner.Value)); + } + } } diff --git a/Content.Server/_Amour/InteractionPanel/Interactions.cs b/Content.Server/_Amour/InteractionPanel/Interactions.cs new file mode 100644 index 0000000000..890cf4d6f0 --- /dev/null +++ b/Content.Server/_Amour/InteractionPanel/Interactions.cs @@ -0,0 +1,38 @@ +using Content.Shared._Amour.InteractionPanel; + +namespace Content.Server._Amour.InteractionPanel; + +public sealed class Interactions : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(OnBegin); + SubscribeLocalEvent(OnEnd); + } + + private void OnEnd(EntityUid uid, InteractionPanelComponent component, InteractionEndingEvent args) + { + if(args.Handled) + return; + + Logger.Debug(args.Id + " END"); + + switch (args.Id) + { + + } + } + + private void OnBegin(EntityUid uid, InteractionPanelComponent component, InteractionBeginningEvent args) + { + if(args.Handled) + return; + + Logger.Debug(args.Id + " START"); + + switch (args.Id) + { + + } + } +} diff --git a/Content.Shared/_Amour/InteractionPanel/Checks/Distance.cs b/Content.Shared/_Amour/InteractionPanel/Checks/Distance.cs new file mode 100644 index 0000000000..11e707e246 --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/Checks/Distance.cs @@ -0,0 +1,18 @@ +using Content.Shared.Interaction; + +namespace Content.Shared._Amour.InteractionPanel.Checks; + +public sealed class HasSmallDistance : IInteractionCheck +{ + [DataField] private readonly float _range = SharedInteractionSystem.InteractionRange; + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + var transformSystem = entityManager.System(); + + if (_range <= 0) + return true; + + var distance = (transformSystem.GetWorldPosition(user) - transformSystem.GetWorldPosition(target)).Length(); + return distance <= _range; + } +} diff --git a/Content.Shared/_Amour/InteractionPanel/Checks/Hole.cs b/Content.Shared/_Amour/InteractionPanel/Checks/Hole.cs new file mode 100644 index 0000000000..2c3aec482f --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/Checks/Hole.cs @@ -0,0 +1,83 @@ +using Content.Shared._Amour.Hole; + +namespace Content.Shared._Amour.InteractionPanel.Checks; + +public sealed class UserHasButt : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(user.Owner, "Anus", out _); + } +} + +public sealed class TargetHasButt : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(target.Owner, "Anus", out _); + } +} + +public sealed class UserHasPenis : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(user.Owner, "Dick", out _); + } +} + +public sealed class TargetHasPenis : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(target.Owner, "Dick", out _); + } +} + +public sealed class UserHasVagina : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(user.Owner, "Vagina", out _); + } +} + +public sealed class TargetHasVagina : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(target.Owner, "Vagina", out _); + } +} + +public sealed class UserHasTesticles : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(user.Owner, "Testicles", out _); + } +} + +public sealed class TargetHasTesticles : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(target.Owner, "Testicles", out _); + } +} + +public sealed class UserHasBreast : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(user.Owner, "Breast", out _); + } +} + +public sealed class TargetHasBreast : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return entityManager.System().TryFind(target.Owner, "Breast", out _); + } +} diff --git a/Content.Shared/_Amour/InteractionPanel/Checks/Interaction.cs b/Content.Shared/_Amour/InteractionPanel/Checks/Interaction.cs new file mode 100644 index 0000000000..b3cc722703 --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/Checks/Interaction.cs @@ -0,0 +1,17 @@ +namespace Content.Shared._Amour.InteractionPanel.Checks; + +public sealed class InteractSelf : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return user == target; + } +} + +public sealed class CantInteractSelf: IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + return user != target; + } +} diff --git a/Content.Shared/_Amour/InteractionPanel/IInteractionCheck.cs b/Content.Shared/_Amour/InteractionPanel/IInteractionCheck.cs new file mode 100644 index 0000000000..4389821238 --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/IInteractionCheck.cs @@ -0,0 +1,18 @@ +using Content.Shared._Amour.Hole; + +namespace Content.Shared._Amour.InteractionPanel; + +public interface IInteractionCheck +{ + public bool IsAvailable(Entity user, + Entity target,IEntityManager entityManager); +} + +public sealed class BasicCheck : IInteractionCheck +{ + public bool IsAvailable(Entity user, Entity target, IEntityManager entityManager) + { + Logger.Debug("MEWO!!"); + return true; + } +} diff --git a/Content.Shared/_Amour/InteractionPanel/InteractionPanelComponent.cs b/Content.Shared/_Amour/InteractionPanel/InteractionPanelComponent.cs new file mode 100644 index 0000000000..0c12227f86 --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/InteractionPanelComponent.cs @@ -0,0 +1,18 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._Amour.InteractionPanel; + +[RegisterComponent] +public sealed partial class InteractionPanelComponent : Component +{ + [ViewVariables] public bool IsActive = false; + [ViewVariables] public bool IsBlocked = false; + [ViewVariables] public ProtoId CurrentAction; + [ViewVariables] public TimeSpan Timeout; + [ViewVariables] public Entity? CurrentPartner; + + [DataField] public List> ActionPrototypes = new(); +} + diff --git a/Content.Shared/_Amour/InteractionPanel/InteractionPanelEvent.cs b/Content.Shared/_Amour/InteractionPanel/InteractionPanelEvent.cs new file mode 100644 index 0000000000..7776191f3b --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/InteractionPanelEvent.cs @@ -0,0 +1,33 @@ +using Content.Shared.Actions; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._Amour.InteractionPanel; + +public abstract class InteractionBaseEvent : HandledEntityEventArgs +{ + public ProtoId Id; + public Entity Performer; + public Entity Target; + + protected InteractionBaseEvent(ProtoId id, Entity performer, Entity target) + { + Id = id; + Performer = performer; + Target = target; + } +} + +public sealed class InteractionBeginningEvent : InteractionBaseEvent +{ + public InteractionBeginningEvent(ProtoId id, Entity performer, Entity target) : base(id, performer, target) + { + } +} + +public sealed class InteractionEndingEvent : InteractionBaseEvent +{ + public InteractionEndingEvent(ProtoId id, Entity performer, Entity target) : base(id, performer, target) + { + } +} diff --git a/Content.Shared/_Amour/InteractionPanel/InteractionPanelMessages.cs b/Content.Shared/_Amour/InteractionPanel/InteractionPanelMessages.cs new file mode 100644 index 0000000000..5b1226f25a --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/InteractionPanelMessages.cs @@ -0,0 +1,35 @@ +using Content.Shared.Eui; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._Amour.InteractionPanel; + +[Serializable,NetSerializable] +public sealed class InteractionSelectedMessage : EuiMessageBase +{ + public string Id; + + public InteractionSelectedMessage(string id) + { + Id = id; + } +} + + +[Serializable,NetSerializable] +public sealed class InteractionState: EuiStateBase +{ + public NetEntity Performer { get; } + public NetEntity Target { get; } + public HashSet AvailableInteractions; + public byte? Arousal; + + public InteractionState(NetEntity performer, NetEntity target, HashSet availableInteractions, byte? arousal) + { + Performer = performer; + Target = target; + AvailableInteractions = availableInteractions; + Arousal = arousal; + } +} + diff --git a/Content.Shared/_Amour/InteractionPanel/InteractionPanelSystem.cs b/Content.Shared/_Amour/InteractionPanel/InteractionPanelSystem.cs new file mode 100644 index 0000000000..05d50b2380 --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/InteractionPanelSystem.cs @@ -0,0 +1,11 @@ +using Content.Shared.Actions; + +namespace Content.Shared._Amour.InteractionPanel; + +public sealed class InteractionPanelSystem : EntitySystem +{ + public override void Initialize() + { + + } +} diff --git a/Content.Shared/_Amour/InteractionPanel/InteractionPrototype.cs b/Content.Shared/_Amour/InteractionPanel/InteractionPrototype.cs new file mode 100644 index 0000000000..a8dd760679 --- /dev/null +++ b/Content.Shared/_Amour/InteractionPanel/InteractionPrototype.cs @@ -0,0 +1,23 @@ +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._Amour.InteractionPanel; + +[Prototype("interaction")] +public sealed partial class InteractionPrototype : IPrototype +{ + [IdDataField] public string ID { get; private set; } = default!; + [ViewVariables] public PrototypeLayerData? Icon; + + [ViewVariables] public SoundSpecifier? BeginningSound; + [ViewVariables] public SoundSpecifier? EndingSound; + + [DataField] public List BeginningMessages = new(); + [DataField] public List EndingMessages = new(); + + [DataField] public List Checks = new(); + + [DataField] public TimeSpan Timeout = TimeSpan.Zero; +} + diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index fcd9dae591..a09be229ff 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -265,6 +265,9 @@ - type: Mood - type: HoleContainer - type: Arousal + - type: InteractionPanel + actionPrototypes: + - basic - type: entity save: false diff --git a/Resources/Prototypes/_Amour/Entities/Holes/base.yml b/Resources/Prototypes/_Amour/Entities/Holes/base.yml index 509f8990a4..6845307e4f 100644 --- a/Resources/Prototypes/_Amour/Entities/Holes/base.yml +++ b/Resources/Prototypes/_Amour/Entities/Holes/base.yml @@ -95,7 +95,7 @@ name: Яички components: - type: Hole - holeName: Dick + holeName: Testicles holeNotVisibleIn: - suitstorage - outerClothing diff --git a/Resources/Prototypes/_Amour/Interactions/interaction.yml b/Resources/Prototypes/_Amour/Interactions/interaction.yml new file mode 100644 index 0000000000..7c9c134f65 --- /dev/null +++ b/Resources/Prototypes/_Amour/Interactions/interaction.yml @@ -0,0 +1,6 @@ +- type: interaction + id: basic + checks: + - !type:HasSmallDistance + beginningMessages: + - шлёпает по попе