Compare commits

...

10 Commits

Author SHA1 Message Date
0a5d394eab use LabApi properties where possible 2025-05-01 19:24:32 +02:00
0a1192d5fc port plugin and events 2025-05-01 19:19:02 +02:00
6d39360955 begin LabApi version 2025-05-01 19:08:03 +02:00
755cfb0d88 fix spawn wave checks 2024-12-22 09:45:00 +01:00
bce7d936b3 detain events 2024-07-14 16:53:38 +02:00
cf8e68f159 Revert "Christmas"
This reverts commit 773f8c1fec87f6d903f88fd922bda964a871684f.
2024-01-13 10:28:51 +01:00
773f8c1fec Christmas 2023-12-23 22:32:45 +01:00
d668a1b28e 13.3.1 2023-11-14 21:47:34 +01:00
cda02035c6 3114 2023-10-28 12:04:59 +02:00
6bcb554c40 13.3 2023-10-27 18:46:42 +02:00
9 changed files with 134 additions and 234 deletions

4
.gitignore vendored
View File

@ -2,4 +2,6 @@ bin/
obj/ obj/
/packages/ /packages/
riderModule.iml riderModule.iml
/_ReSharper.Caches/ /_ReSharper.Caches/
*.user
/.idea/

View File

@ -1,139 +1,25 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.8\build\Microsoft.CodeAnalysis.Analyzers.props" Condition="Exists('..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.8\build\Microsoft.CodeAnalysis.Analyzers.props')"/>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFramework>net48</TargetFramework>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{67776CDF-B249-4B71-B8B9-6537A9DCE309}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <LangVersion>12</LangVersion>
<RootNamespace>DeathLog</RootNamespace>
<AssemblyName>DeathLog</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<LangVersion>10</LangVersion>
<NoWarn>MSB3277</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>$(NW-ASSEMBLIES)\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>$(NW-ASSEMBLIES)\Assembly-CSharp-firstpass.dll</HintPath>
</Reference>
<Reference Include="Axwabo.Helpers.NWAPI">
<HintPath>$(NW-ASSEMBLIES)\Axwabo.Helpers.dll</HintPath>
</Reference>
<Reference Include="CommandSystem.Core">
<HintPath>$(NW-ASSEMBLIES)\CommandSystem.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=3.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.3.3.1\lib\netstandard2.0\Microsoft.CodeAnalysis.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=3.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.3.3.1\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
</Reference>
<Reference Include="Mirror">
<HintPath>$(NW-ASSEMBLIES)\Mirror.dll</HintPath>
</Reference>
<Reference Include="Mirror.Components">
<HintPath>$(NW-ASSEMBLIES)\Mirror.Components.dll</HintPath>
</Reference>
<Reference Include="mscorlib"/>
<Reference Include="PluginAPI, Version=13.1.0.0, Culture=neutral, processorArchitecture=Amd64">
<HintPath>..\packages\Northwood.PluginAPI.13.1.0\lib\net48\PluginAPI.dll</HintPath>
</Reference>
<Reference Include="Pooling">
<HintPath>$(NW-ASSEMBLIES)\Pooling.dll</HintPath>
</Reference>
<Reference Include="System"/>
<Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics"/>
<Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Metadata, Version=1.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encoding.CodePages.4.5.1\lib\net461\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Xml"/>
<Reference Include="UnityEngine">
<HintPath>$(NW-ASSEMBLIES)\UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(NW-ASSEMBLIES)\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="YamlDotNet, Version=11.0.0.0, Culture=neutral, PublicKeyToken=ec19458f3c15af5e, processorArchitecture=MSIL">
<HintPath>..\packages\YamlDotNet.11.0.1\lib\net45\YamlDotNet.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="DeathLogConfig.cs"/>
<Compile Include="DeathLogPlugin.cs"/>
<Compile Include="LogHandler.cs"/>
<Compile Include="Properties\AssemblyInfo.cs"/>
<Compile Include="ToggleLogsCommand.cs"/>
</ItemGroup>
<ItemGroup>
<None Include="packages.config"/>
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.8\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll"/>
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.8\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll"/>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.8\build\Microsoft.CodeAnalysis.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeAnalysis.Analyzers.2.9.8\build\Microsoft.CodeAnalysis.Analyzers.props'))"/>
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<AppDesignerFolder>Properties</AppDesignerFolder>
<PlatformTarget>x64</PlatformTarget>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp" Private="false"/>
<Reference Include="Assembly-CSharp-firstpass" Private="false"/>
<Reference Include="Axwabo.Helpers" Private="false"/>
<Reference Include="CommandSystem.Core" Private="false"/>
<Reference Include="Mirror" Private="false"/>
<Reference Include="Mirror.Components" Private="false"/>
<Reference Include="mscorlib" Private="false"/>
<Reference Include="LabApi" Private="false"/>
<Reference Include="Pooling" Private="false"/>
<Reference Include="System"/>
<Reference Include="UnityEngine.CoreModule" Private="false"/>
</ItemGroup>
</Project> </Project>

