/// <summary> /// Finds the target within the specified conditions that has the at least one matching tag /// </summary> /// <param name="rHitInfo">RaycastHit with the hit information</param> /// <param name="rMinDistance">Distance from the camera to start the ray</param> /// <param name="rMaxDistance">Max distance to shoot the ray</param> /// <param name="rRadius">Radius of the ray (use 0 for a simple ray)</param> /// <param name="rLayerMask">Layers to collide with</param> /// <param name="rTags">Comma delimited tags where one must exist</param> /// <param name="rIgnore">Object that we'll ignore collision with</param> /// <param name="rIgnoreList">Objects that we'll ignore collisions with</param> /// <returns>Returns true if a collision occurs or false if not</returns> public virtual bool FindTarget(out RaycastHit rHitInfo, float rMinDistance, float rMaxDistance, float rRadius, int rLayerMask = -1, string rTags = "", Transform rIgnore = null, List <Transform> rIgnoreList = null) { bool lRayHit = false; rHitInfo = RaycastExt.EmptyHitInfo; RaycastHit[] lHitInfos; int lHitCount = RaycastAll(out lHitInfos, rMinDistance, rMaxDistance, rRadius, rLayerMask, rIgnore, rIgnoreList); if (lHitCount > 0) { if (rTags == null || rTags.Length == 0) { lRayHit = true; rHitInfo = lHitInfos[0]; } else { for (int i = 0; i < lHitCount; i++) { IAttributeSource lAttributeSource = lHitInfos[i].collider.gameObject.GetComponent <IAttributeSource>(); if (lAttributeSource != null && lAttributeSource.AttributesExist(rTags, false)) { lRayHit = true; rHitInfo = lHitInfos[i]; break; } } } } return(lRayHit); }
/// <summary> /// Casts a ray using the reticle and then validates the position /// </summary> /// <returns></returns> protected virtual bool Raycast(bool rUseReticle = true) { bool lRayHit = false; Transform lOwner = mOwner.transform; if (rUseReticle && TargetingReticle.Instance != null) { RaycastHit[] lHitInfos; int lHitCount = TargetingReticle.Instance.RaycastAll(out lHitInfos, _MinDistance, _MaxDistance, _Radius, _CollisionLayers, lOwner); if (lHitCount > 0) { if (_Tags == null || _Tags.Length == 0) { lRayHit = true; mHitInfo = lHitInfos[0]; } else { for (int i = 0; i < lHitCount; i++) { IAttributeSource lAttributeSource = lHitInfos[i].collider.gameObject.GetComponent <IAttributeSource>(); if (lAttributeSource != null && lAttributeSource.AttributesExist(_Tags)) { lRayHit = true; mHitInfo = lHitInfos[i]; break; } } } } } else { Ray lRay = Camera.main.ScreenPointToRay(UnityEngine.Input.mousePosition); if (RaycastExt.SafeRaycast(lRay.origin, lRay.direction, out mHitInfo, _MaxDistance, _CollisionLayers, lOwner)) { if (_Tags == null || _Tags.Length == 0) { lRayHit = true; } else { IAttributeSource lAttributeSource = mHitInfo.collider.gameObject.GetComponent <IAttributeSource>(); if (lAttributeSource != null && lAttributeSource.AttributesExist(_Tags)) { lRayHit = true; } } } } return(lRayHit); }
/// <summary> /// Find a position by targeting down /// </summary> /// <returns></returns> public virtual bool FindPosition() { Transform lOwner = _Spell.Owner.transform; float lStep = (_MinDistance - _MinDistance) / 5f; // Start at the center and spiral out for (float lDistance = _MaxDistance; lDistance >= _MinDistance; lDistance = lDistance - lStep) { //GraphicsManager.DrawLine(mMotionController.CameraTransform.position, mMotionController.CameraTransform.TransformPoint(lPosition), (lCount == 0 ? Color.red : lColor), null, 5f); RaycastHit lHitInfo; Vector3 lStart = lOwner.position + _StartOffset + (lOwner.forward * lDistance); Vector3 lDirection = -lOwner.up; if (RaycastExt.SafeRaycast(lStart, lDirection, out lHitInfo, _MaxDistance, _CollisionLayers, lOwner)) { // Grab the gameobject this collider belongs to GameObject lGameObject = lHitInfo.collider.gameObject; // Don't count the ignore if (lGameObject.transform == lOwner) { continue; } if (_Tags != null && _Tags.Length > 0) { IAttributeSource lAttributeSource = lGameObject.GetComponent <IAttributeSource>(); if (lAttributeSource == null || !lAttributeSource.AttributesExist(_Tags)) { continue; } } // Determine if we're done choosing a point if (_Spell.Data.Positions == null) { _Spell.Data.Positions = new List <Vector3>(); } _Spell.Data.Positions.Clear(); _Spell.Data.Positions.Add(lHitInfo.point); return(true); } } // Return the target hit return(false); }
/// <summary> /// Attempt to find a target that we can focus on. This approach uses a spiralling raycast /// </summary> /// <returns></returns> public virtual Transform FindTarget() { float lMaxRadius = 8f; float lMaxDistance = 20f; float lRevolutions = 2f; float lDegreesPerStep = 27f; float lSteps = lRevolutions * (360f / lDegreesPerStep); float lRadiusPerStep = lMaxRadius / lSteps; float lAngle = 0f; float lRadius = 0f; Vector3 lPosition = Vector3.zero; //float lColorPerStep = 1f / lSteps; //Color lColor = Color.white; Transform lOwner = _Spell.Owner.transform; // We want our final revolution to be max radius. So, increase the steps lSteps = lSteps + (360f / lDegreesPerStep) - 1f; // Start at the center and spiral out int lCount = 0; for (lCount = 0; lCount < lSteps; lCount++) { lPosition.x = lRadius * Mathf.Cos(lAngle * Mathf.Deg2Rad); lPosition.y = lRadius * Mathf.Sin(lAngle * Mathf.Deg2Rad); lPosition.z = lMaxDistance; //GraphicsManager.DrawLine(mMotionController.CameraTransform.position, mMotionController.CameraTransform.TransformPoint(lPosition), (lCount == 0 ? Color.red : lColor), null, 5f); RaycastHit lHitInfo; Vector3 lStart = lOwner.position + _StartOffset; Vector3 lDirection = lOwner.forward; if (RaycastExt.SafeRaycast(lStart, lDirection, out lHitInfo, _MaxDistance, _CollisionLayers, lOwner)) { // Grab the gameobject this collider belongs to GameObject lGameObject = lHitInfo.collider.gameObject; // Don't count the ignore if (lGameObject.transform == lOwner) { continue; } if (lHitInfo.collider is TerrainCollider) { continue; } if (_Tags != null && _Tags.Length > 0) { IAttributeSource lAttributeSource = lGameObject.GetComponent <IAttributeSource>(); if (lAttributeSource == null || !lAttributeSource.AttributesExist(_Tags)) { continue; } } if (RequiresRigidbody && lGameObject.GetComponent <Rigidbody>() == null) { continue; } if (RequiresActorCore && lGameObject.GetComponent <ActorCore>() == null) { continue; } if (RequiresCombatant && lGameObject.GetComponent <ICombatant>() == null) { continue; } // Store the target if (_Spell.Data.Targets == null) { _Spell.Data.Targets = new List <GameObject>(); } _Spell.Data.Targets.Clear(); _Spell.Data.Targets.Add(lGameObject); return(lGameObject.transform); } // Increment the spiral lAngle += lDegreesPerStep; lRadius = Mathf.Min(lRadius + lRadiusPerStep, lMaxRadius); //lColor.r = lColor.r - lColorPerStep; //lColor.g = lColor.g - lColorPerStep; } // Return the target hit return(null); }
/// <summary> /// Called when the action is first activated /// <param name="rPreviousSpellActionState">State of the action prior to this one activating</param> public override void Activate(int rPreviousSpellActionState = -1, object rData = null) { base.Activate(rPreviousSpellActionState, rData); mActivations = 0; mBatchDelay = 0f; mLastBatchTime = 0f; if (_Spell != null && _Spell.Data != null) { SpellData lSpellData = _Spell.Data; Transform lCenter = null; Vector3 lCenterPosition = PositionOffset; GetBestPosition(SearchRootIndex, rData, _Spell.Data, PositionOffset, out lCenter, out lCenterPosition); // Ignore any existing targets for future tests if (IgnorePreviousTargets && lSpellData.Targets != null && lSpellData.Targets.Count > 0) { if (lSpellData.PreviousTargets == null) { lSpellData.PreviousTargets = new List <GameObject>(); } for (int i = 0; i < lSpellData.Targets.Count; i++) { if (!lSpellData.PreviousTargets.Contains(lSpellData.Targets[i])) { lSpellData.PreviousTargets.Add(lSpellData.Targets[i]); } } } // Remove any existing targets if (Replace) { if (lSpellData.Targets != null) { lSpellData.Targets.Clear(); lSpellData.Targets = null; } } // Find new targets if (lCenterPosition != Vector3Ext.Null) { Collider[] lColliders = null; List <GameObject> lTargets = null; int lCount = RaycastExt.SafeOverlapSphere(lCenterPosition, Radius, out lColliders, CollisionLayers, _Spell.Owner.transform, null, true); if (lColliders != null && lCount > 0) { if (lTargets == null) { lTargets = new List <GameObject>(); } for (int i = 0; i < lCount; i++) { GameObject lGameObject = lColliders[i].gameObject; if (lGameObject == _Spell.Owner) { continue; } if (RequireRigidbody && lGameObject.GetComponent <Rigidbody>() == null) { continue; } if (RequireActorCore && lGameObject.GetComponent <ActorCore>() == null) { continue; } if (RequireCombatant && lGameObject.GetComponent <ICombatant>() == null) { continue; } if (lSpellData.PreviousTargets != null && lSpellData.PreviousTargets.Contains(lGameObject)) { continue; } if (_Tags != null && _Tags.Length > 0) { IAttributeSource lAttributeSource = lGameObject.GetComponent <IAttributeSource>(); if (lAttributeSource == null || !lAttributeSource.AttributesExist(_Tags)) { continue; } } if (!lTargets.Contains(lGameObject)) { lTargets.Add(lGameObject); } } // Sort the list based on distance if (lTargets.Count > 1) { lTargets = lTargets.OrderBy(x => Vector3.Distance(lCenterPosition, x.transform.position)).ToList <GameObject>(); } } // Choose what we want if (lTargets != null && lTargets.Count > 0) { if (lSpellData.Targets == null) { lSpellData.Targets = new List <GameObject>(); } // Any or nearest if (SearchTypeIndex == 0 || SearchTypeIndex == 1) { for (int i = 0; i < lTargets.Count; i++) { if (!lSpellData.Targets.Contains(lTargets[i])) { lSpellData.Targets.Add(lTargets[i]); } if (MaxTargets > 0 && lSpellData.Targets.Count >= MaxTargets) { break; } } } // Furthest else if (SearchTypeIndex == 2) { for (int i = lTargets.Count - 1; i >= 0; i--) { if (!lSpellData.Targets.Contains(lTargets[i])) { lSpellData.Targets.Insert(0, lTargets[i]); } if (MaxTargets > 0 && lSpellData.Targets.Count >= MaxTargets) { break; } } } } } if (lSpellData.Targets != null && lSpellData.Targets.Count > 0) { if (!UseBatches) { OnSuccess(); return; } } } // Immediately deactivate if (!UseBatches) { OnFailure(); } }
/// <summary> /// Casts a ray using the reticle and then validates the position /// </summary> /// <returns></returns> protected virtual bool Raycast(bool rUseReticle = true) { bool lRayHit = false; Transform lOwner = mOwner.transform; if (rUseReticle && TargetingReticle.Instance != null) { RaycastHit[] lHitInfos; int lHitCount = TargetingReticle.Instance.RaycastAll(out lHitInfos, _MinDistance, _MaxDistance, _Radius, _CollisionLayers, lOwner); if (lHitCount > 0) { if (_Tags == null || _Tags.Length == 0) { lRayHit = true; mHitInfo = lHitInfos[0]; } else { for (int i = 0; i < lHitCount; i++) { IAttributeSource lAttributeSource = lHitInfos[i].collider.gameObject.GetComponent <IAttributeSource>(); if (lAttributeSource != null && lAttributeSource.AttributesExist(_Tags)) { lRayHit = true; mHitInfo = lHitInfos[i]; break; } } } } } else { Ray lRay = Camera.main.ScreenPointToRay(UnityEngine.Input.mousePosition); lRayHit = RaycastExt.SafeRaycast(lRay.origin, lRay.direction, out mHitInfo, _MaxDistance, _CollisionLayers, lOwner); } // Since we don't seem to have a hit, test if we can use the max distance and shoot a ray down if (!lRayHit) { Transform lOrigin = TargetingReticle.Instance.RaycastRoot; if (lOrigin == null && Camera.main != null) { lOrigin = Camera.main.transform; } if (lOrigin == null) { lOrigin = transform; } Vector3 lStart = lOrigin.position + (lOrigin.forward * _MaxDistance); RaycastHit lHitInfo; if (RaycastExt.SafeRaycast(lStart, -lOwner.up, out lHitInfo, 10f, _CollisionLayers, lOwner, null, true)) { if (_Tags == null || _Tags.Length == 0) { lRayHit = true; mHitInfo = lHitInfo; } else { IAttributeSource lAttributeSource = lHitInfo.collider.gameObject.GetComponent <IAttributeSource>(); if (lAttributeSource != null && lAttributeSource.AttributesExist(_Tags)) { lRayHit = true; mHitInfo = lHitInfo; } } } } return(lRayHit); }
/// <summary> /// Called when the action is first activated /// <param name="rPreviousSpellActionState">State of the action prior to this one activating</param> public override void Activate(int rPreviousSpellActionState = -1, object rData = null) { base.Activate(rPreviousSpellActionState, rData); if (_Spell != null && _Spell.Data != null) { SpellData lSpellData = _Spell.Data; GameObject lGameObject = _Spell.Owner; // Ignore any existing targets for future tests if (ShiftToPreviousTargets && lSpellData.Targets != null && lSpellData.Targets.Count > 0) { if (lSpellData.PreviousTargets == null) { lSpellData.PreviousTargets = new List <GameObject>(); } for (int i = 0; i < lSpellData.Targets.Count; i++) { if (!lSpellData.PreviousTargets.Contains(lSpellData.Targets[i])) { lSpellData.PreviousTargets.Add(lSpellData.Targets[i]); } } } // Remove any existing targets if (Replace) { if (lSpellData.Targets != null) { lSpellData.Targets.Clear(); lSpellData.Targets = null; } } // Find new targets bool lAdd = true; if (lAdd && RequireRigidbody && lGameObject.GetComponent <Rigidbody>() == null) { lAdd = false; } if (lAdd && RequireActorCore && lGameObject.GetComponent <ActorCore>() == null) { lAdd = false; } if (lAdd && RequireCombatant && lGameObject.GetComponent <ICombatant>() == null) { lAdd = false; } if (lAdd && lSpellData.PreviousTargets != null && lSpellData.PreviousTargets.Contains(lGameObject)) { lAdd = false; } if (lAdd && _Tags != null && _Tags.Length > 0) { IAttributeSource lAttributeSource = lGameObject.GetComponent <IAttributeSource>(); if (lAttributeSource == null || !lAttributeSource.AttributesExist(_Tags)) { lAdd = false; } } if (lAdd & !lSpellData.Targets.Contains(lGameObject)) { lSpellData.Targets.Add(lGameObject); } if (lAdd) { OnSuccess(); return; } } // Immediately deactivate OnFailure(); }