using System.Collections.Generic; using Core.Health; using KTGMGemClient; using TowerDefense.Affectors; using TowerDefense.UI.HUD; using UnityEngine; using TMPro; namespace TowerDefense.Towers { /// /// An individual level of a tower /// [DisallowMultipleComponent] public class TowerLevel : MonoBehaviour, ISerializationCallbackReceiver { /// /// The prefab for communicating placement in the scene /// public TowerPlacementGhost towerGhostPrefab; /// /// 升级特效 /// public GameObject UpgradeEffectPrefab; /// /// The parent tower controller of this tower /// public Tower ParentTower { get; protected set; } /// /// The list of effects attached to the tower /// Affector[] m_Affectors; /// /// 未上阵的形象 /// public GameObject Body; /// /// 上阵形象 /// public GameObject AttackBody; /// /// 可以放置的材质 /// public MeshRenderer canPlaceMesh; /// /// 精灵塔动作状态 /// public TowerActionState ActionState { get; protected set; } private string paramName = "ActionState"; /// /// 动作动画器 /// public Animator ActionAnimator; public TextMeshPro LevelText; /// /// 精灵初始配置数据 /// public elf_info ElfInfo { get; protected set; } /// /// 发射子弹速率 /// protected float fireRate; /// /// 初始攻击速率 /// private float attackSpeed = 1f; /// /// 多倍速攻击速度,基准速度的 N 倍速 /// private float fireSpeed = 1f; [SerializeField] private SpriteRenderer levelBorder; [SerializeField] private ParticleSystem buffPS; /// /// 发射倍速,如果设置多倍速攻击,直接修改此属性,恢复之前的攻速直接设置为 1 /// /// public float FireSpeed { get { return fireSpeed; } set { if (value < 0) value = 0; fireSpeed = value; if (ActionState == TowerActionState.Attack) ActionAnimator.speed = attackSpeed * fireSpeed; } } /// /// 各个动作的基准播放时长(播放一遍用的时间) /// protected float[] actionTimeArr; /// /// Gets the list of effects attached to the tower /// protected Affector[] Affectors { get { if (m_Affectors == null) { m_Affectors = GetComponentsInChildren(); } return m_Affectors; } } /// /// The physics layer mask that the tower searches on /// public LayerMask mask { get; protected set; } /// /// Initialises the Effects attached to this object /// public virtual void Initialize(Tower tower, LayerMask enemyMask, IAlignmentProvider alignment) { mask = enemyMask; foreach (Affector effect in Affectors) { effect.Initialize(alignment, mask); effect.towerPtr = tower; AttackAffector attackAffector = effect.GetComponent(); } ParentTower = tower; ElfInfo = ElfInfoData.GetDataById(tower.ElfId); } [SerializeField] private Sprite[] sprites; /// /// 设置显示等级 /// /// 从1开始 public void SetShowLevel(int level) { LevelText.text = level < 4 ? "" : level.ToString(); levelBorder.sprite = level < 5 ? sprites[level - 1] : sprites[4]; // elf_upgrade info = ElfUpgradeData.GetDataById(level); // LevelText.text = $"{level}"; // levelBorder.sprite = Resources.Load($"UI/TowerLevel/{info.rank_img}"); // Vector3 pos = levelBorder.transform.localPosition; // if (info.rank_img < 3) // pos.z = ParentTower.ElfId == 201 ? 0.542f : 0.645f; // else // pos.z = ParentTower.ElfId == 201 ? 0.497f : 0.594f; // levelBorder.transform.localPosition = pos; } //buff生效 public void ShowBuffPS() { buffPS?.Play(); } /// /// 设置缩放 /// /// 从1开始 public void SetScale(int level) { elf_upgrade info = ElfUpgradeData.GetDataById(level); //Debug.Log($"level:{level} 设置了缩放:{info.zoom}"); transform.localScale = Vector3.one * info.zoom; } private void Awake() { canPlaceMesh.enabled = false; } private void Start() { if (ActionAnimator != null) { AnimationClip[] clips = ActionAnimator.runtimeAnimatorController.animationClips; actionTimeArr = new float[clips.Length]; for (int i = 0; i < clips.Length; ++i) { if (clips[i].name == "Standing") actionTimeArr[0] = clips[i].length; else if (clips[i].name == "Attack") actionTimeArr[1] = clips[i].length; } fireRate = GetFireRate(); if (actionTimeArr[1] > 1 / fireRate) { // 动画时间比攻击长 attackSpeed = actionTimeArr[1] * fireRate; } SetAttackState(false); } } /// /// 获取发射速率 /// /// public float GetFireRate() { DecreaseTowerAttackCD endlessBuff = (DecreaseTowerAttackCD)EndlessBuffManager.instance.GetBuffInstanceByType(EndlessBuffEffectType.DecreaseTowerAttackCD); float fireRate = endlessBuff != null ? endlessBuff.GetDecreaseCD(ParentTower.ElfId, 1 / ElfInfo.b_atkf) : 1 / ElfInfo.b_atkf; // 限制最大速度为 每0.1s发射一次 return Mathf.Max(fireRate, 0.1f); } public void LateUpdate() { if (ActionAnimator == null || !ActionAnimator.isActiveAndEnabled) return; AnimatorStateInfo stateInfo = ActionAnimator.GetCurrentAnimatorStateInfo(0); if (ActionState == TowerActionState.Attack && stateInfo.normalizedTime >= 1f) ChangeState(TowerActionState.Standing); } /// /// 设置可以放置 /// /// public void SetCanPlace(bool isOn) { if (canPlaceMesh.enabled != isOn) canPlaceMesh.enabled = isOn; } public void ChangeState(TowerActionState state) { if (ActionAnimator == null || !ActionAnimator.isActiveAndEnabled) return; ActionState = state; if (ActionState == TowerActionState.Attack && state == TowerActionState.Attack) { ActionAnimator.Update(0); ActionAnimator.Play("Attack", 0, 0); } ActionAnimator.SetInteger(paramName, (int)state); if (state == TowerActionState.Attack) ActionAnimator.speed = attackSpeed * FireSpeed; else if (state == TowerActionState.Standing) ActionAnimator.speed = 1f; } /// /// A method for activating or deactivating the attached /// public void SetAffectorState(bool state, int waveline) { foreach (Affector affector in Affectors) { if (affector != null) { affector.enabled = state; affector.waveLineID = waveline; } } } /// /// Returns a list of affectors that implement ITowerRadiusVisualizer /// /// ITowerRadiusVisualizers of tower public List GetRadiusVisualizers() { List visualizers = new List(); foreach (Affector affector in Affectors) { var visualizer = affector as ITowerRadiusProvider; if (visualizer != null) { visualizers.Add(visualizer); } } return visualizers; } public void Kill() { ParentTower.KillTower(); } public void OnBeforeSerialize() { } /// /// 获取当前TowerLevel对应的AttackRise. /// /// public float attackRise { get { return ParentTower.attackRise; } } public void OnAfterDeserialize() { // Setting this member to null is required because we are setting this value on a prefab which will // persists post run in editor, so we null this member to ensure it is repopulated every run m_Affectors = null; } /// /// 设置上阵和非上阵状态下,塔的自身形象 /// /// public void SetAttackState(bool isAttackMode) { if (isAttackMode) { AttackBody.SetActive(isAttackMode); Body.SetActive(!isAttackMode); ChangeState(TowerActionState.Attack); } else { ChangeState(TowerActionState.Standing); } } /// /// 播放升级特效 /// public void PlayUpGradeEffect() { if (UpgradeEffectPrefab != null) { GameObject obj = Instantiate(UpgradeEffectPrefab); obj.transform.position = gameObject.transform.position; ParticleSystem ps = obj.GetComponent(); if (ps == null) ps = obj.transform.GetChild(0).GetComponent(); Vector3 pos = obj.transform.position; pos.y = 5f; obj.transform.position = pos; ps.Play(); Destroy(obj, ps.main.duration); } } } }