// WARNING: DUPLICATE OF HBS CODE. THIS IS LIKELY TO BREAK IF HBS CHANGES THE SOURCE FUNCTIONS public static float GetSensorsRange(AbstractActor source) { if (source.StatCollection.ContainsStatistic(ModStats.DisableSensors)) { Mod.Log.Debug?.Write($"Returning minimum sensors range for {CombatantUtils.Label(source)} due to disabled sensors."); return(Mod.Config.Sensors.MinimumSensorRange()); } // Add multipliers and absolute bonuses EWState ewState = source.GetEWState(); Mod.Log.Trace?.Write($" == Sensors Range for for actor:{CombatantUtils.Label(source)}"); float rawRangeMulti = SensorLockHelper.GetAllSensorRangeMultipliers(source); float rangeMulti = rawRangeMulti + ewState.GetSensorsRangeMulti(); Mod.Log.Trace?.Write($" rangeMulti: {rangeMulti} = rawRangeMulti: {rawRangeMulti} + sensorCheckRangeMulti: {ewState.GetSensorsRangeMulti()}"); float rawRangeMod = SensorLockHelper.GetAllSensorRangeAbsolutes(source); float rangeMod = rawRangeMod * (1 + ewState.GetSensorsRangeMulti()); Mod.Log.Trace?.Write($" rangeMod: {rangeMod} = rawRangeMod: {rawRangeMod} + sensorCheckRangeMulti: {ewState.GetSensorsRangeMulti()}"); float sensorsRange = ewState.GetSensorsBaseRange() * rangeMulti + rangeMod; Mod.Log.Trace?.Write($" sensorsRange: { sensorsRange} = baseRange: {ewState.GetSensorsBaseRange()} * rangeMult: {rangeMulti} + rangeMod: {rangeMod}"); if (sensorsRange < Mod.Config.Sensors.MinimumSensorRange()) { sensorsRange = Mod.Config.Sensors.MinimumSensorRange(); } return(sensorsRange); }
public static float GetAdjustedSensorRange(AbstractActor source, ICombatant target) { EWState sourceState = source.GetEWState(); float sourceSensorRange = SensorLockHelper.GetSensorsRange(source); float targetSignature = SensorLockHelper.GetTargetSignature(target, sourceState); //LowVisibility.Logger.Debug($" source:{CombatantUtils.Label(source)} sensorRange:{sourceSensorRange}m vs targetSignature:x{targetSignature}"); //if (target != null && source.VisibilityToTargetUnit(target) > VisibilityLevel.None) { // // If is sensor lock, add the Hysterisis modifier // signatureModifiedRange += ___Combat.Constants.Visibility.SensorHysteresisAdditive; //} float modifiedRange = sourceSensorRange * targetSignature; return(modifiedRange); }
public static int UpdateSensorCheck(AbstractActor actor, bool updateAuras) { int checkResult = ModState.GetCheckResult(); actor.StatCollection.Set <int>(ModStats.CurrentRoundEWCheck, checkResult); Mod.Log.Debug?.Write($"Actor:{CombatantUtils.Label(actor)} has raw EW Check: {checkResult}"); if (updateAuras && actor.StatCollection.ContainsStatistic(ModStats.CAESensorsRange)) { float sensorsRange = SensorLockHelper.GetSensorsRange(actor); actor.StatCollection.Set <float>(ModStats.CAESensorsRange, sensorsRange); // TODO: Re-enable once KMission has researched actor.UpdateAuras(false); } return(checkResult); }
public static SensorScanType CalculateSensorLock(AbstractActor source, Vector3 sourcePos, ICombatant target, Vector3 targetPos) { if (source.GUID == target.GUID || source.Combat.HostilityMatrix.IsFriendly(source.TeamId, target.team.GUID)) { // If they are us, or allied, automatically give sensor details Mod.Log.Trace?.Write($" source:{CombatantUtils.Label(source)} is friendly to target:{CombatantUtils.Label(target)}. Forcing full visibility."); return(SensorScanType.AllInformation); } if (source.IsDead || source.IsFlaggedForDeath) { // If we're dead, we can't have vision or sensors. If we're off the map, we can't either. If the target is off the map, we can't see it. Mod.Log.Trace?.Write($" source:{CombatantUtils.Label(source)} is dead or dying. Forcing no visibility."); return(SensorScanType.NoInfo); } if (target.IsDead || target.IsFlaggedForDeath) { // If the target is dead, we can't have sensor but we have vision Mod.Log.Trace?.Write($" target:{CombatantUtils.Label(target)} is dead or dying. Forcing no sensor lock, vision based upon visibility."); return(SensorScanType.NoInfo); } if (source.IsTeleportedOffScreen) { Mod.Log.Trace?.Write($" source as is teleported off screen. Skipping."); return(SensorScanType.NoInfo); } if (source.StatCollection.ContainsStatistic(ModStats.DisableSensors)) { Mod.Log.Debug?.Write($"Sensors disabled for source: {CombatantUtils.Label(source)}, returning no info."); return(SensorScanType.NoInfo); } EWState sourceState = source.GetEWState(); float distance = Vector3.Distance(sourcePos, targetPos); float sensorRangeVsTarget = SensorLockHelper.GetAdjustedSensorRange(source, target); Mod.Log.Trace?.Write($"SensorLockHelper - source: {CombatantUtils.Label(source)} sensorRangeVsTarget: {sensorRangeVsTarget} vs distance: {distance}"); if (target is BattleTech.Building targetBuilding) { // If the target is a building, show them so long as they are in sensor distance // TODO: ADD FRIENDLY ECM CHECK HERE? // TODO: This should be calculated more fully! Major bug here! SensorScanType buildingLock = sourceState.GetCurrentEWCheck() > 0 ? SensorScanType.ArmorAndWeaponType : SensorScanType.NoInfo; Mod.Log.Trace?.Write($" target:{CombatantUtils.Label(targetBuilding)} is a building with lockState:{buildingLock}"); return(buildingLock); } else if ((target as AbstractActor) != null) { AbstractActor targetActor = target as AbstractActor; EWState targetState = targetActor.GetEWState(); if (distance > sensorRangeVsTarget) { // Check for Narc effect that will show the target regardless of range SensorScanType narcLock = HasNarcBeaconDetection(target, sourceState, targetState) ? SensorScanType.LocationAndType : SensorScanType.NoInfo; Mod.Log.Trace?.Write($" source:{CombatantUtils.Label(source)} is out of range, lock from Narc is:{narcLock}"); return(narcLock); } else { SensorScanType sensorLock = SensorScanType.NoInfo; if (targetActor.IsTeleportedOffScreen) { Mod.Log.Trace?.Write($" target is teleported off screen. Skipping."); } else { // TODO: Re-add shadowing logic // TODO: SensorLock adds a boost from friendlies if they have shares sensors? // We are within range, but check to see if the sensorInfoCheck failed sensorLock = CalculateSensorInfoLevel(source, target); // Check for Narc effect overriding detection if (sensorLock < SensorScanType.LocationAndType && HasNarcBeaconDetection(targetActor, sourceState, targetState)) { sensorLock = SensorScanType.LocationAndType; } } Mod.Log.Trace?.Write($"SensorLockHelper - source:{CombatantUtils.Label(source)} has sensorLock:({sensorLock}) vs " + $"target:{CombatantUtils.Label(target)}"); return(sensorLock); } } else { Mod.Log.Info?.Write($"SensorLockHelper - fallthrough case for target: {CombatantUtils.Label(target)} with type: {target.GetType()}. Returning NoLock!"); return(SensorScanType.NoInfo); } }