diff --git a/.gitignore b/.gitignore index 3237856..4edc121 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,5 @@ -# Created by https://www.toptal.com/developers/gitignore/api/rider -# Edit at https://www.toptal.com/developers/gitignore?templates=rider - -### Custom ### -DamageTrackingFramework/obj -DamageTrackingFramework/bin -.idea/.idea.DamageTrackerUtility/.idea/*.xml -References +# Created by https://www.toptal.com/developers/gitignore/api/visualstudio,rider +# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudio,rider ### Rider ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider @@ -86,4 +80,405 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser -# End of https://www.toptal.com/developers/gitignore/api/rider +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +### VisualStudio Patch ### +# Additional files built by Visual Studio + +# End of https://www.toptal.com/developers/gitignore/api/visualstudio,rider diff --git a/.vs/DamageTrackerUtility/v16/.suo b/.vs/DamageTrackerUtility/v16/.suo new file mode 100644 index 0000000..91af490 Binary files /dev/null and b/.vs/DamageTrackerUtility/v16/.suo differ diff --git a/DamageTrackingFramework/DamageInfo/BodyRegion.cs b/DamageTrackerLib/DamageInfo/BodyRegion.cs similarity index 71% rename from DamageTrackingFramework/DamageInfo/BodyRegion.cs rename to DamageTrackerLib/DamageInfo/BodyRegion.cs index be8dfb6..e96ac5f 100644 --- a/DamageTrackingFramework/DamageInfo/BodyRegion.cs +++ b/DamageTrackerLib/DamageInfo/BodyRegion.cs @@ -1,4 +1,4 @@ -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { public enum BodyRegion { diff --git a/DamageTrackingFramework/DamageInfo/BoneDamageInfo.cs b/DamageTrackerLib/DamageInfo/BoneDamageInfo.cs similarity index 57% rename from DamageTrackingFramework/DamageInfo/BoneDamageInfo.cs rename to DamageTrackerLib/DamageInfo/BoneDamageInfo.cs index e220b67..06d28e8 100644 --- a/DamageTrackingFramework/DamageInfo/BoneDamageInfo.cs +++ b/DamageTrackerLib/DamageInfo/BoneDamageInfo.cs @@ -1,7 +1,10 @@ using System; -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { + /// + /// Holds info on the Bone that was damaged on the Ped. + /// [Serializable] public struct BoneDamageInfo { diff --git a/DamageTrackingFramework/DamageInfo/BoneId.cs b/DamageTrackerLib/DamageInfo/BoneId.cs similarity index 91% rename from DamageTrackingFramework/DamageInfo/BoneId.cs rename to DamageTrackerLib/DamageInfo/BoneId.cs index bed73a9..55d3818 100644 --- a/DamageTrackingFramework/DamageInfo/BoneId.cs +++ b/DamageTrackerLib/DamageInfo/BoneId.cs @@ -1,5 +1,8 @@ -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { + /// + /// Complete set of BoneIds. Should be cast-able to RagePluginHook BoneIds however, RPH has no "Root" bone which is 0. + /// public enum BoneId : ushort { LeftThumb1 = 4089, // 0x0FF9 diff --git a/DamageTrackingFramework/DamageInfo/DamageGroup.cs b/DamageTrackerLib/DamageInfo/DamageGroup.cs similarity index 78% rename from DamageTrackingFramework/DamageInfo/DamageGroup.cs rename to DamageTrackerLib/DamageInfo/DamageGroup.cs index e37a67a..6543590 100644 --- a/DamageTrackingFramework/DamageInfo/DamageGroup.cs +++ b/DamageTrackerLib/DamageInfo/DamageGroup.cs @@ -1,4 +1,4 @@ -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { public enum DamageGroup { @@ -15,7 +15,7 @@ public enum DamageGroup Environmental = 11, Gas = 12, WaterCannon = 13, - Medical = 14, - Drowning = 15 + Bodily = 14, + Drowning = 15, } } \ No newline at end of file diff --git a/DamageTrackingFramework/DamageInfo/DamageType.cs b/DamageTrackerLib/DamageInfo/DamageType.cs similarity index 85% rename from DamageTrackingFramework/DamageInfo/DamageType.cs rename to DamageTrackerLib/DamageInfo/DamageType.cs index 1a55149..fd25ed4 100644 --- a/DamageTrackingFramework/DamageInfo/DamageType.cs +++ b/DamageTrackerLib/DamageInfo/DamageType.cs @@ -1,5 +1,4 @@ -// ReSharper disable InconsistentNaming -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { public enum DamageType { @@ -20,7 +19,7 @@ public enum DamageType Misc = 14, NonDamaging = 15, WaterCannon = 16, - Medical = 17, + Bodily = 17, // Bleeding, Exhaustion Drowning = 18, Animal = 19, Vehicle = 20, diff --git a/DamageTrackingFramework/DamageInfo/Limb.cs b/DamageTrackerLib/DamageInfo/Limb.cs similarity index 78% rename from DamageTrackingFramework/DamageInfo/Limb.cs rename to DamageTrackerLib/DamageInfo/Limb.cs index e91728b..8e0db8f 100644 --- a/DamageTrackingFramework/DamageInfo/Limb.cs +++ b/DamageTrackerLib/DamageInfo/Limb.cs @@ -1,4 +1,4 @@ -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { public enum Limb { diff --git a/DamageTrackerLib/DamageInfo/PedDamageInfo.cs b/DamageTrackerLib/DamageInfo/PedDamageInfo.cs new file mode 100644 index 0000000..c9514e3 --- /dev/null +++ b/DamageTrackerLib/DamageInfo/PedDamageInfo.cs @@ -0,0 +1,18 @@ +using System; + +namespace DamageTrackerLib.DamageInfo +{ + /// + /// Holds all info for a Ped's damage. + /// + [Serializable] + public struct PedDamageInfo + { + public uint PedHandle; + public uint AttackerPedHandle; + public int Damage; + public int ArmourDamage; + public WeaponDamageInfo WeaponInfo; + public BoneDamageInfo BoneInfo; + } +} \ No newline at end of file diff --git a/DamageTrackingFramework/DamageInfo/WeaponDamageInfo.cs b/DamageTrackerLib/DamageInfo/WeaponDamageInfo.cs similarity index 57% rename from DamageTrackingFramework/DamageInfo/WeaponDamageInfo.cs rename to DamageTrackerLib/DamageInfo/WeaponDamageInfo.cs index e654eb9..807550e 100644 --- a/DamageTrackingFramework/DamageInfo/WeaponDamageInfo.cs +++ b/DamageTrackerLib/DamageInfo/WeaponDamageInfo.cs @@ -1,7 +1,10 @@ using System; -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { + /// + /// Holds info on the Weapon/Thing that damaged the Ped. + /// [Serializable] public struct WeaponDamageInfo { diff --git a/DamageTrackingFramework/DamageInfo/WeaponHash.cs b/DamageTrackerLib/DamageInfo/WeaponHash.cs similarity index 93% rename from DamageTrackingFramework/DamageInfo/WeaponHash.cs rename to DamageTrackerLib/DamageInfo/WeaponHash.cs index d34dfe6..d200473 100644 --- a/DamageTrackingFramework/DamageInfo/WeaponHash.cs +++ b/DamageTrackerLib/DamageInfo/WeaponHash.cs @@ -1,6 +1,8 @@ -// ReSharper disable InconsistentNaming -namespace DamageTrackingFramework.DamageInfo +namespace DamageTrackerLib.DamageInfo { + /// + /// Complete set of Weapon Hashes. + /// public enum WeaponHash : uint { Unknown = 0, @@ -85,7 +87,7 @@ public enum WeaponHash : uint Ray_Minigun = 3056410471, Grenade = 2481070269, BZGas = 2694266206, - Smoke_Grenade = 4256991824, + Tear_Gas = 4256991824, Flare = 1233104067, Molotov = 615608432, Sticky_Bomb = 741814745, @@ -232,5 +234,21 @@ public enum WeaponHash : uint Vehicle_Volatol_Dual_MG = 1150790720, Vehicle_Water_Cannon = 1741783703, Vehicle_Helicopter_Rotors = 2971687502, + + // 0.9.9 + Military_Rifle = 0x9D1F17E6, + Heavy_Rifle = 0xC78D71B4, + Service_Carbine = 3520460075, + Precision_Rifle = 1853742572, + Combat_Shotgun = 94989220, + Compact_EMP_Launcher = 3676729658, + Railgun_XM3 = 4272043364, + Stun_Gun_MP = 1171102963, + Perico_Pistol = 1470379660, + WM29_Pistol = 465894841, + Navy_Revolver = 2441047180, + Ceramic_Pistol = 727643628, + Candy_Cane = 1703483498, + Custom = 694201337, } } \ No newline at end of file diff --git a/DamageTrackerLib/DamageTrackerLib.csproj b/DamageTrackerLib/DamageTrackerLib.csproj new file mode 100644 index 0000000..296e85b --- /dev/null +++ b/DamageTrackerLib/DamageTrackerLib.csproj @@ -0,0 +1,73 @@ + + + + + Debug + AnyCPU + {8BA678B1-D73D-4B13-8D42-F6750285E52A} + Library + Properties + DamageTrackerLib + DamageTrackerLib + v4.8 + 512 + 10 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + ..\packages\RagePluginHook.1.98.0\lib\net472\RagePluginHook.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DamageTrackerLib/DamageTrackerLookups.cs b/DamageTrackerLib/DamageTrackerLookups.cs new file mode 100644 index 0000000..70f58e2 --- /dev/null +++ b/DamageTrackerLib/DamageTrackerLookups.cs @@ -0,0 +1,327 @@ +using System.Collections.Generic; +using DamageTrackerLib.DamageInfo; + +namespace DamageTrackerLib +{ + public static class DamageTrackerLookups + { + /// + /// Lookups for the Bones. It is not recommended to change/use these values. + /// + public static readonly Dictionary + BoneLookup = + new() + { + [BoneId.Root] = (Limb.Stomach, BodyRegion.Torso), + [BoneId.LeftThumb1] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftThumb2] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftRingFinger1] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftRingFinger2] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftPinky1] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftPinky2] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftIndexFinger1] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftIndexFinger2] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftMiddleFinger1] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftMiddleFinger2] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.RightClavicle] = (Limb.Chest, BodyRegion.Torso), + [BoneId.Pelvis] = (Limb.Stomach, BodyRegion.Torso), + [BoneId.LeftFoot] = (Limb.LeftLeg, BodyRegion.Legs), + [BoneId.LeftHand] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.Spine] = (Limb.Stomach, BodyRegion.Torso), + [BoneId.RightPhFoot] = (Limb.RightLeg, BodyRegion.Legs), + [BoneId.Spine1] = (Limb.Stomach, BodyRegion.Torso), + [BoneId.Spine2] = (Limb.Chest, BodyRegion.Torso), + [BoneId.Spine3] = (Limb.Chest, BodyRegion.Torso), + [BoneId.LeftThumb0] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftIndexFinger0] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftMiddleFinger0] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftRingFinger0] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftPinky0] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.RightForearm] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightPhHand] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.Head] = (Limb.Head, BodyRegion.Head), + [BoneId.RightCalf] = (Limb.RightLeg, BodyRegion.Legs), + [BoneId.Neck] = (Limb.Head, BodyRegion.Head), + [BoneId.RightUpperArm] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.LeftUpperArm] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.RightThigh] = (Limb.RightLeg, BodyRegion.Legs), + [BoneId.RightFoot] = (Limb.RightLeg, BodyRegion.Legs), + [BoneId.RightHand] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.SpineRoot] = (Limb.Stomach, BodyRegion.Torso), + [BoneId.LeftPhFoot] = (Limb.LeftLeg, BodyRegion.Arms), + [BoneId.LeftThigh] = (Limb.LeftLeg, BodyRegion.Legs), + [BoneId.RightThumb0] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightIndexFinger0] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightMiddleFinger0] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightRingFinger0] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightPinky0] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.LeftPhHand] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftForeArm] = (Limb.LeftArm, BodyRegion.Arms), + [BoneId.LeftCalf] = (Limb.LeftLeg, BodyRegion.Legs), + [BoneId.RightThumb1] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightThumb2] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightRingFinger1] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightRingFinger2] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightPinky1] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightPinky2] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightIndexFinger1] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightIndexFinger2] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightMiddleFinger1] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.RightMiddleFinger2] = (Limb.RightArm, BodyRegion.Arms), + [BoneId.LeftClavicle] = (Limb.Chest, BodyRegion.Torso), + }; + + + /// + /// Lookups for the Weapons. It is not recommended to change/use these values. + /// + public static readonly Dictionary + WeaponLookup = + new() + { + [WeaponHash.Unknown] = (DamageGroup.Unknown, DamageType.Unknown), + [WeaponHash.Antique_Cavalry_Dagger] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Baseball_Bat] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Bottle] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Crowbar] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Fist] = (DamageGroup.Melee, DamageType.Unarmed), + [WeaponHash.Flashlight] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Golf_Club] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Hammer] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Hatchet] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Knuckle] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Knife] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Machete] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Switchblade] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Nightstick] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Pipe_Wrench] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Battle_Axe] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Pool_Cue] = (DamageGroup.Melee, DamageType.MeleeBlunt), + [WeaponHash.Stone_Hatchet] = (DamageGroup.Melee, DamageType.MeleeStab), + [WeaponHash.Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Pistol_MK2] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Combat_Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.APPistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Stun_Gun] = (DamageGroup.LessThanLethal, DamageType.LessThanLethal), + [WeaponHash.Pistol50] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.SNSPistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.SNSPistol_MK2] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Heavy_Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Vintage_Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Flare_Gun] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Marksman_Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Heavy_Revolver] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Heavy_Revolver_MK2] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Double_Action] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Up_n_Atomizer] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Micro_SMG] = (DamageGroup.Bullet, DamageType.SMG), + [WeaponHash.SMG] = (DamageGroup.Bullet, DamageType.SMG), + [WeaponHash.SMGMK2] = (DamageGroup.Bullet, DamageType.SMG), + [WeaponHash.Assault_SMG] = (DamageGroup.Bullet, DamageType.SMG), + [WeaponHash.Combat_PDW] = (DamageGroup.Bullet, DamageType.SMG), + [WeaponHash.Machine_Pistol] = (DamageGroup.Bullet, DamageType.SMG), + [WeaponHash.Mini_SMG] = (DamageGroup.Bullet, DamageType.SMG), + [WeaponHash.Unholy_Hellbringer] = (DamageGroup.Bullet, DamageType.MG), + [WeaponHash.Pump_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Pump_Shotgun_MK2] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Sawed_Off_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Assault_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Bullpup_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Musket] = (DamageGroup.Bullet, DamageType.Sniper), + [WeaponHash.Heavy_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Double_Barrel_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Sweeper_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Assault_Rifle] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Assault_Rifle_MK2] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Carbine_Rifle] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Carbine_Rifle_MK2] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Advanced_Rifle] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Special_Carbine] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Special_Carbine_MK2] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Bullpup_Rifle] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Bullpup_Rifle_MK2] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Compact_Rifle] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.MG] = (DamageGroup.Bullet, DamageType.MG), + [WeaponHash.Combat_MG] = (DamageGroup.Bullet, DamageType.MG), + [WeaponHash.Combat_MGMK2] = (DamageGroup.Bullet, DamageType.MG), + [WeaponHash.Gusenberg_Sweeper] = (DamageGroup.Bullet, DamageType.MG), + [WeaponHash.Sniper_Rifle] = (DamageGroup.Bullet, DamageType.Sniper), + [WeaponHash.Heavy_Sniper] = (DamageGroup.Bullet, DamageType.Sniper), + [WeaponHash.Heavy_Sniper_MK2] = (DamageGroup.Bullet, DamageType.Sniper), + [WeaponHash.Marksman_Rifle] = (DamageGroup.Bullet, DamageType.Sniper), + [WeaponHash.Marksman_Rifle_MK2] = (DamageGroup.Bullet, DamageType.Sniper), + [WeaponHash.RPG] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Grenade_Launcher] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Smoke_Grenade_Launcher] = (DamageGroup.NonDamaging, DamageType.Launcher), + [WeaponHash.Minigun] = (DamageGroup.Bullet, DamageType.Launcher), + [WeaponHash.Firework_Launcher] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Railgun] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Homing_Launcher] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Compact_Grenade_Launcher] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Ray_Minigun] = (DamageGroup.Bullet, DamageType.Launcher), + [WeaponHash.Grenade] = (DamageGroup.Explosion, DamageType.Explosive), + [WeaponHash.BZGas] = (DamageGroup.Gas, DamageType.Gas), + [WeaponHash.Tear_Gas] = (DamageGroup.Gas, DamageType.Gas), + [WeaponHash.Flare] = (DamageGroup.NonDamaging, DamageType.ThrowableNonLethal), + [WeaponHash.Molotov] = (DamageGroup.Fire, DamageType.Fire), + [WeaponHash.Sticky_Bomb] = (DamageGroup.Explosion, DamageType.Explosive), + [WeaponHash.Proximity_Mine] = (DamageGroup.Explosion, DamageType.Explosive), + [WeaponHash.Snowball] = (DamageGroup.NonDamaging, DamageType.ThrowableNonLethal), + [WeaponHash.Pipe_Bomb] = (DamageGroup.Explosion, DamageType.Explosive), + [WeaponHash.Baseball] = (DamageGroup.NonDamaging, DamageType.ThrowableNonLethal), + [WeaponHash.Jerry_Can] = (DamageGroup.NonDamaging, DamageType.Misc), + [WeaponHash.Fire_Extinguisher] = (DamageGroup.NonDamaging, DamageType.Misc), + [WeaponHash.Parachute] = (DamageGroup.Unknown, DamageType.Unknown), + [WeaponHash.Electric_Fence] = (DamageGroup.Environmental, DamageType.Electric), + [WeaponHash.Hitby_Water_Cannon] = (DamageGroup.WaterCannon, DamageType.WaterCannon), + [WeaponHash.Rammedby_Car] = (DamageGroup.Vehicle, DamageType.Vehicle), + [WeaponHash.Run_Overby_Car] = (DamageGroup.Vehicle, DamageType.Vehicle), + [WeaponHash.Fall] = (DamageGroup.Fall, DamageType.Fall), + [WeaponHash.Animal] = (DamageGroup.Animal, DamageType.Animal), + [WeaponHash.Airstrike_Rocket] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Bleeding] = (DamageGroup.Bodily, DamageType.Bodily), + [WeaponHash.Briefcase] = (DamageGroup.Unknown, DamageType.Unknown), + [WeaponHash.Briefcase02] = (DamageGroup.Unknown, DamageType.Unknown), + [WeaponHash.Cougar] = (DamageGroup.Animal, DamageType.Animal), + [WeaponHash.Barbed_Wire] = (DamageGroup.Environmental, DamageType.BarbedWire), + [WeaponHash.Drowning] = (DamageGroup.Drowning, DamageType.Drowning), + [WeaponHash.Drowning_In_Vehicle] = (DamageGroup.Drowning, DamageType.Drowning), + [WeaponHash.Explosion] = (DamageGroup.Explosion, DamageType.Explosive), + [WeaponHash.Exhaustion] = (DamageGroup.Bodily, DamageType.Bodily), + [WeaponHash.Fire] = (DamageGroup.Fire, DamageType.Fire), + [WeaponHash.Heli_Crash] = (DamageGroup.Explosion, DamageType.Explosive), + [WeaponHash.Vehicle_Rocket] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Vehicle_Akula_Barrage] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Akula_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Akula_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Akula_Turret_Dual] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Akula_Turret_Single] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_APCCannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_APCMG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_APCMissile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Ardent_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Avenger_Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Barrage_Rear_GL] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Barrage_Rear_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Barrage_Rear_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Barrage_Top_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Barrage_Top_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Bombushka_Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Bombushka_Dual_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Cannon_Blazer] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Caracara_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Caracara_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Cherno_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Comet_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Deluxo_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Deluxo_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Dogfighter_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Dogfighter_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Dune_Grenade_Launcher] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Dune_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Dune_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Enemy_Laser] = (DamageGroup.Unknown, DamageType.Unknown), + [WeaponHash.Vehicle_Hacker_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Hacker_Missile_Homing] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Halftrack_Dual_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Halftrack_Quad_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Havok_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Hunter_Barrage] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Hunter_Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Hunter_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Hunter_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Insurgent_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Khanjali_Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Khanjali_Cannon_Heavy] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Khanjali_GL] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Khanjali_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Menacer_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Microlight_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Mobileops_Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Mogul_Dual_Nose] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Mogul_Dual_Turret] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Mogul_Nose] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Mogul_Turret] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Mule4MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Mule4Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Mule4Turret_GL] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Nightshark_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Nose_Turret_Valkyrie] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Oppressor_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Oppressor_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Oppressor2Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Oppressor2MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Oppressor2Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Plane_Rocket] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Player_Buzzard] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Player_Lazer] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Player_Savage] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Pounder2Barrage] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Pounder2GL] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Pounder2Mini] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Pounder2Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Radar] = (DamageGroup.NonDamaging, DamageType.NonDamaging), + [WeaponHash.Vehicle_Revolter_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Rogue_Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Rogue_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Rogue_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Ruiner_Bullet] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Ruiner_Rocket] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Savestra_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Scramjet_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Scramjet_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Seabreeze_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Searchlight] = (DamageGroup.NonDamaging, DamageType.NonDamaging), + [WeaponHash.Vehicle_Space_Rocket] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Speedo4MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Speedo4Turret_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Speedo4Turret_Mini] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Strikeforce_Barrage] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Strikeforce_Cannon] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Strikeforce_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Subcar_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Subcar_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Subcar_Torpedo] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Tampa_Dual_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Tampa_Fixed_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Tampa_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Tampa_Mortar] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Tank] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Technical_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Thruster_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Thruster_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Trailer_Dualaa] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Trailer_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Trailer_Quad_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Tula_Dual_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Tula_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Tula_Minigun] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Tula_Nose_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Turret_Boxville] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Turret_Insurgent] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Turret_Limo] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Turret_Technical] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Turret_Valkyrie] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Vigilante_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Vigilante_Missile] = (DamageGroup.Explosion, DamageType.VehicleLauncher), + [WeaponHash.Vehicle_Viseris_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Volatol_Dual_MG] = (DamageGroup.Bullet, DamageType.VehicleFirearm), + [WeaponHash.Vehicle_Water_Cannon] = (DamageGroup.WaterCannon, DamageType.WaterCannon), + [WeaponHash.Vehicle_Helicopter_Rotors] = (DamageGroup.Vehicle, DamageType.Vehicle), + // 0.9.9 + [WeaponHash.Military_Rifle] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Heavy_Rifle] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Service_Carbine] = (DamageGroup.Bullet, DamageType.Rifle), + [WeaponHash.Precision_Rifle] = (DamageGroup.Bullet, DamageType.Sniper), + [WeaponHash.Combat_Shotgun] = (DamageGroup.Bullet, DamageType.Shotgun), + [WeaponHash.Compact_EMP_Launcher] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Railgun_XM3] = (DamageGroup.Explosion, DamageType.Launcher), + [WeaponHash.Stun_Gun_MP] = (DamageGroup.LessThanLethal, DamageType.LessThanLethal), + [WeaponHash.Perico_Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.WM29_Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Navy_Revolver] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Ceramic_Pistol] = (DamageGroup.Bullet, DamageType.Pistol), + [WeaponHash.Candy_Cane] = (DamageGroup.Melee, DamageType.MeleeBlunt), + }; + }; +} \ No newline at end of file diff --git a/DamageTrackerLib/DamageTrackerService.cs b/DamageTrackerLib/DamageTrackerService.cs new file mode 100644 index 0000000..5c4e5c2 --- /dev/null +++ b/DamageTrackerLib/DamageTrackerService.cs @@ -0,0 +1,133 @@ +using System; +using System.IO; +using System.IO.MemoryMappedFiles; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using DamageTrackerLib.DamageInfo; +using Rage; +using Rage.Native; + +namespace DamageTrackerLib +{ + // ReSharper disable once UnusedType.Global + public static class DamageTrackerService + { + // ReSharper disable once UnusedMember.Global + public static string CurrentVersion => Assembly.GetExecutingAssembly().GetName().Version.ToString(3); + + public const string Guid = "609a228f"; + + /// + /// Delegate to be used for TookDamage events. + /// + public delegate void PedTookDamageDelegate(Ped victimPed, Ped attackerPed, PedDamageInfo damageInfo); + + /// + /// Event invoked when a Ped takes damage. This event excludes the Player. + /// + // ReSharper disable once EventNeverSubscribedTo.Global + public static event PedTookDamageDelegate OnPedTookDamage; + + /// + /// Event invoked when the Player takes damage ONLY. + /// + // ReSharper disable once EventNeverSubscribedTo.Global + public static event PedTookDamageDelegate OnPlayerTookDamage; + + private static readonly BinaryFormatter BinaryFormatter = new(); + private static GameFiber _gameFiber; + + // ReSharper disable once UnusedMember.Global + public static bool IsRunning => _gameFiber != null; + + /// + /// Starts a GameFiber that collects incoming damage data from the DamageTracker plugin and turns them into events. + /// + // ReSharper disable once UnusedMember.Global + public static void Start() => Start(false); + + /// + /// Starts a GameFiber that collects incoming damage data from the DamageTracker plugin and turns them into events. Takes a boolean parameter that will enable logging damage. + /// + // ReSharper disable once MemberCanBePrivate.Global + public static void Start(bool enableLogging) + { + if (_gameFiber != null) + { + Game.LogTrivial("Tried to start DamageTrackerService while already running!"); + return; + } + NativeFunction.Natives + .x5BA652A0CD14DF2F(); // HACK: Fixes stuttering issue by warming up JIT with a useless native. + Game.LogTrivial("DamageTrackerService Started"); + _gameFiber = GameFiber.StartNew(() => Run(enableLogging)); + } + + + /// + /// Stops DamageTrackerService GameFiber. + /// + // ReSharper disable once UnusedMember.Global + public static void Stop() + { + if (_gameFiber == null) + { + Game.LogTrivial("Tried to stop DamageTrackerService while it was not running"); + return; + } + + Game.LogTrivial("DamageTrackerService Stopped"); + _gameFiber.Abort(); + } + + private static void Run(bool enableLogging) + { + using var mmf = MemoryMappedFile.CreateOrOpen(Guid, 20000, MemoryMappedFileAccess.ReadWrite); + using var mmfAccessor = mmf.CreateViewAccessor(); + using var stream = new MemoryStream(); + while (true) + { + GameFiber.Yield(); + stream.SetLength(0); + var buffer = new byte[mmfAccessor.Capacity]; + mmfAccessor.ReadArray(0, buffer, 0, buffer.Length); + if (IsByteArrayZero(buffer)) continue; // TODO: Add error message + stream.Write(buffer, 0, buffer.Length); + stream.Position = 0; + if (stream.Length <= 0) continue; // TODO: Add error message + var damagedPeds = (PedDamageInfo[])BinaryFormatter.Deserialize(stream); + foreach (var pedDamageInfo in damagedPeds) InvokeDamageEvent(pedDamageInfo, enableLogging); + } + // ReSharper disable once FunctionNeverReturns + } + + private static void InvokeDamageEvent(PedDamageInfo pedDamageInfo, bool enableLogging) + { + var ped = HandleUtility.TryGetPedByHandle(pedDamageInfo.PedHandle); + if (!ped) return; + if (enableLogging) + Game.LogTrivial( + $"DamageTrackerService: Ped {ped.Model.Name} damaged by {pedDamageInfo.WeaponInfo.Hash}."); + var attackerPed = pedDamageInfo.AttackerPedHandle == default + ? null + : HandleUtility.TryGetPedByHandle(pedDamageInfo.AttackerPedHandle); + switch (ped.IsPlayer) + { + case true when OnPlayerTookDamage != null: + OnPlayerTookDamage.Invoke(ped, attackerPed, pedDamageInfo); + break; + case false when OnPedTookDamage != null: + OnPedTookDamage.Invoke(ped, attackerPed, pedDamageInfo); + break; + } + } + + private static bool IsByteArrayZero(byte[] array) + { + foreach (var element in array) + if (element != 0) + return false; + return true; + } + } +} \ No newline at end of file diff --git a/DamageTrackerLib/HandleUtility.cs b/DamageTrackerLib/HandleUtility.cs new file mode 100644 index 0000000..048911c --- /dev/null +++ b/DamageTrackerLib/HandleUtility.cs @@ -0,0 +1,26 @@ +using System; +using Rage; +using Rage.Native; + +namespace DamageTrackerLib; + +public static class HandleUtility +{ + public static Ped TryGetPedByHandle(PoolHandle handle) + { + if (!NativeFunction.Natives.DOES_ENTITY_EXIST((uint)handle)) + { + Game.LogTrivial($"DamageTrackerService Warning: Ped Handle {handle.ToString()} does not exist."); + return null; + } + try + { + return NativeFunction.Natives.IS_ENTITY_A_PED((uint)handle) ? World.GetEntityByHandle(handle) : null; + } + catch (ArgumentException) + { + Game.LogTrivial($"Exception Caught: Ped Handle ({handle.ToString()}) did not return an Entity."); + } + return null; + } +} \ No newline at end of file diff --git a/DamageTrackerLib/Properties/AssemblyInfo.cs b/DamageTrackerLib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ca90b94 --- /dev/null +++ b/DamageTrackerLib/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DamageTrackerLib")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DamageTrackerLib")] +[assembly: AssemblyCopyright("Copyright © 2022 Variapolis")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8BA678B1-D73D-4B13-8D42-F6750285E52A")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] \ No newline at end of file diff --git a/DamageTrackerLib/Properties/AssemblyVersion.cs b/DamageTrackerLib/Properties/AssemblyVersion.cs new file mode 100644 index 0000000..542180e --- /dev/null +++ b/DamageTrackerLib/Properties/AssemblyVersion.cs @@ -0,0 +1,5 @@ +using System.Reflection; + +[assembly: AssemblyVersion("2.0.0")] +[assembly: AssemblyFileVersion("2.0.0")] + diff --git a/DamageTrackerLib/packages.config b/DamageTrackerLib/packages.config new file mode 100644 index 0000000..8f90e06 --- /dev/null +++ b/DamageTrackerLib/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/DamageTrackerUtility.sln b/DamageTrackerUtility.sln index 82d2dfc..2bd6a9a 100644 --- a/DamageTrackerUtility.sln +++ b/DamageTrackerUtility.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DamageTrackingFramework", "DamageTrackingFramework\DamageTrackingFramework.csproj", "{94C2148E-3005-4946-9C57-2CC4D8BC250B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DamageTrackerLib", "DamageTrackerLib\DamageTrackerLib.csproj", "{8BA678B1-D73D-4B13-8D42-F6750285E52A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +14,9 @@ Global {94C2148E-3005-4946-9C57-2CC4D8BC250B}.Debug|Any CPU.Build.0 = Debug|Any CPU {94C2148E-3005-4946-9C57-2CC4D8BC250B}.Release|Any CPU.ActiveCfg = Release|Any CPU {94C2148E-3005-4946-9C57-2CC4D8BC250B}.Release|Any CPU.Build.0 = Release|Any CPU + {8BA678B1-D73D-4B13-8D42-F6750285E52A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BA678B1-D73D-4B13-8D42-F6750285E52A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BA678B1-D73D-4B13-8D42-F6750285E52A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BA678B1-D73D-4B13-8D42-F6750285E52A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/DamageTrackerUtility.sln.DotSettings.user b/DamageTrackerUtility.sln.DotSettings.user new file mode 100644 index 0000000..7ee935c --- /dev/null +++ b/DamageTrackerUtility.sln.DotSettings.user @@ -0,0 +1,8 @@ + + True + True + True + <AssemblyExplorer> + <Assembly Path="D:\Users\Vari\Desktop\Work\Forks\DamageTrackerPlugin\DamageTrackerUtility\packages\RagePluginHook.1.98.0\lib\net472\RagePluginHook.dll" /> +</AssemblyExplorer> + True \ No newline at end of file diff --git a/DamageTrackingFramework/.vs/DamageTrackingFramework/v16/.suo b/DamageTrackingFramework/.vs/DamageTrackingFramework/v16/.suo new file mode 100644 index 0000000..da09090 Binary files /dev/null and b/DamageTrackingFramework/.vs/DamageTrackingFramework/v16/.suo differ diff --git a/DamageTrackingFramework/.vs/ProjectSettings.json b/DamageTrackingFramework/.vs/ProjectSettings.json new file mode 100644 index 0000000..0801583 --- /dev/null +++ b/DamageTrackingFramework/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/DamageTrackingFramework/.vs/VSWorkspaceState.json b/DamageTrackingFramework/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..6338ec9 --- /dev/null +++ b/DamageTrackingFramework/.vs/VSWorkspaceState.json @@ -0,0 +1,6 @@ +{ + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/DamageTrackingFramework/.vs/slnx.sqlite b/DamageTrackingFramework/.vs/slnx.sqlite new file mode 100644 index 0000000..f4049e8 Binary files /dev/null and b/DamageTrackingFramework/.vs/slnx.sqlite differ diff --git a/DamageTrackingFramework/App.config b/DamageTrackingFramework/App.config new file mode 100644 index 0000000..7064a37 --- /dev/null +++ b/DamageTrackingFramework/App.config @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DamageTrackingFramework/DamageInfo/PedDamageInfo.cs b/DamageTrackingFramework/DamageInfo/PedDamageInfo.cs deleted file mode 100644 index 3ae224c..0000000 --- a/DamageTrackingFramework/DamageInfo/PedDamageInfo.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using Rage; - -namespace DamageTrackingFramework.DamageInfo -{ - [Serializable] - public struct PedDamageInfo - { - public Ped Ped; - public int Damage; - public WeaponDamageInfo WeaponInfo; - public BoneDamageInfo BoneInfo; - } -} \ No newline at end of file diff --git a/DamageTrackingFramework/DamageTracker.cs b/DamageTrackingFramework/DamageTracker.cs index 95d30f6..729f681 100644 --- a/DamageTrackingFramework/DamageTracker.cs +++ b/DamageTrackingFramework/DamageTracker.cs @@ -1,73 +1,88 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.MemoryMappedFiles; using System.Linq; -using DamageTrackingFramework.DamageInfo; +using System.Runtime.Serialization.Formatters.Binary; +using DamageTrackerLib; +using DamageTrackerLib.DamageInfo; using Rage; using Rage.Native; -using WeaponHash = DamageTrackingFramework.DamageInfo.WeaponHash; +using WeaponHash = DamageTrackerLib.DamageInfo.WeaponHash; namespace DamageTrackingFramework { - public static class DamageTracker + internal static class DamageTracker { - public delegate void PedDamagedDelegate(Ped ped, PedDamageInfo pedDamageInfo); - - public static event PedDamagedDelegate OnPedTookDamage; - public static event PedDamagedDelegate OnPlayerTookDamage; - // ReSharper disable once HeapView.ObjectAllocation.Evident - private static readonly Dictionary PedDict = new Dictionary(); + private static readonly Dictionary PedHealthDict = new(); + private static readonly HashSet UnknownWeaponHashCache = new(); + private static readonly List PedDamageList = new(); + private static readonly DetourHandler PedDetourHandler = new(); + private static readonly BinaryFormatter Formatter = new(); internal static void CheckPedsFiber() { - // var beforeCount = DamageSubCount; - // OnPedTookDamage += Test; - // Game.LogTrivial($"{beforeCount} to {DamageSubCount}"); - PipeServer.Start(); + PedDetourHandler.StartHook(); + using var mmf = MemoryMappedFile.CreateOrOpen(DamageTrackerService.Guid, 20000, + MemoryMappedFileAccess.ReadWrite); // TODO: Replace with GUID from Lib + using var mmfAccessor = mmf.CreateViewAccessor(); + using var stream = new MemoryStream(); while (true) { + PedDamageList.Clear(); var peds = World.GetAllPeds(); - foreach (var ped in peds) HandlePed(ped); // TODO: Add peds to pipe queue here - // TODO: Flush ped queue here - CleanPedDictionary(); + foreach (var ped in peds) HandlePed(ped); + SendPedData(mmfAccessor, stream); + CleanPedDictionaries(); GameFiber.Yield(); } // ReSharper disable once FunctionNeverReturns } + private static void + SendPedData(MemoryMappedViewAccessor accessor, + MemoryStream stream) // TODO: Resize file if ped count is too small or send less. + { + stream.SetLength(0); + Formatter.Serialize(stream, PedDamageList.ToArray()); + var buffer = stream.ToArray(); + accessor.WriteArray(0, buffer, 0, buffer.Length); + accessor.Flush(); + } + private static void HandlePed(Ped ped) { - if (!ped.Exists()) return; - if (!PedDict.ContainsKey(ped)) PedDict.Add(ped, ped.Health); + if (!ped.Exists() || !ped.IsHuman) return; + if (!PedHealthDict.ContainsKey(ped)) PedHealthDict.Add(ped, (ped.Health, ped.Armor)); - var previousHealth = PedDict[ped]; + var previousHealth = PedHealthDict[ped]; if (!TryGetPedDamage(ped, out var damage)) return; - InvokeDamageEvent(ped, GenerateDamageInfo(ped, previousHealth, damage)); + PedDamageList.Add(GenerateDamageInfo(ped, previousHealth.health, previousHealth.armour, damage)); ClearPedDamage(ped); } - private static void InvokeDamageEvent(Ped ped, PedDamageInfo damageInfo) - { - switch (ped.IsPlayer) - { - case true when OnPlayerTookDamage != null: - OnPlayerTookDamage(ped, damageInfo); - break; - case false when OnPedTookDamage != null: - OnPedTookDamage(ped, damageInfo); - break; - } - } - - private static PedDamageInfo GenerateDamageInfo(Ped ped, int previousHealth, WeaponDamageInfo damage) + private static PedDamageInfo GenerateDamageInfo(Ped ped, int previousHealth, int previousArmour, + WeaponHash damageHash) { var lastDamagedBone = (BoneId)ped.LastDamageBone; - var boneTuple = Lookups.BoneLookup[lastDamagedBone]; - return new PedDamageInfo() + var boneTuple = DamageTrackerLookups.BoneLookup[lastDamagedBone]; + var weaponTuple = DamageTrackerLookups.WeaponLookup[damageHash]; + var attackerPed = GetAttackerPed(ped); + + return new PedDamageInfo { + PedHandle = ped.Handle, + AttackerPedHandle = attackerPed, Damage = previousHealth - ped.Health, - WeaponInfo = damage, - BoneInfo = new BoneDamageInfo() + ArmourDamage = previousArmour - ped.Armor, + WeaponInfo = + { + Hash = damageHash, + Type = weaponTuple.DamageType, + Group = weaponTuple.DamageGroup + }, + BoneInfo = new BoneDamageInfo { BoneId = lastDamagedBone, Limb = boneTuple.limb, @@ -76,47 +91,98 @@ private static PedDamageInfo GenerateDamageInfo(Ped ped, int previousHealth, Wea }; } - private static void ClearPedDamage(Ped ped) + private static PoolHandle GetAttackerPed(Ped ped) { - ped.ClearLastDamageBone(); - NativeFunction.Natives.xAC678E40BE7C74D2(ped); + if (PedDetourHandler.PedHookData.TryGetValue(ped.Handle, out var data)) + { + return data.AttackerHandle.GetValueOrDefault(); + } + + PoolHandle attackerPed = default; + if (!ped.HasBeenDamagedByAnyPed) return attackerPed; + foreach (var otherPed in PedHealthDict.Keys) + { + if (!otherPed.IsValid() || !ped.HasBeenDamagedBy(otherPed)) continue; + attackerPed = otherPed.Handle; + break; + } + + return attackerPed; } - private static bool TryGetPedDamage(Ped ped, out WeaponDamageInfo damage) + private static bool TryGetPedDamage(Ped ped, out WeaponHash damageHash) { var pedAddr = ped.MemoryAddress; - damage = default; + damageHash = default; + // If data exists from hook, use hook values. + if (PedDetourHandler.PedHookData.TryGetValue(ped.Handle, out var data)) + { + damageHash = DamageTrackerLookups.WeaponLookup.ContainsKey((WeaponHash)data.WeaponHash) + ? (WeaponHash)data.WeaponHash + : WeaponHash.Unknown; + if (damageHash == WeaponHash.Unknown && !UnknownWeaponHashCache.Contains((WeaponHash)data.WeaponHash)) + { + Game.LogTrivial( + $"WARNING: {data.WeaponHash:X8} Hash is unknown. Please notify DamageTracker Developer at: https://www.lcpdfr.com/downloads/gta5mods/scripts/42767-damage-tracker-framework/"); + UnknownWeaponHashCache.Add(damageHash); + } + return WasDamaged(ped); + } + // Otherwise use legacy system (For odd injuries like bleeding and falling) unsafe { var damageHandler = *(IntPtr*)(pedAddr + 648); - if (damageHandler == IntPtr.Zero) return false; + if (damageHandler == IntPtr.Zero) // Always true if the Ped has never taken damage. + { + if (!WasDamaged(ped)) return false; + damageHash = WeaponHash.Fall; // Triggers damage event if health went down due to falling. + return true; + } + var damageArray = *(int*)(damageHandler + 72); - if (ped.Health >= PedDict[ped] || damageArray <= 0) + if (damageArray == 0) // true unless the ped took damage since LastDamage was cleared (Except Falling). { - PedDict[ped] = ped.Health; - return false; + if (!WasDamaged(ped)) return false; + damageHash = WeaponHash.Fall; // Triggers damage event if health went down due to falling. + return true; } var hashAddr = damageHandler + 8; - if (hashAddr == IntPtr.Zero || *(WeaponHash*)hashAddr == 0 || - !Lookups.WeaponLookup.ContainsKey(*(WeaponHash*)hashAddr)) return false; // May not be necessary. - var weaponHash = *(WeaponHash*)hashAddr; - var damageTuple = Lookups.WeaponLookup[weaponHash]; - damage = new WeaponDamageInfo() + var hash = *(WeaponHash*)hashAddr; + damageHash = DamageTrackerLookups.WeaponLookup.ContainsKey(hash) + ? hash + : WeaponHash.Unknown; + if (damageHash == WeaponHash.Unknown && !UnknownWeaponHashCache.Contains(hash)) { - Hash = weaponHash, - Group = damageTuple.DamageGroup, - Type = damageTuple.DamageType - }; + Game.LogTrivial( + $"WARNING: {(uint)hash:X8} Hash is unknown. Please notify DamageTracker Developer at: https://www.lcpdfr.com/downloads/gta5mods/scripts/42767-damage-tracker-framework/"); + UnknownWeaponHashCache.Add(hash); + } return true; } } - private static void CleanPedDictionary() + private static bool WasDamaged(Ped ped) { - foreach (var ped in PedDict.Keys.ToList()) + var previousHealth = PedHealthDict[ped]; + return ped.Health < previousHealth.health || ped.Armor < previousHealth.armour; + } + + private static void ClearPedDamage(Ped ped) + { + ped.ClearLastDamageBone(); + NativeFunction.Natives.xAC678E40BE7C74D2(ped); + PedHealthDict[ped] = (ped.Health, ped.Armor); + } + + private static void CleanPedDictionaries() + { + foreach (var ped in PedHealthDict.Keys.ToList()) if (!ped.Exists()) - PedDict.Remove(ped); + PedHealthDict.Remove(ped); + PedDetourHandler.PedHookData.Clear(); } + + internal static void Dispose() => DetourHandler.Dispose(); } } \ No newline at end of file diff --git a/DamageTrackingFramework/DamageTrackingFramework.csproj b/DamageTrackingFramework/DamageTrackingFramework.csproj index 82083c0..b15de5b 100644 --- a/DamageTrackingFramework/DamageTrackingFramework.csproj +++ b/DamageTrackingFramework/DamageTrackingFramework.csproj @@ -12,6 +12,7 @@ v4.8 512 true + 10 AnyCPU @@ -33,6 +34,12 @@ 4 + + ..\DamageTrackerLib\bin\Release\DamageTrackerLib.dll + + + G:\SteamLibrary\steamapps\common\Grand Theft Auto V\EasyHook.dll + @@ -45,25 +52,25 @@ - - - - - - - - - + + Properties\AssemblyVersion.cs + - - + + + + + {8ba678b1-d73d-4b13-8d42-f6750285e52a} + DamageTrackerLib + +