View File

@ -15,4 +15,6 @@ public sealed class DeathLogConfig
public float DefaultFontSizeScalar { get; set; } = 1; public float DefaultFontSizeScalar { get; set; } = 1;
public bool LogDetainEvents { get; set; } = true;
} }

View File

@ -1,93 +1,82 @@
using Axwabo.Helpers; using System;
using LabApi.Events.Arguments.PlayerEvents;
using LabApi.Events.Arguments.ServerEvents;
using LabApi.Events.Handlers;
using LabApi.Loader.Features.Plugins;
using PlayerRoles; using PlayerRoles;
using PlayerRoles.PlayableScps;
using PlayerStatsSystem; using PlayerStatsSystem;
using PluginAPI.Core;
using PluginAPI.Core.Attributes;
using PluginAPI.Enums;
using PluginAPI.Events;
namespace DeathLog; namespace DeathLog;
public sealed class DeathLogPlugin public sealed class DeathLogPlugin : Plugin<DeathLogConfig>
{ {
[PluginEntryPoint("DeathLog", "1.1.0", "DeathLog", "Axwabo")] public override string Name => "DeathLog";
public void OnEnabled() public override string Description => "Logs deaths, cuffing and leaving SCPs";
public override string Author => "Axwabo";
public override Version Version => GetType().Assembly.GetName().Version;
public override Version RequiredApiVersion { get; } = new(1, 0, 0);
public override void Enable()
{ {
EventManager.RegisterEvents(this); ServerEvents.WaveRespawned += OnTeamRespawn;
Log.Info("DeathLog loaded!"); ServerEvents.RoundStarted += OnRoundStarted;
PlayerEvents.Dying += OnPlayerDeath;
PlayerEvents.ChangingRole += OnPlayerLeave;
PlayerEvents.Cuffed += OnDetaining;
PlayerEvents.Uncuffed += OnUnDetaining;
} }
[PluginUnload] public override void Disable()
public void OnDisabled()
{ {
EventManager.UnregisterEvents(this); ServerEvents.WaveRespawned -= OnTeamRespawn;
Log.Info("DeathLog disabled!"); ServerEvents.RoundStarted -= OnRoundStarted;
PlayerEvents.Dying -= OnPlayerDeath;
PlayerEvents.ChangingRole -= OnPlayerLeave;
PlayerEvents.Cuffed -= OnDetaining;
PlayerEvents.Uncuffed -= OnUnDetaining;
} }
[PluginConfig]
public DeathLogConfig Config = new();
private bool _spawnWaveOccurred; private bool _spawnWaveOccurred;
[PluginEvent(ServerEventType.RoundStart)]
private void OnRoundStarted() private void OnRoundStarted()
{ {
_spawnWaveOccurred = false; _spawnWaveOccurred = false;
_lastId = "";
LogHandler.KosIgnoredVictimNetIdList.Clear(); LogHandler.KosIgnoredVictimNetIdList.Clear();
} }
[PluginEvent(ServerEventType.TeamRespawn)] private void OnTeamRespawn(WaveRespawnedEventArgs ev)
private void OnTeamRespawn(TeamRespawnEvent e) => _spawnWaveOccurred = Config.IgnoreLeavingAfterSpawnWave; => _spawnWaveOccurred = Config!.IgnoreLeavingAfterSpawnWave;
private static bool IsUnknownCause(DamageHandlerBase handler) => private void OnPlayerDeath(PlayerDyingEventArgs e)
handler is UniversalDamageHandler udh && (udh.TranslationId == 0 ? string.IsNullOrEmpty(udh._logsText) : udh._logsText == DeathTranslations.Unknown.LogLabel);
[PluginEvent(ServerEventType.PlayerDying)]
private void OnPlayerDeath(PlayerDyingEvent e)
{ {
var player = e.Player; var player = e.Player;
var attacker = e.Attacker; var attacker = e.Attacker;
var handler = e.DamageHandler; var handler = e.DamageHandler;
if (player.Role is RoleTypeId.None or RoleTypeId.Scp0492 || string.IsNullOrEmpty(player.ReferenceHub.nicknameSync._myNickSync)) if (!player.IsReady || player.Role is RoleTypeId.None or RoleTypeId.Scp0492 || string.IsNullOrEmpty(player.Nickname))
return; return;
if (attacker != null && handler is AttackerDamageHandler adh) if (attacker != null && handler is AttackerDamageHandler adh)
LogHandler.LogAttackerDeathMessage(player, attacker, adh, Config.VisibilityRequirement, Config.KillOnSightPermitted, Config.DefaultFontSizeScalar); LogHandler.LogAttackerDeathMessage(player, attacker, adh, Config!.VisibilityRequirement, Config.KillOnSightPermitted, Config.DefaultFontSizeScalar);
else if (Config.LogSimpleDeaths) else if (Config!.LogSimpleDeaths)
LogHandler.LogSimpleDeathMessage(player, handler, Config.VisibilityRequirement, Config.DefaultFontSizeScalar); LogHandler.LogSimpleDeathMessage(player, handler, Config.VisibilityRequirement, Config.DefaultFontSizeScalar);
if (!IsUnknownCause(handler) || player.ReferenceHub.roleManager.CurrentRole is not FpcStandardScp scp)
return;
_lastRole = scp.RoleName.Color(scp.RoleColor.ToHex());
_lastId = player.UserId;
} }
[PluginEvent(ServerEventType.PlayerDamage)] private void OnPlayerLeave(PlayerChangingRoleEventArgs ev)
private void OnDamage(PlayerDamageEvent e)
{ {
var handler = e.DamageHandler; if (ev.NewRole == RoleTypeId.Destroyed && !_spawnWaveOccurred && Config!.LogLeavingScpPlayers)
var player = e.Player; LogHandler.LogLeavingScp(ev.OldRole.RoleName, ev.Player.Health, ev.Player.HumeShield, Config.VisibilityRequirement, Config.DefaultFontSizeScalar);
if (player == null
|| !player.IsConnected()
|| !IsUnknownCause(handler)
|| player.ReferenceHub.roleManager.CurrentRole is not FpcStandardScp {RoleTypeId: not RoleTypeId.Scp0492})
return;
var stats = player.ReferenceHub.playerStats;
_lastHealth = stats.GetModule<HealthStat>().CurValue;
_lastHumeShield = stats.GetModule<HumeShieldStat>().CurValue;
} }
private string _lastRole = ""; private void OnDetaining(PlayerCuffedEventArgs e)
private float _lastHealth;
private float _lastHumeShield;
private string _lastId;
[PluginEvent(ServerEventType.PlayerLeft)]
private void OnPlayerLeave(Player player)
{ {
if (!_spawnWaveOccurred && Config.LogLeavingScpPlayers && player.UserId == _lastId) if (Config!.LogDetainEvents)
LogHandler.LogLeavingScp(_lastRole, _lastHealth, _lastHumeShield, Config.VisibilityRequirement, Config.DefaultFontSizeScalar); LogHandler.LogDetain(e.Target, e.Player, Config.VisibilityRequirement, Config.DefaultFontSizeScalar);
}
private void OnUnDetaining(PlayerUncuffedEventArgs e)
{
if (Config!.LogDetainEvents)
LogHandler.LogUnDetain(e.Target, e.Player, Config.VisibilityRequirement, Config.DefaultFontSizeScalar);
} }
} }

