191 lines
4.8 KiB
C#
191 lines
4.8 KiB
C#
using Invector;
|
|
using Invector.vCharacterController;
|
|
using UnityEngine;
|
|
|
|
namespace DemonBoss.Magic
|
|
{
|
|
/// <summary>
|
|
/// Component that adds damage when the player gets too close to the shield.
|
|
/// Add to the shield object along with Sphere Collider (IsTrigger = true).
|
|
/// </summary>
|
|
public class ShieldDamage : MonoBehaviour
|
|
{
|
|
[Header("Damage Configuration")]
|
|
[Tooltip("Damage dealt to the player")]
|
|
public int damage = 15;
|
|
|
|
[Tooltip("Knockback force")]
|
|
public float knockbackForce = 10f;
|
|
|
|
[Tooltip("Player Tag")]
|
|
public string playerTag = "Player";
|
|
|
|
[Tooltip("Time between consecutive hits (so as not to deal damage to every frame)")]
|
|
public float damageInterval = 1f;
|
|
|
|
[Header("Effects")]
|
|
[Tooltip("Sound effect when dealing damage")]
|
|
public AudioClip damageSound;
|
|
|
|
[Tooltip("Visual effect when dealing damage")]
|
|
public GameObject damageEffect;
|
|
|
|
[Header("Debug")]
|
|
[Tooltip("Enable debug logs")]
|
|
public bool enableDebug = false;
|
|
|
|
private AudioSource audioSource;
|
|
private float lastDamageTime;
|
|
|
|
private void Awake()
|
|
{
|
|
if (damageSound != null)
|
|
{
|
|
audioSource = GetComponent<AudioSource>();
|
|
if (audioSource == null)
|
|
{
|
|
audioSource = gameObject.AddComponent<AudioSource>();
|
|
audioSource.playOnAwake = false;
|
|
audioSource.spatialBlend = 1f; // 3D sound
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnTriggerStay(Collider other)
|
|
{
|
|
if (other.CompareTag(playerTag) && Time.time >= lastDamageTime + damageInterval)
|
|
{
|
|
DealDamageToPlayer(other);
|
|
lastDamageTime = Time.time;
|
|
}
|
|
}
|
|
|
|
private void DealDamageToPlayer(Collider playerCollider)
|
|
{
|
|
if (enableDebug) Debug.Log($"[ShieldDamage] I deal {damage} damage to the player: {playerCollider.name}");
|
|
|
|
Vector3 hitPoint = playerCollider.ClosestPoint(transform.position);
|
|
Vector3 hitDirection = (playerCollider.transform.position - transform.position).normalized;
|
|
|
|
vDamage damageInfo = new vDamage(damage)
|
|
{
|
|
sender = transform,
|
|
hitPosition = hitPoint
|
|
};
|
|
|
|
if (knockbackForce > 0f)
|
|
{
|
|
damageInfo.force = hitDirection * knockbackForce;
|
|
}
|
|
|
|
bool damageDealt = false;
|
|
|
|
// 1) vIDamageReceiver
|
|
var damageReceiver = playerCollider.GetComponent<vIDamageReceiver>() ??
|
|
playerCollider.GetComponentInParent<vIDamageReceiver>();
|
|
|
|
if (damageReceiver != null)
|
|
{
|
|
damageReceiver.TakeDamage(damageInfo);
|
|
damageDealt = true;
|
|
if (enableDebug) Debug.Log("[ShieldDamage] Damage dealt by vIDamageReceiver");
|
|
}
|
|
|
|
// 2) vHealthController
|
|
if (!damageDealt)
|
|
{
|
|
var healthController = playerCollider.GetComponent<vHealthController>() ??
|
|
playerCollider.GetComponentInParent<vHealthController>();
|
|
|
|
if (healthController != null)
|
|
{
|
|
healthController.TakeDamage(damageInfo);
|
|
damageDealt = true;
|
|
if (enableDebug) Debug.Log("[ShieldDamage] Damage dealt by vHealthController");
|
|
}
|
|
}
|
|
|
|
// 3) vThirdPersonController
|
|
if (!damageDealt)
|
|
{
|
|
var tpc = playerCollider.GetComponent<vThirdPersonController>() ??
|
|
playerCollider.GetComponentInParent<vThirdPersonController>();
|
|
|
|
if (tpc != null)
|
|
{
|
|
// SprawdŸ czy to Beyond variant
|
|
if (tpc is Beyond.bThirdPersonController beyond)
|
|
{
|
|
if (!beyond.GodMode && !beyond.isImmortal)
|
|
{
|
|
tpc.TakeDamage(damageInfo);
|
|
damageDealt = true;
|
|
if (enableDebug) Debug.Log("[ShieldDamage] Damage dealt by bThirdPersonController");
|
|
}
|
|
else
|
|
{
|
|
if (enableDebug) Debug.Log("[ShieldDamage] Player is immortal - no damage");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tpc.TakeDamage(damageInfo);
|
|
damageDealt = true;
|
|
if (enableDebug) Debug.Log("[ShieldDamage] Damage dealt by vThirdPersonController");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (damageDealt)
|
|
{
|
|
PlayEffects(hitPoint);
|
|
}
|
|
else if (enableDebug)
|
|
{
|
|
Debug.LogWarning("[ShieldDamage] Cannot deal damage - missing required component!");
|
|
}
|
|
}
|
|
|
|
private void PlayEffects(Vector3 hitPoint)
|
|
{
|
|
// Play hit sound
|
|
if (audioSource != null && damageSound != null)
|
|
{
|
|
audioSource.PlayOneShot(damageSound);
|
|
}
|
|
|
|
// Show visual effect
|
|
if (damageEffect != null)
|
|
{
|
|
GameObject effect = Instantiate(damageEffect, hitPoint, Quaternion.identity);
|
|
Destroy(effect, 2f); // Remove after 2 seconds
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
/// <summary>
|
|
/// Draw damage range visualization in Scene View
|
|
/// </summary>
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
// Show damage range
|
|
Collider col = GetComponent<Collider>();
|
|
if (col != null && col.isTrigger)
|
|
{
|
|
Gizmos.color = Color.red;
|
|
if (col is SphereCollider sphere)
|
|
{
|
|
Gizmos.DrawWireSphere(transform.position, sphere.radius);
|
|
}
|
|
else if (col is CapsuleCollider capsule)
|
|
{
|
|
// Approximate capsule visualization
|
|
Gizmos.DrawWireSphere(transform.position, capsule.radius);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
} |