diff --git a/SAIN Combat/Patches/RateofFirePatch.cs b/SAIN Combat/Patches/RateofFirePatch.cs index f64adcdc6..ddb2a5dba 100644 --- a/SAIN Combat/Patches/RateofFirePatch.cs +++ b/SAIN Combat/Patches/RateofFirePatch.cs @@ -48,14 +48,9 @@ public static bool PatchPrefix(ref BotOwner ___botOwner_0, ref float ___float_0) } public class SemiAutoPatch : ModulePatch { - private static PropertyInfo _WeaponManagerPI; - private static PropertyInfo _WeaponAIPresetPI; - protected override MethodBase GetTargetMethod() { - _WeaponManagerPI = AccessTools.Property(typeof(BotOwner), "WeaponManager"); - _WeaponAIPresetPI = AccessTools.Property(_WeaponManagerPI.PropertyType, "WeaponAIPreset"); - return AccessTools.Method(_WeaponAIPresetPI.PropertyType, "method_1"); + return AccessTools.Method(typeof(GClass363), "method_1"); } [PatchPrefix] diff --git a/SAIN Combat/Patches/RecoilPatch.cs b/SAIN Combat/Patches/RecoilPatch.cs index 3418bd0e6..f13d185c9 100644 --- a/SAIN Combat/Patches/RecoilPatch.cs +++ b/SAIN Combat/Patches/RecoilPatch.cs @@ -13,18 +13,23 @@ namespace SAIN_Audio.Combat.Patches { public class AimOffsetPatch : ModulePatch { - private static PropertyInfo _AimingDataPI; protected override MethodBase GetTargetMethod() { - _AimingDataPI = AccessTools.Property(typeof(BotOwner), "AimingData"); - return AccessTools.Method(_AimingDataPI.PropertyType, "method_13"); + // Note: Can't find this based on the property type of AimingData? Is this because of it being an interface? + return AccessTools.Method(typeof(GClass544), "method_13"); } [PatchPrefix] public static bool PatchPrefix(GClass544 __instance, ref BotOwner ___botOwner_0, ref Vector3 ___vector3_5, ref Vector3 ___vector3_4, ref float ___float_13) { - __instance.EndTargetPoint = __instance.RealTargetPoint + ___vector3_5 + ___float_13 * (___vector3_4 + (___botOwner_0.RecoilData.RecoilOffset * ScatterMultiplier.Value)); + __instance.EndTargetPoint = __instance.RealTargetPoint + + ___vector3_5 + + ___float_13 + + * (___vector3_4 + + (___botOwner_0.RecoilData.RecoilOffset + * ScatterMultiplier.Value)); return false; } diff --git a/SAIN Combat/Plugin.cs b/SAIN Combat/Plugin.cs index d3eecef9a..e081e3d75 100644 --- a/SAIN Combat/Plugin.cs +++ b/SAIN Combat/Plugin.cs @@ -6,7 +6,7 @@ namespace SAIN_Audio.Combat { - [BepInPlugin("me.sol.sain", "SAIN Combat", "1.6")] + [BepInPlugin("me.sol.sain", "SAIN Combat", "1.1")] public class CombatPlugin : BaseUnityPlugin { private void Awake() diff --git a/SAIN Flashlights/Components/FlashlightDetection.cs b/SAIN Flashlights/Components/FlashlightDetection.cs index d66e36c71..66b0716f4 100644 --- a/SAIN Flashlights/Components/FlashlightDetection.cs +++ b/SAIN Flashlights/Components/FlashlightDetection.cs @@ -1,8 +1,11 @@ using BepInEx.Logging; using Comfort.Common; using EFT; +using SAIN_Helpers; using System.Collections; using UnityEngine; +using UnityEngine.AI; +using static Mono.Security.X509.X520; using static SAIN_Flashlights.Config.DazzleConfig; namespace SAIN_Flashlights.Components @@ -15,6 +18,13 @@ public class FlashlightDetection private static Player LocalPlayer { get; set; } protected static ManualLogSource Logger { get; private set; } + private float SearchTime; + + private float RayCastFrequencyTime; + + /// + /// Finds the local player and the SAIN_Flashlight_Component if it is not already set. + /// public void FindYourPlayer() { if (LocalPlayer == null) @@ -27,14 +37,17 @@ public void FindYourPlayer() } } } + + /// + /// Creates detection points for the flashlight detection system. + /// + /// The player to create the detection points for. public void CreateDetectionPoints(Player player) { if (Logger == null) - { Logger = BepInEx.Logging.Logger.CreateLogSource(nameof(FlashlightDetection)); - } - if (player == null || player.IsAI || !player.HealthController.IsAlive) + if (player == null || !player.HealthController.IsAlive) return; Vector3 playerPosition = player.WeaponRoot.position; @@ -43,95 +56,229 @@ public void CreateDetectionPoints(Player player) float detectionDistance = 60f; - if (Physics.Raycast(playerPosition, playerLookDirection, out RaycastHit hit, detectionDistance, LayerMaskClass.HighPolyWithTerrainMask)) + // Define the cone angle (in degrees) + float coneAngle = 10f; + + // Generate random angles within the cone range for yaw and pitch + float randomYawAngle = UnityEngine.Random.Range(-coneAngle * 0.5f, coneAngle * 0.5f); + float randomPitchAngle = UnityEngine.Random.Range(-coneAngle * 0.5f, coneAngle * 0.5f); + + // Create a Quaternion rotation based on the random yaw and pitch angles + Quaternion randomRotation = Quaternion.Euler(randomPitchAngle, randomYawAngle, 0); + + // Rotate the player's look direction by the Quaternion rotation + Vector3 rotatedLookDirection = randomRotation * playerLookDirection; + + if (Physics.Raycast(playerPosition, rotatedLookDirection, out RaycastHit hit, detectionDistance, LayerMaskClass.HighPolyWithTerrainMask)) { FlashLightPoint = hit.point; - ExpireDetectionPoint(0.25f); + ExpireDetectionPoint(0.1f); - PlayerPosition = playerPosition; - ExpirePlayerPoint(0.25f); + PlayerPosition = player.Transform.position; + ExpirePlayerPoint(0.1f); + + if (DebugFlash.Value) + DebugDrawer.Sphere(hit.point, 0.1f, Color.red, 0.25f); } } - public void DetectPoints(Player player) + /// + /// Detects and investigates a flashlight for bots. + /// + public void DetectAndInvestigateFlashlight(Player player) { if (Logger == null) - { Logger = BepInEx.Logging.Logger.CreateLogSource(nameof(FlashlightDetection)); - } if (!player.IsAI || player?.AIData?.BotOwner == null) - { return; - } FindYourPlayer(); if (PlayerFlashComponent == null) { - Logger.LogWarning($"Could not find flashlight component for local player"); + Logger.LogError($"Could not find flashlight component for local player"); return; } BotOwner bot = player.AIData.BotOwner; + Vector3 playerPos = PlayerPosition; + Vector3 flashPos = FlashLightPoint; - if (FlashLightPoint != Vector3.zero && PlayerPosition != Vector3.zero) + if (flashPos != Vector3.zero && playerPos != Vector3.zero) { - if (bot.LookSensor.IsPointInVisibleSector(FlashLightPoint)) + Vector3 botPos = bot.MyHead.position; + + if ((botPos - flashPos).magnitude < 100f) { - Vector3 botPosition = bot.MyHead.position; + if (CanISeeFlashlight(bot, flashPos)) + { + Vector3 estimatedPosition = EstimateSearchPosition(playerPos, flashPos, botPos, 5f); - Vector3 direction = (FlashLightPoint - botPosition).normalized; + TryToInvestigate(bot, estimatedPosition, out Vector3 debugHitPos); - float rayLength = (FlashLightPoint - botPosition).magnitude; + DebugSearchPosition(bot.name, debugHitPos, flashPos, botPos, 5f, 0.15f, 0.05f); + } + } + } + } + + /// + /// Checks if the bot can see the flashlight based on the bot's position, the player's position, and the flashlight's position. + /// + /// The bot owner. + /// The player's position. + /// The flashlight's position. + /// True if the bot can see the flashlight, false otherwise. + private bool CanISeeFlashlight(BotOwner bot, Vector3 flashPos) + { + if (bot.LookSensor.IsPointInVisibleSector(flashPos)) + { + Vector3 botPos = bot.Transform.position; + + Vector3 direction = (flashPos - botPos).normalized; + + float rayLength = (flashPos - botPos).magnitude - 0.1f; - if (!Physics.Raycast(botPosition, direction, rayLength, LayerMaskClass.HighPolyWithTerrainMask)) + if (RayCastFrequencyTime < Time.time && !Physics.Raycast(botPos, direction, rayLength, LayerMaskClass.HighPolyWithTerrainMask)) + { + SetRayCastTimer(0.25f); + + if (SearchTime < Time.time) { - float dispersion = rayLength / 10f; + return true; + } + } + } - float num2 = MathHelpers.Random(-dispersion, dispersion); - float num3 = MathHelpers.Random(-dispersion, dispersion); + return false; + } - Vector3 vector = new Vector3(PlayerPosition.x + num2, PlayerPosition.y, PlayerPosition.z + num3); + /// + /// Tries to investigate a visible flashlight beam by estimating a search position and adding it to the bot's group search points. + /// + /// The bot owner. + /// The player's position. + /// The flashbang's position. + /// The bot's position. + private void TryToInvestigate(BotOwner bot, Vector3 estimatedPosition, out Vector3 debugHitPos) + { + debugHitPos = Vector3.zero; - //var target = new GClass270(vector, PlaceForCheckType.suspicious); + if (NavMesh.SamplePosition(estimatedPosition, out NavMeshHit hit, 1.0f, -1)) + { + NavMeshPath searchpath = new NavMeshPath(); + NavMesh.CalculatePath(bot.Transform.position, hit.position, -1, searchpath); - bot.BotsGroup.AddPointToSearch(vector, 10f, bot, true); + if (searchpath.status == NavMeshPathStatus.PathInvalid) + { + SetSearchTimer(1f); + SetRayCastTimer(1f); - //bot.Memory.GoalTarget.SetTarget(target); + if (DebugFlash.Value) + Logger.LogDebug($"Path Invalid"); + } + else + { + SetSearchTimer(5f); + SetRayCastTimer(5f); - if (DebugFlash.Value) - { - Helpers.DebugDrawer.Line(vector, botPosition, 0.005f, Color.red, 3f); - Helpers.DebugDrawer.Line(FlashLightPoint, botPosition, 0.005f, Color.red, 3f); - } - } + debugHitPos = hit.position; + + bot.BotsGroup.AddPointToSearch(hit.position, 20f, bot, true); } } } + /// + /// Estimates a search position based on the player, flash, and bot positions, and a dispersion value. + /// + /// The position of the player. + /// The position of the flashlight point. + /// The position of the bot. + /// What the distance to enemy is divided by to produce dispersion. Higher is more accurate + /// The estimated search position. + private Vector3 EstimateSearchPosition(Vector3 playerPos, Vector3 flashPos, Vector3 botPos, float dispersion) + { + Vector3 estimatedPosition = Vector3.Lerp(playerPos, flashPos, Random.Range(0.0f, 0.25f)); + + float distance = (playerPos - botPos).magnitude; + + float maxDispersion = Mathf.Clamp(distance, 0f, 20f); + + float positionDispersion = maxDispersion / dispersion; + + float x = SAIN_Math.Random(-positionDispersion, positionDispersion); + float z = SAIN_Math.Random(-positionDispersion, positionDispersion); + + return new Vector3(estimatedPosition.x + x, estimatedPosition.y, estimatedPosition.z + z); + } + + /// + /// Sets the search timer to the current time plus the given duration. + /// + /// The duration to add to the current time. + private void SetSearchTimer(float duration) + { + SearchTime = Time.time + duration; + } + + /// + /// Sets the RayCastFrequencyTime to the current time plus the given duration. + /// + /// The duration to add to the current time. + private void SetRayCastTimer(float duration) + { + RayCastFrequencyTime = Time.time + duration; + } + + /// + /// Draws debug lines and spheres to visualize the search position of a bot. + /// + /// Name of the bot. + /// Position of the hit. + /// Position of the flashlight. + /// Position of the bot. + /// Time until the debug lines and spheres expire. + /// Size of the debug spheres. + /// Size of the debug lines. + private void DebugSearchPosition(string name, Vector3 hitpos, Vector3 flashpos, Vector3 botpos, float expiretime, float spheresize, float linesize) + { + if (DebugFlash.Value) + { + Logger.LogDebug($"{name} Is Investigating Flashlight Beam"); + + Helpers.DebugDrawer.Sphere(hitpos, spheresize, Color.red, expiretime); + Helpers.DebugDrawer.Sphere(flashpos, spheresize, Color.red, expiretime); + + Helpers.DebugDrawer.Line(flashpos, botpos, linesize, Color.red, expiretime); + Helpers.DebugDrawer.Line(hitpos, botpos, linesize, Color.red, expiretime); + Helpers.DebugDrawer.Line(hitpos, flashpos, linesize, Color.red, expiretime); + } + } + + /// + /// Waits for a specified amount of time before setting the FlashLightPoint to Vector3.zero. + /// + /// The amount of time to wait before setting the FlashLightPoint. + /// An IEnumerator object. private IEnumerator ExpireDetectionPoint(float delay) { yield return new WaitForSeconds(delay); FlashLightPoint = Vector3.zero; } + /// + /// Waits for a specified delay and then sets the PlayerPosition to Vector3.zero. + /// + /// The delay to wait before setting the PlayerPosition. + /// An IEnumerator object. private IEnumerator ExpirePlayerPoint(float delay) { yield return new WaitForSeconds(delay); PlayerPosition = Vector3.zero; } } - public static class MathHelpers - { - public static float Random(float a, float b) - { - float num = (float)random_0.NextDouble(); - return a + (b - a) * num; - } - - private static readonly System.Random random_0 = new System.Random(); - } public class TimedVector3 { public TimedVector3(Vector3 point, float timestamp) @@ -143,5 +290,4 @@ public TimedVector3(Vector3 point, float timestamp) public Vector3 Point { get; set; } public float Timestamp { get; set; } } - } \ No newline at end of file diff --git a/SAIN Flashlights/Components/SAIN_Flashlight_Component.cs b/SAIN Flashlights/Components/SAIN_Flashlight_Component.cs index 98bed359a..137d8af6b 100644 --- a/SAIN Flashlights/Components/SAIN_Flashlight_Component.cs +++ b/SAIN Flashlights/Components/SAIN_Flashlight_Component.cs @@ -16,14 +16,8 @@ public class SAIN_Flashlight_Component : MonoBehaviour private Player Player { get; set; } protected static ManualLogSource Logger { get; private set; } - public List LightComponents { get; set; } - private FlashlightDetection _lightDetection; - public int SelectedMode { get; set; } - public bool IsActive { get; set; } - public Item FlashlightItem { get; set; } - private void Start() { Player = GetComponent(); @@ -58,17 +52,20 @@ private IEnumerator LightDetection() yield return new WaitForSeconds(1f); } - if (Player.AIData.UsingLight && WhiteLight) + if (WhiteLight) { - _lightDetection.CreateDetectionPoints(Player); - } + if (Player.IsAI) + { + _lightDetection.DetectAndInvestigateFlashlight(Player); + } - if (Player.IsAI) - { - _lightDetection.DetectPoints(Player); + if (Player.IsYourPlayer) + { + _lightDetection.CreateDetectionPoints(Player); + } } - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.05f); } } diff --git a/SAIN Flashlights/Config/DazzleConfig.cs b/SAIN Flashlights/Config/DazzleConfig.cs index e827b6703..3a383dff5 100644 --- a/SAIN Flashlights/Config/DazzleConfig.cs +++ b/SAIN Flashlights/Config/DazzleConfig.cs @@ -4,8 +4,8 @@ namespace SAIN_Flashlights.Config { internal class DazzleConfig { - public static ConfigEntry EnableMod { get; private set; } - public static ConfigEntry Angle { get; private set; } + public static ConfigEntry EnableDetection { get; private set; } + public static ConfigEntry FasterDetection { get; private set; } public static ConfigEntry Effectiveness { get; private set; } public static ConfigEntry MaxDazzleRange { get; private set; } public static ConfigEntry DebugFlash { get; private set; } @@ -15,22 +15,27 @@ public static void Init(ConfigFile Config) { string debugmode = "Settings"; - Effectiveness = Config.Bind(debugmode, "Dazzle Intensity", 1f, + EnableDetection = Config.Bind(debugmode, "Enable Player Flashlight Detection", true, + new ConfigDescription("Bots will notice flashlights being shined around and investigate the source", + null, + new ConfigurationManagerAttributes { IsAdvanced = false, Order = 10 })); + + FasterDetection = Config.Bind(debugmode, "Faster Detection from Flashlights", true, + new ConfigDescription("Bots will notice you faster if you are shining a light at them", + null, + new ConfigurationManagerAttributes { IsAdvanced = false, Order = 9 })); + + Effectiveness = Config.Bind(debugmode, "Dazzle Intensity", 3f, new ConfigDescription("Intensifies the dazzle effect", - new AcceptableValueRange(0.1f, 3.0f), + new AcceptableValueRange(0.1f, 10.0f), new ConfigurationManagerAttributes { IsAdvanced = false, Order = 6 })); - Angle = Config.Bind(debugmode, "Angle Modifier", 1f, - new ConfigDescription("Lower value is equal to wider flashlight angle. The wider the angle, the easier it is for bots to be dazzled.", - new AcceptableValueRange(0.8f, 1.0f), - new ConfigurationManagerAttributes { IsAdvanced = true, Order = 5 })); - MaxDazzleRange = Config.Bind(debugmode, "Max Dazzle Range", 25f, new ConfigDescription("Maximum possible distance to affect AI aim", new AcceptableValueRange(5.0f, 100.0f), new ConfigurationManagerAttributes { IsAdvanced = true, Order = 4 })); - AIHatesFlashlights = Config.Bind(debugmode, "Random Voicelines", true, + AIHatesFlashlights = Config.Bind(debugmode, "Random Voicelines", false, new ConfigDescription("Small Chance to play a random voiceline when being dazzled", null, new ConfigurationManagerAttributes { IsAdvanced = false, Order = 3 })); @@ -40,9 +45,8 @@ public static void Init(ConfigFile Config) null, new ConfigurationManagerAttributes { IsAdvanced = false, Order = 2 })); - - DebugFlash = Config.Bind(debugmode, "Debug Logs", false, - new ConfigDescription("", + DebugFlash = Config.Bind(debugmode, "Debug Mode", false, + new ConfigDescription("Draws Lines and Spheres to visualize flashlight detection. Logs information about dazzle.", null, new ConfigurationManagerAttributes { IsAdvanced = true, Order = 1 })); } diff --git a/SAIN Flashlights/Helpers/FlashlightHelpers.cs b/SAIN Flashlights/Helpers/FlashlightHelpers.cs index b5eea3e4f..2bcebce24 100644 --- a/SAIN Flashlights/Helpers/FlashlightHelpers.cs +++ b/SAIN Flashlights/Helpers/FlashlightHelpers.cs @@ -3,15 +3,12 @@ using System; using UnityEngine; using static SAIN_Flashlights.Config.DazzleConfig; +using SAIN_Helpers; namespace SAIN_Flashlights.Helpers { public class FlashLight { - private GameObject _flashlight; - - private GameObject[] _modes; - protected static ManualLogSource Logger { get; private set; } /// @@ -34,20 +31,20 @@ public static void EnemyWithFlashlight(BotOwner bot, IAIDetails person) { if (!Physics.Raycast(weaponRoot, (position - weaponRoot).normalized, (position - weaponRoot).magnitude, LayerMaskClass.HighPolyWithTerrainMask)) { + DebugDraw(weaponRoot, position); + if (SillyMode.Value) { - NonStaticHelpers voice = new NonStaticHelpers(); - voice.FunnyMode(bot, position); + FunnyHelpers.FunnyMode(bot, position); return; } float gainSight = GetGainSightModifier(enemyDist); float dazzlemodifier = 1f; + if (enemyDist < MaxDazzleRange.Value) - { dazzlemodifier = GetDazzleModifier(bot, person); - } ApplyDazzle(dazzlemodifier, gainSight, bot); @@ -77,8 +74,7 @@ public static void EnemyWithLaser(BotOwner bot, IAIDetails person) { if (SillyMode.Value) { - NonStaticHelpers voice = new NonStaticHelpers(); - voice.FunnyMode(bot, position); + FunnyHelpers.FunnyMode(bot, position); return; } @@ -130,13 +126,13 @@ private static void DebugLogs(BotOwner bot, float dazzlemod, float gainsightmod, /// The position of the enemy. /// The weapon root of the enemy. /// Whether the enemy is looking at the player. - private static void DebugDraw(Vector3 position, Vector3 weaponRoot, bool enemylookatme) + private static void DebugDraw(Vector3 position, Vector3 weaponRoot) { - if (DebugFlash.Value && enemylookatme) + if (DebugFlash.Value) { - DebugDrawer.Sphere(position - weaponRoot, 0.05f, Color.white, 1f); - DebugDrawer.Line(position, weaponRoot, 0.01f, Color.green, 1f); - DebugDrawer.Line(weaponRoot, position, 0.01f, Color.red, 1f); + SAIN_Helpers.DebugDrawer.Sphere(position - weaponRoot, 0.05f, Color.white, 1f); + SAIN_Helpers.DebugDrawer.Line(position, weaponRoot, 0.01f, Color.green, 1f); + SAIN_Helpers.DebugDrawer.Line(weaponRoot, position, 0.01f, Color.red, 1f); } } @@ -150,18 +146,23 @@ private static void ApplyDazzle(float dazzleModif, float gainSightModif, BotOwne { GClass557 modif = new GClass557 { - PrecicingSpeedCoef = Mathf.Clamp(dazzleModif, 1f, 2f) * Effectiveness.Value, - AccuratySpeedCoef = Mathf.Clamp(dazzleModif, 1f, 2f) * Effectiveness.Value, + PrecicingSpeedCoef = Mathf.Clamp(dazzleModif, 1f, 5f) * Effectiveness.Value, + AccuratySpeedCoef = Mathf.Clamp(dazzleModif, 1f, 5f) * Effectiveness.Value, LayChanceDangerCoef = 1f, VisibleDistCoef = 1f, GainSightCoef = gainSightModif, - ScatteringCoef = Mathf.Clamp(dazzleModif, 1f, 1.5f) * Effectiveness.Value, - PriorityScatteringCoef = Mathf.Clamp(dazzleModif, 1f, 1.5f) * Effectiveness.Value, + ScatteringCoef = Mathf.Clamp(dazzleModif, 1f, 2.5f) * Effectiveness.Value, + PriorityScatteringCoef = Mathf.Clamp(dazzleModif, 1f, 2.5f) * Effectiveness.Value, HearingDistCoef = 1f, TriggerDownDelay = 1f, WaitInCoverCoef = 1f }; + if (AIHatesFlashlights.Value) + { + FunnyHelpers.RandomVoiceLine(bot); + } + bot.Settings.Current.Apply(modif, 0.1f); } @@ -176,10 +177,8 @@ private static bool FlashLightVisionCheck(BotOwner bot, IAIDetails person) Vector3 position = bot.MyHead.position; Vector3 weaponRoot = person.WeaponRoot.position; - float flashAngle = Mathf.Clamp(0.9770526f * Angle.Value, 0.8f, 1f); - bool enemylookatme = IsAngLessNormalized(NormalizeFastSelf(position - weaponRoot), person.LookDirection, flashAngle); - - DebugDraw(position, weaponRoot, enemylookatme); + float flashAngle = Mathf.Clamp(0.9770526f, 0.8f, 1f); + bool enemylookatme = SAIN_Math.IsAngLessNormalized(SAIN_Math.NormalizeFastSelf(position - weaponRoot), person.LookDirection, flashAngle); return enemylookatme; } @@ -195,40 +194,12 @@ private static bool LaserVisionCheck(BotOwner bot, IAIDetails person) Vector3 position = bot.MyHead.position; Vector3 weaponRoot = person.WeaponRoot.position; - float laserAngle = 0.999f; - bool enemylookatme = IsAngLessNormalized(NormalizeFastSelf(position - weaponRoot), person.LookDirection, laserAngle); - - DebugDraw(position, weaponRoot, enemylookatme); + float laserAngle = 0.990f; + bool enemylookatme = SAIN_Math.IsAngLessNormalized(SAIN_Math.NormalizeFastSelf(position - weaponRoot), person.LookDirection, laserAngle); return enemylookatme; } - /// - /// Checks if the angle between two vectors is less than a given cosine value. - /// - /// The first vector. - /// The second vector. - /// The cosine value. - /// True if the angle between the two vectors is less than the given cosine value, false otherwise. - private static bool IsAngLessNormalized(Vector3 a, Vector3 b, float cos) - { - return a.x * b.x + a.y * b.y + a.z * b.z > cos; - } - - /// - /// Normalizes the vector in a less performance heavy way than normal - /// - /// The vector to normalize. - /// The normalized vector. - private static Vector3 NormalizeFastSelf(Vector3 v) - { - float num = (float)Math.Sqrt((double)(v.x * v.x + v.y * v.y + v.z * v.z)); - v.x /= num; - v.y /= num; - v.z /= num; - return v; - } - /// /// Calculates the dazzle modifier for a given BotOwner and Enemy. /// @@ -243,20 +214,13 @@ private static float GetDazzleModifier(BotOwner ___botOwner_0, IAIDetails person float enemyDist = (position - weaponRoot).magnitude; float dazzlemodifier = 1f - (enemyDist / MaxDazzleRange.Value); - dazzlemodifier = Mathf.Clamp(dazzlemodifier, 0.1f, 1.0f); - dazzlemodifier += 1.33f; + dazzlemodifier = (2 * dazzlemodifier) + 1f; if (bot.NightVision.UsingNow) { dazzlemodifier *= 1.5f; } - if (AIHatesFlashlights.Value) - { - NonStaticHelpers voice = new NonStaticHelpers(); - voice.RandomVoiceLine(bot); - } - return dazzlemodifier; } @@ -274,11 +238,11 @@ private static float GetGainSightModifier(float enemyDist) } } - public class NonStaticHelpers + public class FunnyHelpers { private static float funnytimer = 0f; - public void FunnyMode(BotOwner bot, Vector3 position) + public static void FunnyMode(BotOwner bot, Vector3 position) { if (funnytimer < Time.time) { @@ -332,7 +296,7 @@ public void FunnyMode(BotOwner bot, Vector3 position) } } - public void RandomVoiceLine(BotOwner bot) + public static void RandomVoiceLine(BotOwner bot) { float randomphrase = UnityEngine.Random.value; if (randomphrase > 0.97f) diff --git a/SAIN Flashlights/Patches/CheckFlashlightPatch.cs b/SAIN Flashlights/Patches/CheckFlashlightPatch.cs index ddd4e8af7..168b97685 100644 --- a/SAIN Flashlights/Patches/CheckFlashlightPatch.cs +++ b/SAIN Flashlights/Patches/CheckFlashlightPatch.cs @@ -3,15 +3,20 @@ using HarmonyLib; using SAIN_Flashlights.Components; using System.Reflection; +using static SAIN_Flashlights.Config.DazzleConfig; namespace SAIN_Flashlights.Patches { public class CheckFlashlightPatch : ModulePatch { private static FieldInfo _tacticalModesField; + private static MethodInfo _UsingLight; protected override MethodBase GetTargetMethod() { + _UsingLight = AccessTools.PropertySetter(typeof(AiDataClass), "UsingLight"); + _tacticalModesField = AccessTools.Field(typeof(TacticalComboVisualController), "list_0"); + return AccessTools.Method(typeof(Player.FirearmController), "SetLightsState"); } @@ -19,9 +24,18 @@ protected override MethodBase GetTargetMethod() public static void PatchPostfix(ref Player ____player) { SAIN_Flashlight_Component flashlightComponent = ____player.gameObject.GetComponent(); + if (flashlightComponent != null) { flashlightComponent.CheckDevice(____player, _tacticalModesField); + + if (!flashlightComponent.WhiteLight && !flashlightComponent.Laser) + { + _UsingLight.Invoke(____player.AIData, new object[] { false }); + + if (DebugFlash.Value) + Logger.LogDebug($"Updated Using Light for {____player.Profile.Nickname}, now set to {____player.AIData.UsingLight}"); + } } else { diff --git a/SAIN Flashlights/Patches/DazzlePatch.cs b/SAIN Flashlights/Patches/DazzlePatch.cs index be75fd8fe..c7848c2df 100644 --- a/SAIN Flashlights/Patches/DazzlePatch.cs +++ b/SAIN Flashlights/Patches/DazzlePatch.cs @@ -25,7 +25,7 @@ public static void Prefix(ref BotOwner ___botOwner_0, IAIDetails person, ref flo SAIN_Flashlight_Component flashlightComponent = person.GetPlayer.gameObject.GetComponent(); if (flashlightComponent == null) { - Logger.LogError("flashlightComponent is null"); + Logger.LogError("SAIN Flashlight Dazzle: flashlightComponent is null"); return; } diff --git a/SAIN Flashlights/Plugin.cs b/SAIN Flashlights/Plugin.cs index cb5ee3f3c..dda204fb9 100644 --- a/SAIN Flashlights/Plugin.cs +++ b/SAIN Flashlights/Plugin.cs @@ -6,7 +6,7 @@ namespace SAIN_Flashlights { - [BepInPlugin("me.sol.sainflash", "SAIN Flashlights", "1.1")] + [BepInPlugin("me.sol.sainflash", "SAIN Flashlights", "2.0")] public class FlashlightsPlugin : BaseUnityPlugin { private void Awake() diff --git a/SAIN Flashlights/Properties/AssemblyInfo.cs b/SAIN Flashlights/Properties/AssemblyInfo.cs index f0dc09338..4c5970035 100644 --- a/SAIN Flashlights/Properties/AssemblyInfo.cs +++ b/SAIN Flashlights/Properties/AssemblyInfo.cs @@ -32,6 +32,6 @@ // 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.*")] -[assembly: AssemblyVersion("1.1.0.0")] -[assembly: AssemblyFileVersion("1.1.0.0")] +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] [assembly: TarkovVersion(22617)] diff --git a/SAIN Flashlights/SAIN Flashlights.csproj b/SAIN Flashlights/SAIN Flashlights.csproj index 3707f2a96..0268e1135 100644 --- a/SAIN Flashlights/SAIN Flashlights.csproj +++ b/SAIN Flashlights/SAIN Flashlights.csproj @@ -48,7 +48,7 @@ false - SAIN.Flashlights + SAIN_Flashlights diff --git a/SAIN Helpers/Helpers/Math.cs b/SAIN Helpers/Helpers/SAIN_Math.cs similarity index 99% rename from SAIN Helpers/Helpers/Math.cs rename to SAIN Helpers/Helpers/SAIN_Math.cs index 17b4f05ea..0a4e742e3 100644 --- a/SAIN Helpers/Helpers/Math.cs +++ b/SAIN Helpers/Helpers/SAIN_Math.cs @@ -10,7 +10,7 @@ namespace SAIN_Helpers { - public static class Math + public static class SAIN_Math { /// /// Calculates the inverse of a value using a logistic function. @@ -1057,7 +1057,7 @@ public static bool IsOdd(int value) /// The Vector3 to rotate. /// The direction to rotate. /// The rotated Vector3. - public static Vector3 Rotate90(Vector3 n, Math.SideTurn side) + public static Vector3 Rotate90(Vector3 n, SAIN_Math.SideTurn side) { if (side == SideTurn.left) { diff --git a/SAIN Helpers/SAIN Helpers.csproj b/SAIN Helpers/SAIN Helpers.csproj index f71c104cc..e87b1547e 100644 --- a/SAIN Helpers/SAIN Helpers.csproj +++ b/SAIN Helpers/SAIN Helpers.csproj @@ -154,7 +154,7 @@ - + diff --git a/SAIN Movement/Patches/BotMemoryPatch.cs b/SAIN Movement/Patches/BotMemoryPatch.cs index eb7a18bce..f05165c5a 100644 --- a/SAIN Movement/Patches/BotMemoryPatch.cs +++ b/SAIN Movement/Patches/BotMemoryPatch.cs @@ -15,7 +15,6 @@ public class SainMemory : MonoBehaviour public bool NeedtoHeal { get; set; } = false; public bool NeedtoReload { get; set; } = false; public float DodgeTimer { get; set; } = 0f; - public bool GoingToNewCover { get; set; } } public class AddComponentPatch : ModulePatch diff --git a/SAIN Movement/Patches/DogFightPatch.cs b/SAIN Movement/Patches/DogFightPatch.cs index 57ebccaf2..83a1c5e31 100644 --- a/SAIN Movement/Patches/DogFightPatch.cs +++ b/SAIN Movement/Patches/DogFightPatch.cs @@ -8,12 +8,12 @@ using UnityEngine.AI; using static SAIN_Audio.Movement.Config.DebugConfig; using static SAIN_Audio.Movement.Config.DogFighterConfig; +using SAIN_Helpers; namespace SAIN_Audio.Movement.Patches { public class DogFight { - private static Type _DogFightType; public class Start : ModulePatch { private static PropertyInfo _DogFightProperty; @@ -21,11 +21,12 @@ public class Start : ModulePatch protected override MethodBase GetTargetMethod() { _DogFightProperty = AccessTools.Property(typeof(BotOwner), "DogFight"); - _DogFightType = _DogFightProperty.PropertyType; - _DogFightState = AccessTools.PropertySetter(_DogFightType, "DogFightState"); - return AccessTools.Method(_DogFightType, "ShallStartCauseHavePlace"); + _DogFightState = AccessTools.PropertySetter(_DogFightProperty.PropertyType, "DogFightState"); + + return AccessTools.Method(_DogFightProperty.PropertyType, "ShallStartCauseHavePlace"); } + [PatchPrefix] public static bool PatchPrefix(ref BotOwner ___botOwner_0, ref NavMeshPath ___navMeshPath_0) { @@ -48,9 +49,10 @@ public class ManualUpdate : ModulePatch protected override MethodBase GetTargetMethod() { _DogFightProperty = AccessTools.Property(typeof(BotOwner), "DogFight"); - _DogFightType = _DogFightProperty.PropertyType; - _DogFightState = AccessTools.PropertySetter(_DogFightType, "DogFightState"); - return AccessTools.Method(_DogFightType, "ManualUpdate"); + + _DogFightState = AccessTools.PropertySetter(_DogFightProperty.PropertyType, "DogFightState"); + + return AccessTools.Method(_DogFightProperty.PropertyType, "ManualUpdate"); } [PatchPrefix] public static bool PatchPrefix(ref BotOwner ___botOwner_0, ref NavMeshPath ___navMeshPath_0, ref float ___float_2) @@ -115,9 +117,10 @@ public class Fight : ModulePatch protected override MethodBase GetTargetMethod() { _DogFightProperty = AccessTools.Property(typeof(BotOwner), "DogFight"); - _DogFightType = _DogFightProperty.PropertyType; - _DogFightState = AccessTools.PropertySetter(_DogFightType, "DogFightState"); - return AccessTools.Method(_DogFightType, "Fight"); + + _DogFightState = AccessTools.PropertySetter(_DogFightProperty.PropertyType, "DogFightState"); + + return AccessTools.Method(_DogFightProperty.PropertyType, "Fight"); } [PatchPrefix] public static bool PatchPrefix(ref BotOwner ___botOwner_0, ref float ___float_1, ref bool ___bool_0, ref NavMeshPath ___navMeshPath_0) @@ -192,7 +195,7 @@ private static bool CheckPathLength(NavMeshPath path, float straighDist) // Method_1 public static bool Backup(BotOwner bot, NavMeshPath navMeshPath_0, out Vector3 trgPos) { - Vector3 a = -NormalizeFastSelf(bot.Memory.GoalEnemy.Direction); + Vector3 a = -SAIN_Math.NormalizeFastSelf(bot.Memory.GoalEnemy.Direction); trgPos = Vector3.zero; float num = 0f; NavMeshHit navMeshHit; @@ -223,13 +226,5 @@ public static bool Backup(BotOwner bot, NavMeshPath navMeshPath_0, out Vector3 t } return false; } - public static Vector3 NormalizeFastSelf(Vector3 v) - { - float num = (float)Math.Sqrt((double)(v.x * v.x + v.y * v.y + v.z * v.z)); - v.x /= num; - v.y /= num; - v.z /= num; - return v; - } } } diff --git a/SAIN Movement/Patches/MovementPatch.cs b/SAIN Movement/Patches/MovementPatch.cs index b19fa437b..3394f07f5 100644 --- a/SAIN Movement/Patches/MovementPatch.cs +++ b/SAIN Movement/Patches/MovementPatch.cs @@ -10,7 +10,6 @@ public class MovementSpeed : ModulePatch { protected override MethodBase GetTargetMethod() { - // AccessTools lets us get methods easily return AccessTools.Method(typeof(BotOwner), "UpdateManual"); } [PatchPostfix] @@ -67,147 +66,4 @@ public static void PatchPostfix(BotOwner __instance) bot.GetPlayer.ChangePose(Pose); } } -} -/* - public class MovementSpeedPatch1 : ModulePatch - { - static float VisibleTimer = 0f; - protected override MethodBase GetTargetMethod() - { - return typeof(GClass406)?.GetMethod("GoToByWay", BindingFlags.Instance | BindingFlags.Public); - } - [PatchPostfix] - public static void PatchPostfix(ref BotOwner ___botOwner_0) - { - if (VisibleTimer < Time.time) - { - VisibleTimer = Time.time + 0.25f; - - if (___botOwner_0.Memory.HaveEnemy && !___botOwner_0.Memory.GoalEnemy.CanShoot && ___botOwner_0.Memory.GoalEnemy.PersonalLastSeenTime > Time.time + 5f) - { - ___botOwner_0.SetTargetMoveSpeed(0.1f); - ___botOwner_0.Mover.SetTargetMoveSpeed(0.1f); - ___botOwner_0.SetPose(0.1f); - ___botOwner_0.GetPlayer.ChangePose(0.1f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(false, 1f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Visible but not Shootable, Rat mode engaged"); - return; - } - //Move speed is set to 0.6 by default, this changes that to 1.0 (max walk speed) - if (___botOwner_0.AimingData.LastDist2Target < 20f || !___botOwner_0.WeaponManager.HaveBullets) - { - ___botOwner_0.SetTargetMoveSpeed(1.0f); - ___botOwner_0.Mover.SetTargetMoveSpeed(1.0f); - ___botOwner_0.SetPose(1.0f); - ___botOwner_0.GetPlayer.ChangePose(1.0f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(false, 1f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Close!"); - return; - } - if (___botOwner_0.AimingData.LastDist2Target > 40f && ___botOwner_0.Memory.GoalEnemy.CanShoot) - { - ___botOwner_0.SetTargetMoveSpeed(0.6f); - ___botOwner_0.Mover.SetTargetMoveSpeed(0.6f); - ___botOwner_0.SetPose(0.6f); - ___botOwner_0.GetPlayer.ChangePose(0.6f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(true, 0.6f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Visible but is far away, so I'm aiming"); - return; - } - } - } - } - public class MovementSpeedPatch2 : ModulePatch - { - static float VisibleTimer = 0f; - protected override MethodBase GetTargetMethod() - { - return typeof(GClass327)?.GetMethod("ManualUpdate", BindingFlags.Instance | BindingFlags.Public); - } - [PatchPostfix] - public static void PatchPostfix(ref BotOwner ___botOwner_0) - { - if (VisibleTimer < Time.time) - { - VisibleTimer = Time.time + 0.25f; - if (___botOwner_0.Memory.HaveEnemy && !___botOwner_0.Memory.GoalEnemy.CanShoot && ___botOwner_0.Memory.GoalEnemy.PersonalLastSeenTime > Time.time + 5f) - { - ___botOwner_0.SetTargetMoveSpeed(0.1f); - ___botOwner_0.Mover.SetTargetMoveSpeed(0.1f); - ___botOwner_0.SetPose(0.1f); - ___botOwner_0.GetPlayer.ChangePose(0.1f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(false, 1f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Visible but not Shootable, Rat mode engaged"); - return; - } - //Move speed is set to 0.6 by default, this changes that to 1.0 (max walk speed) - if (___botOwner_0.AimingData.LastDist2Target < 20f || !___botOwner_0.WeaponManager.HaveBullets) - { - ___botOwner_0.SetTargetMoveSpeed(1.0f); - ___botOwner_0.Mover.SetTargetMoveSpeed(1.0f); - ___botOwner_0.SetPose(1.0f); - ___botOwner_0.GetPlayer.ChangePose(1.0f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(false, 1f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Close!"); - return; - } - if (___botOwner_0.AimingData.LastDist2Target > 30f && ___botOwner_0.Memory.GoalEnemy.CanShoot) - { - ___botOwner_0.SetTargetMoveSpeed(0.6f); - ___botOwner_0.Mover.SetTargetMoveSpeed(0.6f); - ___botOwner_0.SetPose(0.6f); - ___botOwner_0.GetPlayer.ChangePose(0.6f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(true, 0.6f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Visible but is far away, so I'm aiming"); - return; - } - } - } - } - public class MovementSpeedPatch3 : ModulePatch - { - static float VisibleTimer = 0f; - protected override MethodBase GetTargetMethod() - { - return typeof(GClass473)?.GetMethod("CheckLookEnemy", BindingFlags.Instance | BindingFlags.Public); - } - [PatchPostfix] - public static void PatchPostfix(ref BotOwner ___botOwner_0) - { - if (VisibleTimer < Time.time) - { - VisibleTimer = Time.time + 0.25f; - if (___botOwner_0.Memory.HaveEnemy && !___botOwner_0.Memory.GoalEnemy.CanShoot && ___botOwner_0.Memory.GoalEnemy.PersonalLastSeenTime > Time.time + 5f) - { - ___botOwner_0.SetTargetMoveSpeed(0.1f); - ___botOwner_0.Mover.SetTargetMoveSpeed(0.1f); - ___botOwner_0.SetPose(0.1f); - ___botOwner_0.GetPlayer.ChangePose(0.1f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(false, 1f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Visible but not Shootable, Rat mode engaged"); - return; - } - //Move speed is set to 0.6 by default, this changes that to 1.0 (max walk speed) - if (___botOwner_0.AimingData.LastDist2Target < 20f || !___botOwner_0.WeaponManager.HaveBullets) - { - ___botOwner_0.SetTargetMoveSpeed(1.0f); - ___botOwner_0.Mover.SetTargetMoveSpeed(1.0f); - ___botOwner_0.SetPose(1.0f); - ___botOwner_0.GetPlayer.ChangePose(1.0f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(false, 1f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Close!"); - return; - } - if (___botOwner_0.AimingData.LastDist2Target > 30f && ___botOwner_0.Memory.GoalEnemy.CanShoot) - { - ___botOwner_0.SetTargetMoveSpeed(0.6f); - ___botOwner_0.Mover.SetTargetMoveSpeed(0.6f); - ___botOwner_0.SetPose(0.6f); - ___botOwner_0.GetPlayer.ChangePose(0.6f); - ___botOwner_0.GetPlayer.MovementContext.SetAimingSlowdown(true, 0.6f); - //Logger.LogInfo($"Movement: [{___botOwner_0.name}] Enemy Visible but is far away, so I'm aiming"); - return; - } - } - } - }*/ \ No newline at end of file +} \ No newline at end of file diff --git a/SAIN-Helpers.dll b/SAIN-Helpers.dll index b3f1d0330..6a9811022 100644 Binary files a/SAIN-Helpers.dll and b/SAIN-Helpers.dll differ