-using System.Threading;
using Content.Server.Administration.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
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;
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;
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;
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<MovementSpeedModifierComponent>(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<ChasingWalkComponent>(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<TimedDespawnComponent>(rod, out var despawn))
+ despawn.Lifetime = offset.Length() / speed * 3; // exists thrice as long as it takes to get to you.
}
}
+using Content.Server.Administration.Systems;
using Content.Server.Physics.Controllers;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
/// <summary>
/// A component which makes its entity chasing entity with selected component.
/// </summary>
-[RegisterComponent, Access(typeof(ChasingWalkSystem)), AutoGenerateComponentPause]
+[RegisterComponent, Access(typeof(ChasingWalkSystem), typeof(AdminVerbSystem)), AutoGenerateComponentPause]
public sealed partial class ChasingWalkComponent : Component
{
/// <summary>
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public EntityUid? ChasingEntity;
+
+ /// <summary>
+ /// whether the entity should point in the direction its moving
+ /// </summary>
+ [DataField]
+ public bool RotateWithImpulse;
+
+ /// <summary>
+ /// Sprite rotation offset.
+ /// </summary>
+ [DataField]
+ public Angle RotationAngleOffset = Angle.Zero;
}