技能主要更新,修复卡顿并加入动画,以及各种其他更新。
This commit is contained in:
@@ -3,14 +3,14 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// SkillBuilder: ���ж���ɿ��ٵ��õļ��ܺ�����
|
||||
/// 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
|
||||
{
|
||||
@@ -64,6 +64,12 @@ public class SkillBuilder : MonoBehaviour
|
||||
private Dictionary<int, AllyHero_SO> _allyHeroSoById;
|
||||
private Dictionary<int, AllyHero_SO> _allyHeroSoBySlotCache;
|
||||
|
||||
// Reusable buffers to reduce allocations during gameplay
|
||||
private readonly Dictionary<string, float> _varsBuffer = new Dictionary<string, float>(16);
|
||||
private readonly List<string> _tmpNoteIdRemoval = new List<string>(16);
|
||||
private int _cachedAlliesFrame = -1;
|
||||
private readonly List<GameObject> _cachedAllies = new List<GameObject>(8);
|
||||
|
||||
private void PrewarmAllyHeroSOIndex()
|
||||
{
|
||||
if (_allAllyHeroSOs != null && _allAllyHeroSOs.Length > 0) return;
|
||||
@@ -85,7 +91,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
|
||||
if (GameConfig.verboseLogs)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] PrewarmAllyHeroSOIndex: loaded {_allAllyHeroSOs?.Length ?? 0} AllyHero_SO assets, indexed {_allyHeroSoById.Count}");
|
||||
LogVerbose($"[SkillBuilder] PrewarmAllyHeroSOIndex: loaded {_allAllyHeroSOs?.Length ?? 0} AllyHero_SO assets, indexed {_allyHeroSoById.Count}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +107,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
// Apply as single-instance damage to current enemies; EffectSystem will pick first applicable enemy for DamageSingleEnemy
|
||||
global::EffectSystem.Instance.ApplyEffect(Selector.CurrentEnemies, EffectType.DamageSingleEnemy, amount, 0f, caster, null);
|
||||
Debug.Log($"[SkillBuilder] DealDamageFromAllyToEnemies: applied {amount} from slot {slotIndex} via EffectSystem");
|
||||
LogVerbose($"[SkillBuilder] DealDamageFromAllyToEnemies: applied {amount} from slot {slotIndex} via EffectSystem");
|
||||
}
|
||||
|
||||
private void ApplySharedOnNoteHit(int trackIndex, string judgeResult)
|
||||
@@ -140,7 +146,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (ally != null && manaGain != 0)
|
||||
{
|
||||
ally.ModifyMana(manaGain, true, false);
|
||||
Debug.Log($"[SkillBuilder] Applied mana gain {manaGain} to slot {trackIndex} due to judge {judgeResult}");
|
||||
LogVerbose($"[SkillBuilder] Applied mana gain {manaGain} to slot {trackIndex} due to judge {judgeResult}");
|
||||
}
|
||||
|
||||
if (judgeResult == "Miss")
|
||||
@@ -151,7 +157,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
// apply damage reduction by damageResistance: final loss = missBase * (1 - damageResistance)
|
||||
float loss = missBase * (1f - ally.damageResistance);
|
||||
ally.ModifyHP(-Mathf.CeilToInt(loss), true);
|
||||
Debug.Log($"[SkillBuilder] Applied miss HP loss {loss} to slot {trackIndex} (damageResistance={ally.damageResistance})");
|
||||
LogVerbose($"[SkillBuilder] Applied miss HP loss {loss} to slot {trackIndex} (damageResistance={ally.damageResistance})");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -167,7 +173,7 @@ 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)
|
||||
@@ -176,7 +182,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
// 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}");
|
||||
LogVerbose($"[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)
|
||||
@@ -196,7 +202,51 @@ public class SkillBuilder : MonoBehaviour
|
||||
ExecuteSkill(skillName, effectType, amount, selector, casterGO, targetGO, duration, tickInterval);
|
||||
}
|
||||
|
||||
// ----------------------------- Ŀ������������ű�ʹ�ã��� EffectSystem �Ľ���һ�£� -----------------------------
|
||||
|
||||
private void LogVerbose(string message)
|
||||
{
|
||||
if (GameConfig.verboseLogs) Debug.Log(message);
|
||||
}
|
||||
|
||||
private List<GameObject> GetAlliesCached()
|
||||
{
|
||||
if (_cachedAlliesFrame == Time.frameCount) return _cachedAllies;
|
||||
_cachedAlliesFrame = Time.frameCount;
|
||||
_cachedAllies.Clear();
|
||||
|
||||
var ui = teamUIController.Instance;
|
||||
if (ui != null)
|
||||
{
|
||||
int count = ui.allySlotIds != null ? ui.allySlotIds.Count : 5;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var go = ui.GetAllyObjectBySlot(i);
|
||||
if (go != null && !_cachedAllies.Contains(go)) _cachedAllies.Add(go);
|
||||
}
|
||||
}
|
||||
|
||||
if (_cachedAllies.Count == 0)
|
||||
{
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
var go = GameObject.Find($"ally_0{i}");
|
||||
if (go != null && !_cachedAllies.Contains(go)) _cachedAllies.Add(go);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var tagged = GameObject.FindGameObjectsWithTag("Ally");
|
||||
foreach (var g in tagged)
|
||||
{
|
||||
if (g != null && !_cachedAllies.Contains(g)) _cachedAllies.Add(g);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return _cachedAllies;
|
||||
}
|
||||
// ----------------------------- Ŀ������������ű�ʹ�ã���?EffectSystem �Ľ���һ�£� -----------------------------
|
||||
// ���ط��� selector �� GameObject �б������㼼�ܽű����в���������ֱ�Ӹ� ICombatant.Buff��
|
||||
public List<GameObject> ResolveTargetsLocal(Selector selector, GameObject source = null, GameObject specificTarget = null)
|
||||
{
|
||||
@@ -213,12 +263,16 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (source != null) list.Add(source);
|
||||
break;
|
||||
case Selector.AllAllies:
|
||||
for (int i = 1; i <= 5; i++) { var go = GameObject.Find($"ally_0{i}"); if (go != null) list.Add(go); }
|
||||
try { var tagged = GameObject.FindGameObjectsWithTag("Ally"); foreach (var g in tagged) if (!list.Contains(g)) list.Add(g); } catch { }
|
||||
foreach (var go in GetAlliesCached())
|
||||
{
|
||||
if (go != null) list.Add(go);
|
||||
}
|
||||
break;
|
||||
case Selector.AllAlliesExceptSelf:
|
||||
for (int i = 1; i <= 5; i++) { var go = GameObject.Find($"ally_0{i}"); if (go != null) list.Add(go); }
|
||||
try { var tagged = GameObject.FindGameObjectsWithTag("Ally"); foreach (var g in tagged) if (!list.Contains(g)) list.Add(g); } catch { }
|
||||
foreach (var go in GetAlliesCached())
|
||||
{
|
||||
if (go != null) list.Add(go);
|
||||
}
|
||||
if (source != null) list.RemoveAll(g => g == null || g == source);
|
||||
break;
|
||||
case Selector.AdjacentAllies:
|
||||
@@ -275,8 +329,10 @@ public class SkillBuilder : MonoBehaviour
|
||||
else { try { var tagged = GameObject.FindGameObjectsWithTag("Enemy"); foreach (var g in tagged) if (!list.Contains(g)) list.Add(g); } catch { var single = GameObject.Find("thisEnemy"); if (single != null) list.Add(single); } }
|
||||
break;
|
||||
case Selector.AllEntities:
|
||||
for (int i = 1; i <= 5; i++) { var go = GameObject.Find($"ally_0{i}"); if (go != null) list.Add(go); }
|
||||
try { var tagged = GameObject.FindGameObjectsWithTag("Ally"); foreach (var g in tagged) if (!list.Contains(g)) list.Add(g); } catch { }
|
||||
foreach (var go in GetAlliesCached())
|
||||
{
|
||||
if (go != null) list.Add(go);
|
||||
}
|
||||
try { var taggedE = GameObject.FindGameObjectsWithTag("Enemy"); foreach (var g in taggedE) if (!list.Contains(g)) list.Add(g); } catch { var single = GameObject.Find("thisEnemy"); if (single != null && !list.Contains(single)) list.Add(single); }
|
||||
break;
|
||||
}
|
||||
@@ -379,7 +435,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------- ���б�ݼ���ʾ�� -----------------------------
|
||||
// ----------------------------- ���б�ݼ���ʾ��?-----------------------------
|
||||
public void DealSingleEnemyDamage(GameObject caster, GameObject enemyTarget, float amount)
|
||||
{
|
||||
if (enemyTarget == null) { Debug.LogWarning("DealSingleEnemyDamage: enemyTarget == null"); return; }
|
||||
@@ -549,7 +605,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
return best;
|
||||
}
|
||||
|
||||
// ȡ��Ӣ�ۻ�����������ʹ�õ�ǰ����ƥ��ĵȼ��� attack������û���� 0
|
||||
// ȡ��Ӣ�ۻ�����������ʹ�õ�ǰ����ƥ��ĵȼ���?attack������û���� 0
|
||||
public int GetAllyBaseAttack(AllyHero_SO so)
|
||||
{
|
||||
if (so == null) return 0;
|
||||
@@ -559,8 +615,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;
|
||||
@@ -619,7 +675,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (alt != null)
|
||||
{
|
||||
caster = alt;
|
||||
Debug.Log($"UseSkillDefinition: resolved caster via teamUIController for slot {slotIndex} -> {caster.name}");
|
||||
LogVerbose($"UseSkillDefinition: resolved caster via teamUIController for slot {slotIndex} -> {caster.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -631,12 +687,12 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (byName != null)
|
||||
{
|
||||
caster = byName;
|
||||
Debug.Log($"UseSkillDefinition: resolved caster via name ally_0{slotIndex + 1} -> {caster.name}");
|
||||
LogVerbose($"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")}");
|
||||
LogVerbose($"[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
|
||||
@@ -648,7 +704,9 @@ public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
// Build variables from SO and caster; formula can be a plain number too
|
||||
var so = GetAllyHeroSOBySlot(slotIndex);
|
||||
var vars = new Dictionary<string, float>();
|
||||
var casterAlly = caster != null ? caster.GetComponent<AllyCombatant>() : null;
|
||||
var vars = _varsBuffer;
|
||||
vars.Clear();
|
||||
vars["slot"] = slotIndex;
|
||||
vars["attack"] = GetAllyBaseAttack(so);
|
||||
if (so != null && so.levelStats != null && so.levelStats.Count > 0)
|
||||
@@ -660,6 +718,9 @@ public class SkillBuilder : MonoBehaviour
|
||||
vars["damageResistance"] = lvl.damageResistance;
|
||||
vars["scoreEfficiency"] = lvl.scoreEfficiency;
|
||||
vars["attack"] = lvl.attack; // ensure attack from SO levelStats is available
|
||||
vars["level"] = lvl.levelID;
|
||||
vars["levelID"] = lvl.levelID;
|
||||
vars["currentLevel"] = lvl.levelID;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -667,9 +728,16 @@ public class SkillBuilder : MonoBehaviour
|
||||
vars["maxMana"] = 0f;
|
||||
vars["damageResistance"] = 0f;
|
||||
vars["scoreEfficiency"] = 1f;
|
||||
vars["level"] = 0f;
|
||||
vars["levelID"] = 0f;
|
||||
vars["currentLevel"] = 0f;
|
||||
}
|
||||
if (so != null) vars["ally_currentEXP"] = so.ally_currentEXP;
|
||||
else vars["ally_currentEXP"] = 0f;
|
||||
vars["currentMana"] = casterAlly != null ? casterAlly.currentMana : 0f;
|
||||
vars["currentScore"] = casterAlly != null ? casterAlly.currentScore : 0f;
|
||||
vars["idolScore"] = vars["currentScore"];
|
||||
vars["currentHP"] = casterAlly != null ? casterAlly.currentHP : 0f;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(def.formula))
|
||||
{
|
||||
@@ -723,6 +791,12 @@ public class SkillBuilder : MonoBehaviour
|
||||
foreach (var t in targets)
|
||||
{
|
||||
if (t == null) continue;
|
||||
|
||||
if (GameConfig.skillDebugMode)
|
||||
{
|
||||
Debug.Log($"<color=#00FFFF>[SkillDebug]</color> <color=#FFD700>ID: {def.skillId}</color> | <color=#00FF00>Trigger: {def.triggerCondition}</color> | <color=#FFA500>Target: {t.name}</color> | <color=#EE82EE>Effect: {def.effectType}</color> | <color=#FF4500>Value: {amountTotal:F2}</color>");
|
||||
}
|
||||
|
||||
var ally = t.GetComponent<AllyCombatant>();
|
||||
var ic = t.GetComponent<ICombatant>();
|
||||
|
||||
@@ -811,13 +885,16 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (ally != null) ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency - amountTotal);
|
||||
break;
|
||||
case EffectType.IncreaseAttack:
|
||||
if (ally != null) ally.attack += Mathf.CeilToInt(amountTotal);
|
||||
if (ally != null) ally.ModifyAttack(Mathf.CeilToInt(amountTotal));
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy5)) enemy5.attack += Mathf.CeilToInt(amountTotal);
|
||||
break;
|
||||
case EffectType.DecreaseAttack:
|
||||
if (ally != null) ally.attack = Mathf.Max(0, ally.attack - Mathf.CeilToInt(amountTotal));
|
||||
if (ally != null) ally.ModifyAttack(-Mathf.CeilToInt(amountTotal));
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy6)) enemy6.attack = Mathf.Max(0, enemy6.attack - Mathf.CeilToInt(amountTotal));
|
||||
break;
|
||||
case EffectType.RedirectNextDamageToSelf:
|
||||
if (ally != null) AllyCombatant.ActivateNextDamageRedirect(ally, def.defaultDuration);
|
||||
break;
|
||||
default:
|
||||
// non-direct path handled below, but keep compatibility
|
||||
ExecuteSkill(def.displayName ?? def.skillId, def.effectType, amountTotal, def.defaultSelector, caster, specificTarget, def.defaultDuration, def.defaultTickInterval);
|
||||
@@ -827,6 +904,10 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GameConfig.skillDebugMode)
|
||||
{
|
||||
Debug.Log($"<color=#00FFFF>[SkillDebug]</color> <color=#FFD700>ID: {def.skillId}</color> | <color=#00FF00>Trigger: {def.triggerCondition}</color> | <color=#FFA500>Target: (Resolving via EffectSystem)</color> | <color=#EE82EE>Effect: {def.effectType}</color> | <color=#FF4500>Value: {amountTotal:F2}</color>");
|
||||
}
|
||||
// For non-direct path, EffectSystem expects 'amount' to be total amount for sustained effects
|
||||
ExecuteSkill(def.displayName ?? def.skillId, def.effectType, amountTotal, def.defaultSelector, caster, specificTarget, def.defaultDuration, def.defaultTickInterval);
|
||||
}
|
||||
@@ -895,7 +976,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
var s = group.skills[i];
|
||||
if (s == null) continue;
|
||||
UseSkillDefinition(s, slotIndex, inputValue, specificTarget);
|
||||
Debug.Log($"[SkillBuilder] UseSkillGroupForSlot: cast skill {s.skillId} from group '{group.groupName}' for slot {slotIndex}");
|
||||
LogVerbose($"[SkillBuilder] UseSkillGroupForSlot: cast skill {s.skillId} from group '{group.groupName}' for slot {slotIndex}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,7 +1004,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (sk == null) continue;
|
||||
if (sk.triggerCondition == SkillDefinition.SkillTrigger.OnGameStart)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] TriggerOnGameStart: casting equipped group skill {sk.skillId} for slot {i}");
|
||||
LogVerbose($"[SkillBuilder] TriggerOnGameStart: casting equipped group skill {sk.skillId} for slot {i}");
|
||||
UseSkillDefinition(sk, i, -1f, null);
|
||||
}
|
||||
}
|
||||
@@ -940,7 +1021,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (sk == null) continue;
|
||||
if (sk.triggerCondition == SkillDefinition.SkillTrigger.OnGameStart)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] TriggerOnGameStart: casting group skill {sk.skillId} for slot {i}");
|
||||
LogVerbose($"[SkillBuilder] TriggerOnGameStart: casting group skill {sk.skillId} for slot {i}");
|
||||
UseSkillDefinition(sk, i, -1f, null);
|
||||
}
|
||||
}
|
||||
@@ -951,7 +1032,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition == SkillDefinition.SkillTrigger.OnGameStart)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] TriggerOnGameStart: casting primary skill {def.skillId} for slot {i}");
|
||||
LogVerbose($"[SkillBuilder] TriggerOnGameStart: casting primary skill {def.skillId} for slot {i}");
|
||||
UsePrimarySkillForSlot(i, -1f, null);
|
||||
}
|
||||
}
|
||||
@@ -985,7 +1066,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnEnemyDead) continue;
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyDead: slot {i+1} casting skill {def.skillId}");
|
||||
LogVerbose($"[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;
|
||||
@@ -1002,7 +1083,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnEnemyDead) continue;
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyDead: slot {i+1} casting skill {def.skillId}");
|
||||
LogVerbose($"[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);
|
||||
@@ -1013,7 +1094,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
var primary = so.GetPrimarySkill();
|
||||
if (primary != null && primary.triggerCondition == SkillDefinition.SkillTrigger.OnEnemyDead)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyDead: slot {i+1} casting primary skill {primary.skillId}");
|
||||
LogVerbose($"[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;
|
||||
@@ -1049,7 +1130,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
if (def == null) continue;
|
||||
if (def.triggerCondition != SkillDefinition.SkillTrigger.OnEnemyRevive) continue;
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting skill {def.skillId}");
|
||||
LogVerbose($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting skill {def.skillId}");
|
||||
UseSkillDefinition(def, i, -1f, enemy != null ? enemy.gameObject : null);
|
||||
}
|
||||
}
|
||||
@@ -1063,7 +1144,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
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)");
|
||||
LogVerbose($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting skill {def.skillId} (from primary group)");
|
||||
UseSkillDefinition(def, i, -1f, enemy != null ? enemy.gameObject : null);
|
||||
}
|
||||
continue;
|
||||
@@ -1072,7 +1153,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
var primary2 = so.GetPrimarySkill();
|
||||
if (primary2 != null && primary2.triggerCondition == SkillDefinition.SkillTrigger.OnEnemyRevive)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting primary skill {primary2.skillId}");
|
||||
LogVerbose($"[SkillBuilder] TriggerOnEnemyRevive: slot {i+1} casting primary skill {primary2.skillId}");
|
||||
UsePrimarySkillForSlot(i, -1f, enemy != null ? enemy.gameObject : null);
|
||||
}
|
||||
}
|
||||
@@ -1137,10 +1218,11 @@ public class SkillBuilder : MonoBehaviour
|
||||
// noteType indicates whether the hit event came from a Tap or Hold (tail)
|
||||
public bool NotifyNoteHit(int trackIndex, string judgeResult, SkillDefinition.NoteTypeTrigger noteType = SkillDefinition.NoteTypeTrigger.Tap, string uniqueNoteId = null)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] NotifyNoteHit RECEIVED: track={trackIndex} judge={judgeResult} noteType={noteType} uniqueId={uniqueNoteId}");
|
||||
LogVerbose($"[SkillBuilder] NotifyNoteHit RECEIVED: track={trackIndex} judge={judgeResult} noteType={noteType} uniqueId={uniqueNoteId}");
|
||||
// cleanup old processed ids (> 10s)
|
||||
float nowCleanup = Time.time;
|
||||
var toRemove = new List<string>();
|
||||
_tmpNoteIdRemoval.Clear();
|
||||
var toRemove = _tmpNoteIdRemoval;
|
||||
foreach (var kv in _processedNoteHitTimestamps)
|
||||
{
|
||||
if (nowCleanup - kv.Value > 10f) toRemove.Add(kv.Key);
|
||||
@@ -1167,21 +1249,21 @@ public class SkillBuilder : MonoBehaviour
|
||||
try { ApplySharedOnNoteHit(trackIndex, judgeResult); } catch (System.Exception ex) { Debug.LogError($"[SkillBuilder] ApplySharedOnNoteHit threw: {ex}"); }
|
||||
}
|
||||
|
||||
if (trackIndex < 0) { Debug.Log("[SkillBuilder] NotifyNoteHit: invalid trackIndex"); return false; }
|
||||
if (trackIndex < 0) { LogVerbose("[SkillBuilder] NotifyNoteHit: invalid trackIndex"); return false; }
|
||||
var so = GetAllyHeroSOBySlot(trackIndex);
|
||||
if (so == null)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] NotifyNoteHit: no SO found for slot {trackIndex}, attempting fallback resolution...");
|
||||
LogVerbose($"[SkillBuilder] NotifyNoteHit: no SO found for slot {trackIndex}, attempting fallback resolution...");
|
||||
// Dump current UI slot ids for diagnostics
|
||||
if (teamUIController.Instance != null && teamUIController.Instance.allySlotIds != null)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] teamUIController.allySlotIds = [{string.Join(",", teamUIController.Instance.allySlotIds)}]");
|
||||
LogVerbose($"[SkillBuilder] teamUIController.allySlotIds = [{string.Join(",", teamUIController.Instance.allySlotIds)}]");
|
||||
}
|
||||
// Try to find ally GameObject named by convention
|
||||
var foundGO = GameObject.Find($"ally_0{trackIndex + 1}");
|
||||
if (foundGO != null)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] Found GameObject by name ally_0{trackIndex + 1}: {foundGO.name}");
|
||||
LogVerbose($"[SkillBuilder] Found GameObject by name ally_0{trackIndex + 1}: {foundGO.name}");
|
||||
// try to map to UI slot
|
||||
var ui = teamUIController.Instance;
|
||||
if (ui != null && ui.allySlotIds != null)
|
||||
@@ -1192,7 +1274,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
if (slotObj == null) continue;
|
||||
if (slotObj == foundGO || foundGO.transform.IsChildOf(slotObj.transform))
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] Resolved fallback slot {i} for GameObject {foundGO.name}");
|
||||
LogVerbose($"[SkillBuilder] Resolved fallback slot {i} for GameObject {foundGO.name}");
|
||||
trackIndex = i; // override
|
||||
so = GetAllyHeroSOBySlot(trackIndex);
|
||||
break;
|
||||
@@ -1202,7 +1284,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
if (so == null)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] NotifyNoteHit: still no SO for resolved slot {trackIndex}, aborting NotifyNoteHit");
|
||||
LogVerbose($"[SkillBuilder] NotifyNoteHit: still no SO for resolved slot {trackIndex}, aborting NotifyNoteHit");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1252,7 +1334,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
|
||||
// trigger
|
||||
Debug.Log($"[SkillBuilder] NotifyNoteHit: triggering equipped skill {def.skillId} for slot {trackIndex} due to note hit {judgeResult} (noteType={noteType})");
|
||||
LogVerbose($"[SkillBuilder] NotifyNoteHit: triggering equipped skill {def.skillId} for slot {trackIndex} due to note hit {judgeResult} (noteType={noteType})");
|
||||
UseSkillDefinition(def, trackIndex, -1f, null);
|
||||
_lastOnNoteHitTriggerTime[key] = now;
|
||||
anyTriggered = true;
|
||||
@@ -1263,10 +1345,10 @@ public class SkillBuilder : MonoBehaviour
|
||||
|
||||
// Fallback to previous behavior using primary skill (availableSkills)
|
||||
var defPrimary = so.GetPrimarySkill();
|
||||
if (defPrimary == null) { Debug.Log($"[SkillBuilder] NotifyNoteHit: no primary skill for slot {trackIndex}"); return false; }
|
||||
if (defPrimary == null) { LogVerbose($"[SkillBuilder] NotifyNoteHit: no primary skill for slot {trackIndex}"); return false; }
|
||||
if (defPrimary.triggerCondition != SkillDefinition.SkillTrigger.OnNoteHit)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] NotifyNoteHit: primary skill {defPrimary.skillId} for slot {trackIndex} is not set to OnNoteHit (actual={defPrimary.triggerCondition}), rejecting");
|
||||
LogVerbose($"[SkillBuilder] NotifyNoteHit: primary skill {defPrimary.skillId} for slot {trackIndex} is not set to OnNoteHit (actual={defPrimary.triggerCondition}), rejecting");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1276,10 +1358,10 @@ public class SkillBuilder : MonoBehaviour
|
||||
switch (defPrimary.noteTriggerType)
|
||||
{
|
||||
case SkillDefinition.NoteTypeTrigger.Tap:
|
||||
if (effectiveNoteTypePrimary != SkillDefinition.NoteTypeTrigger.Tap) { Debug.Log($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} requires Tap but event is {noteType}, rejecting"); return false; }
|
||||
if (effectiveNoteTypePrimary != SkillDefinition.NoteTypeTrigger.Tap) { LogVerbose($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} requires Tap but event is {noteType}, rejecting"); return false; }
|
||||
break;
|
||||
case SkillDefinition.NoteTypeTrigger.Hold:
|
||||
if (noteType != SkillDefinition.NoteTypeTrigger.Hold) { Debug.Log($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} requires Hold but event is {noteType}, rejecting"); return false; }
|
||||
if (noteType != SkillDefinition.NoteTypeTrigger.Hold) { LogVerbose($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} requires Hold but event is {noteType}, rejecting"); return false; }
|
||||
break;
|
||||
case SkillDefinition.NoteTypeTrigger.Either:
|
||||
break;
|
||||
@@ -1288,12 +1370,12 @@ public class SkillBuilder : MonoBehaviour
|
||||
int qualityPrimary = JudgeQualityFromString(judgeResult);
|
||||
if (defPrimary.onNoteHitMinThreshold == SkillDefinition.NoteTriggerThreshold.Miss)
|
||||
{
|
||||
if (qualityPrimary != 0) { Debug.Log($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} is Miss-only but quality={qualityPrimary}, rejecting"); return false; }
|
||||
if (qualityPrimary != 0) { LogVerbose($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} is Miss-only but quality={qualityPrimary}, rejecting"); return false; }
|
||||
}
|
||||
else
|
||||
{
|
||||
int required = (int)defPrimary.onNoteHitMinThreshold;
|
||||
if (qualityPrimary < required) { Debug.Log($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} requires quality>={required} but got {qualityPrimary}, rejecting"); return false; }
|
||||
if (qualityPrimary < required) { LogVerbose($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} requires quality>={required} but got {qualityPrimary}, rejecting"); return false; }
|
||||
}
|
||||
|
||||
string keyPrimary = $"{trackIndex}:{defPrimary.skillId}";
|
||||
@@ -1302,12 +1384,12 @@ public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
if (nowPrimary - lastPrimary < defPrimary.onNoteHitCooldown)
|
||||
{
|
||||
Debug.Log($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} on cooldown for slot {trackIndex}");
|
||||
LogVerbose($"[SkillBuilder] NotifyNoteHit: skill {defPrimary.skillId} on cooldown for slot {trackIndex}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[SkillBuilder] NotifyNoteHit: triggering primary skill {defPrimary.skillId} for slot {trackIndex} due to note hit {judgeResult} (noteType={noteType})");
|
||||
LogVerbose($"[SkillBuilder] NotifyNoteHit: triggering primary skill {defPrimary.skillId} for slot {trackIndex} due to note hit {judgeResult} (noteType={noteType})");
|
||||
UsePrimarySkillForSlot(trackIndex, -1f, null);
|
||||
_lastOnNoteHitTriggerTime[keyPrimary] = nowPrimary;
|
||||
return true;
|
||||
@@ -1323,8 +1405,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)
|
||||
// ----------------------------- ʾ����Ϊ���? ��װһ����ݺ������û�ʾ����?-----------------------------
|
||||
// ���?(����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);
|
||||
@@ -1423,3 +1505,13 @@ public class SkillBuilder : MonoBehaviour
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user