-
-
Notifications
You must be signed in to change notification settings - Fork 225
Модуль похоти киборга #480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
04043c1
d59896a
0c02a27
fd6fcb5
89b1c4f
37d5151
3830d1a
45f77f6
0daabf7
c9e213f
1773750
e1ca220
a44ae64
5c08df0
9640747
3f6b7a2
d4f42b0
f9533b5
45e3c12
dffd74e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| using Robust.Shared.GameStates; | ||
| using Robust.Shared.Prototypes; | ||
|
|
||
| namespace Content.Server._Lust.Silicons.Borgs; | ||
|
|
||
| /// <summary> | ||
| /// Компонент, позволяющий давать боргам действия (экшены) и компоненты через модуль | ||
| /// </summary> | ||
| [RegisterComponent] | ||
| public sealed partial class BorgModuleInnateComponent : Component | ||
| { | ||
| /// <summary> | ||
| /// Предметы, которые активируются прямо в руке | ||
| /// </summary> | ||
| [DataField] | ||
| public List<EntProtoId?> UseItems = new(); | ||
|
|
||
| /// <summary> | ||
| /// Предметы, с помощью которых можно взаимодействовать с сущностями | ||
| /// </summary> | ||
| [DataField] | ||
| public List<EntProtoId?> InteractionItems = new(); | ||
|
|
||
| /// <summary> | ||
| /// Компоненты, которые будут добавлены боргу при установке модуля | ||
| /// Будут удалены после его изъятия! | ||
| /// </summary> | ||
| [DataField] | ||
| public ComponentRegistry InnateComponents = new(); | ||
|
|
||
| /// <summary> | ||
| /// Айди добавленных предметов этим модулем | ||
| /// Данный список нужен сугубо для корректной очистки | ||
| /// </summary> | ||
| [ViewVariables, Access(typeof(BorgModuleInnateSystem))] | ||
| public List<EntityUid> InnateItems = new(); | ||
|
|
||
| /// <summary> | ||
| /// Экшены для борга, созданные данным модулем | ||
| /// Данный список нужен сугубо для корректной очистки | ||
| /// </summary> | ||
| [ViewVariables, Access(typeof(BorgModuleInnateSystem))] | ||
| public List<EntityUid> Actions = new(); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,214 @@ | ||||||||||
| using Content.Shared._Lust.Silicons.Borgs; | ||||||||||
| using Content.Shared.Actions; | ||||||||||
| using Content.Shared.Interaction; | ||||||||||
| using Content.Shared.Interaction.Events; | ||||||||||
| using Content.Shared.Silicons.Borgs.Components; | ||||||||||
| using Content.Shared.UserInterface; | ||||||||||
| using Robust.Shared.Containers; | ||||||||||
| using Robust.Shared.Prototypes; | ||||||||||
| using Robust.Shared.Utility; | ||||||||||
|
|
||||||||||
| namespace Content.Server._Lust.Silicons.Borgs; | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Система выдачи встраиваемых предметов и компонентов через модуль. | ||||||||||
| /// </summary> | ||||||||||
| public sealed class BorgModuleInnateSystem : EntitySystem | ||||||||||
| { | ||||||||||
| [Dependency] private readonly SharedActionsSystem _actions = default!; | ||||||||||
| [Dependency] private readonly ActionContainerSystem _actionContainer = default!; | ||||||||||
| [Dependency] private readonly SharedContainerSystem _containers = default!; | ||||||||||
| [Dependency] private readonly MetaDataSystem _metadata = default!; | ||||||||||
| [Dependency] private readonly SharedInteractionSystem _interactions = default!; | ||||||||||
|
|
||||||||||
| // Название контейнера-хранилища встроенных предметов | ||||||||||
| private const string InnateItemsContainerId = "module_innate_items"; | ||||||||||
|
|
||||||||||
| // Прототипы действий над предметами | ||||||||||
| private static readonly EntProtoId InnateUseItemAction = "ModuleInnateUseItemAction"; | ||||||||||
| private static readonly EntProtoId InnateInteractionItemAction = "ModuleInnateInteractionItemAction"; | ||||||||||
|
|
||||||||||
| public override void Initialize() | ||||||||||
| { | ||||||||||
| base.Initialize(); | ||||||||||
|
|
||||||||||
| SubscribeLocalEvent<BorgModuleInnateComponent, BorgModuleInstalledEvent>(OnInstalled); | ||||||||||
| SubscribeLocalEvent<BorgModuleInnateComponent, BorgModuleUninstalledEvent>(OnUninstalled); | ||||||||||
|
|
||||||||||
| SubscribeLocalEvent<BorgModuleInnateComponent, ModuleInnateUseItem>(OnInnateUseItem); | ||||||||||
| SubscribeLocalEvent<BorgModuleInnateComponent, ModuleInnateInteractionItem>(OnInnateInteractionItem); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Добавляет нужные компоненты и предметы при "установке" модуля | ||||||||||
| /// </summary> | ||||||||||
| private void OnInstalled(Entity<BorgModuleInnateComponent> module, ref BorgModuleInstalledEvent args) | ||||||||||
| { | ||||||||||
| var containerManager = EnsureComp<ContainerManagerComponent>(args.ChassisEnt); | ||||||||||
| _containers.EnsureContainer<Container>(args.ChassisEnt, InnateItemsContainerId, containerManager); | ||||||||||
|
|
||||||||||
| EntityManager.AddComponents(args.ChassisEnt, module.Comp.InnateComponents); | ||||||||||
|
|
||||||||||
| if (!_containers.TryGetContainer(args.ChassisEnt, InnateItemsContainerId, out var container)) | ||||||||||
| return; | ||||||||||
|
|
||||||||||
| AddItems(args.ChassisEnt, module, container); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Удаляет нужные компоненты и предметы при "удалении" модуля | ||||||||||
| /// </summary> | ||||||||||
| private void OnUninstalled(Entity<BorgModuleInnateComponent> module, ref BorgModuleUninstalledEvent args) | ||||||||||
| { | ||||||||||
| foreach (var action in module.Comp.Actions) | ||||||||||
| { | ||||||||||
| _actions.RemoveAction(args.ChassisEnt, action); | ||||||||||
| QueueDel(action); | ||||||||||
| } | ||||||||||
| foreach (var item in module.Comp.InnateItems) | ||||||||||
| QueueDel(item); | ||||||||||
|
|
||||||||||
| module.Comp.Actions.Clear(); | ||||||||||
| module.Comp.InnateItems.Clear(); | ||||||||||
|
|
||||||||||
| EntityManager.RemoveComponents(args.ChassisEnt, module.Comp.InnateComponents); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Добавляет предметы в контейнер, а также создаёт экшены их активации в модуле для тела киборга | ||||||||||
| /// </summary> | ||||||||||
| private void AddItems(EntityUid chassis, Entity<BorgModuleInnateComponent> module, BaseContainer container) | ||||||||||
| { | ||||||||||
| foreach (var itemProto in module.Comp.UseItems) | ||||||||||
| { | ||||||||||
| if (itemProto is null) | ||||||||||
| continue; | ||||||||||
|
|
||||||||||
| AddUseItem(itemProto.Value, chassis, module, container); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| foreach (var itemProto in module.Comp.InteractionItems) | ||||||||||
| { | ||||||||||
| if (itemProto is null) | ||||||||||
| continue; | ||||||||||
|
|
||||||||||
| AddInteractionItem(itemProto.Value, chassis, module, container); | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Добавляет предмет, который активируется в руке, вместе с экшеном для его активации | ||||||||||
| /// </summary> | ||||||||||
| private void AddUseItem( | ||||||||||
| EntProtoId itemProto, | ||||||||||
| EntityUid chassis, | ||||||||||
| Entity<BorgModuleInnateComponent> module, | ||||||||||
| BaseContainer container | ||||||||||
| ) | ||||||||||
| { | ||||||||||
| var item = CreateInnateItem(itemProto, module, container); | ||||||||||
| var ev = new ModuleInnateUseItem(item); | ||||||||||
| var action = CreateAction(item, ev, InnateUseItemAction); | ||||||||||
| AssignAction(chassis, module, action); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Добавляет предмет, который активируется выбором цели, вместе с экшеном для его активации | ||||||||||
| /// </summary> | ||||||||||
| private void AddInteractionItem( | ||||||||||
| EntProtoId itemProto, | ||||||||||
| EntityUid chassis, | ||||||||||
| Entity<BorgModuleInnateComponent> module, | ||||||||||
| BaseContainer container | ||||||||||
| ) | ||||||||||
| { | ||||||||||
| var item = CreateInnateItem(itemProto, module, container); | ||||||||||
| var ev = new ModuleInnateInteractionItem(item); | ||||||||||
| var action = CreateAction(item, ev, InnateInteractionItemAction); | ||||||||||
| AssignAction(chassis, module, action); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Создает предмет для использования через экшены согласно прототипу в заданном контейнере | ||||||||||
| /// </summary> | ||||||||||
| /// <returns>Сущность предмета</returns> | ||||||||||
| private EntityUid CreateInnateItem( | ||||||||||
| EntProtoId itemProto, | ||||||||||
| Entity<BorgModuleInnateComponent> module, | ||||||||||
| BaseContainer container | ||||||||||
| ) | ||||||||||
| { | ||||||||||
| var item = Spawn(itemProto); | ||||||||||
| module.Comp.InnateItems.Add(item); | ||||||||||
|
|
||||||||||
| // Модифицируем компач юай, чтобы борг наверняка мог его использовать | ||||||||||
| if (TryComp<ActivatableUIComponent>(item, out var activatableUIComponent)) | ||||||||||
| { | ||||||||||
| activatableUIComponent.RequiresComplex = false; | ||||||||||
| activatableUIComponent.InHandsOnly = false; | ||||||||||
| activatableUIComponent.RequireActiveHand = false; | ||||||||||
| Dirty(item, activatableUIComponent); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Сохраняем его в контейнере предметов модуля | ||||||||||
| _containers.Insert(item, container); | ||||||||||
|
|
||||||||||
| return item; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Согласно прототипу и событию создает экшен для активации данной сущности-предмета | ||||||||||
| /// </summary> | ||||||||||
| /// <returns>Сущность экшена</returns> | ||||||||||
| private EntityUid CreateAction(EntityUid item, BaseActionEvent assignedEvent, EntProtoId actionProto) | ||||||||||
| { | ||||||||||
| var actionEnt = Spawn(actionProto); | ||||||||||
| // Подгружаем спрайт для экшена из прото предмета | ||||||||||
| _actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(MetaData(item).EntityPrototype!.ID)); | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Оператор
🛡️ Предлагаемое исправление- _actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(MetaData(item).EntityPrototype!.ID));
+ var proto = MetaData(item).EntityPrototype;
+ if (proto != null)
+ _actions.SetIcon(actionEnt, new SpriteSpecifier.EntityPrototype(proto.ID));📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут надо думать - система предполагает, что все предметы созданы по прототипу как-никак. И в самой системе так и есть.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Использование Оставляйте как есть, если считаете, что это соответствует архитектурным гарантиям системы. 👍 🧠 Learnings used |
||||||||||
| // Заготовка события для экшена | ||||||||||
| _actions.SetEvent(actionEnt, assignedEvent); | ||||||||||
|
|
||||||||||
| // Даем экшену название и описание предмета | ||||||||||
| _metadata.SetEntityName(actionEnt, MetaData(item).EntityName); | ||||||||||
| _metadata.SetEntityDescription(actionEnt, MetaData(item).EntityDescription); | ||||||||||
| return actionEnt; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Добавляет экшен в шасси и сохраняет его в контейнере модуля | ||||||||||
| /// </summary> | ||||||||||
| private void AssignAction(EntityUid chassis, Entity<BorgModuleInnateComponent> module, EntityUid action) | ||||||||||
| { | ||||||||||
| // Добавляем экшн в список экшенов и в список компача | ||||||||||
| _actionContainer.AddAction(module.Owner, action); | ||||||||||
| _actions.AddAction(chassis, action, module.Owner); | ||||||||||
| module.Comp.Actions.Add(action); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Обработчик события использования предмета как будто он в руке | ||||||||||
| /// </summary> | ||||||||||
| private void OnInnateUseItem(Entity<BorgModuleInnateComponent> ent, ref ModuleInnateUseItem args) | ||||||||||
| { | ||||||||||
| var ev = new UseInHandEvent(args.Performer); | ||||||||||
| RaiseLocalEvent(args.Item, ev); | ||||||||||
| args.Handled = true; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// <summary> | ||||||||||
| /// Обработчик события использования предмета на заданной цели | ||||||||||
| /// </summary> | ||||||||||
| private void OnInnateInteractionItem(Entity<BorgModuleInnateComponent> ent, ref ModuleInnateInteractionItem args) | ||||||||||
| { | ||||||||||
| _interactions.InteractUsing( | ||||||||||
| args.Performer, | ||||||||||
| args.Item, | ||||||||||
| args.Target, | ||||||||||
| Transform(args.Target).Coordinates, | ||||||||||
| false, | ||||||||||
| false, | ||||||||||
| false | ||||||||||
| ); | ||||||||||
| args.Handled = true; | ||||||||||
| } | ||||||||||
| } | ||||||||||
Uh oh!
There was an error while loading. Please reload this page.