From 65959bff2631fe75f17a53d3192200933f4b2c2b Mon Sep 17 00:00:00 2001 From: MathiasL Date: Sat, 14 May 2022 23:28:02 +0200 Subject: [PATCH] Add taser to weapon list * Taser has new shock damage type, that doesn't account for multipliers/armor --- .../DamageCalculator/MainWindow.xaml.cs | 92 ++++++++++--------- .../SteamHelpers/SteamHelpers/CsgoHelper.cs | 58 ++++++++++-- .../SteamHelpers/Models/CsgoWeapon.cs | 8 ++ 3 files changed, 110 insertions(+), 48 deletions(-) diff --git a/DamageCalculator/DamageCalculator/MainWindow.xaml.cs b/DamageCalculator/DamageCalculator/MainWindow.xaml.cs index 886bfbd..3ddeb6d 100644 --- a/DamageCalculator/DamageCalculator/MainWindow.xaml.cs +++ b/DamageCalculator/DamageCalculator/MainWindow.xaml.cs @@ -1055,51 +1055,59 @@ namespace Damage_Calculator // Range damage *= Math.Pow(this.selectedWeapon.DamageDropoff, double.Parse((this.unitsDistance / 500f).ToString())); - // Multipliers and armor penetration - if (radioHead.IsChecked == true) + switch (this.selectedWeapon.DamageType) { - // Headshot - damage *= this.selectedWeapon.HeadshotModifier; + case DamageType.Shock: + // Deals the same damage everywhere + break; + case DamageType.Bullet: + // Multipliers and armor penetration + if (radioHead.IsChecked == true) + { + // Headshot + damage *= this.selectedWeapon.HeadshotModifier; - if (chkHelmet.IsChecked == true) - { - // Has helmet - double previousDamage = damage; - damage *= this.selectedWeapon.ArmorPenetration / 100f; - absorbedDamageByArmor = previousDamage - (int)damage; - wasArmorHit = true; - } - } - else if (radioChestArms.IsChecked == true) - { - // Chest or arms - if (chkKevlar.IsChecked == true) - { - // Has kevlar - double previousDamage = damage; - damage *= this.selectedWeapon.ArmorPenetration / 100f; - absorbedDamageByArmor = previousDamage - (int)damage; - wasArmorHit = true; - } - } - else if (radioStomach.IsChecked == true) - { - // Stomach - damage *= 1.25f; + if (chkHelmet.IsChecked == true) + { + // Has helmet + double previousDamage = damage; + damage *= this.selectedWeapon.ArmorPenetration / 100f; + absorbedDamageByArmor = previousDamage - (int)damage; + wasArmorHit = true; + } + } + else if (radioChestArms.IsChecked == true) + { + // Chest or arms + if (chkKevlar.IsChecked == true) + { + // Has kevlar + double previousDamage = damage; + damage *= this.selectedWeapon.ArmorPenetration / 100f; + absorbedDamageByArmor = previousDamage - (int)damage; + wasArmorHit = true; + } + } + else if (radioStomach.IsChecked == true) + { + // Stomach + damage *= 1.25f; - if (chkKevlar.IsChecked == true) - { - // Has kevlar - double previousDamage = damage; - damage *= this.selectedWeapon.ArmorPenetration / 100f; - absorbedDamageByArmor = previousDamage - (int)damage; - wasArmorHit = true; - } - } - else - { - // Legs - damage *= 0.75f; + if (chkKevlar.IsChecked == true) + { + // Has kevlar + double previousDamage = damage; + damage *= this.selectedWeapon.ArmorPenetration / 100f; + absorbedDamageByArmor = previousDamage - (int)damage; + wasArmorHit = true; + } + } + else + { + // Legs + damage *= 0.75f; + } + break; } txtResult.Text = ((int)damage).ToString(); diff --git a/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs b/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs index d4e0925..265a047 100644 --- a/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs +++ b/Shared/SteamHelpers/SteamHelpers/CsgoHelper.cs @@ -235,11 +235,12 @@ namespace Shared Element items = vdfItems["items_game"]?["items"]!; if (prefabs == null || items == null) + // There is no prefab list or item list to read out return null!; var weapons = new List(); - foreach(var item in items.Children) + foreach (var item in items.Children) { string? itemPrefab = item["prefab"]?.Value!; string? itemName = item["name"].Value; @@ -247,11 +248,25 @@ namespace Shared if (itemPrefab == null || !itemName!.StartsWith("weapon_")) continue; + // Here we're sure the item is supposed to be a weapon + var weapon = new CsgoWeapon(); weapon.ClassName = itemName; - if(this.tryPopulateWeapon(weapon, prefabs, itemPrefab)) + // Handle weapon specific modifications before fetching its attributes + switch (weapon.ClassName) { + case "weapon_taser": + weapon.DamageType = DamageType.Shock; + break; + default: + weapon.DamageType = DamageType.Bullet; + break; + } + + if (this.tryPopulateWeapon(weapon, prefabs, itemPrefab)) + { + // Item has an initial prefab and is allowed based on the conditions met in isWeaponFireable() weapons.Add(weapon); } } @@ -259,8 +274,29 @@ namespace Shared return weapons; } + private bool isWeaponFireable(CsgoWeapon weapon, List? prefabTrace) + { + bool isWhitelisted = false; + + if(prefabTrace != null) + { + // Stuff involving prefab trace here + if(prefabTrace.FirstOrDefault(pr => pr == "primary" || pr == "secondary") != null) + // Allow any weapon in the primary or secondary slot + isWhitelisted = true; + } + + // Other + if(weapon.ClassName == "weapon_taser") + // Allow zeus, even though it's "equipment" and listed in the melee slot + isWhitelisted = true; + + return isWhitelisted; + } + private bool tryPopulateWeapon(CsgoWeapon weapon, Element prefabs, string prefabName, List? prefabTrace = null) { + // Get the initial prefab specified in the item Element prefab = prefabs[prefabName]; if (prefab == null) @@ -269,16 +305,24 @@ namespace Shared string nextPrefab = prefab["prefab"]?.Value!; - if (prefab == null || (nextPrefab == null && prefabTrace?.FirstOrDefault(pr => pr == "primary" || pr == "secondary") == null)) + if (nextPrefab == null) // We've reached the end of abstraction but it wasn't found to be primary nor secondary - return false; + // However the taser is special because it's "equipment" and not primary or secondary. + // So we will treat it like a special lil guy and add him either way + if (!this.isWeaponFireable(weapon, prefabTrace)) + { + // We're done but we don't want this fucker included as a weapon + return false; + } bool gatheredAllInfo = true; Element attributes = prefab["attributes"]; - if (attributes == null) - return false; + if (attributes == null && nextPrefab != null) + // it might have no attributes but just skip to the next prefab in that case, because they might have attributes + // one example of this is the taser (zeus) + return this.tryPopulateWeapon(weapon, prefabs, nextPrefab, prefabTrace); // =========================== ATTRIBUTES =========================== // @@ -365,6 +409,8 @@ namespace Shared // ================================================================== // if (gatheredAllInfo || nextPrefab == null) + // We've got all we need or we've reached the end of abstraction + // We're sure the weapon is for example either primary, secondary or it's the zeus, since it's treated as "equipment" instead return true; // ? if (prefabTrace == null) diff --git a/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs b/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs index 1bde349..4a29905 100644 --- a/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs +++ b/Shared/SteamHelpers/SteamHelpers/Models/CsgoWeapon.cs @@ -45,5 +45,13 @@ namespace Shared.Models /// Gets or sets the multiplier of headshots by this weapon. At the point of writing this is "4" for all weapons except two. /// public float HeadshotModifier { get; set; } = -1; + + /// + /// Gets or sets the type of damage done by this weapon. + /// Used for damage multipliers, since shock damage deals the same damage on every hitgroup. + /// + public DamageType DamageType { get; set; } } + + public enum DamageType { Bullet, Shock } }