using System; using BumpCombat.Player; using UnityEngine; namespace BumpCombat.Combat { public readonly struct CombatHitResult { public CombatHitResult( GameObject attacker, GameObject target, bool isDash, HitSide side, float damage, Vector2 knockbackDirection, float knockbackForce, Vector2 hitPosition, bool isOffsetHit = false, bool isStrongDash = false, DamageTag damageTag = DamageTag.Collision, string sourceId = null, bool usesPositionBonus = true, bool showsHitFeedback = true, bool launchSucceeded = false, bool isArtifactHit = false, ActiveArtifactEffect artifactEffect = ActiveArtifactEffect.Dash, bool isChargedArtifact = false) { Attacker = attacker; Target = target; IsDash = isDash; Side = side; Damage = damage; KnockbackDirection = knockbackDirection; KnockbackForce = knockbackForce; HitPosition = hitPosition; IsOffsetHit = isOffsetHit; IsStrongDash = isStrongDash; DamageTag = damageTag; SourceId = sourceId; UsesPositionBonus = usesPositionBonus; ShowsHitFeedback = showsHitFeedback; LaunchSucceeded = launchSucceeded; IsArtifactHit = isArtifactHit; ArtifactEffect = artifactEffect; IsChargedArtifact = isChargedArtifact; } public static CombatHitResult ForArtifactContact( GameObject attacker, GameObject target, ActiveArtifactEffect artifactEffect, bool isChargedArtifact, HitSide side, Vector2 knockbackDirection, Vector2 hitPosition, DamageTag damageTag, string sourceId, bool isOffsetHit = false) { bool isDash = artifactEffect == ActiveArtifactEffect.Dash; return new CombatHitResult( attacker, target, isDash, side, 0f, knockbackDirection, 0f, hitPosition, isOffsetHit: isOffsetHit, isStrongDash: isDash && isChargedArtifact, damageTag: damageTag, sourceId: sourceId, usesPositionBonus: false, showsHitFeedback: false, launchSucceeded: false, isArtifactHit: true, artifactEffect: artifactEffect, isChargedArtifact: isChargedArtifact); } public GameObject Attacker { get; } public GameObject Target { get; } public bool IsDash { get; } public bool IsStrongDash { get; } public DamageTag DamageTag { get; } public string SourceId { get; } public bool UsesPositionBonus { get; } public bool ShowsHitFeedback { get; } /// True only when a strong dash actually created the launch state. public bool LaunchSucceeded { get; } public bool IsArtifactHit { get; } public ActiveArtifactEffect ArtifactEffect { get; } public bool IsChargedArtifact { get; } public bool IsOrdinaryBump => !IsDash && string.IsNullOrEmpty(SourceId); public HitSide Side { get; } public float Damage { get; } public bool HasBackBonus => UsesPositionBonus && Side == HitSide.Back; public bool IsOffsetHit { get; } public bool HasPositionBonus => UsesPositionBonus && (Side == HitSide.Side || IsOffsetHit); public Vector2 KnockbackDirection { get; } public float KnockbackForce { get; } public Vector2 HitPosition { get; } } /// A confirmed artifact effect on one enemy during one activation. public readonly struct ArtifactEffectiveHitResult { public ArtifactEffectiveHitResult( GameObject target, int castIdentity, ActiveArtifactEffect artifactEffect, bool isCharged, bool matchedShieldRequirement) { Target = target; CastIdentity = castIdentity; ArtifactEffect = artifactEffect; IsCharged = isCharged; MatchedShieldRequirement = matchedShieldRequirement; } public GameObject Target { get; } public int CastIdentity { get; } public ActiveArtifactEffect ArtifactEffect { get; } public bool IsCharged { get; } public bool MatchedShieldRequirement { get; } } public static class CombatEvents { public static event Action OnValidHit; public static event Action OnArtifactEffectiveHit; public static event Action OnRearAttackCancelled; public static event Action OnStunApplied; public static event Action OnAttackCancelled; public static event Action OnEnemyStagger; public static event Action OnEnemyStaggerCleared; public static event Action OnLaunchResisted; public static event Action OnKnockbackCompleted; public static event Action OnEnemyRetired; public static event Action OnEnemyDied; public static event Action OnThunderShield; public static void RaiseValidHit(CombatHitResult result) { OnValidHit?.Invoke(result); } public static void RaiseArtifactEffectiveHit( GameObject target, int castIdentity, ActiveArtifactEffect artifactEffect, bool isCharged, bool matchedShieldRequirement = false) { OnArtifactEffectiveHit?.Invoke(new ArtifactEffectiveHitResult( target, castIdentity, artifactEffect, isCharged, matchedShieldRequirement)); } public static void RaiseRearAttackCancelled(GameObject target) { OnRearAttackCancelled?.Invoke(target); } public static void RaiseStunApplied(GameObject target, float duration) { OnStunApplied?.Invoke(target, duration); } public static void RaiseAttackCancelled(GameObject target, bool fromStun) { OnAttackCancelled?.Invoke(target, fromStun); } public static void RaiseEnemyStagger( GameObject target, int current, int maximum, bool broke) { OnEnemyStagger?.Invoke(target, current, maximum, broke); } public static void RaiseEnemyStaggerCleared(GameObject target) { OnEnemyStaggerCleared?.Invoke(target); } public static void RaiseLaunchResisted(GameObject target) { OnLaunchResisted?.Invoke(target); } public static void RaiseKnockbackCompleted( GameObject target, Vector2 start, Vector2 end) { OnKnockbackCompleted?.Invoke(target, start, end); } public static void RaiseEnemyRetired(GameObject target) { OnEnemyRetired?.Invoke(target); } public static void RaiseEnemyDied(GameObject target) { OnEnemyDied?.Invoke(target); } public static void RaiseThunderShield(Vector2 center, float duration) { OnThunderShield?.Invoke(center, duration); } } }