Skip to content
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

Port Cool Punpun #1157

Merged
merged 4 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Content.Server/Punpun/PunpunComponent.cs
Original file line number Diff line number Diff line change
@@ -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;
}
114 changes: 114 additions & 0 deletions Content.Server/Punpun/PunpunSystem.cs
Original file line number Diff line number Diff line change
@@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should really be a named struct/class



public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<PunpunComponent, ComponentStartup>(OnRoundStart);
SubscribeLocalEvent<RoundEndTextAppendEvent>(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<InventoryComponent>(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<PunpunComponent>();
punpunComponents.MoveNext(out var punpun, out _);

if (!EntityManager.TryGetComponent<MobStateComponent>(punpun, out var mobState)
|| mobState.CurrentState == MobState.Dead)
_punpunData = (1, string.Empty, string.Empty, string.Empty);

_punpunData.Item1++;

if (EntityManager.HasComponent<InventoryComponent>(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<TransformComponent>(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<MetaDataComponent>(item.Value).EntityPrototype!.ID
: string.Empty;
}


// Punpun, the lord of Roman Numerals
public static List<string> RomanNumerals = new() { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
public static List<int> 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;
}
}
8 changes: 1 addition & 7 deletions Resources/Prototypes/Entities/Mobs/NPCs/pets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -859,6 +852,7 @@
- TauCetiBasic
- Monkey
- Kobold
- type: Punpun

- type: entity
name: Tropico
Expand Down
10 changes: 10 additions & 0 deletions Resources/Prototypes/Entities/Objects/Misc/paper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions SpaceStation14.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ public sealed partial class $CLASS$ : Shared$CLASS$ {
<s:Boolean x:Key="/Default/UserDictionary/Words/=prefs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Protolathe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pullable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=punpun/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Redescribe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reparenting/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=roundstart/@EntryIndexedValue">True</s:Boolean>
Expand Down
Loading