public static void SelectionStateFire_SetCalledShot_Postfix(SelectionStateFire __instance, ArmorLocation location) { Mod.Log.Trace("SSF:SCS entered"); if (location == ArmorLocation.Head) { Mod.Log.Debug(" SCS Checking if headshot should be prevented."); bool canAlwaysCalledShot = false; List <Statistic> customStats = ActorHelper.FindCustomStatistic(ModStats.CalledShowAlwaysAllow, __instance.SelectedActor); foreach (Statistic stat in customStats) { if (stat.ValueType() == typeof(bool) && stat.Value <bool>()) { canAlwaysCalledShot = true; } } bool canBeTargeted = __instance.TargetedCombatant.IsShutDown || __instance.TargetedCombatant.IsProne || canAlwaysCalledShot; Mod.Log.Debug($" Select - target:{__instance.TargetedCombatant.DisplayName}_{__instance.TargetedCombatant.GetPilot()?.Name} canBeTargeted:{canBeTargeted} by attacker:{__instance.SelectedActor}"); Mod.Log.Debug($" isShutdown:{__instance.TargetedCombatant.IsShutDown} isProne:{__instance.TargetedCombatant.IsProne} canAlwaysCalledShot:{canAlwaysCalledShot}"); if (!canBeTargeted) { Mod.Log.Debug(" Disabling headshot."); Traverse.Create(__instance).Method("ClearCalledShot").GetValue(); } } }
static void Postfix(SelectionStateFire __instance) { Mod.Log.Trace?.Write("SSF:SCS entered"); bool attackerCanAlwaysMakeCalledShot = __instance.SelectedActor.CanAlwaysUseCalledShot(); if (!attackerCanAlwaysMakeCalledShot && Mod.Config.Combat.CalledShot.DisableAllLocations) { Mod.Log.Info?.Write($" Disabling called shot from attacker: {__instance.SelectedActor.DistinctId()} against target vehicle: {__instance.TargetedCombatant.DistinctId()}"); Traverse.Create(__instance).Method("ClearCalledShot").GetValue(); } }
public static bool Prefix(SelectionStateFire __instance, ref bool __result, ICombatant combatant) { Mod.Log.Trace?.Write("SSF:PCC:PRE entered"); if (__instance != null && combatant != null && combatant is AbstractActor targetActor && __instance.SelectedActor != null) { CombatGameState Combat = __instance.SelectedActor.Combat; bool targetIsFriendly = Combat.HostilityMatrix.IsFriendly(combatant.team.GUID, Combat.LocalPlayerTeamGuid); if (targetIsFriendly) { Mod.Log.Trace?.Write("Friendly target, skipping check"); return(true); } EWState targetState = new EWState(targetActor); EWState attackerState = new EWState(__instance.SelectedActor); if (__instance.SelectionType == SelectionType.FireMorale) { // Prevents blips from being the targets of called shots VisibilityLevel targetVisibility = __instance.SelectedActor.VisibilityToTargetUnit(targetActor); if (targetVisibility < VisibilityLevel.LOSFull) { Mod.Log.Info?.Write($"Target {CombatantUtils.Label(combatant)} is a blip, cannot be targeted by called shot"); __result = false; return(false); } float distance = Vector3.Distance(__instance.SelectedActor.CurrentPosition, targetActor.CurrentPosition); bool hasVisualScan = VisualLockHelper.GetVisualScanRange(__instance.SelectedActor) >= distance; SensorScanType sensorScan = SensorLockHelper.CalculateSharedLock(targetActor, __instance.SelectedActor); if (sensorScan < SensorScanType.ArmorAndWeaponType && !hasVisualScan) { Mod.Log.Info?.Write($"Target {CombatantUtils.Label(targetActor)} sensor info {sensorScan} is less than SurfaceScan and range:{distance} outside visualScan range, cannot be targeted by called shot"); __result = false; return(false); } } else if (__instance.SelectionType == SelectionType.FireMulti) { if (targetState.HasStealth() || targetState.HasMimetic()) { Mod.Log.Info?.Write($"Target {CombatantUtils.Label(targetActor)} has stealth, cannot be multi-targeted!"); __result = false; return(false); } } } __result = false; return(true); }
static void Postfix(SelectionStateFire __instance, ref bool __result) { Mod.Log.Trace?.Write("SSF:NCS:GET entered"); if (__result == true) { bool attackerCanAlwaysMakeCalledShot = __instance.SelectedActor.CanAlwaysUseCalledShot(); if (!attackerCanAlwaysMakeCalledShot && Mod.Config.Combat.CalledShot.DisableAllLocations) { Mod.Log.Debug?.Write($" Disabling NeedsCalledShot from attacker: {__instance.SelectedActor.DistinctId()} against target vehicle: {__instance.TargetedCombatant.DistinctId()}"); __result = false; } } }
public static void Postfix(SelectionStateFire __instance, ref bool __result) { if (__instance.TargetedCombatant == null || __instance.TargetedCombatant.Combat.EffectManager == null) { return; } if (__instance.TargetedCombatant.UnitType != UnitType.Mech && __instance.TargetedCombatant.UnitType != UnitType.Vehicle) { return; } if (Core.Settings.Tagged_Called_Shots) { var isTagged = __instance.TargetedCombatant.Combat.EffectManager.GetAllEffectsTargeting(__instance.TargetedCombatant) .Any(x => x.EffectData.Description.Name == "TAG MARKED"); if (isTagged) { __result = true; } } }
public static void Postfix(SelectionStateFire __instance, ArmorLocation location) { try { if (location == ArmorLocation.Head) { Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] Disable headshot if too many weapons are enabled..."); int enabledWeaponCount = Utilities.GetReadiedWeaponCount(__instance.SelectedActor.Weapons, __instance.TargetedCombatant); Pilot selectedPilot = __instance.SelectedActor.GetPilot(); int maxAllowedWeapons = Utilities.GetMaxAllowedWeaponCountForHeadshots(selectedPilot); bool validWeaponCountForPrecisionStrike = enabledWeaponCount <= maxAllowedWeapons ? true : false; bool headCanBeTargeted = __instance.TargetedCombatant.IsShutDown || __instance.TargetedCombatant.IsProne || validWeaponCountForPrecisionStrike; Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] __instance.SelectedActor: " + __instance.SelectedActor.DisplayName); Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] enabledWeaponCount: " + enabledWeaponCount); Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] validWeaponCountForPrecisionStrike: " + validWeaponCountForPrecisionStrike); Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] __instance.TargetedCombatant.DisplayName: " + __instance.TargetedCombatant.DisplayName); Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] __instance.TargetedCombatant.IsShutDown: " + __instance.TargetedCombatant.IsShutDown); Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] __instance.TargetedCombatant.IsProne: " + __instance.TargetedCombatant.IsProne); Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] headCanBeTargeted: " + headCanBeTargeted); if (!headCanBeTargeted) { Logger.Debug("[SelectionStateFire_SetCalledShot_POSTFIX] Disabling headshot..."); Traverse.Create(__instance).Method("ClearCalledShot").GetValue(); } } } catch (Exception e) { Logger.Error(e); } }
static void Postfix(SelectionStateFire __instance, ArmorLocation location) { Mod.Log.Trace?.Write("SSF:SCS entered"); bool attackerCanAlwaysMakeCalledShot = __instance.SelectedActor.CanAlwaysUseCalledShot(); bool targetCanBeCalledShot = __instance.TargetedCombatant.IsShutDown || __instance.TargetedCombatant.IsProne || attackerCanAlwaysMakeCalledShot; Mod.Log.Debug?.Write($" Select - target:{__instance.TargetedCombatant.DistinctId()} canBeTargeted:{targetCanBeCalledShot} by attacker:{__instance.SelectedActor.DistinctId()}"); Mod.Log.Debug?.Write($" isShutdown:{__instance.TargetedCombatant.IsShutDown} isProne:{__instance.TargetedCombatant.IsProne} canAlwaysCalledShot:{attackerCanAlwaysMakeCalledShot}"); if (!targetCanBeCalledShot) { if (Mod.Config.Combat.CalledShot.DisableAllLocations) { Mod.Log.Info?.Write($" Disabling called shot from attacker: {__instance.SelectedActor.DistinctId()} against target: {__instance.TargetedCombatant.DistinctId()}"); Traverse.Create(__instance).Method("ClearCalledShot").GetValue(); } else if (Mod.Config.Combat.CalledShot.DisableHeadshots && location == ArmorLocation.Head) { Mod.Log.Info?.Write($" Disabling headshot from attacker: {__instance.SelectedActor.DistinctId()} against target mech: {__instance.TargetedCombatant.DistinctId()}"); Traverse.Create(__instance).Method("ClearCalledShot").GetValue(); } } }