I managed to find a scuffed workaround which works perfectly. I had to change the code in the main plugin .cs file. Here's the 2 config to make it work.
Hope it helps someone.

DeathNotes.cs
// #define DEBUG
using Newtonsoft.Json;
using Oxide.Core;
using Rust;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
namespace Oxide.Plugins
{
using EnemyPrefabs = DeathNotes.RemoteConfiguration<Dictionary<string, string>>;
using WeaponPrefabs = DeathNotes.RemoteConfiguration<Dictionary<string, string>>;
using CombatEntityTypes = DeathNotes.RemoteConfiguration<Dictionary<string, DeathNotes.CombatEntityType>>;
[Info("Death Notes", "LaserHydra", "6.3.5")]
class DeathNotes : RustPlugin
{
#region Fields
private const string WildcardCharacter = "*";
private const string CanSeePermission = "deathnotes.cansee";
private static DeathNotes _instance;
private PluginConfiguration _configuration;
private readonly EnemyPrefabs _enemyPrefabs = new EnemyPrefabs("EnemyPrefabs");
private readonly WeaponPrefabs _weaponPrefabs = new WeaponPrefabs("WeaponPrefabs");
private readonly CombatEntityTypes _combatEntityTypes = new CombatEntityTypes("CombatEntityTypes");
private readonly Regex _colorTagRegex = new Regex(@"<color=.{0,7}>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private readonly Regex _sizeTagRegex = new Regex(@"<size=\d*>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private readonly List<string> _richTextLiterals = new List<string>
{
"</color>", "</size>", "<b>", "</b>", "<i>", "</i>"
};
private readonly Dictionary<ulong, AttackInfo> _previousAttack = new Dictionary<ulong, AttackInfo>();
private readonly Func<PluginConfiguration.DeathMessage, DeathData, bool>[] _messageMatchingStages =
{
(m, d) => MatchesCombatEntityType(d.KillerEntityType, m.KillerType) &&
MatchesCombatEntityType(d.VictimEntityType, m.VictimType) &&
MatchesDamageType(d.DamageType, m.DamageType),
(m, d) => MatchesCombatEntityType(d.KillerEntityType, m.KillerType) &&
MatchesCombatEntityType(d.VictimEntityType, m.VictimType) &&
m.DamageType == WildcardCharacter,
(m, d) => MatchesCombatEntityType(d.KillerEntityType, m.KillerType) &&
m.VictimType == WildcardCharacter &&
MatchesDamageType(d.DamageType, m.DamageType),
(m, d) => m.KillerType == WildcardCharacter &&
MatchesCombatEntityType(d.VictimEntityType, m.VictimType) &&
MatchesDamageType(d.DamageType, m.DamageType),
(m, d) => MatchesCombatEntityType(d.KillerEntityType, m.KillerType) &&
m.VictimType == WildcardCharacter &&
m.DamageType == WildcardCharacter,
(m, d) => m.KillerType == WildcardCharacter &&
MatchesCombatEntityType(d.VictimEntityType, m.VictimType) &&
m.DamageType == WildcardCharacter,
(m, d) => m.KillerType == WildcardCharacter &&
m.VictimType == WildcardCharacter &&
MatchesDamageType(d.DamageType, m.DamageType),
(m, d) => m.KillerType == WildcardCharacter &&
m.VictimType == WildcardCharacter &&
m.DamageType == WildcardCharacter
};
#endregion
#region Hooks
private void Init()
{
_instance = this;
permission.RegisterPermission(CanSeePermission, this);
_configuration = Config.ReadObject<PluginConfiguration>();
_configuration.LoadDefaults();
Config.WriteObject(_configuration);
_enemyPrefabs.Load();
_weaponPrefabs.Load();
_combatEntityTypes.Load();
}
private void OnEntityTakeDamage(BaseCombatEntity victimEntity, HitInfo hitInfo)
{
if (!(victimEntity is BasePlayer))
return;
// Don't track bleeding
if (victimEntity.lastDamage == DamageType.Bleeding)
return;
var userId = victimEntity.ToPlayer().userID;
_previousAttack[userId] = new AttackInfo
{
HitInfo = hitInfo,
Attacker = victimEntity.lastAttacker ?? hitInfo?.Initiator,
DamageType = victimEntity.lastDamage
};
}
private void OnEntityDeath(BaseCombatEntity victimEntity, HitInfo hitInfo)
{
// Ignore - there is no victim for some reason
if (victimEntity == null)
return;
// Try to avoid error when entity was destroyed
if (victimEntity.gameObject == null)
return;
var data = new DeathData
{
VictimEntity = victimEntity,
KillerEntity = victimEntity.lastAttacker ?? hitInfo?.Initiator,
VictimEntityType = GetCombatEntityType(victimEntity),
KillerEntityType = GetCombatEntityType(victimEntity.lastAttacker),
DamageType = victimEntity.lastDamage,
HitInfo = hitInfo
};
// Handle inconsistencies/exceptions
HandleInconsistencies(ref data);
#if DEBUG
LogDebug("[DEATHNOTES DEBUG]");
LogDebug($"VictimEntity: {data.VictimEntity?.GetType().Name ?? "NULL"} / {data.VictimEntity?.ShortPrefabName ?? "NULL"} / {data.VictimEntity?.PrefabName ?? "NULL"}");
LogDebug($"KillerEntity: {data.KillerEntity?.GetType().Name ?? "NULL"} / {data.KillerEntity?.ShortPrefabName ?? "NULL"} / {data.KillerEntity?.PrefabName ?? "NULL"}");
LogDebug($"VictimEntityType: {data.VictimEntityType}");
LogDebug($"KillerEntityType: {data.KillerEntityType}");
LogDebug($"DamageType: {data.DamageType}");
LogDebug($"Bodypart: {GetCustomizedBodypartName(data.HitInfo)}");
LogDebug($"Weapon: {hitInfo?.WeaponPrefab?.ShortPrefabName ?? "NULL"}");
#endif
// Ignore deaths of other entities
if (data.KillerEntityType == CombatEntityType.Other || data.VictimEntityType == CombatEntityType.Other)
return;
// Ignore deaths which don't involve players or the helicopter which usually does not track a player as killer
if (data.VictimEntityType != CombatEntityType.Player && data.KillerEntityType != CombatEntityType.Player && data.VictimEntityType != CombatEntityType.Helicopter)
return;
// Populate the variables in the message
string message = PopulateMessageVariables(
// Find the best matching death message for this death
GetDeathMessage(data),
data
);
if (message == null)
return;
object hookResult = Interface.Call("OnDeathNotice", data.ToDictionary(), message);
if (hookResult?.Equals(false) ?? false)
return;
if (_configuration.ShowInChat)
{
foreach (var player in BasePlayer.activePlayerList)
{
if (_configuration.RequirePermission && !permission.UserHasPermission(player.UserIDString, CanSeePermission))
continue;
if (_configuration.MessageRadius != -1 && player.Distance(data.VictimEntity) > _configuration.MessageRadius)
continue;
Player.Reply(
player,
_configuration.ChatFormat.Replace("{message}", message),
ulong.Parse(_configuration.ChatIcon)
);
}
}
if (_configuration.ShowInConsole)
Puts(StripRichText(message));
}
private void OnFlameThrowerBurn(FlameThrower flameThrower, BaseEntity baseEntity)
{
var flame = baseEntity.gameObject.AddComponent<Flame>();
flame.Source = Flame.FlameSource.Flamethrower;
flame.SourceEntity = flameThrower;
flame.Initiator = flameThrower.GetOwnerPlayer();
}
private void OnFlameExplosion(FlameExplosive explosive, BaseEntity baseEntity)
{
var flame = baseEntity.gameObject.AddComponent<Flame>();
flame.Source = Flame.FlameSource.IncendiaryProjectile;
flame.SourceEntity = explosive;
flame.Initiator = explosive.creatorEntity;
}
private void OnFireBallSpread(FireBall fireBall, BaseEntity newFire)
{
var flame = fireBall.GetComponent<Flame>();
if (flame != null)
{
var newFlame = newFire.gameObject.AddComponent<Flame>();
newFlame.Source = flame.Source;
newFlame.SourceEntity = flame.SourceEntity;
newFlame.Initiator = flame.Initiator;
}
}
private void OnFireBallDamage(FireBall fireBall, BaseCombatEntity target, HitInfo hitInfo) => hitInfo.Initiator = fireBall;
#endregion
#region Death Messages
private string GetDeathMessage(DeathData data)
{
foreach (var matchingStage in _messageMatchingStages)
{
var match = _configuration.Translations.Messages.Find(m => matchingStage.Invoke(m, data));
if (match != null)
return match.Messages.GetRandom((uint)DateTime.UtcNow.Millisecond);
}
return null;
}
private string PopulateMessageVariables(string message, DeathData data)
{
if (string.IsNullOrEmpty(message))
return null;
var replacements = new Dictionary<string, string>
{
["victim"] = GetCustomizedEntityName(data.VictimEntity, data.VictimEntityType)
};
if (data.KillerEntityType != CombatEntityType.None)
{
replacements.Add("killer", GetCustomizedEntityName(data.KillerEntity, data.KillerEntityType));
replacements.Add("bodypart", GetCustomizedBodypartName(data.HitInfo));
if (data.KillerEntity != null)
{
var distance = data.KillerEntity.Distance(data.VictimEntity);
replacements.Add("distance", GetDistance(distance, _configuration.UseMetricDistance));
}
if (data.KillerEntityType == CombatEntityType.Player)
{
replacements.Add("hp", data.KillerEntity.Health().ToString("#0.#"));
replacements.Add("weapon", GetCustomizedWeaponName(data.HitInfo));
replacements.Add("attachments", string.Join(", ", GetCustomizedAttachmentNames(data.HitInfo).ToArray()));
}
else if (data.KillerEntityType == CombatEntityType.Turret
|| data.KillerEntityType == CombatEntityType.Lock
|| data.KillerEntityType == CombatEntityType.Trap)
{
replacements.Add("owner",
covalence.Players.FindPlayerById(data.KillerEntity.OwnerID.ToString())?.Name ?? "unknown owner"
); // TODO: Work on the potential unknown owner case
}
}
message = InsertPlaceholderValues(message, replacements);
replacements = null;
return message;
}
private struct DeathData
{
public CombatEntityType VictimEntityType { get; set; }
[JsonIgnore] public BaseCombatEntity VictimEntity { get; set; }
public CombatEntityType KillerEntityType { get; set; }
[JsonIgnore] public BaseEntity KillerEntity { get; set; }
public DamageType DamageType { get; set; }
[JsonIgnore] public HitInfo HitInfo { get; set; }
public Dictionary<string, object> ToDictionary() => new Dictionary<string, object>
{
["VictimEntityType"] = VictimEntityType,
["VictimEntity"] = VictimEntity,
["KillerEntityType"] = KillerEntityType,
["KillerEntity"] = KillerEntity,
["DamageType"] = DamageType,
["HitInfo"] = HitInfo
};
}
#endregion
#region Entity Identification
private CombatEntityType GetCombatEntityType(BaseEntity entity)
{
if (entity == null)
return CombatEntityType.None;
if (_combatEntityTypes.Contents != null)
{
if (_combatEntityTypes.Contents.ContainsKey(entity.ShortPrefabName))
return _combatEntityTypes.Contents[entity.ShortPrefabName];
if (_combatEntityTypes.Contents.ContainsKey(entity.GetType().Name))
return _combatEntityTypes.Contents[entity.GetType().Name];
}
if (entity is BaseOven)
return CombatEntityType.HeatSource;
if (entity is SimpleBuildingBlock)
return CombatEntityType.ExternalWall;
if (entity is BaseAnimalNPC)
return CombatEntityType.Animal;
if (entity is BaseTrap)
return CombatEntityType.Trap;
if (entity is Barricade)
return CombatEntityType.Barricade;
if (entity is IOEntity)
return CombatEntityType.Trap;
return CombatEntityType.Other;
}
private string GetCustomizedEntityName(BaseEntity entity, CombatEntityType combatEntityType)
{
var name = GetEntityName(entity, combatEntityType);
if (string.IsNullOrEmpty(name))
return null;
// Don't load player names into config
if (combatEntityType == CombatEntityType.Player)
return name;
if (!_configuration.Translations.Names.ContainsKey(name))
{
_configuration.Translations.Names.Add(name, name);
Config.WriteObject(_configuration);
}
return _configuration.Translations.Names[name];
}
private string GetEntityName(BaseEntity entity, CombatEntityType combatEntityType)
{
// Entity may be null for helicopter or bradley, see HandleExceptions(...)
if (entity == null &&
combatEntityType != CombatEntityType.Helicopter &&
combatEntityType != CombatEntityType.Bradley)
return null;
switch (combatEntityType)
{
case CombatEntityType.Player:
return StripRichText(entity.ToPlayer().displayName);
case CombatEntityType.Helicopter:
return "Helicopter";
case CombatEntityType.Scientist:
case CombatEntityType.Murderer:
case CombatEntityType.Scarecrow:
var name = entity.ToPlayer()?.displayName;
return
string.IsNullOrEmpty(name) || name == entity.ToPlayer()?.userID.ToString()
? combatEntityType.ToString()
: name;
case CombatEntityType.Bradley:
return "Bradley APC";
case CombatEntityType.ScientistSentry:
return "Scientist Sentry";
case CombatEntityType.Fire:
return entity.creatorEntity?.ToPlayer()?.displayName ?? "Fire";
}
if (_enemyPrefabs.Contents.ContainsKey(entity.ShortPrefabName))
return _enemyPrefabs.Contents[entity.ShortPrefabName];
return HumanizePascalCase(entity.GetType().Name);
}
internal enum CombatEntityType
{
Helicopter = 0,
Bradley = 1,
Animal = 2,
Murderer = 3,
Scientist = 4,
Scarecrow = 16,
Player = 5,
Trap = 6,
Turret = 7,
Barricade = 8,
ExternalWall = 9,
HeatSource = 10,
Fire = 11,
Lock = 12,
ScientistSentry = 13,
Other = 14,
None = 15
}
#endregion
#region Workarounds and Inconsistency Handling
private void HandleInconsistencies(ref DeathData data)
{
// Deaths of other entity types are not of interest and might cause errors
if (data.VictimEntityType == CombatEntityType.Other)
return;
if (data.KillerEntity is FireBall)
data.DamageType = DamageType.Heat;
// If the killer entity is null, but a weapon is given, we might be able to fall back to the parent entity of that weapon
// Notably for the auto turret after the changes it has had
if (data.KillerEntity == null && data.HitInfo?.Weapon != null)
{
data.KillerEntity = data.HitInfo.Weapon.GetParentEntity();
data.KillerEntityType = GetCombatEntityType(data.KillerEntity);
}
// Get previous attacker when bleeding out
if (data.VictimEntityType == CombatEntityType.Player && (data.DamageType == DamageType.Bleeding || data.HitInfo == null))
{
var userId = data.VictimEntity.ToPlayer().userID;
if (_previousAttack.ContainsKey(userId))
{
var attack = _previousAttack[userId];
data.KillerEntity = attack.Attacker;
data.KillerEntityType = GetCombatEntityType(data.KillerEntity);
// Restore previous hitInfo for weapon determination
if (attack.HitInfo != null)
data.HitInfo = attack.HitInfo;
// Use previous damagetype if this is a selfinflicted death,
// so falling to death etc. is also shown when wounded and bleeding out
if (data.KillerEntity == null || data.KillerEntity == data.VictimEntity)
data.DamageType = attack.DamageType;
else
data.DamageType = DamageType.Bleeding;
}
}
if (data.KillerEntityType != CombatEntityType.None)
{
try
{
// Workaround for deaths caused by flamethrower or rocket fire
var flame = data.KillerEntity?.gameObject?.GetComponent<Flame>();
if (flame?.Initiator != null)
{
data.KillerEntity = flame.Initiator;
data.KillerEntityType = CombatEntityType.Player;
return;
}
}
catch (Exception e)
{
PrintError($"Exception while trying to access Flame component: {e}\n\nDeath Details: {JsonConvert.SerializeObject(data)}");
}
}
// Bradley kill with main cannon
if (data.HitInfo?.WeaponPrefab?.ShortPrefabName == "maincannonshell")
{
data.KillerEntityType = CombatEntityType.Bradley;
return;
}
if (data.HitInfo?.WeaponPrefab?.ShortPrefabName?.StartsWith("rocket_heli") ?? false)
{
data.KillerEntityType = CombatEntityType.Helicopter;
return;
}
}
private struct AttackInfo
{
public HitInfo HitInfo { get; set; }
public DamageType DamageType { get; set; }
public BaseEntity Attacker { get; set; }
}
private class Flame : MonoBehaviour
{
public FlameSource Source { get; set; }
public BaseEntity SourceEntity { get; set; }
public BaseEntity Initiator { get; set; }
public enum FlameSource
{
Flamethrower,
IncendiaryProjectile
}
}
#endregion
#region Weapons
private string GetCustomizedWeaponName(HitInfo hitInfo)
{
var name = GetWeaponName(hitInfo);
if (string.IsNullOrEmpty(name))
return null;
if (!_configuration.Translations.Weapons.ContainsKey(name))
{
_configuration.Translations.Weapons.Add(name, name);
Config.WriteObject(_configuration);
}
return _configuration.Translations.Weapons[name];
}
private string GetWeaponName(HitInfo hitInfo)
{
if (hitInfo == null)
return null;
Item item = hitInfo.Weapon?.GetItem();
/*var parentEntity = hitInfo.Weapon?.GetParentEntity();
Item item = null;
if (parentEntity is BasePlayer)
{
(parentEntity as BasePlayer).inventory.FindItemUID(hitInfo.Weapon.ownerItemUID);
}
else if (parentEntity is ContainerIOEntity)
{
(parentEntity as ContainerIOEntity).inventory.FindItemByUID(hitInfo.Weapon.ownerItemUID);
}*/
if (item != null)
return item.info.displayName.english;
var prefab = hitInfo.Initiator?.GetComponent<Flame>()?.SourceEntity?.ShortPrefabName ??
hitInfo.WeaponPrefab?.ShortPrefabName;
if (prefab != null)
{
if (_weaponPrefabs.Contents.ContainsKey(prefab))
return _weaponPrefabs.Contents[prefab];
return prefab;
}
return null;
}
private List<string> GetCustomizedAttachmentNames(HitInfo info)
{
var items = info?.Weapon?.GetItem()?.contents?.itemList;
if (items == null)
return new List<string>();
return items.Select(i => GetCustomizedAttachmentName(i.info.displayName.english)).ToList();
}
private string GetCustomizedAttachmentName(string name)
{
if (!_configuration.Translations.Attachments.ContainsKey(name))
{
_configuration.Translations.Attachments.Add(name, name);
Config.WriteObject(_configuration);
}
return _configuration.Translations.Attachments[name];
}
#endregion
#region Bodyparts
private string GetCustomizedBodypartName(HitInfo hitInfo)
{
var name = GetBodypartName(hitInfo);
if (string.IsNullOrEmpty(name))
return null;
if (!_configuration.Translations.Bodyparts.ContainsKey(name))
{
_configuration.Translations.Bodyparts.Add(name, name);
Config.WriteObject(_configuration);
}
return _configuration.Translations.Bodyparts[name];
}
private string GetBodypartName(HitInfo hitInfo)
{
var hitArea = hitInfo?.boneArea ?? (HitArea)(-1);
return (int)hitArea == -1 ? "Body" : hitArea.ToString();
}
#endregion
#region Helper
#if DEBUG
private static void LogDebug(string text)
{
if (BasePlayer.activePlayerList.Count >= 1)
{
BasePlayer.activePlayerList[0].ConsoleMessage($"<color=orange>{text}</color>");
}
}
#endif
private static string GetDistance(float meters, bool useMetric)
{
double value = Math.Round(useMetric ? meters : meters * 3.28f, 1);
string unit = value == 1
? _instance.lang.GetMessage("Distance Unit Singular", _instance)
: _instance.lang.GetMessage("Distance Unit Plural", _instance);
return $"{value} {unit}";
}
private static string ApplyVariableFormat(string text, string variableName)
{
if (_instance._configuration.VariableFormats.ContainsKey(variableName))
{
var format = _instance._configuration.VariableFormats[variableName];
text = format.Replace("{value}", text);
}
return text;
}
private static string InsertPlaceholderValues(string text, Dictionary<string, string> values)
{
foreach (var kvp in values)
{
string value = ApplyVariableFormat(kvp.Value, kvp.Key);
if (string.IsNullOrEmpty(kvp.Value))
{
text = text.Replace($"{{{kvp.Key}}}", string.Empty);
}
else if (_instance._configuration.VariableColors.ContainsKey(kvp.Key))
{
var color = _instance._configuration.VariableColors[kvp.Key];
text = text.Replace($"{{{kvp.Key}}}", $"{color}{value}");
color = null;
}
else
{
text = text.Replace($"{{{kvp.Key}}}", value);
}
}
return text;
}
private static string HumanizePascalCase(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
var sb = new StringBuilder();
foreach (char c in text)
{
if (char.IsUpper(c) && sb.Length != 0 && !char.IsUpper(sb[sb.Length - 1]))
sb.Append(" ");
sb.Append(c);
}
return sb.ToString();
}
private string StripRichText(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
text = _colorTagRegex.Replace(text, string.Empty);
text = _sizeTagRegex.Replace(text, string.Empty);
foreach (var richTextLiteral in _richTextLiterals)
text = text.Replace(richTextLiteral, string.Empty, StringComparison.InvariantCulture);
return text;
}
private static bool MatchesCombatEntityType(CombatEntityType combatEntityType, string text)
{
if (combatEntityType == CombatEntityType.None && text == "-")
return true;
return combatEntityType.ToString().Equals(text, StringComparison.InvariantCulture);
}
private static bool MatchesDamageType(DamageType damageType, string text)
{
return damageType.ToString().Equals(text, StringComparison.InvariantCulture);
}
#endregion
#region Configuration
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Distance Unit Singular"] = "meter",
["Distance Unit Plural"] = "meters"
}, this);
}
protected override void LoadDefaultConfig() => PrintWarning("Generating new configuration file...");
private sealed class PluginConfiguration
{
[JsonProperty("Translations")]
public Translation Translations = new Translation();
[JsonProperty("Variable Formats")]
public Dictionary<string, string> VariableFormats = new Dictionary<string, string>
{
["attachments"] = " ({value})"
};
[JsonProperty("Variable Colors")]
public Dictionary<string, string> VariableColors = new Dictionary<string, string>
{
["killer"] = "#C4FF00",
["victim"] = "#C4FF00",
["weapon"] = "#C4FF00",
["attachments"] = "#C4FF00",
["distance"] = "#C4FF00",
["owner"] = "#C4FF00"
};
[JsonProperty("Chat Format")]
public string ChatFormat = "<color=#838383>[<color=#80D000>DeathNotes</color>] {message}</color>";
[JsonProperty("Chat Icon (SteamID)")]
public string ChatIcon = "76561############";
[JsonProperty("Show Kills in Console")]
public bool ShowInConsole = true;
[JsonProperty("Show Kills in Chat")]
public bool ShowInChat = true;
[JsonProperty("Message Broadcast Radius (in meters)")]
public int MessageRadius = -1;
[JsonProperty("Use Metric Distance")]
public bool UseMetricDistance = true;
[JsonProperty("Require Permission (deathnotes.cansee)")]
public bool RequirePermission = false;
public void LoadDefaults()
{
if (Translations.Messages == null)
{
var defaults = new RemoteConfiguration<List<DeathMessage>>("DefaultMessages");
defaults.Load(success =>
{
if (success)
{
Translations.Messages = defaults.Contents;
_instance.Config.WriteObject(this);
}
});
}
}
public class DeathMessage
{
public string KillerType { get; set; }
public string VictimType { get; set; }
public string DamageType { get; set; }
public string[] Messages { get; set; }
protected bool Equals(DeathMessage other) => string.Equals(KillerType, other.KillerType) &&
string.Equals(VictimType, other.VictimType) &&
string.Equals(DamageType, other.DamageType);
}
public class Translation
{
[JsonProperty("Death Messages")]
public List<DeathMessage> Messages;
[JsonProperty("Names")]
public Dictionary<string, string> Names = new Dictionary<string, string>();
[JsonProperty("Bodyparts")]
public Dictionary<string, string> Bodyparts = new Dictionary<string, string>();
[JsonProperty("Weapons")]
public Dictionary<string, string> Weapons = new Dictionary<string, string>();
[JsonProperty("Attachments")]
public Dictionary<string, string> Attachments = new Dictionary<string, string>();
}
}
internal sealed class RemoteConfiguration<T>
{
private const string Host = "http://files.laserhydra.com/config/DeathNotes/";
private readonly string _file;
public RemoteConfiguration(string file)
{
_file = file;
}
public T Contents { get; private set; }
private string ExactUrl => Host + _file;
public void Load(Action<bool> callback = null)
{
_instance.webrequest.Enqueue(ExactUrl, string.Empty, (code, response) =>
{
try
{
if (!IsSuccessStatusCode(code))
throw new Exception($"Status code indicates failure. Code: {code}");
Contents = JsonConvert.DeserializeObject<T>(response);
callback?.Invoke(true);
Interface.Oxide.DataFileSystem.WriteObject($"{nameof(DeathNotes)}/{_file}", Contents);
}
catch (Exception ex)
{
if (Interface.Oxide.DataFileSystem.ExistsDatafile($"{nameof(DeathNotes)}/{_file}"))
{
Contents = Interface.Oxide.DataFileSystem.ReadObject<T>($"{nameof(DeathNotes)}/{_file}");
_instance.PrintWarning($"Could not load remote config '{_file}'. The plugin will be using the previously downloaded file.");
callback?.Invoke(true);
}
else
{
_instance.PrintError($"Could not load remote config '{_file}'. The plugin will not work properly. Please check whether you can access {ExactUrl} via your browser. If you can, please check the FAQ on how to solve this.");
_instance.PrintError($"[Code {code}] {ex.GetType().Name}: {ex.Message}");
_instance.PrintError($"Response: {response}");
callback?.Invoke(false);
}
}
}, _instance);
}
private bool IsSuccessStatusCode(int code) => code >= 200 && code < 300;
}
#endregion
}
}
DeathNote.json
{
"Translations": {
"Death Messages": [
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{killer}</color> killed <color=#55aaff>{victim}</color> in the <color=#cf0000>{bodypart}</color> using a <color=#C4FF00>{weapon}</color>."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Bullet",
"Messages": [
"<color=#55aaff>{killer}</color> shot <color=#55aaff>{victim}</color> in the <color=#cf0000>{bodypart}</color> using a <color=#C4FF00>{weapon}</color> over a distance of <color=#C4FF00>{distance}</color>."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Slash",
"Messages": [
"<color=#55aaff>{victim}</color> was slashed to death by <color=#55aaff>{killer}</color>'s <color=#C4FF00>{weapon}</color>.",
"<color=#55aaff>{killer}</color> slashed <color=#55aaff>{victim}</color> into pieces with their <color=#C4FF00>{weapon}</color>."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Blunt",
"Messages": [
"<color=#cf0000>{victim}</color> was beaten to death with <color=#55aaff>{killer}</color>'s <color=#C4FF00>{weapon}</color>.",
"<color=#55aaff>{killer}</color> killed <color=#55aaff>{victim}</color> by blunt force trauma.",
"<color=#55aaff>{killer}</color> pummeled <color=#55aaff>{victim}</color> to death with a <color=#C4FF00>{weapon}</color>."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Stab",
"Messages": [
"<color=#55aaff>{victim}</color> was stabbed to death with <color=#55aaff>{killer}</color>'s <color=#C4FF00>{weapon}</color>."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Arrow",
"Messages": [
"<color=#55aaff>{victim}</color> was impaled by <color=#55aaff>{killer}</color>'s arrow in the <color=#cf0000>{bodypart}</color> over a distance of <color=#C4FF00>{distance}</color>.",
"<color=#55aaff>{killer}</color> speared <color=#55aaff>{victim}</color> with an arrow in the <color=#cf0000>{bodypart}</color> over a distance of <color=#C4FF00>{distance}</color>."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Heat",
"Messages": [
"<color=#55aaff>{killer}</color> inflamed <color=#55aaff>{victim}</color> with their <color=#C4FF00>{weapon}</color>.",
"<color=#55aaff>{victim}</color> burst into flames from <color=#55aaff>{killer}</color>'s <color=#C4FF00>{weapon}</color>"
]
},
{
"KillerType": "Player",
"VictimType": "Bradley",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{killer}</color> blew up the <color=#cf0000>{victim}</color> with their <color=#C4FF00>{weapon}</color>."
]
},
{
"KillerType": "*",
"VictimType": "Helicopter",
"DamageType": "*",
"Messages": [
"The <color=#cf0000>{victim}</color> was finally shot down by <color=#cf0000>{killer}</color>'s <color=#C4FF00>{weapon}</color> from a distance of <color=#C4FF00>{distance}</color>."
]
},
{
"KillerType": "Murderer",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"A <color=#cf0000>{killer}</color> hunted down <color=#55aaff>{victim}</color>."
]
},
{
"KillerType": "Murderer",
"VictimType": "Player",
"DamageType": "Bullet",
"Messages": [
"A <color=#cf0000>{killer}</color> shot <color=#55aaff>{victim}</color> in the <color=#cf0000>{bodypart}</color> from a distance of <color=#C4FF00>{distance}</color>."
]
},
{
"KillerType": "Murderer",
"VictimType": "Player",
"DamageType": "Slash",
"Messages": [
"<color=#55aaff>{victim}</color> was slashed to death by <color=#cf0000>{killer}</color>."
]
},
{
"KillerType": "Murderer",
"VictimType": "Player",
"DamageType": "Stab",
"Messages": [
"<color=#55aaff>{victim}</color> was stabbed to death by <color=#cf0000>{killer}</color>."
]
},
{
"KillerType": "Scientist",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"Scientist <color=#cf0000>{killer}</color> shot <color=#55aaff>{victim}</color> in the <color=#cf0000>{bodypart}</color> from a distance of <color=#C4FF00>{distance}</color>."
]
},
{
"KillerType": "ScientistSentry",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> did not did not follow the rules in a safezone and was killed by <color=#cf0000>{killer}</color>."
]
},
{
"KillerType": "Animal",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> couldn't run away from the <color=#cf0000>{killer}</color>.",
"<color=#55aaff>{victim}</color> got mangled by a <color=#cf0000>{killer}</color>.",
"<color=#55aaff>{victim}</color> got maimed by a <color=#cf0000>{killer}</color>.",
"A <color=#cf0000>{killer}</color> snuck up on <color=#55aaff>{victim}</color> and killed them."
]
},
{
"KillerType": "Bradley",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> was shredded by the <color=#cf0000>{killer}</color>.",
"<color=#55aaff>{victim}</color> got messed up by the <color=#cf0000>{killer}</color>.",
"<color=#55aaff>{victim}</color> was shot down by the <color=#cf0000>{killer}</color>."
]
},
{
"KillerType": "Helicopter",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#cf0000>{victim}</color> had no chance against the <color=#cf0000>{killer}</color>.",
"<color=#cf0000>{victim}</color> got messed up by the <color=#cf0000>{killer}</color>.",
"<color=#cf0000>{victim}</color> was shot down by the <color=#cf0000>{killer}</color>."
]
},
{
"KillerType": "Trap",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> was uncautious and ran into <color=#55aaff>{owner}</color>'s <color=#cf0000>{killer}</color>.",
"<color=#55aaff>{victim}</color> got caught up in <color=#55aaff>{owner}</color>'s <color=#cf0000>{killer}</color>.",
"<color=#55aaff>{owner}</color>'s <color=#cf0000>{killer}</color> did it's job and killed <color=#55aaff>{victim}</color>."
]
},
{
"KillerType": "Barricade",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> was impaled by a <color=#cf0000>{killer}</color>."
]
},
{
"KillerType": "Turret",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> was shot down by <color=#55aaff>{owner}</color>'s <color=#cf0000>{killer}</color> from a distance of <color=#C4FF00>{distance}</color>.",
"<color=#55aaff>{owner}</color>'s <color=#cf0000>{killer}</color> took down <color=#55aaff>{victim}</color> from a distance of <color=#C4FF00>{distance}</color>.",
"<color=#55aaff>{owner}</color>'s <color=#cf0000>{killer}</color> did it's job and shot <color=#55aaff>{victim}</color> from a distance of <color=#C4FF00>{distance}</color>."
]
},
{
"KillerType": "ScientistSentry",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> did not did not follow the rules in a safezone and was killed by a <color=#cf0000>{killer}</color>."
]
},
{
"KillerType": "-",
"VictimType": "Player",
"DamageType": "Fall",
"Messages": [
"<color=#55aaff>{victim}</color> fell to their death."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Suicide",
"Messages": [
"<color=#55aaff>{victim}</color> had enough of life.",
"<color=#55aaff>{victim}</color> committed suicide.",
"<color=#55aaff>{victim}</color> died. No-one knows why.",
"<color=#55aaff>{victim}</color> decided that life wasn't worth living.",
"<color=#55aaff>{victim}</color> committed suicide - RIP."
]
},
{
"KillerType": "HeatSource",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> was grilled on a <color=#55aaff>{killer}</color>.",
"<color=#55aaff>{victim}</color> burned to death.",
"<color=#55aaff>{victim}</color> was burned to a cinder."
]
},
{
"KillerType": "Lock",
"VictimType": "Player",
"DamageType": "*",
"Messages": [
"<color=#55aaff>{victim}</color> was electrocuted by <color=#55aaff>{owner}</color>'s <color=#55aaff>{killer}</color>."
]
},
{
"KillerType": "*",
"VictimType": "Player",
"DamageType": "Heat",
"Messages": [
"<color=#55aaff>{victim}</color> burned to death.",
"<color=#55aaff>{victim}</color> got hot... WAY too hot.",
"<color=#55aaff>{victim}</color> was burned to a cinder."
]
},
{
"KillerType": "*",
"VictimType": "Player",
"DamageType": "Radiation",
"Messages": [
"<color=#55aaff>{victim}</color> became just a touch too radioactive.",
"<color=#55aaff>{victim}</color> died from radiation poisoning."
]
},
{
"KillerType": "*",
"VictimType": "Player",
"DamageType": "Cold",
"Messages": [
"<color=#55aaff>{victim}</color> turned into an ice statue.",
"<color=#55aaff>{victim}</color> froze to death."
]
},
{
"KillerType": "*",
"VictimType": "Player",
"DamageType": "Drowned",
"Messages": [
"As <color=#55aaff>{victim}</color> just found out, breathing underwater is rather difficult.",
"<color=#55aaff>{victim}</color> drowned.",
"<color=#55aaff>{victim}</color> is swimming with the fishes."
]
},
{
"KillerType": "Player",
"VictimType": "Player",
"DamageType": "Bleeding",
"Messages": [
"<color=#55aaff>{victim}</color> bled out after being attacked by <color=#55aaff>{killer}</color>."
]
}
],
"Names": {
"Wolf": "Wolf",
"Zombie": "Zombie",
"Boar": "Boar",
"Chicken": "Chicken",
"Auto Turret": "Auto Turret",
"Snap Trap": "Snap Trap",
"Wooden Barricade": "Wooden Barricade",
"Wooden Floor Spikes": "Wooden Floor Spikes",
"Stag": "Stag",
"Land Mine": "Land Mine",
"High External Stone Wall": "High External Stone Wall",
"High External Wooden Wall": "High External Wooden Wall",
"Metal Barricade": "Metal Barricade",
"No Attacker": "Meteor",
"Murderer": "Murderer",
"Scientist": "Scientist",
"Horse": "Horse",
"Barricade": "Barricade",
"Bradley APC": "Bradley APC",
"Flame Turret": "Flame Turret",
"Code Lock": "Code Lock",
"Gun Trap": "Gun Trap",
"Campfire": "Campfire",
"Bear Trap": "Bear Trap",
"F. Salazar": "F. Salazar",
"S. Ballard": "S. Ballard",
"Scientist Mariano": "Scientist Mariano",
"Scientist Lakeshia": "Scientist Lakeshia",
"Scientist Ines": "Scientist Ines",
"Scientist Shawnta": "Scientist Shawnta",
"Bear": "Bear",
"H. Morales": "H. Morales",
"Lashell": "Lashell",
"Renna": "Renna",
"Darryl": "Darryl",
"Philomena": "Philomena",
"Refugia": "Refugia",
"Katina": "Katina",
"Rona": "Rona",
"Ettie": "Ettie",
"Lianne": "Lianne",
"Cesar": "Cesar",
"Johnetta": "Johnetta",
"Rachell": "Rachell",
"Jesica": "Jesica",
"Vivienne": "Vivienne",
"Reina": "Reina",
"Ginette": "Ginette",
"Mahalia": "Mahalia",
"Elly": "Elly",
"Priscila": "Priscila",
"Nydia": "Nydia",
"Roxie": "Roxie",
"Gladys": "Gladys",
"A. Sandoval": "A. Sandoval",
"B. Franklin": "B. Franklin",
"L. Smith": "L. Smith",
"H. Mack": "H. Mack",
"F. Hodges": "F. Hodges",
"J. Mathis": "J. Mathis",
"L. Cruz": "L. Cruz",
"A. Wise": "A. Wise",
"M. Bates": "M. Bates",
"B. Howell": "B. Howell",
"P. Hopkins": "P. Hopkins",
"X. Moody": "X. Moody",
"O. Hale": "O. Hale",
"A. Blake": "A. Blake",
"J. Byrd": "J. Byrd",
"S. Gordon": "S. Gordon",
"Willis": "Willis",
"Neomi": "Neomi",
"Barabara": "Barabara",
"Clemencia": "Clemencia",
"Eilene": "Eilene",
"Tiffiny": "Tiffiny",
"Ramiro": "Ramiro",
"Claude": "Claude",
"Paola": "Paola",
"Josie": "Josie",
"Angelena": "Angelena"
},
"Bodyparts": {
"Body": "Body",
"Chest": "Chest",
"Groin": "Groin",
"Head": "Head",
"Head2": "Head2",
"Hip": "Hip",
"Horse_RootBone": "Horse_RootBone",
"Jaw": "Jaw",
"Jaw_END": "Jaw_END",
"Joint32": "Joint32",
"Joint35": "Joint35",
"Joint40": "Joint40",
"L_ear": "L_ear",
"L_Fore_Foot": "L_Fore_Foot",
"L_Fore_Shin": "L_Fore_Shin",
"L_Fore_Thigh": "L_Fore_Thigh",
"L_Hip": "L_Hip",
"L_Rear_Foot": "L_Rear_Foot",
"L_Rear_Foot_END": "L_Rear_Foot_END",
"L_Rear_Shin": "L_Rear_Shin",
"L_Rear_Thigh": "L_Rear_Thigh",
"L_Shoulder": "L_Shoulder",
"Left Arm": "Left Arm",
"Left Foot": "Left Foot",
"Left Forearm": "Left Forearm",
"Left Hand": "Left Hand",
"Left Knee": "Left Knee",
"Left Ring Finger": "Left Ring Finger",
"Left Shoulder": "Left Shoulder",
"Left Thumb": "Left Thumb",
"Left Toe": "Left Toe",
"Left_calf": "Left_calf",
"Left_Calf": "Left_Calf",
"Left_ear": "Left_ear",
"Left_Ear": "Left_Ear",
"Left_Ear_END": "Left_Ear_END",
"Left_Finger": "Left_Finger",
"Left_fingers": "Left_fingers",
"Left_Fingers": "Left_Fingers",
"Left_foot": "Left_foot",
"Left_Foot": "Left_Foot",
"Left_forearm": "Left_forearm",
"Left_Forearm": "Left_Forearm",
"Left_ForeArm": "Left_ForeArm",
"Left_Hand": "Left_Hand",
"Left_Pelvis": "Left_Pelvis",
"Left_Shoulder": "Left_Shoulder",
"Left_thigh": "Left_thigh",
"Left_Thigh": "Left_Thigh",
"Left_Thigh_FatEND": "Left_Thigh_FatEND",
"Left_Toe": "Left_Toe",
"Left_Toes": "Left_Toes",
"Left_ulna": "Left_ulna",
"Left_Ulna": "Left_Ulna",
"Left_Upper_Thigh": "Left_Upper_Thigh",
"Left_upperarm": "Left_upperarm",
"Left_UpperArm": "Left_UpperArm",
"Lip_lower_END": "Lip_lower_END",
"Lower Spine": "Lower Spine",
"Lower_jaw": "Lower_jaw",
"Mane_5a": "Mane_5a",
"Neck": "Neck",
"Neck_1": "Neck_1",
"Neck_2": "Neck_2",
"Neck_3": "Neck_3",
"Neck_expander_1": "Neck_expander_1",
"Neck1": "Neck1",
"Neck2": "Neck2",
"Neck3": "Neck3",
"Pelvis": "Pelvis",
"R_ear": "R_ear",
"R_Fore_Foot": "R_Fore_Foot",
"R_Fore_Shin": "R_Fore_Shin",
"R_Fore_Thigh": "R_Fore_Thigh",
"R_Hip": "R_Hip",
"R_Rear_Foot": "R_Rear_Foot",
"R_Rear_Shin": "R_Rear_Shin",
"R_Rear_Thigh": "R_Rear_Thigh",
"R_Shoulder": "R_Shoulder",
"Right Arm": "Right Arm",
"Right Foot": "Right Foot",
"Right Forearm": "Right Forearm",
"Right Hand": "Right Hand",
"Right Knee": "Right Knee",
"Right Ring Finger": "Right Ring Finger",
"Right Shoulder": "Right Shoulder",
"Right Thumb": "Right Thumb",
"Right Toe": "Right Toe",
"Right_calf": "Right_calf",
"Right_Calf": "Right_Calf",
"Right_ear": "Right_ear",
"Right_fingers": "Right_fingers",
"Right_Fingers": "Right_Fingers",
"Right_foot": "Right_foot",
"Right_Foot": "Right_Foot",
"Right_forearm": "Right_forearm",
"Right_Forearm": "Right_Forearm",
"Right_ForeArm": "Right_ForeArm",
"Right_hand": "Right_hand",
"Right_Hand": "Right_Hand",
"Right_Pelvis": "Right_Pelvis",
"Right_Shoulder": "Right_Shoulder",
"Right_thigh": "Right_thigh",
"Right_Thigh": "Right_Thigh",
"Right_Toe": "Right_Toe",
"Right_toes": "Right_toes",
"Right_Toes": "Right_Toes",
"Right_ulna": "Right_ulna",
"Right_Ulna": "Right_Ulna",
"Right_Upper_Thigh": "Right_Upper_Thigh",
"Right_upperarm": "Right_upperarm",
"Right_UpperArm": "Right_UpperArm",
"Spine_2": "Spine_2",
"Spine_3": "Spine_3",
"Spine_4": "Spine_4",
"Spine_End": "Spine_End",
"Spine_END": "Spine_END",
"Spine1": "Spine1",
"Spine1_FatEnd": "Spine1_FatEnd",
"Spine2": "Spine2",
"Spine3": "Spine3",
"Spine4": "Spine4",
"Stomach": "Stomach",
"Stomache_expander_1": "Stomache_expander_1",
"Stomache_expander_2": "Stomache_expander_2",
"Tail": "Tail",
"Tail_1": "Tail_1",
"Tail_Eff": "Tail_Eff",
"Tail1": "Tail1",
"Tail2": "Tail2",
"Tail3": "Tail3",
"Tail4": "Tail4",
"Tail5": "Tail5",
"Tongue_END": "Tongue_END",
"Arm": "Arm",
"Leg": "Leg",
"Hand": "Hand",
"Foot": "Foot"
},
"Weapons": {
"Ak47u": "Ak47u",
"Assault Rifle": "Assault Rifle",
"Beancan Grenade": "Beancan Grenade",
"Bolt Action Rifle": "Bolt Action Rifle",
"Bone Knife": "Bone Knife",
"Chainsaw": "Chainsaw",
"Crossbow": "Crossbow",
"Custom SMG": "Custom SMG",
"Double Barrel Shotgun": "Double Barrel Shotgun",
"Eoka Pistol": "Eoka Pistol",
"Explosivesatchel": "Explosivesatchel",
"F1 Grenade": "F1 Grenade",
"Flamethrower": "Flamethrower",
"Flameturret": "Flameturret",
"Hatchet": "Hatchet",
"Hunting Bow": "Hunting Bow",
"Landmine": "Landmine",
"Longsword": "Longsword",
"LR-300 Assault Rifle": "LR-300 Assault Rifle",
"M249": "M249",
"M92 Pistol": "M92 Pistol",
"Mace": "Mace",
"Machete": "Machete",
"MP5A4": "MP5A4",
"Nailgun": "Nailgun",
"No Weapon": "Assault rifle",
"Pick Axe": "Pick Axe",
"Pickaxe": "Pickaxe",
"Pump Shotgun": "Pump Shotgun",
"Python Revolver": "Python Revolver",
"Revolver": "Revolver",
"Rocket Basic": "Rocket Basic",
"Rocket Fire": "Rocket Fire",
"Rocket Heli": "Rocket Heli",
"Rocket Hv": "Rocket Hv",
"Rocket Smoke": "Rocket Smoke",
"Salvaged Axe": "Salvaged Axe",
"Salvaged Cleaver": "Salvaged Cleaver",
"Salvaged Hammer": "Salvaged Hammer",
"Salvaged Icepick": "Salvaged Icepick",
"Semi-Automatic Pistol": "Semi-Automatic Pistol",
"Semi-Automatic Rifle": "Semi-Automatic Rifle",
"Shotgun Pump": "Shotgun Pump",
"Shotgun Waterpipe": "Shotgun Waterpipe",
"Spas-12 Shotgun": "Spas-12 Shotgun",
"Stone Hatchet": "Stone Hatchet",
"Stone Pick Axe": "Stone Pick Axe",
"Stone Pickaxe": "Stone Pickaxe",
"Stone Spear": "Stone Spear",
"Survey Charge": "Survey Charge",
"Thompson": "Thompson",
"Timed Explosive": "Timed Explosive",
"Waterpipe Shotgun": "Waterpipe Shotgun",
"Wooden Spear": "Wooden Spear",
"Incendiary Rocket": "Incendiary Rocket",
"Flame Thrower": "Flame Thrower",
"Rocket": "Rocket",
"Salvaged Sword": "Salvaged Sword",
"High Velocity Rocket": "High Velocity Rocket",
"hatchet.entity": "hatchet.entity",
"Satchel Charge": "Satchel Charge",
"Compound Bow": "Compound Bow",
"L96 Rifle": "L96 Rifle",
"bow_hunting.entity": "bow_hunting.entity",
"Candy Cane Club": "Candy Cane Club",
"M39 Rifle": "M39 Rifle",
"pickaxe.entity": "pickaxe.entity",
"Rock": "Rock",
"Timed Explosive Charge": "Timed Explosive Charge"
},
"Attachments": {
"Weapon flashlight": "Weapon flashlight",
"Holosight": "Holosight",
"4x Zoom Scope": "4x Zoom Scope",
"Weapon Lasersight": "Weapon Lasersight",
"Silencer": "Silencer",
"Muzzle Brake": "Muzzle Brake",
"Muzzle Boost": "Muzzle Boost",
"Simple Handmade Sight": "Simple Handmade Sight",
"8x Zoom Scope": "8x Zoom Scope",
"16x Zoom Scope": "16x Zoom Scope"
}
},
"Variable Formats": {
"attachments": " ({value})",
"Attachments Formatting": " ({attachments})",
"Attachments Split": " | "
},
"Variable Colors": {
"killer": "",
"victim": "",
"weapon": "",
"attachments": "",
"distance": "",
"owner": "",
"Bodyparts": ""
},
"Chat Format": "<color=#b0b0b0>[<color=#80D000>DeathNotes</color>] {message}</color>",
"Chat Icon (SteamID)": "76561############",
"Show Kills in Console": true,
"Show Kills in Chat": true,
"Message Broadcast Radius (in meters)": -1,
"Use Metric Distance": true,
"Require Permission (deathnotes.cansee)": false
}