From 979b1f23106d6ec56dee6101f925eb0e5fa24e70 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 25 Mar 2018 23:51:25 -0500 Subject: [PATCH] fixed initialization error when no map set exists in config fixed discord link showing when no invite specified OpenGraph image set to absolute url more changes to killcallback and logging fixed some angle conversion stuff --- Plugins/SimpleStats/Cheat/Detection.cs | 508 +++++++++--------- Plugins/SimpleStats/Helpers/Extensions.cs | 8 +- Plugins/SimpleStats/Helpers/StatManager.cs | 11 +- Plugins/SimpleStats/Models/EFClientKill.cs | 8 +- Plugins/SimpleStats/Plugin.cs | 2 +- SharedLibrary/Helpers/Vector3.cs | 2 +- SharedLibrary/Server.cs | 4 +- WebfrontCore/Application/Server.cs | 4 +- WebfrontCore/Controllers/BaseController.cs | 5 +- WebfrontCore/Controllers/PenaltyController.cs | 2 +- .../Views/Client/Profile/Index.cshtml | 16 + WebfrontCore/Views/Shared/Error.cshtml | 4 +- WebfrontCore/Views/Shared/_Layout.cshtml | 2 +- _customcallbacks.gsc | 8 +- 14 files changed, 316 insertions(+), 268 deletions(-) diff --git a/Plugins/SimpleStats/Cheat/Detection.cs b/Plugins/SimpleStats/Cheat/Detection.cs index 5ef06890b..7fec01d46 100644 --- a/Plugins/SimpleStats/Cheat/Detection.cs +++ b/Plugins/SimpleStats/Cheat/Detection.cs @@ -15,6 +15,8 @@ namespace StatsPlugin.Cheat int Kills; int AboveThresholdCount; double AverageKillTime; + double AverageHitOffset; + int avgcnt; Dictionary HitLocationCount; DateTime LastKill; ILogger Log; @@ -51,271 +53,283 @@ namespace StatsPlugin.Cheat #region VIEWANGLES double distance = Vector3.Distance(kill.KillOrigin, kill.DeathOrigin); - double x = kill.KillOrigin.X + distance * Math.Cos(kill.ViewAngles.Y.ToRadians()) * Math.Cos(kill.ViewAngles.X.ToRadians()); - double y = kill.KillOrigin.Y + (distance * Math.Sin((360.0f - kill.ViewAngles.Y).ToRadians())); - double z = kill.KillOrigin.Z + (distance * Math.Cos(kill.ViewAngles.Y.ToRadians()) * Math.Sin((360.0f - kill.ViewAngles.X).ToRadians())); + double x = kill.KillOrigin.X + distance * Math.Cos(kill.ViewAngles.X.ToRadians()) * Math.Cos(kill.ViewAngles.Y.ToRadians()); + double y = kill.KillOrigin.Y + (distance * Math.Sin(kill.ViewAngles.X.ToRadians()) * Math.Cos(kill.ViewAngles.Y.ToRadians())); + double z = kill.KillOrigin.Z + distance * Math.Sin((360.0f - kill.ViewAngles.Y).ToRadians()); var trueVector = Vector3.Subtract(kill.KillOrigin, kill.DeathOrigin); var calculatedVector = Vector3.Subtract(kill.KillOrigin, new Vector3((float)x, (float)y, (float)z)); double angle = trueVector.AngleBetween(calculatedVector); - // Console.WriteLine(((float)angle).ToDegrees()); - #endregion - - #region SESSION_RATIOS - if (Kills >= Thresholds.LowSampleMinKills) + if (kill.AdsPercent > 0.5) { - double marginOfError = Thresholds.GetMarginOfError(Kills); - // determine what the max headshot percentage can be for current number of kills - double lerpAmount = Math.Min(1.0, (Kills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); - double maxHeadshotLerpValueForFlag = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(2.0), Thresholds.HeadshotRatioThresholdHighSample(2.0), lerpAmount) + marginOfError; - double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.0), Thresholds.HeadshotRatioThresholdHighSample(3.0), lerpAmount) + marginOfError; - // determine what the max bone percentage can be for current number of kills - double maxBoneRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(2.25), Thresholds.BoneRatioThresholdHighSample(2.25), lerpAmount) + marginOfError; - double maxBoneRatioLerpValueForBan = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(3.25), Thresholds.BoneRatioThresholdHighSample(3.25), lerpAmount) + marginOfError; - - // calculate headshot ratio - double currentHeadshotRatio = ((HitLocationCount[IW4Info.HitLocation.head] + HitLocationCount[IW4Info.HitLocation.helmet]) / (double)Kills); - // calculate maximum bone - double currentMaxBoneRatio = (HitLocationCount.Values.Select(v => v / (double)Kills).Max()); - - var bone = HitLocationCount.FirstOrDefault(b => b.Value == HitLocationCount.Values.Max()).Key; - #region HEADSHOT_RATIO - // flag on headshot - if (currentHeadshotRatio > maxHeadshotLerpValueForFlag) - { - // ban on headshot - if (currentHeadshotRatio > maxHeadshotLerpValueForFlag) - { - AboveThresholdCount++; - Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**"); - Log.WriteDebug($"ClientId: {kill.AttackerId}"); - Log.WriteDebug($"**Kills: {Kills}"); - Log.WriteDebug($"**Ratio {currentHeadshotRatio}"); - Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Ban, - RatioAmount = currentHeadshotRatio, - Bone = IW4Info.HitLocation.head, - KillCount = Kills - }; - } - else - { - AboveThresholdCount++; - Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**"); - Log.WriteDebug($"ClientId: {kill.AttackerId}"); - Log.WriteDebug($"**Kills: {Kills}"); - Log.WriteDebug($"**Ratio {currentHeadshotRatio}"); - Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Flag, - RatioAmount = currentHeadshotRatio, - Bone = IW4Info.HitLocation.head, - KillCount = Kills - }; - } - } - #endregion - - #region BONE_RATIO - // flag on bone ratio - else if (currentMaxBoneRatio > maxBoneRatioLerpValueForFlag) - { - // ban on bone ratio - if (currentMaxBoneRatio > maxBoneRatioLerpValueForBan) - { - Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**"); - Log.WriteDebug($"ClientId: {kill.AttackerId}"); - Log.WriteDebug($"**Kills: {Kills}"); - Log.WriteDebug($"**Ratio {currentMaxBoneRatio}"); - Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Ban, - RatioAmount = currentMaxBoneRatio, - Bone = bone, - KillCount = Kills - }; - } - else - { - Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**"); - Log.WriteDebug($"ClientId: {kill.AttackerId}"); - Log.WriteDebug($"**Kills: {Kills}"); - Log.WriteDebug($"**Ratio {currentMaxBoneRatio}"); - Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Flag, - RatioAmount = currentMaxBoneRatio, - Bone = bone, - KillCount = Kills - }; - } - } - #endregion + Log.WriteInfo($"{((float)angle).ToDegrees()}"); + AverageHitOffset += angle; + avgcnt++; + double avg = AverageHitOffset / (float)avgcnt; } - #region CHEST_ABDOMEN_RATIO_SESSION - int chestKills = HitLocationCount[IW4Info.HitLocation.torso_upper]; +/*r = distance, +x = playerX + r*cos(yaw)*cos(pitch), +y = playerY + r*sin(yaw)*cos(pitch) +z = playerZ + r*sin(360-pitch)*/ - if (chestKills >= Thresholds.MediumSampleMinKills) - { - double marginOfError = Thresholds.GetMarginOfError(chestKills); - double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); - // determine max acceptable ratio of chest to abdomen kills - double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3), Thresholds.ChestAbdomenRatioThresholdHighSample(3), lerpAmount) + marginOfError; - double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(4), Thresholds.ChestAbdomenRatioThresholdHighSample(4), lerpAmount) + marginOfError; - - double currentChestAbdomenRatio = HitLocationCount[IW4Info.HitLocation.torso_upper] / (double)HitLocationCount[IW4Info.HitLocation.torso_lower]; - - if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag) - { - - if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestKills >= Thresholds.MediumSampleMinKills + 30) - { - Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**"); - Log.WriteDebug($"ClientId: {kill.AttackerId}"); - Log.WriteDebug($"**Chest Kills: {chestKills}"); - Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); - Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Ban, - RatioAmount = currentChestAbdomenRatio, - Bone = 0, - KillCount = chestKills - }; - } - else - { - Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**"); - Log.WriteDebug($"ClientId: {kill.AttackerId}"); - Log.WriteDebug($"**Chest Kills: {chestKills}"); - Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); - Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Flag, - RatioAmount = currentChestAbdomenRatio, - Bone = 0, - KillCount = chestKills - }; - } - } - } - #endregion #endregion + +#region SESSION_RATIOS +if (Kills >= Thresholds.LowSampleMinKills) +{ + double marginOfError = Thresholds.GetMarginOfError(Kills); + // determine what the max headshot percentage can be for current number of kills + double lerpAmount = Math.Min(1.0, (Kills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); + double maxHeadshotLerpValueForFlag = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(2.0), Thresholds.HeadshotRatioThresholdHighSample(2.0), lerpAmount) + marginOfError; + double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.0), Thresholds.HeadshotRatioThresholdHighSample(3.0), lerpAmount) + marginOfError; + // determine what the max bone percentage can be for current number of kills + double maxBoneRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(2.25), Thresholds.BoneRatioThresholdHighSample(2.25), lerpAmount) + marginOfError; + double maxBoneRatioLerpValueForBan = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(3.25), Thresholds.BoneRatioThresholdHighSample(3.25), lerpAmount) + marginOfError; + + // calculate headshot ratio + double currentHeadshotRatio = ((HitLocationCount[IW4Info.HitLocation.head] + HitLocationCount[IW4Info.HitLocation.helmet]) / (double)Kills); + // calculate maximum bone + double currentMaxBoneRatio = (HitLocationCount.Values.Select(v => v / (double)Kills).Max()); + + var bone = HitLocationCount.FirstOrDefault(b => b.Value == HitLocationCount.Values.Max()).Key; + #region HEADSHOT_RATIO + // flag on headshot + if (currentHeadshotRatio > maxHeadshotLerpValueForFlag) + { + // ban on headshot + if (currentHeadshotRatio > maxHeadshotLerpValueForFlag) + { + AboveThresholdCount++; + Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**"); + Log.WriteDebug($"ClientId: {kill.AttackerId}"); + Log.WriteDebug($"**Kills: {Kills}"); + Log.WriteDebug($"**Ratio {currentHeadshotRatio}"); + Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); + return new DetectionPenaltyResult() { - ClientPenalty = Penalty.PenaltyType.Any, - RatioAmount = 0 + ClientPenalty = Penalty.PenaltyType.Ban, + RatioAmount = currentHeadshotRatio, + Bone = IW4Info.HitLocation.head, + KillCount = Kills }; } - - public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats) + else { - int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.left_arm_upper).HitCount; - - if (totalChestKills >= 250) - { - double marginOfError = Thresholds.GetMarginOfError(totalChestKills); - double lerpAmount = Math.Min(1.0, (totalChestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); - // determine max acceptable ratio of chest to abdomen kills - double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(2.25), Thresholds.ChestAbdomenRatioThresholdHighSample(2.25), lerpAmount) + marginOfError; - double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), lerpAmount) + marginOfError; - - double currentChestAbdomenRatio = HitLocationCount[IW4Info.HitLocation.torso_upper] / (double)HitLocationCount[IW4Info.HitLocation.torso_lower]; - - if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag) - { - - if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan) - { - Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**"); - Log.WriteDebug($"ClientId: {stats.ClientId}"); - Log.WriteDebug($"**Total Chest Kills: {totalChestKills}"); - Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); - Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Ban, - RatioAmount = currentChestAbdomenRatio, - Bone = IW4Info.HitLocation.torso_upper, - KillCount = totalChestKills - }; - } - else - { - Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**"); - Log.WriteDebug($"ClientId: {stats.ClientId}"); - Log.WriteDebug($"**Total Chest Kills: {totalChestKills}"); - Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); - Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}"); - var sb = new StringBuilder(); - foreach (var kvp in HitLocationCount) - sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); - Log.WriteDebug(sb.ToString()); - // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); - - return new DetectionPenaltyResult() - { - ClientPenalty = Penalty.PenaltyType.Flag, - RatioAmount = currentChestAbdomenRatio, - Bone = IW4Info.HitLocation.torso_upper, - KillCount = totalChestKills - }; - } - } - } + AboveThresholdCount++; + Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**"); + Log.WriteDebug($"ClientId: {kill.AttackerId}"); + Log.WriteDebug($"**Kills: {Kills}"); + Log.WriteDebug($"**Ratio {currentHeadshotRatio}"); + Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); return new DetectionPenaltyResult() { - Bone = IW4Info.HitLocation.none, - ClientPenalty = Penalty.PenaltyType.Any + ClientPenalty = Penalty.PenaltyType.Flag, + RatioAmount = currentHeadshotRatio, + Bone = IW4Info.HitLocation.head, + KillCount = Kills + }; + } + } + #endregion + + #region BONE_RATIO + // flag on bone ratio + else if (currentMaxBoneRatio > maxBoneRatioLerpValueForFlag) + { + // ban on bone ratio + if (currentMaxBoneRatio > maxBoneRatioLerpValueForBan) + { + Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**"); + Log.WriteDebug($"ClientId: {kill.AttackerId}"); + Log.WriteDebug($"**Kills: {Kills}"); + Log.WriteDebug($"**Ratio {currentMaxBoneRatio}"); + Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + + return new DetectionPenaltyResult() + { + ClientPenalty = Penalty.PenaltyType.Ban, + RatioAmount = currentMaxBoneRatio, + Bone = bone, + KillCount = Kills + }; + } + else + { + Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**"); + Log.WriteDebug($"ClientId: {kill.AttackerId}"); + Log.WriteDebug($"**Kills: {Kills}"); + Log.WriteDebug($"**Ratio {currentMaxBoneRatio}"); + Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + + return new DetectionPenaltyResult() + { + ClientPenalty = Penalty.PenaltyType.Flag, + RatioAmount = currentMaxBoneRatio, + Bone = bone, + KillCount = Kills + }; + } + } + #endregion +} + +#region CHEST_ABDOMEN_RATIO_SESSION +int chestKills = HitLocationCount[IW4Info.HitLocation.torso_upper]; + +if (chestKills >= Thresholds.MediumSampleMinKills) +{ + double marginOfError = Thresholds.GetMarginOfError(chestKills); + double lerpAmount = Math.Min(1.0, (chestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); + // determine max acceptable ratio of chest to abdomen kills + double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3), Thresholds.ChestAbdomenRatioThresholdHighSample(3), lerpAmount) + marginOfError; + double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(4), Thresholds.ChestAbdomenRatioThresholdHighSample(4), lerpAmount) + marginOfError; + + double currentChestAbdomenRatio = HitLocationCount[IW4Info.HitLocation.torso_upper] / (double)HitLocationCount[IW4Info.HitLocation.torso_lower]; + + if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag) + { + + if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestKills >= Thresholds.MediumSampleMinKills + 30) + { + Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**"); + Log.WriteDebug($"ClientId: {kill.AttackerId}"); + Log.WriteDebug($"**Chest Kills: {chestKills}"); + Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); + Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); + + return new DetectionPenaltyResult() + { + ClientPenalty = Penalty.PenaltyType.Ban, + RatioAmount = currentChestAbdomenRatio, + Bone = 0, + KillCount = chestKills + }; + } + else + { + Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**"); + Log.WriteDebug($"ClientId: {kill.AttackerId}"); + Log.WriteDebug($"**Chest Kills: {chestKills}"); + Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); + Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); + + return new DetectionPenaltyResult() + { + ClientPenalty = Penalty.PenaltyType.Flag, + RatioAmount = currentChestAbdomenRatio, + Bone = 0, + KillCount = chestKills }; } } } +#endregion +#endregion +return new DetectionPenaltyResult() +{ + ClientPenalty = Penalty.PenaltyType.Any, + RatioAmount = 0 +}; +} + +public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats) +{ +int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.left_arm_upper).HitCount; + +if (totalChestKills >= 250) +{ + double marginOfError = Thresholds.GetMarginOfError(totalChestKills); + double lerpAmount = Math.Min(1.0, (totalChestKills - Thresholds.LowSampleMinKills) / (double)(Thresholds.HighSampleMinKills - Thresholds.LowSampleMinKills)); + // determine max acceptable ratio of chest to abdomen kills + double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(2.25), Thresholds.ChestAbdomenRatioThresholdHighSample(2.25), lerpAmount) + marginOfError; + double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdLowSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), lerpAmount) + marginOfError; + + double currentChestAbdomenRatio = HitLocationCount[IW4Info.HitLocation.torso_upper] / (double)HitLocationCount[IW4Info.HitLocation.torso_lower]; + + if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag) + { + + if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan) + { + Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**"); + Log.WriteDebug($"ClientId: {stats.ClientId}"); + Log.WriteDebug($"**Total Chest Kills: {totalChestKills}"); + Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); + Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); + + return new DetectionPenaltyResult() + { + ClientPenalty = Penalty.PenaltyType.Ban, + RatioAmount = currentChestAbdomenRatio, + Bone = IW4Info.HitLocation.torso_upper, + KillCount = totalChestKills + }; + } + else + { + Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**"); + Log.WriteDebug($"ClientId: {stats.ClientId}"); + Log.WriteDebug($"**Total Chest Kills: {totalChestKills}"); + Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); + Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}"); + var sb = new StringBuilder(); + foreach (var kvp in HitLocationCount) + sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n"); + Log.WriteDebug(sb.ToString()); + // Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}"); + + return new DetectionPenaltyResult() + { + ClientPenalty = Penalty.PenaltyType.Flag, + RatioAmount = currentChestAbdomenRatio, + Bone = IW4Info.HitLocation.torso_upper, + KillCount = totalChestKills + }; + } + } +} + +return new DetectionPenaltyResult() +{ + Bone = IW4Info.HitLocation.none, + ClientPenalty = Penalty.PenaltyType.Any +}; +} +} +} diff --git a/Plugins/SimpleStats/Helpers/Extensions.cs b/Plugins/SimpleStats/Helpers/Extensions.cs index ef46f1091..227e074bb 100644 --- a/Plugins/SimpleStats/Helpers/Extensions.cs +++ b/Plugins/SimpleStats/Helpers/Extensions.cs @@ -12,11 +12,11 @@ namespace StatsPlugin.Helpers public static Vector3 FixIW4Angles(this Vector3 vector) { - float X = vector.X > 0 ? 360.0f - vector.X : Math.Abs(vector.X); - float Y = vector.Y > 0 ? 360.0f - vector.Y : Math.Abs(vector.Y); - float Z = vector.Z > 0 ? 360.0f - vector.Z : Math.Abs(vector.Z); + float X = vector.X >= 0 ? vector.X : 360.0f + vector.X; + float Y = vector.Y >= 0 ? vector.Y : 360.0f + vector.Y; + float Z = vector.Z >= 0 ? vector.Z : 360.0f + vector.Z; - return new Vector3(X, Y, Z); + return new Vector3(Y, X, Z); } public static float ToRadians(this float value) => (float)Math.PI * value / 180.0f; diff --git a/Plugins/SimpleStats/Helpers/StatManager.cs b/Plugins/SimpleStats/Helpers/StatManager.cs index 6a68a24fe..b7b8bcebd 100644 --- a/Plugins/SimpleStats/Helpers/StatManager.cs +++ b/Plugins/SimpleStats/Helpers/StatManager.cs @@ -205,7 +205,7 @@ namespace StatsPlugin.Helpers /// /// public async Task AddScriptKill(Player attacker, Player victim, int serverId, string map, string hitLoc, string type, - string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset) + string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads) { var statsSvc = ContextThreads[serverId]; @@ -224,7 +224,9 @@ namespace StatsPlugin.Helpers Weapon = ParseEnum.Get(weapon, typeof(IW4Info.WeaponName)), ViewAngles = Vector3.Parse(viewAngles).FixIW4Angles(), TimeOffset = Int64.Parse(offset), - When = DateTime.UtcNow + When = DateTime.UtcNow, + IsKillstreakKill = isKillstreakKill[0] != '0', + AdsPercent = float.Parse(Ads) }; if (kill.DeathType == IW4Info.MeansOfDeath.MOD_SUICIDE && @@ -236,6 +238,11 @@ namespace StatsPlugin.Helpers await AddStandardKill(attacker, victim); + if (kill.IsKillstreakKill) + { + return; + } + var playerDetection = Servers[serverId].PlayerDetections[attacker.ClientId]; var playerStats = Servers[serverId].PlayerStats[attacker.ClientId]; diff --git a/Plugins/SimpleStats/Models/EFClientKill.cs b/Plugins/SimpleStats/Models/EFClientKill.cs index 948c5a161..316ec6235 100644 --- a/Plugins/SimpleStats/Models/EFClientKill.cs +++ b/Plugins/SimpleStats/Models/EFClientKill.cs @@ -32,13 +32,17 @@ namespace StatsPlugin.Models public IW4Info.WeaponName Weapon { get; set; } public Vector3 KillOrigin { get; set; } public Vector3 DeathOrigin { get; set; } + public Vector3 ViewAngles { get; set; } + public DateTime When { get; set; } // http://wiki.modsrepository.com/index.php?title=Call_of_Duty_5:_Gameplay_standards for conversion to meters [NotMapped] public double Distance => Vector3.Distance(KillOrigin, DeathOrigin) * 0.0254; public IW4Info.MapName Map { get; set; } [NotMapped] public long TimeOffset { get; set; } - public Vector3 ViewAngles { get; set; } - public DateTime When { get; set; } + [NotMapped] + public bool IsKillstreakKill { get; set; } + [NotMapped] + public float AdsPercent { get; set; } } } diff --git a/Plugins/SimpleStats/Plugin.cs b/Plugins/SimpleStats/Plugin.cs index bea22473b..965d1237c 100644 --- a/Plugins/SimpleStats/Plugin.cs +++ b/Plugins/SimpleStats/Plugin.cs @@ -75,7 +75,7 @@ namespace StatsPlugin string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; if (killInfo.Length >= 9 && killInfo[0].Contains("ScriptKill") && E.Owner.CustomCallback) await Manager.AddScriptKill(E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8], - killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10]); + killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12]); else if (!E.Owner.CustomCallback) await Manager.AddStandardKill(E.Origin, E.Target); break; diff --git a/SharedLibrary/Helpers/Vector3.cs b/SharedLibrary/Helpers/Vector3.cs index b51c12bdd..d15307468 100644 --- a/SharedLibrary/Helpers/Vector3.cs +++ b/SharedLibrary/Helpers/Vector3.cs @@ -38,7 +38,7 @@ namespace SharedLibrary.Helpers public static double Distance(Vector3 a, Vector3 b) { - return Math.Round(Math.Sqrt(Math.Pow(b.X - a.X, 2) + Math.Pow(b.Y - a.Y, 2) + Math.Pow(b.Z - a.Z, 2)), 2); + return Math.Sqrt(Math.Pow(b.X - a.X, 2) + Math.Pow(b.Y - a.Y, 2) + Math.Pow(b.Z - a.Z, 2)); } public static Vector3 Subtract(Vector3 a, Vector3 b) => new Vector3(b.X - a.X, b.Y - a.Y, b.Z - a.Z); diff --git a/SharedLibrary/Server.cs b/SharedLibrary/Server.cs index 581dca478..7869474f6 100644 --- a/SharedLibrary/Server.cs +++ b/SharedLibrary/Server.cs @@ -246,7 +246,9 @@ namespace SharedLibrary protected void InitializeMaps() { Maps = new List(); - Maps.AddRange(Manager.GetApplicationSettings().Configuration().Maps.First(m => m.Game == GameName).Maps); + var gameMaps = Manager.GetApplicationSettings().Configuration().Maps.FirstOrDefault(m => m.Game == GameName); + if (gameMaps != null) + Maps.AddRange(gameMaps.Maps); } /// diff --git a/WebfrontCore/Application/Server.cs b/WebfrontCore/Application/Server.cs index 602870d00..da9e98a06 100644 --- a/WebfrontCore/Application/Server.cs +++ b/WebfrontCore/Application/Server.cs @@ -46,6 +46,7 @@ namespace IW4MAdmin return true; } +#if !DEBUG if (polledPlayer.Name.Length < 3) { Logger.WriteDebug($"Kicking {polledPlayer} because their name is too short"); @@ -76,6 +77,7 @@ namespace IW4MAdmin return false; } +#endif Logger.WriteDebug($"Client slot #{polledPlayer.ClientNumber} now reserved"); try @@ -656,7 +658,7 @@ namespace IW4MAdmin LogFile = new IFile(logPath); //#else } - // LogFile = new RemoteFile("https://raidmax.org/IW4MAdmin/getlog.php"); + LogFile = new RemoteFile("https://raidmax.org/IW4MAdmin/getlog.php"); //#endif Logger.WriteInfo($"Log file is {logPath}"); #if !DEBUG diff --git a/WebfrontCore/Controllers/BaseController.cs b/WebfrontCore/Controllers/BaseController.cs index 5c5f74135..57a5e27bf 100644 --- a/WebfrontCore/Controllers/BaseController.cs +++ b/WebfrontCore/Controllers/BaseController.cs @@ -23,7 +23,10 @@ namespace WebfrontCore.Controllers ViewBag.Authorized = Authorized; ViewBag.Url = Startup.Configuration["Web:Address"]; string inviteLink = Manager.GetApplicationSettings().Configuration().DiscordInviteCode; - ViewBag.DiscordLink = inviteLink != null && inviteLink.Contains("http") ? inviteLink : $"https://discordapp.com/invite/{inviteLink}"; + if (inviteLink != null) + ViewBag.DiscordLink = inviteLink.Contains("https") ? inviteLink : $"https://discordapp.com/invite/{inviteLink}"; + else + ViewBag.DiscorLink = ""; base.OnActionExecuting(context); } } diff --git a/WebfrontCore/Controllers/PenaltyController.cs b/WebfrontCore/Controllers/PenaltyController.cs index 8a72cf3a3..c3836b122 100644 --- a/WebfrontCore/Controllers/PenaltyController.cs +++ b/WebfrontCore/Controllers/PenaltyController.cs @@ -24,7 +24,7 @@ namespace WebfrontCore.Controllers public async Task ListAsync(int offset = 0) { - return View("_List", offset); + return await Task.FromResult(View("_List", offset)); } public async Task PublicAsync() diff --git a/WebfrontCore/Views/Client/Profile/Index.cshtml b/WebfrontCore/Views/Client/Profile/Index.cshtml index d61de3dd8..e4da0021a 100644 --- a/WebfrontCore/Views/Client/Profile/Index.cshtml +++ b/WebfrontCore/Views/Client/Profile/Index.cshtml @@ -20,6 +20,22 @@ } + @{ + if (ViewBag.Authorized) + { + if (Model.Level == SharedLibrary.Objects.Player.Permission.User.ToString()) + { + + + } + + if (Model.Level == SharedLibrary.Objects.Player.Permission.Banned.ToString()) + { + + } + } + } +
diff --git a/WebfrontCore/Views/Shared/Error.cshtml b/WebfrontCore/Views/Shared/Error.cshtml index 485244268..296561067 100644 --- a/WebfrontCore/Views/Shared/Error.cshtml +++ b/WebfrontCore/Views/Shared/Error.cshtml @@ -2,5 +2,5 @@ ViewData["Title"] = "Error"; } -

