var addedTags = newAccessList.Except(oldTags).Select(tag => "+" + tag).ToList();
var removedTags = oldTags.Except(newAccessList).Select(tag => "-" + tag).ToList();
- _adminLogger.Add(LogType.Action, LogImpact.Medium,
+ _adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(player):player} has modified {ToPrettyString(accessReaderEnt.Value):entity} with the following allowed access level holders: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");
accessReaderEnt.Value.Comp.AccessLists = ConvertAccessListToHashSet(newAccessList);
/*TODO: ECS SharedIdCardConsoleComponent and then log on card ejection, together with the save.
This current implementation is pretty shit as it logs 27 entries (27 lines) if someone decides to give themselves AA*/
- _adminLogger.Add(LogType.Action, LogImpact.Medium,
+ _adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(player):player} has modified {ToPrettyString(targetId):entity} with the following accesses: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");
}
access.Tags.Add(random.ID);
Dirty(uid, access);
- _adminLogger.Add(LogType.Action, LogImpact.Medium,
+ _adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(args.Microwave)} added {random.ID} access to {ToPrettyString(uid):entity}");
}
var oldValue = _configurationManager.GetCVar<object>(cvar);
_configurationManager.SetCVar(cvar, parsed);
_adminLogManager.Add(LogType.AdminCommands,
- LogImpact.High,
+ LogImpact.Extreme,
$"{shell.Player!.Name} ({shell.Player!.UserId}) changed CVAR {cvar} from {oldValue.ToString()} to {parsed.ToString()}"
);
using Content.Server.GameTicking;
using Content.Shared.Administration.Logs;
using Content.Shared.CCVar;
+using Content.Shared.Chat;
using Content.Shared.Database;
+using Content.Shared.Players.PlayTimeTracking;
using Prometheus;
using Robust.Shared;
using Robust.Shared.Configuration;
+using Robust.Shared.Network;
+using Robust.Shared.Player;
using Robust.Shared.Reflection;
using Robust.Shared.Timing;
[Dependency] private readonly IDynamicTypeFactory _typeFactory = default!;
[Dependency] private readonly IReflectionManager _reflection = default!;
[Dependency] private readonly IDependencyCollection _dependencies = default!;
+ [Dependency] private readonly ISharedPlayerManager _player = default!;
+ [Dependency] private readonly ISharedPlaytimeManager _playtime = default!;
+ [Dependency] private readonly ISharedChatManager _chat = default!;
public const string SawmillId = "admin.logs";
private int _queueMax;
private int _preRoundQueueMax;
private int _dropThreshold;
+ private int _highImpactLogPlaytime;
// Per update
private TimeSpan _nextUpdateTime;
value => _preRoundQueueMax = value, true);
_configuration.OnValueChanged(CCVars.AdminLogsDropThreshold,
value => _dropThreshold = value, true);
+ _configuration.OnValueChanged(CCVars.AdminLogsHighLogPlaytime,
+ value => _highImpactLogPlaytime = value, true);
if (_metricsEnabled)
{
};
log.Players.Add(player);
+ if (impact == LogImpact.Extreme) // Always chat-notify Extreme logs
+ _chat.SendAdminAlert(message);
+
+ if (impact == LogImpact.High) // Only chat-notify High logs if the player is below a threshold playtime
+ {
+ if (_highImpactLogPlaytime >= 0 && _player.TryGetSessionById(new NetUserId(id), out var session))
+ {
+ var playtimes = _playtime.GetPlayTimes(session);
+ if (playtimes.TryGetValue(PlayTimeTrackingShared.TrackerOverall, out var overallTime) &&
+ overallTime <= TimeSpan.FromHours(_highImpactLogPlaytime))
+ {
+ _chat.SendAdminAlert(message);
+ }
+ }
+ }
}
if (preRound)
return;
var humanReadableState = value ? "Inject" : "Not inject";
- _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to {humanReadableState}");
+ _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to {humanReadableState}");
}
public void ToggleInjecting(EntityUid uid, EntityUid? user = null, AmeControllerComponent? controller = null)
return;
var humanReadableState = controller.Injecting ? "Inject" : "Not inject";
- _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to inject {controller.InjectionAmount} while set to {humanReadableState}");
- /* This needs to be information which an admin is very likely to want to be informed about in order to be an admin alert or have a sound notification.
- At the time of editing, players regularly "overclock" the AME and those cases require no admin attention.
- // Admin alert
var safeLimit = int.MaxValue;
if (TryGetAMENodeGroup(uid, out var group))
safeLimit = group.CoreCount * 4;
- if (oldValue <= safeLimit && value > safeLimit)
- {
- if (_gameTiming.CurTime > controller.EffectCooldown)
- {
- _chatManager.SendAdminAlert(user.Value, $"increased AME over safe limit to {controller.InjectionAmount}");
- _audioSystem.PlayGlobal("/Audio/Misc/adminlarm.ogg",
- Filter.Empty().AddPlayers(_adminManager.ActiveAdmins), false, AudioParams.Default.WithVolume(-8f));
- controller.EffectCooldown = _gameTiming.CurTime + controller.CooldownDuration;
- }
- }
- */
+ var logImpact = (oldValue <= safeLimit && value > safeLimit) ? LogImpact.Extreme : LogImpact.Medium;
+
+ _adminLogger.Add(LogType.Action, logImpact, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to inject {controller.InjectionAmount} while set to {humanReadableState}");
}
public void AdjustInjectionAmount(EntityUid uid, int delta, EntityUid? user = null, AmeControllerComponent? controller = null)
_popup.PopupEntity(message, ent, ent, PopupType.MediumCaution);
- _adminLog.Add(LogType.Anomaly,LogImpact.Extreme,$"{ToPrettyString(ent)} became anomaly host.");
+ _adminLog.Add(LogType.Anomaly,LogImpact.Medium,$"{ToPrettyString(ent)} became anomaly host.");
}
Dirty(ent);
}
using Content.Server.Botany.Components;
using Content.Server.Botany.Systems;
using Content.Shared.Atmos;
+using Content.Shared.Database;
using Content.Shared.EntityEffects;
using Content.Shared.Random;
using Robust.Shared.Audio;
[DataField(customTypeSerializer: typeof(PrototypeIdListSerializer<SeedPrototype>))]
public List<string> MutationPrototypes = new();
+ /// <summary>
+ /// Log impact for when the seed is planted.
+ /// </summary>
+ [DataField]
+ public LogImpact? PlantLogImpact = null;
+
+ /// <summary>
+ /// Log impact for when the seed is harvested.
+ /// </summary>
+ [DataField]
+ public LogImpact? HarvestLogImpact = null;
+
public SeedData Clone()
{
DebugTools.Assert(!Immutable, "There should be no need to clone an immutable seed.");
using Robust.Shared.Random;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using Content.Shared.Administration.Logs;
+using Content.Shared.Database;
namespace Content.Server.Botany.Systems;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly RandomHelperSystem _randomHelper = default!;
+ [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
public override void Initialize()
{
{
if (position.IsValid(EntityManager) &&
proto.ProductPrototypes.Count > 0)
+ {
+ if (proto.HarvestLogImpact != null)
+ _adminLogger.Add(LogType.Botany, proto.HarvestLogImpact.Value, $"Auto-harvested {Loc.GetString(proto.Name):seed} at Pos:{position}.");
+
return GenerateProduct(proto, position, yieldMod);
+ }
return Enumerable.Empty<EntityUid>();
}
var name = Loc.GetString(proto.DisplayName);
_popupSystem.PopupCursor(Loc.GetString("botany-harvest-success-message", ("name", name)), user, PopupType.Medium);
+
+ if (proto.HarvestLogImpact != null)
+ _adminLogger.Add(LogType.Botany, proto.HarvestLogImpact.Value, $"{ToPrettyString(user):player} harvested {Loc.GetString(proto.Name):seed} at Pos:{Transform(user).Coordinates}.");
+
return GenerateProduct(proto, Transform(user).Coordinates, yieldMod);
}
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Content.Server.Labels.Components;
+using Content.Shared.Administration.Logs;
using Content.Shared.Containers.ItemSlots;
+using Content.Shared.Database;
namespace Content.Server.Botany.Systems;
[Dependency] private readonly RandomHelperSystem _randomHelper = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
+ [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
public const float HydroponicsSpeedMultiplier = 1f;
CheckLevelSanity(uid, component);
UpdateSprite(uid, component);
+ if (seed.PlantLogImpact != null)
+ _adminLogger.Add(LogType.Botany, seed.PlantLogImpact.Value, $"{ToPrettyString(args.User):player} planted {Loc.GetString(seed.Name):seed} at Pos:{Transform(uid).Coordinates}.");
+
return;
}
{
_mind.TransferTo(ent.Comp.StolenMind.Value, args.Wearer);
_adminLog.Add(LogType.Action,
- LogImpact.Extreme,
+ LogImpact.Medium,
$"{ToPrettyString(args.Wearer):player} was restored to their body after the removal of {ToPrettyString(ent):entity}.");
ent.Comp.StolenMind = null;
}
}
_roundEndSystem.RequestRoundEnd(uid);
- _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(mob):player} has called the shuttle.");
+ _adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(mob):player} has called the shuttle.");
}
private void OnRecallShuttleMessage(EntityUid uid, CommunicationsConsoleComponent comp, CommunicationsConsoleRecallEmergencyShuttleMessage message)
}
_roundEndSystem.CancelRoundEndCountdown(uid);
- _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(message.Actor):player} has recalled the shuttle.");
+ _adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(message.Actor):player} has recalled the shuttle.");
}
}
var logManager = IoCManager.Resolve<IAdminLogManager>();
if (userUid.HasValue)
- logManager.Add(LogType, Impact, $"{Message} - Entity: {entityManager.ToPrettyString(uid):entity}, User: {entityManager.ToPrettyString(userUid.Value):user}");
+ logManager.Add(LogType, Impact, $"{Message} - Entity: {entityManager.ToPrettyString(uid):entity}, User: {entityManager.ToPrettyString(userUid.Value):player}");
else
logManager.Add(LogType, Impact, $"{Message} - Entity: {entityManager.ToPrettyString(uid):entity}");
}
if (eventArgs.SenderSession.AttachedEntity != null)
{
- _adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
+ _adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{ToPrettyString(eventArgs.SenderSession.AttachedEntity.Value):actor} drew a {ev.Decal.Color} {ev.Decal.Id} at {ev.Coordinates}");
}
else
{
- _adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
+ _adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{eventArgs.SenderSession.Name} drew a {ev.Decal.Color} {ev.Decal.Id} at {ev.Coordinates}");
}
}
{
if (eventArgs.SenderSession.AttachedEntity != null)
{
- _adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
+ _adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{ToPrettyString(eventArgs.SenderSession.AttachedEntity.Value):actor} removed a {decal.Color} {decal.Id} at {ev.Coordinates}");
}
else
{
- _adminLogger.Add(LogType.CrayonDraw, LogImpact.High,
+ _adminLogger.Add(LogType.CrayonDraw, LogImpact.Low,
$"{eventArgs.SenderSession.Name} removed a {decal.Color} {decal.Id} at {ev.Coordinates}");
}
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using System.Linq;
+using Content.Shared.Humanoid;
+using Robust.Shared.Player;
namespace Content.Server.Destructible
{
{
RaiseLocalEvent(uid, new DamageThresholdReached(component, threshold), true);
+ var logImpact = LogImpact.Low;
// Convert behaviors into string for logs
var triggeredBehaviors = string.Join(", ", threshold.Behaviors.Select(b =>
{
+ if (logImpact <= b.Impact)
+ logImpact = b.Impact;
if (b is DoActsBehavior doActsBehavior)
{
return $"{b.GetType().Name}:{doActsBehavior.Acts.ToString()}";
return b.GetType().Name;
}));
+ // If it doesn't have a humanoid component, it's probably not particularly notable?
+ if (logImpact > LogImpact.Medium && !HasComp<HumanoidAppearanceComponent>(uid))
+ logImpact = LogImpact.Medium;
+
if (args.Origin != null)
{
- _adminLogger.Add(LogType.Damaged, LogImpact.Medium,
+ _adminLogger.Add(LogType.Damaged,
+ logImpact,
$"{ToPrettyString(args.Origin.Value):actor} caused {ToPrettyString(uid):subject} to trigger [{triggeredBehaviors}]");
}
else
{
- _adminLogger.Add(LogType.Damaged, LogImpact.Medium,
+ _adminLogger.Add(LogType.Damaged,
+ logImpact,
$"Unknown damage source caused {ToPrettyString(uid):subject} to trigger [{triggeredBehaviors}]");
}
using Content.Shared.Body.Components;
+using Content.Shared.Database;
using JetBrains.Annotations;
namespace Content.Server.Destructible.Thresholds.Behaviors
{
[DataField("recursive")] private bool _recursive = true;
+ public LogImpact Impact => LogImpact.Extreme;
+
public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
{
if (system.EntityManager.TryGetComponent(owner, out BodyComponent? body))
-namespace Content.Server.Destructible.Thresholds.Behaviors
+using Content.Shared.Database;
+
+namespace Content.Server.Destructible.Thresholds.Behaviors
{
public interface IThresholdBehavior
{
+ public LogImpact Impact => LogImpact.Low;
+
/// <summary>
/// Executes this behavior.
/// </summary>
}
else
{
- _adminLogger.Add(LogType.Explosion, LogImpact.High,
- $"{ToPrettyString(user.Value):user} caused {ToPrettyString(uid):entity} to explode ({typeId}) at Pos:{(posFound ? $"{gridPos:coordinates}" : "[Grid or Map not found]")} with intensity {totalIntensity} slope {slope}");
var alertMinExplosionIntensity = _cfg.GetCVar(CCVars.AdminAlertExplosionMinIntensity);
- if (alertMinExplosionIntensity > -1 && totalIntensity >= alertMinExplosionIntensity)
- _chat.SendAdminAlert(user.Value, $"caused {ToPrettyString(uid)} to explode ({typeId}:{totalIntensity}) at Pos:{(posFound ? $"{gridPos:coordinates}" : "[Grid or Map not found]")}");
+ var logImpact = (alertMinExplosionIntensity > -1 && totalIntensity >= alertMinExplosionIntensity)
+ ? LogImpact.Extreme
+ : LogImpact.High;
+ _adminLogger.Add(LogType.Explosion, logImpact,
+ $"{ToPrettyString(user.Value):user} caused {ToPrettyString(uid):entity} to explode ({typeId}) at Pos:{(posFound ? $"{gridPos:coordinates}" : "[Grid or Map not found]")} with intensity {totalIntensity} slope {slope}");
}
}
if (!string.IsNullOrWhiteSpace(component.KeyPhrase) && message.Contains(component.KeyPhrase, StringComparison.InvariantCultureIgnoreCase))
{
- _adminLogger.Add(LogType.Trigger, LogImpact.High,
+ _adminLogger.Add(LogType.Trigger, LogImpact.Medium,
$"A voice-trigger on {ToPrettyString(ent):entity} was triggered by {ToPrettyString(args.Source):speaker} speaking the key-phrase {component.KeyPhrase}.");
Trigger(ent, args.Source);
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.DragDrop;
+using Content.Shared.Humanoid;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
if (!Resolve(uid, ref component) || !Resolve(victimUid, ref butcherable))
return;
- _logger.Add(LogType.Gib, LogImpact.Extreme, $"{ToPrettyString(userUid):user} kitchen spiked {ToPrettyString(victimUid):target}");
+ var logImpact = LogImpact.Medium;
+ if (HasComp<HumanoidAppearanceComponent>(victimUid))
+ logImpact = LogImpact.Extreme;
+
+ _logger.Add(LogType.Gib, logImpact, $"{ToPrettyString(userUid):user} kitchen spiked {ToPrettyString(victimUid):target}");
// TODO VERY SUS
component.PrototypesToSpawn = EntitySpawnCollection.GetSpawns(butcherable.SpawnedEntities, _random);
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using System.Linq;
+using Content.Shared.Humanoid;
namespace Content.Server.Materials;
if (CanGib(uid, item, component))
{
- _adminLogger.Add(LogType.Gib, LogImpact.Extreme, $"{ToPrettyString(item):victim} was gibbed by {ToPrettyString(uid):entity} ");
+ var logImpact = HasComp<HumanoidAppearanceComponent>(item) ? LogImpact.Extreme : LogImpact.Medium;
+ _adminLogger.Add(LogType.Gib, logImpact, $"{ToPrettyString(item):victim} was gibbed by {ToPrettyString(uid):entity} ");
SpawnChemicalsFromComposition(uid, item, completion, false, component, xform);
_body.GibBody(item, true);
_appearance.SetData(uid, RecyclerVisuals.Bloody, true);
_throwing.TryThrow(args.Climber, direction, 0.5f);
return;
}
- _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.Instigator):player} used a biomass reclaimer to gib {ToPrettyString(args.Climber):target} in {ToPrettyString(reclaimer):reclaimer}");
+ _adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Instigator):player} used a biomass reclaimer to gib {ToPrettyString(args.Climber):target} in {ToPrettyString(reclaimer):reclaimer}");
StartProcessing(args.Climber, reclaimer);
}
if (args.Args.Used == null || args.Args.Target == null || !HasComp<BiomassReclaimerComponent>(args.Args.Target.Value))
return;
- _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.Args.User):player} used a biomass reclaimer to gib {ToPrettyString(args.Args.Target.Value):target} in {ToPrettyString(reclaimer):reclaimer}");
+ _adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Args.User):player} used a biomass reclaimer to gib {ToPrettyString(args.Args.Target.Value):target} in {ToPrettyString(reclaimer):reclaimer}");
StartProcessing(args.Args.Used.Value, reclaimer);
args.Handled = true;
{
threshold = mobThreshold.Value;
if (HasComp<ActorComponent>(args.OtherEntity))
- _adminLog.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.OtherEntity):player} was struck by meteor {ToPrettyString(uid):ent} and killed instantly.");
+ _adminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.OtherEntity):player} was struck by meteor {ToPrettyString(uid):ent} and killed instantly.");
}
else if (_destructible.TryGetDestroyedAt(args.OtherEntity, out var destroyThreshold))
{
Text = Loc.GetString("cremate-verb-get-data-text"),
// TODO VERB ICON add flame/burn symbol?
Act = () => TryCremate(uid, component, storage),
- Impact = LogImpact.Medium // could be a body? or evidence? I dunno.
+ Impact = LogImpact.High // could be a body? or evidence? I dunno.
};
args.Verbs.Add(verb);
}
_popup.PopupEntity(Loc.GetString("drink-component-force-feed", ("user", userName)), user, target);
// logging
- _adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(user):user} is forcing {ToPrettyString(target):target} to drink {ToPrettyString(item):drink} {SharedSolutionContainerSystem.ToPrettyString(drinkSolution)}");
+ _adminLogger.Add(LogType.ForceFeed, LogImpact.High, $"{ToPrettyString(user):user} is forcing {ToPrettyString(target):target} to drink {ToPrettyString(item):drink} {SharedSolutionContainerSystem.ToPrettyString(drinkSolution)}");
}
else
{
};
if (actorEntity != null)
- _adminLogger.Add(logType, LogImpact.High,
+ _adminLogger.Add(logType, LogImpact.Medium,
$"{ToPrettyString(actorEntity.Value):actor} used placement system to {ev.PlacementEventAction.ToString().ToLower()} {ToPrettyString(ev.EditedEntity):subject} at {ev.Coordinates}");
else if (actor != null)
- _adminLogger.Add(logType, LogImpact.High,
+ _adminLogger.Add(logType, LogImpact.Medium,
$"{actor:actor} used placement system to {ev.PlacementEventAction.ToString().ToLower()} {ToPrettyString(ev.EditedEntity):subject} at {ev.Coordinates}");
else
- _adminLogger.Add(logType, LogImpact.High,
+ _adminLogger.Add(logType, LogImpact.Medium,
$"Placement system {ev.PlacementEventAction.ToString().ToLower()}ed {ToPrettyString(ev.EditedEntity):subject} at {ev.Coordinates}");
}
var actorEntity = actor?.AttachedEntity;
if (actorEntity != null)
- _adminLogger.Add(LogType.Tile, LogImpact.High,
+ _adminLogger.Add(LogType.Tile, LogImpact.Medium,
$"{ToPrettyString(actorEntity.Value):actor} used placement system to set tile {_tileDefinitionManager[ev.TileType].Name} at {ev.Coordinates}");
else if (actor != null)
- _adminLogger.Add(LogType.Tile, LogImpact.High,
+ _adminLogger.Add(LogType.Tile, LogImpact.Medium,
$"{actor} used placement system to set tile {_tileDefinitionManager[ev.TileType].Name} at {ev.Coordinates}");
else
- _adminLogger.Add(LogType.Tile, LogImpact.High,
+ _adminLogger.Add(LogType.Tile, LogImpact.Medium,
$"Placement system set tile {_tileDefinitionManager[ev.TileType].Name} at {ev.Coordinates}");
}
}
if (_electrocutionSystem.TryDoElectrifiedAct(uid, args.User))
return;
- _adminLogger.Add(LogType.CableCut, LogImpact.Medium, $"The {ToPrettyString(uid)} at {xform.Coordinates} was cut by {ToPrettyString(args.User)}.");
+ _adminLogger.Add(LogType.CableCut, LogImpact.High, $"The {ToPrettyString(uid)} at {xform.Coordinates} was cut by {ToPrettyString(args.User)}.");
Spawn(cable.CableDroppedOnCutPrototype, xform.Coordinates);
QueueDel(uid);
}
_adminLogger.Add(LogType.BulletHit,
- HasComp<ActorComponent>(target) ? LogImpact.Extreme : LogImpact.High,
+ LogImpact.Medium,
$"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(component.Shooter!.Value):user} hit {otherName:target} and dealt {modifiedDamage.GetTotal():damage} damage");
}
private void Respawn(EntityUid oldEntity, string prototype, EntityCoordinates coords)
{
var entity = Spawn(prototype, coords);
- _adminLog.Add(LogType.Respawn, LogImpact.High, $"{ToPrettyString(oldEntity)} was deleted and was respawned at {coords.ToMap(EntityManager, _transform)} as {ToPrettyString(entity)}");
+ _adminLog.Add(LogType.Respawn, LogImpact.Extreme, $"{ToPrettyString(oldEntity)} was deleted and was respawned at {coords.ToMap(EntityManager, _transform)} as {ToPrettyString(entity)}");
_chat.SendAdminAlert($"{MetaData(oldEntity).EntityName} was deleted and was respawned as {ToPrettyString(entity)}");
}
{
if (EarlyLaunchAuthorized || !EmergencyShuttleArrived || _consoleAccumulator <= _authorizeTime) return false;
- _logger.Add(LogType.EmergencyShuttle, LogImpact.Extreme, $"Emergency shuttle launch authorized");
+ _logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle launch authorized");
_consoleAccumulator = _authorizeTime;
EarlyLaunchAuthorized = true;
RaiseLocalEvent(new EmergencyShuttleAuthorizedEvent());
|| _tagSystem.HasTag(morsel, "HighRiskItem")
|| HasComp<ContainmentFieldGeneratorComponent>(morsel))
{
- _adminLogger.Add(LogType.EntityDelete, LogImpact.Extreme, $"{ToPrettyString(morsel)} entered the event horizon of {ToPrettyString(hungry)} and was deleted");
+ _adminLogger.Add(LogType.EntityDelete, LogImpact.High, $"{ToPrettyString(morsel):player} entered the event horizon of {ToPrettyString(hungry)} and was deleted");
}
EntityManager.QueueDeleteEntity(morsel);
var timeout = EnsureComp<PortalTimeoutComponent>(user);
timeout.EnteredPortal = null;
component.FirstPortal = Spawn(component.FirstPortalPrototype, Transform(user).Coordinates);
- _adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(user):player} opened {ToPrettyString(component.FirstPortal.Value)} at {Transform(component.FirstPortal.Value).Coordinates} using {ToPrettyString(uid)}");
+ _adminLogger.Add(LogType.EntitySpawn, LogImpact.High, $"{ToPrettyString(user):player} opened {ToPrettyString(component.FirstPortal.Value)} at {Transform(component.FirstPortal.Value).Coordinates} using {ToPrettyString(uid)}");
_audio.PlayPvs(component.NewPortalSound, uid);
}
else if (Deleted(component.SecondPortal))
var timeout = EnsureComp<PortalTimeoutComponent>(user);
timeout.EnteredPortal = null;
component.SecondPortal = Spawn(component.SecondPortalPrototype, Transform(user).Coordinates);
- _adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(user):player} opened {ToPrettyString(component.SecondPortal.Value)} at {Transform(component.SecondPortal.Value).Coordinates} linked to {ToPrettyString(component.FirstPortal!.Value)} using {ToPrettyString(uid)}");
+ _adminLogger.Add(LogType.EntitySpawn, LogImpact.High, $"{ToPrettyString(user):player} opened {ToPrettyString(component.SecondPortal.Value)} at {Transform(component.SecondPortal.Value).Coordinates} linked to {ToPrettyString(component.FirstPortal!.Value)} using {ToPrettyString(uid)}");
_link.TryLink(component.FirstPortal!.Value, component.SecondPortal.Value, true);
_audio.PlayPvs(component.NewPortalSound, uid);
}
portalStrings += " and ";
portalStrings += ToPrettyString(component.SecondPortal);
if (portalStrings != "")
- _adminLogger.Add(LogType.EntityDelete, LogImpact.Low, $"{ToPrettyString(user):player} closed {portalStrings} with {ToPrettyString(uid)}");
+ _adminLogger.Add(LogType.EntityDelete, LogImpact.High, $"{ToPrettyString(user):player} closed {portalStrings} with {ToPrettyString(uid)}");
// Clear both portals
if (!Deleted(component.FirstPortal))
[Serializable]
public enum LogImpact : sbyte
{
- Low = -1,
- Medium = 0,
- High = 1,
- Extreme = 2 // Nar'Sie just dropped
+ Low = -1, // General logging
+ Medium = 0, // Has impact on the round but not necessary for admins to be notified of
+ High = 1, // Notable logs that come up in normal gameplay; new players causing these will pop up as admin alerts!
+ Extreme = 2 // Irreversible round-impacting logs admins should always be notified of, OR big admin actions!!
}
/// A player was selected or assigned antag status
/// </summary>
AntagSelection = 99,
+
+ /// <summary>
+ /// Logs related to botany, such as planting and harvesting crops
+ /// </summary>
+ Botany = 100,
}
if (HasComp<AnomalySupercriticalComponent>(uid))
return;
- AdminLog.Add(LogType.Anomaly, LogImpact.Extreme, $"Anomaly {ToPrettyString(uid)} began to go supercritical.");
+ AdminLog.Add(LogType.Anomaly, LogImpact.High, $"Anomaly {ToPrettyString(uid)} began to go supercritical.");
if (_net.IsServer)
Log.Info($"Anomaly is going supercritical. Entity: {ToPrettyString(uid)}");
public static readonly CVarDef<string> AdminLogsServerName =
CVarDef.Create("adminlogs.server_name", "unknown", CVar.SERVERONLY);
+
+ /// <summary>
+ /// Any session below this playtime will send an admin alert whenever they cause a LogImpact.High log.
+ /// Set to -1 to disable.
+ /// </summary>
+ public static readonly CVarDef<int> AdminLogsHighLogPlaytime =
+ CVarDef.Create("adminlogs.high_log_playtime", 5, CVar.SERVERONLY);
}
("otherName", Identity.Name(target, EntityManager, user))), user, user);
_popup.PopupClient(Loc.GetString("handcuff-component-cuff-by-other-success-message",
("otherName", Identity.Name(user, EntityManager, target))), target, target);
- _adminLog.Add(LogType.Action, LogImpact.Medium,
+ _adminLog.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(user):player} has cuffed {ToPrettyString(target):player}");
}
}
if (!_doAfter.TryStartDoAfter(doAfterEventArgs))
return;
- _adminLog.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user)} is trying to uncuff {ToPrettyString(target)}");
+ _adminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(user):player} is trying to uncuff {ToPrettyString(target):subject}");
var popupText = user == target
? "cuffable-component-start-uncuffing-self-observer"
{
_popup.PopupEntity(Loc.GetString("cuffable-component-remove-cuffs-by-other-success-message",
("otherName", Identity.Name(user.Value, EntityManager, user))), target, target);
- _adminLog.Add(LogType.Action, LogImpact.Medium,
+ _adminLog.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(user):player} has successfully uncuffed {ToPrettyString(target):player}");
}
else
{
- _adminLog.Add(LogType.Action, LogImpact.Medium,
+ _adminLog.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(user):player} has successfully uncuffed themselves");
}
}
using Content.Shared.Database;
+using Content.Shared.Humanoid;
using Content.Shared.Mobs.Components;
+using Robust.Shared.Player;
namespace Content.Shared.Mobs.Systems;
var ev = new MobStateChangedEvent(target, component, oldState, newState, origin);
OnStateChanged(target, component, oldState, newState);
RaiseLocalEvent(target, ev, true);
- _adminLogger.Add(LogType.Damaged, oldState == MobState.Alive ? LogImpact.Low : LogImpact.Medium,
- $"{ToPrettyString(target):user} state changed from {oldState} to {newState}");
+ if (origin != null && HasComp<ActorComponent>(origin) && HasComp<ActorComponent>(target) && oldState < newState)
+ _adminLogger.Add(LogType.Damaged, LogImpact.High, $"{ToPrettyString(origin):player} caused {ToPrettyString(target):player} state to change from {oldState} to {newState}");
+ else
+ _adminLogger.Add(LogType.Damaged, oldState == MobState.Alive ? LogImpact.Low : LogImpact.Medium, $"{ToPrettyString(target):user} state changed from {oldState} to {newState}");
Dirty(target, component);
}
else
{
var error = $"The Character Window of {_minds.MindOwnerLoggingString(comp)} potentially did not update immediately : session error";
- _adminLogger.Add(LogType.Mind, LogImpact.High, $"{error}");
+ _adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{error}");
}
if (comp.OwnedEntity is null)
{
Log.Error($"{ToPrettyString(mind)} does not have an OwnedEntity!");
_adminLogger.Add(LogType.Mind,
- LogImpact.High,
+ LogImpact.Medium,
$"Role Type of {ToPrettyString(mind)} changed to {roleTypeId}");
return;
}
RaiseLocalEvent(item, new DroppedEvent(user), true); // Gas tank internals etc.
_handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: !stealth);
- _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot");
+ _adminLogger.Add(LogType.Stripping, LogImpact.High, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot");
}
/// <summary>
_handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: target.Comp);
_handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: !stealth, handsComp: user.Comp);
- _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands");
+ _adminLogger.Add(LogType.Stripping, LogImpact.High, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands");
// Hand update will trigger strippable update.
}
chat-manager-admin-channel-name = ADMIN
chat-manager-rate-limited = You are sending messages too quickly!
-chat-manager-rate-limit-admin-announcement = Player { $player } breached chat rate limits. Watch them if this is a regular occurence.
+chat-manager-rate-limit-admin-announcement = Rate limit warning: { $player }
## Speech verbs for chat
noun: seeds-noun-seeds
displayName: seeds-killertomato-display-name
plantRsi: Objects/Specific/Hydroponics/tomatokiller.rsi
+ plantLogImpact: High
+ harvestLogImpact: High
packetPrototype: KillerTomatoSeeds
productPrototypes:
- MobTomatoKiller
displayName: seeds-deathnettle-display-name
plantRsi: Objects/Specific/Hydroponics/death_nettle.rsi
packetPrototype: DeathNettleSeeds
+ plantLogImpact: High
+ harvestLogImpact: High
productPrototypes:
- DeathNettle
lifespan: 25
id: MeatSpike
start: start
graph:
- - node: start
- actions:
- - !type:DeleteEntity {}
- edges:
- - to: MeatSpike
- completed:
- - !type:SnapToGrid
- southRotation: true
- steps:
- - material: Steel
- amount: 15
- doAfter: 2
- - node: MeatSpike
- entity: KitchenSpike
- edges:
- - to: start
- completed:
- - !type:SpawnPrototype
- prototype: SheetSteel1
- amount: 15
- steps:
- - tool: Screwing
- doAfter: 1
+ - node: start
+ actions:
+ - !type:DeleteEntity {}
+ edges:
+ - to: MeatSpike
+ completed:
+ - !type:AdminLog # Needs a log for start of attempt in addition to the completion log
+ message: "Construction"
+ impact: High
+ - !type:SnapToGrid
+ southRotation: true
+ steps:
+ - material: Steel
+ amount: 15
+ doAfter: 2
+ - node: MeatSpike
+ entity: KitchenSpike
+ edges:
+ - to: start
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 15
+ steps:
+ - tool: Screwing
+ doAfter: 1
edges:
- to: grille
completed:
+ - !type:AdminLog # Needs a log for start of attempt in addition to the completion log
+ message: "Construction"
+ impact: High
- !type:SnapToGrid
southRotation: true
steps:
entity: ShardGlass
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- material: Cloth
amount: 1
- node: start
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- tag: GlassShard
name: glass shard
entity: ShardGlassReinforced
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- material: Cloth
amount: 1
- node: start
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- tag: ReinforcedGlassShard
name: reinforced glass shard
entity: ShardGlassPlasma
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- material: Cloth
amount: 1
- node: start
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- tag: PlasmaGlassShard
name: plasma glass shard
entity: ShardGlassUranium
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- material: Cloth
amount: 1
- node: start
edges:
- to: icon
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- tag: UraniumGlassShard
name: uranium glass shard
- node: start
edges:
- to: spear
+ completed:
+ - !type:AdminLog # Needs a log for start of attempt in addition to the completion log
+ message: "Construction"
+ impact: High
steps:
- material: MetalRod
amount: 2
- node: start
edges:
- to: spear
+ completed:
+ - !type:AdminLog # Needs a log for start of attempt in addition to the completion log
+ message: "Construction"
+ impact: High
steps:
- material: MetalRod
amount: 2
- node: start
edges:
- to: spear
+ completed:
+ - !type:AdminLog # Needs a log for start of attempt in addition to the completion log
+ message: "Construction"
+ impact: High
steps:
- material: MetalRod
amount: 2
- node: start
edges:
- to: spear
+ completed:
+ - !type:AdminLog # Needs a log for start of attempt in addition to the completion log
+ message: "Construction"
+ impact: High
steps:
- material: MetalRod
amount: 2
- node: start
edges:
- to: spear
+ completed:
+ - !type:AdminLog # Needs a log for start of attempt in addition to the completion log
+ message: "Construction"
+ impact: High
steps:
- material: Bones
amount: 4
- tool: Prying
doAfter: 1
- to: bat
+ completed:
+ - !type:AdminLog
+ message: "Construction"
+ impact: High
steps:
- tool: Slicing
doAfter: 4