static public void CheckDamageLocation(Ped p)
        {
            try
            {
                List <Bone>              damagedBones          = DamageBitFlags.PedGetAllDamagedBones(p);
                List <string>            damagedBonesInHuman   = damagedBones.Select(b => boneToNameMap[b]).ToList();
                Dictionary <string, int> aggregateDamagedBones = new Dictionary <string, int>();
                damagedBonesInHuman.ForEach(d =>
                {
                    if (aggregateDamagedBones.ContainsKey(d))
                    {
                        aggregateDamagedBones[d]++;
                    }
                    else
                    {
                        aggregateDamagedBones[d] = 1;
                    }
                });
                List <string> result = new List <string>();
                damagedBonesInHuman.ForEach(d =>
                {
                    if (aggregateDamagedBones[d] > 1)
                    {
                        result.Add($"multiple instances of damage to the {d}");
                    }
                    else
                    {
                        result.Add($"damage to the {d}");
                    }
                });

                if (aggregateDamagedBones.Count() > 0)
                {
                    BaseScript.TriggerEvent("Chat.Message", "", "#AABB88", $"You see {String.Join(",", result)}.");
                }
                else
                {
                    BaseScript.TriggerEvent("Chat.Message", "", "#AABB88", $"There is no damage that is clearly visible to you at the moment.");
                }
            }
            catch (Exception ex)
            {
                Log.Error($"PedDamage CheckDamageLocation Error: {ex.Message}");
            }
        }
 static public void CheckWeaponSources(Ped p)
 {
     try
     {
         List <WeaponHash> weaponDamageTypes = DamageBitFlags.PedGetAllWeaponDamageTypes(p);
         if (weaponDamageTypes.Count > 0)
         {
             BaseScript.TriggerEvent("Chat.Message", "", "#AABB88", $"You see damage that was probably caused by weapons such as: {String.Join(",", weaponDamageTypes.Select(w => w.ToString().AddSpacesToCamelCase()))}.");
         }
         else
         {
             BaseScript.TriggerEvent("Chat.Message", "", "#AABB88", $"There is no damage that is clearly visible to you at the moment.");
         }
     }
     catch (Exception ex)
     {
         Log.Error($"PedDamage CheckWeaponSources Error: {ex.Message}");
     }
 }
        static async Task PeriodicDamageCheck()
        {
            while (true)
            {
                try
                {
                    //if (Function.Call<bool>(Hash.HAS_PLAYER_DAMAGED_AT_LEAST_ONE_PED, Game.Player.Handle))
                    //{
                    //    //Log.ToChat($"{Function.Call<bool>(Hash.HAS_PLAYER_DAMAGED_AT_LEAST_ONE_PED, Game.Player.Handle)} {(NearbyPeds != null ? NearbyPeds.Count : 0)}");
                    //    Function.Call(Hash.CLEAR_PLAYER_HAS_DAMAGED_AT_LEAST_ONE_PED, Game.Player.Handle);
                    //}

                    if (NearbyPeds != null)
                    {
                        NearbyPeds.ForEach(p =>
                        {
                            if (p.Health < p.MaxHealth)
                            {
                                if (!Function.Call <bool>(Hash.HAS_ENTITY_BEEN_DAMAGED_BY_ANY_PED, p.Handle) && !Function.Call <bool>(Hash.HAS_ENTITY_BEEN_DAMAGED_BY_ANY_VEHICLE, p.Handle) /* && !(Game.PlayerPed.IsInVehicle() && Game.PlayerPed.CurrentVehicle.Driver == Game.PlayerPed && Function.Call<bool>(Hash.HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY, p.Handle, Game.PlayerPed.CurrentVehicle.Handle)))*/)
                                {
                                    //Log.ToChat("Not by me?");
                                    return;
                                }
                                else
                                {
                                    //Log.ToChat("Damaged ped!");
                                    if (Function.Call <bool>(Hash.HAS_ENTITY_BEEN_DAMAGED_BY_ANY_VEHICLE, p.Handle))
                                    {
                                        //Log.ToChat("VEHICLE");
                                        IncrementPedFlag(p, "Damage.Vehicle");
                                        if (p.IsDead)
                                        {
                                            Log.ToChat("VEHICLE KILLER");
                                            Function.Call(Hash.DECOR_SET_INT, p.Handle, "Damage.KillerCategory", KillerCategory.Vehicle);
                                        }
                                    }
                                    else
                                    {
                                        //Log.ToChat(":( NO VEHICLE");
                                    }

                                    if (p.IsDead)
                                    {
                                        Entity killer = Entity.FromHandle(Function.Call <int>(Hash.GET_PED_SOURCE_OF_DEATH, p.Handle));
                                        if (killer.Exists())
                                        {
                                            if ((PedHash)killer.Model.Hash == PedHash.MountainLion)
                                            {
                                                Log.ToChat("MOUNTAIN LION KILLER");
                                                Function.Call(Hash.DECOR_SET_INT, p.Handle, "Damage.KillerCategory", KillerCategory.MountainLion);
                                            }
                                        }
                                    }

                                    PedBone LastDamagedBone = p.Bones.LastDamaged;
                                    OutputArgument outBone  = new OutputArgument();
                                    Function.Call <bool>(Hash.GET_PED_LAST_DAMAGE_BONE, p.Handle, outBone);
                                    //Log.ToChat($"{(Bone)outBone.GetResult<int>()}");
                                    DamageBitFlags.SetPedBoneFlag(p, (Bone)outBone.GetResult <int>());
                                    Enum.GetValues(typeof(WeaponHash)).OfType <WeaponHash>().ToList().ForEach(w =>
                                    {
                                        if (Function.Call <bool>(Hash.HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON, p.Handle, (int)w, 0))
                                        {
                                            //Log.ToChat($"{w}");
                                            switch (Function.Call <int>(Hash.GET_WEAPON_DAMAGE_TYPE, (int)w))
                                            {
                                            case 2:     // Melee
                                                if (SharpMeleeWeapons.Contains(w))
                                                {
                                                    IncrementPedFlag(p, "Damage.Melee.Sharp");
                                                }
                                                else
                                                {
                                                    IncrementPedFlag(p, "Damage.Melee.Blunt");
                                                }
                                                break;

                                            case 3:     // Projectile Weapon
                                                IncrementPedFlag(p, "Damage.Projectile");
                                                break;

                                            case 13:     // Gasoline?
                                                IncrementPedFlag(p, "Damage.Gas");
                                                break;

                                            default:
                                                break;
                                            }
                                            DamageBitFlags.SetPedWeaponFlag(p, w);
                                            //Log.ToChat($"{w} Type: {Function.Call<int>(Hash.GET_WEAPON_DAMAGE_TYPE, (int)w)}");
                                        }
                                    });
                                    p.Bones.ClearLastDamaged();
                                    Function.Call(Hash.CLEAR_ENTITY_LAST_DAMAGE_ENTITY, p.Handle);
                                    p.ClearLastWeaponDamage();
                                    //var builder = new StringBuilder();
                                    //builder.AppendLine($"Damaged by weapons: {String.Join(", ", DamageBitFlags.PedGetAllWeaponDamageTypes(p))}");
                                    //builder.AppendLine($"Damaged in bones: {String.Join(", ", DamageBitFlags.PedGetAllDamagedBones(p))}");
                                    //builder.AppendLine($"Hit by vehicle: {Function.Call<int>(Hash.DECOR_GET_INT, p.Handle, "Damage.Vehicle")}");
                                    //builder.AppendLine($"Shot: {Function.Call<int>(Hash.DECOR_GET_INT, p.Handle, "Damage.Projectile")}");
                                    //builder.AppendLine($"Beaten: {Function.Call<int>(Hash.DECOR_GET_INT, p.Handle, "Damage.Melee.Blunt")}");
                                    //builder.AppendLine($"Cut: {Function.Call<int>(Hash.DECOR_GET_INT, p.Handle, "Damage.Melee.Sharp")}");
                                    //builder.AppendLine($"Gas damage: {Function.Call<int>(Hash.DECOR_GET_INT, p.Handle, "Damage.Gas")}");
                                    //Log.ToChat(builder.ToString());
                                }
                            }
                        });
                    }
                }
                catch (Exception ex)
                {
                    Log.Error($"PedDamage PeriodicDamageCheck Error: {ex.Message}");
                }
                await BaseScript.Delay(100);
            }
        }