forked from space-wizards/space-station-14
-
Notifications
You must be signed in to change notification settings - Fork 161
/
Copy pathSharedImplanterSystem.cs
230 lines (188 loc) · 8.75 KB
/
SharedImplanterSystem.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Forensics;
using Content.Shared.IdentityManagement;
using Content.Shared.Implants.Components;
using Content.Shared.Popups;
using Content.Shared.SS220.ChemicalImplant;
using Content.Shared.Whitelist;
using Robust.Shared.Containers;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Implants;
public abstract class SharedImplanterSystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ImplanterComponent, ComponentInit>(OnImplanterInit);
SubscribeLocalEvent<ImplanterComponent, EntInsertedIntoContainerMessage>(OnEntInserted);
SubscribeLocalEvent<ImplanterComponent, ExaminedEvent>(OnExamine);
}
private void OnImplanterInit(EntityUid uid, ImplanterComponent component, ComponentInit args)
{
if (component.Implant != null)
component.ImplanterSlot.StartingItem = component.Implant;
_itemSlots.AddItemSlot(uid, ImplanterComponent.ImplanterSlotId, component.ImplanterSlot);
}
private void OnEntInserted(EntityUid uid, ImplanterComponent component, EntInsertedIntoContainerMessage args)
{
var implantData = EntityManager.GetComponent<MetaDataComponent>(args.Entity);
component.ImplantData = (implantData.EntityName, implantData.EntityDescription);
}
private void OnExamine(EntityUid uid, ImplanterComponent component, ExaminedEvent args)
{
if (!component.ImplanterSlot.HasItem || !args.IsInDetailsRange)
return;
args.PushMarkup(Loc.GetString("implanter-contained-implant-text", ("desc", component.ImplantData.Item2)));
}
//Instantly implant something and add all necessary components and containers.
//Set to draw mode if not implant only
public void Implant(EntityUid user, EntityUid target, EntityUid implanter, ImplanterComponent component)
{
if (!CanImplant(user, target, implanter, component, out var implant, out var implantComp))
return;
//If the target doesn't have the implanted component, add it.
var implantedComp = EnsureComp<ImplantedComponent>(target);
var implantContainer = implantedComp.ImplantContainer;
if (component.ImplanterSlot.ContainerSlot != null)
_container.Remove(implant.Value, component.ImplanterSlot.ContainerSlot);
implantComp.ImplantedEntity = target;
implantContainer.OccludesLight = false;
_container.Insert(implant.Value, implantContainer);
if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly)
DrawMode(implanter, component);
else
ImplantMode(implanter, component);
var ev = new TransferDnaEvent { Donor = target, Recipient = implanter };
RaiseLocalEvent(target, ref ev);
Dirty(component);
}
public bool CanImplant(
EntityUid user,
EntityUid target,
EntityUid implanter,
ImplanterComponent component,
[NotNullWhen(true)] out EntityUid? implant,
[NotNullWhen(true)] out SubdermalImplantComponent? implantComp)
{
implant = component.ImplanterSlot.ContainerSlot?.ContainedEntities.FirstOrNull();
if (!TryComp(implant, out implantComp))
return false;
if (!CheckTarget(target, component.Whitelist, component.Blacklist) ||
!CheckTarget(target, implantComp.Whitelist, implantComp.Blacklist))
{
return false;
}
var ev = new AddImplantAttemptEvent(user, target, implant.Value, implanter);
RaiseLocalEvent(target, ev);
return !ev.Cancelled;
}
protected bool CheckTarget(EntityUid target, EntityWhitelist? whitelist, EntityWhitelist? blacklist)
{
return whitelist?.IsValid(target, EntityManager) != false &&
blacklist?.IsValid(target, EntityManager) != true;
}
//Draw the implant out of the target
//TODO: Rework when surgery is in so implant cases can be a thing
public void Draw(EntityUid implanter, EntityUid user, EntityUid target, ImplanterComponent component)
{
var implanterContainer = component.ImplanterSlot.ContainerSlot;
if (implanterContainer is null)
return;
var permanentFound = false;
if (_container.TryGetContainer(target, ImplanterComponent.ImplantSlotId, out var implantContainer))
{
var implantCompQuery = GetEntityQuery<SubdermalImplantComponent>();
foreach (var implant in implantContainer.ContainedEntities)
{
if (!implantCompQuery.TryGetComponent(implant, out var implantComp))
continue;
//Don't remove a permanent implant and look for the next that can be drawn
if (!_container.CanRemove(implant, implantContainer))
{
var implantName = Identity.Entity(implant, EntityManager);
var targetName = Identity.Entity(target, EntityManager);
var failedPermanentMessage = Loc.GetString("implanter-draw-failed-permanent",
("implant", implantName), ("target", targetName));
_popup.PopupEntity(failedPermanentMessage, target, user);
permanentFound = implantComp.Permanent;
continue;
}
_container.Remove(implant, implantContainer);
implantComp.ImplantedEntity = null;
_container.Insert(implant, implanterContainer);
permanentFound = implantComp.Permanent;
var ev = new TransferDnaEvent { Donor = target, Recipient = implanter };
RaiseLocalEvent(target, ref ev);
//Break so only one implant is drawn
break;
}
if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly && !permanentFound)
ImplantMode(implanter, component);
Dirty(component);
}
}
private void ImplantMode(EntityUid uid, ImplanterComponent component)
{
component.CurrentMode = ImplanterToggleMode.Inject;
ChangeOnImplantVisualizer(uid, component);
}
private void DrawMode(EntityUid uid, ImplanterComponent component)
{
component.CurrentMode = ImplanterToggleMode.Draw;
ChangeOnImplantVisualizer(uid, component);
}
private void ChangeOnImplantVisualizer(EntityUid uid, ImplanterComponent component)
{
if (!TryComp<AppearanceComponent>(uid, out var appearance))
return;
bool implantFound;
if (component.ImplanterSlot.HasItem)
implantFound = true;
else
implantFound = false;
if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly)
_appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance);
else if (component.CurrentMode == ImplanterToggleMode.Inject && component.ImplantOnly)
{
if (!TryComp<MetaDataComponent>(uid, out var metadata))
return;
_metaData.SetEntityName(uid, Loc.GetString("ent-BaseImplanter")); // Замена на стандартное имя
_metaData.SetEntityDescription(uid, Loc.GetString("ent-BaseImplanter.desc")); // Замена на стандартное описание
_appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); // Ставим спрайт пустого имплантера
}
else
_appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance);
}
}
[Serializable, NetSerializable]
public sealed partial class ImplantEvent : SimpleDoAfterEvent
{
}
[Serializable, NetSerializable]
public sealed partial class DrawEvent : SimpleDoAfterEvent
{
}
public sealed class AddImplantAttemptEvent : CancellableEntityEventArgs
{
public readonly EntityUid User;
public readonly EntityUid Target;
public readonly EntityUid Implant;
public readonly EntityUid Implanter;
public AddImplantAttemptEvent(EntityUid user, EntityUid target, EntityUid implant, EntityUid implanter)
{
User = user;
Target = target;
Implant = implant;
Implanter = implanter;
}
}