Error.

-

An error occurred while processing your request.

+

Sorry!

+

An error occurred while processing your request.

diff --git a/WebfrontCore/Views/Shared/_Layout.cshtml b/WebfrontCore/Views/Shared/_Layout.cshtml index 9afb77e36..dd9349ee9 100644 --- a/WebfrontCore/Views/Shared/_Layout.cshtml +++ b/WebfrontCore/Views/Shared/_Layout.cshtml @@ -6,7 +6,7 @@ @ViewBag.Title | IW4MAdmin - + diff --git a/_customcallbacks.gsc b/_customcallbacks.gsc index 60ef68166..5bf29bcd5 100644 --- a/_customcallbacks.gsc +++ b/_customcallbacks.gsc @@ -68,12 +68,12 @@ Callback_PlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vD _attacker = attacker.owner; else if(!isPlayer(attacker) && sMeansOfDeath == "MOD_FALLING") _attacker = victim; - + + location = victim GetTagOrigin(hitLocationToBone(sHitLoc)); - //attacker iPrintLnBold(location); - //attacker iPrintLnBold(attacker.origin[0]); + isKillstreakKill = !isPlayer(attacker) || isKillstreakWeapon(sWeapon); /*BulletTrace(_attacker GetTagOrigin("tag_eye"), VectorScale(anglesToForward(attacker getPlayerAngles())), true, attacker)["entity"]*/ - logPrint("ScriptKill;" + _attacker.guid + ";" + victim.guid + ";" + _attacker GetTagOrigin("tag_eye") + ";" + location + ";" + iDamage + ";" + sWeapon + ";" + sHitLoc + ";" + sMeansOfDeath + ";" + _attacker getPlayerAngles() + ";" + gettime() + "\n"); + logPrint("ScriptKill;" + _attacker.guid + ";" + victim.guid + ";" + _attacker GetTagOrigin("tag_eye") + ";" + location + ";" + iDamage + ";" + sWeapon + ";" + sHitLoc + ";" + sMeansOfDeath + ";" + _attacker getPlayerAngles() + ";" + gettime() + ";" + isKillstreakKill + ";" + _attacker playerADS() + "\n"); self maps\mp\gametypes\_damage::Callback_PlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ); } \ No newline at end of file