Files
tbd-station-14/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs
deltanedas 02636386b5 item toggling giga rework + full ninja refactor (#28039)
* item toggle refactoring and some new systems

* add ToggleClothing component/system

* unhardcode magboots gravity logic

* make magboots and speedboots use ItemToggle and stuff

* remove now useless clothing components

* update client/server magboots systems

* add note to use ItemToggledEvent in ToggleActionEvent doc

* refactor PowerCellDraw to use ItemToggle for ui open/close control

* add TryUseCharges, refactor charges system

* update magboot trigger code

* make borg use ItemToggle, network SelectedModule instead of now removed Activated

* add AccessToggle for borg

* the giga ninja refactor

* update ninja yml

* update ItemToggle usage for some stuff

* fix activatableui requires power

* random fixing

* yaml fixing

* nuke ItemToggleDisarmMalus

* make defib use ItemToggle

* make things that use power not turn on if missing use charge

* pro

* fix sound prediction

* bruh

* proximity detector use ItemToggle

* oop

* big idiot syndrome

* fix ninja spawn rule and make it generic

* fix ninja spawn rule yml

* move loading profiles into AntagLoadProfileRule

* more ninja refactor

* ninja yml fixes

* the dreaded copy paste ops

* remove useless NinjaRuleComponent and ue AntagSelection for greeting

* fix invisibility

* move IsCompleted to SharedObjectivesSystem

* ability fixes

* oop fix powercell instantly draining itself

* sentient speedboots gaming

* make reflect use ItemToggle

* fix other test

* loadprofilerule moved into its own pr

* remove conflict with dragon refactor

* remove all GenericAntag code from ninja

* )

* probably

* remove old enabled

* great language bravo vince

* GREAT LANGUAGE

* who made this language

* because it stinks

* reparent blood-red magboots to magboots probbbly works

* most of the review stuff

* hasGrav doesnt mean what i thought it did

* make health analyzer use itemtoggle, not fail test

* fix mag/speed boots being wacky

* UNTROLL

* add ItemToggle to the random health analyzers

* a

* remove unused obsolete borg func

* untrolling

* :trollface:

* fix test

* fix

* g

* untroll

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-07-11 15:55:56 +10:00

369 lines
13 KiB
C#

