private void ApplyKnockback(object receiver, Damage.DamageEventArgs e) { if (receiver.GetType() == typeof(DamageableBase) || receiver.GetType().IsSubclassOf(typeof(DamageableBase))) { var damagable = (DamageableBase)receiver; var go = damagable.gameObject; var rb = go.GetComponent <Rigidbody2D>(); if (rb) { Vector3 forceDir = ((Vector3)rb.position - e.HitPoint).normalized; forceDir = Vector3.Project(forceDir, Vector2.right).normalized; forceDir += Vector3.up * _upwardModifier; forceDir = forceDir.normalized; rb.AddForce(forceDir * _knockbackForce, ForceMode2D.Impulse); rb.AddForce(_flatForceVector, ForceMode2D.Impulse); if (_debug) { Debug.Log("Applying Knockback!"); var rbPos = (Vector3)rb.position; // Pink: The initial difference line. Debug.DrawLine(e.HitPoint, rbPos, new Color(255f, 0f, 97f), 0.5f); // Red: The force direction. Debug.DrawLine(rbPos, rbPos + forceDir * 5f, Color.red, 0.5f); // Blue: The flat force vector. Debug.DrawLine(rbPos, rbPos + _flatForceVector, Color.blue, 0.5f); } } } }
/// <summary> /// Checks for an IDamagable on the target GameObject, then attempts to call its ApplyDamage method. /// If an IDamagable isn't found, returns false. /// </summary> /// <param name="damageTarget"> The Target to look for an IDamagable on.</param> /// <param name="args"> Damage Event Arguments.</param> /// <returns></returns> public virtual bool TryDealDamage(GameObject damageTarget, Damage.DamageEventArgs args) { if (!CanDealDamage) { return(false); } if (args.DamageValue <= 0) { return(false); } IDamageable damageable = damageTarget.GetComponent <IDamageable>(); if (damageable != null) { if (this.faction == damageable.GetFaction() && !Damage.FriendlyFireEnabled) { return(false); } // By using a ref parameter, we can see the results of the damage delt after it has been changed by resistances and multipliers. damageable.ApplyDamage(this, ref args); if (args.DamageValue > 0) { OnDealDamage(damageable, args); return(true); } } // No IDamagable Found - Return false. return(false); }
public virtual bool TryDealDamage(GameObject damageTarget, float damage, Vector3?hitPoint = null) { Vector3 point = (hitPoint != null) ? (Vector3)hitPoint : transform.position; // Default on transform position if no hitPoint is set. Damage.DamageEventArgs e = new Damage.DamageEventArgs(damage, point, damageType, faction); return(TryDealDamage(damageTarget, e)); }
protected virtual IEnumerator CoEffectTimer() { if (TickInterval > Duration) { TickInterval = Duration; } //Note: There is no initial tick at t=0. int ticks = 1; Timer = 0f; while (Timer < Duration) { Timer += Time.deltaTime; if (Timer > TickInterval * ticks) { Damage.DamageEventArgs args = new Damage.DamageEventArgs(DamageValue, Vector3.zero, damageType, faction, Damage.DamageEventType.DOT); TryDealDamage(AttachedDamageable.gameObject, args); ticks++; } OnUpdateValue(Timer); yield return(null); } Timer = Duration; if (DestroySelfWhenFinished) { Destroy(gameObject); } }
private void DoOnTakeDamage(object sender, Damage.DamageEventArgs e) { if (_playMaker) { _playMaker.SendEvent(_onDamageEventName); } }
/// <summary> /// Checks for an IDamagable on the target GameObject, then attempts to call its ApplyDamage method. /// If an IDamagable isn't found, returns false. /// </summary> /// <param name="damageTarget"> The Target to look for an IDamagable on.</param> /// <param name="e"> Damage Event Arguments.</param> /// <returns></returns> public virtual bool TryDealDamage(GameObject damageTarget, Damage.DamageEventArgs e) { if (!CanDealDamage) { return(false); } if (e.DamageValue <= 0) { return(false); } IDamagable damagable = damageTarget.GetComponent <IDamagable>(); if (damagable != null) { if (this.faction == damagable.GetFaction()) { return(false); } damagable.ApplyDamage(this, e); OnDealDamage(this, e); return(true); } // No IDamagable Found - Return false. return(false); }
protected override void DoOnTakeDamage(object sender, Damage.DamageEventArgs damageEventArgs) { if (_animator) { if (_stateName.Length > 0) { _animator.Play(_stateName); } } }
protected virtual void InvokeMutateDamage(object sender, ref Damage.DamageEventArgs args) { // Make a temporary copy of the event to avoid possibility of // a race condition if the last subscriber unsubscribes // immediately after the null check and before the event is raised. Damage.DamageEventMutator handler = MutateDamage; if (handler != null) { handler(this, ref args); } }
protected override void HandleDamage(object sender, Damage.DamageEventArgs e) { // Add an invulnerability delay for non-bullets. if (e.DamageType != Damage.DamageType.Bullet) { if (_isInvulnerable) { return; } StartCoroutine(CoInvulnerabilityDelay(_invulnTime)); } base.HandleDamage(sender, e); }
protected override void DoOnTakeDamage(object sender, Damage.DamageEventArgs e) { if (_spriteRenderer) { if (_effectCoroutine != null) { StopCoroutine(_effectCoroutine); _effectCoroutine = null; _spriteRenderer.color = _originalColor; } _effectCoroutine = StartCoroutine(CoFlashColor(_takeDamageColor, _originalColor, _takeDamageFlashDuration)); } }
public override void MutateDamageEvent(object sender, ref Damage.DamageEventArgs args) { foreach (var tm in TypeValues) { if (args.DamageType == tm.DamageType) { args.DamageValue += tm.Value; if (args.DamageValue < 0) { args.DamageValue = 0f; } } } }
protected override void HandleDamage(object sender, ref Damage.DamageEventArgs args) { // Invulnerability Check. if (_useInvulnerability) { if (_isInvulnerable) { return; } StartCoroutine(CoInvulnerabilityDelay(_invulnTime)); } base.HandleDamage(sender, ref args); }
protected override void DoOnTakeDamage(object sender, Damage.DamageEventArgs e) { if (_spriteRenderer) { if (_flashCoroutine != null) { StopCoroutine(_flashCoroutine); //Technically unnecessary, but it's a good, safe practice. _flashCoroutine = null; _spriteRenderer.color = _originalColor; } _flashCoroutine = StartCoroutine(CoFlashColor(_color, _originalColor, _duration)); } }
//================================================================================ #region Damage Handling public override void ApplyDamage(object sender, ref Damage.DamageEventArgs args) { if (IsDead) { args.DamageValue = 0f; return; } // Cannot receive damage from same faction. if (args.SourceFaction == Faction && args.SourceFaction != Damage.Faction.Generic) { return; } HandleDamage(sender, ref args); }
protected virtual void HandleDamage(object sender, Damage.DamageEventArgs e) { if (IsDead) { return; } float damage = CalculateDamage(e); currentHealth -= damage; OnUpdateHealth(currentHealth); if (currentHealth <= 0f) { currentHealth = 0f; HandleDeath(); } }
//================================================================================ #region Damage Handling public override void ApplyDamage(object sender, Damage.DamageEventArgs e) { if (IsDead) { return; } // Cannot receive damage from same faction. if (e.SourceFaction == Faction && e.SourceFaction != Damage.Faction.Generic) { //Debug.Log("SAME FACTION DAMAGE"); return; } // We still call TakeDamage if the damage would kill them, and leave it up to the delgates to check for death. HandleDamage(sender, e); //if(!IsDead) base.ApplyDamage(sender, e); // Simply Calls OnTakeDamage(sender, e); }
protected override void DoOnTakeDamage(object sender, Damage.DamageEventArgs damageEventArgs) { if (_filterByDamageType) { if (damageEventArgs.DamageType != _typeFilter) { return; } } if (_damageEffectPrefab) { var go = GameObject.Instantiate(_damageEffectPrefab); go.transform.position = damageEventArgs.HitPoint; go.transform.LookAt(damageEventArgs.HitPoint + damageEventArgs.HitNormal); Destroy(go, _destroyTime); } }
public override void MutateDamageEvent(object sender, ref Damage.DamageEventArgs args) { if (ShieldHealth.IsDead) { return; } var healthBefore = ShieldHealth.CurrentHealth; ShieldHealth.ApplyDamage(sender, ref args); if (ShieldHealth.IsDead) { var overflow = args.DamageValue - healthBefore; args.DamageValue = overflow; OnShieldDestroyed(); this.enabled = false; } else { args.DamageValue = 0f; } }
protected virtual void HandleDamage(object sender, ref Damage.DamageEventArgs args) { if (IsDead) { return; } InvokeMutateDamage(sender, ref args); float damage = CalculateDamage(args); args.DamageValue = damage; currentHealth -= damage; // We still call TakeDamage if the damage would kill them, and leave it up to the listeners to check for death. InvokeOnTakeDamage(sender, args); if (currentHealth <= 0f) { currentHealth = 0f; HandleDeath(); } OnUpdateHealth(currentHealth); }
protected abstract void DoOnTakeDamage(object sender, Damage.DamageEventArgs damageEventArgs);
public virtual void ApplyDamage(object sender, float damage, Vector3 hitPoint) { var args = new Damage.DamageEventArgs(damage, hitPoint); ApplyDamage(sender, ref args); }
protected override void DoOnTakeDamage(object sender, Damage.DamageEventArgs e) { OnTakeDamageEvent.Invoke(); }
public abstract void MutateDamageEvent(object sender, ref Damage.DamageEventArgs args);
protected override void DoOnTakeDamage(object sender, Damage.DamageEventArgs damageEventArgs) { PlayAnimation(_takeDamageState); }
public virtual void ApplyDamage(object sender, Damage.DamageEventArgs e) { OnTakeDamage(sender, e); }
protected override void DoOnTakeDamage(object sender, Damage.DamageEventArgs damageEventArgs) { _audioSource.PlayOneShot(_clipToPlay); }
public override void ApplyDamage(object sender, Damage.DamageEventArgs e) { base.ApplyDamage(sender, e); //if(_debug) Debug.Log(this.gameObject.name + " RECEIVED DAMAGE: " + e.DamageValue); }
public virtual void ApplyDamage(float damage) { var args = new Damage.DamageEventArgs(damage, this.transform.position); ApplyDamage(this, ref args); }
/// <summary> /// Calculates the effective damage on the HealthManager, AFTER mutators. /// Override this for changing how damage is handled specifically on this class. /// Alternatively, attach a mutator. /// </summary> /// <param name="args"></param> /// <returns></returns> protected virtual float CalculateDamage(Damage.DamageEventArgs args) { // For the simplest case, just pass the raw DamageValue. return(args.DamageValue); }
protected override void DoOnDealDamage(object sender, Damage.DamageEventArgs args) { ApplyKnockback(sender, args); }