```
chore(bridge): 移除桥接包中的提交记录和 Git 属性配置 移除了 .codely-bridge-commit 文件中存储的提交哈希 移除了 .gitattributes 文件中的行结束符配置规则 ```
This commit is contained in:
1 parent
8534d974a9
commit
8c0832e7ca
370 files changed
+418
-129914
No files matched your search
@@ -1,41 +1,42 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家技能系统(召唤师技能)
|
||||
/// 管理技能释放和冷却
|
||||
/// 依据 PlayerData 中 equippedSummonerSkills 动态初始化图标与释放相匹配的技能效果
|
||||
/// </summary>
|
||||
public class PlayerSkillSystem : MonoBehaviour
|
||||
{
|
||||
public static PlayerSkillSystem Instance { get; private set; }
|
||||
|
||||
[Header("战术增益加成倍率")]
|
||||
public float cooldownMultiplier = 1f; // 冷却缩减倍率 (如 0.9 = CD 缩减 10%)
|
||||
public float powerMultiplier = 1f; // 威力加成倍率 (如 1.15 = 效果提升 15%)
|
||||
public float cooldownMultiplier = 1f; // 冷却缩减倍率
|
||||
public float powerMultiplier = 1f; // 威力加成倍率
|
||||
|
||||
[Header("技能1:群体治疗")]
|
||||
[Header("技能1组件绑定")]
|
||||
public Button skill1Button;
|
||||
public Image skill1CooldownMask;
|
||||
public Text skill1CooldownText;
|
||||
public float skill1Cooldown = 20f;
|
||||
public float skill1HealAmount = 100f;
|
||||
public string skill1CurrentName = "神圣赞歌";
|
||||
public float skill1Cooldown = 25f;
|
||||
private float skill1RemainingCooldown = 0f;
|
||||
|
||||
[Header("技能1特效配置")]
|
||||
public GameObject cureBallPrefab; // 飞球预制体 (Assets/Prefabs/特效/飞球/cureBall.prefab)
|
||||
public GameObject healNovaPrefab; // 治疗冲击波预制体 (Assets/TJGeneratorLibEffects/Prefabs/Interactive/Healing/HealNova.prefab)
|
||||
public Transform castStartTransform; // 技能施放起点 (如未指定默认摄像机下方或召唤师位置)
|
||||
public Vector3 castTargetPosition = new Vector3(0f, 0.1f, -9f); // 我方阵地中心落地点
|
||||
|
||||
[Header("技能2:全屏AOE")]
|
||||
[Header("技能2组件绑定")]
|
||||
public Button skill2Button;
|
||||
public Image skill2CooldownMask;
|
||||
public Text skill2CooldownText;
|
||||
public string skill2CurrentName = "天雷狂轰";
|
||||
public float skill2Cooldown = 20f;
|
||||
public float skill2Damage = 80f;
|
||||
private float skill2RemainingCooldown = 0f;
|
||||
|
||||
[Header("技能2特效配置")]
|
||||
public GameObject lightningStrikePrefab; // 落雷击中特效 (Assets/TJGeneratorLibEffects/Prefabs/Combat/Explosions/LightningExplosion/LightningExplosionBlue.prefab)
|
||||
public GameObject lightningNovaPrefab; // 雷暴全屏光环特效 (Assets/TJGeneratorLibEffects/Prefabs/Combat/Nova/Lightning/NovaLightningBlue.prefab)
|
||||
[Header("通用特效预制体引用")]
|
||||
public GameObject cureBallPrefab; // 飞球预制体 (Assets/Prefabs/特效/飞球/cureBall.prefab)
|
||||
public GameObject healNovaPrefab; // 治疗冲击波 (Assets/TJGeneratorLibEffects/Prefabs/Interactive/Healing/HealNova.prefab)
|
||||
public GameObject lightningStrikePrefab; // 落雷击中 (Assets/TJGeneratorLibEffects/Prefabs/Combat/Explosions/LightningExplosion/LightningExplosionBlue.prefab)
|
||||
public GameObject lightningNovaPrefab; // 雷暴全屏光环 (Assets/TJGeneratorLibEffects/Prefabs/Combat/Nova/Lightning/NovaLightningBlue.prefab)
|
||||
public Transform castStartTransform; // 施法起始点
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -44,20 +45,18 @@ public class PlayerSkillSystem : MonoBehaviour
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 自动从场景或父节点绑定技能按钮与图标引用
|
||||
EnsureSkillUIReferences();
|
||||
|
||||
// 从 PlayerData 加载玩家装备的 2 个召唤师技能图标
|
||||
LoadEquippedSkillIcons();
|
||||
|
||||
// 绑定按钮点击事件
|
||||
if (skill1Button != null)
|
||||
{
|
||||
skill1Button.onClick.RemoveAllListeners();
|
||||
skill1Button.onClick.AddListener(UseSkill1);
|
||||
}
|
||||
|
||||
if (skill2Button != null)
|
||||
{
|
||||
skill2Button.onClick.RemoveAllListeners();
|
||||
skill2Button.onClick.AddListener(UseSkill2);
|
||||
}
|
||||
}
|
||||
@@ -70,18 +69,44 @@ public class PlayerSkillSystem : MonoBehaviour
|
||||
var skillsPanel = canvas.transform.Find("BottomUI/SkillsPanel");
|
||||
if (skillsPanel == null) return;
|
||||
|
||||
if (skill1Button == null && skillsPanel.childCount > 0)
|
||||
if (skillsPanel.childCount > 0)
|
||||
{
|
||||
var item1 = skillsPanel.GetChild(0);
|
||||
skill1Button = item1.GetComponent<Button>();
|
||||
if (skill1Button == null) skill1Button = item1.gameObject.AddComponent<Button>();
|
||||
if (skill1Button == null)
|
||||
{
|
||||
skill1Button = item1.GetComponent<Button>();
|
||||
if (skill1Button == null) skill1Button = item1.gameObject.AddComponent<Button>();
|
||||
}
|
||||
if (skill1CooldownMask == null)
|
||||
{
|
||||
var maskTr = item1.Find("CooldownMask");
|
||||
if (maskTr != null) skill1CooldownMask = maskTr.GetComponent<Image>();
|
||||
}
|
||||
if (skill1CooldownText == null)
|
||||
{
|
||||
var textTr = item1.Find("CooldownText");
|
||||
if (textTr != null) skill1CooldownText = textTr.GetComponent<Text>();
|
||||
}
|
||||
}
|
||||
|
||||
if (skill2Button == null && skillsPanel.childCount > 1)
|
||||
if (skillsPanel.childCount > 1)
|
||||
{
|
||||
var item2 = skillsPanel.GetChild(1);
|
||||
skill2Button = item2.GetComponent<Button>();
|
||||
if (skill2Button == null) skill2Button = item2.gameObject.AddComponent<Button>();
|
||||
if (skill2Button == null)
|
||||
{
|
||||
skill2Button = item2.GetComponent<Button>();
|
||||
if (skill2Button == null) skill2Button = item2.gameObject.AddComponent<Button>();
|
||||
}
|
||||
if (skill2CooldownMask == null)
|
||||
{
|
||||
var maskTr = item2.Find("CooldownMask");
|
||||
if (maskTr != null) skill2CooldownMask = maskTr.GetComponent<Image>();
|
||||
}
|
||||
if (skill2CooldownText == null)
|
||||
{
|
||||
var textTr = item2.Find("CooldownText");
|
||||
if (textTr != null) skill2CooldownText = textTr.GetComponent<Text>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,17 +115,36 @@ public class PlayerSkillSystem : MonoBehaviour
|
||||
/// </summary>
|
||||
public void LoadEquippedSkillIcons()
|
||||
{
|
||||
string skill1Name = "神圣赞歌";
|
||||
string skill2Name = "陨石轰炸";
|
||||
skill1CurrentName = "神圣赞歌";
|
||||
skill2CurrentName = "天雷狂轰";
|
||||
|
||||
if (PlayerDataManager.Instance != null && PlayerDataManager.Instance.equippedSummonerSkills != null && PlayerDataManager.Instance.equippedSummonerSkills.Length >= 2)
|
||||
{
|
||||
skill1Name = PlayerDataManager.Instance.equippedSummonerSkills[0];
|
||||
skill2Name = PlayerDataManager.Instance.equippedSummonerSkills[1];
|
||||
skill1CurrentName = PlayerDataManager.Instance.equippedSummonerSkills[0];
|
||||
skill2CurrentName = PlayerDataManager.Instance.equippedSummonerSkills[1];
|
||||
}
|
||||
|
||||
SetSkillIcon(skill1Button, skill1Name);
|
||||
SetSkillIcon(skill2Button, skill2Name);
|
||||
SetSkillIcon(skill1Button, skill1CurrentName);
|
||||
SetSkillIcon(skill2Button, skill2CurrentName);
|
||||
|
||||
skill1Cooldown = GetSkillBaseCooldown(skill1CurrentName);
|
||||
skill2Cooldown = GetSkillBaseCooldown(skill2CurrentName);
|
||||
}
|
||||
|
||||
private float GetSkillBaseCooldown(string skillName)
|
||||
{
|
||||
return skillName switch
|
||||
{
|
||||
"神圣赞歌" => 25f,
|
||||
"天雷狂轰" => 20f,
|
||||
"陨石轰炸" => 22f,
|
||||
"绝对零度" => 30f,
|
||||
"斩杀风暴" => 25f,
|
||||
"庇护圣盾" => 24f,
|
||||
"虚弱诅咒" => 20f,
|
||||
"岩石傀儡" => 28f,
|
||||
_ => 20f
|
||||
};
|
||||
}
|
||||
|
||||
private void SetSkillIcon(Button skillBtn, string skillName)
|
||||
@@ -134,13 +178,18 @@ public class PlayerSkillSystem : MonoBehaviour
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 更新技能1冷却
|
||||
EnsureSkillUIReferences();
|
||||
|
||||
// 技能 1 冷却更新
|
||||
float totalCD1 = skill1Cooldown * cooldownMultiplier;
|
||||
if (skill1RemainingCooldown > 0)
|
||||
{
|
||||
skill1RemainingCooldown -= Time.deltaTime;
|
||||
if (skill1Button != null)
|
||||
if (skill1Button != null) skill1Button.interactable = false;
|
||||
if (skill1CooldownMask != null)
|
||||
{
|
||||
skill1Button.interactable = false;
|
||||
skill1CooldownMask.gameObject.SetActive(true);
|
||||
skill1CooldownMask.fillAmount = totalCD1 > 0 ? Mathf.Clamp01(skill1RemainingCooldown / totalCD1) : 0f;
|
||||
}
|
||||
if (skill1CooldownText != null)
|
||||
{
|
||||
@@ -150,23 +199,21 @@ public class PlayerSkillSystem : MonoBehaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
if (skill1Button != null)
|
||||
{
|
||||
skill1Button.interactable = true;
|
||||
}
|
||||
if (skill1CooldownText != null)
|
||||
{
|
||||
skill1CooldownText.gameObject.SetActive(false);
|
||||
}
|
||||
if (skill1Button != null) skill1Button.interactable = true;
|
||||
if (skill1CooldownMask != null) skill1CooldownMask.gameObject.SetActive(false);
|
||||
if (skill1CooldownText != null) skill1CooldownText.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// 更新技能2冷却
|
||||
// 技能 2 冷却更新
|
||||
float totalCD2 = skill2Cooldown * cooldownMultiplier;
|
||||
if (skill2RemainingCooldown > 0)
|
||||
{
|
||||
skill2RemainingCooldown -= Time.deltaTime;
|
||||
if (skill2Button != null)
|
||||
if (skill2Button != null) skill2Button.interactable = false;
|
||||
if (skill2CooldownMask != null)
|
||||
{
|
||||
skill2Button.interactable = false;
|
||||
skill2CooldownMask.gameObject.SetActive(true);
|
||||
skill2CooldownMask.fillAmount = totalCD2 > 0 ? Mathf.Clamp01(skill2RemainingCooldown / totalCD2) : 0f;
|
||||
}
|
||||
if (skill2CooldownText != null)
|
||||
{
|
||||
@@ -176,83 +223,355 @@ public class PlayerSkillSystem : MonoBehaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
if (skill2Button != null)
|
||||
{
|
||||
skill2Button.interactable = true;
|
||||
}
|
||||
if (skill2CooldownText != null)
|
||||
{
|
||||
skill2CooldownText.gameObject.SetActive(false);
|
||||
}
|
||||
if (skill2Button != null) skill2Button.interactable = true;
|
||||
if (skill2CooldownMask != null) skill2CooldownMask.gameObject.SetActive(false);
|
||||
if (skill2CooldownText != null) skill2CooldownText.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用技能1:群体治疗
|
||||
/// 触发技能1
|
||||
/// </summary>
|
||||
public void UseSkill1()
|
||||
{
|
||||
if (skill1RemainingCooldown > 0)
|
||||
if (skill1RemainingCooldown > 0) return;
|
||||
|
||||
ExecuteSkillByName(skill1CurrentName);
|
||||
skill1RemainingCooldown = skill1Cooldown * cooldownMultiplier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发技能2
|
||||
/// </summary>
|
||||
public void UseSkill2()
|
||||
{
|
||||
if (skill2RemainingCooldown > 0) return;
|
||||
|
||||
ExecuteSkillByName(skill2CurrentName);
|
||||
skill2RemainingCooldown = skill2Cooldown * cooldownMultiplier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统一按技能名字调度执行对应的技能效果
|
||||
/// </summary>
|
||||
public void ExecuteSkillByName(string skillName)
|
||||
{
|
||||
Debug.Log($"<color=yellow>【召唤师技能】释放:{skillName}(威力倍率: {powerMultiplier:F2})</color>");
|
||||
|
||||
switch (skillName)
|
||||
{
|
||||
return;
|
||||
case "神圣赞歌":
|
||||
ExecuteDivineHymn();
|
||||
break;
|
||||
case "天雷狂轰":
|
||||
ExecuteLightningStorm();
|
||||
break;
|
||||
case "陨石轰炸":
|
||||
ExecuteMeteorStrike();
|
||||
break;
|
||||
case "绝对零度":
|
||||
ExecuteAbsoluteZero();
|
||||
break;
|
||||
case "斩杀风暴":
|
||||
ExecuteExecuteStorm();
|
||||
break;
|
||||
case "庇护圣盾":
|
||||
ExecuteSanctuaryShield();
|
||||
break;
|
||||
case "虚弱诅咒":
|
||||
ExecuteWeaknessCurse();
|
||||
break;
|
||||
case "岩石傀儡":
|
||||
ExecuteRockGolemSummon();
|
||||
break;
|
||||
default:
|
||||
Debug.LogWarning($"未找到技能 [{skillName}] 的处理分支,默认执行天雷狂轰");
|
||||
ExecuteLightningStorm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float finalHeal = skill1HealAmount * powerMultiplier;
|
||||
Debug.Log($"释放技能1:群体治疗(恢复 {finalHeal:F1} 生命,威力倍率: {powerMultiplier:F2})");
|
||||
#region 技能具体逻辑实现
|
||||
|
||||
// 智能获取友方阵地中心或平均位置
|
||||
/// <summary>
|
||||
/// 1. 神圣赞歌:群体治疗
|
||||
/// </summary>
|
||||
private void ExecuteDivineHymn()
|
||||
{
|
||||
float finalHeal = (100f + 25f) * powerMultiplier;
|
||||
Vector3 targetPos = GetAllyCenterPosition();
|
||||
Vector3 startPos = castStartTransform != null ? castStartTransform.position : new Vector3(targetPos.x, targetPos.y + 10f, targetPos.z - 8f);
|
||||
|
||||
// 加载/实例化抛物线 cureBall
|
||||
GameObject ballPrefab = cureBallPrefab;
|
||||
if (ballPrefab == null)
|
||||
{
|
||||
ballPrefab = Resources.Load<GameObject>("Prefabs/特效/飞球/cureBall");
|
||||
}
|
||||
if (ballPrefab == null) ballPrefab = Resources.Load<GameObject>("Prefabs/特效/飞球/cureBall");
|
||||
#if UNITY_EDITOR
|
||||
if (ballPrefab == null)
|
||||
{
|
||||
ballPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/特效/飞球/cureBall.prefab");
|
||||
}
|
||||
if (ballPrefab == null) ballPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/特效/飞球/cureBall.prefab");
|
||||
#endif
|
||||
|
||||
GameObject novaPrefab = healNovaPrefab;
|
||||
#if UNITY_EDITOR
|
||||
if (novaPrefab == null)
|
||||
{
|
||||
novaPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Interactive/Healing/HealNova.prefab");
|
||||
}
|
||||
if (novaPrefab == null) novaPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Interactive/Healing/HealNova.prefab");
|
||||
#endif
|
||||
|
||||
if (ballPrefab != null)
|
||||
{
|
||||
GameObject ballGo = Instantiate(ballPrefab, startPos, Quaternion.identity);
|
||||
var parabola = ballGo.GetComponent<ParabolaFlyObject>();
|
||||
if (parabola == null)
|
||||
{
|
||||
parabola = ballGo.AddComponent<ParabolaFlyObject>();
|
||||
}
|
||||
if (parabola == null) parabola = ballGo.AddComponent<ParabolaFlyObject>();
|
||||
|
||||
parabola.Launch(startPos, targetPos, 0.8f, 4.5f, novaPrefab, () =>
|
||||
{
|
||||
// 对所有友方单位施加治疗
|
||||
BuffSystem.Instance.ApplyGroupHeal(finalHeal);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// 特效缺失兜底直接治疗
|
||||
BuffSystem.Instance.ApplyGroupHeal(finalHeal);
|
||||
}
|
||||
|
||||
// 开始冷却
|
||||
skill1RemainingCooldown = skill1Cooldown * cooldownMultiplier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算场上己方英雄的实时中心点位置,无单位时回退默认网格中心
|
||||
/// 2. 天雷狂轰:全屏落雷
|
||||
/// </summary>
|
||||
private void ExecuteLightningStorm()
|
||||
{
|
||||
float finalDamage = 120f * powerMultiplier;
|
||||
|
||||
GameObject strikePrefab = lightningStrikePrefab;
|
||||
#if UNITY_EDITOR
|
||||
if (strikePrefab == null) strikePrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Explosions/LightningExplosion/LightningExplosionBlue.prefab");
|
||||
#endif
|
||||
|
||||
GameObject novaPrefab = lightningNovaPrefab;
|
||||
#if UNITY_EDITOR
|
||||
if (novaPrefab == null) novaPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Nova/Lightning/NovaLightningBlue.prefab");
|
||||
#endif
|
||||
|
||||
if (novaPrefab != null)
|
||||
{
|
||||
Vector3 centerPos = new Vector3(0f, 0.1f, 0f);
|
||||
var novaGo = Instantiate(novaPrefab, centerPos, novaPrefab.transform.rotation);
|
||||
Destroy(novaGo, 3.5f);
|
||||
}
|
||||
|
||||
var targetEnemies = GetActiveEnemyUnits();
|
||||
StartCoroutine(ExecuteLightningStrikesRoutine(targetEnemies, strikePrefab, finalDamage));
|
||||
}
|
||||
|
||||
private IEnumerator ExecuteLightningStrikesRoutine(List<UnitBase> targetEnemies, GameObject strikePrefab, float finalDamage)
|
||||
{
|
||||
if (targetEnemies.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < targetEnemies.Count; i++)
|
||||
{
|
||||
var enemy = targetEnemies[i];
|
||||
if (enemy != null && enemy.gameObject.activeInHierarchy)
|
||||
{
|
||||
Vector3 strikePos = enemy.transform.position;
|
||||
strikePos.y = 0.1f;
|
||||
|
||||
if (strikePrefab != null)
|
||||
{
|
||||
var strikeGo = Instantiate(strikePrefab, strikePos, strikePrefab.transform.rotation);
|
||||
Destroy(strikeGo, 3f);
|
||||
}
|
||||
|
||||
var healthBar = enemy.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
healthBar.TakeDamage(finalDamage);
|
||||
// 30% 概率眩晕 1.5 秒
|
||||
if (Random.value <= 0.3f)
|
||||
{
|
||||
enemy.ApplyStun(1.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
yield return new WaitForSeconds(0.08f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
Vector3 randomPos = new Vector3(Random.Range(-5f, 5f), 0.1f, Random.Range(2f, 12f));
|
||||
if (strikePrefab != null)
|
||||
{
|
||||
var strikeGo = Instantiate(strikePrefab, randomPos, strikePrefab.transform.rotation);
|
||||
Destroy(strikeGo, 3f);
|
||||
}
|
||||
yield return new WaitForSeconds(0.08f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 3. 陨石轰炸:全屏/多目标烈焰砸击
|
||||
/// </summary>
|
||||
private void ExecuteMeteorStrike()
|
||||
{
|
||||
float finalDamage = 300f * powerMultiplier;
|
||||
var targetEnemies = GetActiveEnemyUnits();
|
||||
|
||||
GameObject expPrefab = null;
|
||||
#if UNITY_EDITOR
|
||||
expPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Explosions/MagicExplosion/MagicExplosionFire.prefab");
|
||||
#endif
|
||||
|
||||
if (targetEnemies.Count > 0)
|
||||
{
|
||||
foreach (var enemy in targetEnemies)
|
||||
{
|
||||
if (enemy == null || !enemy.gameObject.activeInHierarchy) continue;
|
||||
Vector3 pos = enemy.transform.position;
|
||||
pos.y = 0.1f;
|
||||
|
||||
if (expPrefab != null)
|
||||
{
|
||||
var exp = Instantiate(expPrefab, pos, expPrefab.transform.rotation);
|
||||
exp.transform.localScale = Vector3.one * 2f;
|
||||
Destroy(exp, 3f);
|
||||
}
|
||||
|
||||
var healthBar = enemy.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
healthBar.TakeDamage(finalDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 centerPos = new Vector3(0f, 0.1f, 5f);
|
||||
if (expPrefab != null)
|
||||
{
|
||||
var exp = Instantiate(expPrefab, centerPos, expPrefab.transform.rotation);
|
||||
exp.transform.localScale = Vector3.one * 3f;
|
||||
Destroy(exp, 3f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 4. 绝对零度:全场冰冻 3.5 秒
|
||||
/// </summary>
|
||||
private void ExecuteAbsoluteZero()
|
||||
{
|
||||
var targetEnemies = GetActiveEnemyUnits();
|
||||
foreach (var enemy in targetEnemies)
|
||||
{
|
||||
if (enemy == null || !enemy.gameObject.activeInHierarchy) continue;
|
||||
enemy.ApplyStun(3.5f);
|
||||
var healthBar = enemy.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
healthBar.TakeDamage(40f * powerMultiplier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 5. 斩杀风暴:全屏基础伤害 + 残血 (<25%) 斩杀
|
||||
/// </summary>
|
||||
private void ExecuteExecuteStorm()
|
||||
{
|
||||
float baseDamage = 80f * powerMultiplier;
|
||||
var targetEnemies = GetActiveEnemyUnits();
|
||||
|
||||
foreach (var enemy in targetEnemies)
|
||||
{
|
||||
if (enemy == null || !enemy.gameObject.activeInHierarchy) continue;
|
||||
var healthBar = enemy.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
float hpRatio = healthBar.currentHealth / healthBar.maxHealth;
|
||||
if (hpRatio < 0.25f)
|
||||
{
|
||||
healthBar.TakeDamage(healthBar.currentHealth + 9999f); // 斩杀
|
||||
}
|
||||
else
|
||||
{
|
||||
healthBar.TakeDamage(baseDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 6. 庇护圣盾:全场己方群体护盾 (临时效果:为全员施加持续治疗/伤害吸收)
|
||||
/// </summary>
|
||||
private void ExecuteSanctuaryShield()
|
||||
{
|
||||
float healShieldAmount = 150f * powerMultiplier;
|
||||
BuffSystem.Instance.ApplyGroupHeal(healShieldAmount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 7. 虚弱诅咒:全场敌人易伤并受到伤害
|
||||
/// </summary>
|
||||
private void ExecuteWeaknessCurse()
|
||||
{
|
||||
float curseDamage = 60f * powerMultiplier;
|
||||
var targetEnemies = GetActiveEnemyUnits();
|
||||
|
||||
foreach (var enemy in targetEnemies)
|
||||
{
|
||||
if (enemy == null || !enemy.gameObject.activeInHierarchy) continue;
|
||||
var healthBar = enemy.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
healthBar.TakeDamage(curseDamage);
|
||||
enemy.ApplyStun(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 8. 岩石傀儡:在全场引发冲击并造成震击控制
|
||||
/// </summary>
|
||||
private void ExecuteRockGolemSummon()
|
||||
{
|
||||
float rockDamage = 160f * powerMultiplier;
|
||||
var targetEnemies = GetActiveEnemyUnits();
|
||||
|
||||
foreach (var enemy in targetEnemies)
|
||||
{
|
||||
if (enemy == null || !enemy.gameObject.activeInHierarchy) continue;
|
||||
var healthBar = enemy.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
healthBar.TakeDamage(rockDamage);
|
||||
enemy.ApplyStun(1.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 工具辅助方法
|
||||
|
||||
private List<UnitBase> GetActiveEnemyUnits()
|
||||
{
|
||||
var allUnits = FindObjectsOfType<UnitBase>();
|
||||
var list = new List<UnitBase>();
|
||||
|
||||
foreach (var unit in allUnits)
|
||||
{
|
||||
if (unit == null || !unit.gameObject.activeInHierarchy) continue;
|
||||
var team = unit.GetComponent<UnitTeam>();
|
||||
if (team != null && team.teamId == 1) // 敌方
|
||||
{
|
||||
var healthBar = unit.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
list.Add(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private Vector3 GetAllyCenterPosition()
|
||||
{
|
||||
var heroes = FindObjectsOfType<UnitBase>();
|
||||
@@ -277,125 +596,14 @@ public class PlayerSkillSystem : MonoBehaviour
|
||||
return center;
|
||||
}
|
||||
|
||||
return new Vector3(0f, 0.1f, -10f); // 网格阵地真正中心点
|
||||
return new Vector3(0f, 0.1f, -10f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用技能2:全屏天雷狂轰伤害
|
||||
/// </summary>
|
||||
public void UseSkill2()
|
||||
{
|
||||
if (skill2RemainingCooldown > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float finalDamage = skill2Damage * powerMultiplier;
|
||||
Debug.Log($"释放技能2:天雷狂轰(造成 {finalDamage:F1} 伤害,威力倍率: {powerMultiplier:F2})");
|
||||
|
||||
// 加载特效资源
|
||||
GameObject strikePrefab = lightningStrikePrefab;
|
||||
#if UNITY_EDITOR
|
||||
if (strikePrefab == null)
|
||||
{
|
||||
strikePrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Explosions/LightningExplosion/LightningExplosionBlue.prefab");
|
||||
}
|
||||
#endif
|
||||
|
||||
GameObject novaPrefab = lightningNovaPrefab;
|
||||
#if UNITY_EDITOR
|
||||
if (novaPrefab == null)
|
||||
{
|
||||
novaPrefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/TJGeneratorLibEffects/Prefabs/Combat/Nova/Lightning/NovaLightningBlue.prefab");
|
||||
}
|
||||
#endif
|
||||
|
||||
// 1. 屏幕中央触发全屏雷暴光环
|
||||
if (novaPrefab != null)
|
||||
{
|
||||
Vector3 centerPos = new Vector3(0f, 0.1f, 0f);
|
||||
var novaGo = Instantiate(novaPrefab, centerPos, novaPrefab.transform.rotation);
|
||||
Destroy(novaGo, 3.5f);
|
||||
}
|
||||
|
||||
// 2. 检索所有活着的敌方单位
|
||||
var allUnits = FindObjectsOfType<UnitBase>();
|
||||
var targetEnemies = new System.Collections.Generic.List<UnitBase>();
|
||||
|
||||
foreach (var unit in allUnits)
|
||||
{
|
||||
if (unit == null || !unit.gameObject.activeInHierarchy) continue;
|
||||
var team = unit.GetComponent<UnitTeam>();
|
||||
if (team != null && team.teamId == 1) // 敌方
|
||||
{
|
||||
var healthBar = unit.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
targetEnemies.Add(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StartCoroutine(ExecuteLightningStrikesRoutine(targetEnemies, strikePrefab, finalDamage));
|
||||
|
||||
// 开始冷却
|
||||
skill2RemainingCooldown = skill2Cooldown * cooldownMultiplier;
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator ExecuteLightningStrikesRoutine(
|
||||
System.Collections.Generic.List<UnitBase> targetEnemies,
|
||||
GameObject strikePrefab,
|
||||
float finalDamage)
|
||||
{
|
||||
if (targetEnemies.Count > 0)
|
||||
{
|
||||
// 敌群交错落雷
|
||||
for (int i = 0; i < targetEnemies.Count; i++)
|
||||
{
|
||||
var enemy = targetEnemies[i];
|
||||
if (enemy != null && enemy.gameObject.activeInHierarchy)
|
||||
{
|
||||
Vector3 strikePos = enemy.transform.position;
|
||||
strikePos.y = 0.1f;
|
||||
|
||||
if (strikePrefab != null)
|
||||
{
|
||||
var strikeGo = Instantiate(strikePrefab, strikePos, strikePrefab.transform.rotation);
|
||||
Destroy(strikeGo, 3f);
|
||||
}
|
||||
|
||||
var healthBar = enemy.GetComponent<WorldHealthBar>();
|
||||
if (healthBar != null && !healthBar.IsDead)
|
||||
{
|
||||
healthBar.TakeDamage(finalDamage);
|
||||
}
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(0.08f); // 80毫秒交错落雷节奏
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 无敌人时在敌方阵地随机散落 6 道震撼天雷
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
Vector3 randomPos = new Vector3(Random.Range(-5f, 5f), 0.1f, Random.Range(2f, 12f));
|
||||
if (strikePrefab != null)
|
||||
{
|
||||
var strikeGo = Instantiate(strikePrefab, randomPos, strikePrefab.transform.rotation);
|
||||
Destroy(strikeGo, 3f);
|
||||
}
|
||||
yield return new WaitForSeconds(0.08f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置所有技能冷却(测试用)
|
||||
/// </summary>
|
||||
public void ResetAllCooldowns()
|
||||
{
|
||||
skill1RemainingCooldown = 0f;
|
||||
skill2RemainingCooldown = 0f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in new issue
Block a user