using System.Linq;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction.Components;
using Content.Shared.Silicons.Borgs.Components;
using Robust.Shared.Containers;
namespace Content.Server.Silicons.Borgs;
/// <inheritdoc/>
public sealed partial class BorgSystem
{
public void InitializeModules()
{
SubscribeLocalEvent<BorgModuleComponent, EntGotInsertedIntoContainerMessage>(OnModuleGotInserted);
SubscribeLocalEvent<BorgModuleComponent, EntGotRemovedFromContainerMessage>(OnModuleGotRemoved);
SubscribeLocalEvent<SelectableBorgModuleComponent, BorgModuleInstalledEvent>(OnSelectableInstalled);
SubscribeLocalEvent<SelectableBorgModuleComponent, BorgModuleUninstalledEvent>(OnSelectableUninstalled);
SubscribeLocalEvent<SelectableBorgModuleComponent, BorgModuleActionSelectedEvent>(OnSelectableAction);
SubscribeLocalEvent<ItemBorgModuleComponent, ComponentStartup>(OnProvideItemStartup);
SubscribeLocalEvent<ItemBorgModuleComponent, BorgModuleSelectedEvent>(OnItemModuleSelected);
SubscribeLocalEvent<ItemBorgModuleComponent, BorgModuleUnselectedEvent>(OnItemModuleUnselected);
}
private void OnModuleGotInserted(EntityUid uid, BorgModuleComponent component, EntGotInsertedIntoContainerMessage args)
{
var chassis = args.Container.Owner;
if (!TryComp<BorgChassisComponent>(chassis, out var chassisComp) ||
args.Container != chassisComp.ModuleContainer ||
!Toggle.IsActivated(chassis))
return;
if (!_powerCell.HasDrawCharge(uid))
return;
InstallModule(chassis, uid, chassisComp, component);
}
private void OnModuleGotRemoved(EntityUid uid, BorgModuleComponent component, EntGotRemovedFromContainerMessage args)
{
var chassis = args.Container.Owner;
if (!TryComp<BorgChassisComponent>(chassis, out var chassisComp) ||
args.Container != chassisComp.ModuleContainer)
return;
UninstallModule(chassis, uid, chassisComp, component);
}
private void OnProvideItemStartup(EntityUid uid, ItemBorgModuleComponent component, ComponentStartup args)
{
component.ProvidedContainer = Container.EnsureContainer<Container>(uid, component.ProvidedContainerId);
}
private void OnSelectableInstalled(EntityUid uid, SelectableBorgModuleComponent component, ref BorgModuleInstalledEvent args)
{
var chassis = args.ChassisEnt;
if (_actions.AddAction(chassis, ref component.ModuleSwapActionEntity, out var action, component.ModuleSwapActionId, uid))
{
action.EntityIcon = uid;
Dirty(component.ModuleSwapActionEntity.Value, action);
}
if (!TryComp(chassis, out BorgChassisComponent? chassisComp))
return;
if (chassisComp.SelectedModule == null)
SelectModule(chassis, uid, chassisComp, component);
}
private void OnSelectableUninstalled(EntityUid uid, SelectableBorgModuleComponent component, ref BorgModuleUninstalledEvent args)
{
var chassis = args.ChassisEnt;
_actions.RemoveProvidedActions(chassis, uid);
if (!TryComp(chassis, out BorgChassisComponent? chassisComp))
return;
if (chassisComp.SelectedModule == uid)
UnselectModule(chassis, chassisComp);
}
private void OnSelectableAction(EntityUid uid, SelectableBorgModuleComponent component, BorgModuleActionSelectedEvent args)
{
var chassis = args.Performer;
if (!TryComp<BorgChassisComponent>(chassis, out var chassisComp))
return;
var selected = chassisComp.SelectedModule;
args.Handled = true;
UnselectModule(chassis, chassisComp);
if (selected != uid)
{
SelectModule(chassis, uid, chassisComp, component);
}
}
/// <summary>
/// Selects a module, enabling the borg to use its provided abilities.
/// </summary>
public void SelectModule(EntityUid chassis,
EntityUid moduleUid,
BorgChassisComponent? chassisComp = null,
SelectableBorgModuleComponent? selectable = null,
BorgModuleComponent? moduleComp = null)
{
if (LifeStage(chassis) >= EntityLifeStage.Terminating)
return;
if (!Resolve(chassis, ref chassisComp))
return;
if (!Resolve(moduleUid, ref moduleComp) || !moduleComp.Installed || moduleComp.InstalledEntity != chassis)
{
Log.Error($"{ToPrettyString(chassis)} attempted to select uninstalled module {ToPrettyString(moduleUid)}");
return;
}
if (selectable == null && !HasComp<SelectableBorgModuleComponent>(moduleUid))
{
Log.Error($"{ToPrettyString(chassis)} attempted to select invalid module {ToPrettyString(moduleUid)}");
return;
}
if (!chassisComp.ModuleContainer.Contains(moduleUid))
{
Log.Error($"{ToPrettyString(chassis)} does not contain the installed module {ToPrettyString(moduleUid)}");
return;
}
if (chassisComp.SelectedModule != null)
return;
if (chassisComp.SelectedModule == moduleUid)
return;
UnselectModule(chassis, chassisComp);
var ev = new BorgModuleSelectedEvent(chassis);
RaiseLocalEvent(moduleUid, ref ev);
chassisComp.SelectedModule = moduleUid;
Dirty(chassis, chassisComp);
}
/// <summary>
/// Unselects a module, removing its provided abilities
/// </summary>
public void UnselectModule(EntityUid chassis, BorgChassisComponent? chassisComp = null)
{
if (LifeStage(chassis) >= EntityLifeStage.Terminating)
return;
if (!Resolve(chassis, ref chassisComp))
return;
if (chassisComp.SelectedModule == null)
return;
var ev = new BorgModuleUnselectedEvent(chassis);
RaiseLocalEvent(chassisComp.SelectedModule.Value, ref ev);
chassisComp.SelectedModule = null;
Dirty(chassis, chassisComp);
}
private void OnItemModuleSelected(EntityUid uid, ItemBorgModuleComponent component, ref BorgModuleSelectedEvent args)
{
ProvideItems(args.Chassis, uid, component: component);
}
private void OnItemModuleUnselected(EntityUid uid, ItemBorgModuleComponent component, ref BorgModuleUnselectedEvent args)
{
RemoveProvidedItems(args.Chassis, uid, component: component);
}
private void ProvideItems(EntityUid chassis, EntityUid uid, BorgChassisComponent? chassisComponent = null, ItemBorgModuleComponent? component = null)
{
if (!Resolve(chassis, ref chassisComponent) || !Resolve(uid, ref component))
return;
if (!TryComp<HandsComponent>(chassis, out var hands))
return;
var xform = Transform(chassis);
foreach (var itemProto in component.Items)
{
EntityUid item;
if (!component.ItemsCreated)
{
item = Spawn(itemProto, xform.Coordinates);
}
else
{
item = component.ProvidedContainer.ContainedEntities
.FirstOrDefault(ent => Prototype(ent)?.ID == itemProto);
if (!item.IsValid())
{
Log.Debug($"no items found: {component.ProvidedContainer.ContainedEntities.Count}");
continue;
}
_container.Remove(item, component.ProvidedContainer, force: true);
}
if (!item.IsValid())
{
Log.Debug("no valid item");
continue;
}
var handId = $"{uid}-item{component.HandCounter}";
component.HandCounter++;
_hands.AddHand(chassis, handId, HandLocation.Middle, hands);
_hands.DoPickup(chassis, hands.Hands[handId], item, hands);
EnsureComp<UnremoveableComponent>(item);
component.ProvidedItems.Add(handId, item);
}
component.ItemsCreated = true;
}
private void RemoveProvidedItems(EntityUid chassis, EntityUid uid, BorgChassisComponent? chassisComponent = null, ItemBorgModuleComponent? component = null)
{
if (!Resolve(chassis, ref chassisComponent) || !Resolve(uid, ref component))
return;
if (!TryComp<HandsComponent>(chassis, out var hands))
return;
if (TerminatingOrDeleted(uid))
{
foreach (var (hand, item) in component.ProvidedItems)
{
QueueDel(item);
_hands.RemoveHand(chassis, hand, hands);
}
component.ProvidedItems.Clear();
return;
}
foreach (var (handId, item) in component.ProvidedItems)
{
if (LifeStage(item) <= EntityLifeStage.MapInitialized)
{
RemComp<UnremoveableComponent>(item);
_container.Insert(item, component.ProvidedContainer);
}
_hands.RemoveHand(chassis, handId, hands);
}
component.ProvidedItems.Clear();
}
/// <summary>
/// Checks if a given module can be inserted into a borg
/// </summary>
public bool CanInsertModule(EntityUid uid, EntityUid module, BorgChassisComponent? component = null, BorgModuleComponent? moduleComponent = null, EntityUid? user = null)
{
if (!Resolve(uid, ref component) || !Resolve(module, ref moduleComponent))
return false;
if (component.ModuleContainer.ContainedEntities.Count >= component.MaxModules)
{
if (user != null)
Popup.PopupEntity(Loc.GetString("borg-module-too-many"), uid, user.Value);
return false;
}
if (_whitelistSystem.IsWhitelistFail(component.ModuleWhitelist, module))
{
if (user != null)
Popup.PopupEntity(Loc.GetString("borg-module-whitelist-deny"), uid, user.Value);
return false;
}
if (TryComp<ItemBorgModuleComponent>(module, out var itemModuleComp))
{
foreach (var containedModuleUid in component.ModuleContainer.ContainedEntities)
{
if (!TryComp<ItemBorgModuleComponent>(containedModuleUid, out var containedItemModuleComp))
continue;
if (containedItemModuleComp.Items.Count == itemModuleComp.Items.Count &&
containedItemModuleComp.Items.All(itemModuleComp.Items.Contains))
{
if (user != null)
Popup.PopupEntity(Loc.GetString("borg-module-duplicate"), uid, user.Value);
return false;
}
}
}
return true;
}
/// <summary>
/// Installs and activates all modules currently inside the borg's module container
/// </summary>
public void InstallAllModules(EntityUid uid, BorgChassisComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
var query = GetEntityQuery<BorgModuleComponent>();
foreach (var moduleEnt in new List<EntityUid>(component.ModuleContainer.ContainedEntities))
{
if (!query.TryGetComponent(moduleEnt, out var moduleComp))
continue;
InstallModule(uid, moduleEnt, component, moduleComp);
}
}
/// <summary>
/// Deactivates all modules currently inside the borg's module container
/// </summary>
/// <param name="uid"></param>
/// <param name="component"></param>
public void DisableAllModules(EntityUid uid, BorgChassisComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
var query = GetEntityQuery<BorgModuleComponent>();
foreach (var moduleEnt in new List<EntityUid>(component.ModuleContainer.ContainedEntities))
{
if (!query.TryGetComponent(moduleEnt, out var moduleComp))
continue;
UninstallModule(uid, moduleEnt, component, moduleComp);
}
}
/// <summary>
/// Installs a single module into a borg.
/// </summary>
public void InstallModule(EntityUid uid, EntityUid module, BorgChassisComponent? component, BorgModuleComponent? moduleComponent = null)
{
if (!Resolve(uid, ref component) || !Resolve(module, ref moduleComponent))
return;
if (moduleComponent.Installed)
return;
moduleComponent.InstalledEntity = uid;
var ev = new BorgModuleInstalledEvent(uid);
RaiseLocalEvent(module, ref ev);
}
/// <summary>
/// Uninstalls a single module from a borg.
/// </summary>
public void UninstallModule(EntityUid uid, EntityUid module, BorgChassisComponent? component, BorgModuleComponent? moduleComponent = null)
{
if (!Resolve(uid, ref component) || !Resolve(module, ref moduleComponent))
return;
if (!moduleComponent.Installed)
return;
moduleComponent.InstalledEntity = null;
var ev = new BorgModuleUninstalledEvent(uid);
RaiseLocalEvent(module, ref ev);
}
}