From: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Date: Thu, 25 Sep 2025 21:43:53 +0000 (-0400) Subject: Admin smite: Homing rods. (#40246) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=9fa17c51bd286d812cfbbfe2a0508acb3c0664ac;p=space-station-14.git Admin smite: Homing rods. (#40246) * add homing rod support * oop * speed betterer * commentia --- diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index 79c616322a..30008fcac5 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -1,4 +1,3 @@ -using System.Threading; using Content.Server.Administration.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; @@ -8,6 +7,7 @@ using Content.Server.Explosion.EntitySystems; using Content.Server.GhostKick; using Content.Server.Medical; using Content.Server.Nutrition.EntitySystems; +using Content.Server.Physics.Components; using Content.Server.Pointing.Components; using Content.Server.Polymorph.Systems; using Content.Server.Popups; @@ -22,8 +22,8 @@ using Content.Shared.Administration.Components; using Content.Shared.Atmos.Components; using Content.Shared.Body.Components; using Content.Shared.Body.Part; -using Content.Shared.Clumsy; using Content.Shared.Clothing.Components; +using Content.Shared.Clumsy; using Content.Shared.Cluwne; using Content.Shared.Damage; using Content.Shared.Damage.Systems; @@ -54,7 +54,10 @@ using Robust.Shared.Physics.Systems; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using Robust.Shared.Spawners; using Robust.Shared.Utility; +using System.Numerics; +using System.Threading; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.Administration.Systems; @@ -1006,5 +1009,63 @@ public sealed partial class AdminVerbSystem Message = string.Join(": ", siliconName, Loc.GetString("admin-smite-silicon-laws-bound-description")) }; args.Verbs.Add(silicon); + + var homingRodName = Loc.GetString("admin-smite-homing-rod-name").ToLowerInvariant(); + Verb homingRod = new() + { + Text = homingRodName, + Category = VerbCategory.Smite, + Icon = new SpriteSpecifier.Rsi(new("Objects/Specific/Security/target.rsi"), "target_s"), + Act = () => + { + var speed = 25f; // It don't miss brother. + var distance = 350f; + HomingLaunchSequence(args.Target, "ImmovableRodKeepTiles", distance, speed); // todo: swap the proto for an EntityTable GetSpawns once rod rule rework + }, + Impact = LogImpact.Extreme, + Message = string.Join(": ", homingRodName, Loc.GetString("admin-smite-homing-rod-description")) + }; + args.Verbs.Add(homingRod); + + var homingRodSlowName = Loc.GetString("admin-smite-homing-rod-slow-name").ToLowerInvariant(); + Verb homingRodSlow = new() + { + Text = homingRodSlowName, + Category = VerbCategory.Smite, + Icon = new SpriteSpecifier.Rsi(new("Objects/Specific/Security/target.rsi"), "target_c"), + Act = () => + { + var speed = 5f; // slightly faster than default sprint speed 4.5 + if (TryComp(args.Target, out var movement)) + speed = movement.CurrentSprintSpeed + 0.001f;// run + var distance = 200f; // its kinda slow so were just gonna cheat a bit. + HomingLaunchSequence(args.Target, "ImmovableRodKeepTiles", distance, speed); + }, + Impact = LogImpact.Extreme, + Message = string.Join(": ", homingRodSlowName, Loc.GetString("admin-smite-homing-rod-slow-description")) + }; + args.Verbs.Add(homingRodSlow); + } + + public void HomingLaunchSequence(EntityUid target, EntProtoId proto, float distance, float speed) + { + // ToDo: Reuse some spawning code from whereever the rod rule ends up. + // I would do it now but theres a massive rod rewrite, and I don't wanna poke it for this. + // find reasonable spawn location (use gamerule and find rod?) but respect map not on grid etc etc + + var offset = new Random(target.Id).NextAngle().RotateVec(new Vector2(distance, 0)); + var spawnCoords = _transformSystem.GetMapCoordinates(target).Offset(offset); + var rod = Spawn(proto, spawnCoords); + // Here we abuse the ChasingWalkComp by making it skip targetting logic and dialling its frequency up + EnsureComp(rod, out var chasingComp); + chasingComp.NextChangeVectorTime = TimeSpan.MaxValue; // we just want it to never change + chasingComp.ChasingEntity = target; + chasingComp.ImpulseInterval = .1f; // skrrt skrrrrrrt skrrrt + chasingComp.RotateWithImpulse = true; + chasingComp.MaxSpeed = speed; + chasingComp.Speed = speed; // tell me lies, tell me sweet little lies. + + if (TryComp(rod, out var despawn)) + despawn.Lifetime = offset.Length() / speed * 3; // exists thrice as long as it takes to get to you. } } diff --git a/Content.Server/Physics/Components/ChasingWalkComponent.cs b/Content.Server/Physics/Components/ChasingWalkComponent.cs index 819fd80939..3c66132bd3 100644 --- a/Content.Server/Physics/Components/ChasingWalkComponent.cs +++ b/Content.Server/Physics/Components/ChasingWalkComponent.cs @@ -1,4 +1,5 @@ +using Content.Server.Administration.Systems; using Content.Server.Physics.Controllers; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; @@ -8,7 +9,7 @@ namespace Content.Server.Physics.Components; /// /// A component which makes its entity chasing entity with selected component. /// -[RegisterComponent, Access(typeof(ChasingWalkSystem)), AutoGenerateComponentPause] +[RegisterComponent, Access(typeof(ChasingWalkSystem), typeof(AdminVerbSystem)), AutoGenerateComponentPause] public sealed partial class ChasingWalkComponent : Component { /// @@ -78,4 +79,16 @@ public sealed partial class ChasingWalkComponent : Component /// [DataField, ViewVariables(VVAccess.ReadWrite)] public EntityUid? ChasingEntity; + + /// + /// whether the entity should point in the direction its moving + /// + [DataField] + public bool RotateWithImpulse; + + /// + /// Sprite rotation offset. + /// + [DataField] + public Angle RotationAngleOffset = Angle.Zero; } diff --git a/Content.Server/Physics/Controllers/ChasingWalkSystem.cs b/Content.Server/Physics/Controllers/ChasingWalkSystem.cs index fa55ce024e..ffeb53bea9 100644 --- a/Content.Server/Physics/Controllers/ChasingWalkSystem.cs +++ b/Content.Server/Physics/Controllers/ChasingWalkSystem.cs @@ -101,5 +101,11 @@ public sealed class ChasingWalkSystem : VirtualController _physics.SetLinearVelocity(uid, speed); _physics.SetBodyStatus(uid, physics, BodyStatus.InAir); //If this is not done, from the explosion up close, the tesla will "Fall" to the ground, and almost stop moving. + + if (component.RotateWithImpulse) + { + var ang = speed.ToAngle() + Angle.FromDegrees(90); // we want "Up" to be forward, bullet convention. + _transform.SetWorldRotation(uid, ang + component.RotationAngleOffset); + } } } diff --git a/Resources/Locale/en-US/administration/smites.ftl b/Resources/Locale/en-US/administration/smites.ftl index 794077a484..e8dfbd2055 100644 --- a/Resources/Locale/en-US/administration/smites.ftl +++ b/Resources/Locale/en-US/administration/smites.ftl @@ -60,6 +60,8 @@ admin-smite-nyanify-name = Cat Ears admin-smite-kill-sign-name = Kill Sign admin-smite-omni-accent-name = Omni-Accent admin-smite-crawler-name = Crawler +admin-smite-homing-rod-name = Homing Rod +admin-smite-homing-rod-slow-name = Slowming Rod admin-smite-silicon-laws-bound-name = Become Silicon ## Smite descriptions @@ -107,6 +109,8 @@ admin-smite-terminate-description = Creates a Terminator ghost role with the sol admin-smite-super-slip-description = Slips them really, really hard. admin-smite-omni-accent-description = Makes the target speak with almost every accent available. admin-smite-crawler-description = Makes the target fall down and be unable to stand up. Remove their hands too for added effect! +admin-smite-homing-rod-description = Launches a homing immovable rod straight at them. +admin-smite-homing-rod-slow-description = Launches a slow moving homing immovable rod straight at them. admin-smite-silicon-laws-bound-description = Makes the target bound to silicon laws. Law 2, jump out of the window. ## Tricks descriptions