--- /dev/null
+using Content.Server.Administration.Systems;
+using Content.Shared.Climbing.Components;
+
+namespace Content.Server.Administration.Components;
+
+/// <summary>
+/// Component to track the timer for the SuperBonk smite.
+/// </summary>
+[RegisterComponent, Access(typeof(SuperBonkSystem))]
+public sealed partial class SuperBonkComponent: Component
+{
+ /// <summary>
+ /// Entity being Super Bonked.
+ /// </summary>
+ [DataField]
+ public EntityUid Target;
+
+ /// <summary>
+ /// All of the tables the target will be bonked on.
+ /// </summary>
+ [DataField]
+ public Dictionary<EntityUid, BonkableComponent>.Enumerator Tables;
+
+ /// <summary>
+ /// Value used to reset the timer once it expires.
+ /// </summary>
+ [DataField]
+ public float InitialTime = 0.10f;
+
+ /// <summary>
+ /// Timer till the next bonk.
+ /// </summary>
+ [DataField]
+ public float TimeRemaining = 0.10f;
+
+ /// <summary>
+ /// Whether to remove the clumsy component from the target after SuperBonk is done.
+ /// </summary>
+ [DataField]
+ public bool RemoveClumsy = true;
+
+ /// <summary>
+ /// Whether to stop Super Bonk on the target once he dies. Otherwise it will continue until no other tables are left
+ /// or the target is gibbed.
+ /// </summary>
+ [DataField]
+ public bool StopWhenDead = true;
+}
using Content.Shared.Tabletop.Components;
using Content.Shared.Tools.Systems;
using Content.Shared.Verbs;
-using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
[Dependency] private readonly WeldableSystem _weldableSystem = default!;
[Dependency] private readonly SharedContentEyeSystem _eyeSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
+ [Dependency] private readonly SuperBonkSystem _superBonkSystem = default!;
// All smite verbs have names so invokeverb works.
private void AddSmiteVerbs(GetVerbsEvent<Verb> args)
Message = Loc.GetString("admin-smite-super-speed-description"),
};
args.Verbs.Add(superSpeed);
+ //Bonk
+ Verb superBonkLite = new()
+ {
+ Text = "Super Bonk Lite",
+ Category = VerbCategory.Smite,
+ Icon = new SpriteSpecifier.Rsi(new("Structures/Furniture/Tables/glass.rsi"), "full"),
+ Act = () =>
+ {
+ _superBonkSystem.StartSuperBonk(args.Target, stopWhenDead: true);
+ },
+ Message = Loc.GetString("admin-smite-super-bonk-lite-description"),
+ Impact = LogImpact.Extreme,
+ };
+ args.Verbs.Add(superBonkLite);
+ Verb superBonk= new()
+ {
+ Text = "Super Bonk",
+ Category = VerbCategory.Smite,
+ Icon = new SpriteSpecifier.Rsi(new("Structures/Furniture/Tables/generic.rsi"), "full"),
+ Act = () =>
+ {
+ _superBonkSystem.StartSuperBonk(args.Target);
+ },
+ Message = Loc.GetString("admin-smite-super-bonk-description"),
+ Impact = LogImpact.Extreme,
+ };
+ args.Verbs.Add(superBonk);
}
}
--- /dev/null
+using Content.Server.Administration.Components;
+using Content.Shared.Climbing.Components;
+using Content.Shared.Climbing.Events;
+using Content.Shared.Climbing.Systems;
+using Content.Shared.Interaction.Components;
+using Content.Shared.Mobs;
+using Content.Shared.Mobs.Components;
+
+namespace Content.Server.Administration.Systems;
+
+public sealed class SuperBonkSystem: EntitySystem
+{
+ [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
+ [Dependency] private readonly BonkSystem _bonkSystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<SuperBonkComponent, ComponentShutdown>(OnBonkShutdown);
+ SubscribeLocalEvent<SuperBonkComponent, MobStateChangedEvent>(OnMobStateChanged);
+ }
+
+ public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDead = false )
+ {
+
+ //The other check in the code to stop when the target dies does not work if the target is already dead.
+ if (stopWhenDead && TryComp<MobStateComponent>(target, out var mState))
+ {
+ if (mState.CurrentState == MobState.Dead)
+ return;
+ }
+
+
+ var hadClumsy = EnsureComp<ClumsyComponent>(target, out _);
+
+ var tables = EntityQueryEnumerator<BonkableComponent>();
+ var bonks = new Dictionary<EntityUid, BonkableComponent>();
+ // This is done so we don't crash if something like a new table is spawned.
+ while (tables.MoveNext(out var uid, out var comp))
+ {
+ bonks.Add(uid, comp);
+ }
+
+ var sComp = new SuperBonkComponent
+ {
+ Target = target,
+ Tables = bonks.GetEnumerator(),
+ RemoveClumsy = !hadClumsy,
+ StopWhenDead = stopWhenDead,
+ };
+
+ AddComp(target, sComp);
+ }
+
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+ var comps = EntityQueryEnumerator<SuperBonkComponent>();
+
+ while (comps.MoveNext(out var uid, out var comp))
+ {
+ comp.TimeRemaining -= frameTime;
+ if (!(comp.TimeRemaining <= 0))
+ continue;
+
+ Bonk(comp);
+
+ if (!(comp.Tables.MoveNext()))
+ {
+ RemComp<SuperBonkComponent>(comp.Target);
+ continue;
+ }
+
+ comp.TimeRemaining = comp.InitialTime;
+ }
+ }
+
+ private void Bonk(SuperBonkComponent comp)
+ {
+ var uid = comp.Tables.Current.Key;
+ var bonkComp = comp.Tables.Current.Value;
+
+ // It would be very weird for something without a transform component to have a bonk component
+ // but just in case because I don't want to crash the server.
+ if (!HasComp<TransformComponent>(uid))
+ return;
+
+ _transformSystem.SetCoordinates(comp.Target, Transform(uid).Coordinates);
+
+ _bonkSystem.TryBonk(comp.Target, uid, bonkComp);
+ }
+
+ private void OnMobStateChanged(EntityUid uid, SuperBonkComponent comp, MobStateChangedEvent args)
+ {
+ if (comp.StopWhenDead && args.NewMobState == MobState.Dead)
+ {
+ RemComp<SuperBonkComponent>(uid);
+ }
+ }
+
+ private void OnBonkShutdown(EntityUid uid, SuperBonkComponent comp, ComponentShutdown ev)
+ {
+ if (comp.RemoveClumsy)
+ RemComp<ClumsyComponent>(comp.Target);
+ }
+}
changes:
- {message: 'The respawn verb now respawns the targeted player instead of the admin', type: Fix}
time: '2023-11-22T16:39:00.0000000+00:00'
+- author: nikthechampiongr
+ changes:
+ - {message: 'The Super Bonk smite is now available. Targets will bonk their head on every single table.', type: Add}
+ time: '2023-12-12T11:54:00.0000000+00:00'
admin-smite-remove-hand-description = Removes only one of their hands instead of all of them.
admin-smite-disarm-prone-description = Makes them get disarmed 100% of the time and cuffed instantly.
admin-smite-garbage-can-description = Turn them into a garbage bin to emphasize what they remind you of.
-
+admin-smite-super-bonk-description = Slams them on every single table on the Station and beyond.
+admin-smite-super-bonk-lite-description= Slams them on every single table on the Station and beyond. Stops when the target is dead.
## Tricks descriptions