From ae204a8944c4ba04ae8f67a63f3365ce641f9aa9 Mon Sep 17 00:00:00 2001 From: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> Date: Fri, 8 Nov 2024 10:54:27 -0800 Subject: [PATCH] Port Cool Punpun (#1157) https://github.com/Simple-Station/Parkstation/pull/48 https://github.com/Simple-Station/Parkstation-Friendly-Chainsaw/issues/2 --------- Co-authored-by: VMSolidus --- Content.Server/Punpun/PunpunComponent.cs | 9 ++ Content.Server/Punpun/PunpunSystem.cs | 114 ++++++++++++++++++ .../Prototypes/Entities/Mobs/NPCs/pets.yml | 8 +- .../Entities/Objects/Misc/paper.yml | 10 ++ SpaceStation14.sln.DotSettings | 1 + 5 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 Content.Server/Punpun/PunpunComponent.cs create mode 100644 Content.Server/Punpun/PunpunSystem.cs diff --git a/Content.Server/Punpun/PunpunComponent.cs b/Content.Server/Punpun/PunpunComponent.cs new file mode 100644 index 00000000000..19d2da42c9d --- /dev/null +++ b/Content.Server/Punpun/PunpunComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Punpun; + +[RegisterComponent] +public sealed partial class PunpunComponent : Component +{ + /// How many rounds Punpun will be around for before disappearing with a note + [DataField] + public int Lifetime = 14; +} diff --git a/Content.Server/Punpun/PunpunSystem.cs b/Content.Server/Punpun/PunpunSystem.cs new file mode 100644 index 00000000000..5f1f22b42a1 --- /dev/null +++ b/Content.Server/Punpun/PunpunSystem.cs @@ -0,0 +1,114 @@ +using System.Linq; +using Content.Server.GameTicking; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Inventory; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Robust.Server.GameObjects; + +namespace Content.Server.Punpun; + +public sealed class PunpunSystem : EntitySystem +{ + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly ServerMetaDataSystem _meta = default!; + + private (int, string, string, string) _punpunData = (1, string.Empty, string.Empty, string.Empty); + + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRoundStart); + SubscribeLocalEvent(OnRoundEnd); + } + + + // Checks if the Punpun data has any items to equip, and names the Punpun upon initialization + private void OnRoundStart(EntityUid uid, PunpunComponent component, ComponentStartup args) + { + if (_punpunData.Item1 > component.Lifetime) + { + EntityManager.SpawnEntity("PaperWrittenPunpunNote", Transform(uid).Coordinates); + EntityManager.QueueDeleteEntity(uid); + _punpunData = (1, string.Empty, string.Empty, string.Empty); + + return; + } + + var meta = MetaData(uid); + _meta.SetEntityName(uid, $"{meta.EntityName} {ToRomanNumeral(_punpunData.Item1)}", meta); + + if (!EntityManager.TryGetComponent(uid, out _)) + return; + EquipItem(uid, "head", _punpunData.Item2); + EquipItem(uid, "mask", _punpunData.Item3); + EquipItem(uid, "jumpsuit", _punpunData.Item4); + } + + // Checks if Punpun exists, and is alive at round end + // If so, stores the items and increments the Punpun count + private void OnRoundEnd(RoundEndTextAppendEvent ev) + { + // I couldn't find a method to get a single entity, so this just enumerates over the first and disposes it + var punpunComponents = EntityManager.EntityQueryEnumerator(); + punpunComponents.MoveNext(out var punpun, out _); + + if (!EntityManager.TryGetComponent(punpun, out var mobState) + || mobState.CurrentState == MobState.Dead) + _punpunData = (1, string.Empty, string.Empty, string.Empty); + + _punpunData.Item1++; + + if (EntityManager.HasComponent(punpun)) + { + _punpunData.Item2 = CheckSlot(punpun, "head"); + _punpunData.Item3 = CheckSlot(punpun, "mask"); + _punpunData.Item4 = CheckSlot(punpun, "jumpsuit"); + } + + punpunComponents.Dispose(); + } + + // Equips an item to a slot, and names it. + private void EquipItem(EntityUid uid, string slot, string item) + { + if (item == string.Empty) + return; + + var itemEnt = EntityManager.SpawnEntity(item, EntityManager.GetComponent(uid).Coordinates); + if (_inventory.TryEquip(uid, itemEnt, slot, true, true)) + _meta.SetEntityName(itemEnt, $"{MetaData(uid).EntityName}'s {MetaData(itemEnt).EntityName}"); + else + EntityManager.DeleteEntity(itemEnt); + } + + // Checks if an item exists in a slot, and returns its name + private string CheckSlot(EntityUid uid, string slot) + { + return _inventory.TryGetSlotEntity(uid, slot, out var item) + ? EntityManager.GetComponent(item.Value).EntityPrototype!.ID + : string.Empty; + } + + + // Punpun, the lord of Roman Numerals + public static List RomanNumerals = new() { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; + public static List Numerals = new() { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; + + public static string ToRomanNumeral(int number) + { + var romanNumeral = string.Empty; + while (number > 0) + { + // Find the biggest numeral that is less than equal to number + var index = Numerals.FindIndex(x => x <= number); + // Subtract its value from your number + number -= Numerals[index]; + // Add it onto the end of your roman numeral + romanNumeral += RomanNumerals[index]; + } + return romanNumeral; + } +} diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 420e7ed50da..f19e76ecf54 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -825,13 +825,6 @@ id: MobMonkeyPunpun description: A prominent representative of monkeys with unlimited access to alcohol. components: - - type: GhostRole - prob: 1 - makeSentient: true - allowSpeech: true - allowMovement: true - name: ghost-role-information-punpun-name - description: ghost-role-information-punpun-description - type: GhostTakeoverAvailable - type: Butcherable butcheringType: Spike @@ -859,6 +852,7 @@ - TauCetiBasic - Monkey - Kobold + - type: Punpun - type: entity name: Tropico diff --git a/Resources/Prototypes/Entities/Objects/Misc/paper.yml b/Resources/Prototypes/Entities/Objects/Misc/paper.yml index d3db29b4209..c72f7a2e91e 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/paper.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/paper.yml @@ -159,6 +159,16 @@ backgroundPatchMargin: 16.0, 16.0, 16.0, 16.0 contentMargin: 32.0, 16.0, 32.0, 0.0 +- type: entity + name: note + description: A piece of white paper. + id: PaperWrittenPunpunNote + parent: PaperCaptainsThoughts + suffix: Punpun Note + components: + - type: Paper + content: I, Punpun, invoke my right to have all of my clones on the NT family vacation to the meat packaging plant one out of every 15 shifts. + - type: entity name: cargo invoice parent: Paper diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 15424a68ec7..156e5d27014 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -655,6 +655,7 @@ public sealed partial class $CLASS$ : Shared$CLASS$ { True True True + True True True True