Merge remote-tracking branch 'upstream/stable' into ed-30-04-2025-upstream-sync
# Conflicts: # Content.Client/Parallax/ParallaxControl.cs # Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs # Content.IntegrationTests/Tests/PostMapInitTest.cs # Content.Server/Chat/Managers/ChatManager.cs # Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs # Content.Server/Labels/Label/LabelSystem.cs # Content.Shared/Actions/SharedActionsSystem.cs # Content.Shared/Fluids/Components/EvaporationComponent.cs # Content.Shared/Labels/EntitySystems/SharedLabelSystem.cs # README.md # Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml # Resources/Prototypes/Maps/Pools/deathmatch.yml # Resources/Prototypes/Maps/arenas.yml
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Ghost;
|
||||
using Content.Server.Mind;
|
||||
@@ -8,6 +8,7 @@ using Content.Shared.Mind;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Administration.Commands;
|
||||
|
||||
@@ -15,7 +16,7 @@ namespace Content.Server.Administration.Commands;
|
||||
public sealed class AGhostCommand : LocalizedCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly ISharedPlayerManager _playerManager = default!;
|
||||
|
||||
public override string Command => "aghost";
|
||||
public override string Help => "aghost";
|
||||
@@ -104,8 +105,8 @@ public sealed class AGhostCommand : LocalizedCommands
|
||||
// TODO: Remove duplication between all this and "GamePreset.OnGhostAttempt()"...
|
||||
if (!string.IsNullOrWhiteSpace(mind.CharacterName))
|
||||
metaDataSystem.SetEntityName(ghost, mind.CharacterName);
|
||||
else if (!string.IsNullOrWhiteSpace(mind.Session?.Name))
|
||||
metaDataSystem.SetEntityName(ghost, mind.Session.Name);
|
||||
else if (!string.IsNullOrWhiteSpace(player.Name))
|
||||
metaDataSystem.SetEntityName(ghost, player.Name);
|
||||
|
||||
mindSystem.Visit(mindId, ghost, mind);
|
||||
}
|
||||
@@ -116,6 +117,6 @@ public sealed class AGhostCommand : LocalizedCommands
|
||||
}
|
||||
|
||||
var comp = _entities.GetComponent<GhostComponent>(ghost);
|
||||
ghostSystem.SetCanReturnToBody(comp, canReturn);
|
||||
ghostSystem.SetCanReturnToBody((ghost, comp), canReturn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace Content.Server.Administration.Commands;
|
||||
[AdminCommand(AdminFlags.Admin)]
|
||||
public sealed class ForceGhostCommand : LocalizedEntityCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Server.Warps;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Follower;
|
||||
using Content.Shared.Ghost;
|
||||
using Content.Shared.Warps;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
@@ -1,37 +1,31 @@
|
||||
using Content.Server.Administration.Systems;
|
||||
using Content.Shared.Climbing.Components;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
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
|
||||
[RegisterComponent, AutoGenerateComponentPause, 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;
|
||||
public List<EntityUid>.Enumerator Tables;
|
||||
|
||||
/// <summary>
|
||||
/// Value used to reset the timer once it expires.
|
||||
/// How often should we bonk.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float InitialTime = 0.10f;
|
||||
public TimeSpan BonkCooldown = TimeSpan.FromMilliseconds(100);
|
||||
|
||||
/// <summary>
|
||||
/// Timer till the next bonk.
|
||||
/// Next time when we will bonk.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float TimeRemaining = 0.10f;
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
|
||||
public TimeSpan NextBonk = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to remove the clumsy component from the target after SuperBonk is done.
|
||||
|
||||
@@ -330,7 +330,12 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
|
||||
var cachedInfo = adminSys.GetCachedPlayerInfo(new NetUserId(id));
|
||||
if (cachedInfo != null && cachedInfo.Antag)
|
||||
{
|
||||
logMessage += " [ANTAG: " + cachedInfo.CharacterName + "]";
|
||||
var subtype = Loc.GetString(cachedInfo.Subtype ?? cachedInfo.RoleProto.Name);
|
||||
logMessage = Loc.GetString(
|
||||
"admin-alert-antag-label",
|
||||
("message", logMessage),
|
||||
("name", cachedInfo.CharacterName),
|
||||
("subtype", subtype));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json;
|
||||
using Content.Shared.Station.Components;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
@@ -72,6 +72,6 @@ public readonly struct SerializableEntityCoordinates
|
||||
EntityUid = coordinates.EntityId;
|
||||
X = coordinates.X;
|
||||
Y = coordinates.Y;
|
||||
MapUid = coordinates.GetMapUid(entityManager);
|
||||
MapUid = entityManager.System<SharedTransformSystem>().GetMap(coordinates);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,8 @@ using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.Players;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Info;
|
||||
using Content.Shared.Players;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Player;
|
||||
@@ -108,7 +106,7 @@ namespace Content.Server.Administration.Managers
|
||||
// The DB function handles this scenario fine, but it's worth noting.
|
||||
await _dbManager.UpdateAdminDeadminnedAsync(player.UserId, newState);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
_sawmill.Error("Failed to save deadmin state to database for {Admin}", player.UserId);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Server.EUI;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Eui;
|
||||
using Content.Shared.Follower;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
@@ -33,11 +34,13 @@ public sealed class PlayerPanelEui : BaseEui
|
||||
private bool _frozen;
|
||||
private bool _canFreeze;
|
||||
private bool _canAhelp;
|
||||
private FollowerSystem _follower;
|
||||
|
||||
public PlayerPanelEui(LocatedPlayerData player)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_targetPlayer = player;
|
||||
_follower = _entity.System<FollowerSystem>();
|
||||
}
|
||||
|
||||
public override void Opened()
|
||||
@@ -141,6 +144,16 @@ public sealed class PlayerPanelEui : BaseEui
|
||||
_entity.DeleteEntity(session.AttachedEntity);
|
||||
}
|
||||
break;
|
||||
case PlayerPanelFollowMessage:
|
||||
if (!_admins.HasAdminFlag(Player, AdminFlags.Admin) ||
|
||||
!_player.TryGetSessionById(_targetPlayer.UserId, out session) ||
|
||||
session.AttachedEntity == null ||
|
||||
Player.AttachedEntity is null ||
|
||||
session.AttachedEntity == Player.AttachedEntity)
|
||||
return;
|
||||
|
||||
_follower.StartFollowingEntity(Player.AttachedEntity.Value, session.AttachedEntity.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,9 +153,7 @@ public sealed class AdminSystem : EntitySystem
|
||||
|
||||
private void OnRoleEvent(RoleEvent ev)
|
||||
{
|
||||
var session = _minds.GetSession(ev.Mind);
|
||||
|
||||
if (!ev.RoleTypeUpdate || session == null)
|
||||
if (!ev.RoleTypeUpdate || !_playerManager.TryGetSessionById(ev.Mind.UserId, out var session))
|
||||
return;
|
||||
|
||||
UpdatePlayerList(session);
|
||||
@@ -235,12 +233,16 @@ public sealed class AdminSystem : EntitySystem
|
||||
// Starting role, antagonist status and role type
|
||||
RoleTypePrototype roleType = new();
|
||||
var startingRole = string.Empty;
|
||||
LocId? subtype = null;
|
||||
if (_minds.TryGetMind(session, out var mindId, out var mindComp) && mindComp is not null)
|
||||
{
|
||||
sortWeight = _role.GetRoleCompByTime(mindComp)?.Comp.SortWeight ?? 0;
|
||||
|
||||
if (_proto.TryIndex(mindComp.RoleType, out var role))
|
||||
{
|
||||
roleType = role;
|
||||
subtype = mindComp.Subtype;
|
||||
}
|
||||
else
|
||||
Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(roleType.Name)}' instead");
|
||||
|
||||
@@ -269,6 +271,7 @@ public sealed class AdminSystem : EntitySystem
|
||||
startingRole,
|
||||
antag,
|
||||
roleType,
|
||||
subtype,
|
||||
sortWeight,
|
||||
GetNetEntity(session?.AttachedEntity),
|
||||
data.UserId,
|
||||
|
||||
@@ -421,7 +421,7 @@ public sealed partial class AdminVerbSystem
|
||||
{
|
||||
var xform = Transform(args.Target);
|
||||
var fixtures = Comp<FixturesComponent>(args.Target);
|
||||
_transformSystem.Unanchor(args.Target); // Just in case.
|
||||
_transformSystem.Unanchor(args.Target, xform); // Just in case.
|
||||
_physics.SetBodyType(args.Target, BodyType.Dynamic, manager: fixtures, body: physics);
|
||||
_physics.SetBodyStatus(args.Target, physics, BodyStatus.InAir);
|
||||
_physics.WakeBody(args.Target, manager: fixtures, body: physics);
|
||||
@@ -877,9 +877,9 @@ public sealed partial class AdminVerbSystem
|
||||
var hadSlipComponent = EnsureComp(args.Target, out SlipperyComponent slipComponent);
|
||||
if (!hadSlipComponent)
|
||||
{
|
||||
slipComponent.SuperSlippery = true;
|
||||
slipComponent.ParalyzeTime = 5;
|
||||
slipComponent.LaunchForwardsMultiplier = 20;
|
||||
slipComponent.SlipData.SuperSlippery = true;
|
||||
slipComponent.SlipData.ParalyzeTime = TimeSpan.FromSeconds(5);
|
||||
slipComponent.SlipData.LaunchForwardsMultiplier = 20;
|
||||
}
|
||||
|
||||
_slipperySystem.TrySlip(args.Target, slipComponent, args.Target, requiresContact: false);
|
||||
|
||||
@@ -65,343 +65,340 @@ public sealed partial class AdminVerbSystem
|
||||
if (!_adminManager.HasAdminFlag(player, AdminFlags.Admin))
|
||||
return;
|
||||
|
||||
if (_adminManager.HasAdminFlag(player, AdminFlags.Admin))
|
||||
if (TryComp<DoorBoltComponent>(args.Target, out var bolts))
|
||||
{
|
||||
if (TryComp<DoorBoltComponent>(args.Target, out var bolts))
|
||||
Verb bolt = new()
|
||||
{
|
||||
Verb bolt = new()
|
||||
{
|
||||
Text = bolts.BoltsDown ? "Unbolt" : "Bolt",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = bolts.BoltsDown
|
||||
? new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/unbolt.png"))
|
||||
: new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/bolt.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_door.SetBoltsDown((args.Target, bolts), !bolts.BoltsDown);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString(bolts.BoltsDown
|
||||
? "admin-trick-unbolt-description"
|
||||
: "admin-trick-bolt-description"),
|
||||
Priority = (int) (bolts.BoltsDown ? TricksVerbPriorities.Unbolt : TricksVerbPriorities.Bolt),
|
||||
};
|
||||
args.Verbs.Add(bolt);
|
||||
}
|
||||
|
||||
if (TryComp<AirlockComponent>(args.Target, out var airlockComp))
|
||||
{
|
||||
Verb emergencyAccess = new()
|
||||
{
|
||||
Text = airlockComp.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/emergency_access.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_airlockSystem.SetEmergencyAccess((args.Target, airlockComp), !airlockComp.EmergencyAccess);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString(airlockComp.EmergencyAccess
|
||||
? "admin-trick-emergency-access-off-description"
|
||||
: "admin-trick-emergency-access-on-description"),
|
||||
Priority = (int) (airlockComp.EmergencyAccess ? TricksVerbPriorities.EmergencyAccessOff : TricksVerbPriorities.EmergencyAccessOn),
|
||||
};
|
||||
args.Verbs.Add(emergencyAccess);
|
||||
}
|
||||
|
||||
if (HasComp<DamageableComponent>(args.Target))
|
||||
{
|
||||
Verb rejuvenate = new()
|
||||
{
|
||||
Text = "Rejuvenate",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rejuvenate.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_rejuvenate.PerformRejuvenate(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-rejuvenate-description"),
|
||||
Priority = (int) TricksVerbPriorities.Rejuvenate,
|
||||
};
|
||||
args.Verbs.Add(rejuvenate);
|
||||
}
|
||||
|
||||
if (!HasComp<GodmodeComponent>(args.Target))
|
||||
{
|
||||
Verb makeIndestructible = new()
|
||||
{
|
||||
Text = "Make Indestructible",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_sharedGodmodeSystem.EnableGodmode(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-make-indestructible-description"),
|
||||
Priority = (int) TricksVerbPriorities.MakeIndestructible,
|
||||
};
|
||||
args.Verbs.Add(makeIndestructible);
|
||||
}
|
||||
else
|
||||
{
|
||||
Verb makeVulnerable = new()
|
||||
{
|
||||
Text = "Make Vulnerable",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_sharedGodmodeSystem.DisableGodmode(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-make-vulnerable-description"),
|
||||
Priority = (int) TricksVerbPriorities.MakeVulnerable,
|
||||
};
|
||||
args.Verbs.Add(makeVulnerable);
|
||||
}
|
||||
|
||||
if (TryComp<BatteryComponent>(args.Target, out var battery))
|
||||
{
|
||||
Verb refillBattery = new()
|
||||
{
|
||||
Text = "Refill Battery",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill_battery.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_batterySystem.SetCharge(args.Target, battery.MaxCharge, battery);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-refill-battery-description"),
|
||||
Priority = (int) TricksVerbPriorities.RefillBattery,
|
||||
};
|
||||
args.Verbs.Add(refillBattery);
|
||||
|
||||
Verb drainBattery = new()
|
||||
{
|
||||
Text = "Drain Battery",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/drain_battery.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_batterySystem.SetCharge(args.Target, 0, battery);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-drain-battery-description"),
|
||||
Priority = (int) TricksVerbPriorities.DrainBattery,
|
||||
};
|
||||
args.Verbs.Add(drainBattery);
|
||||
|
||||
Verb infiniteBattery = new()
|
||||
{
|
||||
Text = "Infinite Battery",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/infinite_battery.png")),
|
||||
Act = () =>
|
||||
{
|
||||
var recharger = EnsureComp<BatterySelfRechargerComponent>(args.Target);
|
||||
recharger.AutoRecharge = true;
|
||||
recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
|
||||
recharger.AutoRechargePause = false; // No delay.
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-infinite-battery-object-description"),
|
||||
Priority = (int) TricksVerbPriorities.InfiniteBattery,
|
||||
};
|
||||
args.Verbs.Add(infiniteBattery);
|
||||
}
|
||||
|
||||
if (TryComp<AnchorableComponent>(args.Target, out var anchor))
|
||||
{
|
||||
Verb blockUnanchor = new()
|
||||
{
|
||||
Text = "Block Unanchoring",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/anchor.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
RemComp(args.Target, anchor);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-block-unanchoring-description"),
|
||||
Priority = (int) TricksVerbPriorities.BlockUnanchoring,
|
||||
};
|
||||
args.Verbs.Add(blockUnanchor);
|
||||
}
|
||||
|
||||
if (TryComp<GasTankComponent>(args.Target, out var tank))
|
||||
{
|
||||
Verb refillInternalsO2 = new()
|
||||
{
|
||||
Text = "Refill Internals Oxygen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
RefillGasTank(args.Target, Gas.Oxygen, tank);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
|
||||
Priority = (int) TricksVerbPriorities.RefillOxygen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsO2);
|
||||
|
||||
Verb refillInternalsN2 = new()
|
||||
{
|
||||
Text = "Refill Internals Nitrogen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
RefillGasTank(args.Target, Gas.Nitrogen, tank);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
|
||||
Priority = (int) TricksVerbPriorities.RefillNitrogen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsN2);
|
||||
|
||||
Verb refillInternalsPlasma = new()
|
||||
{
|
||||
Text = "Refill Internals Plasma",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
RefillGasTank(args.Target, Gas.Plasma, tank);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
|
||||
Priority = (int) TricksVerbPriorities.RefillPlasma,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsPlasma);
|
||||
}
|
||||
|
||||
if (HasComp<InventoryComponent>(args.Target))
|
||||
{
|
||||
Verb refillInternalsO2 = new()
|
||||
{
|
||||
Text = "Refill Internals Oxygen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
|
||||
Act = () => RefillEquippedTanks(args.User, Gas.Oxygen),
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
|
||||
Priority = (int) TricksVerbPriorities.RefillOxygen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsO2);
|
||||
|
||||
Verb refillInternalsN2 = new()
|
||||
{
|
||||
Text = "Refill Internals Nitrogen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
|
||||
Act = () =>RefillEquippedTanks(args.User, Gas.Nitrogen),
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
|
||||
Priority = (int) TricksVerbPriorities.RefillNitrogen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsN2);
|
||||
|
||||
Verb refillInternalsPlasma = new()
|
||||
{
|
||||
Text = "Refill Internals Plasma",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
|
||||
Act = () => RefillEquippedTanks(args.User, Gas.Plasma),
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
|
||||
Priority = (int) TricksVerbPriorities.RefillPlasma,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsPlasma);
|
||||
}
|
||||
|
||||
Verb sendToTestArena = new()
|
||||
{
|
||||
Text = "Send to test arena",
|
||||
Text = bolts.BoltsDown ? "Unbolt" : "Bolt",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")),
|
||||
|
||||
Icon = bolts.BoltsDown
|
||||
? new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/unbolt.png"))
|
||||
: new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/bolt.png")),
|
||||
Act = () =>
|
||||
{
|
||||
var (mapUid, gridUid) = _adminTestArenaSystem.AssertArenaLoaded(player);
|
||||
_transformSystem.SetCoordinates(args.Target, new EntityCoordinates(gridUid ?? mapUid, Vector2.One));
|
||||
_door.SetBoltsDown((args.Target, bolts), !bolts.BoltsDown);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-send-to-test-arena-description"),
|
||||
Priority = (int) TricksVerbPriorities.SendToTestArena,
|
||||
Message = Loc.GetString(bolts.BoltsDown
|
||||
? "admin-trick-unbolt-description"
|
||||
: "admin-trick-bolt-description"),
|
||||
Priority = (int)(bolts.BoltsDown ? TricksVerbPriorities.Unbolt : TricksVerbPriorities.Bolt),
|
||||
};
|
||||
args.Verbs.Add(sendToTestArena);
|
||||
args.Verbs.Add(bolt);
|
||||
}
|
||||
|
||||
var activeId = FindActiveId(args.Target);
|
||||
|
||||
if (activeId is not null)
|
||||
if (TryComp<AirlockComponent>(args.Target, out var airlockComp))
|
||||
{
|
||||
Verb emergencyAccess = new()
|
||||
{
|
||||
Verb grantAllAccess = new()
|
||||
Text = airlockComp.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/emergency_access.png")),
|
||||
Act = () =>
|
||||
{
|
||||
Text = "Grant All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"),
|
||||
Act = () =>
|
||||
{
|
||||
GiveAllAccess(activeId.Value);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-grant-all-access-description"),
|
||||
Priority = (int) TricksVerbPriorities.GrantAllAccess,
|
||||
};
|
||||
args.Verbs.Add(grantAllAccess);
|
||||
_airlockSystem.SetEmergencyAccess((args.Target, airlockComp), !airlockComp.EmergencyAccess);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString(airlockComp.EmergencyAccess
|
||||
? "admin-trick-emergency-access-off-description"
|
||||
: "admin-trick-emergency-access-on-description"),
|
||||
Priority = (int)(airlockComp.EmergencyAccess ? TricksVerbPriorities.EmergencyAccessOff : TricksVerbPriorities.EmergencyAccessOn),
|
||||
};
|
||||
args.Verbs.Add(emergencyAccess);
|
||||
}
|
||||
|
||||
Verb revokeAllAccess = new()
|
||||
{
|
||||
Text = "Revoke All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"),
|
||||
Act = () =>
|
||||
{
|
||||
RevokeAllAccess(activeId.Value);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-revoke-all-access-description"),
|
||||
Priority = (int) TricksVerbPriorities.RevokeAllAccess,
|
||||
};
|
||||
args.Verbs.Add(revokeAllAccess);
|
||||
}
|
||||
|
||||
if (HasComp<AccessComponent>(args.Target))
|
||||
if (HasComp<DamageableComponent>(args.Target))
|
||||
{
|
||||
Verb rejuvenate = new()
|
||||
{
|
||||
Verb grantAllAccess = new()
|
||||
Text = "Rejuvenate",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rejuvenate.png")),
|
||||
Act = () =>
|
||||
{
|
||||
Text = "Grant All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"),
|
||||
Act = () =>
|
||||
{
|
||||
GiveAllAccess(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-grant-all-access-description"),
|
||||
Priority = (int) TricksVerbPriorities.GrantAllAccess,
|
||||
};
|
||||
args.Verbs.Add(grantAllAccess);
|
||||
_rejuvenate.PerformRejuvenate(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-rejuvenate-description"),
|
||||
Priority = (int)TricksVerbPriorities.Rejuvenate,
|
||||
};
|
||||
args.Verbs.Add(rejuvenate);
|
||||
}
|
||||
|
||||
Verb revokeAllAccess = new()
|
||||
if (!HasComp<GodmodeComponent>(args.Target))
|
||||
{
|
||||
Verb makeIndestructible = new()
|
||||
{
|
||||
Text = "Make Indestructible",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
Text = "Revoke All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"),
|
||||
Act = () =>
|
||||
{
|
||||
RevokeAllAccess(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-revoke-all-access-description"),
|
||||
Priority = (int) TricksVerbPriorities.RevokeAllAccess,
|
||||
};
|
||||
args.Verbs.Add(revokeAllAccess);
|
||||
}
|
||||
_sharedGodmodeSystem.EnableGodmode(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-make-indestructible-description"),
|
||||
Priority = (int)TricksVerbPriorities.MakeIndestructible,
|
||||
};
|
||||
args.Verbs.Add(makeIndestructible);
|
||||
}
|
||||
else
|
||||
{
|
||||
Verb makeVulnerable = new()
|
||||
{
|
||||
Text = "Make Vulnerable",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_sharedGodmodeSystem.DisableGodmode(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-make-vulnerable-description"),
|
||||
Priority = (int)TricksVerbPriorities.MakeVulnerable,
|
||||
};
|
||||
args.Verbs.Add(makeVulnerable);
|
||||
}
|
||||
|
||||
if (TryComp<BatteryComponent>(args.Target, out var battery))
|
||||
{
|
||||
Verb refillBattery = new()
|
||||
{
|
||||
Text = "Refill Battery",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill_battery.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_batterySystem.SetCharge(args.Target, battery.MaxCharge, battery);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-refill-battery-description"),
|
||||
Priority = (int)TricksVerbPriorities.RefillBattery,
|
||||
};
|
||||
args.Verbs.Add(refillBattery);
|
||||
|
||||
Verb drainBattery = new()
|
||||
{
|
||||
Text = "Drain Battery",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/drain_battery.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_batterySystem.SetCharge(args.Target, 0, battery);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-drain-battery-description"),
|
||||
Priority = (int)TricksVerbPriorities.DrainBattery,
|
||||
};
|
||||
args.Verbs.Add(drainBattery);
|
||||
|
||||
Verb infiniteBattery = new()
|
||||
{
|
||||
Text = "Infinite Battery",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/infinite_battery.png")),
|
||||
Act = () =>
|
||||
{
|
||||
var recharger = EnsureComp<BatterySelfRechargerComponent>(args.Target);
|
||||
recharger.AutoRecharge = true;
|
||||
recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
|
||||
recharger.AutoRechargePause = false; // No delay.
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-infinite-battery-object-description"),
|
||||
Priority = (int)TricksVerbPriorities.InfiniteBattery,
|
||||
};
|
||||
args.Verbs.Add(infiniteBattery);
|
||||
}
|
||||
|
||||
if (TryComp<AnchorableComponent>(args.Target, out var anchor))
|
||||
{
|
||||
Verb blockUnanchor = new()
|
||||
{
|
||||
Text = "Block Unanchoring",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/anchor.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
RemComp(args.Target, anchor);
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-block-unanchoring-description"),
|
||||
Priority = (int)TricksVerbPriorities.BlockUnanchoring,
|
||||
};
|
||||
args.Verbs.Add(blockUnanchor);
|
||||
}
|
||||
|
||||
if (TryComp<GasTankComponent>(args.Target, out var tank))
|
||||
{
|
||||
Verb refillInternalsO2 = new()
|
||||
{
|
||||
Text = "Refill Internals Oxygen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
RefillGasTank(args.Target, Gas.Oxygen, tank);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
|
||||
Priority = (int)TricksVerbPriorities.RefillOxygen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsO2);
|
||||
|
||||
Verb refillInternalsN2 = new()
|
||||
{
|
||||
Text = "Refill Internals Nitrogen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
RefillGasTank(args.Target, Gas.Nitrogen, tank);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
|
||||
Priority = (int)TricksVerbPriorities.RefillNitrogen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsN2);
|
||||
|
||||
Verb refillInternalsPlasma = new()
|
||||
{
|
||||
Text = "Refill Internals Plasma",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
RefillGasTank(args.Target, Gas.Plasma, tank);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
|
||||
Priority = (int)TricksVerbPriorities.RefillPlasma,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsPlasma);
|
||||
}
|
||||
|
||||
if (HasComp<InventoryComponent>(args.Target))
|
||||
{
|
||||
Verb refillInternalsO2 = new()
|
||||
{
|
||||
Text = "Refill Internals Oxygen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
|
||||
Act = () => RefillEquippedTanks(args.User, Gas.Oxygen),
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
|
||||
Priority = (int)TricksVerbPriorities.RefillOxygen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsO2);
|
||||
|
||||
Verb refillInternalsN2 = new()
|
||||
{
|
||||
Text = "Refill Internals Nitrogen",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
|
||||
Act = () => RefillEquippedTanks(args.User, Gas.Nitrogen),
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
|
||||
Priority = (int)TricksVerbPriorities.RefillNitrogen,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsN2);
|
||||
|
||||
Verb refillInternalsPlasma = new()
|
||||
{
|
||||
Text = "Refill Internals Plasma",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
|
||||
Act = () => RefillEquippedTanks(args.User, Gas.Plasma),
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
|
||||
Priority = (int)TricksVerbPriorities.RefillPlasma,
|
||||
};
|
||||
args.Verbs.Add(refillInternalsPlasma);
|
||||
}
|
||||
|
||||
Verb sendToTestArena = new()
|
||||
{
|
||||
Text = "Send to test arena",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")),
|
||||
|
||||
Act = () =>
|
||||
{
|
||||
var (mapUid, gridUid) = _adminTestArenaSystem.AssertArenaLoaded(player);
|
||||
_transformSystem.SetCoordinates(args.Target, new EntityCoordinates(gridUid ?? mapUid, Vector2.One));
|
||||
},
|
||||
Impact = LogImpact.Medium,
|
||||
Message = Loc.GetString("admin-trick-send-to-test-arena-description"),
|
||||
Priority = (int)TricksVerbPriorities.SendToTestArena,
|
||||
};
|
||||
args.Verbs.Add(sendToTestArena);
|
||||
|
||||
var activeId = FindActiveId(args.Target);
|
||||
|
||||
if (activeId is not null)
|
||||
{
|
||||
Verb grantAllAccess = new()
|
||||
{
|
||||
Text = "Grant All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"),
|
||||
Act = () =>
|
||||
{
|
||||
GiveAllAccess(activeId.Value);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-grant-all-access-description"),
|
||||
Priority = (int)TricksVerbPriorities.GrantAllAccess,
|
||||
};
|
||||
args.Verbs.Add(grantAllAccess);
|
||||
|
||||
Verb revokeAllAccess = new()
|
||||
{
|
||||
Text = "Revoke All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"),
|
||||
Act = () =>
|
||||
{
|
||||
RevokeAllAccess(activeId.Value);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-revoke-all-access-description"),
|
||||
Priority = (int)TricksVerbPriorities.RevokeAllAccess,
|
||||
};
|
||||
args.Verbs.Add(revokeAllAccess);
|
||||
}
|
||||
|
||||
if (HasComp<AccessComponent>(args.Target))
|
||||
{
|
||||
Verb grantAllAccess = new()
|
||||
{
|
||||
Text = "Grant All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"),
|
||||
Act = () =>
|
||||
{
|
||||
GiveAllAccess(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-grant-all-access-description"),
|
||||
Priority = (int)TricksVerbPriorities.GrantAllAccess,
|
||||
};
|
||||
args.Verbs.Add(grantAllAccess);
|
||||
|
||||
Verb revokeAllAccess = new()
|
||||
{
|
||||
Text = "Revoke All Access",
|
||||
Category = VerbCategory.Tricks,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"),
|
||||
Act = () =>
|
||||
{
|
||||
RevokeAllAccess(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-trick-revoke-all-access-description"),
|
||||
Priority = (int)TricksVerbPriorities.RevokeAllAccess,
|
||||
};
|
||||
args.Verbs.Add(revokeAllAccess);
|
||||
}
|
||||
|
||||
if (TryComp<StackComponent>(args.Target, out var stack))
|
||||
|
||||
@@ -2,16 +2,12 @@ using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Administration.UI;
|
||||
using Content.Server.Disposal.Tube;
|
||||
using Content.Server.Disposal.Tube.Components;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Ghost.Roles;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Mind.Commands;
|
||||
using Content.Server.Prayer;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
@@ -26,7 +22,6 @@ using Content.Shared.Verbs;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -58,9 +53,7 @@ namespace Content.Server.Administration.Systems
|
||||
[Dependency] private readonly AdminSystem _adminSystem = default!;
|
||||
[Dependency] private readonly DisposalTubeSystem _disposalTubes = default!;
|
||||
[Dependency] private readonly EuiManager _euiManager = default!;
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly GhostRoleSystem _ghostRoleSystem = default!;
|
||||
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly PrayerSystem _prayerSystem = default!;
|
||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||
@@ -151,7 +144,7 @@ namespace Content.Server.Administration.Systems
|
||||
|
||||
var stationUid = _stations.GetOwningStation(args.Target);
|
||||
|
||||
var profile = _ticker.GetPlayerProfile(targetActor.PlayerSession);
|
||||
var profile = _gameTicker.GetPlayerProfile(targetActor.PlayerSession);
|
||||
var mobUid = _spawning.SpawnPlayerMob(coords.Value, null, profile, stationUid);
|
||||
|
||||
if (_mindSystem.TryGetMind(args.Target, out var mindId, out var mindComp))
|
||||
@@ -177,7 +170,7 @@ namespace Content.Server.Administration.Systems
|
||||
|
||||
var stationUid = _stations.GetOwningStation(args.Target);
|
||||
|
||||
var profile = _ticker.GetPlayerProfile(targetActor.PlayerSession);
|
||||
var profile = _gameTicker.GetPlayerProfile(targetActor.PlayerSession);
|
||||
_spawning.SpawnPlayerMob(coords.Value, null, profile, stationUid);
|
||||
},
|
||||
ConfirmationPopup = true,
|
||||
@@ -194,7 +187,7 @@ namespace Content.Server.Administration.Systems
|
||||
});
|
||||
}
|
||||
|
||||
if (_mindSystem.TryGetMind(args.Target, out _, out var mind) && mind.UserId != null)
|
||||
if (_mindSystem.TryGetMind(args.Target, out var mindId, out var mindComp) && mindComp.UserId != null)
|
||||
{
|
||||
// Erase
|
||||
args.Verbs.Add(new Verb
|
||||
@@ -206,7 +199,7 @@ namespace Content.Server.Administration.Systems
|
||||
new("/Textures/Interface/VerbIcons/delete_transparent.svg.192dpi.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_adminSystem.Erase(mind.UserId.Value);
|
||||
_adminSystem.Erase(mindComp.UserId.Value);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
ConfirmationPopup = true
|
||||
@@ -219,11 +212,20 @@ namespace Content.Server.Administration.Systems
|
||||
Category = VerbCategory.Admin,
|
||||
Act = () =>
|
||||
{
|
||||
_console.ExecuteCommand(player, $"respawn \"{mind.UserId}\"");
|
||||
_console.ExecuteCommand(player, $"respawn \"{mindComp.UserId}\"");
|
||||
},
|
||||
ConfirmationPopup = true,
|
||||
// No logimpact as the command does it internally.
|
||||
});
|
||||
|
||||
// Inspect mind
|
||||
args.Verbs.Add(new Verb
|
||||
{
|
||||
Text = Loc.GetString("inspect-mind-verb-get-data-text"),
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/sentient.svg.192dpi.png")),
|
||||
Category = VerbCategory.Debug,
|
||||
Act = () => _console.RemoteExecuteCommand(player, $"vv {GetNetEntity(mindId)}"),
|
||||
});
|
||||
}
|
||||
|
||||
// Freeze
|
||||
@@ -445,29 +447,6 @@ namespace Content.Server.Administration.Systems
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
// XenoArcheology
|
||||
if (_adminManager.IsAdmin(player) && TryComp<ArtifactComponent>(args.Target, out var artifact))
|
||||
{
|
||||
// make artifact always active (by adding timer trigger)
|
||||
args.Verbs.Add(new Verb()
|
||||
{
|
||||
Text = Loc.GetString("artifact-verb-make-always-active"),
|
||||
Category = VerbCategory.Debug,
|
||||
Act = () => EntityManager.AddComponent<ArtifactTimerTriggerComponent>(args.Target),
|
||||
Disabled = EntityManager.HasComponent<ArtifactTimerTriggerComponent>(args.Target),
|
||||
Impact = LogImpact.High
|
||||
});
|
||||
|
||||
// force to activate artifact ignoring timeout
|
||||
args.Verbs.Add(new Verb()
|
||||
{
|
||||
Text = Loc.GetString("artifact-verb-activate"),
|
||||
Category = VerbCategory.Debug,
|
||||
Act = () => _artifactSystem.ForceActivateArtifact(args.Target, component: artifact),
|
||||
Impact = LogImpact.High
|
||||
});
|
||||
}
|
||||
|
||||
// Make Sentient verb
|
||||
if (_groupController.CanCommand(player, "makesentient") &&
|
||||
args.User != args.Target &&
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Shared.Clumsy;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Administration.Systems;
|
||||
|
||||
@@ -12,44 +13,38 @@ public sealed class SuperBonkSystem : EntitySystem
|
||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||
[Dependency] private readonly ClumsySystem _clumsySystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SuperBonkComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<SuperBonkComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
SubscribeLocalEvent<SuperBonkComponent, ComponentShutdown>(OnBonkShutdown);
|
||||
SubscribeLocalEvent<SuperBonkComponent, ComponentShutdown>(OnShutdown);
|
||||
}
|
||||
|
||||
public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDead = false)
|
||||
private void OnInit(Entity<SuperBonkComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
var (_, component) = ent;
|
||||
|
||||
//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;
|
||||
}
|
||||
component.NextBonk = _timing.CurTime + component.BonkCooldown;
|
||||
}
|
||||
|
||||
var hadClumsy = EnsureComp<ClumsyComponent>(target, out _);
|
||||
private void OnMobStateChanged(Entity<SuperBonkComponent> ent, ref MobStateChangedEvent args)
|
||||
{
|
||||
var (uid, component) = ent;
|
||||
|
||||
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);
|
||||
}
|
||||
if (component.StopWhenDead && args.NewMobState == MobState.Dead)
|
||||
RemCompDeferred<SuperBonkComponent>(uid);
|
||||
}
|
||||
|
||||
var sComp = new SuperBonkComponent
|
||||
{
|
||||
Target = target,
|
||||
Tables = bonks.GetEnumerator(),
|
||||
RemoveClumsy = !hadClumsy,
|
||||
StopWhenDead = stopWhenDead,
|
||||
};
|
||||
private void OnShutdown(Entity<SuperBonkComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
var (uid, component) = ent;
|
||||
|
||||
AddComp(target, sComp);
|
||||
if (component.RemoveClumsy)
|
||||
RemComp<ClumsyComponent>(uid);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -59,49 +54,58 @@ public sealed class SuperBonkSystem : EntitySystem
|
||||
|
||||
while (comps.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
comp.TimeRemaining -= frameTime;
|
||||
if (!(comp.TimeRemaining <= 0))
|
||||
if (comp.NextBonk > _timing.CurTime)
|
||||
continue;
|
||||
|
||||
Bonk(comp);
|
||||
|
||||
if (!(comp.Tables.MoveNext()))
|
||||
if (!TryBonk(uid, comp.Tables.Current) || !comp.Tables.MoveNext())
|
||||
{
|
||||
RemComp<SuperBonkComponent>(comp.Target);
|
||||
RemComp<SuperBonkComponent>(uid);
|
||||
continue;
|
||||
}
|
||||
|
||||
comp.TimeRemaining = comp.InitialTime;
|
||||
comp.NextBonk += comp.BonkCooldown;
|
||||
}
|
||||
}
|
||||
|
||||
private void Bonk(SuperBonkComponent comp)
|
||||
public void StartSuperBonk(EntityUid target, bool stopWhenDead = false)
|
||||
{
|
||||
var uid = comp.Tables.Current.Key;
|
||||
//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 mobState) && mobState.CurrentState == MobState.Dead)
|
||||
return;
|
||||
|
||||
|
||||
if (EnsureComp<SuperBonkComponent>(target, out var component))
|
||||
return;
|
||||
|
||||
var tables = EntityQueryEnumerator<BonkableComponent>();
|
||||
var bonks = new List<EntityUid>();
|
||||
// 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);
|
||||
}
|
||||
|
||||
component.Tables = bonks.GetEnumerator();
|
||||
component.RemoveClumsy = !EnsureComp<ClumsyComponent>(target, out _);
|
||||
component.StopWhenDead = stopWhenDead;
|
||||
}
|
||||
|
||||
private bool TryBonk(EntityUid uid, EntityUid tableUid)
|
||||
{
|
||||
if (!TryComp<ClumsyComponent>(uid, out var clumsyComp))
|
||||
return false;
|
||||
|
||||
// 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) || !TryComp<ClumsyComponent>(comp.Target, out var clumsyComp))
|
||||
return;
|
||||
|
||||
_transformSystem.SetCoordinates(comp.Target, Transform(uid).Coordinates);
|
||||
|
||||
_clumsySystem.HitHeadClumsy((comp.Target, clumsyComp), uid);
|
||||
|
||||
_audioSystem.PlayPvs(clumsyComp.TableBonkSound, comp.Target);
|
||||
}
|
||||
|
||||
private void OnMobStateChanged(EntityUid uid, SuperBonkComponent comp, MobStateChangedEvent args)
|
||||
{
|
||||
if (comp.StopWhenDead && args.NewMobState == MobState.Dead)
|
||||
if (HasComp<TransformComponent>(tableUid))
|
||||
{
|
||||
RemComp<SuperBonkComponent>(uid);
|
||||
}
|
||||
}
|
||||
_transformSystem.SetCoordinates(uid, Transform(tableUid).Coordinates);
|
||||
|
||||
private void OnBonkShutdown(EntityUid uid, SuperBonkComponent comp, ComponentShutdown ev)
|
||||
{
|
||||
if (comp.RemoveClumsy)
|
||||
RemComp<ClumsyComponent>(comp.Target);
|
||||
_clumsySystem.HitHeadClumsy((uid, clumsyComp), tableUid);
|
||||
|
||||
_audioSystem.PlayPvs(clumsyComp.TableBonkSound, tableUid);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -29,10 +29,10 @@ public sealed class TagCommand : ToolshedCommand
|
||||
public IEnumerable<EntityUid> With(
|
||||
[CommandInvocationContext] IInvocationContext ctx,
|
||||
[PipedArgument] IEnumerable<EntityUid> entities,
|
||||
[CommandArgument] ValueRef<string, Prototype<TagPrototype>> tag)
|
||||
[CommandArgument] ProtoId<TagPrototype> tag)
|
||||
{
|
||||
_tag ??= GetSys<TagSystem>();
|
||||
return entities.Where(e => _tag.HasTag(e, tag.Evaluate(ctx)!));
|
||||
return entities.Where(e => _tag.HasTag(e, tag!));
|
||||
}
|
||||
|
||||
[CommandImplementation("add")]
|
||||
|
||||
Reference in New Issue
Block a user