public TargetingBase(IMyEntity entity, IMyCubeBlock controllingBlock) { if (entity == null) throw new ArgumentNullException("entity"); if (controllingBlock == null) throw new ArgumentNullException("controllingBlock"); myLogger = new Logger("TargetingBase", entity); MyEntity = entity; CubeBlock = controllingBlock; FuncBlock = controllingBlock as IMyFunctionalBlock; myTarget = NoTarget.Instance; CurrentTarget = myTarget; Options = new TargetingOptions(); entity.OnClose += obj => { if (WeaponsTargetingProjectile != null) CurrentTarget = null; }; //myLogger.debugLog("entity: " + MyEntity.getBestName() + ", block: " + CubeBlock.getBestName(), "TargetingBase()"); }
/// <summary> /// Calculates FiringDirection and InterceptionPoint /// </summary> /// TODO: if target is accelerating, look ahead (missiles and such) protected void SetFiringDirection() { if (myTarget.Entity == null || myTarget.Entity.MarkedForClose || MyEntity.MarkedForClose) return; Vector3 myVelocity = MyEntity.GetLinearVelocity(); Vector3 targetVelocity = myTarget.GetLinearVelocity(); Vector3 TargetPosition = myTarget.GetPosition(); FindInterceptVector(ProjectilePosition(), myVelocity, ProjectileSpeed(TargetPosition), TargetPosition, targetVelocity); if (myTarget.Entity != null) { if (PhysicalProblem(myTarget.ContactPoint.Value)) { myLogger.debugLog("Shot path is obstructed, blacklisting " + myTarget.Entity.getBestName(), "SetFiringDirection()"); BlacklistTarget(); return; } myLogger.debugLog("got an intercept vector: " + myTarget.FiringDirection + ", ContactPoint: " + myTarget.ContactPoint + ", target position: " + TargetPosition + ", by entity: " + myTarget.Entity.GetCentre(), "SetFiringDirection()"); } CurrentTarget = myTarget; }
/// <summary> /// Get any projectile which is a threat from Available_Targets[tType]. /// </summary> private bool PickAProjectile(TargetType tType) { List<IMyEntity> targetsOfType; if (Available_Targets.TryGetValue(tType, out targetsOfType)) { var sorted = targetsOfType.OrderBy(entity => GetWeaponsTargetingProjectile(entity)); foreach (IMyEntity entity in sorted) { if (entity.Closed) continue; if (tType == TargetType.Missile) { long owner = Guided.GuidedMissile.GetOwnerId(entity.EntityId); if (!CubeBlock.canConsiderHostile(owner)) { myLogger.debugLog("owner is not hostile", "PickAProjectile()"); continue; } } //bool isMissile = entity.ToString().StartsWith("MyMissile"); //if ((isMissile || entity is IMyMeteor) && Target.WeaponsTargeting(entity.EntityId) > 10) //{ // myLogger.debugLog("Not targeting " + entity.getBestName() + ", already targeted by " + Target.WeaponsTargeting(entity.EntityId) + " weapons", "PickAProjectile()"); // continue; //} // meteors and missiles are dangerous even if they are slow if (!(entity is IMyMeteor || entity.GetLinearVelocity().LengthSquared() > 100 || entity.ToString().StartsWith("MyMissile"))) continue; IMyEntity projectile = entity; IMyCubeGrid asGrid = projectile as IMyCubeGrid; if (asGrid != null) { IMyCubeBlock targetBlock; double distanceValue; if (GetTargetBlock(asGrid, tType, out targetBlock, out distanceValue)) projectile = targetBlock; else { myLogger.debugLog("failed to get a block from: " + asGrid.DisplayName, "PickAProjectile()"); continue; } } if (ProjectileIsThreat(projectile, tType)) { if (!PhysicalProblem(projectile.GetPosition())) { myLogger.debugLog("Is a threat: " + projectile.getBestName() + ", weapons targeting: " + GetWeaponsTargetingProjectile(projectile), "PickAProjectile()"); myTarget = new TurretTarget(projectile, tType); return true; } else myLogger.debugLog("Physical problem: " + projectile.getBestName(), "PickAProjectile()"); } else myLogger.debugLog("Not a threat: " + projectile.getBestName(), "PickAProjectile()"); } } return false; }
/// <summary> /// Get the closest target of the specified type from Available_Targets[tType]. /// </summary> private bool SetClosest(TargetType tType, ref double closerThan) { List<IMyEntity> targetsOfType; if (!Available_Targets.TryGetValue(tType, out targetsOfType)) return false; myLogger.debugLog("getting closest " + tType + ", from list of " + targetsOfType.Count, "SetClosest()"); IMyEntity closest = null; Vector3D weaponPosition = ProjectilePosition(); foreach (IMyEntity entity in targetsOfType) { if (entity.Closed) continue; IMyEntity target; Vector3D targetPosition; double distanceValue; // get block from grid before obstruction test IMyCubeGrid asGrid = entity as IMyCubeGrid; if (asGrid != null) { IMyCubeBlock targetBlock; if (GetTargetBlock(asGrid, tType, out targetBlock, out distanceValue)) target = targetBlock; else continue; targetPosition = target.GetPosition(); } else { target = entity; targetPosition = target.GetPosition(); distanceValue = Vector3D.DistanceSquared(targetPosition, weaponPosition); if (distanceValue > Options.TargetingRangeSquared) { myLogger.debugLog("for type: " + tType + ", too far to target: " + target.getBestName(), "SetClosest()"); continue; } if (PhysicalProblem(targetPosition)) { myLogger.debugLog("can't target: " + target.getBestName(), "SetClosest()"); Blacklist.Add(target); continue; } } if (distanceValue < closerThan) { closest = target; closerThan = distanceValue; } } if (closest != null) { myTarget = new TurretTarget(closest, tType); return true; } return false; }
/// <summary> /// Finds a target /// </summary> protected void UpdateTarget() { if (Options.TargetingRange < 1f) { myLogger.debugLog("Not targeting, zero range", "UpdateTarget()"); return; } if ((myTarget.TType & TargetType.Projectile) != 0 && !myTarget.Entity.Closed) if (TryHard || ProjectileIsThreat(myTarget.Entity, myTarget.TType)) { myLogger.debugLog("Keeping Target = " + myTarget.Entity.getBestName(), "UpdateTarget()"); return; } myTarget = new NoTarget(); CollectTargets(); PickATarget(); if (myTarget.Entity != null && CurrentTarget != myTarget) myLogger.debugLog("New target: " + myTarget.Entity.getBestName(), "UpdateTarget()"); else if (CurrentTarget != null && CurrentTarget.Entity != null) myLogger.debugLog("Lost target: " + CurrentTarget.Entity.getBestName(), "UpdateTarget()"); CurrentTarget = myTarget; }
protected void BlacklistTarget() { myLogger.debugLog("Blacklisting " + myTarget.Entity, "BlacklistTarget()"); Blacklist.Add(myTarget.Entity); myTarget = new NoTarget(); CurrentTarget = myTarget; }
/// <summary> /// Targets a LastSeen chosen from the given storage, will overrride current target. /// </summary> /// <param name="storage">NetworkStorage to get LastSeen from.</param> protected void GetLastSeenTarget(RelayStorage storage, double range) { if (Globals.UpdateCount < m_nextLastSeenSearch) return; m_nextLastSeenSearch = Globals.UpdateCount + 100ul; if (storage == null) { //myLogger.debugLog("no storage", "GetLastSeenTarget()", Logger.severity.INFO); return; } if (storage.LastSeenCount == 0) { //myLogger.debugLog("no last seen in storage", "GetLastSeenTarget()", Logger.severity.DEBUG); return; } LastSeen processing; IMyCubeBlock targetBlock; if (CurrentTarget.Entity != null && storage.TryGetLastSeen(CurrentTarget.Entity.EntityId, out processing) && processing.isRecent()) { LastSeenTarget lst = myTarget as LastSeenTarget; if (lst != null && lst.Block != null && !lst.Block.Closed) { lst.Update(processing); CurrentTarget = myTarget; return; } if (ChooseBlock(processing, out targetBlock)) { myTarget = new LastSeenTarget(processing, targetBlock); CurrentTarget = myTarget; return; } } if (Options.TargetEntityId.HasValue) { if (storage.TryGetLastSeen(Options.TargetEntityId.Value, out processing)) { ChooseBlock(processing, out targetBlock); myTarget = new LastSeenTarget(processing, targetBlock); CurrentTarget = myTarget; } //else // myLogger.debugLog("failed to get last seen from entity id", "GetLastSeenTarget()"); return; } processing = null; targetBlock = null; if (SEAD) { float highestPowerLevel = 0f; storage.ForEachLastSeen((LastSeen seen) => { if (seen.isRecent() && CubeBlock.canConsiderHostile(seen.Entity) && Options.CanTargetType(seen.Entity)) { IMyCubeBlock block; float powerLevel; if (RadarEquipment.GetRadarEquipment(seen, out block, out powerLevel) && powerLevel > highestPowerLevel) { highestPowerLevel = powerLevel; processing = seen; targetBlock = block; } } }); } else { // choose closest grid Vector3D myPos = ProjectilePosition(); double closestDist = range * range; storage.ForEachLastSeen(seen => { if (seen.isRecent() && CubeBlock.canConsiderHostile(seen.Entity) && Options.CanTargetType(seen.Entity)) { IMyCubeBlock block; if (!ChooseBlock(seen, out block)) return; // always prefer a grid with a block if (targetBlock != null && block == null) return; double dist = Vector3D.DistanceSquared(myPos, seen.LastKnownPosition); if (dist < closestDist) { closestDist = dist; processing = seen; targetBlock = block; } } }); } if (processing == null) { //myLogger.debugLog("failed to get a target from last seen", "GetLastSeenTarget()"); myTarget = NoTarget.Instance; CurrentTarget = myTarget; } else { myTarget = new LastSeenTarget(processing, targetBlock); CurrentTarget = myTarget; } }
protected void BlacklistTarget() { //myLogger.debugLog("Blacklisting " + myTarget.Entity, "BlacklistTarget()"); Blacklist.Add(myTarget.Entity); myTarget = NoTarget.Instance; CurrentTarget = myTarget; }