diff --git a/Content.Client/Administration/Components/KillSignComponent.cs b/Content.Client/Administration/Components/KillSignComponent.cs new file mode 100644 index 0000000000..88d7c266b1 --- /dev/null +++ b/Content.Client/Administration/Components/KillSignComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared.Administration.Components; +using Robust.Shared.GameStates; + +namespace Content.Client.Administration.Components; + +[NetworkedComponent, RegisterComponent] +public sealed class KillSignComponent : SharedKillSignComponent +{ } diff --git a/Content.Client/Administration/KillSignSystem.cs b/Content.Client/Administration/KillSignSystem.cs new file mode 100644 index 0000000000..2959593bb9 --- /dev/null +++ b/Content.Client/Administration/KillSignSystem.cs @@ -0,0 +1,47 @@ +using Content.Client.Administration.Components; +using Robust.Client.GameObjects; +using Robust.Shared.Utility; + +namespace Content.Client.Administration; + +public sealed class KillSignSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(KillSignAdded); + SubscribeLocalEvent(KillSignRemoved); + } + + private void KillSignRemoved(EntityUid uid, KillSignComponent component, ComponentShutdown args) + { + if (!TryComp(uid, out var sprite)) + return; + + if (!sprite.LayerMapTryGet(KillSignKey.Key, out var layer)) + return; + + sprite.RemoveLayer(layer); + } + + private void KillSignAdded(EntityUid uid, KillSignComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var sprite)) + return; + + if (sprite.LayerMapTryGet(KillSignKey.Key, out var _)) + return; + + var adj = sprite.Bounds.Height / 2 + ((1.0f/32) * 6.0f); + + var layer = sprite.AddLayer(new SpriteSpecifier.Rsi(new ResourcePath("Objects/Misc/killsign.rsi"), "sign")); + sprite.LayerMapSet(KillSignKey.Key, layer); + + sprite.LayerSetOffset(layer, new Vector2(0.0f, adj)); + sprite.LayerSetShader(layer, "unshaded"); + } + + private enum KillSignKey + { + Key, + } +} diff --git a/Content.Server/Administration/Commands/SetOutfitCommand.cs b/Content.Server/Administration/Commands/SetOutfitCommand.cs index 978c7cda9b..cd582ace23 100644 --- a/Content.Server/Administration/Commands/SetOutfitCommand.cs +++ b/Content.Server/Administration/Commands/SetOutfitCommand.cs @@ -47,7 +47,7 @@ namespace Content.Server.Administration.Commands return; } - if (!entityManager.TryGetComponent(target, out var inventoryComponent)) + if (!entityManager.HasComponent(target)) { shell.WriteLine(Loc.GetString("shell-target-entity-does-not-have-message",("missing", "inventory"))); return; @@ -67,12 +67,18 @@ namespace Content.Server.Administration.Commands return; } - var prototypeManager = IoCManager.Resolve(); - if (!prototypeManager.TryIndex(args[1], out var startingGear)) - { + if (!SetOutfit(target, args[1], entityManager)) shell.WriteLine(Loc.GetString("set-outfit-command-invalid-outfit-id-error")); - return; - } + } + + public static bool SetOutfit(EntityUid target, string gear, IEntityManager entityManager, Action? onEquipped = null) + { + if (!entityManager.TryGetComponent(target, out var inventoryComponent)) + return false; + + var prototypeManager = IoCManager.Resolve(); + if (!prototypeManager.TryIndex(gear, out var startingGear)) + return false; HumanoidCharacterProfile? profile = null; // Check if we are setting the outfit of a player to respect the preferences @@ -104,8 +110,12 @@ namespace Content.Server.Administration.Commands } invSystem.TryEquip(target, equipmentEntity, slot.Name, true, inventory: inventoryComponent); + + onEquipped?.Invoke(target, equipmentEntity); } } + + return true; } } } diff --git a/Content.Server/Administration/Components/BufferingComponent.cs b/Content.Server/Administration/Components/BufferingComponent.cs new file mode 100644 index 0000000000..57edce5480 --- /dev/null +++ b/Content.Server/Administration/Components/BufferingComponent.cs @@ -0,0 +1,22 @@ +using Content.Server.Administration.Systems; + +namespace Content.Server.Administration.Components; + +[RegisterComponent, Friend(typeof(BufferingSystem))] +public sealed class BufferingComponent : Component +{ + [DataField("minBufferTime")] + public float MinimumBufferTime = 0.5f; + [DataField("maxBufferTime")] + public float MaximumBufferTime = 1.5f; + [DataField("minTimeTilNextBuffer")] + public float MinimumTimeTilNextBuffer = 10.0f; + [DataField("maxTimeTilNextBuffer")] + public float MaximumTimeTilNextBuffer = 120.0f; + [DataField("timeTilNextBuffer")] + public float TimeTilNextBuffer = 15.0f; + [DataField("bufferingIcon")] + public EntityUid? BufferingIcon = null; + [DataField("bufferingTimer")] + public float BufferingTimer = 0.0f; +} diff --git a/Content.Server/Administration/Components/KillSignComponent.cs b/Content.Server/Administration/Components/KillSignComponent.cs new file mode 100644 index 0000000000..97ae88994f --- /dev/null +++ b/Content.Server/Administration/Components/KillSignComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared.Administration.Components; +using Robust.Shared.GameStates; + +namespace Content.Server.Administration.Components; + +[NetworkedComponent, RegisterComponent] +public sealed class KillSignComponent : SharedKillSignComponent +{ } diff --git a/Content.Server/Administration/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs similarity index 98% rename from Content.Server/Administration/AdminSystem.cs rename to Content.Server/Administration/Systems/AdminSystem.cs index c4eae343ce..b9e2f5a633 100644 --- a/Content.Server/Administration/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -1,4 +1,4 @@ -using System.Globalization; +using System.Globalization; using System.Linq; using Content.Server.Administration.Managers; using Content.Server.Players; @@ -10,7 +10,7 @@ using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.Network; -namespace Content.Server.Administration +namespace Content.Server.Administration.Systems { public sealed class AdminSystem : EntitySystem { diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs new file mode 100644 index 0000000000..974deb0f9c --- /dev/null +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -0,0 +1,534 @@ +using System.Linq; +using System.Threading; +using Content.Server.Administration.Commands; +using Content.Server.Administration.Components; +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Server.Clothing.Components; +using Content.Server.Damage.Systems; +using Content.Server.Disease; +using Content.Server.Disease.Components; +using Content.Server.Electrocution; +using Content.Server.Explosion.EntitySystems; +using Content.Server.GhostKick; +using Content.Server.Interaction.Components; +using Content.Server.Medical; +using Content.Server.Nutrition.EntitySystems; +using Content.Server.Pointing.Components; +using Content.Server.Polymorph.Systems; +using Content.Server.Popups; +using Content.Server.Tabletop; +using Content.Server.Tabletop.Components; +using Content.Shared.Administration; +using Content.Shared.Body.Components; +using Content.Shared.Body.Part; +using Content.Shared.Damage; +using Content.Shared.Database; +using Content.Shared.Disease; +using Content.Shared.Electrocution; +using Content.Shared.Interaction.Components; +using Content.Shared.Inventory; +using Content.Shared.MobState.Components; +using Content.Shared.Movement.Components; +using Content.Shared.Nutrition.Components; +using Content.Shared.Tabletop.Components; +using Content.Shared.Verbs; +using Robust.Server.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Player; +using Robust.Shared.Random; +using Robust.Shared.Utility; +using Timer = Robust.Shared.Timing.Timer; + +namespace Content.Server.Administration.Systems; + +public sealed partial class AdminVerbSystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly GhostKickManager _ghostKickManager = default!; + [Dependency] private readonly PolymorphableSystem _polymorphableSystem = default!; + [Dependency] private readonly InventorySystem _inventorySystem = default!; + [Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!; + [Dependency] private readonly CreamPieSystem _creamPieSystem = default!; + [Dependency] private readonly DiseaseSystem _diseaseSystem = default!; + [Dependency] private readonly TabletopSystem _tabletopSystem = default!; + [Dependency] private readonly ExplosionSystem _explosionSystem = default!; + [Dependency] private readonly FlammableSystem _flammableSystem = default!; + [Dependency] private readonly GodmodeSystem _godmodeSystem = default!; + [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!; + [Dependency] private readonly BodySystem _bodySystem = default!; + [Dependency] private readonly VomitSystem _vomitSystem = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + + // All smite verbs have names so invokeverb works. + private void AddSmiteVerbs(GetVerbsEvent args) + { + if (!EntityManager.TryGetComponent(args.User, out var actor)) + return; + + var player = actor.PlayerSession; + + if (!_adminManager.HasAdminFlag(player, AdminFlags.Fun)) + return; + + Verb explode = new() + { + Text = "Explode", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Interface/VerbIcons/smite.svg.192dpi.png", + Act = () => + { + var coords = Transform(args.Target).MapPosition; + Timer.Spawn(_gameTiming.TickPeriod, + () => _explosionSystem.QueueExplosion(coords, ExplosionSystem.DefaultExplosionPrototypeId, + 4, 1, 2, maxTileBreak: 0), // it gibs, damage doesn't need to be high. + CancellationToken.None); + + if (TryComp(args.Target, out SharedBodyComponent? body)) + { + body.Gib(); + } + }, + Impact = LogImpact.Extreme, + Message = "Explode them.", + }; + args.Verbs.Add(explode); + + Verb chess = new() + { + Text = "Chess Dimension", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Fun/Tabletop/chessboard.rsi/chessboard.png", + Act = () => + { + _godmodeSystem.EnableGodmode(args.Target); // So they don't suffocate. + EnsureComp(args.Target); + RemComp(args.Target); // So they can be dragged around. + var xform = Transform(args.Target); + _popupSystem.PopupEntity(Loc.GetString("admin-smite-chess-self"), args.Target, Filter.Entities(args.Target)); + _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-chess-others", ("name", args.Target)), xform.Coordinates, Filter.Pvs(args.Target).RemoveWhereAttachedEntity(x => x == args.Target)); + var board = Spawn("ChessBoard", xform.Coordinates); + var session = _tabletopSystem.EnsureSession(Comp(board)); + xform.Coordinates = EntityCoordinates.FromMap(_mapManager, session.Position); + xform.WorldRotation = Angle.Zero; + }, + Impact = LogImpact.Extreme, + Message = "Banishment to the Chess Dimension.", + }; + args.Verbs.Add(chess); + + if (TryComp(args.Target, out var flammable)) + { + Verb flames = new() + { + Text = "Set Alight", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Interface/Alerts/Fire/fire.png", + Act = () => + { + // Fuck you. Burn Forever. + flammable.FireStacks = 99999.9f; + _flammableSystem.Ignite(args.Target); + var xform = Transform(args.Target); + _popupSystem.PopupEntity(Loc.GetString("admin-smite-set-alight-self"), args.Target, Filter.Entities(args.Target)); + _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-set-alight-others", ("name", args.Target)), xform.Coordinates, Filter.Pvs(args.Target).RemoveWhereAttachedEntity(x => x == args.Target)); + }, + Impact = LogImpact.Extreme, + Message = "Makes them burn.", + }; + args.Verbs.Add(flames); + } + + Verb monkey = new() + { + Text = "Monkeyify", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Mobs/Animals/monkey.rsi/dead.png", + Act = () => + { + _polymorphableSystem.PolymorphEntity(args.Target, "AdminMonkeySmite"); + }, + Impact = LogImpact.Extreme, + Message = "Monkey mode.", + }; + args.Verbs.Add(monkey); + + if (TryComp(args.Target, out var carrier)) + { + Verb lungCancer = new() + { + Text = "Lung Cancer", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Mobs/Species/Human/organs.rsi/lung-l.png", + Act = () => + { + _diseaseSystem.TryInfect(carrier, _prototypeManager.Index("StageIIIALungCancer"), + 1.0f, true); + }, + Impact = LogImpact.Extreme, + Message = "Stage IIIA Lung Cancer, for when they really like the hit show Breaking Bad.", + }; + args.Verbs.Add(lungCancer); + } + + if (TryComp(args.Target, out var damageable) && + TryComp(args.Target, out var mobState)) + { + Verb hardElectrocute = new() + { + Text = "Electrocute", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Clothing/Hands/Gloves/Color/yellow.rsi/icon.png", + Act = () => + { + int damageToDeal; + var critState = mobState._highestToLowestStates.Where(x => x.Value.IsCritical()).FirstOrNull(); + if (critState is null) + { + // We can't crit them so try killing them. + var deadState = mobState._highestToLowestStates.Where(x => x.Value.IsDead()).FirstOrNull(); + if (deadState is null) + return; // whelp. + + damageToDeal = deadState.Value.Key - (int) damageable.TotalDamage; + } + else + { + damageToDeal = critState.Value.Key - (int) damageable.TotalDamage; + } + + if (damageToDeal <= 0) + damageToDeal = 100; // murder time. + + if (_inventorySystem.TryGetSlots(args.Target, out var slotDefinitions)) + { + foreach (var slot in slotDefinitions) + { + if (!_inventorySystem.TryGetSlotEntity(args.Target, slot.Name, out var slotEnt)) + continue; + + RemComp(slotEnt.Value); // Fry the gloves. + } + } + + _electrocutionSystem.TryDoElectrocution(args.Target, null, damageToDeal, + TimeSpan.FromSeconds(30), true); + }, + Impact = LogImpact.Extreme, + Message = "Electrocutes them, rendering anything they were wearing useless.", + }; + args.Verbs.Add(hardElectrocute); + } + + if (TryComp(args.Target, out var creamPied)) + { + Verb creamPie = new() + { + Text = "Creampie", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Consumable/Food/Baked/pie.rsi/plain-slice.png", + Act = () => + { + _creamPieSystem.SetCreamPied(args.Target, creamPied, true); + }, + Impact = LogImpact.Extreme, + Message = "A cream pie, condensed into a button.", + }; + args.Verbs.Add(creamPie); + } + + if (TryComp(args.Target, out var bloodstream)) + { + Verb bloodRemoval = new() + { + Text = "Remove blood", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Fluids/tomato_splat.rsi/puddle-1.png", + Act = () => + { + _bloodstreamSystem.SpillAllSolutions(args.Target, bloodstream); + var xform = Transform(args.Target); + _popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-blood-self"), args.Target, Filter.Entities(args.Target)); + _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-remove-blood-others", ("name", args.Target)), xform.Coordinates, Filter.Pvs(args.Target).RemoveWhereAttachedEntity(x => x == args.Target)); + }, + Impact = LogImpact.Extreme, + Message = "Removes their blood. All of it.", + }; + args.Verbs.Add(bloodRemoval); + } + + // bobby... + if (TryComp(args.Target, out var body)) + { + Verb vomitOrgans = new() + { + Text = "Vomit organs", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Fluids/vomit_toxin.rsi/vomit_toxin-1.png", + Act = () => + { + _vomitSystem.Vomit(args.Target, -1000, -1000); // You feel hollow! + var organs = _bodySystem.GetComponentsOnMechanisms(args.Target, body); + var baseXform = Transform(args.Target); + foreach (var (xform, mechanism) in organs) + { + if (HasComp(xform.Owner) || HasComp(xform.Owner)) + continue; + + mechanism.Part?.RemoveMechanism(mechanism); + xform.Coordinates = baseXform.Coordinates.Offset(_random.NextVector2(0.5f,0.75f)); + } + + _popupSystem.PopupEntity(Loc.GetString("admin-smite-vomit-organs-self"), args.Target, Filter.Entities(args.Target)); + _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-vomit-organs-others", ("name", args.Target)), baseXform.Coordinates, Filter.Pvs(args.Target).RemoveWhereAttachedEntity(x => x == args.Target)); + }, + Impact = LogImpact.Extreme, + Message = "Causes them to vomit, including their internal organs.", + }; + args.Verbs.Add(vomitOrgans); + + Verb handRemoval = new() + { + Text = "Remove hands", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Interface/fist.svg.192dpi.png", + Act = () => + { + var baseXform = Transform(args.Target); + foreach (var part in body.GetPartsOfType(BodyPartType.Hand)) + { + body.RemovePart(part); + Transform(part.Owner).Coordinates = baseXform.Coordinates; + } + _popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-hands-self"), args.Target, Filter.Entities(args.Target)); + _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-remove-hands-others", ("name", args.Target)), baseXform.Coordinates, Filter.Pvs(args.Target).RemoveWhereAttachedEntity(x => x == args.Target)); + }, + Impact = LogImpact.Extreme, + Message = "Removes the target's hands.", + }; + args.Verbs.Add(handRemoval); + } + + if (TryComp(args.Target, out var physics)) + { + Verb pinball = new() + { + Text = "Pinball", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Fun/toys.rsi/basketball.png", + Act = () => + { + var xform = Transform(args.Target); + var fixtures = Comp(args.Target); + xform.Anchored = false; // Just in case. + physics.BodyType = BodyType.Dynamic; + physics.BodyStatus = BodyStatus.InAir; + physics.WakeBody(); + foreach (var (_, fixture) in fixtures.Fixtures) + { + if (!fixture.Hard) + continue; + fixture.Restitution = 1.1f; + } + + physics.LinearVelocity = _random.NextVector2(1.5f, 1.5f); + physics.AngularVelocity = MathF.PI * 12; + physics.LinearDamping = 0.0f; + physics.AngularDamping = 0.0f; + }, + Impact = LogImpact.Extreme, + Message = + "Turns them into a super bouncy ball, flinging them around until they clip through the station into the abyss.", + }; + args.Verbs.Add(pinball); + + Verb yeet = new() + { + Text = "Yeet", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Interface/VerbIcons/eject.svg.192dpi.png", + Act = () => + { + var xform = Transform(args.Target); + var fixtures = Comp(args.Target); + xform.Anchored = false; // Just in case. + physics.BodyType = BodyType.Dynamic; + physics.BodyStatus = BodyStatus.InAir; + physics.WakeBody(); + foreach (var (_, fixture) in fixtures.Fixtures) + { + fixture.Hard = false; + } + + physics.LinearVelocity = _random.NextVector2(8.0f, 8.0f); + physics.AngularVelocity = MathF.PI * 12; + physics.LinearDamping = 0.0f; + physics.AngularDamping = 0.0f; + }, + Impact = LogImpact.Extreme, + Message = "Banishes them into the depths of space by turning on no-clip and tossing them.", + }; + args.Verbs.Add(yeet); + } + + Verb bread = new() + { + Text = "Become Bread", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Consumable/Food/Baked/bread.rsi/plain.png", + Act = () => + { + _polymorphableSystem.PolymorphEntity(args.Target, "AdminBreadSmite"); + }, + Impact = LogImpact.Extreme, + Message = "It turns them into bread. Really. That's all it does.", + }; + args.Verbs.Add(bread); + + if (TryComp(args.Target, out var actorComponent)) + { + Verb ghostKick = new() + { + Text = "Ghostkick", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Interface/gavel.svg.192dpi.png", + Act = () => + { + _ghostKickManager.DoDisconnect(actorComponent.PlayerSession.ConnectedClient, "Smitten."); + }, + Impact = LogImpact.Extreme, + Message = "Silently kicks the user, dropping their connection.", + }; + args.Verbs.Add(ghostKick); + } + + if (TryComp(args.Target, out var inventory)) { + Verb nyanify = new() + { + Text = "Nyanify", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Clothing/Head/Hats/catears.rsi/icon.png", + Act = () => + { + var ears = Spawn("ClothingHeadHatCatEars", Transform(args.Target).Coordinates); + EnsureComp(ears); + _inventorySystem.TryUnequip(args.Target, "head", true, true, false, inventory); + _inventorySystem.TryEquip(args.Target, ears, "head", true, true, false, inventory); + }, + Impact = LogImpact.Extreme, + Message = "Forcibly adds cat ears. There is no escape.", + }; + args.Verbs.Add(nyanify); + + Verb killSign = new() + { + Text = "Kill sign", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Misc/killsign.rsi/icon.png", + Act = () => + { + EnsureComp(args.Target); + }, + Impact = LogImpact.Extreme, + Message = "Marks a player for death by their fellows.", + }; + args.Verbs.Add(killSign); + + // TODO: Port cluwne outfit. + Verb clown = new() + { + Text = "Clown", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Fun/bikehorn.rsi/icon.png", + Act = () => + { + SetOutfitCommand.SetOutfit(args.Target, "ClownGear", EntityManager, (_, clothing) => + { + if (HasComp(clothing)) + EnsureComp(clothing); + EnsureComp(args.Target); + }); + }, + Impact = LogImpact.Extreme, + Message = "Clowns them. The suit cannot be removed.", + }; + args.Verbs.Add(clown); + } + + Verb angerPointingArrows = new() + { + Text = "Anger Pointing Arrows", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Interface/Misc/pointing.rsi/pointing.png", + Act = () => + { + EnsureComp(args.Target); + }, + Impact = LogImpact.Extreme, + Message = "Angers the pointing arrows, causing them to assault this entity.", + }; + args.Verbs.Add(angerPointingArrows); + + Verb dust = new() + { + Text = "Dust", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Materials/materials.rsi/ash.png", + Act = () => + { + EntityManager.QueueDeleteEntity(args.Target); + Spawn("Ash", Transform(args.Target).Coordinates); + _popupSystem.PopupEntity(Loc.GetString("admin-smite-turned-ash-other", ("name", args.Target)), args.Target, Filter.Pvs(args.Target)); + }, + Impact = LogImpact.Extreme, + Message = "Reduces the target to a small pile of ash.", + }; + args.Verbs.Add(dust); + + Verb youtubeVideoSimulation = new() + { + Text = "Buffering", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Interface/Misc/buffering_smite_icon.png", + Act = () => + { + EnsureComp(args.Target); + }, + Impact = LogImpact.Extreme, + Message = "Causes the target to randomly start buffering, freezing them in place for a short timespan while they load.", + }; + args.Verbs.Add(youtubeVideoSimulation); + + Verb instrumentation = new() + { + Text = "Become Instrument", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Objects/Fun/Instruments/h_synthesizer.rsi/icon.png", + Act = () => + { + _polymorphableSystem.PolymorphEntity(args.Target, "AdminInstrumentSmite"); + }, + Impact = LogImpact.Extreme, + Message = "It turns them into a supersynth. Really. That's all it does.", + }; + args.Verbs.Add(instrumentation); + + Verb noGravity = new() + { + Text = "Remove gravity", + Category = VerbCategory.Smite, + IconTexture = "/Textures/Structures/Machines/gravity_generator.rsi/off.png", + Act = () => + { + var grav = EnsureComp(args.Target); + grav.Weightless = true; + }, + Impact = LogImpact.Extreme, + Message = "Grants them anti-gravity.", + }; + args.Verbs.Add(noGravity); + } +} diff --git a/Content.Server/Administration/AdminVerbSystem.cs b/Content.Server/Administration/Systems/AdminVerbSystem.cs similarity index 91% rename from Content.Server/Administration/AdminVerbSystem.cs rename to Content.Server/Administration/Systems/AdminVerbSystem.cs index 3a286b3857..69242acb92 100644 --- a/Content.Server/Administration/AdminVerbSystem.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.cs @@ -1,4 +1,3 @@ -using System.Threading; using Content.Server.Administration.Commands; using Content.Server.Administration.Managers; using Content.Server.Administration.UI; @@ -7,7 +6,6 @@ using Content.Server.Chemistry.EntitySystems; using Content.Server.Configurable; using Content.Server.Disposal.Tube.Components; using Content.Server.EUI; -using Content.Server.Explosion.EntitySystems; using Content.Server.Ghost.Roles; using Content.Server.Mind.Commands; using Content.Server.Mind.Components; @@ -15,7 +13,6 @@ using Content.Server.Players; using Content.Server.Xenoarchaeology.XenoArtifacts; using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components; using Content.Shared.Administration; -using Content.Shared.Body.Components; using Content.Shared.Database; using Content.Shared.GameTicking; using Content.Shared.Interaction.Helpers; @@ -26,23 +23,25 @@ using Robust.Server.Console; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Console; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; using static Content.Shared.Configurable.SharedConfigurationComponent; -using Timer = Robust.Shared.Timing.Timer; -namespace Content.Server.Administration +namespace Content.Server.Administration.Systems { /// /// System to provide various global admin/debug verbs /// - public sealed class AdminVerbSystem : EntitySystem + public sealed partial class AdminVerbSystem : EntitySystem { [Dependency] private readonly IConGroupController _groupController = default!; [Dependency] private readonly IConsoleHost _console = default!; [Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly EuiManager _euiManager = default!; - [Dependency] private readonly ExplosionSystem _explosionSystem = default!; [Dependency] private readonly GhostRoleSystem _ghostRoleSystem = default!; [Dependency] private readonly ArtifactSystem _artifactSystem = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; @@ -53,6 +52,7 @@ namespace Content.Server.Administration { SubscribeLocalEvent>(AddAdminVerbs); SubscribeLocalEvent>(AddDebugVerbs); + SubscribeLocalEvent>(AddSmiteVerbs); SubscribeLocalEvent(Reset); SubscribeLocalEvent(OnSolutionChanged); } @@ -142,29 +142,6 @@ namespace Content.Server.Administration Impact = LogImpact.Low }); } - - // Artillery - if (_adminManager.HasAdminFlag(player, AdminFlags.Fun)) - { - Verb verb = new(); - verb.Text = Loc.GetString("explode-verb-get-data-text"); - verb.Category = VerbCategory.Admin; - verb.Act = () => - { - var coords = Transform(args.Target).MapPosition; - Timer.Spawn(_gameTiming.TickPeriod, - () => _explosionSystem.QueueExplosion(coords, ExplosionSystem.DefaultExplosionPrototypeId, 4, 1, 2, maxTileBreak: 0), // it gibs, damage doesn't need to be high. - CancellationToken.None); - - if (TryComp(args.Target, out SharedBodyComponent? body)) - { - body.Gib(); - } - }; - verb.Impact = LogImpact.Extreme; // if you're just outright killing a person, I guess that deserves to be extreme? - verb.ConfirmationPopup = true; - args.Verbs.Add(verb); - } } private void AddDebugVerbs(GetVerbsEvent args) diff --git a/Content.Server/Administration/Systems/BufferingSystem.cs b/Content.Server/Administration/Systems/BufferingSystem.cs new file mode 100644 index 0000000000..00a0a929fe --- /dev/null +++ b/Content.Server/Administration/Systems/BufferingSystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Administration.Components; +using Content.Shared.Administration; +using Robust.Shared.Map; +using Robust.Shared.Random; + +namespace Content.Server.Administration.Systems; + +public sealed class BufferingSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + + public override void Update(float frameTime) + { + foreach (var buffering in EntityQuery()) + { + if (buffering.BufferingIcon is not null) + { + buffering.BufferingTimer -= frameTime; + if (!(buffering.BufferingTimer <= 0.0f)) + continue; + + Del(buffering.BufferingIcon.Value); + RemComp(buffering.Owner); + buffering.TimeTilNextBuffer = _random.NextFloat(buffering.MinimumTimeTilNextBuffer, buffering.MaximumTimeTilNextBuffer); + buffering.BufferingIcon = null; + } + else + { + buffering.TimeTilNextBuffer -= frameTime; + if (!(buffering.TimeTilNextBuffer <= 0.0f)) + continue; + + buffering.BufferingTimer = _random.NextFloat(buffering.MinimumBufferTime, buffering.MaximumBufferTime); + buffering.BufferingIcon = Spawn("BufferingIcon", new EntityCoordinates(buffering.Owner, Vector2.Zero)); + EnsureComp(buffering.Owner); + } + } + } +} diff --git a/Content.Server/Administration/BwoinkSystem.cs b/Content.Server/Administration/Systems/BwoinkSystem.cs similarity index 99% rename from Content.Server/Administration/BwoinkSystem.cs rename to Content.Server/Administration/Systems/BwoinkSystem.cs index c4e28c5cf6..305b8c0315 100644 --- a/Content.Server/Administration/BwoinkSystem.cs +++ b/Content.Server/Administration/Systems/BwoinkSystem.cs @@ -1,9 +1,12 @@ -using System.Linq; +using System.Linq; using System.Net.Http; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; +using System.Text.Json.Serialization; using Content.Server.Administration.Managers; +using Content.Server.GameTicking; +using Content.Server.GameTicking.Events; using Content.Shared.Administration; using Content.Shared.CCVar; using JetBrains.Annotations; @@ -12,11 +15,8 @@ using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Network; using Robust.Shared.Utility; -using System.Text.Json.Serialization; -using Content.Server.GameTicking.Events; -using Content.Server.GameTicking; -namespace Content.Server.Administration +namespace Content.Server.Administration.Systems { [UsedImplicitly] public sealed class BwoinkSystem : SharedBwoinkSystem diff --git a/Content.Server/Administration/UI/EditSolutionsEui.cs b/Content.Server/Administration/UI/EditSolutionsEui.cs index e9f04696a2..419425c356 100644 --- a/Content.Server/Administration/UI/EditSolutionsEui.cs +++ b/Content.Server/Administration/UI/EditSolutionsEui.cs @@ -30,7 +30,7 @@ namespace Content.Server.Administration.UI public override void Closed() { base.Closed(); - EntitySystem.Get().OnEditSolutionsEuiClosed(Player); + EntitySystem.Get().OnEditSolutionsEuiClosed(Player); } public override EuiStateBase GetNewState() diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index f733b36bf5..9e5cdc7722 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -289,8 +289,11 @@ public sealed class BloodstreamSystem : EntitySystem var tempSol = new Solution() { MaxVolume = max }; tempSol.AddSolution(component.BloodSolution); + component.BloodSolution.RemoveAllSolution(); tempSol.AddSolution(component.BloodTemporarySolution); + component.BloodTemporarySolution.RemoveAllSolution(); tempSol.AddSolution(component.ChemicalSolution); + component.ChemicalSolution.RemoveAllSolution(); _spillableSystem.SpillAt(uid, tempSol, "PuddleBlood", true); } } diff --git a/Content.Server/Mind/Commands/RenameCommand.cs b/Content.Server/Mind/Commands/RenameCommand.cs index bf9c544e6d..ec0149f233 100644 --- a/Content.Server/Mind/Commands/RenameCommand.cs +++ b/Content.Server/Mind/Commands/RenameCommand.cs @@ -1,5 +1,6 @@ using Content.Server.Access.Systems; using Content.Server.Administration; +using Content.Server.Administration.Systems; using Content.Server.Cloning; using Content.Server.Mind.Components; using Content.Server.PDA; diff --git a/Content.Server/Pointing/Components/PointingArrowAngeringComponent.cs b/Content.Server/Pointing/Components/PointingArrowAngeringComponent.cs new file mode 100644 index 0000000000..42d8e3c154 --- /dev/null +++ b/Content.Server/Pointing/Components/PointingArrowAngeringComponent.cs @@ -0,0 +1,12 @@ +namespace Content.Server.Pointing.Components; + +/// +/// Causes pointing arrows to go mode and murder this entity. +/// +[RegisterComponent] +public sealed class PointingArrowAngeringComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + [DataField("remainingAnger")] + public int RemainingAnger = 5; +} diff --git a/Content.Server/Pointing/Components/PointingArrowComponent.cs b/Content.Server/Pointing/Components/PointingArrowComponent.cs index 53e7753534..37e89cf3ea 100644 --- a/Content.Server/Pointing/Components/PointingArrowComponent.cs +++ b/Content.Server/Pointing/Components/PointingArrowComponent.cs @@ -51,7 +51,7 @@ namespace Content.Server.Pointing.Components /// [ViewVariables(VVAccess.ReadWrite)] [DataField("rogue")] - private bool _rogue = default; + public bool Rogue = false; protected override void Startup() { @@ -73,7 +73,7 @@ namespace Content.Server.Pointing.Components if (_duration <= 0) { - if (_rogue) + if (Rogue) { _entMan.RemoveComponent(Owner); _entMan.AddComponent(Owner); diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index 0a06c6ad00..bf8d522941 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Server.Ghost.Components; using Content.Server.Players; using Content.Server.Pointing.Components; @@ -120,6 +121,14 @@ namespace Content.Server.Pointing.EntitySystems var arrow = EntityManager.SpawnEntity("pointingarrow", mapCoords); + if (EntityQuery().FirstOrDefault() != null) + { + if (TryComp(arrow, out var pointingArrowComponent)) + { + pointingArrowComponent.Rogue = true; + } + } + var layer = (int) VisibilityFlags.Normal; if (TryComp(player, out VisibilityComponent? playerVisibility)) { diff --git a/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs b/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs index 4cab96fe59..9abe7fbc8d 100644 --- a/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs @@ -37,15 +37,17 @@ namespace Content.Server.Pointing.EntitySystems if (!Resolve(uid, ref component, ref transform)) return null; - var players = Filter.Empty() - .AddPlayersByPvs(transform.MapPosition) - .RemoveWhereAttachedEntity(euid => !EntityManager.TryGetComponent(euid, out MobStateComponent? mobStateComponent) || mobStateComponent.IsDead()) - .Recipients - .ToArray(); + var targets = EntityQuery().ToList(); - return players.Length != 0 - ? _random.Pick(players).AttachedEntity - : null; + if (targets.Count == 0) + return null; + + var angering = _random.Pick(targets); + angering.RemainingAnger -= 1; + if (angering.RemainingAnger <= 0) + RemComp(uid); + + return angering.Owner; } private void UpdateAppearance(EntityUid uid, RoguePointingArrowComponent? component = null, TransformComponent? transform = null, AppearanceComponent? appearance = null) @@ -56,6 +58,14 @@ namespace Content.Server.Pointing.EntitySystems appearance.SetData(RoguePointingArrowVisuals.Rotation, transform.LocalRotation.Degrees); } + public void SetTarget(EntityUid arrow, EntityUid target, RoguePointingArrowComponent? component = null) + { + if (!Resolve(arrow, ref component)) + throw new ArgumentException("Input was not a rogue pointing arrow!", nameof(arrow)); + + component.Chasing = target; + } + public override void Update(float frameTime) { foreach (var (component, transform) in EntityManager.EntityQuery()) @@ -63,7 +73,7 @@ namespace Content.Server.Pointing.EntitySystems var uid = component.Owner; component.Chasing ??= RandomNearbyPlayer(uid, component, transform); - if (component.Chasing is not {Valid: true} chasing) + if (component.Chasing is not {Valid: true} chasing || Deleted(chasing)) { EntityManager.QueueDeleteEntity(uid); return; diff --git a/Content.Server/Tabletop/TabletopSystem.Session.cs b/Content.Server/Tabletop/TabletopSystem.Session.cs index dc4cb0a78c..5dd822120c 100644 --- a/Content.Server/Tabletop/TabletopSystem.Session.cs +++ b/Content.Server/Tabletop/TabletopSystem.Session.cs @@ -14,7 +14,7 @@ namespace Content.Server.Tabletop /// /// The tabletop game in question. /// The session for the given tabletop game. - private TabletopSession EnsureSession(TabletopGameComponent tabletop) + public TabletopSession EnsureSession(TabletopGameComponent tabletop) { // We already have a session, return it // TODO: if tables are connected, treat them as a single entity. This can be done by sharing the session. diff --git a/Content.Shared/Administration/Components/SharedKillSignComponent.cs b/Content.Shared/Administration/Components/SharedKillSignComponent.cs new file mode 100644 index 0000000000..6536c39cbb --- /dev/null +++ b/Content.Shared/Administration/Components/SharedKillSignComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.Administration.Components; + +public abstract class SharedKillSignComponent : Component +{ + +} diff --git a/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs b/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs index 1384dbb52a..6e6499927b 100644 --- a/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs +++ b/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs @@ -1,14 +1,32 @@ using Content.Shared.Clothing; using Content.Shared.Gravity; using Content.Shared.Inventory; +using Robust.Shared.GameStates; using Robust.Shared.Map; using Robust.Shared.Physics; +using Robust.Shared.Serialization; namespace Content.Shared.Movement.Components { - [RegisterComponent] + [RegisterComponent, NetworkedComponent] public sealed class MovementIgnoreGravityComponent : Component { + /// + /// Whether or not gravity is on or off for this object. + /// + [DataField("gravityState")] public bool Weightless = false; + } + + + [NetSerializable, Serializable] + public sealed class MovementIgnoreGravityComponentState : ComponentState + { + public bool Weightless; + + public MovementIgnoreGravityComponentState(MovementIgnoreGravityComponent component) + { + Weightless = component.Weightless; + } } public static class GravityExtensions @@ -20,8 +38,8 @@ namespace Content.Shared.Movement.Components if (body == null) entityManager.TryGetComponent(entity, out body); - if (entityManager.HasComponent(entity) || - (body?.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0) return false; + if (entityManager.TryGetComponent(entity, out var ignoreGravityComponent) || + (body?.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0) return ignoreGravityComponent.Weightless; var transform = entityManager.GetComponent(entity); var gridId = transform.GridID; diff --git a/Content.Shared/Movement/EntitySystems/MovementIgnoreGravitySystem.cs b/Content.Shared/Movement/EntitySystems/MovementIgnoreGravitySystem.cs new file mode 100644 index 0000000000..4ecae7ca24 --- /dev/null +++ b/Content.Shared/Movement/EntitySystems/MovementIgnoreGravitySystem.cs @@ -0,0 +1,27 @@ +using Content.Shared.Alert; +using Content.Shared.Movement.Components; +using Robust.Shared.GameStates; + +namespace Content.Shared.Movement.EntitySystems; + +public sealed class MovementIgnoreGravitySystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(GetState); + SubscribeLocalEvent(HandleState); + } + + private void HandleState(EntityUid uid, MovementIgnoreGravityComponent component, ref ComponentHandleState args) + { + if (args.Next is null) + return; + + component.Weightless = ((MovementIgnoreGravityComponentState) args.Next).Weightless; + } + + private void GetState(EntityUid uid, MovementIgnoreGravityComponent component, ref ComponentGetState args) + { + args.State = new MovementIgnoreGravityComponentState(component); + } +} diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs index 26905d8815..66b0e39055 100644 --- a/Content.Shared/Verbs/VerbCategory.cs +++ b/Content.Shared/Verbs/VerbCategory.cs @@ -57,7 +57,10 @@ namespace Content.Shared.Verbs new("verb-categories-unbuckle", "/Textures/Interface/VerbIcons/unbuckle.svg.192dpi.png"); public static readonly VerbCategory Rotate = - new("verb-categories-rotate", "/Textures/Interface/VerbIcons/refresh.svg.192dpi.png", iconsOnly: true) { Columns = 5}; + new("verb-categories-rotate", "/Textures/Interface/VerbIcons/refresh.svg.192dpi.png", iconsOnly: true) { Columns = 5 }; + + public static readonly VerbCategory Smite = + new("verb-categories-smite", "/Textures/Interface/VerbIcons/smite.svg.192dpi.png", iconsOnly: true) { Columns = 5 }; public static readonly VerbCategory SetTransferAmount = new("verb-categories-transfer", "/Textures/Interface/VerbIcons/spill.svg.192dpi.png"); diff --git a/Resources/Locale/en-US/administration/smites.ftl b/Resources/Locale/en-US/administration/smites.ftl new file mode 100644 index 0000000000..cdbbef14a6 --- /dev/null +++ b/Resources/Locale/en-US/administration/smites.ftl @@ -0,0 +1,11 @@ +admin-smite-chess-self = You feel exceptionally small. +admin-smite-chess-others = {CAPITALIZE($name)} shrinks into the chessboard! +admin-smite-set-alight-self = You burst into flames! +admin-smite-set-alight-others = {CAPITALIZE($name)} bursts into flames! +admin-smite-remove-blood-self = You feel lighter, and chilly. +admin-smite-remove-blood-others = {CAPITALIZE($name)} leaks blood all over the floor! +admin-smite-vomit-organs-self = You puke, and feel rather hollow! +admin-smite-vomit-organs-others = {CAPITALIZE($name)} vomits up their organs! +admin-smite-remove-hands-self = Your hands fall off! +admin-smite-remove-hands-other = {CAPITALIZE($name)}'s hands fall off! +admin-smite-turned-ash-other = {CAPITALISE($name)} turns into a pile of ash! diff --git a/Resources/Locale/en-US/verbs/verb-system.ftl b/Resources/Locale/en-US/verbs/verb-system.ftl index f988b8561b..c4fdaed060 100644 --- a/Resources/Locale/en-US/verbs/verb-system.ftl +++ b/Resources/Locale/en-US/verbs/verb-system.ftl @@ -17,6 +17,7 @@ verb-categories-insert = Insert verb-categories-buckle = Buckle verb-categories-unbuckle = Unbuckle verb-categories-rotate = Rotate +verb-categories-smite = Smite verb-categories-transfer = Set Transfer Amount verb-categories-split = Split verb-categories-set-sensor = Sensor diff --git a/Resources/Prototypes/Diseases/noninfectious.yml b/Resources/Prototypes/Diseases/noninfectious.yml index ee0c3eb78d..753bdcc858 100644 --- a/Resources/Prototypes/Diseases/noninfectious.yml +++ b/Resources/Prototypes/Diseases/noninfectious.yml @@ -18,6 +18,29 @@ reagent: Phalanximine min: 15 + +- type: disease + id: StageIIIALungCancer + name: Stage IIIA Lung Cancer + infectious: false + cureResist: 1.0 + effects: + - !type:DiseaseHealthChange + probability: 0.3 + damage: + types: + Cellular: 1 + - !type:DiseaseVomit + probability: 0.01 + - !type:DiseaseSnough + probability: 0.10 + snoughMessage: disease-cough + snoughSound: + collection: Coughs + - !type:DiseasePopUp + probability: 0.03 + + ### Once radiation is refactored I want it to have a small chance of giving you regular cancer - type: disease diff --git a/Resources/Prototypes/Entities/Objects/Misc/buffering.yml b/Resources/Prototypes/Entities/Objects/Misc/buffering.yml new file mode 100644 index 0000000000..dbd3534459 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Misc/buffering.yml @@ -0,0 +1,8 @@ +- type: entity + id: BufferingIcon + noSpawn: true + components: + - type: Sprite + sprite: Objects/Misc/buffering.rsi + state: icon + drawdepth: Overlays diff --git a/Resources/Prototypes/Polymorphs/polymorph.yml b/Resources/Prototypes/Polymorphs/polymorph.yml index 7cf0eae1de..c7013ea795 100644 --- a/Resources/Prototypes/Polymorphs/polymorph.yml +++ b/Resources/Prototypes/Polymorphs/polymorph.yml @@ -16,4 +16,22 @@ forced: true dropInventory: true revertOnCrit: true - revertOnDeath: true \ No newline at end of file + revertOnDeath: true + +- type: polymorph + id: AdminMonkeySmite + entity: MobMonkey + forced: true + dropInventory: true + +- type: polymorph + id: AdminBreadSmite + entity: FoodBreadPlain + forced: true + dropInventory: true + +- type: polymorph + id: AdminInstrumentSmite + entity: SuperSynthesizerInstrument + forced: true + dropInventory: true diff --git a/Resources/Textures/Interface/Misc/buffering_smite_icon.png b/Resources/Textures/Interface/Misc/buffering_smite_icon.png new file mode 100644 index 0000000000..69796ed026 Binary files /dev/null and b/Resources/Textures/Interface/Misc/buffering_smite_icon.png differ diff --git a/Resources/Textures/Objects/Misc/buffering.rsi/icon.png b/Resources/Textures/Objects/Misc/buffering.rsi/icon.png new file mode 100644 index 0000000000..f30130c50b Binary files /dev/null and b/Resources/Textures/Objects/Misc/buffering.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Misc/buffering.rsi/meta.json b/Resources/Textures/Objects/Misc/buffering.rsi/meta.json new file mode 100644 index 0000000000..6e738a8f04 --- /dev/null +++ b/Resources/Textures/Objects/Misc/buffering.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Created by github user @moonheart08", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Misc/killsign.rsi/icon.png b/Resources/Textures/Objects/Misc/killsign.rsi/icon.png new file mode 100644 index 0000000000..6194592f26 Binary files /dev/null and b/Resources/Textures/Objects/Misc/killsign.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Misc/killsign.rsi/meta.json b/Resources/Textures/Objects/Misc/killsign.rsi/meta.json new file mode 100644 index 0000000000..f756df4139 --- /dev/null +++ b/Resources/Textures/Objects/Misc/killsign.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Created by github user @moonheart08", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "sign", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "icon", + "directions": 1 + } + ] +} diff --git a/Resources/Textures/Objects/Misc/killsign.rsi/sign.png b/Resources/Textures/Objects/Misc/killsign.rsi/sign.png new file mode 100644 index 0000000000..65db271566 Binary files /dev/null and b/Resources/Textures/Objects/Misc/killsign.rsi/sign.png differ