using Spine.Unity; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public enum TurretAnimType { None = 0, skeletonAnimation = 1, animation = 2, animator = 3 } public enum TurretState { None = 0, Idle = 1, Attack = 2, LaserStart = 3, LaserLoop = 4, LaserEnd = 5 } public class TurretData : MonoBehaviour { [Header("基础")] public string turretID; public SitPosData setPosData; public Transform tra_BulletStartPosition; [Tooltip("炮台旋转节点。拖入后 SitPosData.tra_CurrTurret 用此节点旋转;不拖则用炮台自身的父节点(兼容旧逻辑)")] public Transform tra_RotationPivot; public GameObject bulletPrefab_Two; public GameObject bulletPrefab; [Header("战神激光(锁定时显示,普通炮台不配置即无此效果)")] [Tooltip("激光预制体。非空=预制体形态(JiGuangControl 工具类驱动);为空=LineRenderer 兜底形态(自动创建)")] public GameObject laserPrefab; [Tooltip("LineRenderer 兜底形态的线宽")] public float laserWidth = 0.3f; [Tooltip("LineRenderer 兜底形态的颜色")] public Color laserColor = new Color(1f, 0.3f, 0.3f, 0.9f); [Tooltip("预制体形态激光的长度校正值(不同激光预制体设置不同值)")] public float laserLengthCorrect = 1f; [Header("UI面板属性")] [Tooltip("炮台编号,对应 TurretResourcesData.turretNumber")] public int turretNumber; [Tooltip("1=普通炮台 2=战神 3=翅膀")] public int turretType = 1; [Tooltip("UI 展示名称")] public string displayName; [Tooltip("品质 1=普通 2=稀有 3=史诗 4=传说")] [Range(1, 5)] public int quality = 1; [Tooltip("解锁所需等级(0=默认拥有)")] public int unlockLevel; [Tooltip("UI 列表/详情用的缩略图")] public Sprite uiIconSprite; [TextArea(2, 4)] [Tooltip("描述文字")] public string description; // ---- 运行时状态(由服务器/UI面板读写) ---- [System.NonSerialized] public bool isUnlocked; [System.NonSerialized] public bool isEquipped; [System.NonSerialized] public int ownStarLevel; [Header("动画组件")] public SkeletonGraphic skeletonAnimation; public Animation old_CurrAnimation; public Animator new_CurrAnimation; public TurretAnimType currTurretType; public bool isFrenzy=false; [Header("动画名")] public string idleAnim; public string attackAnim; // 新增:狂暴专用攻击动画(已经是二倍速帧动画) public string frenzyAttackAnim; private bool useFrenzyAnim = false; public string laserStartAnim; public string laserLoopAnim; public string laserEndAnim; [Header("战神 Animator 参数")] [Tooltip("战神状态机开火参数名(Bool:Idle0 --PlayFire--> Fire状态机,Fire --PlayFire=false--> Exit回Idle)。" + "检测到此参数自动启用战神模式,无需手动配置")] public string playFireParam = "PlayFire"; [Tooltip("开火动画变体参数名(Int):0=Fire0(正常子弹) 1=Fire1(激光)。锁定时自动切1,非锁定开火用0")] public string fireIndexParam = "FireIndex"; [Tooltip("待机动画变体参数名(Int:IdleIndex=0选Idle0...)")] public string idleIndexParam = "IdleIndex"; [Tooltip("开火动画变体索引默认值:0=Fire0(正常子弹) 1=Fire1(激光)。运行时按锁定状态自动切换,此值仅为无锁定信息时的兜底")] public int fireIndex = 0; [Tooltip("待机动画变体索引:0=Idle0 1=Idle1...")] public int idleIndex = 0; [Header("XJMH加减炮倍")] public GameObject obj_Add; public GameObject obj_Down; // ---- 战神模式运行时缓存(首次 PlayAnimator 时检测)---- private bool _warGodAnimChecked; // 是否已检测过参数 private bool _warGodAnimMode; // true=战神 PlayFire 约定 private bool _playFireIsTrigger; // PlayFire 实际类型是否 Trigger(个别控制器用触发器) private bool _hasFireIndex; private bool _hasIdleIndex; private AnimatorControllerParameterType _fireIndexType = AnimatorControllerParameterType.Int; private AnimatorControllerParameterType _idleIndexType = AnimatorControllerParameterType.Int; private TurretState currState; /// 出现动画保护截止时间:这段时间内 Idle(动画名为空)不 ClearTrack,避免出现动画刚播就被抹掉 private float _appearAnimHoldUntil; /// /// 从资源表查询 TurretResourcesData。表里没有则返回 null,调用方应使用 TurretData 自身的 Inspector 默认值。 /// public TurretResourcesData GetResourcesData() { return TurretResourcesData.GetTurretData(turretNumber); } /// 安全获取攻击音效 ID:表里有就用,没有则返回 0(静音)。 public int GetAttackAudioID() { var res = GetResourcesData(); return res != null ? res.attackAudioID : 0; } /// 安全获取子弹 ID 列表:表里有就用,没有则返回空列表。 public List GetBulletIDs() { var res = GetResourcesData(); return res?.bulletID ?? new List(); } /// 安全获取动画类型:表里有就用,没有则用 Inspector 配置的 currTurretType。 public TurretAnimType GetAnimationType() { var res = GetResourcesData(); return res != null ? (TurretAnimType)res.animationType : currTurretType; } private void Awake() { //if (setPosData != null) // setPosData.OnStateChange = ChangeState; // 自动判断:如果狂暴攻击动画名不为空,就启用切换动画模式 useFrenzyAnim = !string.IsNullOrEmpty(frenzyAttackAnim); } private void OnEnable() { PlayState(TurretState.Idle); BindAddDownButtons(); // ⭐ XJMH 加减炮倍:炮台上的 +/- 绑定点击(每次激活重绑,幂等) } // ==================== XJMH 加减炮倍按钮绑定 ==================== // 炮台上的 obj_Add / obj_Down(物体名 Up / Down)在预制体里没有 Button 组件、也没有任何代码绑定 // → 点击无反应。这里在炮台激活时统一补 Button + 绑定: // + → 座位 ChangeTurretAddConsumeNum(发 ChangeGunMultiple,等服务端确认后应用新炮倍) // - → 座位 ChangeTurretMinusConsumeNum // 未拖引用跳过(可要可不要);非本地座位由 SitPosData.HideTurretAddMinusUI 隐藏。 private SitPosData ResolveSit() { return setPosData != null ? setPosData : GetComponentInParent(); } private void OnClickTurretAdd() { ResolveSit()?.ChangeTurretAddConsumeNum(); } private void OnClickTurretMinus() { ResolveSit()?.ChangeTurretMinusConsumeNum(); } private void BindAddDownButtons() { BindAddDownButton(obj_Add, OnClickTurretAdd); BindAddDownButton(obj_Down, OnClickTurretMinus); } private static void BindAddDownButton(GameObject go, UnityEngine.Events.UnityAction action) { if (go == null) return; // 未拖引用:跳过,不报错 var btn = go.GetComponent