private void AttackInteractable(IInteractable interactable) { // if the attack was blocked, it can't hit anymore // TODO: we probably should do this on a per-source basis // and probably should track per-source if it hit / was blocked // so we never re-hit and re-block or whatever if (_brawler.CurrentAction.WasBlocked) { return; } IDamagable damagable = interactable.gameObject.GetComponent <IDamagable>(); if (null == damagable) { return; } Actors.DamageData damageData = new Actors.DamageData { Source = Owner, SourceBrawlerActionHandler = Owner.Behavior as IBrawlerBehaviorActions, AttackData = _attackData, Bounds = _collider.bounds, Direction = _direction, }; if (damagable.Damage(damageData)) { AttackHitEvent?.Invoke(this, new AttackVolumeEventArgs { HitTarget = damagable, }); } }
public bool Damage(Game.Actors.DamageData damageData) { if (ActionHandler.IsDead) { return(false); } Actors.DamageData dd = (Actors.DamageData)damageData; // did we block the damage? if (!dd.AttackData.Unblockable && Brawler.CurrentAction.IsBlocking && _blockVolume.Intersects(dd.Bounds)) { if (BrawlerAction.ActionType.Parry == Brawler.CurrentAction.Type) { Debug.Log($"TODO: Brawler {Owner.Id} can parry"); } if (GameManager.Instance.DebugBrawlers) { DisplayDebugText($"Blocked damage for {dd.AttackData.DamageAmount} (took {dd.AttackData.BlockDamageAmount})", Color.blue); } if (null != dd.SourceBrawlerActionHandler) { BrawlerAction currentAction = Brawler.CurrentAction; currentAction.WasBlocked = true; Brawler.CurrentAction = currentAction; } if (DoDamage(dd, true)) { return(true); } //_blockAudioEffectTriggerComponent.AudioClip = dd.AttackData.BlockAudioCip; _blockEffectTrigger.Trigger(); ActionHandler.ClearActionBuffer(); ActionHandler.OnHit(true); return(false); } if (GameManager.Instance.DebugBrawlers) { DisplayDebugText($"Damage: {dd.AttackData.DamageAmount}", Color.red); } CancelActions(false); DoDamage(dd, false); return(true); }
// returns true if the hit kills the brawler private bool DoDamage(Actors.DamageData damageData, bool blocked) { if (!ActionHandler.IsImmune) { Brawler.Health -= damageData.AttackData.DamageAmount; // TODO: we shouldn't actually die until we're done being combo'd to death if (ActionHandler.IsDead) { Brawler.Health = 0; _deathEffectTrigger.Trigger(() => ActionHandler.OnDeathComplete()); ActionHandler.OnHit(false); ActionHandler.OnDead(); return(true); } } if (blocked) { return(false); } // push the source if (null != damageData.SourceBrawlerActionHandler) { damageData.SourceBrawlerActionHandler.Brawler.BrawlerBehavior._velocityModifier = damageData.Direction * damageData.AttackData.MoveFoward; } // push the recipient _velocityModifier = damageData.Direction * damageData.AttackData.PushBackAmount; // vertical push if (damageData.AttackData.KnockUpForce > 0.0f) { Owner.Behavior.Movement.PrepareJump(); } Owner.Behavior.Movement.Velocity += damageData.AttackData.KnockDownForce * Vector3.down + damageData.AttackData.KnockUpForce * Vector3.up; _hitAudioEffectTriggerComponent.AudioClip = damageData.AttackData.ImpactAudioCip; if (damageData.AttackData.KnockDown) { Brawler.CurrentAction = new BrawlerAction(BrawlerAction.ActionType.KnockedDown); // TODO: make the time configurable _knockDownEffectTrigger.Trigger(); _knockDownTimer.Start(1.0f); } else { Brawler.CurrentAction = new BrawlerAction(BrawlerAction.ActionType.Stunned); _hitEffectTrigger.Trigger(() => { Idle(); }); } ActionHandler.ClearActionBuffer(); ActionHandler.OnHit(false); return(false); }