using OTGIntegrated.Combat; using OTGIntegrated.Stats; using UnityEngine; namespace OTGIntegrated.Weapons { public sealed class WeaponController : MonoBehaviour { public Transform attackOrigin; public LayerMask hitMask = ~0; [SerializeField] private float meleeRadius = 0.7f; private readonly Collider[] hits = new Collider[16]; public bool Attack(WeaponData weapon, PlayerStats stats) { if (weapon == null || stats == null) { return false; } Transform origin = attackOrigin != null ? attackOrigin : transform; Vector3 start = origin.position + Vector3.up * 0.8f; Vector3 forward = origin.forward; forward.y = 0f; forward = forward.sqrMagnitude > 0.001f ? forward.normalized : transform.forward; float finalDamage = weapon.damage + stats.Damage; bool critical = Random.value < stats.CriticalChance; if (critical) { finalDamage *= 1.75f; } if (weapon.isRanged) { if (Physics.Raycast(start, forward, out RaycastHit hit, weapon.range, hitMask, QueryTriggerInteraction.Ignore)) { return ApplyDamage(hit.collider, finalDamage, critical); } return false; } Vector3 center = start + forward * Mathf.Max(0.6f, weapon.range * 0.55f); int count = Physics.OverlapSphereNonAlloc(center, meleeRadius + weapon.range * 0.12f, hits, hitMask, QueryTriggerInteraction.Ignore); bool damaged = false; for (int i = 0; i < count; i++) { Collider hit = hits[i]; if (hit == null || hit.transform == transform || hit.GetComponentInParent() != null) { continue; } if (ApplyDamage(hit, finalDamage, critical)) { damaged = true; break; } } return damaged; } private bool ApplyDamage(Collider collider, float amount, bool critical) { Damageable damageable = collider.GetComponentInParent(); if (damageable == null || !damageable.IsAlive) { return false; } damageable.TakeDamage(amount, gameObject); if (critical) { OTGIntegrated.Core.GameEvents.RaiseNotification("Критический удар"); } return true; } private void OnDrawGizmosSelected() { Gizmos.color = new Color(1f, 0.45f, 0.1f, 0.25f); Transform origin = attackOrigin != null ? attackOrigin : transform; Gizmos.DrawWireSphere(origin.position + origin.forward * 1.3f + Vector3.up * 0.8f, meleeRadius); } } }