View File

@ -2,11 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Axwabo.Helpers; using Axwabo.Helpers;
using LabApi.Features.Wrappers;
using PlayerRoles; using PlayerRoles;
using PlayerRoles.PlayableScps; using PlayerRoles.PlayableScps;
using PlayerRoles.PlayableScps.Scp3114;
using PlayerRoles.PlayableScps.Scp939; using PlayerRoles.PlayableScps.Scp939;
using PlayerStatsSystem; using PlayerStatsSystem;
using PluginAPI.Core;
using UnityEngine; using UnityEngine;
namespace DeathLog; namespace DeathLog;
@ -19,7 +20,7 @@ public static class LogHandler
private static readonly Color DntColor = new(0.59f, 0.59f, 0.59f); private static readonly Color DntColor = new(0.59f, 0.59f, 0.59f);
public static readonly HashSet<uint> KosIgnoredVictimNetIdList = new(); public static readonly HashSet<uint> KosIgnoredVictimNetIdList = [];
private static bool IsWeapon(ItemType type) => type is ItemType.GunCOM15 private static bool IsWeapon(ItemType type) => type is ItemType.GunCOM15
or ItemType.GunCOM18 or ItemType.GunCOM18
@ -53,9 +54,8 @@ public static class LogHandler
public static void LogAttackerDeathMessage(Player victim, Player attacker, AttackerDamageHandler handler, PlayerPermissions permissions, bool kosPermitted, float defaultScalar) public static void LogAttackerDeathMessage(Player victim, Player attacker, AttackerDamageHandler handler, PlayerPermissions permissions, bool kosPermitted, float defaultScalar)
{ {
var isCuffed = victim.IsDisarmed; var isCuffed = victim.IsDisarmed;
var inv = victim.ReferenceHub.inventory; var hasWeaponEquipped = IsWeapon(victim.Inventory.CurItem.TypeId);
var hasWeaponEquipped = IsWeapon(inv.CurItem.TypeId); var carriesWeapon = victim.Items.Any(item => IsWeapon(item!.Type));
var carriesWeapon = inv.UserInventory.Items.Any(item => IsWeapon(item.Value.ItemTypeId));
var victimRole = victim.Role; var victimRole = victim.Role;
var footprint = handler.Attacker; var footprint = handler.Attacker;
var attackerRole = footprint.Role; var attackerRole = footprint.Role;
@ -75,7 +75,7 @@ public static class LogHandler
private static void Log(Func<float, string> msg, bool success, PlayerPermissions playerPermissions, float defaultScalar) private static void Log(Func<float, string> msg, bool success, PlayerPermissions playerPermissions, float defaultScalar)
{ {
foreach (var p in Player.GetPlayers()) foreach (var p in Player.ReadyList)
{ {
var sender = p.ReferenceHub.queryProcessor._sender; var sender = p.ReferenceHub.queryProcessor._sender;
if (!p.RemoteAdminAccess || !PermissionsHandler.IsPermitted(sender.Permissions, playerPermissions) || ToggleLogsCommand.HiddenIdList.Contains(p.UserId)) if (!p.RemoteAdminAccess || !PermissionsHandler.IsPermitted(sender.Permissions, playerPermissions) || ToggleLogsCommand.HiddenIdList.Contains(p.UserId))
@ -93,7 +93,7 @@ public static class LogHandler
private static object GetKillerStatus(Player attacker, float sizeScalar) private static object GetKillerStatus(Player attacker, float sizeScalar)
{ {
var role = attacker.Rm().CurrentRole; var role = attacker.RoleBase;
return GetIdWithDnt(attacker, sizeScalar) return GetIdWithDnt(attacker, sizeScalar)
+ " " + " "
+ role.RoleName.Color(role.RoleColor.ToHex(true, false)).Size(35.Scale(sizeScalar)) + role.RoleName.Color(role.RoleColor.ToHex(true, false)).Size(35.Scale(sizeScalar))
@ -102,7 +102,7 @@ public static class LogHandler
private static object GetVictimStatus(Player victim, float sizeScalar) private static object GetVictimStatus(Player victim, float sizeScalar)
{ {
var role = victim.Rm().CurrentRole; var role = victim.RoleBase;
return GetIdWithDnt(victim, sizeScalar).Size(25.Scale(sizeScalar)) return GetIdWithDnt(victim, sizeScalar).Size(25.Scale(sizeScalar))
+ " " + " "
+ role.RoleName.Color(role.RoleColor.ToHex(true, false)).Size(35.Scale(sizeScalar)) + role.RoleName.Color(role.RoleColor.ToHex(true, false)).Size(35.Scale(sizeScalar))
@ -125,6 +125,7 @@ public static class LogHandler
Scp018DamageHandler => $"{{0}} killed {{1}} with {"SCP-018".Bold().Color(Lime).Size(35.Scale(sizeScalar))}", Scp018DamageHandler => $"{{0}} killed {{1}} with {"SCP-018".Bold().Color(Lime).Size(35.Scale(sizeScalar))}",
DisruptorDamageHandler => $"{{0}} killed {{1}} with the {"3-X Particle Disruptor".Bold().Color(Lime).Size(35.Scale(sizeScalar))}", DisruptorDamageHandler => $"{{0}} killed {{1}} with the {"3-X Particle Disruptor".Bold().Color(Lime).Size(35.Scale(sizeScalar))}",
JailbirdDamageHandler => $"{{0}} killed {{1}} with the {"Jailbird".Bold().Color(Lime).Size(35.Scale(sizeScalar))}", JailbirdDamageHandler => $"{{0}} killed {{1}} with the {"Jailbird".Bold().Color(Lime).Size(35.Scale(sizeScalar))}",
Scp3114DamageHandler scp3114 => $"{{0}} killed {{1}} with {scp3114.Subtype.ToString().Bold().Color(Lime).Size(35.Scale(sizeScalar))}",
_ => $"{{0}} killed {{1}}. {"Reason is unknown".Italic().Color(Lime)}" _ => $"{{0}} killed {{1}}. {"Reason is unknown".Italic().Color(Lime)}"
} }
+ WeaponStatusMessage(!scpAttacker, hasWeaponEquipped, carriesWeapon, sizeScalar); + WeaponStatusMessage(!scpAttacker, hasWeaponEquipped, carriesWeapon, sizeScalar);
@ -132,8 +133,8 @@ public static class LogHandler
private static string WeaponStatusMessage(bool show, bool hasWeaponEquipped, bool carriesWeapon, float sizeScalar) => private static string WeaponStatusMessage(bool show, bool hasWeaponEquipped, bool carriesWeapon, float sizeScalar) =>
show && (carriesWeapon || hasWeaponEquipped) show && (carriesWeapon || hasWeaponEquipped)
? (hasWeaponEquipped ? (hasWeaponEquipped
? " Victim was " + "holding".Underline() + " a weapon." ? " Victim was " + "holding".Underline() + " a weapon"
: " Victim had a weapon " + "in their inventory.".Underline() : " Victim had a weapon " + "in their inventory".Underline()
).Color(Cyan).Size(30.Scale(sizeScalar)) ).Color(Cyan).Size(30.Scale(sizeScalar))
: ""; : "";
@ -157,7 +158,7 @@ public static class LogHandler
_ => "[an unknown attack type]" _ => "[an unknown attack type]"
}; };
private static string GetScp939AttackType(Scp939DamageHandler scp939) => scp939._damageType switch private static string GetScp939AttackType(Scp939DamageHandler scp939) => scp939.Scp939DamageType switch
{ {
Scp939DamageType.Claw => nameof(Scp939DamageType.Claw), Scp939DamageType.Claw => nameof(Scp939DamageType.Claw),
Scp939DamageType.LungeSecondary => "Lunge Secondary", Scp939DamageType.LungeSecondary => "Lunge Secondary",
@ -165,10 +166,18 @@ public static class LogHandler
_ => "[an unknown attack type]" _ => "[an unknown attack type]"
}; };
public static void LogLeavingScp(string role, float health, float hs, PlayerPermissions permissions, float defaultScalar) => public static void LogLeavingScp(string role, float health, float hs, PlayerPermissions permissions, float defaultScalar)
Log(sizeScalar => $"{"SCP Left".Color("red").Bold()}#Please replace {role.Size(40.Scale(sizeScalar))} as the player has left the game.\n" + => Log(sizeScalar => $"{"SCP Left".Color("red").Bold()}#Please replace {role.Size(40.Scale(sizeScalar))} as the player has left the game.\n" +
($"HP: {((int) health).ToString().Color("red")} " + ($"HP: {((int) health).ToString().Color("red")} " +
$"HS: {((int) hs).ToString().Color("purple")}").Size(35.Scale(sizeScalar)), false, permissions, defaultScalar); $"HS: {((int) hs).ToString().Color("purple")}").Size(35.Scale(sizeScalar)), false, permissions, defaultScalar);
public static void LogDetain(Player target, Player detainer, PlayerPermissions permissions, float defaultScalar)
=> Log(sizeScalar => $"{"CUFFING".Color("orange")}#{GetKillerStatus(detainer, sizeScalar)} {"detained".Color("orange").Size(30.Scale(sizeScalar))} {GetVictimStatus(target, sizeScalar)}",
true, permissions, defaultScalar);
public static void LogUnDetain(Player uncuffedPlayer, Player undetainer, PlayerPermissions permissions, float defaultScalar)
=> Log(sizeScalar => $"{"UNCUFFING".Color("red")}#{GetKillerStatus(undetainer, sizeScalar)} {"undetained".Color("red").Size(30.Scale(sizeScalar))} {GetVictimStatus(uncuffedPlayer, sizeScalar)}",
true, permissions, defaultScalar);
private static int Scale(this int number, float scalar) => (int) (number * scalar); private static int Scale(this int number, float scalar) => (int) (number * scalar);

View File

@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DeathLog")] [assembly: AssemblyProduct("DeathLog")]
[assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")] [assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyFileVersion("2.0.0.0")]

View File

@ -6,7 +6,8 @@ using RemoteAdmin;
namespace DeathLog; namespace DeathLog;
[CommandHandler(typeof(RemoteAdminCommandHandler))] [CommandHandler(typeof(RemoteAdminCommandHandler))]
public sealed class ToggleLogsCommand : ICommand { public sealed class ToggleLogsCommand : ICommand
{
public static readonly HashSet<string> HiddenIdList = new(); public static readonly HashSet<string> HiddenIdList = new();
public static readonly Dictionary<string, float> SizeScalar = new(); public static readonly Dictionary<string, float> SizeScalar = new();
@ -14,17 +15,22 @@ public sealed class ToggleLogsCommand : ICommand {
public string Command => "toggleKillLogs"; public string Command => "toggleKillLogs";
public string[] Aliases { get; } = {"tkl"}; public string[] Aliases { get; } = {"tkl"};
public string Description => "Toggles the visibility of kill logs or changes the font size scalar for the caller."; public string Description => "Toggles the visibility of kill logs or changes the font size scalar for the caller.";
public bool SanitizeResponse => false;
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response) { public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
if (sender is not PlayerCommandSender {ReferenceHub.characterClassManager.UserId: var id}) { {
if (sender is not PlayerCommandSender {ReferenceHub.authManager.UserId: var id})
{
response = "You must be a player to use this command."; response = "You must be a player to use this command.";
return false; return false;
} }
if (arguments.Count < 1) { if (arguments.Count < 1)
{
if (HiddenIdList.Add(id)) if (HiddenIdList.Add(id))
response = "You will no longer see kill logs."; response = "You will no longer see kill logs.";
else { else
{
HiddenIdList.Remove(id); HiddenIdList.Remove(id);
response = "You will now see kill logs."; response = "You will now see kill logs.";
} }
@ -32,7 +38,8 @@ public sealed class ToggleLogsCommand : ICommand {
return true; return true;
} }
switch (arguments.At(0).ToLower()) { switch (arguments.At(0).ToLower())
{
case "on" or "enable" or "true" or "yes": case "on" or "enable" or "true" or "yes":
HiddenIdList.Remove(id); HiddenIdList.Remove(id);
response = "You will now see kill logs."; response = "You will now see kill logs.";
@ -46,13 +53,16 @@ public sealed class ToggleLogsCommand : ICommand {
} }
} }
private static bool ParseScalar(ArraySegment<string> arguments, string id, out string response) { private static bool ParseScalar(ArraySegment<string> arguments, string id, out string response)
if (!float.TryParse(arguments.At(0), out var scalar)) { {
if (!float.TryParse(arguments.At(0), out var scalar))
{
response = "Invalid argument. Expected a float or a boolean."; response = "Invalid argument. Expected a float or a boolean.";
return false; return false;
} }
if (scalar is not (> 0 and <= 5)) { if (scalar is not (> 0 and <= 5))
{
response = "Invalid argument. Expected a float in range 0-5."; response = "Invalid argument. Expected a float in range 0-5.";
return false; return false;
} }

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.CodeAnalysis.Analyzers" version="2.9.8" targetFramework="net48"
developmentDependency="true"/>
<package id="Microsoft.CodeAnalysis.CSharp" version="3.3.1" targetFramework="net48"/>
<package id="Microsoft.CodeAnalysis.Common" version="3.3.1" targetFramework="net48"/>
<package id="Northwood.PluginAPI" version="13.1.0" targetFramework="net48"/>
<package id="System.Buffers" version="4.4.0" targetFramework="net48"/>
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net48"/>
<package id="System.Memory" version="4.5.3" targetFramework="net48"/>
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net48"/>
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net48"/>
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net48"/>
<package id="System.Text.Encoding.CodePages" version="4.5.1" targetFramework="net48"/>
<package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net48"/>
<package id="YamlDotNet" version="11.0.1" targetFramework="net48"/>
</packages>

19
Directory.Build.targets Normal file
View File

@ -0,0 +1,19 @@
<Project>
<Import Project="ReferencePath.props.user" Condition="Exists('ReferencePath.props.user')"/>
<PropertyGroup>
<AssemblySearchPaths>$(AssemblySearchPaths);$(ReferencePath)</AssemblySearchPaths>
</PropertyGroup>
<Target Name="NotifyIncompleteSetup" BeforeTargets="PrepareForBuild" Condition="$(ReferencePath) == ''">
<PropertyGroup>
<Template>
&lt;Project&gt;
&lt;PropertyGroup&gt;
&lt;ReferencePath&gt;&lt;/ReferencePath&gt;
&lt;/PropertyGroup&gt;
&lt;/Project&gt;
</Template>
</PropertyGroup>
<WriteLinesToFile File="../ReferencePath.props.user" Lines="$(Template)" Overwrite="false" Condition="!Exists('../ReferencePath.props.user')"/>
<Error Text="The ReferencePath property is not specified! Make sure to set the property in the ReferencePath.props.user file."/>
</Target>
</Project>