using Content.Shared._Horizon.NPC; using Content.Shared.Verbs; using Robust.Shared.Utility; using Robust.Shared.Prototypes; using Content.Server.Chat.Systems; using Content.Shared.Mobs.Systems; namespace Content.Server._Horizon.NPC { public sealed class DialogueSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly ChatSystem _chatSystem = default!; [Dependency] private readonly MobStateSystem _mobState = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent>(AddDialogueVerbs); } private void AddDialogueVerbs(EntityUid uid, DialogueComponent component, GetVerbsEvent args) { if (!args.CanInteract || !args.CanAccess) return; if (!TryComp(uid, out var state)) return; switch (state.State) { case DialogueState.Idle: var talkVerb = new InteractionVerb { Act = () => StartDialogue(uid, args.User, component), Text = Loc.GetString("verb-dialogue-talk"), Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/sentient.svg.192dpi.png")), Priority = 2 }; args.Verbs.Add(talkVerb); break; case DialogueState.Talking when state.CurrentResponse == "follow": AddResponseVerbs(uid, args.User, args); break; case DialogueState.Following: var stopFollowVerb = new InteractionVerb { Act = () => StopFollow(uid, args.User), Text = Loc.GetString("verb-dialogue-stop-follow"), Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/close.svg.192dpi.png")), Priority = 3 }; args.Verbs.Add(stopFollowVerb); break; } } private void AddResponseVerbs(EntityUid npc, EntityUid user, GetVerbsEvent args) { var replyCategory = new VerbCategory(Loc.GetString("verb-dialogue-reply-category"), "/Textures/Interface/VerbIcons/information.svg.192dpi.png"); var acceptVerb = new InteractionVerb { Act = () => AcceptFollow(npc, user), Text = Loc.GetString("verb-dialogue-accept"), Category = replyCategory, Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")), Priority = 1 }; args.Verbs.Add(acceptVerb); var declineVerb = new InteractionVerb { Act = () => DeclineFollow(npc, user), Text = Loc.GetString("verb-dialogue-decline"), Category = replyCategory, Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), Priority = 2 }; args.Verbs.Add(declineVerb); } public void StartDialogue(EntityUid npc, EntityUid user, DialogueComponent? component = null) { if (!Resolve(npc, ref component)) return; if (_mobState.IsDead(npc) || EntityManager.IsQueuedForDeletion(npc)) return; var state = EnsureComp(npc); state.State = DialogueState.Talking; if (!_prototypeManager.TryIndex(component.DialogueTree, out var dialogueTree)) return; DialogueEntry? dialogue = null; foreach (var entry in dialogueTree.Dialogues) { if (entry.Id == "start") { dialogue = entry; break; } } if (dialogue != null && dialogue.Responses.Count > 0) { state.CurrentResponse = dialogue.Responses[0].Action; _chatSystem.TrySendInGameICMessage( npc, dialogue.Text, InGameICChatType.Speak, false ); } } private void AcceptFollow(EntityUid npc, EntityUid user) { if (_mobState.IsDead(npc) || EntityManager.IsQueuedForDeletion(npc)) return; if (!TryComp(npc, out var state)) return; state.State = DialogueState.Following; state.CurrentResponse = null; _chatSystem.TrySendInGameICMessage( npc, Loc.GetString("dialogue-npc-accept-follow"), InGameICChatType.Speak, false ); var follow = EnsureComp(npc); follow.Target = user; } private void DeclineFollow(EntityUid npc, EntityUid user) { if (!TryComp(npc, out var state)) return; state.State = DialogueState.Idle; state.CurrentResponse = null; _chatSystem.TrySendInGameICMessage( npc, Loc.GetString("dialogue-npc-decline-follow"), InGameICChatType.Speak, false ); } private void StopFollow(EntityUid npc, EntityUid user) { if (!TryComp(npc, out var state)) return; state.State = DialogueState.Idle; RemComp(npc); _chatSystem.TrySendInGameICMessage( npc, Loc.GetString("dialogue-npc-stop-follow"), InGameICChatType.Speak, false ); } private void AddStateVerbs(EntityUid uid, DialogueStateComponent component, GetVerbsEvent args) { // Этот метод будет вызван автоматически для всех сущностей с DialogueStateComponent // Здесь можно добавить дополнительную логику если нужно } } }