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;
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;
///
/// Build effect gameObject to instantiate on start
///
public GameObject buildEffectPrefab;
///
/// 升级特效
///
public GameObject UpgradeEffectPrefab;
///
/// 当前的Level对应的DamagerData.
///
public Damager levelDamager;
///
/// Reference to scriptable object with level data on it
///
public TowerLevelData levelData;
///
/// The parent tower controller of this tower
///
protected Tower m_ParentTower;
///
/// The list of effects attached to the tower
///
Affector[] m_Affectors;
///
/// TEST CODE: 是否已经缩放.
///
protected bool bScaleForCombat = false;
///
/// 未上阵的形象
///
public GameObject Body;
///
/// 上阵形象
///
public GameObject AttackBody;
///
/// 精灵塔动作状态
///
public TowerActionState ActionState { get; protected set; }
private string paramName = "ActionState";
///
/// 动作动画器
///
public Animator ActionAnimator;
///
/// 发射子弹速率
///
protected float fireRate;
///
/// 初始攻击速率
///
private float attackSpeed = 1f;
///
/// 多倍速攻击速度,基准速度的 N 倍速
///
private float fireSpeed = 1f;
///
/// 发射倍速,如果设置多倍速攻击,直接修改此属性,恢复之前的攻速直接设置为 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;
public void ChangeState(TowerActionState state)
{
if (state == ActionState) return;
ActionState = state;
if (state == TowerActionState.Attack)
ActionAnimator.speed = attackSpeed * FireSpeed;
else if (state == TowerActionState.Standing)
ActionAnimator.speed = 1f;
ActionAnimator.SetInteger(paramName, (int)state);
}
///
/// 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; }
///
/// Gets the cost value
///
public int cost
{
get { return levelData.cost; }
}
///
/// Gets the sell value
///
public int sell
{
get { return levelData.sell; }
}
///
/// Gets the max health
///
public int maxHealth
{
get { return levelData.maxHealth; }
}
///
/// Gets the starting health
///
public int startingHealth
{
get { return levelData.startingHealth; }
}
///
/// Gets the tower description
///
public string description
{
get { return levelData.description; }
}
///
/// Gets the tower description
///
public string upgradeDescription
{
get { return levelData.upgradeDescription; }
}
///
/// 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;
}
m_ParentTower = tower;
}
private Transform mat;
private MeshRenderer myRender;
Vector3 normalScale;
private void Awake()
{
mat = transform.Find("Cube");
myRender = mat.GetComponent();
normalScale = new Vector3(1.5f, 1.5f, 1.5f);
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;
}
GameObject affectorObj = transform.Find("Affector").gameObject;
AttackAffector attackAffector = affectorObj.GetComponent();
fireRate = attackAffector.fireRate;
if (actionTimeArr[1] > 1 / fireRate)
{
// 动画时间比攻击长
attackSpeed = actionTimeArr[1] * fireRate;
}
SetAttackState(false);
}
private void LateUpdate()
{
if (ActionAnimator.isActiveAndEnabled)
{
AnimatorStateInfo stateInfo = ActionAnimator.GetCurrentAnimatorStateInfo(0);
if (ActionState == TowerActionState.Attack && stateInfo.normalizedTime >= 1f)
ChangeState(TowerActionState.Standing);
}
}
///
/// 未上阵塔缩放,固定缩放
///
public void NormalScale()
{
mat.localScale = normalScale;
mat.localPosition = Vector3.zero;
}
private bool isAttack;
///
/// 设置火宝石攻速
///
///
public void SetFireMatSpeed(bool isFast)
{
if (isFast && isAttack)
{
myRender.material.SetFloat("_Speed", 40);
}
else
{
//还原10
myRender.material.SetFloat("_Speed", 8);
}
}
///
/// 上阵塔缩放
///
public void ResetScale()
{
if (transform.name.StartsWith("GrowUpTower"))
{
//火元素
mat.localScale = GameConfig.fireScale;
mat.localPosition = GameConfig.fireOffectp;
}
else if (transform.name.StartsWith("BlinkTower"))
{
//木元素
mat.localScale = GameConfig.woodScale;
mat.localPosition = GameConfig.woodOffectp;
}
else if (transform.name.StartsWith("CopyCatTower"))
{
//水元素
//mat.localScale = woodScale;
Vector3 scale = mat.localScale;
if (!this.bScaleForCombat)
{
scale.z *= 1.267f;
mat.localScale = scale;
Vector3 pos = mat.localPosition;
pos.z -= 0.2f;
mat.localPosition = pos;
bScaleForCombat = true;
}
}
}
///
/// 当前的TowerLevel设置为对应怪物的材质显示
///
///
public void SetTowerMonsterMat(Material material, bool isAttack)
{
if (material == null) return;
this.isAttack = isAttack;
myRender.material = material;
if (isAttack)
{
if (transform.name.StartsWith("GrowUpTower") || transform.name.StartsWith("BlinkTower"))
{
float t = Mathf.Floor(Time.time);
float offect = t % 8;
myRender.material.SetFloat("_ChangeTime", Mathf.Floor(Time.time - offect));
}
}
else
{
myRender.material.SetFloat("_ChangeTime", Mathf.Floor(Time.time));
}
//Debug.Log("当前时间Time.time:"+Time.time);
// 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())
// {
// if (t.name == "Cube")
// {
// t.GetComponent().material = mat;
// //Vector3 scale = t.localScale;
// // if (!this.bScaleForCombat)
// // {
// // scale.z *= 1.267f;
// // t.localScale = scale;
// // Vector3 pos = t.localPosition;
// // pos.z -= 0.2f;
// // t.localPosition = pos;
// // bScaleForCombat = true;
// // }
// }
// }
}
///
/// 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;
}
///
/// Returns the dps of the tower
///
/// The dps of the tower
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();
}
public void OnBeforeSerialize()
{
}
///
/// 获取当前TowerLevel对应的AttackRise.
///
public float attackRise { get { return m_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)
{
Body.SetActive(!isAttackMode);
AttackBody.SetActive(isAttackMode);
ActionAnimator.enabled = isAttackMode;
}
///
/// 播放升级特效
///
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);
}
}
}
}