gameplay所有基本功能都装了,加入了全局警告。加入飘字等各种东西。
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -112,6 +112,9 @@ public class SkillBuilder : MonoBehaviour
|
||||
public EffectType effectType;
|
||||
public float floatDelta;
|
||||
public int intDelta;
|
||||
public string budeffIconId;
|
||||
public int budeffSlotIndex = -1;
|
||||
public int budeffEnemyInstanceId;
|
||||
}
|
||||
|
||||
private void PrewarmAllyHeroSOIndex()
|
||||
@@ -205,6 +208,12 @@ public class SkillBuilder : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
// Log Miss event to feed (since HP loss will occur)
|
||||
string mName = "Unknown";
|
||||
if (so != null && !string.IsNullOrEmpty(so.ally_heroName)) mName = so.ally_heroName;
|
||||
else if (ally != null) mName = ally.name; // fallback to GameObject name
|
||||
SkillTriggerFeedUI.PushMiss(mName);
|
||||
|
||||
float missBase = (levelInfo != null) ? levelInfo.missHpLossBase : missHpLossBase;
|
||||
|
||||
// 播放敌人攻击特效,并将伤害逻辑延迟到特效到达时执行
|
||||
@@ -751,6 +760,30 @@ public class SkillBuilder : MonoBehaviour
|
||||
return def.skillId + ":" + target.GetInstanceID();
|
||||
}
|
||||
|
||||
private static bool ShouldSpawnApprForEffect(EffectType effectType)
|
||||
{
|
||||
switch (effectType)
|
||||
{
|
||||
case EffectType.DamageOverTimeAlly:
|
||||
case EffectType.ReduceEnemyHealOverTime:
|
||||
case EffectType.IncreaseMaxHP:
|
||||
case EffectType.DecreaseMaxHP:
|
||||
case EffectType.IncreaseMaxMana:
|
||||
case EffectType.DecreaseMaxMana:
|
||||
case EffectType.IncreaseScoreEfficiency:
|
||||
case EffectType.DecreaseScoreEfficiency:
|
||||
case EffectType.IncreaseDamageResistance:
|
||||
case EffectType.DecreaseDamageResistance:
|
||||
case EffectType.IncreaseAttack:
|
||||
case EffectType.DecreaseAttack:
|
||||
case EffectType.RedirectNextDamageToSelf:
|
||||
case EffectType.RedirectSelfDamageToAdjacent:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryApplyRefreshOnlyTimedEffect(SkillDefinition def, GameObject target, float amount, float duration)
|
||||
{
|
||||
if (!IsRefreshOnlyTimedSkill(def)) return false;
|
||||
@@ -773,6 +806,41 @@ public class SkillBuilder : MonoBehaviour
|
||||
return false;
|
||||
}
|
||||
|
||||
var ally = target.GetComponent<AllyCombatant>() ?? target.GetComponentInChildren<AllyCombatant>(true);
|
||||
var enemy = target.GetComponent<EnemyCombatant>() ?? target.GetComponentInChildren<EnemyCombatant>(true);
|
||||
if (iBudeffPrefabController.Instance != null)
|
||||
{
|
||||
PlayerBudeffIconType? iconType = null;
|
||||
switch (def.effectType)
|
||||
{
|
||||
case EffectType.IncreaseScoreEfficiency: iconType = PlayerBudeffIconType.ot_scoreEfficiency_up; break;
|
||||
case EffectType.DecreaseScoreEfficiency: iconType = PlayerBudeffIconType.ot_scoreEfficiency_down; break;
|
||||
case EffectType.IncreaseDamageResistance: iconType = PlayerBudeffIconType.ot_defend_up; break;
|
||||
case EffectType.DecreaseDamageResistance: iconType = PlayerBudeffIconType.ot_defend_down; break;
|
||||
case EffectType.IncreaseAttack: iconType = PlayerBudeffIconType.ot_atk_up; break;
|
||||
case EffectType.DecreaseAttack: iconType = PlayerBudeffIconType.ot_atk_down; break;
|
||||
case EffectType.IncreaseMaxHP: iconType = PlayerBudeffIconType.ot_maxHP_up; break;
|
||||
case EffectType.DecreaseMaxHP: iconType = PlayerBudeffIconType.ot_maxHP_down; break;
|
||||
case EffectType.IncreaseMaxMana: iconType = PlayerBudeffIconType.ot_maxMana_up; break;
|
||||
case EffectType.DecreaseMaxMana: iconType = PlayerBudeffIconType.ot_maxMana_down; break;
|
||||
}
|
||||
|
||||
if (iconType.HasValue)
|
||||
{
|
||||
float v = applied.intDelta != 0 ? applied.intDelta : applied.floatDelta;
|
||||
if (ally != null)
|
||||
{
|
||||
applied.budeffSlotIndex = ally.slotIndex;
|
||||
applied.budeffIconId = iBudeffPrefabController.Instance.RegisterTimedEffect(ally, iconType.Value, v, duration);
|
||||
}
|
||||
else if (enemy != null && def.effectType != EffectType.IncreaseScoreEfficiency && def.effectType != EffectType.DecreaseScoreEfficiency)
|
||||
{
|
||||
applied.budeffEnemyInstanceId = enemy.GetInstanceID();
|
||||
applied.budeffIconId = iBudeffPrefabController.Instance.RegisterEnemyTimedEffect(enemy, iconType.Value, v, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_refreshOnlyTimedEffectStates[key] = applied;
|
||||
_refreshOnlyTimedEffectCoroutines[key] = StartCoroutine(RemoveRefreshOnlyTimedEffectAfterDuration(key, target, duration));
|
||||
return true;
|
||||
@@ -798,21 +866,28 @@ public class SkillBuilder : MonoBehaviour
|
||||
var enemy = target != null ? target.GetComponent<EnemyCombatant>() : null;
|
||||
if (ally == null && enemy == null) return false;
|
||||
|
||||
string targetName = ally != null ? ally.allyName : (enemy != null && enemy.sourceData != null ? enemy.sourceData.enemyName : target.name);
|
||||
|
||||
switch (effectType)
|
||||
{
|
||||
case EffectType.IncreaseScoreEfficiency:
|
||||
case EffectType.DecreaseScoreEfficiency:
|
||||
if (ally == null) return false;
|
||||
float scoreDelta = effectType == EffectType.IncreaseScoreEfficiency ? amount : -amount;
|
||||
float oldScore = ally.scoreEfficiency;
|
||||
ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency + scoreDelta);
|
||||
CheckLimitAndWarn(targetName, "分数效率", oldScore, ally.scoreEfficiency, scoreDelta);
|
||||
state = new RefreshOnlyTimedState { effectType = effectType, floatDelta = scoreDelta };
|
||||
return true;
|
||||
|
||||
case EffectType.IncreaseDamageResistance:
|
||||
case EffectType.DecreaseDamageResistance:
|
||||
float resistDelta = effectType == EffectType.IncreaseDamageResistance ? amount : -amount;
|
||||
if (ally != null) ally.damageResistance = Mathf.Clamp01(ally.damageResistance + resistDelta);
|
||||
else enemy.damageResistance = Mathf.Clamp01(enemy.damageResistance + resistDelta);
|
||||
float oldResist = ally != null ? ally.damageResistance : enemy.damageResistance;
|
||||
if (ally != null) ally.damageResistance = ClampDamageResistance(ally.damageResistance + resistDelta);
|
||||
else enemy.damageResistance = ClampDamageResistance(enemy.damageResistance + resistDelta);
|
||||
float newResist = ally != null ? ally.damageResistance : enemy.damageResistance;
|
||||
CheckLimitAndWarn(targetName, "伤害抗性", oldResist, newResist, resistDelta);
|
||||
state = new RefreshOnlyTimedState { effectType = effectType, floatDelta = resistDelta };
|
||||
return true;
|
||||
|
||||
@@ -820,8 +895,11 @@ public class SkillBuilder : MonoBehaviour
|
||||
case EffectType.DecreaseAttack:
|
||||
int atkDelta = Mathf.CeilToInt(Mathf.Abs(amount));
|
||||
if (effectType == EffectType.DecreaseAttack) atkDelta = -atkDelta;
|
||||
int oldAtk = ally != null ? ally.attack : enemy.attack;
|
||||
if (ally != null) ally.ModifyAttack(atkDelta);
|
||||
else enemy.ModifyAttack(atkDelta);
|
||||
int newAtk = ally != null ? ally.attack : enemy.attack;
|
||||
CheckLimitAndWarnInt(targetName, "攻击力", oldAtk, newAtk, atkDelta);
|
||||
state = new RefreshOnlyTimedState { effectType = effectType, intDelta = atkDelta };
|
||||
return true;
|
||||
|
||||
@@ -829,8 +907,11 @@ public class SkillBuilder : MonoBehaviour
|
||||
case EffectType.DecreaseMaxHP:
|
||||
int hpDelta = Mathf.CeilToInt(Mathf.Abs(amount));
|
||||
if (effectType == EffectType.DecreaseMaxHP) hpDelta = -hpDelta;
|
||||
int oldHP = ally != null ? ally.maxHP : enemy.maxHP;
|
||||
if (ally != null) ally.SetMaxHP(Mathf.Max(1, ally.maxHP + hpDelta), false);
|
||||
else enemy.SetMaxHP(Mathf.Max(1, enemy.maxHP + hpDelta), false);
|
||||
int newHP = ally != null ? ally.maxHP : enemy.maxHP;
|
||||
CheckLimitAndWarnInt(targetName, "最大生命值", oldHP, newHP, hpDelta);
|
||||
state = new RefreshOnlyTimedState { effectType = effectType, intDelta = hpDelta };
|
||||
return true;
|
||||
|
||||
@@ -838,8 +919,11 @@ public class SkillBuilder : MonoBehaviour
|
||||
case EffectType.DecreaseMaxMana:
|
||||
int manaDelta = Mathf.CeilToInt(Mathf.Abs(amount));
|
||||
if (effectType == EffectType.DecreaseMaxMana) manaDelta = -manaDelta;
|
||||
int oldMana = ally != null ? ally.maxMana : enemy.maxMana;
|
||||
if (ally != null) ally.SetMaxMana(Mathf.Max(1, ally.maxMana + manaDelta), false);
|
||||
else enemy.SetMaxMana(Mathf.Max(1, enemy.maxMana + manaDelta), false);
|
||||
int newMana = ally != null ? ally.maxMana : enemy.maxMana;
|
||||
CheckLimitAndWarnInt(targetName, "最大法力值", oldMana, newMana, manaDelta);
|
||||
state = new RefreshOnlyTimedState { effectType = effectType, intDelta = manaDelta };
|
||||
return true;
|
||||
}
|
||||
@@ -847,6 +931,30 @@ public class SkillBuilder : MonoBehaviour
|
||||
return false;
|
||||
}
|
||||
|
||||
private void CheckLimitAndWarn(string targetName, string attrName, float startValue, float newValue, float attemptedDelta)
|
||||
{
|
||||
float actualChange = newValue - startValue;
|
||||
// If we attempted a change but the actual change differs significantly from attempted, we hit a limit.
|
||||
if (Mathf.Abs(attemptedDelta) > 0.001f && Mathf.Abs(actualChange - attemptedDelta) > 0.001f)
|
||||
{
|
||||
load_skillwarn.Instance?.ShowWarning(targetName, attrName);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckLimitAndWarnInt(string targetName, string attrName, int startValue, int newValue, int attemptedDelta)
|
||||
{
|
||||
int actualChange = newValue - startValue;
|
||||
if (attemptedDelta != 0 && actualChange != attemptedDelta)
|
||||
{
|
||||
load_skillwarn.Instance?.ShowWarning(targetName, attrName);
|
||||
}
|
||||
}
|
||||
|
||||
private static float ClampDamageResistance(float value)
|
||||
{
|
||||
return Mathf.Min(value, 1f);
|
||||
}
|
||||
|
||||
private void RevertRefreshOnlyTimedEffect(GameObject target, RefreshOnlyTimedState state)
|
||||
{
|
||||
if (target == null || state == null) return;
|
||||
@@ -864,8 +972,8 @@ public class SkillBuilder : MonoBehaviour
|
||||
|
||||
case EffectType.IncreaseDamageResistance:
|
||||
case EffectType.DecreaseDamageResistance:
|
||||
if (ally != null) ally.damageResistance = Mathf.Clamp01(ally.damageResistance - state.floatDelta);
|
||||
else enemy.damageResistance = Mathf.Clamp01(enemy.damageResistance - state.floatDelta);
|
||||
if (ally != null) ally.damageResistance = ClampDamageResistance(ally.damageResistance - state.floatDelta);
|
||||
else enemy.damageResistance = ClampDamageResistance(enemy.damageResistance - state.floatDelta);
|
||||
break;
|
||||
|
||||
case EffectType.IncreaseAttack:
|
||||
@@ -886,6 +994,15 @@ public class SkillBuilder : MonoBehaviour
|
||||
else enemy.SetMaxMana(Mathf.Max(1, enemy.maxMana - state.intDelta), false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(state.budeffIconId))
|
||||
{
|
||||
if (state.budeffSlotIndex >= 0) iBudeffPrefabController.Instance?.UnregisterTimedEffect(state.budeffSlotIndex, state.budeffIconId);
|
||||
else if (state.budeffEnemyInstanceId != 0) iBudeffPrefabController.Instance?.UnregisterEnemyTimedEffect(state.budeffEnemyInstanceId, state.budeffIconId);
|
||||
state.budeffIconId = null;
|
||||
state.budeffSlotIndex = -1;
|
||||
state.budeffEnemyInstanceId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryApplyRefreshOnlyOverTimeEffect(SkillDefinition def, GameObject target, float totalAmount, GameObject source)
|
||||
@@ -973,15 +1090,15 @@ public class SkillBuilder : MonoBehaviour
|
||||
{
|
||||
if (def == null) { Debug.LogWarning("UseSkillDefinition: null def"); return; }
|
||||
|
||||
int groupId = 0;
|
||||
string smallSkillName = null;
|
||||
Sprite smallSkillIcon = null;
|
||||
// Resolve group/icon metadata for the ally HUD skill icon queue.
|
||||
try
|
||||
{
|
||||
var heroSoForName = GetAllyHeroSOBySlot(slotIndex);
|
||||
|
||||
// Documentation text normalized.
|
||||
int groupId = 0;
|
||||
string smallSkillName = null;
|
||||
Sprite smallSkillIcon = null;
|
||||
if (heroSoForName != null && heroSoForName.skillGroups != null)
|
||||
{
|
||||
foreach (var g in heroSoForName.skillGroups)
|
||||
@@ -1043,6 +1160,13 @@ ResolvedGroup:
|
||||
if (!s_lastSkillFeedFrameByKey.TryGetValue(key, out lastFrame) || lastFrame != frame)
|
||||
{
|
||||
s_lastSkillFeedFrameByKey[key] = frame;
|
||||
|
||||
// Push to text feed
|
||||
if (heroSoForName != null && !string.IsNullOrEmpty(heroSoForName.ally_heroName))
|
||||
{
|
||||
SkillTriggerFeedUI.Push(heroSoForName.ally_heroName, smallSkillName);
|
||||
}
|
||||
|
||||
// Ally HUD skill icon feed (newest first, max 3).
|
||||
if (smallSkillIcon != null && slotIndex >= 0 && slotIndex < 5)
|
||||
{
|
||||
@@ -1247,6 +1371,12 @@ ResolvedGroup:
|
||||
var ally = t.GetComponent<AllyCombatant>();
|
||||
var ic = t.GetComponent<ICombatant>();
|
||||
|
||||
if (ally != null && ShouldSpawnApprForEffect(def.effectType))
|
||||
{
|
||||
var apprSprite = iBudeffPrefabController.Instance != null ? iBudeffPrefabController.Instance.GetSpriteForEffect(def.effectType) : null;
|
||||
if (apprSprite != null) iBudeffPrefabController.Instance?.SpawnApprForSlot(ally.slotIndex, apprSprite);
|
||||
}
|
||||
|
||||
switch (def.effectType)
|
||||
{
|
||||
case EffectType.DamageSingleEnemy:
|
||||
@@ -1263,7 +1393,25 @@ ResolvedGroup:
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(ApplyDamageOverTimeDirect(t, amountTotal, def.defaultDuration, def.GetEffectiveTickInterval(), caster));
|
||||
string iconId = null;
|
||||
int allySlotIndex = -1;
|
||||
int enemyInstanceId = 0;
|
||||
var enemyDot = t.GetComponent<EnemyCombatant>() ?? t.GetComponentInChildren<EnemyCombatant>(true);
|
||||
if (enemyDot != null)
|
||||
{
|
||||
int ticks = Mathf.Max(1, Mathf.CeilToInt(def.defaultDuration / def.GetEffectiveTickInterval()));
|
||||
float perTick = amountTotal / ticks;
|
||||
iconId = iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemyDot, PlayerBudeffIconType.ot_bleeding, perTick, def.defaultDuration);
|
||||
enemyInstanceId = enemyDot.GetInstanceID();
|
||||
}
|
||||
else if (ally != null)
|
||||
{
|
||||
int ticks = Mathf.Max(1, Mathf.CeilToInt(def.defaultDuration / def.GetEffectiveTickInterval()));
|
||||
float perTick = amountTotal / ticks;
|
||||
iconId = iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_bleeding, perTick, def.defaultDuration);
|
||||
allySlotIndex = ally.slotIndex;
|
||||
}
|
||||
StartCoroutine(ApplyDamageOverTimeDirect(t, amountTotal, def.defaultDuration, def.GetEffectiveTickInterval(), caster, iconId, allySlotIndex, enemyInstanceId));
|
||||
}
|
||||
break;
|
||||
case EffectType.HealSingleSelf:
|
||||
@@ -1332,20 +1480,60 @@ ResolvedGroup:
|
||||
break;
|
||||
// Documentation text normalized.
|
||||
case EffectType.IncreaseMaxHP:
|
||||
if (ally != null) ally.SetMaxHP(ally.maxHP + Mathf.CeilToInt(amountTotal), false);
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy)) enemy.SetMaxHP(enemy.maxHP + Mathf.CeilToInt(amountTotal), false);
|
||||
if (ally != null)
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
ally.SetMaxHP(ally.maxHP + d, false);
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_maxHP_up, d, 0f);
|
||||
}
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy))
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
enemy.SetMaxHP(enemy.maxHP + d, false);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy, PlayerBudeffIconType.ot_maxHP_up, d, 0f);
|
||||
}
|
||||
break;
|
||||
case EffectType.DecreaseMaxHP:
|
||||
if (ally != null) ally.SetMaxHP(Mathf.Max(1, ally.maxHP - Mathf.CeilToInt(amountTotal)), false);
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy2)) enemy2.SetMaxHP(Mathf.Max(1, enemy2.maxHP - Mathf.CeilToInt(amountTotal)), false);
|
||||
if (ally != null)
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
ally.SetMaxHP(Mathf.Max(1, ally.maxHP - d), false);
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_maxHP_down, -d, 0f);
|
||||
}
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy2))
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
enemy2.SetMaxHP(Mathf.Max(1, enemy2.maxHP - d), false);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy2, PlayerBudeffIconType.ot_maxHP_down, -d, 0f);
|
||||
}
|
||||
break;
|
||||
case EffectType.IncreaseMaxMana:
|
||||
if (ally != null) ally.SetMaxMana(ally.maxMana + Mathf.CeilToInt(amountTotal), false);
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy3)) enemy3.SetMaxMana(enemy3.maxMana + Mathf.CeilToInt(amountTotal), false);
|
||||
if (ally != null)
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
ally.SetMaxMana(ally.maxMana + d, false);
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_maxMana_up, d, 0f);
|
||||
}
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy3))
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
enemy3.SetMaxMana(enemy3.maxMana + d, false);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy3, PlayerBudeffIconType.ot_maxMana_up, d, 0f);
|
||||
}
|
||||
break;
|
||||
case EffectType.DecreaseMaxMana:
|
||||
if (ally != null) ally.SetMaxMana(Mathf.Max(1, ally.maxMana - Mathf.CeilToInt(amountTotal)), false);
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy4)) enemy4.SetMaxMana(Mathf.Max(1, enemy4.maxMana - Mathf.CeilToInt(amountTotal)), false);
|
||||
if (ally != null)
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
ally.SetMaxMana(Mathf.Max(1, ally.maxMana - d), false);
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_maxMana_down, -d, 0f);
|
||||
}
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy4))
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
enemy4.SetMaxMana(Mathf.Max(1, enemy4.maxMana - d), false);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy4, PlayerBudeffIconType.ot_maxMana_down, -d, 0f);
|
||||
}
|
||||
break;
|
||||
case EffectType.IncreaseScoreEfficiency:
|
||||
if (ally != null)
|
||||
@@ -1353,19 +1541,28 @@ ResolvedGroup:
|
||||
if (def.defaultDuration <= 0f)
|
||||
{
|
||||
ally.scoreEfficiency += amountTotal;
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_scoreEfficiency_up, amountTotal, 0f);
|
||||
}
|
||||
else if (!TryApplyRefreshOnlyTimedEffect(def, t, amountTotal, def.defaultDuration))
|
||||
{
|
||||
StartCoroutine(ApplyTemporaryScoreEfficiencyChangeDirect(ally, amountTotal, def.defaultDuration));
|
||||
var iconId = iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_scoreEfficiency_up, amountTotal, def.defaultDuration);
|
||||
StartCoroutine(ApplyTemporaryScoreEfficiencyChangeDirect(ally, amountTotal, def.defaultDuration, iconId));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EffectType.DecreaseScoreEfficiency:
|
||||
if (ally != null)
|
||||
{
|
||||
if (def.defaultDuration <= 0f) ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency - amountTotal);
|
||||
if (def.defaultDuration <= 0f)
|
||||
{
|
||||
ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency - amountTotal);
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_scoreEfficiency_down, -amountTotal, 0f);
|
||||
}
|
||||
else if (!TryApplyRefreshOnlyTimedEffect(def, t, amountTotal, def.defaultDuration))
|
||||
StartCoroutine(ApplyTemporaryScoreEfficiencyChangeDirect(ally, -amountTotal, def.defaultDuration));
|
||||
{
|
||||
var iconId = iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_scoreEfficiency_down, -amountTotal, def.defaultDuration);
|
||||
StartCoroutine(ApplyTemporaryScoreEfficiencyChangeDirect(ally, -amountTotal, def.defaultDuration, iconId));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EffectType.IncreaseAttack:
|
||||
@@ -1373,15 +1570,29 @@ ResolvedGroup:
|
||||
int delta = Mathf.CeilToInt(amountTotal);
|
||||
if (ally != null)
|
||||
{
|
||||
if (def.defaultDuration <= 0f) ally.ModifyAttack(delta);
|
||||
if (def.defaultDuration <= 0f)
|
||||
{
|
||||
ally.ModifyAttack(delta);
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_atk_up, delta, 0f);
|
||||
}
|
||||
else if (!TryApplyRefreshOnlyTimedEffect(def, t, amountTotal, def.defaultDuration))
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(ally, delta, def.defaultDuration));
|
||||
{
|
||||
var iconId = iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_atk_up, delta, def.defaultDuration);
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(ally, delta, def.defaultDuration, iconId));
|
||||
}
|
||||
}
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy5))
|
||||
{
|
||||
if (def.defaultDuration <= 0f) enemy5.ModifyAttack(delta);
|
||||
if (def.defaultDuration <= 0f)
|
||||
{
|
||||
enemy5.ModifyAttack(delta);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy5, PlayerBudeffIconType.ot_atk_up, delta, 0f);
|
||||
}
|
||||
else if (!TryApplyRefreshOnlyTimedEffect(def, t, amountTotal, def.defaultDuration))
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(enemy5, delta, def.defaultDuration));
|
||||
{
|
||||
var iconId = iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy5, PlayerBudeffIconType.ot_atk_up, delta, def.defaultDuration);
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(enemy5, delta, def.defaultDuration, iconId, enemy5.GetInstanceID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1390,15 +1601,29 @@ ResolvedGroup:
|
||||
int delta = Mathf.CeilToInt(amountTotal);
|
||||
if (ally != null)
|
||||
{
|
||||
if (def.defaultDuration <= 0f) ally.ModifyAttack(-delta);
|
||||
if (def.defaultDuration <= 0f)
|
||||
{
|
||||
ally.ModifyAttack(-delta);
|
||||
iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_atk_down, -delta, 0f);
|
||||
}
|
||||
else if (!TryApplyRefreshOnlyTimedEffect(def, t, amountTotal, def.defaultDuration))
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(ally, -delta, def.defaultDuration));
|
||||
{
|
||||
var iconId = iBudeffPrefabController.Instance?.RegisterTimedEffect(ally, PlayerBudeffIconType.ot_atk_down, -delta, def.defaultDuration);
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(ally, -delta, def.defaultDuration, iconId));
|
||||
}
|
||||
}
|
||||
else if (t.TryGetComponent<EnemyCombatant>(out var enemy6))
|
||||
{
|
||||
if (def.defaultDuration <= 0f) enemy6.ModifyAttack(-delta);
|
||||
if (def.defaultDuration <= 0f)
|
||||
{
|
||||
enemy6.ModifyAttack(-delta);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy6, PlayerBudeffIconType.ot_atk_down, -delta, 0f);
|
||||
}
|
||||
else if (!TryApplyRefreshOnlyTimedEffect(def, t, amountTotal, def.defaultDuration))
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(enemy6, -delta, def.defaultDuration));
|
||||
{
|
||||
var iconId = iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy6, PlayerBudeffIconType.ot_atk_down, -delta, def.defaultDuration);
|
||||
StartCoroutine(ApplyTemporaryAttackChangeDirect(enemy6, -delta, def.defaultDuration, iconId, enemy6.GetInstanceID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1419,6 +1644,24 @@ ResolvedGroup:
|
||||
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>");
|
||||
}
|
||||
|
||||
if (ShouldSpawnApprForEffect(def.effectType))
|
||||
{
|
||||
var apprSprite = iBudeffPrefabController.Instance != null ? iBudeffPrefabController.Instance.GetSpriteForEffect(def.effectType) : null;
|
||||
if (apprSprite != null)
|
||||
{
|
||||
var apprTargets = ResolveTargetsLocal(def.defaultSelector, caster, specificTarget);
|
||||
if (apprTargets != null)
|
||||
{
|
||||
foreach (var t in apprTargets)
|
||||
{
|
||||
if (t == null) continue;
|
||||
var ally = t.GetComponent<AllyCombatant>() ?? t.GetComponentInChildren<AllyCombatant>(true);
|
||||
if (ally != null) iBudeffPrefabController.Instance?.SpawnApprForSlot(ally.slotIndex, apprSprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (def.defaultDuration > 0f)
|
||||
{
|
||||
var resolvedTargets = ResolveTargetsLocal(def.defaultSelector, caster, specificTarget);
|
||||
@@ -1984,61 +2227,98 @@ ResolvedGroup:
|
||||
ic?.RemoveBuff(buffId);
|
||||
}
|
||||
|
||||
private IEnumerator ApplyTemporaryScoreEfficiencyChangeDirect(AllyCombatant ally, float delta, float duration)
|
||||
private IEnumerator ApplyTemporaryScoreEfficiencyChangeDirect(AllyCombatant ally, float delta, float duration, string iconId)
|
||||
{
|
||||
if (ally == null) yield break;
|
||||
ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency + delta);
|
||||
yield return new WaitForSeconds(duration);
|
||||
if (ally == null) yield break;
|
||||
ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency - delta);
|
||||
try
|
||||
{
|
||||
if (ally == null) yield break;
|
||||
ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency + delta);
|
||||
yield return new WaitForSeconds(duration);
|
||||
if (ally == null) yield break;
|
||||
ally.scoreEfficiency = Mathf.Max(0f, ally.scoreEfficiency - delta);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ally != null && !string.IsNullOrEmpty(iconId))
|
||||
iBudeffPrefabController.Instance?.UnregisterTimedEffect(ally.slotIndex, iconId);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator ApplyTemporaryAttackChangeDirect(AllyCombatant ally, int delta, float duration)
|
||||
private IEnumerator ApplyTemporaryAttackChangeDirect(AllyCombatant ally, int delta, float duration, string iconId)
|
||||
{
|
||||
if (ally == null) yield break;
|
||||
ally.ModifyAttack(delta);
|
||||
yield return new WaitForSeconds(duration);
|
||||
if (ally == null) yield break;
|
||||
ally.ModifyAttack(-delta);
|
||||
try
|
||||
{
|
||||
if (ally == null) yield break;
|
||||
ally.ModifyAttack(delta);
|
||||
yield return new WaitForSeconds(duration);
|
||||
if (ally == null) yield break;
|
||||
ally.ModifyAttack(-delta);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ally != null && !string.IsNullOrEmpty(iconId))
|
||||
iBudeffPrefabController.Instance?.UnregisterTimedEffect(ally.slotIndex, iconId);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator ApplyTemporaryAttackChangeDirect(EnemyCombatant enemy, int delta, float duration)
|
||||
private IEnumerator ApplyTemporaryAttackChangeDirect(EnemyCombatant enemy, int delta, float duration, string iconId, int enemyInstanceId)
|
||||
{
|
||||
if (enemy == null) yield break;
|
||||
enemy.ModifyAttack(delta);
|
||||
yield return new WaitForSeconds(duration);
|
||||
if (enemy == null) yield break;
|
||||
enemy.ModifyAttack(-delta);
|
||||
try
|
||||
{
|
||||
if (enemy == null) yield break;
|
||||
enemy.ModifyAttack(delta);
|
||||
iBudeffPrefabController.Instance?.RefreshEnemyNow(enemy);
|
||||
yield return new WaitForSeconds(duration);
|
||||
if (enemy == null) yield break;
|
||||
enemy.ModifyAttack(-delta);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!string.IsNullOrEmpty(iconId) && enemyInstanceId != 0)
|
||||
iBudeffPrefabController.Instance?.UnregisterEnemyTimedEffect(enemyInstanceId, iconId);
|
||||
}
|
||||
}
|
||||
|
||||
// Coroutine helpers for direct DoT/HoT on GameObject targets
|
||||
private IEnumerator ApplyDamageOverTimeDirect(GameObject target, float totalAmount, float duration, float tickInterval, GameObject source)
|
||||
private IEnumerator ApplyDamageOverTimeDirect(GameObject target, float totalAmount, float duration, float tickInterval, GameObject source, string iconId, int allySlotIndex, int enemyInstanceId)
|
||||
{
|
||||
if (target == null) yield break;
|
||||
var ic = target.GetComponent<ICombatant>();
|
||||
var ally = target.GetComponent<AllyCombatant>();
|
||||
if (ally == null && ic == null)
|
||||
try
|
||||
{
|
||||
Debug.LogWarning($"ApplyDamageOverTimeDirect: target {target.name} cannot receive damage");
|
||||
yield break;
|
||||
}
|
||||
if (target == null) yield break;
|
||||
var ic = target.GetComponent<ICombatant>();
|
||||
var ally = target.GetComponent<AllyCombatant>();
|
||||
if (ally == null && ic == null)
|
||||
{
|
||||
Debug.LogWarning($"ApplyDamageOverTimeDirect: target {target.name} cannot receive damage");
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (duration <= 0f || tickInterval <= 0f)
|
||||
{
|
||||
if (ally != null) ally.ModifyHP(-Mathf.CeilToInt(totalAmount), true);
|
||||
else ic?.ReceiveDamage(totalAmount, source);
|
||||
yield break;
|
||||
}
|
||||
if (duration <= 0f || tickInterval <= 0f)
|
||||
{
|
||||
if (ally != null) ally.ModifyHP(-Mathf.CeilToInt(totalAmount), true);
|
||||
else ic?.ReceiveDamage(totalAmount, source);
|
||||
yield break;
|
||||
}
|
||||
|
||||
int ticks = Mathf.Max(1, Mathf.CeilToInt(duration / tickInterval));
|
||||
float perTick = totalAmount / ticks;
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
int ticks = Mathf.Max(1, Mathf.CeilToInt(duration / tickInterval));
|
||||
float perTick = totalAmount / ticks;
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
if (target == null) yield break;
|
||||
if (ally != null) ally.ModifyHP(-Mathf.CeilToInt(perTick), true);
|
||||
else ic?.ReceiveDamage(perTick, source);
|
||||
yield return new WaitForSeconds(tickInterval);
|
||||
elapsed += tickInterval;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ally != null) ally.ModifyHP(-Mathf.CeilToInt(perTick), true);
|
||||
else ic?.ReceiveDamage(perTick, source);
|
||||
yield return new WaitForSeconds(tickInterval);
|
||||
elapsed += tickInterval;
|
||||
if (!string.IsNullOrEmpty(iconId))
|
||||
{
|
||||
if (allySlotIndex >= 0) iBudeffPrefabController.Instance?.UnregisterTimedEffect(allySlotIndex, iconId);
|
||||
else if (enemyInstanceId != 0) iBudeffPrefabController.Instance?.UnregisterEnemyTimedEffect(enemyInstanceId, iconId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user