/// <summary> /// Handles all firing events including target aquisition and firing. /// Events are: /// OnStart() : /// Runs once when the firing system first becomes active /// OnUpdate() : /// Runs each frame while the firing system is active /// OnTargetUpdate() : /// Runs each frame while tracking a target (there is at least one target.) /// OnIdleUpdate() : /// Runs each frame while the firing system is idle (no targets) /// OnFire() : /// Runs when it is time to fire. /// /// Counter Behavior Notes: /// * If there are no targets. the counter will keep running up. /// This means the next target to enter will be fired upon /// immediatly. /// /// * The counter is always active so if the last target exits, then a /// new target enters right after that, there may still be a wait. /// </summary> private IEnumerator FiringSystem() { // While (true) because of the timer, we want this to run all the time, not // start and stop based on targets in range if (this.initIntervalCountdownAtZero) { this.fireIntervalCounter = 0; } else { this.fireIntervalCounter = this.interval; } this.targets.Clear(); this.OnStart(); // EVENT TRIGGER while (true) { // if there is no target, counter++, handle idle behavior, and // try next frame. // Will init this.targets for child classes as well. this.targets = this.targetTracker.targets; if (this.targets.Count != 0) { // Let the delegate filter a copy of the list just for the OnFire // Test. We still want this.targets to remain as is. // Do this in here to still trigger OnTargetUpdate var targetsCopy = new TargetList(); targetsCopy.AddRange(this.targets); if (this.onPreFireDelegates != null) { this.onPreFireDelegates(targetsCopy); } // if all is right, fire if (targetsCopy.Count != 0 && // Incase of pre-fire delegate changes this.fireIntervalCounter <= 0 && this.isLockedOnTarget) // Always true if WaitForAlignment is OFF { this.OnFire(); this.fireIntervalCounter = this.interval; // Reset } else if (this.debugLevel > DEBUG_LEVELS.Off) { // Just for debug. Show a gizmo line to each target being tracked // OnFire() has another color, so keep this here where this // won't overlay the OnFired line. foreach (Target target in targets) { Debug.DrawLine ( this.emitter.position, target.transform.position, Color.gray ); } } // Update event while tracking a target this.OnTargetUpdate(targets); // EVENT TRIGGER } else { // Update event while NOT tracking a target this.OnIdleUpdate(); // EVENT TRIGGER } this.fireIntervalCounter -= Time.deltaTime; // Update event no matter what this.OnUpdate(); // EVENT TRIGGER // Stager calls to get Target (the whole system actually) yield return(null); } }
/// <summary> /// Destroys the projectile on impact and finds objects in range to /// affect if they share the same tag as target. /// </summary> public void DetonateProjectile() { // Prevent being run more than once in a frame where it has already // been destroyed. if (!this.gameObject.activeInHierarchy) { return; } // Build a new list of targets depending on the options used var targetList = new TargetList(); if (this.areaHit) { // This is turned back off OnDisable() (base class) this.perimeter.enabled = true; targetList.AddRange(this.targets); // Add all targets in range } else { if (this.target != Target.Null) { targetList.Add(this.target); // Add projectile target } } if (this.debugLevel > DEBUG_LEVELS.Off) { string msg = string.Format("Detonating with targets: {0}", targetList); Debug.Log(string.Format("Projectile ({0}): {1}", this.name, msg)); } // Create a new list of targets which have this target tracker reference. // This is for output so targets which are handled at all by this Projectile // are stamped with a reference. var targetCopies = new TargetList(); Target target; foreach (Target inTarget in targetList) { if (inTarget == Target.Null) { continue; } // Can't edit a struct in a foreach loop, so need to copy and store target = new Target(inTarget); target.projectile = this; // Add reference. null before t targetCopies.Add(target); switch (this.notifyTargets) { case NOTIFY_TARGET_OPTIONS.Direct: target.targetable.OnHit(this.effectsOnTarget, target, this.collider); break; } // Just for debug. Show a gizmo line when firing if (this.debugLevel > DEBUG_LEVELS.Off) { Debug.DrawLine ( this.xform.position, target.transform.position, Color.red ); } } switch (this.notifyTargets) { case NOTIFY_TARGET_OPTIONS.Direct: this.SpawnDetonatorPrefab(false); break; case NOTIFY_TARGET_OPTIONS.PassToDetonator: this.SpawnDetonatorPrefab(true); break; } // Trigger delegates if (this.OnDetonationDelegates != null) { this.OnDetonationDelegates(targetCopies); } // Clean-up in case this instance is used in a pooling system like PoolManager this.target = Target.Null; InstanceManager.Despawn(this.transform); }