using System; using ActionGameFramework.Health; using Core.Utilities; using TowerDefense.Level; using TowerDefense.Targetting; using TowerDefense.Towers.Placement; using TowerDefense.UI.HUD; using UnityEngine; namespace TowerDefense.Towers { public enum EFeatureTower { NULL, GrowUp, CopyCat, LightTower, Skill_Fire, Skill_Bomb, END } public enum ETowerFuntion { NULL, BULLET, // 子弹塔 ENERGY, // 能量充能. END } /// /// Common functionality for all types of towers /// public class Tower : Targetable { public readonly float INSCENE_TU_DAMAGE = 30f; public static readonly int MAX_LEVEL = 4; /// /// 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; /// /// 当前塔防对应的MonsterMaterial,自身和对方显示不同的Mat. /// public Material materialMonsterSelf; public Material materialMonsterOppo; /// /// 当前塔防对应的攻击和等待Mat. /// public Material materialTowerAttackSelf; public Material materialTowerWaitSelf; public Material materialTowerAttackOppo; public Material materialTowerWaitOppo; /// /// 0 空状态 1 等待状态 2 攻击状态. /// protected int curActionState = 0; /// /// 塔防对应的充能状态. /// public ETowerFuntion eTowerFuntion = ETowerFuntion.NULL; public BulletUICtl bulletCtl = null; public EnergyUICtl energyCtl = null; /// /// The tower levels associated with this tower /// public TowerLevel[] levels; /// /// 当前塔防对应的AttributeID. /// public int attributeId; /// /// 当前的Tower在游戏内UI界面上用到的Image数据,再以后应该是直接在表格内配置才合适 /// public Sprite uiImage; /// /// 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; /// /// 精英怪和Boss双倍伤害. /// public bool bDoubleHitElit = false; /// /// Reference to the data of the current level /// public TowerLevel currentTowerLevel { get; protected set; } /// /// 攻击增加 /// public float attackRise { get; set; } /// /// 塔防数据的局内升级 /// public int inSceneTowerLevel { get; set; } /// /// Gets whether the tower can level up anymore /// public bool isAtMaxLevel { get { return currentLevel == levels.Length - 1; } } public void setTowerState(bool attack) { if (!materialTowerAttackSelf) return; if( opponentSide) { if (attack && (this.curActionState != 2)) { currentTowerLevel.SetTowerMonsterMat(materialTowerAttackOppo); this.curActionState = 2; } if ((!attack) && (this.curActionState != 1)) { currentTowerLevel.SetTowerMonsterMat( materialTowerWaitOppo ); this.curActionState = 1; } } else { if (attack && (this.curActionState != 2)) { currentTowerLevel.SetTowerMonsterMat(materialTowerAttackSelf); this.curActionState = 2; } if ((!attack) && (this.curActionState != 1)) { currentTowerLevel.SetTowerMonsterMat(materialTowerWaitSelf); this.curActionState = 1; } } } /// /// 是否是对手塔防 /// public bool opponentSide { get; set; } /// /// 当前是否处于攻击模式 /// public bool bInAttackMode { get { return this.m_bInAttackMode; } // 设置是否处于攻击状态: set { m_bInAttackMode = value; currentTowerLevel.SetAffectorState(m_bInAttackMode, gridPosition.x); if (value) { if (opponentSide) currentTowerLevel.SetTowerMonsterMat(materialMonsterOppo); else currentTowerLevel.SetTowerMonsterMat(materialMonsterSelf); // 处理Tower this.setTowerState(false); if (opponentSide) { OpponentMgr.instance.SetTowerAttID(gridPosition.x, attributeId, this.currentLevel); } else { if (LevelManager.instanceExists) { LevelManager.instance.SetTowerAttID(gridPosition.x, attributeId, this.currentLevel); WaveLineSelMgr.instance.attackTowerFixed(gridPosition.x); } else if (EndlessLevelManager.instanceExists) { EndlessLevelManager.instance.SetTowerAttID(gridPosition.x, attributeId, this.currentLevel); EndlessWaveLineManager.instance.AttackTowerFixed(gridPosition.x); } } // 处理塔位边上的界面. OnTowerUICtrl(); } } } protected void OnTowerUICtrl() { // // 根据是否是子弹塔防来决定是否显示相应的界面 BulletUICtl buc = this.placementArea.GetBulletUICtl(gridPosition.x); if ((this.eTowerFuntion == ETowerFuntion.BULLET) && (buc != null)) { // 设置数据 buc.gameObject.SetActive(true); this.bulletCtl = buc; buc.resetToMaxBullet(); } else { // 清空数据 buc.gameObject.SetActive(false); this.bulletCtl = null; } // 根据是否是能量充能来决定是否显示相应的界面. EnergyUICtl euc = placementArea.GetEnergyUICtl(gridPosition.x); if( (eTowerFuntion == ETowerFuntion.ENERGY) &&(euc != null )) { // 设置数据 euc.gameObject.SetActive(true); this.energyCtl = euc; euc.SetEnergyProgress(0); } else { // 清空数据 euc.gameObject.SetActive(false); this.energyCtl = null; } } /// /// 初始化当前塔防的局内升级,lvl从1开始. /// /// public void initInSceneTowerLevel(int lvl) { inSceneTowerLevel = lvl; if (lvl <= 1) { ResetInSceneTowerLevel(); return; } // 设置攻击数据的加强,暂时是测试数据,后面需要读取表格数据处理: float damageAdd = (inSceneTowerLevel - 1) * this.INSCENE_TU_DAMAGE; for (int ti = 0; ti < this.levels.Length; ti++) { if (levels[ti].levelDamager) { levels[ti].levelDamager.doubleHit = bDoubleHitElit; levels[ti].levelDamager.inSceneUpGradeDamage = damageAdd; } } } protected void ResetInSceneTowerLevel() { for (int ti = 0; ti < this.levels.Length; ti++) { if (levels[ti].levelDamager) { levels[ti].levelDamager.inSceneUpGradeDamage = 0; levels[ti].levelDamager.doubleHit = bDoubleHitElit; } } return; } /// /// 升级当前塔防的局内等级,需要播放相关的特效 /// public void upGradeInSceneTL() { inSceneTowerLevel++; // 设置攻击数据的加强,暂时是测试数据,后面需要读取表格数据处理: float damageAdd = inSceneTowerLevel * this.INSCENE_TU_DAMAGE; for (int ti = 0; ti < this.levels.Length; ti++) { if (levels[ti].levelDamager) { levels[ti].levelDamager.inSceneUpGradeDamage = damageAdd; levels[ti].levelDamager.towerName = name; levels[ti].levelDamager.bSet = true; } } Debug.Log("Upgrade Tower name is:" + name); // 播放相关的特效 currentTowerLevel.PlayUpGradeEffect(); } /// /// Gets the first level tower ghost prefab /// public TowerPlacementGhost towerGhostPrefab { get { return levels[currentLevel].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 purchase cost of the tower /// public int purchaseCost { get { return levels[0].cost; } } /// /// 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 = this.GetComponentInChildren(); if (target) { target.bOpponent = this.opponentSide; } else Debug.Log("在当前的Tower中找不到Targetter."); // // 初始化当前的局内Tower等级数据 this.initInSceneTowerLevel(SceneTowerLvl.getInSceneTowerLvl(this.towerName)); } /// /// Provides information on the cost to upgrade /// /// Returns -1 if the towers is already at max level, other returns the cost to upgrade public int GetCostForNextLevel() { if (isAtMaxLevel) { return -1; } return levels[currentLevel + 1].cost; } /// /// 当前的Tower是显示还是隐藏,用于减少游戏内Tower创建和删除对应的一系列数据操作 /// /// public void showTower(bool vis) { if (vis) { this.gameObject.SetActive(true); } else { this.gameObject.SetActive(false); } } /// /// Kills this tower /// public void KillTower() { // Invoke base kill method Kill(); } /// /// Provides the value recived for selling this tower /// /// A sell value of the tower public int GetSellLevel() { return GetSellLevel(currentLevel); } /// /// Provides the value recived for selling this tower of a particular level /// /// Level of tower /// A sell value of the tower public int GetSellLevel(int level) { // sell for full price if waves haven't started yet if (LevelManager.instanceExists && LevelManager.instance.levelState == LevelState.Building || EndlessLevelManager.instanceExists && EndlessLevelManager.instance.EndlessLeveltate == LevelState.Building) { int cost = 0; for (int i = 0; i <= level; i++) { cost += levels[i].cost; } return cost; } return levels[currentLevel].sell; } /// /// Used to (try to) upgrade the tower data /// public virtual bool UpgradeTower() { if (isAtMaxLevel) { 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 || isAtMaxLevel || level >= levels.Length) { return false; } SetLevel(level); return true; } public void Sell() { Remove(); } /// /// Removes tower from placement area and destroys it /// public override void Remove() { base.Remove(); // 清空局内升级数据: ResetInSceneTowerLevel(); 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 /// public void SetLevel(int level) { if (level < 0 || level >= levels.Length) { return; } currentLevel = level; if (currentTowerLevel != null) { Destroy(currentTowerLevel.gameObject); } // instantiate the visual representation currentTowerLevel = Instantiate(levels[currentLevel], transform); // initialize TowerLevel currentTowerLevel.Initialize(this, enemyLayerMask, configuration.alignmentProvider); // health data ScaleHealth(); // // 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); } /// /// Scales the health based on the previous health /// Requires override when the rules for scaling health on upgrade changes /// protected virtual void ScaleHealth() { configuration.SetMaxHealth(currentTowerLevel.maxHealth); if (currentLevel == 0) { configuration.SetHealth(currentTowerLevel.maxHealth); } else { int currentHealth = Mathf.FloorToInt(configuration.normalisedHealth * currentTowerLevel.maxHealth); configuration.SetHealth(currentHealth); } } /// /// 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(initialise); currentTowerLevel.SetAffectorState(bInAttackMode, gridPosition.x); } } }