diff --git a/Content.Client/_Sunrise/ERP/InteractionEui.cs b/Content.Client/_Sunrise/ERP/InteractionEui.cs index 0f3cc34646..d0c7b52421 100644 --- a/Content.Client/_Sunrise/ERP/InteractionEui.cs +++ b/Content.Client/_Sunrise/ERP/InteractionEui.cs @@ -10,15 +10,15 @@ using Robust.Client.Player; using Robust.Shared.Timing; using Content.Shared.IdentityManagement; + namespace Content.Client._Sunrise.ERP { [UsedImplicitly] public sealed class InteractionEui : BaseEui { - private readonly InteractionWindow _window; + private InteractionWindow _window; public IEntityManager _entManager; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IChatManager _chat = default!; [Dependency] private readonly IPlayerManager _player = default!; @@ -27,7 +27,10 @@ public InteractionEui() { _entManager = IoCManager.Resolve(); _window = new InteractionWindow(this); - _window.OnClose += OnClosed; + _window.OnClose += () => + { + SendMessage(new CloseEuiMessage()); + }; } public override void HandleMessage(EuiMessageBase msg) @@ -67,13 +70,9 @@ public void RequestState() SendMessage(new RequestInteractionState()); } - private void OnClosed() - { - SendMessage(new CloseEuiMessage()); - } - public override void Opened() { + base.Opened(); _window.OpenCenteredLeft(); } @@ -102,10 +101,10 @@ public override void HandleState(EuiStateBase state) public void FrameUpdate(FrameEventArgs args) { - foreach((var item, var time, var text) in _disabledItems) + foreach ((var item, var time, var text) in _disabledItems) { item.Text = text + $" ({(time - _gameTiming.CurTime).Seconds} сек.)"; - if(_gameTiming.CurTime >= time) + if (_gameTiming.CurTime >= time) { item.Text = text; item.Disabled = false; diff --git a/Content.Client/_Sunrise/ERP/InteractionWindow.xaml.cs b/Content.Client/_Sunrise/ERP/InteractionWindow.xaml.cs index 0cc8c2769a..c8089780f9 100644 --- a/Content.Client/_Sunrise/ERP/InteractionWindow.xaml.cs +++ b/Content.Client/_Sunrise/ERP/InteractionWindow.xaml.cs @@ -15,29 +15,33 @@ using Content.Client.Stylesheets; using Content.Shared._Sunrise.ERP.Components; using Content.Client.UserInterface.Controls; + namespace Content.Client._Sunrise.ERP; [GenerateTypedNameReferences] public sealed partial class InteractionWindow : FancyWindow { - private readonly SpriteSystem _spriteSystem; [Dependency] private readonly EntityManager _entManager = default!; [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; + private readonly SpriteSystem _spriteSystem; + private readonly InteractionEui _eui; public NetEntity? TargetEntityId { get; set; } public Sex? UserSex { get; set; } public Sex? TargetSex { get; set; } public bool UserHasClothing { get; set; } public bool TargetHasClothing { get; set; } + + /// + /// ЕРП-статус + /// public bool Erp { get; set; } public HashSet? UserTags { get; set; } public HashSet? TargetTags { get; set; } - public ProgressBar LoveBar; public TimeSpan TimeUntilAllow = TimeSpan.Zero; - private readonly InteractionEui _eui; public TimeSpan UntilUpdate = TimeSpan.Zero; public InteractionWindow(InteractionEui eui) { @@ -61,7 +65,7 @@ public InteractionWindow(InteractionEui eui) ModeButtons.Visible = true; // TODO: Спрайты для описаний. DescriptionButton.Visible = false; - // Dev Windnow + // Dev Window DevButton.Visible = false; } @@ -96,71 +100,99 @@ private void DescriptionPopulate() DescriptionLeft.DisposeAllChildren(); DescriptionRight.DisposeAllChildren(); - if (!_player.LocalEntity.HasValue) return; - if (!UserSex.HasValue) return; - if (!_entManager.TryGetComponent(_player.LocalEntity.Value, out var UserInteraction)) return; - if (!_entManager.TryGetComponent(_player.LocalEntity.Value, out var UserHumanoid)) return; + if (!_player.LocalEntity.HasValue) + return; + + if (!UserSex.HasValue) + return; + + if (!_entManager.TryGetComponent(_player.LocalEntity.Value, out var userInteraction)) + return; + + if (!_entManager.TryGetComponent(_player.LocalEntity.Value, out var userHumanoid)) + return; + SpriteLeft.SetEntity(_player.LocalEntity.Value); - UserName.Text = $"{Identity.Name(_player.LocalEntity.Value, _eui._entManager, _player.LocalEntity.Value)}\n\n{Loc.GetString($"erp-panel-sex-{UserSex.Value.ToString().ToLowerInvariant()}-text")}"; + UserName.Text = $"{Identity.Name(_player.LocalEntity.Value, + _eui._entManager, _player.LocalEntity.Value)}\n\n{Loc.GetString( + $"erp-panel-sex-{UserSex.Value.ToString().ToLowerInvariant()}-text")}"; UserName.SetOnlyStyleClass(StyleNano.StyleClassLabelSmall); - foreach (var i in UserInteraction.GenitalSprites) + + foreach (var sprite in userInteraction.GenitalSprites) { - if (UserHasClothing) break; - var t = new TextureRect(); - t.TexturePath = i; - t.SetSize = new(125, 125); - t.VerticalAlignment = VAlignment.Top; - t.HorizontalAlignment = HAlignment.Center; - t.Stretch = TextureRect.StretchMode.KeepAspectCentered; - t.Modulate = UserHumanoid.SkinColor; - t.Margin = new(15); - DescriptionLeft.AddChild(t); + if (UserHasClothing) + break; + + var texture = new TextureRect(); + + texture.TexturePath = sprite; + texture.SetSize = new(125, 125); + texture.VerticalAlignment = VAlignment.Top; + texture.HorizontalAlignment = HAlignment.Center; + texture.Stretch = TextureRect.StretchMode.KeepAspectCentered; + texture.Modulate = userHumanoid.SkinColor; + texture.Margin = new(15); + DescriptionLeft.AddChild(texture); } var targets = _entManager.GetEntity(TargetEntityId); if (!targets.HasValue) return; var target = targets.Value; - if (!TargetEntityId.HasValue) return; - if (!TargetSex.HasValue) return; - if (!_entManager.TryGetComponent(target, out var TargetInteraction)) return; - if (!_entManager.TryGetComponent(target, out var TargetHumanoid)) return; + + if (!TargetEntityId.HasValue) + return; + + if (!TargetSex.HasValue) + return; + + if (!_entManager.TryGetComponent(target, out var targetInteraction)) + return; + + if (!_entManager.TryGetComponent(target, out var targetHumanoid)) + return; + SpriteRight.SetEntity(target); TargetName.Text = $"{Identity.Name(target, _eui._entManager, _player.LocalEntity.Value)}\n\n{Loc.GetString($"erp-panel-sex-{TargetSex.Value.ToString().ToLowerInvariant()}-text")}"; TargetName.SetOnlyStyleClass(StyleNano.StyleClassLabelSmall); - foreach (var i in TargetInteraction.GenitalSprites) + foreach (var sprite in targetInteraction.GenitalSprites) { - if (TargetHasClothing) break; - var t = new TextureRect(); - t.TexturePath = i; - t.SetSize = new(125, 125); - t.VerticalAlignment = VAlignment.Top; - t.HorizontalAlignment = HAlignment.Center; - t.Stretch = TextureRect.StretchMode.KeepAspectCentered; - t.Margin = new(15); - t.Modulate = TargetHumanoid.SkinColor; - DescriptionRight.AddChild(t); + if (TargetHasClothing) + break; + + var texture = new TextureRect(); + texture.TexturePath = sprite; + texture.SetSize = new(125, 125); + texture.VerticalAlignment = VAlignment.Top; + texture.HorizontalAlignment = HAlignment.Center; + texture.Stretch = TextureRect.StretchMode.KeepAspectCentered; + texture.Margin = new(15); + texture.Modulate = targetHumanoid.SkinColor; + DescriptionRight.AddChild(texture); } } private void DevPopulate() { - if (!_player.LocalEntity.HasValue) return; + if (!_player.LocalEntity.HasValue) + return; if (UserTags != null) { - foreach (var i in UserTags) + foreach (var tag in UserTags) { - DevLeft.AddItem(i, null, false); + DevLeft.AddItem(tag, null, false); } } - if (!TargetEntityId.HasValue) return; + + if (!TargetEntityId.HasValue) + return; if (TargetTags != null) { - foreach (var i in TargetTags) + foreach (var tag in TargetTags) { - DevRight.AddItem(i, null, false); + DevRight.AddItem(tag, null, false); } } } @@ -172,10 +204,15 @@ private void SearchBarOnOnTextChanged(LineEdit.LineEditEventArgs obj) private List<(string, Robust.Client.Graphics.Texture, InteractionPrototype)> oldItemList = new(); private void PopulateByFilter(string filter, bool check = true) { - if (!_player.LocalEntity.HasValue) return; - if (!TargetEntityId.HasValue) return; + if (!_player.LocalEntity.HasValue) + return; + + if (!TargetEntityId.HasValue) + return; + var uid = _player.LocalEntity.Value; var protos = _prototypeManager.EnumeratePrototypes().ToArray(); + Array.Sort(protos, (x, y) => x.SortOrder.CompareTo(y.SortOrder)); List<(string, Robust.Client.Graphics.Texture, InteractionPrototype)> itemList = new(); foreach (string category in new List @@ -191,56 +228,61 @@ private void PopulateByFilter(string filter, bool check = true) { if (_entManager.TryGetComponent(uid, out var hands)) { - if (hands.ActiveHand == null) continue; - if (hands.ActiveHand.Container == null) continue; - if (!hands.ActiveHand.Container.ContainedEntity.HasValue) continue; - if (!_entManager.TryGetComponent(hands.ActiveHand.Container.ContainedEntity.Value, out var meta)) continue; - if (meta.EntityPrototype == null) continue; - if (!proto.InhandObject.Contains(meta.EntityPrototype.ID)) continue; + if (hands.ActiveHand == null) + continue; + + if (hands.ActiveHand.Container == null) + continue; + + if (!hands.ActiveHand.Container.ContainedEntity.HasValue) + continue; + + if (!_entManager.TryGetComponent(hands.ActiveHand.Container.ContainedEntity.Value, out var meta)) + continue; + + if (meta.EntityPrototype == null) + continue; + + if (!proto.InhandObject.Contains(meta.EntityPrototype.ID)) + continue; } - else continue; } - if (proto.Category.ToLower() != category) continue; - if (_entManager.GetEntity(TargetEntityId.Value) == _player.LocalEntity.Value && !proto.UseSelf) continue; - if (_entManager.GetEntity(TargetEntityId.Value) != _player.LocalEntity.Value && proto.UseSelf) continue; + + if (proto.Category.ToLower() != category) + continue; + + if (_entManager.GetEntity(TargetEntityId.Value) == _player.LocalEntity.Value && !proto.UseSelf) + continue; + + if (_entManager.GetEntity(TargetEntityId.Value) != _player.LocalEntity.Value && proto.UseSelf) + continue; + if (string.IsNullOrEmpty(filter) || proto.Name.ToLowerInvariant().Contains(filter.Trim().ToLowerInvariant())) { var texture = _spriteSystem.Frame0(proto.Icon); - if (UserHasClothing && proto.UserWithoutCloth) continue; - if (TargetHasClothing && proto.TargetWithoutCloth) continue; - if (UserSex != proto.UserSex && proto.UserSex != Sex.Unsexed) continue; - if (TargetSex != proto.TargetSex && proto.TargetSex != Sex.Unsexed) continue; - if (!Erp && proto.Erp) continue; - if (UserTags != null) - { - if (proto.UserTagWhitelist.Count > 0) - { - foreach (var tag in proto.UserTagWhitelist) - { - if (!UserTags.Contains(tag)) goto CONTINUE; - } - } - foreach (var tag in UserTags) - { - if (proto.UserTagBlacklist.Contains(tag)) goto CONTINUE; - } - } - if (TargetTags != null) - { - if (proto.TargetTagWhitelist.Count > 0) - { - foreach (var tag in proto.TargetTagWhitelist) - { - if (!TargetTags.Contains(tag)) goto CONTINUE; - } - } - foreach (var tag in TargetTags) - { - if (proto.TargetTagBlacklist.Contains(tag)) goto CONTINUE; - } - } + if (UserHasClothing && proto.UserWithoutCloth) + continue; + + if (TargetHasClothing && proto.TargetWithoutCloth) + continue; + + if (UserSex != proto.UserSex && proto.UserSex != Sex.Unsexed) + continue; + + if (TargetSex != proto.TargetSex && proto.TargetSex != Sex.Unsexed) + continue; + + if (!Erp && proto.Erp) + continue; + + if (!AreTagsAllowed(UserTags, proto.UserTagWhitelist, proto.UserTagBlacklist)) + goto CONTINUE; + + if (!AreTagsAllowed(TargetTags, proto.TargetTagWhitelist, proto.TargetTagBlacklist)) + goto CONTINUE; + //ItemInteractions.AddItem(proto.Name, texture, metadata: proto); itemList.Add((proto.Name, texture, proto)); } @@ -291,47 +333,60 @@ protected override void FrameUpdate(FrameEventArgs args) public void Populate() { var prototypes = _prototypeManager.EnumeratePrototypes().ToList(); + UserDescription.DisposeAllChildren(); TargetDescription.DisposeAllChildren(); + //Проверки nullable-типов - if (!TargetEntityId.HasValue) return; - if (!UserSex.HasValue) return; - if (!TargetSex.HasValue) return; - if (!_player.LocalEntity.HasValue) return; + if (!TargetEntityId.HasValue || !UserSex.HasValue || + !TargetSex.HasValue || !_player.LocalEntity.HasValue) + return; - if (!TargetEntityId.Value.Valid) return; + if (!TargetEntityId.Value.Valid) + return; //Аминь if (Erp) { //Юзер UserDescription.AddChild(new Label { Text = "Вы...", StyleClasses = { StyleNano.StyleClassLabelBig } }); ; - if (UserHasClothing) UserDescription.AddChild(new Label { Text = "...Обладаете одеждой" }); - else UserDescription.AddChild(new Label { Text = "...Не обладаете одеждой" }); UserDescription.AddChild(new Label { Text = "...Обладаете анусом" }); - if (UserSex.Value == Sex.Male) UserDescription.AddChild(new Label { Text = "...Обладаете пенисом" }); - if (UserSex.Value == Sex.Female) UserDescription.AddChild(new Label { Text = "...Обладаете вагиной" }); - if (UserSex.Value == Sex.Female) UserDescription.AddChild(new Label { Text = "...Обладаете грудью" }); + + if (UserHasClothing) + UserDescription.AddChild(new Label { Text = "...Обладаете одеждой" }); + else UserDescription.AddChild(new Label { Text = "...Не обладаете одеждой" }); + + if (UserSex.Value == Sex.Male) + UserDescription.AddChild(new Label { Text = "...Обладаете пенисом" }); + + if (UserSex.Value == Sex.Female) + { + UserDescription.AddChild(new Label { Text = "...Обладаете вагиной" }); + UserDescription.AddChild(new Label { Text = "...Обладаете грудью" }); + } //Таргет if (_entManager.GetEntity(TargetEntityId.Value) != _player.LocalEntity.Value) { TargetDescription.AddChild(new Label { Text = Identity.Name(_eui._entManager.GetEntity(TargetEntityId.Value), _eui._entManager, _player.LocalEntity.Value) + "...", StyleClasses = { StyleNano.StyleClassLabelBig } }); - if (TargetHasClothing) TargetDescription.AddChild(new Label { Text = "...Обладает одеждой" }); + if (TargetHasClothing) + TargetDescription.AddChild(new Label { Text = "...Обладает одеждой" }); else { TargetDescription.AddChild(new Label { Text = "...Не обладает одеждой" }); TargetDescription.AddChild(new Label { Text = "...Обладает анусом" }); - if (TargetSex.Value == Sex.Male) TargetDescription.AddChild(new Label { Text = "...Обладает пенисом" }); - if (TargetSex.Value == Sex.Female) TargetDescription.AddChild(new Label { Text = "...Обладает вагиной" }); + + if (TargetSex.Value == Sex.Male) + TargetDescription.AddChild(new Label { Text = "...Обладает пенисом" }); + + if (TargetSex.Value == Sex.Female) + TargetDescription.AddChild(new Label { Text = "...Обладает вагиной" }); + } - if (TargetSex.Value == Sex.Female) TargetDescription.AddChild(new Label { Text = "...Обладает грудью" }); + if (TargetSex.Value == Sex.Female) + TargetDescription.AddChild(new Label { Text = "...Обладает грудью" }); } - - } - else - { - ErpProgress.Dispose(); } + else ErpProgress.Dispose(); if (DescriptionContainer.Visible) { @@ -343,4 +398,32 @@ public void Populate() } ItemInteractions.OnItemSelected += _eui.OnItemSelect; } + + private static bool AreTagsAllowed(HashSet? tags, HashSet whiteListTags, HashSet blackListTags) + { + + if (tags != null) + { + if (whiteListTags.Count > 0) + { + foreach (var tag in whiteListTags) + { + if (tags.Contains(tag)) + return true; + } + return false; + } + + if (blackListTags.Count > 0) + { + foreach (var tag in blackListTags) + { + if (tags.Contains(tag)) + return false; + } + } + } + + return true; + } } diff --git a/Content.Server/_Sunrise/ERP/Systems/InteractionEui.cs b/Content.Server/_Sunrise/ERP/Systems/InteractionEui.cs index a07a9b864a..fba8dc5c22 100644 --- a/Content.Server/_Sunrise/ERP/Systems/InteractionEui.cs +++ b/Content.Server/_Sunrise/ERP/Systems/InteractionEui.cs @@ -4,13 +4,13 @@ using JetBrains.Annotations; using Content.Shared._Sunrise.ERP; using Content.Shared.Humanoid; -using Content.Shared._Sunrise.ERP.Components; using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; using Robust.Shared.Random; using Robust.Shared.Timing; using Robust.Shared.Prototypes; using System.Linq; + namespace Content.Server._Sunrise.ERP.Systems { [UsedImplicitly] diff --git a/Content.Server/_Sunrise/ERP/Systems/InteractionSystem.cs b/Content.Server/_Sunrise/ERP/Systems/InteractionSystem.cs index 5f6b7985c2..a56be196e1 100644 --- a/Content.Server/_Sunrise/ERP/Systems/InteractionSystem.cs +++ b/Content.Server/_Sunrise/ERP/Systems/InteractionSystem.cs @@ -1,5 +1,4 @@ // © SUNRISE, An EULA/CLA with a hosting restriction, full text: https://github.com/space-sunrise/lust-station/blob/master/CLA.txt - using System.Diagnostics.CodeAnalysis; using Content.Server.Body.Components; using Content.Server.Body.Systems; @@ -19,10 +18,10 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.FixedPoint; using Content.Shared.Hands.Components; -using Content.Shared.Humanoid.Prototypes; -using Robust.Shared.Prototypes; +using Content.Shared.Ghost; +using Content.Shared.GameTicking; +using Content.Server.GameTicking; namespace Content.Server._Sunrise.ERP.Systems { @@ -35,6 +34,7 @@ public sealed class InteractionSystem : EntitySystem [Dependency] private readonly PuddleSystem _puddle = default!; [Dependency] private readonly BloodstreamSystem _bloodstream = default!; [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly GameTicker _gameTicker = default!; public static string DefaultBloodSolutionName = "bloodstream"; public static string DefaultChemicalsSolutionName = "chemicals"; @@ -60,169 +60,183 @@ public sealed class InteractionSystem : EntitySystem {"Felinid", DefaultLactationSolution}, {"Vulpkanin", DefaultLactationSolution}, }; - + private readonly Dictionary _openUis = new(); public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnComponentInit); SubscribeLocalEvent>(AddVerbs); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(Reset); } - public (Sex, bool, Sex, bool, bool, HashSet, HashSet, float)? RequestMenu(EntityUid User, EntityUid Target) + private void OnComponentInit(EntityUid uid, InteractionComponent component, ComponentInit args) { - if (GetInteractionData(User, Target, out var dataNullable)) { - if (dataNullable.HasValue) - { - var data = dataNullable.Value; - return (data.Item1, data.Item2, data.Item3, data.Item4, data.Item5, data.Item6, data.Item7, data.Item8); - } - return null; - } - return null; } + private void AddVerbs(EntityUid uid, InteractionComponent comp, GetVerbsEvent args) + { + if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) + return; + if (!args.CanInteract || !args.CanAccess) + return; - public bool GetInteractionData(EntityUid user, EntityUid target, out (Sex, bool, Sex, bool, bool, HashSet, HashSet, float)? data) + var player = actor.PlayerSession; + + args.Verbs.Add(new Verb + { + Priority = 9, + Text = "Взаимодействовать с...", + Icon = new SpriteSpecifier.Texture(new("/Textures/_Lust/Interface/ERP/heart.png")), + Act = () => OpenInteractionEui(player, args), + Impact = LogImpact.Low, + }); + } + + private void OnPlayerAttached(PlayerAttachedEvent message) + { + + if (!_openUis.ContainsKey(message.Player)) + return; + + if (!HasComp(message.Entity)) + return; + + CloseEui(message.Player); + } + + public void Reset(RoundRestartCleanupEvent ev) { - if (TryComp(target, out var targetInteraction) && TryComp(user, out var userInteraction)) + foreach (var session in _openUis.Keys) { + CloseEui(session); + } - bool erp = true; - bool userClothing = false; - bool targetClothing = false; - if (!targetInteraction.Erp || !userInteraction.Erp) erp = false; + _openUis.Clear(); + } - HashSet userTags = new(); - HashSet targetTags = new(); + public bool GetInteractionData(EntityUid user, EntityUid target, out (Sex, bool, Sex, bool, bool, HashSet, HashSet, float)? data) + { + data = null; - if (TryComp(user, out var container)) - { - if (container.Containers.TryGetValue("jumpsuit", out var userJumpsuit)) - if (userJumpsuit.ContainedEntities.Count != 0) userClothing = true; - if (container.Containers.TryGetValue("outerClothing", out var userOuterClothing)) - if (userOuterClothing.ContainedEntities.Count != 0) userClothing = true; + if (!TryComp(target, out var targetInteraction) || !TryComp(user, out var userInteraction)) + return false; - foreach (var c in container.Containers) - { - if (c.Value.ContainedEntities.Count != 0) userTags.Add(c.Key); - foreach (var value in c.Value.ContainedEntities) - { - var m = MetaData(value); - if (m.EntityPrototype != null) - { - var s = m.EntityPrototype.ID; - userTags.Add(s); - userTags.Add(s + "Unstrict"); - var parents = m.EntityPrototype.Parents; - if (parents != null) - { - foreach (var parent in parents) - { - userTags.Add(parent + "Unstrict"); - } - } - } - } - } - } + bool erp = true; + bool userClothing = CheckClothing(user, out var userTags); + bool targetClothing = CheckClothing(target, out var targetTags); - if (TryComp(target, out var targetContainer)) + if (!targetInteraction.Erp || !userInteraction.Erp) + erp = false; + + var (userSex, targetSex) = SexCheck(user, target, userTags, targetTags); + + data = (userSex, userClothing, targetSex, targetClothing, erp, userTags, targetTags, userInteraction.Love); + return true; + } + + private bool CheckClothing(EntityUid uid, out HashSet tags) + { + tags = new HashSet(); + + if (!TryComp(uid, out var containerManager)) + return false; + + bool hasClothing = false; + + foreach (var container in containerManager.Containers) + { + if (container.Value.ContainedEntities.Count > 0) { - if (targetContainer.Containers.TryGetValue("jumpsuit", out var targetJumpsuit)) - if (targetJumpsuit.ContainedEntities.Count != 0) targetClothing = true; - if (targetContainer.Containers.TryGetValue("outerClothing", out var targetOuterClothing)) - if (targetOuterClothing.ContainedEntities.Count != 0) targetClothing = true; + tags.Add(container.Key); + hasClothing |= container.Key == "jumpsuit" || container.Key == "outerClothing"; + } - foreach (var c in targetContainer.Containers) + foreach (var value in container.Value.ContainedEntities) + { + var meta = MetaData(value); + if (meta.EntityPrototype != null) { - if (c.Value.ContainedEntities.Count != 0) targetTags.Add(c.Key); - foreach (var value in c.Value.ContainedEntities) + var proto = meta.EntityPrototype.ID; + tags.Add(proto); + tags.Add(proto + "Unstrict"); + if (meta.EntityPrototype.Parents != null) { - var m = MetaData(value); - if (m.EntityPrototype != null) + foreach (var parent in meta.EntityPrototype.Parents) { - var s = m.EntityPrototype.ID; - targetTags.Add(s); - targetTags.Add(s + "Unstrict"); - var parents = m.EntityPrototype.Parents; - if (parents != null) - { - foreach (var parent in parents) - { - targetTags.Add(parent + "Unstrict"); - } - } + tags.Add(parent + "Unstrict"); } } } } + } - var userSex = Sex.Unsexed; - var targetSex = Sex.Unsexed; + return hasClothing; + } - if (TryComp(target, out var targetHumanoid) && TryComp(user, out var userHumanoid)) - { - foreach (var spec in userHumanoid.MarkingSet.Markings) - { - userTags.Add(spec.Key.ToString()); - foreach (var val in spec.Value) - { - userTags.Add(val.MarkingId); - } - } + private (Sex userSex, Sex targetSex) SexCheck(EntityUid user, EntityUid target, HashSet userTags, HashSet targetTags) + { + var userSex = Sex.Unsexed; + var targetSex = Sex.Unsexed; - foreach (var spec in targetHumanoid.MarkingSet.Markings) - { - targetTags.Add(spec.Key.ToString()); - foreach (var val in spec.Value) - { - targetTags.Add(val.MarkingId); - } - } + if (TryComp(user, out var userHumanoid)) + { + AddTagsFromMarkings(userHumanoid, userTags); + userTags.Add(userHumanoid.Species.Id); + userSex = userHumanoid.Sex; + } - userTags.Add(userHumanoid.Species.Id); - targetTags.Add(targetHumanoid.Species.Id); - targetSex = targetHumanoid.Sex; - userSex = userHumanoid.Sex; - } + if (TryComp(target, out var targetHumanoid)) + { + AddTagsFromMarkings(targetHumanoid, targetTags); + targetTags.Add(targetHumanoid.Species.Id); + targetSex = targetHumanoid.Sex; + } - if (TryComp(target, out var targetSexComp)) targetSex = targetSexComp.Sex; - if (TryComp(user, out var userSexComp)) userSex = userSexComp.Sex; + userSex = TryComp(user, out var userSexComp) ? userSexComp.Sex : userSex; + targetSex = TryComp(target, out var targetSexComp) ? targetSexComp.Sex : targetSex; - data = (userSex, userClothing, targetSex, targetClothing, erp, userTags, targetTags, userInteraction.Love); - return true; - } - data = null; - return false; + return (userSex, targetSex); } + private void AddTagsFromMarkings(HumanoidAppearanceComponent humanoid, HashSet tags) + { + foreach (var spec in humanoid.MarkingSet.Markings) + { + tags.Add(spec.Key.ToString()); + foreach (var val in spec.Value) + { + tags.Add(val.MarkingId); + } + } + } public void ProcessInteraction(NetEntity user, NetEntity target, InteractionPrototype prototype) { - var User = GetEntity(user); - var Target = GetEntity(target); + var netUser = GetEntity(user); + var netTarget = GetEntity(target); - foreach(var entity in new List {User, Target}) + foreach (var entity in new List {netUser, netTarget}) { if (!TryComp(entity, out var interaction)) continue; //Virginity check - if((entity == User && prototype.UserVirginityLoss == VirginityLoss.anal || - entity == Target && prototype.TargetVirginityLoss == VirginityLoss.anal) && + if ((entity == netUser && prototype.UserVirginityLoss == VirginityLoss.anal || + entity == netTarget && prototype.TargetVirginityLoss == VirginityLoss.anal) && interaction.AnalVirginity == Virginity.Yes) { interaction.AnalVirginity = Virginity.No; _chat.TrySendInGameICMessage(entity, "лишается анальной девственности", InGameICChatType.Emote, false); } - if (entity == User && _random.Prob(prototype.UserMoanChance) || - entity == Target && _random.Prob(prototype.TargetMoanChance)) _chat.TryEmoteWithChat(entity, "Moan", ChatTransmitRange.Normal); + if (entity == netUser && _random.Prob(prototype.UserMoanChance) || + entity == netTarget && _random.Prob(prototype.TargetMoanChance)) _chat.TryEmoteWithChat(entity, "Moan", ChatTransmitRange.Normal); if (TryComp(entity, out var humanoid)) { - switch(humanoid.Sex) + switch (humanoid.Sex) { case Sex.Male: - if ((entity == User && prototype.UserVirginityLoss == VirginityLoss.male || - entity == Target && prototype.TargetVirginityLoss == VirginityLoss.male) && + if ((entity == netUser && prototype.UserVirginityLoss == VirginityLoss.male || + entity == netTarget && prototype.TargetVirginityLoss == VirginityLoss.male) && interaction.Virginity == Virginity.Yes) { interaction.Virginity = Virginity.No; @@ -230,8 +244,8 @@ public void ProcessInteraction(NetEntity user, NetEntity target, InteractionProt } break; case Sex.Female: - if ((entity == User && prototype.UserVirginityLoss == VirginityLoss.female || - entity == Target && prototype.TargetVirginityLoss == VirginityLoss.female) && + if ((entity == netUser && prototype.UserVirginityLoss == VirginityLoss.female || + entity == netTarget && prototype.TargetVirginityLoss == VirginityLoss.female) && interaction.Virginity == Virginity.Yes) { interaction.Virginity = Virginity.No; @@ -246,7 +260,7 @@ public void ProcessInteraction(NetEntity user, NetEntity target, InteractionProt // Process Lactation if (prototype.LactationStimulationFlag) { - HandleLactation(ref User, ref Target, ref prototype); + HandleLactation(ref netUser, ref netTarget, ref prototype); } } @@ -351,104 +365,114 @@ public void AddLove(NetEntity entity, NetEntity target, int percentUser, int per { var User = GetEntity(entity); var Target = GetEntity(target); - if (!TryComp(User, out var compUser)) return; - if (!TryComp(Target, out var compTarget)) return; - if (percentUser != 0) + if (!TryComp(User, out var compUser)) + return; + + if (!TryComp(Target, out var compTarget)) + return; + + UpdateLove(ref compUser, percentUser, User, "EffectHearts"); + UpdateLove(ref compTarget, percentTarget, Target, "EffectHearts"); + } + + private void UpdateLove(ref InteractionComponent comp, int percent, EntityUid entity, string effect) + { + if (percent == 0) + return; + + if (_gameTiming.CurTime > comp.LoveDelay) { - if (_gameTiming.CurTime > compUser.LoveDelay) - { - compUser.ActualLove += (percentUser + _random.Next(-percentUser / 2, percentUser / 2)) / 100f; - compUser.TimeFromLastErp = _gameTiming.CurTime; - } - Spawn("EffectHearts", Transform(User).Coordinates); + comp.ActualLove += (percent + _random.Next(-percent / 2, percent / 2)) / 100f; + comp.TimeFromLastErp = _gameTiming.CurTime; } - if (compUser.Love >= 1) + Spawn(effect, Transform(entity).Coordinates); + + if (comp.Love >= 1) { - compUser.ActualLove = 0; - compUser.Love = 0.95f; - compUser.LoveDelay = _gameTiming.CurTime + TimeSpan.FromMinutes(1); - _chat.TrySendInGameICMessage(User, "кончает!", InGameICChatType.Emote, false); - if(TryComp(User, out var humuser)) + comp.ActualLove = 0; + comp.Love = 0.95f; + comp.LoveDelay = _gameTiming.CurTime + TimeSpan.FromMinutes(1); + _chat.TrySendInGameICMessage(entity, "кончает!", InGameICChatType.Emote, false); + + if (TryComp(entity, out var humanoid) && humanoid.Sex == Sex.Male) { - if(humuser.Sex == Sex.Male) - { - Spawn("PuddleSemen", Transform(User).Coordinates); - } + Spawn("PuddleSemen", Transform(entity).Coordinates); } } + } - if (percentTarget != 0) + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) { - if (_gameTiming.CurTime > compTarget.LoveDelay) + float loveChange = (comp.Love - comp.ActualLove) * frameTime; + comp.Love -= loveChange; + if (_gameTiming.CurTime - comp.TimeFromLastErp > TimeSpan.FromSeconds(15) && comp.Love > 0) { - compTarget.ActualLove += (percentTarget + _random.Next(-percentTarget / 2, percentTarget / 2)) / 100f; - compTarget.TimeFromLastErp = _gameTiming.CurTime; + comp.ActualLove = MathF.Max(0, comp.ActualLove - 0.001f); } - Spawn("EffectHearts", Transform(Target).Coordinates); + + if (comp.Love < 0.00001) + comp.Love = 0; + + if (comp.ActualLove < 0) + comp.ActualLove = 0; } - if (compTarget.Love >= 1) - { - compTarget.ActualLove = 0; - compTarget.Love = 0.95f; - compTarget.LoveDelay = _gameTiming.CurTime + TimeSpan.FromMinutes(1); - _chat.TrySendInGameICMessage(Target, "кончает!", InGameICChatType.Emote, false); - if (TryComp(Target, out var taruser)) + } + + public (Sex, bool, Sex, bool, bool, HashSet, HashSet, float)? RequestMenu(EntityUid User, EntityUid Target) + { + if (GetInteractionData(User, Target, out var dataNullable)) { + if (dataNullable.HasValue) { - if (taruser.Sex == Sex.Male) - { - Spawn("PuddleSemen", Transform(Target).Coordinates); - } + var data = dataNullable.Value; + return (data.Item1, data.Item2, data.Item3, data.Item4, data.Item5, data.Item6, data.Item7, data.Item8); } + return null; } + return null; } - private void AddVerbs(EntityUid uid, InteractionComponent comp, GetVerbsEvent args) + + + public void OpenInteractionEui(ICommonSession player, GetVerbsEvent args) { - if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) + + if (!_gameTicker.PlayerGameStatuses.TryGetValue(player.UserId, out var status)) return; - var player = actor.PlayerSession; - if (!args.CanInteract || !args.CanAccess) return; - args.Verbs.Add(new Verb - { - Priority = 9, - Text = "Взаимодействовать с...", - Icon = new SpriteSpecifier.Texture(new("/Textures/_Lust/Interface/ERP/heart.png")), - Act = () => - { - if (!args.CanInteract || !args.CanAccess) return; - if (GetInteractionData(args.User, args.Target, out var dataNullable)) - { - if (dataNullable.HasValue) - { - var data = dataNullable.Value; - _eui.OpenEui(new InteractionEui(GetNetEntity(args.User), GetNetEntity(args.Target), data.Item1, data.Item2, data.Item3, data.Item4, data.Item5, data.Item6, data.Item7), player); - } - } - }, - Impact = LogImpact.Low, - }); - } + if ((player.AttachedEntity is not { Valid: true } attached || + EntityManager.HasComponent(attached)) && status != PlayerGameStatus.NotReadyToPlay) + CloseEui(player); - public override void Update(float frameTime) - { - base.Update(frameTime); + if (!args.CanInteract || !args.CanAccess) + return; - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var comp)) + if (_openUis.ContainsKey(player)) + CloseEui(player); + + if (GetInteractionData(args.User, args.Target, out var dataNullable)) { - comp.Love -= ((comp.Love - comp.ActualLove) / 1) * frameTime; - if (_gameTiming.CurTime - comp.TimeFromLastErp > TimeSpan.FromSeconds(15) && comp.Love > 0) + if (dataNullable.HasValue) { - comp.ActualLove -= 0.001f; + var data = dataNullable.Value; + var eui = _openUis[player] = new InteractionEui(GetNetEntity(args.User), GetNetEntity(args.Target), data.Item1, data.Item2, data.Item3, data.Item4, data.Item5, data.Item6, data.Item7); + _eui.OpenEui(eui, player); } - if (comp.Love < 0) comp.Love = 0; - if (comp.ActualLove < 0) comp.ActualLove = 0; } } - private void OnComponentInit(EntityUid uid, InteractionComponent component, ComponentInit args) + public void CloseEui(ICommonSession session) { + if (!_openUis.ContainsKey(session)) + return; + + _openUis.Remove(session, out var eui); + + eui?.Close(); } } }