using KTGMGemClient;
using System;
using ActionGameFramework.Health;
using Core.Utilities;
using TowerDefense.Level;
using TowerDefense.Targetting;
using TowerDefense.Towers.Placement;
using TowerDefense.UI.HUD;
using UnityEngine;
using TowerDefense.Agents;
using System.Collections;
using System.Collections.Generic;
namespace TowerDefense.Towers
{
public enum EFeatureTower
{
NULL,
GrowUp,
CopyCat,
LightTower,
Skill_Fire,
Skill_Bomb,
END
}
public enum ETowerFuntion
{
NULL,
BULLET, // 子弹塔
ENERGY, // 能量充能.
FREEZE, // 水精灵充能
END
}
///
/// Common functionality for all types of towers
///
public class Tower : Targetable
{
///
/// A generalised name common to a levels
///
public string towerName;
///
/// The size of the tower's footprint
///
public IntVector2 dimensions;
///
/// 是否是特色骰子,如果是,则选择一个Enum类型。
///
public EFeatureTower towerFeature = EFeatureTower.NULL;
///
/// 塔防对应的充能状态.
///
public ETowerFuntion eTowerFuntion = ETowerFuntion.NULL;
[HideInInspector]
public BulletUICtl bulletCtl = null;
[HideInInspector]
public EnergyUICtl energyCtl = null;
[HideInInspector]
public FreezeBreath FreezeBreathCtrl = null;
///
/// The tower levels associated with this tower
///
[SerializeField]
private TowerLevel towerLevel;
public TowerLevel CurrentTowerLevel { get; private set; }
///
/// 精灵id,一一对应 elf_info表中的id,唯一的区分每一种精灵塔
///
public int ElfId;
///
/// The physics mask the tower searches on
///
public LayerMask enemyLayerMask;
///
/// The current level of the tower
///
public int currentLevel { get; protected set; }
protected bool m_bInAttackMode = false;
///
/// 攻击增加
///
public float attackRise { get; set; }
///
/// 用于界面部分的数据位移
///
protected int progressOffset = 0;
public int FreezeBreathProgressOffset { get; set; }
public bool PlayWaveLineFlash { get; set; } = true;
private bool isBondage;
///
/// 是否是泡泡禁锢状态
///
///
public bool IsBondage
{
get { return isBondage; }
set
{
isBondage = value;
CanAttack = !value;
}
}
///
/// 禁锢时间
///
public float BondageTime { get; set; }
///
/// 禁锢警告时间
///
///
public float BondageWarningTime { get; set; }
///
/// 泡泡禁锢期间,点击一次减少的时间
///
public float BondageClickDecreaseTime { get; set; } = 1f;
///
/// 是否是木属性蓄力状态
///
public bool IsWoodCharge { get; set; }
///
/// 木属性蓄力瞄准的目标
///
public Agent WoodAimAgent;
public int uiProOffset
{
get { return progressOffset; }
set { progressOffset = value; }
}
///
/// Gets whether the tower can level up anymore
///
public bool IsMaxLevel
{
get { return currentLevel == ElfUpgradeData.MaxTowerLevel - 1; }
}
///
/// 是否可以攻击
///
public bool CanAttack = true;
///
/// 是否是对手塔防
///
public bool opponentSide { get; set; }
///
/// 禁锢警告
///
protected GameObject bondageWarningObj;
///
/// 禁锢泡泡
///
protected GameObject bondageObj;
private GameObject tapObj;
///
/// 精灵被禁锢时点击次数
///
public int BondageTapCount { get; private set; }
///
/// 泡泡上升高度
///
private float yAdd = 10f;
///
/// 原始y值
///
private float originY;
///
/// 是否开始禁锢
///
public bool IsStartBondage { get; set; }
private float bombDuration = 0.7f;
private float bombTime;
///
/// 爆炸是否结束
///
private bool isBombCompleted;
private void Start()
{
originY = transform.position.y;
promptDic = new Dictionary();
}
private void Update()
{
HandleBondageBubble();
}
private static Dictionary promptDic;
///
/// 处理禁锢泡泡技能
///
private void HandleBondageBubble()
{
if (IsStartBondage)
{
if (isBondage)
{
if (transform.position.y < yAdd + originY && bondageObj != null)
{
// 上升状态
Vector3 pos = transform.position;
pos.y += 28f * Time.deltaTime;
transform.position = pos;
pos = bondageObj.transform.position;
pos.y += 28f * Time.deltaTime;
bondageObj.transform.position = pos;
}
}
else
{
if (!isBombCompleted)
{
bombTime += Time.deltaTime;
if (bombTime > bombDuration)
{
// 爆炸结束开始下降
isBombCompleted = true;
}
}
else
{
if (transform.position.y > originY)
{
// 下降状态
Vector3 pos = transform.position;
pos.y -= 55f * Time.deltaTime;
transform.position = pos;
}
else
{
// 下降结束
IsStartBondage = false;
}
}
}
}
if (!IsBondage) return;
if (BondageWarningTime > 0)
{
BondageWarningTime -= Time.deltaTime;
if (BondageWarningTime <= 0)
{
DestroyBondageWarningObj();
StartBondage();
ShowTapPrompt();
}
}
else
{
BondageTime -= Time.deltaTime;
if (BondageTime <= 0)
{
DestroyBondageWarningObj();
HideTapPrompt();
IsBondage = false;
Destroy(bondageObj);
bondageObj = null;
BondageBubbleBomb();
}
}
}
private void DestroyBondageWarningObj()
{
if (bondageWarningObj == null) return;
ParticleSystem ps = bondageWarningObj.transform.GetChild(0).GetComponent();
ps.Stop();
ps.Clear();
Destroy(bondageWarningObj);
bondageWarningObj = null;
}
///
/// 展示连续点击提示
///
private void ShowTapPrompt()
{
string key = $"{gridPosition.x}";
if (promptDic.ContainsKey(key)) return;
promptDic.Add(key, true);
GameObject prefab = Resources.Load("Prefabs/Endless/BondageBubbleTap");
tapObj = Instantiate(prefab);
tapObj.transform.SetParent(TowerPlacementGridEndless.instance.GridContainer.transform, false);
Vector3 worldPos = TowerPlacementGridEndless.instance.GetGridWorldPos(gridPosition.x, 3);
ParticleSystem ps = tapObj.transform.GetChild(0).GetComponent();
tapObj.transform.position = worldPos;
Vector3 pos = tapObj.transform.position;
pos.x += 5.8f;
pos.z += 3f;
pos.y = 15f;
tapObj.transform.position = pos;
ps?.Play();
}
private void HideTapPrompt()
{
if (tapObj != null)
{
ParticleSystem ps = tapObj.transform.GetChild(0).GetComponent();
ps?.Stop();
Destroy(tapObj);
tapObj = null;
string key = $"{gridPosition.x}";
if (promptDic.ContainsKey(key))
promptDic.Remove(key);
}
}
public void OnPressed()
{
if (!IsStartBondage || BondageWarningTime > 0) return;
++BondageTapCount;
if (BondageTapCount >= 3)
HideTapPrompt();
BondageTime -= BondageClickDecreaseTime;
}
///
/// 禁锢泡泡爆炸
///
private void BondageBubbleBomb()
{
GameObject prefab = Resources.Load("Prefabs/Endless/BondageBubbleBomb");
GameObject obj = Instantiate(prefab);
obj.transform.SetParent(TowerPlacementGridEndless.instance.GridContainer.transform, false);
obj.transform.position = transform.position;
obj.transform.GetChild(0).GetComponent().Play();
Destroy(obj, 1.2f);
}
///
/// 开始泡泡禁锢
///
private void StartBondage()
{
bombTime = 0;
BondageTapCount = 0;
isBombCompleted = false;
GameObject prefab = Resources.Load("Prefabs/Endless/BondageBubble");
bondageObj = Instantiate(prefab);
bondageObj.transform.SetParent(TowerPlacementGridEndless.instance.GridContainer.transform, false);
bondageObj.transform.position = transform.position;
Vector3 pos = bondageObj.transform.position;
pos.y += gridPosition.y == 3 ? 2f : 1f;
bondageObj.transform.position = pos;
bondageObj.transform.GetChild(0).GetComponent().Play();
}
///
/// 禁锢警告
///
///
public void BondageWarning()
{
GameObject prefab = Resources.Load("Prefabs/Endless/BondageBubbleWarning");
bondageWarningObj = Instantiate(prefab);
bondageWarningObj.transform.SetParent(TowerPlacementGridEndless.instance.GridContainer.transform, false);
bondageWarningObj.transform.position = TowerPlacementGridEndless.instance.GetGridWorldPos(gridPosition.x, gridPosition.y);
bondageWarningObj.transform.GetChild(0).GetComponent().Play();
}
///
/// 播放充能状态特效.
///
///
public void PlayEnergyEffect(bool play, bool isClose = true)
{
if (energyCtl && isClose)
energyCtl.gameObject.SetActive(!play);
else if (!isClose)
{
}
if (!opponentSide)
{
if (GameUI.instanceExists)
((TowerPlacementGrid)GameUI.instance.selfTowerPlaceArea).PlayEnergyEffect(gridPosition.x, play);
else if (EndlessGameUI.instanceExists)
((TowerPlacementGridEndless)EndlessGameUI.instance.selfTowerPlaceArea).PlayEnergyEffect(gridPosition.x, gridPosition.y, play);
}
else
((TowerPlacementGrid)OpponentMgr.instance.m_CurrentArea).PlayEnergyEffect(gridPosition.x, play);
}
///
/// 播放水精灵充能满了特效
///
///
///
public void PlayFreezeBreathEffect(bool play, bool isClose = true)
{
if (FreezeBreathCtrl && isClose)
FreezeBreathCtrl.gameObject.SetActive(!play);
if (!opponentSide)
{
if (EndlessGameUI.instanceExists)
((TowerPlacementGridEndless)EndlessGameUI.instance.selfTowerPlaceArea).PlayFreezeBreathEffect(gridPosition.x, gridPosition.y, play);
}
}
///
/// 当前是否处于攻击模式
///
public bool bInAttackMode
{
get { return m_bInAttackMode; }
// 设置是否处于攻击状态:
set
{
m_bInAttackMode = value;
CurrentTowerLevel.SetAffectorState(m_bInAttackMode, gridPosition.x);
CurrentTowerLevel.SetAttackState(value);
if (value)
{
if (opponentSide)
{
OpponentMgr.instance.SetTowerAttID(gridPosition.x, ElfId, currentLevel);
}
else
{
if (LevelManager.instanceExists)
{
LevelManager.instance.SetTowerAttID(gridPosition.x, ElfId, currentLevel);
WaveLineSelMgr.instance.attackTowerFixed(gridPosition.x);
}
else if (EndlessLevelManager.instanceExists)
{
EndlessLevelManager.instance.SetTowerAttID(gridPosition.x, ElfId, currentLevel);
EndlessWaveLineManager.instance.AttackTowerFixed(gridPosition.x, PlayWaveLineFlash);
}
}
// 处理塔位边上的界面.
OnTowerUICtrl();
}
}
}
///
/// 去掉当前Tower对应的界面数据.
///
public void DisableTowerUICtrl()
{
// 根据是否是子弹塔防来决定是否显示相应的界面
BulletUICtl buc = placementArea.GetBulletUICtl(gridPosition.x, gridPosition.y);
if ((eTowerFuntion == ETowerFuntion.BULLET) && (buc != null))
{
buc.gameObject.SetActive(false);
bulletCtl = null;
}
EnergyUICtl euc = placementArea.GetEnergyUICtl(gridPosition.x, gridPosition.y);
if ((eTowerFuntion == ETowerFuntion.ENERGY) && (euc != null))
{
// 设置数据
euc.gameObject.SetActive(false);
energyCtl = null;
}
FreezeBreath ctrl = placementArea.GetFreezeBreath(gridPosition.x, gridPosition.y);
if (eTowerFuntion == ETowerFuntion.FREEZE && ctrl != null)
{
ctrl.gameObject.SetActive(false);
ctrl = null;
}
}
public int GetTowerUICtrlProgress()
{
// 根据是否是子弹塔防来决定是否显示相应的界面
BulletUICtl buc = placementArea.GetBulletUICtl(gridPosition.x, gridPosition.y);
if ((eTowerFuntion == ETowerFuntion.BULLET) && (buc != null))
return buc.GetCtlProgress();
EnergyUICtl euc = placementArea.GetEnergyUICtl(gridPosition.x, gridPosition.y);
if ((eTowerFuntion == ETowerFuntion.ENERGY) && (euc != null))
return euc.GetCtlProgress();
FreezeBreath ctrl = placementArea.GetFreezeBreath(gridPosition.x, gridPosition.y);
if (eTowerFuntion == ETowerFuntion.FREEZE && ctrl != null)
return ctrl.CurrentProgress;
return 0;
}
public void SetTowerUICtlProcess(int pro)
{
// 根据是否是子弹塔防来决定是否显示相应的界面
BulletUICtl buc = placementArea.GetBulletUICtl(gridPosition.x, gridPosition.y);
if ((eTowerFuntion == ETowerFuntion.BULLET) && (buc != null))
{
buc.SetCtlProcess(pro);
progressOffset = pro;
return;
}
EnergyUICtl euc = placementArea.GetEnergyUICtl(gridPosition.x, gridPosition.y);
if ((eTowerFuntion == ETowerFuntion.ENERGY) && (euc != null))
{
euc.SetCtlProcess(pro);
progressOffset = pro;
if (progressOffset == 10)
progressOffset = 0;
return;
}
FreezeBreath ctrl = placementArea.GetFreezeBreath(gridPosition.x, gridPosition.y);
if (eTowerFuntion == ETowerFuntion.FREEZE && ctrl != null)
{
ctrl.SetCtrlProgress(pro);
FreezeBreathProgressOffset = pro;
if (FreezeBreathProgressOffset == 10)
FreezeBreathProgressOffset = 0;
}
}
///
/// 充能技能相关的代码开关。包括子弹充能和时间充能
///
protected void OnTowerUICtrl()
{
HandleBulletUICtrl();
HandleEnergyUICtrl();
HandleFreezeBreathCtrl();
}
private void HandleBulletUICtrl()
{
// 根据是否是子弹塔防来决定是否显示相应的界面
BulletUICtl buc = placementArea.GetBulletUICtl(gridPosition.x, gridPosition.y);
if (buc == null) return;
if ((eTowerFuntion == ETowerFuntion.BULLET) && (buc != null))
{
// 设置数据
buc.gameObject.SetActive(true);
bulletCtl = buc;
buc.ResetToMaxBullet();
}
else
{
// 清空数据
buc.gameObject.SetActive(false);
bulletCtl = null;
}
}
private void HandleEnergyUICtrl()
{
// 根据是否是能量充能来决定是否显示相应的界面.
EnergyUICtl euc = placementArea.GetEnergyUICtl(gridPosition.x, gridPosition.y);
if ((eTowerFuntion == ETowerFuntion.ENERGY) && (euc != null))
{
// 设置数据
euc.gameObject.SetActive(true);
energyCtl = euc;
euc.SetEnergyProgress(0);
}
else
{
// 清空数据
euc.gameObject.SetActive(false);
energyCtl = null;
}
}
private void HandleFreezeBreathCtrl()
{
FreezeBreath ctrl = placementArea.GetFreezeBreath(gridPosition.x, gridPosition.y);
if (eTowerFuntion == ETowerFuntion.FREEZE && ctrl != null)
{
ctrl.gameObject.SetActive(true);
FreezeBreathCtrl = ctrl;
ctrl.SetProgress(0);
}
else
{
ctrl.gameObject.SetActive(false);
FreezeBreathCtrl = null;
}
}
public void CheckCtrl()
{
if (bulletCtl != null)
{
bulletCtl.gameObject.SetActive(true);
}
if (energyCtl != null)
{
energyCtl.gameObject.SetActive(true);
}
if (FreezeBreathCtrl != null)
FreezeBreathCtrl.gameObject.SetActive(true);
}
///
/// This function is called when the behaviour becomes disabled or inactive.
///
void OnDisable()
{
if (bulletCtl != null)
{
bulletCtl.gameObject.SetActive(false);
}
if (energyCtl != null)
{
energyCtl.gameObject.SetActive(false);
}
if (FreezeBreathCtrl != null)
FreezeBreathCtrl.gameObject.SetActive(false);
}
///
/// 升级当前塔防的局内等级,需要播放相关的特效
///
public void upGradeInSceneTL()
{
Debug.Log("Upgrade Tower name is:" + name);
// 播放相关的特效
CurrentTowerLevel.PlayUpGradeEffect();
}
///
/// Gets the first level tower ghost prefab
///
public TowerPlacementGhost towerGhostPrefab
{
get { return towerLevel.towerGhostPrefab; }
}
///
/// Gets the grid position for this tower on the
///
public IntVector2 gridPosition { get; private set; }
///
/// The placement area we've been built on
///
public IPlacementArea placementArea { get; private set; }
///
/// The event that fires off when a player deletes a tower
///
public Action towerDeleted;
///
/// The event that fires off when a tower has been destroyed
///
public Action towerDestroyed;
///
/// Provide the tower with data to initialize with
///
/// The placement area configuration
/// The destination position
public virtual void Initialize(IPlacementArea targetArea, IntVector2 destination, int lvl = 0)
{
placementArea = targetArea;
gridPosition = destination;
if (targetArea != null)
{
transform.position = placementArea.GridToWorld(destination, dimensions);
transform.rotation = placementArea.transform.rotation;
targetArea.Occupy(destination, dimensions);
}
SetLevel(lvl);
if (LevelManager.instanceExists)
LevelManager.instance.levelStateChanged += OnLevelStateChanged;
else if (EndlessLevelManager.instanceExists)
EndlessLevelManager.instance.LevelStateChanged += OnLevelStateChanged;
// 查找Targetter:
Targetter target = GetComponentInChildren();
if (target)
target.bOpponent = opponentSide;
else
Debug.Log("在当前的Tower中找不到Targetter.");
}
///
/// 当前的Tower是显示还是隐藏,用于减少游戏内Tower创建和删除对应的一系列数据操作
///
///
public void showTower(bool vis)
{
if (vis)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}
///
/// Kills this tower
///
public void KillTower()
{
// Invoke base kill method
Kill();
}
///
/// Used to (try to) upgrade the tower data
///
public virtual bool UpgradeTower()
{
if (IsMaxLevel)
{
return false;
}
SetLevel(currentLevel + 1);
return true;
}
///
/// A method for downgrading tower
///
///
/// false if tower is at lowest level
///
public virtual bool DowngradeTower()
{
if (currentLevel == 0)
{
return false;
}
SetLevel(currentLevel - 1);
return true;
}
///
/// Used to set the tower to any valid level
///
///
/// The level to upgrade the tower to
///
///
/// True if successful
///
public virtual bool UpgradeTowerToLevel(int level)
{
if (level < 0 || IsMaxLevel || level >= ElfUpgradeData.MaxTowerLevel) return false;
SetLevel(level);
return true;
}
public void Sell()
{
Remove();
}
///
/// Removes tower from placement area and destroys it
///
public override void Remove()
{
base.Remove();
attackRise = 0.0f;
placementArea.Clear(gridPosition, dimensions);
Destroy(gameObject);
}
///
/// unsubsribe when necessary
///
protected virtual void OnDestroy()
{
if (LevelManager.instanceExists)
{
LevelManager.instance.levelStateChanged += OnLevelStateChanged;
}
else if (EndlessLevelManager.instanceExists)
EndlessLevelManager.instance.LevelStateChanged += OnLevelStateChanged;
}
///
/// Cache and update oftenly used data
///
protected void SetLevel(int level)
{
if (level < 0 || level >= ElfUpgradeData.MaxTowerLevel) return;
currentLevel = level;
if (CurrentTowerLevel != null)
Destroy(CurrentTowerLevel.gameObject);
CurrentTowerLevel = Instantiate(towerLevel, transform);
CurrentTowerLevel.Initialize(this, enemyLayerMask, configuration.alignmentProvider);
CurrentTowerLevel.SetShowLevel(level + 1);
//if(gridPosition.y>=2)
{
//Debug.Log("上阵状态,设置缩放");
CurrentTowerLevel.SetScale(level + 1);
}
// disable affectors
LevelState levelState = LevelState.Intro;
if (LevelManager.instanceExists)
levelState = LevelManager.instance.levelState;
else if (EndlessLevelManager.instanceExists)
levelState = EndlessLevelManager.instance.EndlessLeveltate;
bool initialise = levelState == LevelState.AllEnemiesSpawned || levelState == LevelState.SpawningEnemies;
initialise = false;
CurrentTowerLevel.SetAffectorState(initialise, gridPosition.x);
}
///
/// Intiailises affectors based on the level state
///
protected virtual void OnLevelStateChanged(LevelState previous, LevelState current)
{
bool initialise = current == LevelState.AllEnemiesSpawned || current == LevelState.SpawningEnemies;
initialise = false;
CurrentTowerLevel.SetAffectorState(bInAttackMode, gridPosition.x);
}
}
}