using TowerDefense.UI.HUD; using Core.Utilities; using System.Collections.Generic; using UnityEngine; using TowerDefense.Agents; using TowerDefense.Level; /** * 泡泡炸弹 * @Author: chenxin * @Date: 2020-11-02 17:09:03 */ namespace KTGMGemClient { /// /// 泡泡炸弹配置数据 /// public class BubbleBombConfig { public BubbleBombAgent Agent { get; set; } public GameObject obj { get; set; } /// /// 需要被攻击的次数,攻击 * 次炸弹才会被销毁 /// public int NeedAttackCount { get; set; } /// /// 已经被攻击的次数 /// public int AttackCount { get; set; } /// /// 是否抵达基地,抵达基地后,不能继续被塔攻击 /// public bool IsArrived { get; set; } /// /// 出生点坐标 /// public Vector3 StartPosition { get; set; } /// /// 目的地坐标,也就是基地位置 /// public Vector3 TargetPosition { get; set; } /// /// 是否被攻击打死,被塔打死或者被火技能宝石打死(火技能宝石是直接秒杀炸弹的) /// public bool IsAttackDeath { get; set; } /// /// 销毁时间,被塔打死或者攻击玩家基地后,时间减为0之后销毁 /// public float DestroyTime { get; set; } /// /// 移动速度 /// public float MoveSpeed { get; set; } /// /// 是否被眩晕 /// public bool IsDizzinessed { get; set; } /// /// 眩晕时间 /// public float DizzinessTime { get; set; } /// /// 是否是攻击状态,延时取摧毁基地 /// public bool IsAttack { get; set; } /// /// 延迟产生伤害时间 /// public float AttackTime { get; set; } } public class BossSkillBubbleBomb : EndlessBossSkill { public BossSkillBubbleBomb(boss_skill param) : base(param) { } /// /// 被攻击的次数 /// protected int beAttackedCount; protected string prefabPath = "Prefabs/Endless/BubbleBomb"; /// /// 所有存在于场景中的泡泡炸弹 /// protected List bubbleBombList; /// /// 泡泡炸弹对象池 /// protected List bubbleBombPool; protected int capacity = 10; private int getCount; private int recycleCount; /// /// 释放技能 /// public override void ReleaseSkill() { base.ReleaseSkill(); Debug.Log("--------------------- 泡泡炸弹释放 ---------------------"); SpawnBubbleBomb(); } /// /// 在场景中生成泡泡炸弹 /// protected void SpawnBubbleBomb() { switch ((EndlessBossSkillUseTarget)SkillData.target[0]) { case EndlessBossSkillUseTarget.Tower: Debug.Log("--------------------- WTF 不支持哦~ ---------------------"); break; case EndlessBossSkillUseTarget.Agent: Debug.Log("--------------------- WTF 不支持哦~ ---------------------"); break; case EndlessBossSkillUseTarget.Tunel: SpawnOnTunel(); break; } } /// /// 在赛道上生成炸弹 /// protected void SpawnOnTunel() { List tunelIdList = GetTunelList(); for (int i = 0; i < tunelIdList.Count; ++i) { GameObject obj = GetBubbleBomb(); BubbleBombAgent bubbleBomb = obj.GetComponent(); // 分配唯一id bubbleBomb.Id = GameUtils.GetId(); bubbleBomb.waveLineID = tunelIdList[i] - 1; bubbleBomb.AgentType = SpawnAgentType.BubbleBomb; bubbleBomb.opponentAgent = false; bubbleBomb.Reset(); bubbleBomb.Initialize(); // 出生位置 Vector3 spawnPosition = EndlessLevelManager.instance.GetTunelWorldPosition(tunelIdList[i], (EndlessBossSkillTunelType)SkillData.target[1]); obj.transform.position = spawnPosition; bubbleBomb.PlayNormalEffect(); AgentInsManager.instance.addAgent(bubbleBomb); BubbleBombConfig config = new BubbleBombConfig(); config.Agent = bubbleBomb; config.obj = obj; config.NeedAttackCount = (int)SkillData.effect[0]; config.StartPosition = spawnPosition; config.TargetPosition = EndlessLevelManager.instance.GetHomeBasePosition(tunelIdList[i]); config.DestroyTime = bubbleBomb.GetExplodeTime(); config.MoveSpeed = SkillData.effect[1]; bubbleBombList.Add(config); } } public override void Reset() { base.Reset(); beAttackedCount = 0; ClearBubbleBomb(); } public override void Clear() { base.Clear(); ClearBubbleBomb(); ClearBubbleBombPool(); } /// /// 清理在场景中的所有炸弹 /// private void ClearBubbleBomb() { for (int i = 0; i < bubbleBombList.Count; ++i) { bubbleBombList[i].Agent.Reset(); bubbleBombList[i].Agent.StopNormalEffect(); bubbleBombList[i].Agent.StopExplodeEffect(); AgentInsManager.instance.removeAgent(bubbleBombList[i].Agent); RecycleBubbleBomb(bubbleBombList[i].obj); } bubbleBombList.Clear(); } public override void Init() { base.Init(); Debug.Log("--------------------- 泡泡炸弹技能初始化 ---------------------"); bubbleBombList = new List(); bubbleBombPool = new List(); GameObject prefab = Resources.Load(prefabPath); for (int i = 0; i < capacity; ++i) { GameObject obj = GameObject.Instantiate(prefab); obj.SetActive(false); bubbleBombPool.Add(obj); } } /// /// 从对象池中获取一个炸弹 /// protected GameObject GetBubbleBomb() { GameObject ret; if (bubbleBombPool.Count > 0) { ret = bubbleBombPool[0]; bubbleBombPool.Remove(bubbleBombPool[0]); } else { GameObject prefab = Resources.Load(prefabPath); ret = GameObject.Instantiate(prefab); } ret.SetActive(true); return ret; } /// /// 回收泡泡炸弹 /// /// protected void RecycleBubbleBomb(GameObject obj) { if (obj != null) { obj.SetActive(false); bubbleBombPool.Add(obj); } } /// /// 清空泡泡炸弹对象池 /// protected void ClearBubbleBombPool() { while (bubbleBombPool.Count > 0) { GameObject obj = bubbleBombPool[0]; bubbleBombPool.Remove(obj); GameObject.Destroy(obj); } } protected override void AddEvent() { EventCenter.Ins.Add((int)KTGMGemClient.EventType.EndlessBossSkillBubbleBombGetHit, OnGetHit); EventCenter.Ins.Add((int)KTGMGemClient.EventType.EndlessFireSkillKillBubbleBomb, OnFireSkillKillBubbleBomb); EventCenter.Ins.Add((int)KTGMGemClient.EventType.EndlessBubbleBombBeDizzinessed, OnBubbleBombBeDizzinessed); } protected override void RemoveEvent() { EventCenter.Ins.Remove((int)KTGMGemClient.EventType.EndlessBossSkillBubbleBombGetHit, OnGetHit); EventCenter.Ins.Remove((int)KTGMGemClient.EventType.EndlessFireSkillKillBubbleBomb, OnFireSkillKillBubbleBomb); EventCenter.Ins.Remove((int)KTGMGemClient.EventType.EndlessBubbleBombBeDizzinessed, OnBubbleBombBeDizzinessed); } /// /// 泡泡炸弹受到一次攻击 /// /// 炸弹代理的唯一id private void OnGetHit(int id) { for (int i = 0; i < bubbleBombList.Count; ++i) { if (bubbleBombList[i].Agent.Id == id) { BubbleBombConfig config = bubbleBombList[i]; // 攻击次数够了被打死了 或者 达到基地了 if (config.Agent.bInDeathState) return; ++config.AttackCount; Debug.Log($"--------------------- BubbleBombAgent Id: {id}, AttackCount:{config.AttackCount} ---------------------"); if (config.AttackCount >= config.NeedAttackCount) AgentDead(config); break; } } } /// /// 泡泡炸弹被火技能烧死 /// /// private void OnFireSkillKillBubbleBomb(int id) { for (int i = 0; i < bubbleBombList.Count; ++i) { if (bubbleBombList[i].Agent.Id == id) { BubbleBombConfig config = bubbleBombList[i]; if (config.Agent.bInDeathState) return; AgentDead(config); break; } } } /// /// 泡泡炸弹被眩晕 /// /// /// 持续时间 private void OnBubbleBombBeDizzinessed(int id, int duration) { for (int i = 0; i < bubbleBombList.Count; ++i) { if (bubbleBombList[i].Agent.Id == id) { BubbleBombConfig config = bubbleBombList[i]; if (config.Agent.bInDeathState) return; config.IsDizzinessed = true; config.Agent.CanMove = false; // 直接覆盖持续时间 config.DizzinessTime = duration / 1000f; break; } } } /// /// 炸弹突然去世 /// /// private void AgentDead(BubbleBombConfig config) { config.Agent.StopNormalEffect(); config.Agent.PlayExplodeEffect(); AgentInsManager.instance.removeAgent(config.Agent); config.Agent.bInDeathState = true; config.IsAttackDeath = true; } /// /// 炸弹到达基地 /// /// private void AgentArrived(BubbleBombConfig config) { config.IsArrived = true; config.Agent.StopNormalEffect(); config.Agent.PlayExplodeEffect(); AgentInsManager.instance.removeAgent(config.Agent); config.Agent.bInDeathState = true; } public override void Update(float deltaTime) { base.Update(deltaTime); for (int i = 0; i < bubbleBombList.Count; ++i) { BubbleBombConfig config = bubbleBombList[i]; // 泡泡炸弹已经触发了攻击,延时一会过后掉爱心 if (config.IsAttack) { config.AttackTime -= deltaTime; if (config.AttackTime <= 0) { EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.EndlessLoseHeart, 3); config.IsAttack = false; } } // 被打死了 或 到达基地 if (config.IsAttackDeath || config.IsArrived) { config.DestroyTime -= deltaTime; if (config.DestroyTime <= 0) { bubbleBombList[i].Agent.Reset(); RecycleBubbleBomb(bubbleBombList[i].obj); AgentInsManager.instance.removeAgent(bubbleBombList[i].Agent); bubbleBombList.Remove(bubbleBombList[i]); --i; } continue; } // 处理被眩晕的 if (config.IsDizzinessed) { config.DizzinessTime -= deltaTime; if (config.DizzinessTime <= 0) { // 解除眩晕 config.IsDizzinessed = false; config.Agent.CanMove = true; } else continue; } // 更新移动 if (config.Agent != null && !config.Agent.bInDeathState && config.Agent.CanMove) { Vector3 pos = config.obj.transform.position; pos.z -= deltaTime * config.MoveSpeed; config.obj.transform.position = pos; if (pos.z <= config.TargetPosition.z) { AgentArrived(config); config.IsAttack = true; config.AttackTime = 0.65f; } } } } } }