using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CrimsonKiller.Services;
using CrimsonKiller.Structs;
using CrimsonKiller.Utility;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Network;
using Stunlock.Core;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
using VAMP;
using VAMP.Attributes;
using VAMP.Data;
using VAMP.Models;
using VAMP.Services;
using VAMP.Utilities;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CrimsonKiller")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Fully customizable kill feeds!")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+1.Branch.master.Sha.81cb0575c6ce79e0126453d11f07382663ebe944.81cb0575c6ce79e0126453d11f07382663ebe944")]
[assembly: AssemblyProduct("CrimsonKiller")]
[assembly: AssemblyTitle("CrimsonKiller")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
public class KillStreak
{
public Player player;
public int streak;
public int multi;
public DateTime lastKill;
public KillStreak(Player player, User killed, int streak, int multi)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
this.player = player;
lastKill = DateTime.Now;
AddKill(killed);
}
public void AddKill(User killed)
{
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
TimeSpan timeSpan = DateTime.Now - lastKill;
if (Settings.TimeForMultiKillReset.Value > 0 && timeSpan.TotalSeconds > (double)Settings.TimeForMultiKillReset.Value)
{
multi = 0;
}
if (Settings.TimeForKillStreakReset.Value > 0 && timeSpan.TotalSeconds > (double)Settings.TimeForKillStreakReset.Value)
{
streak = 0;
}
streak++;
multi++;
if (Settings.ToggleKillStreaks.Value)
{
int currentStreak = streak;
if (Database.KillStreaks.Any((KillToMessagePair k) => k.Key == currentStreak))
{
string value = Database.KillStreaks.First((KillToMessagePair k) => k.Key == currentStreak).Value;
value = Broadcast.ProcessUser("killer", value, EntityUtil.Read<User>(player.User), player);
value = Broadcast.ProcessUser("died", value, killed, PlayerService.PlayerFromUser(killed));
ChatUtil.SystemSendAll(value);
}
}
if (Settings.ToggleMultiKills.Value)
{
int currentMulti = multi;
if (Database.MultiKills.Any((KillToMessagePair m) => m.Key == currentMulti))
{
string value2 = Database.MultiKills.First((KillToMessagePair m) => m.Key == currentMulti).Value;
value2 = Broadcast.ProcessUser("killer", value2, EntityUtil.Read<User>(player.User), player);
value2 = Broadcast.ProcessUser("died", value2, killed, PlayerService.PlayerFromUser(killed));
ChatUtil.SystemSendAll(value2);
}
}
lastKill = DateTime.Now;
}
}
namespace CrimsonKiller
{
[BepInPlugin("CrimsonKiller", "CrimsonKiller", "1.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BasePlugin
{
private Harmony _harmony;
public static Plugin Instance { get; private set; }
public static Harmony Harmony => Instance._harmony;
public static ManualLogSource LogInstance => ((BasePlugin)Instance).Log;
public static Settings Settings { get; private set; }
public static string ConfigFiles => Path.Combine(Paths.ConfigPath, "CrimsonKiller");
public Database Database { get; private set; }
public override void Load()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
Instance = this;
Settings = default(Settings);
Settings.InitConfig();
_harmony = new Harmony("CrimsonKiller");
_harmony.PatchAll(Assembly.GetExecutingAssembly());
Events.OnCoreLoaded = (Action)Delegate.Combine(Events.OnCoreLoaded, new Action(Loaded));
}
public void Loaded()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
Database = new Database();
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("CrimsonKiller");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.1.1");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!");
}
log.LogInfo(val);
}
public override bool Unload()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
return true;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "CrimsonKiller";
public const string PLUGIN_NAME = "CrimsonKiller";
public const string PLUGIN_VERSION = "1.1.1";
}
}
namespace CrimsonKiller.Utility
{
public static class RaidTime
{
private static readonly List<DayOfWeek> WeekendDays = new List<DayOfWeek>(2)
{
DayOfWeek.Saturday,
DayOfWeek.Sunday
};
private static ServerGameSettings serverGameSettings;
public static bool IsRaidTimeNow()
{
return IsRaidTime(DateTime.Now);
}
public static bool IsRaidTime(DateTime dateTime)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected I4, but got Unknown
if (serverGameSettings == null)
{
serverGameSettings = Core.Server.GetExistingSystemManaged<ServerGameSettingsSystem>()._Settings;
}
CastleDamageMode castleDamageMode = serverGameSettings.CastleDamageMode;
switch ((int)castleDamageMode)
{
case 0:
return false;
case 1:
return true;
case 2:
{
PlayerInteractionSettings playerInteractionSettings = serverGameSettings.PlayerInteractionSettings;
StartEndTimeData window = (IsWeekend(dateTime) ? playerInteractionSettings.VSCastleWeekendTime : playerInteractionSettings.VSCastleWeekdayTime);
return IsInWindow(dateTime, window);
}
default:
return false;
}
}
private static bool IsWeekend(DateTime dateTime)
{
return WeekendDays.Contains(dateTime.DayOfWeek);
}
private static bool IsInWindow(DateTime dateTime, StartEndTimeData window)
{
TimeSpan timeOfDay = dateTime.TimeOfDay;
TimeSpan timeSpan = new TimeSpan(window.StartHour, window.StartMinute, 0);
TimeSpan timeSpan2 = new TimeSpan(window.EndHour, window.EndMinute, 0);
if (timeOfDay >= timeSpan)
{
return timeOfDay < timeSpan2;
}
return false;
}
}
}
namespace CrimsonKiller.Structs
{
public class Database
{
private static string SlayerOldPath = Path.Combine(Plugin.ConfigFiles, "vblood_firsts.json");
public static string SlayerFile = Path.Combine(FilePaths.WipeData, "ckiller_vblood_firsts.json");
[FileReload("LoadVBloods")]
public static string ToggleVBloods = Path.Combine(Plugin.ConfigFiles, "toggle_vbloods.json");
[FileReload("LoadMessages")]
public static string MessagesFile = Path.Combine(Plugin.ConfigFiles, "messages.json");
[FileReload("LoadKillStreaks")]
public static string KillStreakFile = Path.Combine(Plugin.ConfigFiles, "kill_streaks.json");
[FileReload("LoadMultiKills")]
public static string MultiKillFile = Path.Combine(Plugin.ConfigFiles, "multi_kills.json");
public static Dictionary<ulong, ulong> SlayerList;
public static Dictionary<int, bool> VBloodToggles;
public static Dictionary<string, string> Messages;
public static List<KillToMessagePair> KillStreaks;
public static List<KillToMessagePair> MultiKills;
public static List<KillStreak> CurrentStreaks = new List<KillStreak>();
public Database()
{
LoadDatabase();
}
private static void LoadDatabase()
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
if (!Directory.Exists(Plugin.ConfigFiles))
{
Directory.CreateDirectory(Plugin.ConfigFiles);
}
if (Settings.ToggleFirstSlayer.Value)
{
if (File.Exists(SlayerOldPath) && !File.Exists(SlayerFile))
{
File.Move(SlayerOldPath, SlayerFile);
ManualLogSource logInstance = Plugin.LogInstance;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Moved V Blood Firsts file from ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SlayerOldPath);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" to ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SlayerFile);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logInstance.LogInfo(val);
}
try
{
if (File.Exists(SlayerFile))
{
SlayerList = JsonSerializer.Deserialize<Dictionary<ulong, ulong>>(File.ReadAllText(SlayerFile, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)), JsonUtil.PrettyJsonOptions);
}
else
{
SlayerList = new Dictionary<ulong, ulong>();
SaveDatabase();
}
}
catch
{
SlayerList = new Dictionary<ulong, ulong>();
}
}
LoadVBloods();
LoadMessages();
if (Settings.ToggleKillStreaks.Value)
{
LoadKillStreaks();
}
if (Settings.ToggleMultiKills.Value)
{
LoadMultiKills();
}
}
private static void LoadKillStreaks()
{
if (File.Exists(KillStreakFile))
{
KillStreaks = JsonSerializer.Deserialize<List<KillToMessagePair>>(File.ReadAllText(KillStreakFile));
return;
}
KillStreaks = new List<KillToMessagePair>(6)
{
new KillToMessagePair(3, "{killer.name} is on a Killing Spree!"),
new KillToMessagePair(4, "{killer.name} is Dominating!"),
new KillToMessagePair(5, "{killer.name} is on a Rampage!"),
new KillToMessagePair(6, "{killer.name} is Unstoppable!"),
new KillToMessagePair(10, "{killer.name} is Godlike!"),
new KillToMessagePair(15, "{killer.name} is committing a Massacre!")
};
string contents = JsonSerializer.Serialize(KillStreaks, JsonUtil.PrettyJsonOptions);
File.WriteAllText(KillStreakFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
private static void LoadVBloods()
{
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Expected O, but got Unknown
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Expected O, but got Unknown
bool flag = default(bool);
try
{
if (File.Exists(ToggleVBloods))
{
Dictionary<int, bool> dictionary = JsonSerializer.Deserialize<Dictionary<int, bool>>(File.ReadAllText(ToggleVBloods, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)), new JsonSerializerOptions(JsonUtil.PrettyJsonOptions)
{
ReadCommentHandling = JsonCommentHandling.Skip
});
if (dictionary != null)
{
VBloodToggles = dictionary;
ManualLogSource logInstance = Plugin.LogInstance;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(61, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded toggle_vbloods.json with ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(VBloodToggles.Count((KeyValuePair<int, bool> x) => x.Value));
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" toggled on and ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(VBloodToggles.Count((KeyValuePair<int, bool> x) => !x.Value));
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" toggled off.");
}
logInstance.LogInfo(val);
}
else
{
Plugin.LogInstance.LogWarning((object)"Deserialization of toggle_vbloods.json returned null. Creating default toggles.");
VBloodToggles = VBloods.PrefabToNames.ToDictionary<KeyValuePair<PrefabGUID, (string, string)>, int, bool>(delegate(KeyValuePair<PrefabGUID, (string Long, string Short)> x)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
PrefabGUID key3 = x.Key;
return ((PrefabGUID)(ref key3)).GuidHash;
}, (KeyValuePair<PrefabGUID, (string Long, string Short)> _) => true);
SaveDatabase();
}
}
else
{
Plugin.LogInstance.LogInfo((object)"No toggle_vbloods.json file found, creating a new one with all VBloods toggled on.");
VBloodToggles = VBloods.PrefabToNames.ToDictionary<KeyValuePair<PrefabGUID, (string, string)>, int, bool>(delegate(KeyValuePair<PrefabGUID, (string Long, string Short)> x)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
PrefabGUID key2 = x.Key;
return ((PrefabGUID)(ref key2)).GuidHash;
}, (KeyValuePair<PrefabGUID, (string Long, string Short)> _) => true);
SaveDatabase();
}
}
catch (Exception ex)
{
ManualLogSource logInstance2 = Plugin.LogInstance;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(35, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error loading toggle_vbloods.json: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logInstance2.LogInfo(val);
ManualLogSource logInstance3 = Plugin.LogInstance;
val = new BepInExInfoLogInterpolatedStringHandler(12, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error type: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetType().Name);
}
logInstance3.LogInfo(val);
ManualLogSource logInstance4 = Plugin.LogInstance;
val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Stack trace: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.StackTrace);
}
logInstance4.LogInfo(val);
Plugin.LogInstance.LogInfo((object)"Resetting to default state with all VBloods toggled on.");
VBloodToggles = VBloods.PrefabToNames.ToDictionary<KeyValuePair<PrefabGUID, (string, string)>, int, bool>(delegate(KeyValuePair<PrefabGUID, (string Long, string Short)> x)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
PrefabGUID key = x.Key;
return ((PrefabGUID)(ref key)).GuidHash;
}, (KeyValuePair<PrefabGUID, (string Long, string Short)> _) => true);
}
}
private static void LoadMessages()
{
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Expected O, but got Unknown
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Expected O, but got Unknown
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{ "Downed", "{killer.clanTag} {killer.name} ({killer.currentLv}) has downed {died.clanTag} {died.name} ({died.currentLv})" },
{ "Killed", "{killer.clanTag} {killer.name} ({killer.currentLv}) has killed {died.clanTag} {died.name} ({died.currentLv})" },
{ "KillStolen", "{steal.clanTag} {steal.name} ({steal.currentLv}) stole the kill on {died.clanTag} {died.name} ({died.currentLv}) from {killer.clanTag} {killer.name}" },
{ "GriefDowned", "{killer.clanTag} {killer.name} ({killer.currentLv}/{killer.recordLv}) has downed {died.clanTag} {died.name} ({died.currentLv}/{died.recordLv})" },
{ "GriefKilled", "{killer.clanTag} {killer.name} ({killer.currentLv}/{killer.recordLv}) has killed {died.clanTag} {died.name} ({died.currentLv}/{died.recordLv})" },
{ "GriefKillStolen", "{steal.clanTag} {steal.name} ({steal.currentLv}/{steal.recordLv}) stole the kill on {died.clanTag} {died.name} ({died.currentLv}/{died.recordLv}) from {killer.clanTag} {killer.name} ({killer.currentLv}/{killer.recordLv})" },
{ "OfflineDowned", "{killer.clanTag} {killer.name} ({killer.currentLv}) downed {died.clanTag} {died.name} ({died.currentLv}) while they slumbered" },
{ "OfflineKilled", "{killer.clanTag} {killer.name} ({killer.currentLv}) killed {died.clanTag} {died.name} ({died.currentLv}) while they slumbered" },
{ "OfflineKillStolen", "{steal.clanTag} {steal.name} ({steal.currentLv}) stole the kill on {died.clanTag} {died.name} ({died.currentLv}) from {killer.clanTag} {killer.name}" },
{ "FirstVBloodKill", "{killer.name} ({killer.currentLv}) was the first to slay {vblood.long}!" },
{ "VBloodKill", "{killer.name} ({killer.currentLv}) has slain {vblood.short}!" },
{ "KillStreakEnded", "{died.name}'s kill streak ended!" }
};
bool flag = false;
if (File.Exists(MessagesFile))
{
bool flag2 = default(bool);
try
{
Messages = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(MessagesFile));
foreach (KeyValuePair<string, string> item in dictionary)
{
if (!Messages.ContainsKey(item.Key))
{
Messages[item.Key] = item.Value;
flag = true;
ManualLogSource logInstance = Plugin.LogInstance;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Added missing message key: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item.Key);
}
logInstance.LogInfo(val);
}
}
}
catch (Exception ex)
{
ManualLogSource logInstance2 = Plugin.LogInstance;
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(55, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to load messages.json: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(". Using default messages.");
}
logInstance2.LogWarning(val2);
Messages = dictionary;
flag = true;
}
}
else
{
Plugin.LogInstance.LogInfo((object)"No messages.json file found, creating a new one with default messages.");
Messages = dictionary;
flag = true;
}
if (flag)
{
string contents = JsonSerializer.Serialize(Messages, JsonUtil.PrettyJsonOptions);
File.WriteAllText(MessagesFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
}
private static void LoadMultiKills()
{
if (File.Exists(MultiKillFile))
{
MultiKills = JsonSerializer.Deserialize<List<KillToMessagePair>>(File.ReadAllText(MultiKillFile));
return;
}
MultiKills = new List<KillToMessagePair>(5)
{
new KillToMessagePair(2, "{killer.name} got a Double Kill!"),
new KillToMessagePair(3, "{killer.name} got a Multi Kill!"),
new KillToMessagePair(4, "{killer.name} got a Mega Kill!"),
new KillToMessagePair(5, "{killer.name} got an Ultra Kill!"),
new KillToMessagePair(6, "{killer.name} got a Monster Kill!")
};
string contents = JsonSerializer.Serialize(MultiKills, JsonUtil.PrettyJsonOptions);
File.WriteAllText(MultiKillFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
public static void SaveDatabase()
{
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
if (Settings.ToggleFirstSlayer.Value)
{
string contents = JsonSerializer.Serialize(SlayerList, JsonUtil.PrettyJsonOptions);
File.WriteAllText(SlayerFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
string s = JsonSerializer.Serialize(VBloodToggles, JsonUtil.PrettyJsonOptions);
StringBuilder stringBuilder = new StringBuilder();
using (StringReader stringReader = new StringReader(s))
{
Regex regex = new Regex("^\\s*\"(-?\\d+)\"\\s*:\\s*(true|false)");
string text;
while ((text = stringReader.ReadLine()) != null)
{
Match match = regex.Match(text);
if (match.Success)
{
int num = int.Parse(match.Groups[1].Value);
string text2 = "Unknown";
foreach (KeyValuePair<PrefabGUID, (string, string)> prefabToName in VBloods.PrefabToNames)
{
PrefabGUID key = prefabToName.Key;
if (((PrefabGUID)(ref key)).GuidHash == num)
{
text2 = prefabToName.Value.Item1;
break;
}
}
text = text.TrimEnd() + " /* " + text2 + " */";
}
stringBuilder.AppendLine(text);
}
}
File.WriteAllText(ToggleVBloods, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
}
public struct KillToMessagePair
{
public int Key { get; set; }
public string Value { get; set; }
public KillToMessagePair(int key, string value)
{
Key = key;
Value = value;
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
public readonly struct Settings
{
private static readonly List<string> OrderedSections = new List<string> { "Config", "Messages", "Options", "Parameters", "StreaksAndMulti" };
public static ConfigEntry<bool> ToggleMod { get; private set; }
public static ConfigEntry<bool> ToggleDowned { get; private set; }
public static ConfigEntry<bool> ToggleKill { get; private set; }
public static ConfigEntry<bool> ToggleKillSteal { get; private set; }
public static ConfigEntry<bool> ReplaceGriefDowned { get; private set; }
public static ConfigEntry<bool> ReplaceGriefKill { get; private set; }
public static ConfigEntry<bool> ReplaceGriefKillSteal { get; private set; }
public static ConfigEntry<bool> ReplaceOfflineDowned { get; private set; }
public static ConfigEntry<bool> ReplaceOfflineKill { get; private set; }
public static ConfigEntry<bool> ReplaceOfflineKillSteal { get; private set; }
public static ConfigEntry<bool> ToggleSuicide { get; private set; }
public static ConfigEntry<bool> ToggleFirstSlayer { get; private set; }
public static ConfigEntry<bool> ToggleSlayer { get; private set; }
public static ConfigEntry<bool> RaidsHideRegion { get; private set; }
public static ConfigEntry<int> DelayPVPMessages { get; private set; }
public static ConfigEntry<int> DelaySlayerMessages { get; private set; }
public static ConfigEntry<int> GriefDifference { get; private set; }
public static ConfigEntry<int> GriefDifferenceFromMax { get; private set; }
public static ConfigEntry<bool> ToggleKillStreaks { get; private set; }
public static ConfigEntry<bool> ToggleMultiKills { get; private set; }
public static ConfigEntry<int> TimeForKillStreakReset { get; private set; }
public static ConfigEntry<int> TimeForMultiKillReset { get; private set; }
public static ConfigEntry<bool> ToggleKillStreakEndedMessage { get; private set; }
public static ConfigEntry<string> PlayerNames { get; private set; }
public static ConfigEntry<string> PlayerCurrentLevel { get; private set; }
public static ConfigEntry<string> PlayerRecordLevel { get; private set; }
public static ConfigEntry<string> ClanNames { get; private set; }
public static ConfigEntry<string> ClanTags { get; private set; }
public static ConfigEntry<string> VBloodsShort { get; private set; }
public static ConfigEntry<string> VBloodsLong { get; private set; }
public static ConfigEntry<string> RegionLong { get; private set; }
public static ConfigEntry<string> RegionShort { get; private set; }
public static void InitConfig()
{
ToggleMod = InitConfigEntry(OrderedSections[0], "Toggle", defaultValue: true, "If true the mod will be usable; otherwise it will be disabled.");
ToggleDowned = InitConfigEntry(OrderedSections[0], "ToggleDowned", defaultValue: true, "If true, the downed message will be sent.");
ToggleKill = InitConfigEntry(OrderedSections[0], "ToggleKilled", defaultValue: true, "If true, the killed message will be sent.");
ToggleKillSteal = InitConfigEntry(OrderedSections[0], "ToggleKillStolen", defaultValue: true, "If true, the kill stolen message will be sent.");
ReplaceGriefDowned = InitConfigEntry(OrderedSections[0], "ReplaceGriefDowned", defaultValue: true, "If true, the grief downed message will be sent. Replaces the normal downed message if both messages are enabled and a player is downed by grief.");
ReplaceGriefKill = InitConfigEntry(OrderedSections[0], "ReplaceGriefKill", defaultValue: true, "If true, the grief killed message will be sent. Replaces the normal killed message if both messages are enabled and a player is killed by grief.");
ReplaceGriefKillSteal = InitConfigEntry(OrderedSections[0], "ReplaceGriefKillSteal", defaultValue: true, "If true, the grief kill stolen message will be sent. Replaces the normal kill stolen message if both messages are enabled and a kill of an offline player is stolen by grief.");
ReplaceOfflineDowned = InitConfigEntry(OrderedSections[0], "ToggleOfflineDowned", defaultValue: true, "If true, the offline downed message will be sent. Replaces the normal downed message if both messages are enabled and an offline player is downed.");
ReplaceOfflineKill = InitConfigEntry(OrderedSections[0], "ToggleOfflineKill", defaultValue: true, "If true, the offline killed message will be sent. Replaces the normal killed message if both messages are enabled and an offline player is killed.");
ReplaceOfflineKillSteal = InitConfigEntry(OrderedSections[0], "ToggleOfflineKillSteal", defaultValue: true, "If true, the offline kill stolen message will be sent. Replaces the normal kill stolen message if both messages are enabled and a kill of an offline player is stolen");
ToggleFirstSlayer = InitConfigEntry(OrderedSections[0], "ToggleFirstVBloodKill", defaultValue: true, "If true, the first V Blood kill message will be sent.");
ToggleSlayer = InitConfigEntry(OrderedSections[0], "ToggleVBloodKill", defaultValue: true, "If true, the V Blood kill message will be sent.");
RaidsHideRegion = InitConfigEntry(OrderedSections[2], "RaidsHideRegion", defaultValue: true, "If true, the region will be hidden from messages during Raid Time.");
DelayPVPMessages = InitConfigEntry(OrderedSections[2], "DelayPvPMessages", 0, "The amount of seconds to delay PvP messages by. Set to 0 to disable.");
DelaySlayerMessages = InitConfigEntry(OrderedSections[2], "DelayVBloodMessages", 0, "The amount of seconds to delay V Blood kill messages by. Set to 0 to disable.");
GriefDifference = InitConfigEntry(OrderedSections[2], "GriefDifference", 10, "The level difference required between the griefer’s record level and the victim’s level to trigger a grief message.");
GriefDifferenceFromMax = InitConfigEntry(OrderedSections[2], "GriefDifferenceFromMax", 5, "The level difference required between the griefer’s record level of 91 (max level) and the victim’s level to trigger a grief message.");
PlayerNames = InitConfigEntry(OrderedSections[3], "PlayerNames", "<color=#def>{prefix.name}</color>", "Formatting for {player.name}, {killer.name}, {steal.name}. Note: prefix will be replaced by the target player type.");
PlayerCurrentLevel = InitConfigEntry(OrderedSections[3], "PlayerCurrentLevel", "<color=#fcffdd>{prefix.currentLv}</color>", "Formatting for {player.currentLv}, {killer.currentLv}, {steal.currentLv}. Note: prefix will be replaced by the target player type.");
PlayerRecordLevel = InitConfigEntry(OrderedSections[3], "PlayerRecordLevel", "<color=#e84343>{prefix.recordLv}</color>", "Formatting for {player.recordLv}, {killer.recordLv}, {steal.recordLv}. Note: prefix will be replaced by the target player type.");
ClanNames = InitConfigEntry(OrderedSections[3], "ClanNames", "<color=#f5ddff>{prefix.clanName}</color>", "Formatting for {player.clanName}, {killer.clanName}, {steal.clanName}. Note: prefix will be replaced by the target player type.");
ClanTags = InitConfigEntry(OrderedSections[3], "ClanTags", "<color=#f5ddff>{prefix.clanTag}</color>", "Formatting for {player.clanTag}, {killer.clanTag}, {steal.clanTag}. Note: Clan tags include brackets by default.");
VBloodsShort = InitConfigEntry(OrderedSections[3], "VBloodsShort", "<b>{vblood.short}</b>", "Formatting for {vblood.short}. Note: V Blood names can be changed in BepInEx/configs/VAMP/Names_VBloods.json.");
VBloodsLong = InitConfigEntry(OrderedSections[3], "VBloodsLong", "<b>{vblood.long}</b>", "Formatting for {vblood.long}, {vblood}. Note: V Blood names can be changed in BepInEx/configs/VAMP/Names_VBloods.json.");
RegionLong = InitConfigEntry(OrderedSections[3], "RegionLong", " in <i>{region.long}</i>", "Formatting for {region.long}, {region}. Note: Region names can be changed in BepInEx/configs/VAMP/Names_Regions.json.");
RegionShort = InitConfigEntry(OrderedSections[3], "RegionShort", "[<i>{region.short}</i>]", "Formatting for {region.short}. Note: Region names can be changed in BepInEx/configs/VAMP/Names_Regions.json.");
ToggleKillStreaks = InitConfigEntry(OrderedSections[4], "ToggleKillStreaks", defaultValue: true, "If true, the kill streak messages will be sent.");
ToggleMultiKills = InitConfigEntry(OrderedSections[4], "ToggleMultiKills", defaultValue: false, "If true, the multi kill messages will be sent.");
TimeForKillStreakReset = InitConfigEntry(OrderedSections[4], "TimeForKillStreakReset", -1, "The time in seconds for the kill streak to reset. Set to -1 to disable.");
TimeForMultiKillReset = InitConfigEntry(OrderedSections[4], "TimeForMultiKillReset", 180, "The time in seconds for the multi kill streak to reset. Set to -1 to disable.");
ToggleKillStreakEndedMessage = InitConfigEntry(OrderedSections[4], "ToggleKillStreakEndedMessage", defaultValue: true, "If true, the kill streak ended messages will be sent.");
ReorderConfigSections();
}
private static ConfigEntry<T> InitConfigEntry<T>(string section, string key, T defaultValue, string description)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
ConfigEntry<T> val = ((BasePlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, description);
string text = Path.Combine(Paths.ConfigPath, "CrimsonKiller.cfg");
ConfigEntry<T> val2 = default(ConfigEntry<T>);
if (File.Exists(text) && new ConfigFile(text, true).TryGetEntry<T>(section, key, ref val2))
{
val.Value = val2.Value;
}
return val;
}
private static void ReorderConfigSections()
{
string path = Path.Combine(Paths.ConfigPath, "CrimsonKiller.cfg");
if (!File.Exists(path))
{
return;
}
List<string> list = File.ReadAllLines(path).ToList();
Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
string text = "";
foreach (string item in list)
{
if (item.StartsWith("["))
{
text = item.Trim('[', ']');
dictionary[text] = new List<string> { item };
}
else if (!string.IsNullOrWhiteSpace(text))
{
dictionary[text].Add(item);
}
}
using StreamWriter streamWriter = new StreamWriter(path, append: false);
foreach (string orderedSection in OrderedSections)
{
if (!dictionary.ContainsKey(orderedSection))
{
continue;
}
foreach (string item2 in dictionary[orderedSection])
{
streamWriter.WriteLine(item2);
}
streamWriter.WriteLine();
}
}
}
}
namespace CrimsonKiller.Services
{
public static class Broadcast
{
private static bool IsGriefKill(DeathTrack death, ulong who)
{
Player val = default(Player);
if (!PlayerService.TryFindBySteam(who, ref val))
{
return false;
}
Player val2 = default(Player);
if (!PlayerService.TryFindBySteam(death.victim_id, ref val2))
{
return false;
}
if (val.RecordLevel == 91)
{
if (val.RecordLevel - val2.Level > Settings.GriefDifferenceFromMax.Value)
{
return true;
}
}
else if (val.RecordLevel - val2.Level > Settings.GriefDifference.Value)
{
return true;
}
return false;
}
public static void Message(DeathType deathType, DeathTrack death)
{
//IL_045a: Unknown result type (might be due to invalid IL or missing references)
//IL_04b9: Unknown result type (might be due to invalid IL or missing references)
//IL_0470: Unknown result type (might be due to invalid IL or missing references)
//IL_0477: Expected O, but got Unknown
//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
//IL_0518: Unknown result type (might be due to invalid IL or missing references)
//IL_051d: Unknown result type (might be due to invalid IL or missing references)
//IL_0522: Unknown result type (might be due to invalid IL or missing references)
//IL_0524: Unknown result type (might be due to invalid IL or missing references)
//IL_0529: Unknown result type (might be due to invalid IL or missing references)
//IL_052e: Unknown result type (might be due to invalid IL or missing references)
//IL_0536: Unknown result type (might be due to invalid IL or missing references)
//IL_0544: Unknown result type (might be due to invalid IL or missing references)
//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
//IL_04d6: Expected O, but got Unknown
//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
//IL_024c: Unknown result type (might be due to invalid IL or missing references)
//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0401: Unknown result type (might be due to invalid IL or missing references)
//IL_0507: Unknown result type (might be due to invalid IL or missing references)
//IL_027d: Unknown result type (might be due to invalid IL or missing references)
//IL_025a: Unknown result type (might be due to invalid IL or missing references)
//IL_025f: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_026c: Unknown result type (might be due to invalid IL or missing references)
//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
//IL_02dc: Expected O, but got Unknown
//IL_0293: Unknown result type (might be due to invalid IL or missing references)
//IL_029a: Expected O, but got Unknown
//IL_030e: Unknown result type (might be due to invalid IL or missing references)
string text = "";
bool flag = default(bool);
switch (deathType)
{
case DeathType.Downed:
if (Settings.ReplaceOfflineDowned.Value && death.offlined)
{
if (!Database.Messages.ContainsKey("OfflineDowned"))
{
return;
}
text = Database.Messages["OfflineDowned"];
}
else if (Settings.ReplaceGriefDowned.Value && IsGriefKill(death, death.killer_id))
{
if (!Database.Messages.ContainsKey("GriefDowned"))
{
return;
}
text = Database.Messages["GriefDowned"];
}
else
{
if (!Settings.ToggleDowned.Value || !Database.Messages.ContainsKey("Downed"))
{
return;
}
text = Database.Messages["Downed"];
}
break;
case DeathType.Killed:
if (Settings.ReplaceOfflineKill.Value && death.offlined)
{
if (!Database.Messages.ContainsKey("OfflineKilled"))
{
return;
}
text = Database.Messages["OfflineKilled"];
}
else if (Settings.ReplaceGriefKill.Value && IsGriefKill(death, death.killer_id))
{
if (!Database.Messages.ContainsKey("GriefKilled"))
{
return;
}
text = Database.Messages["GriefKilled"];
}
else
{
if (!Settings.ToggleKill.Value || !Database.Messages.ContainsKey("Killed"))
{
return;
}
text = Database.Messages["Killed"];
}
break;
case DeathType.KillStolen:
{
if (Settings.ReplaceOfflineKillSteal.Value && death.offlined)
{
if (!Database.Messages.ContainsKey("OfflineKillStolen"))
{
return;
}
text = Database.Messages["OfflineKillStolen"];
}
else if (Settings.ReplaceGriefKillSteal.Value && IsGriefKill(death, death.killer_id))
{
if (!Database.Messages.ContainsKey("GriefKillStolen"))
{
return;
}
text = Database.Messages["GriefKillStolen"];
}
else
{
if (!Settings.ToggleKillSteal.Value || !Database.Messages.ContainsKey("KillStolen"))
{
return;
}
text = Database.Messages["KillStolen"];
}
if (string.IsNullOrEmpty(text))
{
Message(DeathType.Killed, death);
break;
}
Player val2 = default(Player);
if (!PlayerService.TryFindBySteam(death.steal_id, ref val2))
{
return;
}
if (EntityUtil.Has<User>(val2.User))
{
User user = EntityUtil.Read<User>(val2.User);
text = ProcessUser("steal", text, user, val2);
break;
}
BepInExInfoLogInterpolatedStringHandler val3;
if (!EntityUtil.Has<User>(val2.User))
{
ManualLogSource logInstance = Plugin.LogInstance;
val3 = new BepInExInfoLogInterpolatedStringHandler(106, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Steal data for ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.steal_id);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingStealKiller.txt to SkyTech6.");
}
logInstance.LogInfo(val3);
return;
}
ManualLogSource logInstance2 = Plugin.LogInstance;
val3 = new BepInExInfoLogInterpolatedStringHandler(106, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Steal data for ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.steal_id);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingStealKiller.txt to SkyTech6.");
}
logInstance2.LogInfo(val3);
DevUtil.Dump(val2.User, "MissingStealKiller.txt");
break;
}
case DeathType.VBlood:
{
if (Settings.ToggleFirstSlayer.Value && !Database.SlayerList.ContainsKey(death.victim_id))
{
if (!Database.Messages.ContainsKey("FirstVBloodKill"))
{
return;
}
text = Database.Messages["FirstVBloodKill"];
Database.SlayerList.Add(death.victim_id, death.killer_id);
Database.SaveDatabase();
}
else
{
if (!Settings.ToggleSlayer.Value || !Database.Messages.ContainsKey("VBloodKill"))
{
return;
}
text = Database.Messages["VBloodKill"];
}
if (Database.VBloodToggles != null && Database.VBloodToggles.TryGetValue((int)death.victim_id, out var value) && !value)
{
return;
}
text = ProcessVBlood(text, new PrefabGUID((int)death.victim_id));
Player val = default(Player);
if (PlayerService.TryFindBySteam(death.killer_id, ref val))
{
text = ProcessUser("killer", text, EntityUtil.Read<User>(val.User), val);
if (Settings.DelaySlayerMessages.Value > 0)
{
Core.StartCoroutine(DelayBroadcast(text, Settings.DelaySlayerMessages.Value));
}
else
{
ChatUtil.SystemSendAll(text);
}
}
return;
}
}
Player val4 = default(Player);
Player val5 = default(Player);
if (!PlayerService.TryFindBySteam(death.victim_id, ref val4) || !PlayerService.TryFindBySteam(death.killer_id, ref val5))
{
return;
}
if (!EntityUtil.Has<User>(val4.User))
{
ManualLogSource logInstance3 = Plugin.LogInstance;
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(102, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Victim data for ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.victim_id);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingVictim.txt to SkyTech6.");
}
logInstance3.LogInfo(val3);
DevUtil.Dump(val4.User, "MissingVictim.txt");
return;
}
if (!EntityUtil.Has<User>(val5.User))
{
ManualLogSource logInstance4 = Plugin.LogInstance;
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(102, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("WARNING: Killer data for ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<ulong>(death.killer_id);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" does not have a user component! Send VAMPDump/MissingKiller.txt to SkyTech6.");
}
logInstance4.LogInfo(val3);
DevUtil.Dump(val5.User, "MissingKiller.txt");
return;
}
User user2 = EntityUtil.Read<User>(val4.User);
User user3 = EntityUtil.Read<User>(val5.User);
text = ProcessUser("died", text, user2, val4);
text = ProcessUser("killer", text, user3, val5);
if (!string.IsNullOrEmpty(text))
{
if (Settings.DelayPVPMessages.Value > 0)
{
Core.StartCoroutine(DelayBroadcast(text, Settings.DelayPVPMessages.Value));
}
else
{
ChatUtil.SystemSendAll(text);
}
}
}
private static string ProcessVBlood(string message, PrefabGUID vblood)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
string newValue = VBloods.ToString(vblood);
string newValue2 = VBloods.ToShortString(vblood);
message = message.Replace("{vblood.long}", newValue);
message = message.Replace("{vblood.short}", newValue2);
message = message.Replace("{vblood}", newValue);
return message;
}
public static string ProcessUser(string prefix, string message, User user, Player player)
{
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
//IL_0253: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Unknown result type (might be due to invalid IL or missing references)
//IL_0263: Unknown result type (might be due to invalid IL or missing references)
//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
//IL_02db: Unknown result type (might be due to invalid IL or missing references)
string text = Settings.PlayerNames.Value.Replace("{prefix", "{" + prefix);
message = message.Replace("{" + prefix + ".name}", text.Replace("{" + prefix + ".name}", ((FixedString64Bytes)(ref user.CharacterName)).Value ?? ""));
string text2 = Settings.PlayerCurrentLevel.Value.Replace("{prefix", "{" + prefix);
message = message.Replace("{" + prefix + ".currentLv}", text2.Replace("{" + prefix + ".currentLv}", $"{player.Level}"));
string text3 = Settings.PlayerRecordLevel.Value.Replace("{prefix", "{" + prefix);
message = message.Replace("{" + prefix + ".recordLv}", text3.Replace("{" + prefix + ".recordLv}", $"{player.RecordLevel}"));
if (Settings.RaidsHideRegion.Value && RaidTime.IsRaidTimeNow())
{
message = message.Replace("{region.short}", "");
message = message.Replace("{region.long}", "");
message = message.Replace("{region}", "");
}
else
{
string value = Settings.RegionShort.Value;
string value2 = Settings.RegionLong.Value;
message = message.Replace("{region.short}", value.Replace("{region.short}", player.GetWorldZoneString(true)));
message = message.Replace("{region.long}", value2.Replace("{region.long}", player.GetWorldZoneString(false)));
message = message.Replace("{region}", value2.Replace("{region.long}", player.GetWorldZoneString(false)));
}
if (((Entity)(ref user.ClanEntity._Entity)).Equals(Entity.Null))
{
message = message.Replace("{" + prefix + ".clanTag}", "");
message = message.Replace("{" + prefix + ".clanName}", "");
}
else
{
ClanTeam val = EntityUtil.Read<ClanTeam>(user.ClanEntity._Entity);
string text4 = Settings.ClanTags.Value.Replace("{prefix", "{" + prefix);
string text5 = Settings.ClanNames.Value.Replace("{prefix", "{" + prefix);
string text6 = message;
string oldValue = "{" + prefix + ".clanTag}";
string oldValue2 = "{" + prefix + ".clanTag}";
FixedString32Bytes smartClanName = ClanUtility.GetSmartClanName(((FixedString64Bytes)(ref val.Name)).Value);
message = text6.Replace(oldValue, text4.Replace(oldValue2, ((object)(FixedString32Bytes)(ref smartClanName)).ToString()));
message = message.Replace("{" + prefix + ".clanName}", text5.Replace("{" + prefix + ".clanName}", ((FixedString64Bytes)(ref val.Name)).Value));
}
message = Regex.Replace(message, "<(?<tag>\\w+)(=[^>]*)?>\\s*</\\k<tag>>", "", RegexOptions.IgnoreCase);
return Regex.Replace(message, "\\s+", " ").Trim();
}
private static IEnumerator DelayBroadcast(string message, int seconds)
{
yield return (object)new WaitForSeconds((float)seconds);
ChatUtil.SystemSendAll(message);
}
}
public enum DeathType
{
Downed,
Killed,
KillStolen,
VBlood
}
public struct DeathTrack
{
public ulong killer_id;
public ulong victim_id;
public float3 location;
public ulong steal_id;
public bool offlined;
public DeathTrack(ulong killer_id, ulong victim_id, float3 location)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
steal_id = 0uL;
offlined = false;
this.killer_id = killer_id;
this.victim_id = victim_id;
this.location = location;
}
}
}
namespace CrimsonKiller.Patches
{
[HarmonyPatch]
internal static class DeathEventListenerSystemPatch
{
private static List<DeathTrack> Deaths = new List<DeathTrack>();
private static readonly PrefabGUID siegeGolem = new PrefabGUID(914043867);
[HarmonyPatch(typeof(DeathEventListenerSystem), "OnUpdate")]
[HarmonyPostfix]
private static void Postfix(DeathEventListenerSystem __instance)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0347: Unknown result type (might be due to invalid IL or missing references)
//IL_034e: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_031b: Unknown result type (might be due to invalid IL or missing references)
//IL_0271: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Unknown result type (might be due to invalid IL or missing references)
//IL_0281: Unknown result type (might be due to invalid IL or missing references)
//IL_0256: Unknown result type (might be due to invalid IL or missing references)
//IL_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
//IL_020a: Unknown result type (might be due to invalid IL or missing references)
EntityQuery deathEventQuery = __instance._DeathEventQuery;
NativeArray<DeathEvent> val = ((EntityQuery)(ref deathEventQuery)).ToComponentDataArray<DeathEvent>(AllocatorHandle.op_Implicit((Allocator)2));
try
{
Enumerator<DeathEvent> enumerator = val.GetEnumerator();
PlayerCharacter val2 = default(PlayerCharacter);
Player val3 = default(Player);
VBloodConsumeSource val4 = default(VBloodConsumeSource);
while (enumerator.MoveNext())
{
DeathEvent current = enumerator.Current;
if (!EntityUtil.Has<PlayerCharacter>(current.Killer))
{
continue;
}
Entity userEntity = EntityUtil.Read<PlayerCharacter>(current.Killer).UserEntity;
if (EntityUtil.Has<PlayerCharacter>(current.Killer) && EntityUtil.Has<PlayerCharacter>(current.Died))
{
Entity diedEntity = EntityUtil.Read<PlayerCharacter>(current.Died).UserEntity;
if (Deaths.Exists((DeathTrack x) => x.victim_id == EntityUtil.Read<User>(diedEntity).PlatformId))
{
DeathTrack deathTrack = Deaths.Find((DeathTrack x) => x.victim_id == EntityUtil.Read<User>(diedEntity).PlatformId);
float3 value = EntityUtil.Read<Translation>(diedEntity).Value;
if ((diedEntity == userEntity || EntityUtil.Read<User>(userEntity).PlatformId == deathTrack.killer_id) && math.distance(deathTrack.location, value) < 5f)
{
Broadcast.Message(DeathType.Killed, deathTrack);
}
else
{
deathTrack.steal_id = EntityUtil.Read<User>(userEntity).PlatformId;
Broadcast.Message(DeathType.KillStolen, deathTrack);
}
Deaths.Remove(deathTrack);
}
if (!Settings.ToggleKillStreaks.Value)
{
continue;
}
Player killerPlayer = PlayerService.PlayerFromUser(EntityUtil.Read<User>(userEntity));
Player deadPlayer = PlayerService.PlayerFromUser(EntityUtil.Read<User>(diedEntity));
if (Database.CurrentStreaks.Exists((KillStreak x) => ((object)x.player).Equals((object?)deadPlayer)) && Database.CurrentStreaks.Remove(Database.CurrentStreaks.Find((KillStreak x) => ((object)x.player).Equals((object?)deadPlayer))) && Settings.ToggleKillStreakEndedMessage.Value)
{
if (!Database.Messages.TryGetValue("KillStreakEnded", out var value2))
{
continue;
}
value2 = Broadcast.ProcessUser("died", value2, EntityUtil.Read<User>(diedEntity), deadPlayer);
value2 = Broadcast.ProcessUser("killer", value2, EntityUtil.Read<User>(userEntity), killerPlayer);
ChatUtil.SystemSendAll(value2);
}
if (Database.CurrentStreaks.Exists((KillStreak x) => ((object)x.player).Equals((object?)killerPlayer)))
{
Database.CurrentStreaks.First((KillStreak x) => ((object)x.player).Equals((object?)killerPlayer)).AddKill(EntityUtil.Read<User>(diedEntity));
continue;
}
Entity user = killerPlayer.User;
if (!((Entity)(ref user)).Equals(deadPlayer.User))
{
Database.CurrentStreaks.Add(new KillStreak(killerPlayer, EntityUtil.Read<User>(deadPlayer.User), 1, 1));
}
}
else if (EntityUtil.Has<PlayerCharacter>(current.Killer) && EntityUtil.Has<VBloodConsumeSource>(current.Died) && EntityUtil.TryGetComponent<PlayerCharacter>(current.Killer, ref val2) && PlayerService.TryFindByName(val2.Name, ref val3) && EntityUtil.TryGetComponent<VBloodConsumeSource>(current.Died, ref val4))
{
DeathTrack death = new DeathTrack(val3.SteamID, (ulong)((PrefabGUID)(ref val4.Source)).GuidHash, val3.Position);
Broadcast.Message(DeathType.VBlood, death);
}
}
}
catch (Exception ex)
{
ManualLogSource logInstance = Plugin.LogInstance;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(44, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Exited DeathEventListenerSystem hook early: ");
((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Exception>(ex);
}
logInstance.LogInfo(val5);
}
finally
{
val.Dispose();
}
}
[HarmonyPatch(typeof(VampireDownedServerEventSystem), "OnUpdate")]
[HarmonyPrefix]
private static void Downed(VampireDownedServerEventSystem __instance)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
EntityQuery _query_1174204813_ = __instance.__query_1174204813_0;
Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_1174204813_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
Entity val = default(Entity);
Entity val2 = default(Entity);
PlayerCharacter val3 = default(PlayerCharacter);
while (enumerator.MoveNext())
{
Entity current = enumerator.Current;
if (!VampireDownedServerEventSystem.TryFindRootOwner(current, 1, Core.EntityManager, ref val) || !VampireDownedServerEventSystem.TryFindRootOwner(EntityUtil.Read<VampireDownedBuff>(current).Source, 1, Core.EntityManager, ref val2))
{
continue;
}
PlayerCharacter victim = EntityUtil.Read<PlayerCharacter>(val);
if (!EntityUtil.Has<UnitLevel>(val2) && EntityUtil.TryGetComponent<PlayerCharacter>(val2, ref val3) && !(val3.UserEntity == victim.UserEntity))
{
Deaths.RemoveAll((DeathTrack x) => x.victim_id == EntityUtil.Read<User>(victim.UserEntity).PlatformId);
float3 value = EntityUtil.Read<Translation>(EntityUtil.Read<User>(victim.UserEntity).LocalCharacter._Entity).Value;
DeathTrack deathTrack = new DeathTrack(EntityUtil.Read<User>(val3.UserEntity).PlatformId, EntityUtil.Read<User>(victim.UserEntity).PlatformId, value);
if (!EntityUtil.Read<User>(victim.UserEntity).IsConnected)
{
deathTrack.offlined = true;
}
Deaths.Add(deathTrack);
Broadcast.Message(DeathType.Downed, deathTrack);
}
}
}
}
}