Files
DeviantMobile-Rohan/Assets/Scripts/SpecialMoveCardSystem/CardBehaviour.cs

215 lines
7.8 KiB
C#

using UnityEngine;
using System.Collections;
namespace SpecialMoveCards
{
/// <summary>
/// Handles world pickup visuals and behavior for a card: hover, rotate, glow, and pickup.
/// Expect a trigger collider and optionally a Rigidbody set to kinematic.
/// </summary>
[RequireComponent(typeof(Collider))]
public class CardBehaviour : MonoBehaviour
{
[SerializeField] private CardData cardData;
[Header("Visual References")]
[Tooltip("Renderer(s) that should have emissive color applied.")]
[SerializeField] private Renderer[] emissiveRenderers;
[Tooltip("Optional glow mesh (cube/cylinder/etc) used for volumetric-looking glow.")]
[SerializeField] private Transform glowCube; // kept for backward-compat; any mesh child works
[Tooltip("Optional explicit renderer for the glow mesh. If assigned, takes priority over 'glowCube'.")]
[SerializeField] private Renderer glowRenderer;
[Tooltip("Optional light to boost bloom.")]
[SerializeField] private Light glowLight;
[Header("Glow Sync")]
[Tooltip("If true, reads emission color from the first emissive renderer's material and uses it for glow, without overriding the material. If false, uses CardData color to set emission on the renderers.")]
[SerializeField] private bool deriveGlowFromMaterial = true;
[Tooltip("Scales the glow intensity derived from material or CardData.")]
[SerializeField] private float glowIntensityMultiplier = 1f;
[Header("Motion")]
[SerializeField] private float defaultHoverAmplitude = 0.25f;
[SerializeField] private float defaultHoverSpeed = 1.0f;
[SerializeField] private float defaultRotationSpeed = 35f;
private Vector3 basePos;
private float hoverPhase;
private MaterialPropertyBlock mpb;
private Collider trigger;
private Color baseEmissive = Color.white;
[Header("Glow Pulse (Optional)")]
[SerializeField] private bool pulseGlow = false;
[SerializeField] private float pulseSpeed = 2f;
[SerializeField, Range(0f, 2f)] private float pulseAmplitude = 0.25f;
public CardData Data => cardData;
private void Reset()
{
var col = GetComponent<Collider>();
if (col) col.isTrigger = true;
}
private void Awake()
{
// Skip if card system is disabled globally - destroy this card
if (CardSpawner.CARD_SYSTEM_DISABLED)
{
Destroy(gameObject);
return;
}
trigger = GetComponent<Collider>();
if (trigger) trigger.isTrigger = true;
EnsureMaterialPropertyBlock();
basePos = transform.position;
ApplyVisuals();
}
private void OnValidate()
{
if (Application.isPlaying) return;
EnsureMaterialPropertyBlock();
ApplyVisuals();
}
private void Update()
{
float amp = (cardData && cardData.hoverAmplitude > 0f) ? cardData.hoverAmplitude : defaultHoverAmplitude;
float spd = (cardData && cardData.hoverSpeed > 0f) ? cardData.hoverSpeed : defaultHoverSpeed;
float rot = (cardData && cardData.rotationSpeed > 0f) ? cardData.rotationSpeed : defaultRotationSpeed;
hoverPhase += spd * Time.deltaTime;
float offset = Mathf.Sin(hoverPhase) * amp;
transform.position = basePos + Vector3.up * offset;
transform.Rotate(Vector3.up, rot * Time.deltaTime, Space.World);
// Optional pulsing for volumetric glow look
if (pulseGlow)
{
float f = 1f + Mathf.Sin(Time.time * pulseSpeed) * pulseAmplitude;
Color current = baseEmissive * f;
ApplyGlowOnly(current);
}
}
private void OnTriggerEnter(Collider other)
{
// Look for a PlayerPocket on the other object or its parents
var pocket = other.GetComponentInParent<PlayerPocket>();
if (pocket == null) return;
if (pocket.TryAddCard(cardData))
{
if (cardData && cardData.particlePrefab)
{
Instantiate(cardData.particlePrefab, transform.position, Quaternion.identity);
}
Destroy(gameObject);
}
}
private void ApplyVisuals()
{
EnsureMaterialPropertyBlock();
// Determine target emissive color
Color emissive;
if (deriveGlowFromMaterial && TryGetMaterialEmissionColor(out emissive))
{
emissive *= glowIntensityMultiplier;
}
else
{
Color c = cardData ? cardData.color : Color.white;
float intensity = cardData ? cardData.emissionIntensity : 2.5f;
emissive = c * Mathf.LinearToGammaSpace(intensity) * glowIntensityMultiplier;
// Only in this branch we override renderer emission to match CardData
if (emissiveRenderers != null)
{
for (int i = 0; i < emissiveRenderers.Length; i++)
{
var r = emissiveRenderers[i];
if (r == null) continue;
r.GetPropertyBlock(mpb);
mpb.SetColor("_EmissionColor", emissive);
r.SetPropertyBlock(mpb);
}
}
}
baseEmissive = emissive; // store for pulse updates
ApplyGlowOnly(emissive);
}
private void ApplyGlowOnly(Color emissive)
{
EnsureMaterialPropertyBlock();
// Prefer explicit glowRenderer if provided
Renderer targetRend = glowRenderer;
if (targetRend == null && glowCube != null)
targetRend = glowCube.GetComponent<Renderer>();
if (targetRend)
{
targetRend.GetPropertyBlock(mpb);
mpb.SetColor("_EmissionColor", emissive);
targetRend.SetPropertyBlock(mpb);
}
if (glowLight)
{
Color lightColor = new Color(Mathf.Clamp01(emissive.r), Mathf.Clamp01(emissive.g), Mathf.Clamp01(emissive.b));
glowLight.color = lightColor;
glowLight.intensity = Mathf.Max(1.5f, emissive.maxColorComponent * 2.5f);
glowLight.range = 3f;
}
}
private bool TryGetMaterialEmissionColor(out Color color)
{
color = Color.black;
if (emissiveRenderers == null) return false;
// Common property names across pipelines
string[] props = { "_EmissionColor", "_EmissiveColor", "_EmissiveColorLDR" };
for (int i = 0; i < emissiveRenderers.Length; i++)
{
var r = emissiveRenderers[i];
if (r == null) continue;
var mat = r.sharedMaterial != null ? r.sharedMaterial : r.material;
if (mat == null) continue;
for (int p = 0; p < props.Length; p++)
{
string prop = props[p];
if (mat.HasProperty(prop))
{
color = mat.GetColor(prop);
return true;
}
}
}
return false;
}
/// <summary>Assign the data at runtime for generic prefabs.</summary>
public void SetData(CardData data)
{
cardData = data;
ApplyVisuals();
}
private void EnsureMaterialPropertyBlock()
{
if (mpb == null)
{
mpb = new MaterialPropertyBlock();
}
}
}
}