mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
* [HOTFIX] Fix singularity and tesla friction (#44078) * Vehicle system: Movement & Buckling (#43525) * Part one of Vehicles * Also we need this * And we need this * We REALLY need this * Little fix * fixes (i'm tired) * Apply suggestions from code review Co-authored-by: Princess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com> * update * fixed * just for cleaner diff * just in case * I think this might be cleaner * small fix --------- Co-authored-by: Princess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com> * Fix ID inspect message when ending perma sentence early (#44018) * Automatic changelog update * Smarter Entity Targeting (#39571) * Smart targeting * use swidge statement * Undo * merge conflicts * works well * Better logic * GO TO SLEEP --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> * fix: don't delete items on some polymorph reverts (#39423) * Automatic changelog update * Fix error texture for harmpack hand solution visuals (#39442) * fix: check for inhand sprite's existence * refactor: simplify solution container visuals code this made my brain hurt but I think I didn't break anything * Automatic changelog update * fix role assignment when late joining (#41419) * fix role assignment when late joining * push --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> * Automatic changelog update * SSD Players now properly stay asleep when being revived. (#39409) * Fixes and API changes * aaaaaaaaaa * super shitcode * cleanup * fix admin logs --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> * Automatic changelog update * Fix Barber Scissors not playing audio (#43922) * Fix Barber Scissors not playing audio * Add code comment * Requested changes * More requested changes thanks Warock * Requested changes * Automatic changelog update * [MALD PR] Remove mimic vendor gamerule (#44057) remove mimic vender rule * Automatic changelog update * Destructible Automatic Overkill (#43113) * Change to file scoped namespace * Improve variable naming * Remove unnecessary audiosystem * Add automatic overkill * Small cleanups * Alphabetize dependencies * Change to file scoped namespace * Change to OnMapInit * Fix overkill if no destruction node present * Add overkill test * Example cleanup * Performance improvements * Tuple event subscriptions * Correct comment * Realphabetize I might be dyslexic. Or just stupid. * Invert toggle behavior and rename * Change from MapInit to ComponentInit * Revert "Change from MapInit to ComponentInit" This reverts commit 1ed9fa0ad49be00becd9adca5cfee45cf4fef3a2. * Change to use index instead of raw int * Explicit check not required * Clean up overkill test * Improve commenting * Overhaul the test * Little more * Improve commenting * Update DestructibleOverkillTest.cs * Typo * Change to tuple assignment * Alphabetize dependencies * Update Content.IntegrationTests/Tests/Destructible/DestructibleOverkillTest.cs * Update Content.IntegrationTests/Tests/Destructible/DestructibleOverkillTest.cs * Update Content.IntegrationTests/Tests/Destructible/DestructibleOverkillTest.cs --------- Co-authored-by: Tayrtahn <tayrtahn@gmail.com> * Update Credits (#44060) Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> * fix off by 1 in tips (#44062) fix the thing the uhhhh the thing the thing ynow.... fix uhh the thing. the thing that needs fixing * Remove background box from main menu (#43977) * Menu Change * Change v2 * final change * Format code --------- Co-authored-by: Thomas (Aeshus) <git@aeshus.com> * Mini Gravity Generator requires charging (#44061) * Starting charge to zero * Reach starts with gravity * Revert "Reach starts with gravity" This reverts commit 49a7e22fc054687b879a5a13562433bc081f19cd. * Create charged/uncharged prototypes * Fix formatting * Change construction * Review feedback * Automatic changelog update * [BUGFIX] Shaken sodas now spill again (#44033) Tiders will rule the halls once again. * Automatic changelog update * add empty tile friction modifiers * add empty tile friction modifiers * Revert "[Hotfix] Fix MenuButton Missing Negative Style (#44073)" This reverts commit 0f1abd73669c6c7ff291bb289f760090dc9454b6. * Revert "Automatic changelog update" This reverts commit 4a34a711845f0da49686c750cad7807639b56deb. * Revert "[BUGFIX] Shaken sodas now spill again (#44033)" This reverts commit 37447f4d89feeb98baba91d896b0439d30088b80. * Revert "Automatic changelog update" This reverts commit 1ced1977fb73186a8aaefab504e3a860aee219f9. * Revert "Mini Gravity Generator requires charging (#44061)" This reverts commit 51e0f74f49673146973f8ad4966d1df0d97a506d. * Revert "Remove background box from main menu (#43977)" This reverts commit 48f3fd0c5029b384b008fdda9016e78858fcae38. * Revert "fix off by 1 in tips (#44062)" This reverts commit 1616ed806eef33bbdcaca64aaa642c44ab95f869. * Revert "Update Credits (#44060)" This reverts commit 6a9ffb9b4d5d62d191c173c4670e1c3ea6ffadb0. * Revert "Destructible Automatic Overkill (#43113)" This reverts commit 76277b737df94b02cb3fd439d8cda0f63964b85d. * Revert "Automatic changelog update" This reverts commit 5e3a647839dd5f2e3fb942b9fc4693b0bfe6baa8. * Revert "[MALD PR] Remove mimic vendor gamerule (#44057)" This reverts commit 77ee428ce4ab312b4d91124c884c233328ce871c. * Revert "Automatic changelog update" This reverts commit 71c503bf9c8c9fe785110e6b3cd5a5b46138c1d0. * Revert "Fix Barber Scissors not playing audio (#43922)" This reverts commit 989ab25751eb494b463d476c502a28d82b1cca6d. * Revert "Automatic changelog update" This reverts commit 013962c7160912570e361195c9dfcea694d0c514. * Revert "SSD Players now properly stay asleep when being revived. (#39409)" This reverts commit 546c62b38810bd6f4666235046407fb008593289. * Revert "Automatic changelog update" This reverts commit f5d65b43621721dda77d6c5ce6b18202c6b02ad7. * Revert "fix role assignment when late joining (#41419)" This reverts commit bec4c4c827ad69a2206415fc26a35f2f2e00ff1e. * Revert "Automatic changelog update" This reverts commit 0c6d7aa29bb6dbd3b4b57b5f787152a946cc5b39. * Revert "fix: don't delete items on some polymorph reverts (#39423)" This reverts commit 01a2dfb9762fc53f3918199360717208c9162695. * Revert "Fix error texture for harmpack hand solution visuals (#39442)" This reverts commit 42dbb60e0fe670e5bc35c5dd9f4c1f81c69e15cd. * Revert "Automatic changelog update" This reverts commit 1cb150f5bbd8c430eba0d2471fa4d2b4e72ba8ad. * Revert "Smarter Entity Targeting (#39571)" This reverts commit 87b389d1492af8404eb3c43a5a0dcd7623d724b9. * Revert "Automatic changelog update" This reverts commit 927f9e2652f146686be50750ffc04569893cb5d8. * Revert "Fix ID inspect message when ending perma sentence early (#44018)" This reverts commit c7dfbf89484dd332847924643bd6bfed08d37253. * Revert "Vehicle system: Movement & Buckling (#43525)" This reverts commit 8c85a5927564701e1e44eca27cb55d295c2eda11. * revert --------- Co-authored-by: AndrewFenriz <78079974+AndrewFenriz@users.noreply.github.com> Co-authored-by: Princess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com> Co-authored-by: Ignaz "Ian" Kraft <ignaz.k@live.de> Co-authored-by: Rami <ramialanbagy@gmail.com> Co-authored-by: Jessica M <jessica@jessicamaybe.com> Co-authored-by: Connor Huffine <chuffine@gmail.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: PicklOH <62030853+PicklOH@users.noreply.github.com> Co-authored-by: Lye <128915833+Lyroth001@users.noreply.github.com> Co-authored-by: piskaczek <192605039+piskaczek@users.noreply.github.com> Co-authored-by: riccardi48 <39341154+riccardi48@users.noreply.github.com> Co-authored-by: Thomas (Aeshus) <git@aeshus.com> Co-authored-by: ThatGuyUSA <thatguyusa123@gmail.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> * [HOTFIX] Fix Barber DoAfter Bug (#44162) * Update the Salamander server description for the server browser: Redux (#44104) Update the MRP config --------- Co-authored-by: Crude Oil <124208219+CroilBird@users.noreply.github.com> Co-authored-by: AndrewFenriz <78079974+AndrewFenriz@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com> Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com> Co-authored-by: Ignaz "Ian" Kraft <ignaz.k@live.de> Co-authored-by: Rami <ramialanbagy@gmail.com> Co-authored-by: Jessica M <jessica@jessicamaybe.com> Co-authored-by: Connor Huffine <chuffine@gmail.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: PicklOH <62030853+PicklOH@users.noreply.github.com> Co-authored-by: Lye <128915833+Lyroth001@users.noreply.github.com> Co-authored-by: piskaczek <192605039+piskaczek@users.noreply.github.com> Co-authored-by: riccardi48 <39341154+riccardi48@users.noreply.github.com> Co-authored-by: Thomas (Aeshus) <git@aeshus.com> Co-authored-by: ThatGuyUSA <thatguyusa123@gmail.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> Co-authored-by: Thomas <87614336+Aeshus@users.noreply.github.com> Co-authored-by: Kowlin <10947836+Kowlin@users.noreply.github.com>
294 lines
9.9 KiB
C#
294 lines
9.9 KiB
C#
using Content.Shared.Body;
|
|
using Content.Shared.DoAfter;
|
|
using Content.Shared.Humanoid;
|
|
using Content.Shared.Humanoid.Markings;
|
|
using Content.Shared.IdentityManagement;
|
|
using Content.Shared.Interaction;
|
|
using Content.Shared.Inventory;
|
|
using Content.Shared.Popups;
|
|
using Content.Shared.Tag;
|
|
using Content.Shared.UserInterface;
|
|
using Robust.Shared.Audio.Systems;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Serialization;
|
|
|
|
namespace Content.Shared.MagicMirror;
|
|
|
|
public sealed partial class MagicMirrorSystem : EntitySystem
|
|
{
|
|
[Dependency] private SharedInteractionSystem _interaction = default!;
|
|
[Dependency] private SharedUserInterfaceSystem _userInterface = default!;
|
|
[Dependency] private InventorySystem _inventory = default!;
|
|
[Dependency] private TagSystem _tag = default!;
|
|
[Dependency] private SharedPopupSystem _popup = default!;
|
|
[Dependency] private SharedDoAfterSystem _doAfter = default!;
|
|
[Dependency] private SharedAudioSystem _audio = default!;
|
|
[Dependency] private SharedVisualBodySystem _visualBody = default!;
|
|
|
|
private static readonly ProtoId<TagPrototype> HidesHairTag = "HidesHair";
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<MagicMirrorComponent, AfterInteractEvent>(OnMagicMirrorInteract);
|
|
SubscribeLocalEvent<MagicMirrorComponent, BeforeActivatableUIOpenEvent>(OnBeforeUIOpen);
|
|
SubscribeLocalEvent<MagicMirrorComponent, ActivatableUIOpenAttemptEvent>(OnAttemptOpenUI);
|
|
|
|
Subs.BuiEvents<MagicMirrorComponent>(MagicMirrorUiKey.Key,
|
|
subs =>
|
|
{
|
|
subs.Event<BoundUIClosedEvent>(OnUiClosed);
|
|
subs.Event<MagicMirrorSelectMessage>(OnMagicMirrorSelect);
|
|
});
|
|
|
|
SubscribeLocalEvent<MagicMirrorComponent, MagicMirrorSelectDoAfterEvent>(OnSelectSlotDoAfter);
|
|
|
|
SubscribeLocalEvent<MagicMirrorComponent, BoundUserInterfaceCheckRangeEvent>(OnMirrorRangeCheck);
|
|
}
|
|
|
|
|
|
private void OnMagicMirrorSelect(Entity<MagicMirrorComponent> ent, ref MagicMirrorSelectMessage args)
|
|
{
|
|
if (ent.Comp.Target is not { } target)
|
|
return;
|
|
|
|
// Check if the target getting their hair altered has any clothes that hides their hair
|
|
if (CheckHeadSlotOrClothes(target))
|
|
{
|
|
_popup.PopupEntity(
|
|
ent.Comp.Target == args.Actor
|
|
? Loc.GetString("magic-mirror-blocked-by-hat-self")
|
|
: Loc.GetString("magic-mirror-blocked-by-hat-self-target", ("target", Identity.Entity(target, EntityManager))),
|
|
args.Actor,
|
|
args.Actor,
|
|
PopupType.Medium);
|
|
return;
|
|
}
|
|
|
|
if (ent.Comp.DoAfter.HasValue)
|
|
{
|
|
_doAfter.Cancel(args.Actor, ent.Comp.DoAfter.Value);
|
|
ent.Comp.DoAfter = null;
|
|
}
|
|
|
|
var doafterTime = ent.Comp.ModifyTime;
|
|
if (ent.Comp.Target == args.Actor)
|
|
doafterTime /= 3;
|
|
|
|
var doAfter = new MagicMirrorSelectDoAfterEvent()
|
|
{
|
|
Markings = args.Markings,
|
|
};
|
|
|
|
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Actor, doafterTime, doAfter, ent, target: target, used: ent)
|
|
{
|
|
DistanceThreshold = SharedInteractionSystem.InteractionRange,
|
|
BreakOnDamage = true,
|
|
BreakOnMove = true,
|
|
NeedHand = true,
|
|
},
|
|
out var doAfterId);
|
|
|
|
if (target == args.Actor)
|
|
{
|
|
_popup.PopupEntity(Loc.GetString("magic-mirror-change-slot-self"), target, target, PopupType.Medium);
|
|
}
|
|
else
|
|
{
|
|
_popup.PopupEntity(Loc.GetString("magic-mirror-change-slot-target", ("user", Identity.Entity(args.Actor, EntityManager))), target, target, PopupType.Medium);
|
|
}
|
|
|
|
_audio.PlayPredicted(ent.Comp.ChangeHairSound, ent, args.Actor);
|
|
ent.Comp.DoAfter = doAfterId?.Index;
|
|
}
|
|
|
|
private void OnSelectSlotDoAfter(Entity<MagicMirrorComponent> ent, ref MagicMirrorSelectDoAfterEvent args)
|
|
{
|
|
ent.Comp.DoAfter = null;
|
|
|
|
if (args.Handled || args.Target == null || args.Cancelled)
|
|
return;
|
|
|
|
if (ent.Comp.Target != args.Target)
|
|
return;
|
|
|
|
// what plays the audio
|
|
_audio.PlayPredicted(ent.Comp.ChangeHairSound, args.Target.Value, args.User);
|
|
|
|
foreach (var (organ, markings) in args.Markings)
|
|
{
|
|
if (!ent.Comp.Organs.Contains(organ))
|
|
{
|
|
args.Markings.Remove(organ);
|
|
continue;
|
|
}
|
|
|
|
foreach (var layer in markings.Keys)
|
|
{
|
|
if (!ent.Comp.Layers.Contains(layer))
|
|
markings.Remove(layer);
|
|
}
|
|
}
|
|
|
|
_visualBody.ApplyMarkings(args.Target.Value, args.Markings);
|
|
}
|
|
|
|
private void OnUiClosed(Entity<MagicMirrorComponent> ent, ref BoundUIClosedEvent args)
|
|
{
|
|
ent.Comp.Target = null;
|
|
Dirty(ent);
|
|
}
|
|
|
|
private void OnMagicMirrorInteract(Entity<MagicMirrorComponent> mirror, ref AfterInteractEvent args)
|
|
{
|
|
if (!args.CanReach || args.Target == null)
|
|
return;
|
|
|
|
if (!HasComp<VisualBodyComponent>(args.Target.Value))
|
|
return;
|
|
|
|
UpdateInterface(mirror, args.Target.Value);
|
|
_userInterface.TryOpenUi(mirror.Owner, MagicMirrorUiKey.Key, args.User);
|
|
}
|
|
|
|
private void OnMirrorRangeCheck(EntityUid uid, MagicMirrorComponent component, ref BoundUserInterfaceCheckRangeEvent args)
|
|
{
|
|
if (args.Result == BoundUserInterfaceRangeResult.Fail)
|
|
return;
|
|
|
|
if (component.Target == null || !Exists(component.Target))
|
|
{
|
|
component.Target = null;
|
|
args.Result = BoundUserInterfaceRangeResult.Fail;
|
|
return;
|
|
}
|
|
|
|
if (!_interaction.InRangeUnobstructed(component.Target.Value, uid))
|
|
args.Result = BoundUserInterfaceRangeResult.Fail;
|
|
}
|
|
|
|
private void OnAttemptOpenUI(EntityUid uid, MagicMirrorComponent component, ref ActivatableUIOpenAttemptEvent args)
|
|
{
|
|
var user = component.Target ?? args.User;
|
|
|
|
if (!HasComp<VisualBodyComponent>(user))
|
|
args.Cancel();
|
|
}
|
|
|
|
private void OnBeforeUIOpen(Entity<MagicMirrorComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
|
{
|
|
UpdateInterface(ent, args.User);
|
|
}
|
|
|
|
private void UpdateInterface(Entity<MagicMirrorComponent> ent, EntityUid target)
|
|
{
|
|
if (!_visualBody.TryGatherMarkingsData(target, ent.Comp.Layers, out var profiles, out var markings, out var applied))
|
|
return;
|
|
|
|
ent.Comp.Target = target;
|
|
|
|
foreach (var profile in profiles)
|
|
{
|
|
if (!ent.Comp.Organs.Contains(profile.Key))
|
|
profiles.Remove(profile.Key);
|
|
}
|
|
|
|
foreach (var marking in markings)
|
|
{
|
|
if (!ent.Comp.Organs.Contains(marking.Key))
|
|
{
|
|
profiles.Remove(marking.Key);
|
|
continue;
|
|
}
|
|
|
|
marking.Value.Layers.IntersectWith(ent.Comp.Layers);
|
|
}
|
|
|
|
foreach (var appliedPair in applied)
|
|
{
|
|
if (!ent.Comp.Organs.Contains(appliedPair.Key))
|
|
applied.Remove(appliedPair.Key);
|
|
}
|
|
|
|
// TODO: Component states
|
|
var state = new MagicMirrorUiState(profiles, markings, applied);
|
|
_userInterface.SetUiState(ent.Owner, MagicMirrorUiKey.Key, state);
|
|
|
|
Dirty(ent);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Helper function that checks if the wearer has anything on their head
|
|
/// Or if they have any clothes that hides their hair
|
|
/// </summary>
|
|
private bool CheckHeadSlotOrClothes(EntityUid target)
|
|
{
|
|
if (!TryComp<InventoryComponent>(target, out var inventoryComp))
|
|
return false;
|
|
|
|
// any hat whatsoever will block haircutting
|
|
if (_inventory.TryGetSlotEntity(target, "head", out _, inventoryComp))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// maybe there's some kind of armor that has the HidesHair tag as well, so check every slot for it
|
|
var slots = _inventory.GetSlotEnumerator((target, inventoryComp), SlotFlags.WITHOUT_POCKET);
|
|
while (slots.MoveNext(out var slot))
|
|
{
|
|
if (slot.ContainedEntity != null && _tag.HasTag(slot.ContainedEntity.Value, HidesHairTag))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
[Serializable, NetSerializable]
|
|
public enum MagicMirrorUiKey : byte
|
|
{
|
|
Key
|
|
}
|
|
|
|
[Serializable, NetSerializable]
|
|
public sealed class MagicMirrorSelectMessage : BoundUserInterfaceMessage
|
|
{
|
|
public MagicMirrorSelectMessage(Dictionary<ProtoId<OrganCategoryPrototype>, Dictionary<HumanoidVisualLayers, List<Marking>>> markings)
|
|
{
|
|
Markings = markings;
|
|
}
|
|
|
|
public Dictionary<ProtoId<OrganCategoryPrototype>, Dictionary<HumanoidVisualLayers, List<Marking>>> Markings { get; }
|
|
}
|
|
|
|
|
|
[Serializable, NetSerializable]
|
|
public sealed class MagicMirrorUiState : BoundUserInterfaceState
|
|
{
|
|
public MagicMirrorUiState(Dictionary<ProtoId<OrganCategoryPrototype>, OrganProfileData> profiles,
|
|
Dictionary<ProtoId<OrganCategoryPrototype>, OrganMarkingData> markings,
|
|
Dictionary<ProtoId<OrganCategoryPrototype>, Dictionary<HumanoidVisualLayers, List<Marking>>> applied)
|
|
{
|
|
OrganProfileData = profiles;
|
|
OrganMarkingData = markings;
|
|
AppliedMarkings = applied;
|
|
}
|
|
|
|
public NetEntity Target;
|
|
|
|
public Dictionary<ProtoId<OrganCategoryPrototype>, OrganProfileData> OrganProfileData;
|
|
public Dictionary<ProtoId<OrganCategoryPrototype>, OrganMarkingData> OrganMarkingData;
|
|
public Dictionary<ProtoId<OrganCategoryPrototype>, Dictionary<HumanoidVisualLayers, List<Marking>>> AppliedMarkings;
|
|
}
|
|
|
|
[Serializable, NetSerializable]
|
|
public sealed partial class MagicMirrorSelectDoAfterEvent : DoAfterEvent
|
|
{
|
|
public Dictionary<ProtoId<OrganCategoryPrototype>, Dictionary<HumanoidVisualLayers, List<Marking>>> Markings;
|
|
|
|
public override DoAfterEvent Clone() => this;
|
|
}
|