float ComparisonWeight(ITargetable x) { float distanceWeight = Vector3.Distance(transform.position, x.GetPosition()) / range; // distanceWeight is always 0 to 1 int typeWeight = x.GetTargetType() == preferredTargetType ? 0 : 1; // Move weight out of 0 to 1 range if it is not our preferred type return(distanceWeight + typeWeight); // Always targets the closest preferred target. Only targets a non-preferred target if a preferred target is not present. }
// ignoreNonPreferrential // In a sphere with the radius of range, find all enemy units and pick one to target List <ITargetable> ScanForTargets(bool ignoreNonPreferred) { Collider[] cols = Physics.OverlapSphere(transform.position, range, gameRules.targetLayerMask); List <ITargetable> targs = new List <ITargetable>(); for (int i = 0; i < cols.Length; i++) { ITargetable targ = GetITargetableFromCol(cols[i]); if (IsNull(targ)) // No targetable found { continue; } if (targs.Contains(targ)) // Ignore multiple colliders for one targetable { continue; } if (targ.GetTeam() == parentUnit.GetTeam()) // Can't target allies { continue; } if (!targ.GetVisibleTo(parentUnit.GetTeam())) // Must be visible to this team { continue; } // Can ignore non-preferred targets altogether (used when searching for a better target) if (ignoreNonPreferred && targ.GetTargetType() != preferredTargetType) { continue; } // The list of colliders is created by intersection with a range-radius sphere, but the center of this unit can still actually be out of range, leading to a target which cannot be shot at if (!IsValid(targ)) { continue; } targs.Add(targ); } // Sort by distance and target type targs.Sort(delegate(ITargetable a, ITargetable b) { return(ComparisonWeight(a) .CompareTo( ComparisonWeight(b))); }); return(targs); }
/* * private void UpdateTarget(bool manual) * { * // TODO: What if target is intentionally null? * if (parentUnit.isServer) * { * if (parentUnit.printInfo) * { * if (multManager == null) * Debug.LogError("lost multmanager 2"); * } * Debug.Log("RUN COMMAND "); * try * { * multManager.CmdSyncTarget(parentUnit.GetComponent<NetworkIdentity>(), turretId, target.GetGameObject().GetComponent<NetworkIdentity>(), manual); * } * catch(System.NullReferenceException e) * { * Debug.LogError("null exception, " + e.Message); * Debug.Log("START TRACE "); * Debug.Log("multManager " + multManager); * Debug.Log("parentUnit " + parentUnit); * Debug.Log("parentUnit.GetComponent<NetworkIdentity>() " + parentUnit.GetComponent<NetworkIdentity>()); * Debug.Log("turretId " + turretId); * Debug.Log("target.GetGameObject() " + target.GetGameObject()); * Debug.Log("target.GetGameObject().GetComponent<NetworkIdentity>() " + target.GetGameObject().GetComponent<NetworkIdentity>()); * Debug.Log("END TRACE "); * } * } * resetRotFrame = Time.frameCount; * * if (target.GetGameObject() == parentUnit.GetGameObject()) * { * Debug.Log("Reset target"); * manual = false; * target = null; * } * hasManualTarget = manual; * //Debug.Log("Turret aiming at " + (!IsNull(target) ? target.GetTargetType().ToString() : "null")); * } */ public void ClientUpdateTarget(NetworkIdentity targetIdentity, bool manual) { if (!parentUnit) { Debug.LogWarning("Can't find parent unit " + Time.frameCount); return; } if (parentUnit.isServer) // This is for clients only { return; } ITargetable potentialTarget = GetITargetableFromNetworkIdentity(targetIdentity); target = potentialTarget; Debug.Log("Client turret aiming at " + (!IsNull(target) ? target.GetTargetType().ToString() : "null")); UpdateTarget(manual); }
//public void HitLanded(Projectile attack, Entity hit) //{ // if (bGivingCommands && attack.Type == Power.Fire) // { // giveAttackCommand(hit.GetTargetType()); // } //} //public void HitLanded(Projectile attack, LevelElement hit) //{ // if (bGivingCommands && attack.Type == Power.Fire) // { // giveAttackCommand(hit.GetTargetType()); // } //} public void HitLanded(Projectile attack, ITargetable hit) { //if (bGivingCommands && attack.Type == Power.Fire) if (attack.Type == Power.Fire) { giveAttackCommand(hit.GetTargetType()); } }
void UpdateTargeting() { if (!suspended) { // Have target and it's valid if (!IsNull(target) && IsValid(target)) { // If we are targeting a non-preferred target type, we want to constantly search for a better target if (!hasManualTarget && target.GetTargetType() != preferredTargetType) { // Collect a list of all valid targets, ignoring non-preferred targets List <ITargetable> autoTargets = ScanForTargets(true); // Pick best one (if any were found) if (autoTargets.Count > 0) { // This new target will ALWAYS be different from the previous target because it was filtered differently target = autoTargets[0]; // Update resetRotFrame UpdateTarget(false); } } // Rotate towards the target CalcTargetLookRotation(); Rotate(); // Shoot if possible if (parentUnit.isServer) // Only server actually shoots, it's faked on clients { AttemptStartShooting(); } } else // We haven't assigned one yet, it died, or it's become invalid { // Collect a list of all valid targets List <ITargetable> autoTargets = ScanForTargets(ignoreNonPreferrential); // Pick best one target = autoTargets.Count > 0 ? autoTargets[0] : null; // Found a valid target if (!IsNull(target)) { Debug.Log("my parent team is " + parentUnit.GetTeam() + " targets team is " + target.GetTeam()); // Update resetRotFrame UpdateTarget(false); // Rotate towards the target CalcTargetLookRotation(); Rotate(); // Shoot if possible if (parentUnit.isServer) // Only server actually shoots, it's faked on clients { AttemptStartShooting(); } } else // Failed to find a valid target { // Rotate to standby position direction = transform.forward; lookRotation = CalcLookRotation(direction); Rotate(); } } // if have target and it's valid } // if not suspended else { direction = transform.forward; lookRotation = CalcLookRotation(direction); Rotate(); } }