| | |
| | | using System.Collections.Generic; |
| | | using ActionGameFramework.Health; |
| | | using Core.Health; |
| | | using KTGMGemClient; |
| | | using TowerDefense.Affectors; |
| | | using TowerDefense.Towers.Data; |
| | | using TowerDefense.UI.HUD; |
| | | using UnityEngine; |
| | | using TMPro; |
| | | |
| | | namespace TowerDefense.Towers |
| | | { |
| | |
| | | public TowerPlacementGhost towerGhostPrefab; |
| | | |
| | | /// <summary> |
| | | /// Build effect gameObject to instantiate on start |
| | | /// </summary> |
| | | public GameObject buildEffectPrefab; |
| | | |
| | | /// <summary> |
| | | /// 升级特效 |
| | | /// </summary> |
| | | public GameObject UpgradeEffectPrefab; |
| | | |
| | | /// <summary> |
| | | /// 当前的Level对应的DamagerData. |
| | | /// </summary> |
| | | public Damager levelDamager; |
| | | |
| | | /// <summary> |
| | | /// Reference to scriptable object with level data on it |
| | | /// </summary> |
| | | public TowerLevelData levelData; |
| | | |
| | | /// <summary> |
| | | /// The parent tower controller of this tower |
| | | /// </summary> |
| | | protected Tower m_ParentTower; |
| | | public Tower ParentTower { get; protected set; } |
| | | |
| | | /// <summary> |
| | | /// The list of effects attached to the tower |
| | |
| | | Affector[] m_Affectors; |
| | | |
| | | /// <summary> |
| | | /// TEST CODE: 是否已经缩放. |
| | | /// 未上阵的形象 |
| | | /// </summary> |
| | | protected bool bScaleForCombat = false; |
| | | 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; |
| | | |
| | | /// <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 |
| | |
| | | public LayerMask mask { get; protected set; } |
| | | |
| | | /// <summary> |
| | | /// Gets the cost value |
| | | /// </summary> |
| | | public int cost |
| | | { |
| | | get { return levelData.cost; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Gets the sell value |
| | | /// </summary> |
| | | public int sell |
| | | { |
| | | get { return levelData.sell; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Gets the max health |
| | | /// </summary> |
| | | public int maxHealth |
| | | { |
| | | get { return levelData.maxHealth; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Gets the starting health |
| | | /// </summary> |
| | | public int startingHealth |
| | | { |
| | | get { return levelData.startingHealth; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Gets the tower description |
| | | /// </summary> |
| | | public string description |
| | | { |
| | | get { return levelData.description; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Gets the tower description |
| | | /// </summary> |
| | | public string upgradeDescription |
| | | { |
| | | get { return levelData.upgradeDescription; } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// Initialises the Effects attached to this object |
| | | /// </summary> |
| | | public virtual void Initialize(Tower tower, LayerMask enemyMask, IAlignmentProvider alignment) |
| | |
| | | { |
| | | effect.Initialize(alignment, mask); |
| | | effect.towerPtr = tower; |
| | | AttackAffector attackAffector = effect.GetComponent<AttackAffector>(); |
| | | } |
| | | m_ParentTower = tower; |
| | | |
| | | ParentTower = tower; |
| | | ElfInfo = ElfInfoData.GetDataById(tower.ElfId); |
| | | } |
| | | |
| | | private Transform mat; |
| | | Vector3 normalScale; |
| | | /// <summary> |
| | | /// 设置显示等级 |
| | | /// </summary> |
| | | /// <param name="level">从1开始</param> |
| | | public void SetShowLevel(int level) |
| | | { |
| | | elf_upgrade info = ElfUpgradeData.GetDataById(level); |
| | | LevelText.text = $"{level}"; |
| | | levelBorder.sprite = Resources.Load<Sprite>($"UI/TowerLevel/{info.rank_img}"); |
| | | |
| | | private Vector3 fireScale = new Vector3(1.92f, 1.92f, 2.208f); |
| | | private Vector3 woodScale = new Vector3(1.5f, 1.5f, 2.82f); |
| | | private Vector3 waterScale = new Vector3(1.0f, 1.0f, 1.88f); |
| | | Vector3 pos = levelBorder.transform.localPosition; |
| | | |
| | | private Vector3 fireOffectp = new Vector3(0f, 0f, -0.15f); |
| | | if (info.rank_img < 3) |
| | | pos.z = ParentTower.ElfId == 201 ? 0.542f : 0.645f; |
| | | else |
| | | pos.z = ParentTower.ElfId == 201 ? 0.497f : 0.594f; |
| | | |
| | | private Vector3 woodOffectp = new Vector3(0.08f, 0f, 0.2f); |
| | | levelBorder.transform.localPosition = pos; |
| | | } |
| | | |
| | | private void Awake() |
| | | { |
| | | mat = transform.Find("Cube"); |
| | | normalScale = new Vector3(1.5f, 1.5f, 1.5f); |
| | | canPlaceMesh.enabled = false; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 未上阵塔缩放,固定缩放 |
| | | /// </summary> |
| | | public void NormalScale() |
| | | private void Start() |
| | | { |
| | | mat.localScale = normalScale; |
| | | mat.localPosition = Vector3.zero; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 上阵塔缩放 |
| | | /// </summary> |
| | | public void ResetScale() |
| | | { |
| | | if (transform.name.StartsWith("GrowUpTower")) |
| | | if (ActionAnimator != null) |
| | | { |
| | | //火元素 |
| | | mat.localScale = fireScale; |
| | | mat.localPosition = fireOffectp; |
| | | } |
| | | else if (transform.name.StartsWith("BlinkTower")) |
| | | { |
| | | //木元素 |
| | | mat.localScale = woodScale; |
| | | mat.localPosition = woodOffectp; |
| | | AnimationClip[] clips = ActionAnimator.runtimeAnimatorController.animationClips; |
| | | actionTimeArr = new float[clips.Length]; |
| | | |
| | | } |
| | | else if (transform.name.StartsWith("CopyCatTower")) |
| | | { |
| | | //水元素 |
| | | //mat.localScale = woodScale; |
| | | |
| | | Vector3 scale = mat.localScale; |
| | | |
| | | if (!this.bScaleForCombat) |
| | | for (int i = 0; i < clips.Length; ++i) |
| | | { |
| | | scale.z *= 1.267f; |
| | | mat.localScale = scale; |
| | | Vector3 pos = mat.localPosition; |
| | | pos.z -= 0.2f; |
| | | mat.localPosition = pos; |
| | | bScaleForCombat = true; |
| | | 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> |
| | | /// 当前的TowerLevel设置为对应怪物的材质显示 |
| | | /// 获取发射速率 |
| | | /// </summary> |
| | | /// <param name="mat"></param> |
| | | public void SetTowerMonsterMat(Material material) |
| | | /// <returns></returns> |
| | | public float GetFireRate() |
| | | { |
| | | if (material == null) return; |
| | | DecreaseTowerAttackCD endlessBuff = (DecreaseTowerAttackCD)EndlessBuffManager.instance.GetBuffInstanceByType(EndlessBuffEffectType.DecreaseTowerAttackCD); |
| | | float fireRate = endlessBuff != null ? endlessBuff.GetDecreaseCD(ParentTower.ElfId, 1 / ElfInfo.b_atkf) : 1 / ElfInfo.b_atkf; |
| | | |
| | | mat.GetComponent<MeshRenderer>().material = material; |
| | | // 限制最大速度为 每0.1s发射一次 |
| | | return Mathf.Max(fireRate, 0.1f); |
| | | } |
| | | |
| | | ResetScale(); |
| | | // if (transform.name.StartsWith("GrowUpTower") && mat.localPosition != fireOffectp) |
| | | // { |
| | | // mat.localPosition = fireOffectp; |
| | | // } |
| | | // else if (transform.name.StartsWith("BlinkTower") && mat.localPosition != woodOffectp) |
| | | // { |
| | | // //木元素 |
| | | // mat.localPosition = woodOffectp; |
| | | // } |
| | | // // 查找子结点: |
| | | // foreach (Transform t in transform.GetComponentsInChildren<Transform>()) |
| | | // { |
| | | // if (t.name == "Cube") |
| | | // { |
| | | // t.GetComponent<MeshRenderer>().material = mat; |
| | | // //Vector3 scale = t.localScale; |
| | | public void LateUpdate() |
| | | { |
| | | if (ActionAnimator == null || !ActionAnimator.isActiveAndEnabled) return; |
| | | |
| | | // // if (!this.bScaleForCombat) |
| | | // // { |
| | | // // scale.z *= 1.267f; |
| | | // // t.localScale = scale; |
| | | // // Vector3 pos = t.localPosition; |
| | | // // pos.z -= 0.2f; |
| | | // // t.localPosition = pos; |
| | | // // bScaleForCombat = true; |
| | | // // } |
| | | // } |
| | | // } |
| | | 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> |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// Returns a list of affectors that implement ITowerRadiusVisualizer |
| | |
| | | return visualizers; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Returns the dps of the tower |
| | | /// </summary> |
| | | /// <returns>The dps of the tower</returns> |
| | | public float GetTowerDps() |
| | | { |
| | | float dps = 0; |
| | | foreach (Affector affector in Affectors) |
| | | { |
| | | var attack = affector as AttackAffector; |
| | | if (attack != null && attack.damagerProjectile != null) |
| | | { |
| | | dps += attack.GetProjectileDamage() * attack.fireRate; |
| | | } |
| | | } |
| | | return dps; |
| | | } |
| | | |
| | | public void Kill() |
| | | { |
| | | m_ParentTower.KillTower(); |
| | | ParentTower.KillTower(); |
| | | } |
| | | |
| | | public void OnBeforeSerialize() |
| | | { |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 获取当前TowerLevel对应的AttackRise. |
| | | /// </summary> |
| | | public float attackRise { get { return m_ParentTower.attackRise; } } |
| | | /// /// </summary> |
| | | public float attackRise { get { return ParentTower.attackRise; } } |
| | | |
| | | public void OnAfterDeserialize() |
| | | { |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Insntiate the build particle effect object |
| | | /// 设置上阵和非上阵状态下,塔的自身形象 |
| | | /// </summary> |
| | | void Start() |
| | | /// <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> |