展前冒死重构
This commit is contained in:
@@ -2053,6 +2053,7 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
else
|
||||
{
|
||||
SkillBuilder.Instance?.TriggerOnAdjacentAllySkillCast(slotIndex);
|
||||
GameplayLevelRuleEventBus.NotifyAllySkillCast(slotIndex, GameplayClock.NowSongTime);
|
||||
}
|
||||
return anyTriggered;
|
||||
}
|
||||
|
||||
@@ -90,19 +90,46 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
SkillBuilder.Instance.TriggerOnEnemyRevive(this);
|
||||
}
|
||||
|
||||
// Trigger primary skill on revive if defined and trigger condition matches
|
||||
TryTriggerPrimarySkill(SkillDefinition.SkillTrigger.OnEnemyRevive);
|
||||
// Trigger configured enemy skills on revive if defined and trigger condition matches.
|
||||
TryTriggerConfiguredSkills(SkillDefinition.SkillTrigger.OnEnemyRevive);
|
||||
}
|
||||
|
||||
// Documentation text normalized.
|
||||
private void TryTriggerPrimarySkill(SkillDefinition.SkillTrigger when)
|
||||
private void TryTriggerConfiguredSkills(SkillDefinition.SkillTrigger when)
|
||||
{
|
||||
if (sourceData == null) return;
|
||||
var def = sourceData.GetPrimarySkill();
|
||||
if (def == null) return;
|
||||
|
||||
HashSet<SkillDefinition> executed = new HashSet<SkillDefinition>();
|
||||
SkillDefinition primary = sourceData.GetPrimarySkill();
|
||||
ExecuteEnemySkillIfMatched(primary, when, executed);
|
||||
|
||||
int[] groupIds = sourceData.GetEffectiveEquippedSkillGroupIDs();
|
||||
if (groupIds == null || groupIds.Length == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < groupIds.Length; i++)
|
||||
{
|
||||
int groupId = groupIds[i];
|
||||
if (groupId == 0) continue;
|
||||
|
||||
SkillGroup group = sourceData.GetSkillGroupByID(groupId);
|
||||
if (group == null || group.skills == null)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < group.skills.Length; j++)
|
||||
{
|
||||
ExecuteEnemySkillIfMatched(group.skills[j], when, executed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteEnemySkillIfMatched(SkillDefinition def, SkillDefinition.SkillTrigger when, HashSet<SkillDefinition> executed)
|
||||
{
|
||||
if (def == null || executed == null) return;
|
||||
if (executed.Contains(def)) return;
|
||||
if (def.triggerCondition != when) return;
|
||||
|
||||
// Evaluate formula into amount using enemy fields as variables
|
||||
executed.Add(def);
|
||||
|
||||
float perTick = 0f;
|
||||
var vars = new Dictionary<string, float>();
|
||||
vars["maxHP"] = maxHP;
|
||||
@@ -135,7 +162,6 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
totalAmount = perTick * ticks;
|
||||
}
|
||||
|
||||
// Use SkillBuilder to execute effect, using this Enemy GameObject as caster
|
||||
if (SkillBuilder.Instance != null)
|
||||
{
|
||||
SkillBuilder.Instance.ExecuteSkill(def.displayName ?? def.skillId, def.effectType, totalAmount, def.defaultSelector, this.gameObject, null, def.defaultDuration, def.defaultTickInterval);
|
||||
@@ -190,6 +216,11 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
}
|
||||
}
|
||||
|
||||
if (actual > 0)
|
||||
{
|
||||
GameplayLevelRuleEventBus.NotifyEnemyDamaged(this, actual, source);
|
||||
}
|
||||
|
||||
// grant mana based on sourceData setting
|
||||
if (sourceData != null && sourceData.manaGainOnDamagePercent > 0f && maxMana > 0)
|
||||
{
|
||||
@@ -352,7 +383,16 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
var type = actual > 0 ? iNumberPrefabController.InstantNumberType.Heal : iNumberPrefabController.InstantNumberType.Damage;
|
||||
iNumberPrefabController.SpawnForEnemyStatic(type, actual);
|
||||
}
|
||||
if (currentHP <= 0) Die();
|
||||
if (currentHP <= 0)
|
||||
{
|
||||
if (GameplayLevelRuleEventBus.ShouldPreventEnemyDeath(this))
|
||||
{
|
||||
currentHP = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyMana(int delta, bool animate = true)
|
||||
@@ -371,18 +411,18 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
}
|
||||
}
|
||||
|
||||
// If mana reached full, trigger primary skill and reset mana
|
||||
// If mana reached full, trigger configured skills and reset mana
|
||||
if (currentMana >= maxMana && maxMana > 0 && Application.isPlaying)
|
||||
{
|
||||
Debug.Log($"[EnemyCombatant] Mana full for {gameObject.name} (slot) - triggering OnManaFull");
|
||||
try
|
||||
{
|
||||
// Trigger primary skill configured for OnManaFull
|
||||
TryTriggerPrimarySkill(SkillDefinition.SkillTrigger.OnManaFull);
|
||||
TryTriggerConfiguredSkills(SkillDefinition.SkillTrigger.OnManaFull);
|
||||
GameplayLevelRuleEventBus.NotifyEnemyManaFull(this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[EnemyCombatant] TryTriggerPrimarySkill threw: {ex}");
|
||||
Debug.LogError($"[EnemyCombatant] OnManaFull handling threw: {ex}");
|
||||
}
|
||||
|
||||
// reset mana after casting
|
||||
@@ -457,8 +497,8 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger primary skill on death if configured (enemy's own skill)
|
||||
TryTriggerPrimarySkill(SkillDefinition.SkillTrigger.OnEnemyDead);
|
||||
// Trigger configured enemy skills on death if configured.
|
||||
TryTriggerConfiguredSkills(SkillDefinition.SkillTrigger.OnEnemyDead);
|
||||
|
||||
// notify listeners (UI/manager) that enemy died AFTER triggering skills so they operate on the current instance
|
||||
OnEnemyDied?.Invoke(this);
|
||||
|
||||
@@ -1369,6 +1369,10 @@ ResolvedGroup:
|
||||
}
|
||||
catch { /* never break gameplay because of optional UI */ }
|
||||
|
||||
// Spawn the track skill popup as soon as the skill is confirmed for this frame.
|
||||
// This avoids later target-resolution branches swallowing the popup on early returns.
|
||||
SpawnTrackSkillPopup(slotIndex, smallSkillName, smallSkillIcon);
|
||||
|
||||
GameObject caster = GetAllyObjectBySlot(slotIndex);
|
||||
if (caster == null)
|
||||
{
|
||||
@@ -1926,7 +1930,10 @@ ResolvedGroup:
|
||||
}
|
||||
|
||||
// For listed skills: do not stack when retriggered, only refresh duration.
|
||||
if (appliedRefreshOnly) return;
|
||||
if (appliedRefreshOnly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// For non-direct path, EffectSystem expects 'amount' to be total amount for sustained effects
|
||||
@@ -1986,7 +1993,6 @@ ResolvedGroup:
|
||||
GameplaySkillLogger.RecordSkillRelease(casterDisplayName, skillDisplayName, def.effectType.ToString(), effectSummary, targetSummary);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2111,6 +2117,21 @@ ResolvedGroup:
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly string[] s_trackSkillPopupColors = { "red", "green", "yellow", "purple", "blue" };
|
||||
|
||||
private void SpawnTrackSkillPopup(int slotIndex, string skillName, Sprite skillIcon)
|
||||
{
|
||||
if (slotIndex < 0 || slotIndex >= s_trackSkillPopupColors.Length)
|
||||
return;
|
||||
|
||||
var fx = Animation_GenerateJudgementSituationPrefab.Instance
|
||||
?? SceneObjectLookupCache.FindAny<Animation_GenerateJudgementSituationPrefab>();
|
||||
if (fx == null)
|
||||
return;
|
||||
|
||||
fx.SpawnTrackSkillPrefab(s_trackSkillPopupColors[slotIndex], skillIcon, skillName ?? string.Empty);
|
||||
}
|
||||
|
||||
private bool HandleEquipSkillGhoulSchool(int slotIndex)
|
||||
{
|
||||
_equipGhoulSchoolActiveSlots.Add(slotIndex);
|
||||
|
||||
Reference in New Issue
Block a user