using System.Collections.Generic;
|
using Core.Health;
|
using KTGMGemClient;
|
using TowerDefense.Affectors;
|
using TowerDefense.UI.HUD;
|
using UnityEngine;
|
using TMPro;
|
|
namespace TowerDefense.Towers
|
{
|
/// <summary>
|
/// An individual level of a tower
|
/// </summary>
|
[DisallowMultipleComponent]
|
public class TowerLevel : MonoBehaviour, ISerializationCallbackReceiver
|
{
|
/// <summary>
|
/// The prefab for communicating placement in the scene
|
/// </summary>
|
public TowerPlacementGhost towerGhostPrefab;
|
|
/// <summary>
|
/// 升级特效
|
/// </summary>
|
public GameObject UpgradeEffectPrefab;
|
|
/// <summary>
|
/// The parent tower controller of this tower
|
/// </summary>
|
public Tower ParentTower { get; protected set; }
|
|
/// <summary>
|
/// The list of effects attached to the tower
|
/// </summary>
|
Affector[] m_Affectors;
|
|
/// <summary>
|
/// 未上阵的形象
|
/// </summary>
|
public GameObject Body;
|
|
/// <summary>
|
/// 上阵形象
|
/// </summary>
|
public GameObject AttackBody;
|
|
/// <summary>
|
/// 可以放置的材质
|
/// </summary>
|
public MeshRenderer canPlaceMesh;
|
|
/// <summary>
|
/// 精灵塔动作状态
|
/// </summary>
|
public TowerActionState ActionState { get; protected set; }
|
|
private string paramName = "ActionState";
|
|
/// <summary>
|
/// 动作动画器
|
/// </summary>
|
public Animator ActionAnimator;
|
|
public TextMeshPro LevelText;
|
|
/// <summary>
|
/// 精灵初始配置数据
|
/// </summary>
|
public elf_info ElfInfo { get; protected set; }
|
|
/// <summary>
|
/// 发射子弹速率
|
/// </summary>
|
protected float fireRate;
|
|
/// <summary>
|
/// 初始攻击速率
|
/// </summary>
|
private float attackSpeed = 1f;
|
|
/// <summary>
|
/// 多倍速攻击速度,基准速度的 N 倍速
|
/// </summary>
|
private float fireSpeed = 1f;
|
|
[SerializeField]
|
private SpriteRenderer levelBorder;
|
|
[SerializeField]
|
private ParticleSystem buffPS;
|
/// <summary>
|
/// 发射倍速,如果设置多倍速攻击,直接修改此属性,恢复之前的攻速直接设置为 1
|
/// </summary>
|
/// <value></value>
|
public float FireSpeed
|
{
|
get { return fireSpeed; }
|
set
|
{
|
if (value < 0) value = 0;
|
|
fireSpeed = value;
|
|
if (ActionState == TowerActionState.Attack)
|
ActionAnimator.speed = attackSpeed * fireSpeed;
|
}
|
}
|
|
/// <summary>
|
/// 各个动作的基准播放时长(播放一遍用的时间)
|
/// </summary>
|
protected float[] actionTimeArr;
|
|
/// <summary>
|
/// Gets the list of effects attached to the tower
|
/// </summary>
|
protected Affector[] Affectors
|
{
|
get
|
{
|
if (m_Affectors == null)
|
{
|
m_Affectors = GetComponentsInChildren<Affector>();
|
}
|
return m_Affectors;
|
}
|
}
|
|
/// <summary>
|
/// The physics layer mask that the tower searches on
|
/// </summary>
|
public LayerMask mask { get; protected set; }
|
|
/// <summary>
|
/// Initialises the Effects attached to this object
|
/// </summary>
|
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<AttackAffector>();
|
}
|
|
ParentTower = tower;
|
ElfInfo = ElfInfoData.GetDataById(tower.ElfId);
|
}
|
|
[SerializeField]
|
private Sprite[] sprites;
|
/// <summary>
|
/// 设置显示等级
|
/// </summary>
|
/// <param name="level">从1开始</param>
|
public void SetShowLevel(int level)
|
{
|
LevelText.text = level < 5 ? "" : level.ToString();
|
levelBorder.sprite = level < 5 ? sprites[level - 1] : sprites[4];
|
// elf_upgrade info = ElfUpgradeData.GetDataById(level);
|
// LevelText.text = $"{level}";
|
// levelBorder.sprite = Resources.Load<Sprite>($"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();
|
}
|
|
/// <summary>
|
/// 设置缩放
|
/// </summary>
|
/// <param name="level">从1开始</param>
|
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);
|
}
|
}
|
|
/// <summary>
|
/// 获取发射速率
|
/// </summary>
|
/// <returns></returns>
|
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);
|
}
|
|
/// <summary>
|
/// 设置可以放置
|
/// </summary>
|
/// <param name="isOn"></param>
|
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;
|
}
|
|
/// <summary>
|
/// A method for activating or deactivating the attached <see cref="Affectors"/>
|
/// </summary>
|
public void SetAffectorState(bool state, int waveline)
|
{
|
foreach (Affector affector in Affectors)
|
{
|
if (affector != null)
|
{
|
affector.enabled = state;
|
affector.waveLineID = waveline;
|
}
|
}
|
}
|
|
/// <summary>
|
/// Returns a list of affectors that implement ITowerRadiusVisualizer
|
/// </summary>
|
/// <returns>ITowerRadiusVisualizers of tower</returns>
|
public List<ITowerRadiusProvider> GetRadiusVisualizers()
|
{
|
List<ITowerRadiusProvider> visualizers = new List<ITowerRadiusProvider>();
|
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()
|
{
|
}
|
|
/// <summary>
|
/// 获取当前TowerLevel对应的AttackRise.
|
/// /// </summary>
|
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;
|
}
|
|
/// <summary>
|
/// 设置上阵和非上阵状态下,塔的自身形象
|
/// </summary>
|
/// <param name="isAttackMode"></param>
|
public void SetAttackState(bool isAttackMode)
|
{
|
if (isAttackMode)
|
{
|
AttackBody.SetActive(isAttackMode);
|
Body.SetActive(!isAttackMode);
|
ChangeState(TowerActionState.Attack);
|
}
|
else
|
{
|
ChangeState(TowerActionState.Standing);
|
}
|
}
|
|
/// <summary>
|
/// 播放升级特效
|
/// </summary>
|
public void PlayUpGradeEffect()
|
{
|
if (UpgradeEffectPrefab != null)
|
{
|
GameObject obj = Instantiate(UpgradeEffectPrefab);
|
obj.transform.position = gameObject.transform.position;
|
ParticleSystem ps = obj.GetComponent<ParticleSystem>();
|
|
if (ps == null)
|
ps = obj.transform.GetChild(0).GetComponent<ParticleSystem>();
|
|
Vector3 pos = obj.transform.position;
|
pos.y = 5f;
|
obj.transform.position = pos;
|
ps.Play();
|
Destroy(obj, ps.main.duration);
|
}
|
}
|
}
|
}
|