public static void Postfix(ref TargetAimer __instance) { try { Visible target = __instance.Target; FireData fireData = __instance.GetComponentInParent <FireData>(); if (fireData != null && __instance.HasTarget && target.IsNotNull() && !Singleton.Manager <ManPauseGame> .inst.IsPaused && ((target.type == ObjectTypes.Vehicle && target.tank.IsNotNull()) || (target.type == ObjectTypes.Block && target.block.IsNotNull()))) { TankBlock block = (TankBlock)ProjectilePatch.m_Block.GetValue(__instance); Tank tank = (bool)(UnityEngine.Object)block ? block.tank : (Tank)null; string name = block ? block.name : "UNKNOWN"; TimedFuseData timedFuse = __instance.GetComponentInParent <TimedFuseData>(); bool enemyWeapon = tank == null || !ManSpawn.IsPlayerTeam(tank.Team); if (((enemyWeapon && WeaponAimSettings.EnemyLead) || (!enemyWeapon && WeaponAimSettings.PlayerLead)) && !(fireData is FireDataShotgun) && fireData.m_MuzzleVelocity > 0.0f) { Vector3 AimPointVector = (Vector3)ProjectilePatch.m_TargetPosition.GetValue(__instance); Vector3 relDist = AimPointVector - __instance.transform.position; WeaponRound bulletPrefab = fireData.m_BulletPrefab; bool useGravity = false; if (bulletPrefab != null && bulletPrefab is Projectile projectile && projectile.rbody != null) { if (projectile is MissileProjectile missileProjectile) { useGravity = missileProjectile.rbody.useGravity || WeaponAimSettings.BallisticMissile; } else { useGravity = projectile.rbody.useGravity; } } Rigidbody rbodyTank = __instance.GetComponentInParent <Tank>().rbody; Vector3 angularToggle = rbodyTank.angularVelocity; Vector3 relativeVelocity = (__instance.Target.rbody ? __instance.Target.rbody.velocity : Vector3.zero) - (rbodyTank.velocity + angularToggle); float time = relDist.magnitude / fireData.m_MuzzleVelocity; Vector3 relativeAcceleration = target.type == ObjectTypes.Vehicle ? TargetManager.GetAcceleration(target.tank) : Vector3.zero; if (useGravity) { relativeAcceleration -= Physics.gravity; } float exactTime = BallisticEquations.SolveBallisticArc(__instance.transform.position, fireData.m_MuzzleVelocity, AimPointVector, relativeVelocity, relativeAcceleration); Vector3 adjIntercept = AimPointVector + (relativeVelocity * time); if (exactTime != Mathf.Infinity) { time = exactTime; adjIntercept = AimPointVector + (relativeVelocity * time) + ((relativeAcceleration + (useGravity ? Physics.gravity : Vector3.zero)) / 2 * time * time); } if (timedFuse != null) { timedFuse.m_FuseTime = time; } ProjectilePatch.m_TargetPosition.SetValue(__instance, adjIntercept); } // Either disabled for enemy, or is a beam weapon else { if (timedFuse != null) { timedFuse.m_FuseTime = 0.0f; } } } } catch (NullReferenceException exception) { Console.WriteLine("[WeaponAimMod] TargetAimer.UpdateTarget PATCH FAILED"); Console.WriteLine(exception.Message); } }
public static bool Prefix(ref TargetAimer __instance, ref float rotateSpeed) { TankBlock block = (TankBlock)m_Block.GetValue(__instance); // Has a target if (WeaponAimSettings.OctantAim && block && block.tank && __instance.HasTarget) { Tank tank = block.tank; bool enemyWeapon = !ManSpawn.IsPlayerTeam(tank.Team); if (enemyWeapon && WeaponAimSettings.EnemyLead || !enemyWeapon && WeaponAimSettings.PlayerLead) { Vector3 targetWorld = (Vector3)m_TargetPosition.GetValue(__instance); Func <Vector3, Vector3> aimDelegate = (Func <Vector3, Vector3>)AimDelegate.GetValue(__instance); if (__instance.HasTarget && aimDelegate != null) { targetWorld = aimDelegate(targetWorld); } // Check if we can aim List <GimbalAimer> gimbalAimers = (List <GimbalAimer>)m_GimbalAimers.GetValue(__instance); bool canAim = true; foreach (GimbalAimer aimer in gimbalAimers) { if (__instance.Target && canAim) { canAim = aimer.CanAim(targetWorld); if (!canAim) { break; } } } // If we can aim, is all good - continue as normal (will do aim calculation for gimbals twice) if (canAim) { return(true); } IModuleWeapon moduleWeapon = block.GetComponent <IModuleWeapon>(); OctantVision octantVision = tank.GetComponent <OctantVision>(); if (octantVision && gimbalAimers.Count > 0) { float[] XConstraints = new float[2]; float[] YConstraints = new float[2]; GimbalAimer XGimbal = null; GimbalAimer YGimbal = null; GimbalAimer FreeGimbal = null; bool free = false; foreach (GimbalAimer aimer in gimbalAimers) { if (aimer.rotationAxis == GimbalAimer.AxisConstraint.X) { XConstraints = aimer.rotationLimits; XGimbal = aimer; } else if (aimer.rotationAxis == GimbalAimer.AxisConstraint.Y) { YConstraints = aimer.rotationLimits; YGimbal = aimer; } else { FreeGimbal = aimer; free = true; break; } } int[] octants; if (free) { octants = new int[8] { 0, 1, 2, 3, 4, 5, 6, 7 }; OctantVision.Limits limits = new OctantVision.Limits { localToBlock = block.trans.InverseTransformPoint(FreeGimbal.transform.position), localToGimbal = Vector3.zero, localToBarrel = Vector3.zero, XConstraints = new float[2], YConstraints = new float[2] }; Visible betterTarget = octantVision.GetFirstVisibleTechIsEnemy(octants, limits, block, null, null, aimDelegate); if (betterTarget) { Target.SetValue(__instance, betterTarget); UpdateTarget.Invoke(__instance, null); } } else if (XGimbal || YGimbal) { if (moduleWeapon != null) { GimbalAimer parentGimbal = null; GimbalAimer childGimbal = null; if (XGimbal) { if (YGimbal) { if (YGimbal.transform.IsChildOf(XGimbal.transform)) { parentGimbal = XGimbal; childGimbal = YGimbal; } else { parentGimbal = YGimbal; childGimbal = XGimbal; } } else { parentGimbal = XGimbal; } } else { parentGimbal = YGimbal; } Vector3 gimbalBlockLocalPosition = block.trans.InverseTransformPoint(parentGimbal.transform.position); Vector3 gimbalLocalPosition = Vector3.zero; if (parentGimbal && childGimbal) { gimbalLocalPosition = parentGimbal.transform.InverseTransformPoint(childGimbal.transform.position); } Vector3 fireLocalPosition = Vector3.zero; GimbalAimer localChildGimbal = childGimbal ? childGimbal : parentGimbal; if (moduleWeapon is ModuleWeaponGun moduleWeaponGun) { CannonBarrel[] cannonBarrels = (CannonBarrel[])m_CannonBarrels.GetValue(moduleWeaponGun); foreach (CannonBarrel cannonBarrel in cannonBarrels) { fireLocalPosition += localChildGimbal.transform.InverseTransformPoint(cannonBarrel.projectileSpawnPoint.position); } fireLocalPosition /= cannonBarrels.Length; } else if (moduleWeapon is ModuleWeaponFlamethrower moduleWeaponFlamethrower) { fireLocalPosition = localChildGimbal.transform.InverseTransformPoint(moduleWeaponFlamethrower.GetFireTransform().position); } OctantVision.Limits limits = new OctantVision.Limits { localToBlock = gimbalBlockLocalPosition, localToGimbal = gimbalLocalPosition, localToBarrel = fireLocalPosition, XConstraints = XConstraints, YConstraints = YConstraints }; octants = OctantVision.GetOctants(limits, parentGimbal, block); Visible betterTarget = octantVision.GetFirstVisibleTechIsEnemy(octants, limits, block, XGimbal, YGimbal, aimDelegate); if (betterTarget != null) { Target.SetValue(__instance, betterTarget); UpdateTarget.Invoke(__instance, null); } } } } } } return(true); }