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
+
+