成就系统 巨大修改 新的ui 黑白效果 等一堆
This commit is contained in:
@@ -3,14 +3,14 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// SkillBuilder: 集中定义可快速调用的技能函数。
|
||||
/// - 每个技能为一个独立的 public 方法,接受必要参数(施法者 source, 目标 specificTarget 等)
|
||||
/// - 内部调用 EffectSystem.Instance.ApplyEffect(...),统一使用 Selector 与 EffectType
|
||||
/// - 提供常用参数(amount, duration, tickInterval)并对参数做简单校验
|
||||
/// SkillBuilder: ���ж���ɿ��ٵ��õļ��ܺ�����
|
||||
/// - ÿ������Ϊһ�������� public ���������ܱ�Ҫ������ʩ���� source, Ŀ�� specificTarget �ȣ�
|
||||
/// - �ڲ����� EffectSystem.Instance.ApplyEffect(...)��ͳһʹ�� Selector �� EffectType
|
||||
/// - �ṩ���ò�����amount, duration, tickInterval�����Բ�������У��
|
||||
///
|
||||
/// 用法示例:
|
||||
/// �÷�ʾ��:
|
||||
/// SkillBuilder.Instance.ExecuteSkill("Fireball", EffectType.DamageSingleEnemy, 120f, Selector.CurrentEnemies, caster, target);
|
||||
/// SkillBuilder.Instance.ApplyScoreMultiplier(caster, Selector.AllAllies, 1.5f, 5f); // 5 秒内队伍得分乘 1.5
|
||||
/// SkillBuilder.Instance.ApplyScoreMultiplier(caster, Selector.AllAllies, 1.5f, 5f); // 5 ���ڶ���÷ֳ� 1.5
|
||||
/// </summary>
|
||||
public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
@@ -40,7 +40,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------- 基础参数模板 -----------------------------
|
||||
// ----------------------------- ��������� -----------------------------
|
||||
public float defaultDamage = 100f;
|
||||
public float defaultHeal = 80f;
|
||||
public float defaultDuration = 5f;
|
||||
@@ -139,7 +139,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
|
||||
if (ally != null && manaGain != 0)
|
||||
{
|
||||
ally.ModifyMana(manaGain, true);
|
||||
ally.ModifyMana(manaGain, true, false);
|
||||
Debug.Log($"[SkillBuilder] Applied mana gain {manaGain} to slot {trackIndex} due to judge {judgeResult}");
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------- 通用技能执行接口 -----------------------------
|
||||
// 通用执行:技能名, 效果类型, 数值, 目标选择器, 施法者, 可选具体目标, 持续时间和 tick
|
||||
// ----------------------------- ͨ�ü���ִ�нӿ� -----------------------------
|
||||
// ͨ��ִ�У�������, Ч������, ��ֵ, Ŀ��ѡ����, ʩ����, ��ѡ����Ŀ��, ����ʱ��� tick
|
||||
public void ExecuteSkill(string skillName, EffectType effectType, float amount, Selector selector, GameObject caster, GameObject specificTarget = null, float duration = 0f, float tickInterval = 1f)
|
||||
{
|
||||
if (global::EffectSystem.Instance == null)
|
||||
@@ -178,6 +178,12 @@ public class SkillBuilder : MonoBehaviour
|
||||
// basic logging
|
||||
Debug.Log($"[SkillBuilder] ExecuteSkill: {skillName} type={effectType} amount={amount} selector={selector} caster={(caster?caster.name:"null")} target={(specificTarget?specificTarget.name:"null")} duration={duration}");
|
||||
|
||||
// additional debug: show when caster is null which will make Selector.Self produce no targets
|
||||
if (selector == Selector.Self && caster == null)
|
||||
{
|
||||
Debug.LogWarning($"[SkillBuilder] ExecuteSkill: selector==Self but caster is null for skill {skillName}. Effect will have no targets.");
|
||||
}
|
||||
|
||||
// call EffectSystem using GameObject API (keeps compatibility with existing EffectSystem)
|
||||
global::EffectSystem.Instance.ApplyEffect(selector, effectType, amount, duration, caster, specificTarget, tickInterval);
|
||||
}
|
||||
@@ -190,11 +196,17 @@ public class SkillBuilder : MonoBehaviour
|
||||
ExecuteSkill(skillName, effectType, amount, selector, casterGO, targetGO, duration, tickInterval);
|
||||
}
|
||||
|
||||
// ----------------------------- 目标解析(供本脚本使用,和 EffectSystem 的解析一致) -----------------------------
|
||||
// 返回符合 selector 的 GameObject 列表,方便技能脚本自行操作(例如直接给 ICombatant.Buff)
|
||||
// ----------------------------- Ŀ������������ű�ʹ�ã��� EffectSystem �Ľ���һ�£� -----------------------------
|
||||
// ���ط��� selector �� GameObject �б������㼼�ܽű����в���������ֱ�Ӹ� ICombatant.Buff��
|
||||
public List<GameObject> ResolveTargetsLocal(Selector selector, GameObject source = null, GameObject specificTarget = null)
|
||||
{
|
||||
List<GameObject> list = new List<GameObject>();
|
||||
// If caller provided a specificTarget, honor it as the single target regardless of selector.
|
||||
if (specificTarget != null)
|
||||
{
|
||||
list.Add(specificTarget);
|
||||
return list;
|
||||
}
|
||||
switch (selector)
|
||||
{
|
||||
case Selector.Self:
|
||||
@@ -274,8 +286,8 @@ public class SkillBuilder : MonoBehaviour
|
||||
return uniq;
|
||||
}
|
||||
|
||||
// ----------------------------- 分数影响 API -----------------------------
|
||||
// 直接修改全局总分(立即生效)
|
||||
// ----------------------------- ����Ӱ�� API -----------------------------
|
||||
// ֱ����ȫ���ܷ֣�������Ч��
|
||||
public void ModifyTotalScore(int delta)
|
||||
{
|
||||
if (ScoreManager.Instance == null) { Debug.LogWarning("ModifyTotalScore: ScoreManager.Instance is null"); return; }
|
||||
@@ -289,7 +301,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// 修改单个友军的分数(即时)
|
||||
// �ĵ����Ѿ��ķ�������ʱ��
|
||||
public void ModifySingleAllyScoreDirect(GameObject allyObject, int delta)
|
||||
{
|
||||
if (allyObject == null) return;
|
||||
@@ -309,7 +321,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (ally != null) ally.AddScoreDirect(delta);
|
||||
}
|
||||
|
||||
// 对一组目标应用一次性的分数奖励/惩罚(按集合应用)
|
||||
// ��һ��Ŀ��Ӧ��һ���Եķ�������/�ͷ���������Ӧ�ã�
|
||||
public void ModifyGroupScoreDirect(Selector selector, GameObject caster, int delta)
|
||||
{
|
||||
var targets = ResolveTargetsLocal(selector, caster);
|
||||
@@ -320,7 +332,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// 临时提高(或降低)目标的分数倍率,使用 EffectSystem.ScoreMultiplier(推荐)
|
||||
// ��ʱ��ߣ��ͣ�Ŀ��ķ������ʣ�ʹ�� EffectSystem.ScoreMultiplier���Ƽ���
|
||||
public void ApplyScoreMultiplier(Selector selector, GameObject caster, float multiplier, float duration)
|
||||
{
|
||||
if (multiplier <= 0f) { Debug.LogWarning("ApplyScoreMultiplier: invalid multiplier"); return; }
|
||||
@@ -367,7 +379,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------- 现有便捷技能示例 -----------------------------
|
||||
// ----------------------------- ���б�ݼ���ʾ�� -----------------------------
|
||||
public void DealSingleEnemyDamage(GameObject caster, GameObject enemyTarget, float amount)
|
||||
{
|
||||
if (enemyTarget == null) { Debug.LogWarning("DealSingleEnemyDamage: enemyTarget == null"); return; }
|
||||
@@ -393,7 +405,9 @@ public class SkillBuilder : MonoBehaviour
|
||||
public void DealSingleAllyDamage(GameObject caster, GameObject allyTarget, float amount)
|
||||
{
|
||||
if (allyTarget == null) { Debug.LogWarning("DealSingleAllyDamage: allyTarget == null"); return; }
|
||||
ExecuteSkill("DealSingleAllyDamage", EffectType.DamageSingleAlly, amount, Selector.AllAllies, caster, allyTarget);
|
||||
// This is intended as a single-target ally damage. Use Selector.Self when a specificTarget is provided
|
||||
// so target resolution treats the passed allyTarget as the explicit target.
|
||||
ExecuteSkill("DealSingleAllyDamage", EffectType.DamageSingleAlly, amount, Selector.Self, caster, allyTarget);
|
||||
}
|
||||
|
||||
// New: damage allies over time
|
||||
@@ -464,8 +478,8 @@ public class SkillBuilder : MonoBehaviour
|
||||
HealGroupOverTime(caster, defaultHeal * 5f, 4f, 1f, true);
|
||||
}
|
||||
|
||||
// ----------------------------- 基于 SO 的数值计算 helpers -----------------------------
|
||||
// 获取某个槽位的 ally GameObject(0-based slot index)
|
||||
// ----------------------------- ���� SO ����ֵ���� helpers -----------------------------
|
||||
// ��ȡij����λ�� ally GameObject��0-based slot index��
|
||||
public GameObject GetAllyObjectBySlot(int slotIndex)
|
||||
{
|
||||
var ui = teamUIController.Instance;
|
||||
@@ -474,7 +488,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
return named;
|
||||
}
|
||||
|
||||
// 根据槽位解析 AllyHero_SO(运行时从 Resources 中查找 ally_heroID)
|
||||
// ���ݲ�λ���� AllyHero_SO������ʱ�� Resources �в��� ally_heroID��
|
||||
public AllyHero_SO GetAllyHeroSOBySlot(int slotIndex)
|
||||
{
|
||||
// slot-based cache (depends on team selection)
|
||||
@@ -512,7 +526,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
return result;
|
||||
}
|
||||
|
||||
// 根据当前经验选择生效的等级信息(返回 null 表示未找到)
|
||||
// ���ݵ�ǰ����ѡ����Ч�ĵȼ���Ϣ������ null ��ʾδ�ҵ���
|
||||
private AllyHero_SO.AllyLevelInfo GetEffectiveLevelInfo(AllyHero_SO so)
|
||||
{
|
||||
if (so == null || so.levelStats == null || so.levelStats.Count == 0) return null;
|
||||
@@ -535,7 +549,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
return best;
|
||||
}
|
||||
|
||||
// 取得英雄基础攻击力(使用当前经验匹配的等级的 attack),若没有则返回 0
|
||||
// ȡ��Ӣ�ۻ�����������ʹ�õ�ǰ����ƥ��ĵȼ��� attack������û���� 0
|
||||
public int GetAllyBaseAttack(AllyHero_SO so)
|
||||
{
|
||||
if (so == null) return 0;
|
||||
@@ -545,8 +559,8 @@ public class SkillBuilder : MonoBehaviour
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 统一计算技能造成数值:当 inputValue == -1 时使用 skillStatic + allyAttack,
|
||||
// 否则直接使用 inputValue(按传入的 EffectType 做必要转换)
|
||||
// ͳһ���㼼�������ֵ���� inputValue == -1 ʱʹ�� skillStatic + allyAttack��
|
||||
// ����ֱ��ʹ�� inputValue��������� EffectType ����Ҫת����
|
||||
public float ComputeSkillValue(GameObject caster, int slotIndex, float inputValue, int skillStatic)
|
||||
{
|
||||
if (inputValue != -1f) return inputValue;
|
||||
@@ -555,9 +569,9 @@ public class SkillBuilder : MonoBehaviour
|
||||
return skillStatic + allyAtk;
|
||||
}
|
||||
|
||||
// ----------------------------- 槽位技能通用接口 -----------------------------
|
||||
// 通常技能在被槽位的角色释放时调用此函数:
|
||||
// slotIndex: 0-based 槽位索引;skillId: 自定义技能标识;effectType,value,selector,duration等参数同前述约定
|
||||
// ----------------------------- ��λ����ͨ�ýӿ� -----------------------------
|
||||
// ͨ�������ڱ���λ�Ľ�ɫ�ͷ�ʱ���ô˺�����
|
||||
// slotIndex: 0-based ��λ������skillId: �Զ��弼�ܱ�ʶ��effectType,value,selector,duration�Ȳ���ͬǰ��Լ��
|
||||
public void AllySlotSkill(int slotIndex, string skillId, EffectType effectType, float value, Selector selector, float duration = 0f, GameObject specificTarget = null, float tickInterval = 1f)
|
||||
{
|
||||
GameObject caster = GetAllyObjectBySlot(slotIndex);
|
||||
@@ -567,19 +581,19 @@ public class SkillBuilder : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
// determine skill-specific static values (示例:skill01 的固定伤害为 50)
|
||||
// determine skill-specific static values (ʾ����skill01 �Ĺ̶��˺�Ϊ 50)
|
||||
int skillStaticDamage = 0;
|
||||
switch (skillId)
|
||||
{
|
||||
case "skill01": skillStaticDamage = 50; break;
|
||||
case "skill_heal_small": skillStaticDamage = 30; break;
|
||||
// 在此添加更多技能静态值
|
||||
// �ڴ����Ӹ��༼�ܾ�ֵ̬
|
||||
default: skillStaticDamage = 0; break;
|
||||
}
|
||||
|
||||
float finalValue = ComputeSkillValue(caster, slotIndex, value, skillStaticDamage);
|
||||
|
||||
// 特殊处理:若 effectType 是单次伤害但我们希望对所有敌人使用 CurrentEnemies,selector 参数已由调用方传入
|
||||
// ��������� effectType �ǵ����˺�������ϣ�������е���ʹ�� CurrentEnemies��selector �������ɵ��÷�����
|
||||
ExecuteSkill($"slot{slotIndex + 1}_{skillId}", effectType, finalValue, selector, caster, specificTarget, duration, tickInterval);
|
||||
}
|
||||
|
||||
@@ -593,6 +607,37 @@ public class SkillBuilder : MonoBehaviour
|
||||
Debug.LogWarning($"UseSkillDefinition: no caster GameObject found for slot {slotIndex}. Proceeding with null caster.");
|
||||
}
|
||||
|
||||
// Extra attempts to resolve caster when null: try teamUIController and name pattern fallback
|
||||
if (caster == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ui = teamUIController.Instance;
|
||||
if (ui != null)
|
||||
{
|
||||
var alt = ui.GetAllyObjectBySlot(slotIndex);
|
||||
if (alt != null)
|
||||
{
|
||||
caster = alt;
|
||||
Debug.Log($"UseSkillDefinition: resolved caster via teamUIController for slot {slotIndex} -> {caster.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (caster == null)
|
||||
{
|
||||
var byName = GameObject.Find($"ally_0{slotIndex + 1}");
|
||||
if (byName != null)
|
||||
{
|
||||
caster = byName;
|
||||
Debug.Log($"UseSkillDefinition: resolved caster via name ally_0{slotIndex + 1} -> {caster.name}");
|
||||
}
|
||||
}
|
||||
|
||||
// Log useful debug info for diagnosing OnEnemyDead->Self issues
|
||||
Debug.Log($"[SkillBuilder] UseSkillDefinition: casting skill {def.skillId} for slot {slotIndex} (caster={(caster?caster.name:"null")}) selector={def.defaultSelector} operateDirectly={def.operateDirectly} inputValue={inputValue} specificTarget={(specificTarget?specificTarget.name:"null")}");
|
||||
|
||||
float amount = 0f;
|
||||
// If caller provided explicit inputValue use it
|
||||
if (inputValue != -1f)
|
||||
@@ -723,7 +768,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (def.defaultDuration <= 0f)
|
||||
{
|
||||
// single instance - amountPerTick equals immediate amount
|
||||
ally.ModifyMana(Mathf.CeilToInt(amountPerTick), true);
|
||||
ally.ModifyMana(Mathf.CeilToInt(amountPerTick), true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -742,7 +787,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (def.effectType == EffectType.BuffDuration) b.scoreMultiplier = 1.5f;
|
||||
if (ic != null) ic.ApplyBuff(b, caster);
|
||||
break;
|
||||
// 新增 effect type 处理
|
||||
// ���� effect type ����
|
||||
case EffectType.IncreaseMaxHP:
|
||||
if (ally != null) ally.SetMaxHP(ally.maxHP + Mathf.CeilToInt(amountTotal), false);
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy)) enemy.maxHP += Mathf.CeilToInt(amountTotal);
|
||||
@@ -912,6 +957,176 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger ally skills when a single enemy is defeated
|
||||
public void TriggerOnEnemyDead(EnemyCombatant deadEnemy)
|
||||
{
|
||||
if (!Application.isPlaying) return;
|
||||
// Determine number of ally slots; prefer teamUIController but fallback to 5
|
||||
int slots = 5;
|
||||
if (teamUIController.Instance != null && teamUIController.Instance.allySlotIds != null)
|
||||
slots = teamUIController.Instance.allySlotIds.Count;
|
||||
else
|
||||
Debug.LogWarning("[SkillBuilder] TriggerOnEnemyDead: teamUIController.Instance or allySlotIds is null - falling back to 5 slots");
|
||||
|
||||
for (int i = 0; i < slots; i++)
|
||||
{
|
||||
var so = GetAllyHeroSOBySlot(i);
|
||||
if (so == null) continue;
|
||||
|
||||
if (so.equippedSkillGroupIDs != null && so.equippedSkillGroupIDs.Length > 0 && so.skillGroups != null)
|
||||
{
|
||||
foreach (int gid in so.equippedSkillGroupIDs)
|
||||
{
|
||||
if (gid == 0) continue;
|
||||
SkillGroup group = null;
|
||||
for (int k = 0; k < so.skillGroups.Length; k++) { var g = so.skillGroups[k]; if (g != null && g.skillGroupID == gid) { group = g; break; } }
|
||||
if (group == null) continue;
|
||||
foreach (var def in group.skills)
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnEnemyDead) continue;
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyDead: slot {i+1} casting skill {def.skillId}");
|
||||
// Only pass deadEnemy as specificTarget when the skill truly expects a specific target (e.g. targets CurrentEnemies)
|
||||
GameObject ctxTarget = null;
|
||||
if (deadEnemy != null && (def.requiresSpecificTarget || def.defaultSelector == Selector.CurrentEnemies)) ctxTarget = deadEnemy.gameObject;
|
||||
UseSkillDefinition(def, i, -1f, ctxTarget);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var fallbackGroup = so.GetPrimarySkillGroup();
|
||||
if (fallbackGroup != null)
|
||||
{
|
||||
foreach (var def in fallbackGroup.skills)
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnEnemyDead) continue;
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyDead: slot {i+1} casting skill {def.skillId}");
|
||||
GameObject ctxTarget = null;
|
||||
if (deadEnemy != null && (def.requiresSpecificTarget || def.defaultSelector == Selector.CurrentEnemies)) ctxTarget = deadEnemy.gameObject;
|
||||
UseSkillDefinition(def, i, -1f, ctxTarget);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var primary = so.GetPrimarySkill();
|
||||
if (primary != null && primary.triggerCondition == SkillDefinition.SkillTrigger.OnEnemyDead)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyDead: slot {i+1} casting primary skill {primary.skillId}");
|
||||
// Only pass deadEnemy as specificTarget when the skill truly expects a specific target (e.g. targets CurrentEnemies)
|
||||
GameObject ctxTarget = null;
|
||||
if (deadEnemy != null && (primary.requiresSpecificTarget || primary.defaultSelector == Selector.CurrentEnemies)) ctxTarget = deadEnemy.gameObject;
|
||||
UsePrimarySkillForSlot(i, -1f, ctxTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger ally skills when an enemy revives/enters
|
||||
public void TriggerOnEnemyRevive(EnemyCombatant enemy)
|
||||
{
|
||||
if (!Application.isPlaying) return;
|
||||
int slots = 5;
|
||||
if (teamUIController.Instance != null && teamUIController.Instance.allySlotIds != null)
|
||||
slots = teamUIController.Instance.allySlotIds.Count;
|
||||
else
|
||||
Debug.LogWarning("[SkillBuilder] TriggerOnEnemyRevive: teamUIController.Instance or allySlotIds is null - falling back to 5 slots");
|
||||
|
||||
for (int i = 0; i < slots; i++)
|
||||
{
|
||||
var so = GetAllyHeroSOBySlot(i);
|
||||
if (so == null) continue;
|
||||
|
||||
if (so.equippedSkillGroupIDs != null && so.equippedSkillGroupIDs.Length > 0 && so.skillGroups != null)
|
||||
{
|
||||
foreach (int gid in so.equippedSkillGroupIDs)
|
||||
{
|
||||
if (gid == 0) continue;
|
||||
SkillGroup group = null;
|
||||
for (int k = 0; k < so.skillGroups.Length; k++) { var g = so.skillGroups[k]; if (g != null && g.skillGroupID == gid) { group = g; break; } }
|
||||
if (group == null) continue;
|
||||
foreach (var def in group.skills)
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnEnemyRevive) continue;
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting skill {def.skillId}");
|
||||
UseSkillDefinition(def, i, -1f, enemy != null ? enemy.gameObject : null);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var fallbackGroup2 = so.GetPrimarySkillGroup();
|
||||
if (fallbackGroup2 != null)
|
||||
{
|
||||
foreach (var def in fallbackGroup2.skills)
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnEnemyRevive) continue;
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting skill {def.skillId} (from primary group)");
|
||||
UseSkillDefinition(def, i, -1f, enemy != null ? enemy.gameObject : null);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var primary2 = so.GetPrimarySkill();
|
||||
if (primary2 != null && primary2.triggerCondition == SkillDefinition.SkillTrigger.OnEnemyRevive)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting primary skill {primary2.skillId}");
|
||||
UsePrimarySkillForSlot(i, -1f, enemy != null ? enemy.gameObject : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger ally skills when all enemies are defeated
|
||||
public void TriggerOnAllEnemiesDefeated()
|
||||
{
|
||||
if (!Application.isPlaying) return;
|
||||
if (teamUIController.Instance == null || teamUIController.Instance.allySlotIds == null) return;
|
||||
int slots = teamUIController.Instance.allySlotIds.Count;
|
||||
for (int i = 0; i < slots; i++)
|
||||
{
|
||||
var so = GetAllyHeroSOBySlot(i);
|
||||
if (so == null) continue;
|
||||
|
||||
if (so.equippedSkillGroupIDs != null && so.equippedSkillGroupIDs.Length > 0 && so.skillGroups != null)
|
||||
{
|
||||
foreach (int gid in so.equippedSkillGroupIDs)
|
||||
{
|
||||
if (gid == 0) continue;
|
||||
SkillGroup group = null;
|
||||
for (int k = 0; k < so.skillGroups.Length; k++) { var g = so.skillGroups[k]; if (g != null && g.skillGroupID == gid) { group = g; break; } }
|
||||
if (group == null) continue;
|
||||
foreach (var def in group.skills)
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnAllEnemiesDefeated) continue;
|
||||
UseSkillDefinition(def, i, -1f, null);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var fallbackGroup3 = so.GetPrimarySkillGroup();
|
||||
if (fallbackGroup3 != null)
|
||||
{
|
||||
foreach (var def in fallbackGroup3.skills)
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnAllEnemiesDefeated) continue;
|
||||
UseSkillDefinition(def, i, -1f, null);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var primary3 = so.GetPrimarySkill();
|
||||
if (primary3 != null && primary3.triggerCondition == SkillDefinition.SkillTrigger.OnAllEnemiesDefeated)
|
||||
{
|
||||
UsePrimarySkillForSlot(i, -1f, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, float> _lastOnNoteHitTriggerTime = new Dictionary<string, float>();
|
||||
|
||||
// track processed unique note IDs (e.g. long-hold note id) so shared effects (mana/hp) are applied only once
|
||||
@@ -1108,8 +1323,8 @@ public class SkillBuilder : MonoBehaviour
|
||||
- EnemyTarget: if your skill should hit a specific enemy instance, supply that enemy's GameObject (for example from Enemy spawn manager or from collision detection). If you want to apply to all enemies, pass null and use Selector.CurrentEnemies.
|
||||
*/
|
||||
|
||||
// ----------------------------- 示例:为轨道3 封装一个快捷函数(用户示例) -----------------------------
|
||||
// 轨道3(索引2) 的技能1,遵循用户所需签名:_ally03skill01(EffectType, value, Selector, duration)
|
||||
// ----------------------------- ʾ����Ϊ���3 ��װһ����ݺ������û�ʾ���� -----------------------------
|
||||
// ���3(����2) �ļ���1����ѭ�û�����ǩ����_ally03skill01(EffectType, value, Selector, duration)
|
||||
public void _ally03skill01(EffectType effectType, float value, Selector selector, float duration = 0f, GameObject specificTarget = null)
|
||||
{
|
||||
AllySlotSkill(2, "skill01", effectType, value, selector, duration, specificTarget);
|
||||
@@ -1121,7 +1336,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (ally == null) yield break;
|
||||
if (duration <= 0f || tickInterval <= 0f)
|
||||
{
|
||||
ally.ModifyMana(Mathf.CeilToInt(totalAmount), true);
|
||||
ally.ModifyMana(Mathf.CeilToInt(totalAmount), true, true);
|
||||
yield break;
|
||||
}
|
||||
int ticks = Mathf.Max(1, Mathf.CeilToInt(duration / tickInterval));
|
||||
@@ -1129,7 +1344,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
ally.ModifyMana(Mathf.CeilToInt(perTick), true);
|
||||
ally.ModifyMana(Mathf.CeilToInt(perTick), true, true);
|
||||
yield return new WaitForSeconds(tickInterval);
|
||||
elapsed += tickInterval;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user