hold音符补丁 备份
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
@@ -153,6 +153,22 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
public AppliedEffect(EffectType t, float a) { effectType = t; amount = a; }
|
||||
}
|
||||
|
||||
private List<(iNumberPrefabController.InstantNumberType type, int val)> _queuedPopups = new List<(iNumberPrefabController.InstantNumberType, int)>();
|
||||
|
||||
public void QueueDamagePopup(iNumberPrefabController.InstantNumberType type, int val)
|
||||
{
|
||||
_queuedPopups.Add((type, val));
|
||||
}
|
||||
|
||||
public void TriggerQueuedPopups()
|
||||
{
|
||||
foreach (var p in _queuedPopups)
|
||||
{
|
||||
iNumberPrefabController.SpawnForAllyStatic(slotIndex, p.type, p.val);
|
||||
}
|
||||
_queuedPopups.Clear();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// ensure GameObject name matches pattern so EffectSystem can find it
|
||||
@@ -236,10 +252,9 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
if (allowOverwriteFromSO)
|
||||
InitializeStatsFromData();
|
||||
|
||||
// Documentation text normalized.
|
||||
// Documentation text normalized.
|
||||
isDead = false;
|
||||
currentHP = Mathf.Max(1, maxHP);
|
||||
// Initialize status
|
||||
isDead = (maxHP <= 0);
|
||||
currentHP = maxHP;
|
||||
currentMana = 0;
|
||||
|
||||
UpdateUIImmediate();
|
||||
@@ -271,7 +286,8 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
if (allowOverwriteFromSO)
|
||||
{
|
||||
InitializeStatsFromData();
|
||||
currentHP = Mathf.Max(1, maxHP);
|
||||
currentHP = maxHP;
|
||||
isDead = (maxHP <= 0);
|
||||
UpdateUIImmediate();
|
||||
}
|
||||
|
||||
@@ -1132,6 +1148,11 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
|
||||
// Public setters that update UI and optionally animate fade bars
|
||||
public void SetCurrentHP(int hp, bool animateFade = true)
|
||||
{
|
||||
SetCurrentHP(hp, animateFade, false);
|
||||
}
|
||||
|
||||
public void SetCurrentHP(int hp, bool animateFade, bool skipPopup)
|
||||
{
|
||||
if (isDead) return; // dead characters cannot change HP
|
||||
int old = currentHP;
|
||||
@@ -1141,7 +1162,7 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
|
||||
// Trigger HP changed events
|
||||
int delta = currentHP - old;
|
||||
if (delta != 0)
|
||||
if (delta != 0 && !skipPopup)
|
||||
{
|
||||
if (iNumberPrefabController.Instance != null)
|
||||
{
|
||||
@@ -1180,16 +1201,26 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
|
||||
// Internal HP modifier that does NOT apply heal multipliers (used by ReceiveHeal to avoid double rounding).
|
||||
private void ModifyHPRaw(int delta, bool animateFade = true)
|
||||
{
|
||||
ModifyHPRaw(delta, animateFade, false);
|
||||
}
|
||||
|
||||
private void ModifyHPRaw(int delta, bool animateFade, bool skipPopup)
|
||||
{
|
||||
if (isDead && delta > 0)
|
||||
{
|
||||
// cannot heal a dead unit
|
||||
return;
|
||||
}
|
||||
SetCurrentHP(currentHP + delta, animateFade);
|
||||
SetCurrentHP(currentHP + delta, animateFade, skipPopup);
|
||||
}
|
||||
|
||||
public void ModifyHP(int delta, bool animateFade = true)
|
||||
{
|
||||
ModifyHP(delta, animateFade, false);
|
||||
}
|
||||
|
||||
public void ModifyHP(int delta, bool animateFade, bool skipPopup)
|
||||
{
|
||||
if (isDead && delta > 0)
|
||||
{
|
||||
@@ -1207,7 +1238,7 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
delta = Mathf.CeilToInt(delta * mult);
|
||||
}
|
||||
}
|
||||
ModifyHPRaw(delta, animateFade);
|
||||
ModifyHPRaw(delta, animateFade, skipPopup);
|
||||
}
|
||||
|
||||
public void SetMaxHP(int newMax, bool keepCurrentRatio = true)
|
||||
@@ -1528,12 +1559,12 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
fadeManaImage.fillAmount = targetFill;
|
||||
}
|
||||
|
||||
public void ReceiveDamage(float amount, GameObject source)
|
||||
public void ReceiveDamage(float amount, GameObject source, bool deferPopup = false)
|
||||
{
|
||||
ReceiveDamageInternal(amount, source, true);
|
||||
ReceiveDamageInternal(amount, source, true, deferPopup);
|
||||
}
|
||||
|
||||
private void ReceiveDamageInternal(float amount, GameObject source, bool allowRedirect)
|
||||
private void ReceiveDamageInternal(float amount, GameObject source, bool allowRedirect, bool deferPopup)
|
||||
{
|
||||
if (IsDead) return; // dead characters cannot be hit
|
||||
if (allowRedirect && TryGetGlobalRedirectTargetForReceiverDamage(this, out var redirector))
|
||||
@@ -1541,7 +1572,7 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
ConsumeGlobalRedirect(redirector);
|
||||
if (redirector != null && redirector != this)
|
||||
{
|
||||
redirector.ReceiveDamageInternal(amount, source, false);
|
||||
redirector.ReceiveDamageInternal(amount, source, false, deferPopup);
|
||||
return;
|
||||
}
|
||||
// If redirector is self or invalid, consume redirect and continue to take damage normally.
|
||||
@@ -1555,22 +1586,49 @@ public class AllyCombatant : MonoBehaviour, ICombatant
|
||||
if (adj != null && adj != this)
|
||||
{
|
||||
ConsumeSelfDamageRedirectToAdjacent();
|
||||
adj.ReceiveDamageInternal(amount, source, false);
|
||||
adj.ReceiveDamageInternal(amount, source, false, deferPopup);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int oldHP = currentHP;
|
||||
float effective = amount * (1f - damageResistance);
|
||||
int delta = Mathf.CeilToInt(effective);
|
||||
ModifyHP(-delta, true);
|
||||
ModifyHP(-delta, true, true);
|
||||
|
||||
int actual = oldHP - currentHP;
|
||||
if (actual != 0)
|
||||
{
|
||||
if (deferPopup)
|
||||
{
|
||||
QueueDamagePopup(iNumberPrefabController.InstantNumberType.Damage, -actual);
|
||||
}
|
||||
else
|
||||
{
|
||||
iNumberPrefabController.SpawnForAllyStatic(slotIndex, iNumberPrefabController.InstantNumberType.Damage, -actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ReceiveHeal(float amount, GameObject source)
|
||||
public void ReceiveHeal(float amount, GameObject source, bool deferPopup = false)
|
||||
{
|
||||
if (IsDead) return; // dead characters cannot be healed
|
||||
int oldHP = currentHP;
|
||||
float mult = GetTotalHealReceivedMultiplier();
|
||||
int delta = Mathf.CeilToInt(amount * mult);
|
||||
ModifyHPRaw(delta, true);
|
||||
ModifyHP(delta, true, true);
|
||||
int actual = currentHP - oldHP;
|
||||
if (actual != 0)
|
||||
{
|
||||
if (deferPopup)
|
||||
{
|
||||
QueueDamagePopup(iNumberPrefabController.InstantNumberType.Heal, actual);
|
||||
}
|
||||
else
|
||||
{
|
||||
iNumberPrefabController.SpawnForAllyStatic(slotIndex, iNumberPrefabController.InstantNumberType.Heal, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyBuff(Buff buff, GameObject source)
|
||||
|
||||
@@ -52,8 +52,8 @@ public enum EffectType
|
||||
|
||||
public interface ICombatant
|
||||
{
|
||||
void ReceiveDamage(float amount, GameObject source);
|
||||
void ReceiveHeal(float amount, GameObject source);
|
||||
void ReceiveDamage(float amount, GameObject source, bool deferPopup = false);
|
||||
void ReceiveHeal(float amount, GameObject source, bool deferPopup = false);
|
||||
void ApplyBuff(Buff buff, GameObject source);
|
||||
void RemoveBuff(string buffId);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ public class EffectSystem : MonoBehaviour
|
||||
private readonly List<GameObject> _cachedEnemies = new List<GameObject>(8);
|
||||
|
||||
private readonly HashSet<int> _awaitingHitFxTargets = new HashSet<int>();
|
||||
private readonly Dictionary<int, int> _pendingDamagePopupByTargetId = new Dictionary<int, int>(64);
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -322,12 +321,6 @@ public class EffectSystem : MonoBehaviour
|
||||
{
|
||||
int before = ally.currentScore;
|
||||
ally.AddScoreDirect(Mathf.CeilToInt(amount));
|
||||
int delta = ally.currentScore - before;
|
||||
if (delta != 0)
|
||||
{
|
||||
var type = delta > 0 ? iNumberPrefabController.InstantNumberType.IscorePlus : iNumberPrefabController.InstantNumberType.IscoreMinus;
|
||||
iNumberPrefabController.SpawnForAllyStatic(ally.slotIndex, type, delta);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -372,7 +365,7 @@ public class EffectSystem : MonoBehaviour
|
||||
if (duration <= 0f)
|
||||
{
|
||||
enemy.SetMaxHP(enemy.maxHP + delta, false);
|
||||
if (delta > 0) enemy.currentHP = Mathf.Clamp(enemy.currentHP + delta, 0, enemy.maxHP);
|
||||
if (delta > 0) enemy.ModifyHP(delta);
|
||||
iBudeffPrefabController.Instance?.RefreshEnemyNow(enemy);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy, PlayerBudeffIconType.ot_maxHP_up, delta, 0f);
|
||||
}
|
||||
@@ -1083,18 +1076,8 @@ public class EffectSystem : MonoBehaviour
|
||||
var comp = target.GetComponent<ICombatant>();
|
||||
if (comp != null)
|
||||
{
|
||||
int beforeHP = 0;
|
||||
if (targetAlly != null) beforeHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) beforeHP = targetEnemy.currentHP;
|
||||
|
||||
comp.ReceiveDamage(amount, source);
|
||||
|
||||
int afterHP = 0;
|
||||
if (targetAlly != null) afterHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) afterHP = targetEnemy.currentHP;
|
||||
|
||||
int actualDelta = beforeHP - afterHP;
|
||||
if (actualDelta != 0) QueueOrSpawnDamagePopup(target, targetAlly, targetEnemy, actualDelta);
|
||||
// Use deferPopup: true for synchronization with hit fx
|
||||
comp.ReceiveDamage(amount, source, true);
|
||||
|
||||
// Record stats if source is an ally
|
||||
if (source != null && target.GetComponent<EnemyCombatant>() != null)
|
||||
@@ -1124,26 +1107,8 @@ public class EffectSystem : MonoBehaviour
|
||||
var comp = target.GetComponent<ICombatant>();
|
||||
if (comp != null)
|
||||
{
|
||||
var targetAlly = target.GetComponent<AllyCombatant>();
|
||||
var targetEnemy = target.GetComponent<EnemyCombatant>();
|
||||
int beforeHP = 0;
|
||||
if (targetAlly != null) beforeHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) beforeHP = targetEnemy.currentHP;
|
||||
|
||||
comp.ReceiveHeal(amount, source);
|
||||
|
||||
int afterHP = 0;
|
||||
if (targetAlly != null) afterHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) afterHP = targetEnemy.currentHP;
|
||||
|
||||
int actualDelta = afterHP - beforeHP;
|
||||
if (actualDelta != 0)
|
||||
{
|
||||
if (targetAlly != null)
|
||||
iNumberPrefabController.SpawnForAllyStatic(targetAlly.slotIndex, iNumberPrefabController.InstantNumberType.Heal, Mathf.Abs(actualDelta));
|
||||
else if (targetEnemy != null)
|
||||
iNumberPrefabController.SpawnForEnemyStatic(iNumberPrefabController.InstantNumberType.Heal, Mathf.Abs(actualDelta));
|
||||
}
|
||||
// Use deferPopup: false for heals (usually immediate)
|
||||
comp.ReceiveHeal(amount, source, false);
|
||||
|
||||
// Record stats if source is an ally
|
||||
if (source != null)
|
||||
@@ -1208,7 +1173,9 @@ public class EffectSystem : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
comp.ReceiveDamage(totalAmount, source);
|
||||
comp.ReceiveDamage(totalAmount, source, false);
|
||||
// No need to call TriggerQueuedPopups manually as deferPopup is false
|
||||
|
||||
if (source != null && targetEnemy != null)
|
||||
{
|
||||
var ally = source.GetComponent<AllyCombatant>();
|
||||
@@ -1255,19 +1222,9 @@ public class EffectSystem : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
int beforeHP = 0;
|
||||
if (targetAlly != null) beforeHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) beforeHP = targetEnemy.currentHP;
|
||||
|
||||
comp.ReceiveDamage(perTick, source);
|
||||
|
||||
int afterHP = 0;
|
||||
if (targetAlly != null) afterHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) afterHP = targetEnemy.currentHP;
|
||||
|
||||
int actualDelta = beforeHP - afterHP;
|
||||
if (actualDelta != 0) QueueOrSpawnDamagePopup(target, targetAlly, targetEnemy, actualDelta);
|
||||
|
||||
comp.ReceiveDamage(perTick, source, false);
|
||||
// No need to call TriggerQueuedPopups manually as deferPopup is false
|
||||
|
||||
if (source != null && targetEnemy != null)
|
||||
{
|
||||
var ally = source.GetComponent<AllyCombatant>();
|
||||
@@ -1306,21 +1263,9 @@ public class EffectSystem : MonoBehaviour
|
||||
if (targetAlly != null) beforeHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) beforeHP = targetEnemy.currentHP;
|
||||
|
||||
comp.ReceiveHeal(totalAmount, source);
|
||||
|
||||
int afterHP = 0;
|
||||
if (targetAlly != null) afterHP = targetAlly.currentHP;
|
||||
else if (targetEnemy != null) afterHP = targetEnemy.currentHP;
|
||||
|
||||
int actualDelta = afterHP - beforeHP;
|
||||
if (actualDelta != 0)
|
||||
{
|
||||
if (targetAlly != null)
|
||||
iNumberPrefabController.SpawnForAllyStatic(targetAlly.slotIndex, iNumberPrefabController.InstantNumberType.Heal, Mathf.Abs(actualDelta));
|
||||
else if (targetEnemy != null)
|
||||
iNumberPrefabController.SpawnForEnemyStatic(iNumberPrefabController.InstantNumberType.Heal, Mathf.Abs(actualDelta));
|
||||
}
|
||||
|
||||
comp.ReceiveHeal(totalAmount, source, false);
|
||||
// No need to call TriggerQueuedPopups manually as deferPopup is false
|
||||
|
||||
// Record stats
|
||||
if (source != null)
|
||||
{
|
||||
@@ -1339,25 +1284,9 @@ public class EffectSystem : MonoBehaviour
|
||||
{
|
||||
if (target == null) yield break;
|
||||
|
||||
int beforeHP = 0;
|
||||
if (targetAllyHot != null) beforeHP = targetAllyHot.currentHP;
|
||||
else if (targetEnemyHot != null) beforeHP = targetEnemyHot.currentHP;
|
||||
|
||||
comp.ReceiveHeal(perTick, source);
|
||||
|
||||
int afterHP = 0;
|
||||
if (targetAllyHot != null) afterHP = targetAllyHot.currentHP;
|
||||
else if (targetEnemyHot != null) afterHP = targetEnemyHot.currentHP;
|
||||
|
||||
int actualDelta = afterHP - beforeHP;
|
||||
if (actualDelta != 0)
|
||||
{
|
||||
if (targetAllyHot != null)
|
||||
iNumberPrefabController.SpawnForAllyStatic(targetAllyHot.slotIndex, iNumberPrefabController.InstantNumberType.Heal, Mathf.Abs(actualDelta));
|
||||
else if (targetEnemyHot != null)
|
||||
iNumberPrefabController.SpawnForEnemyStatic(iNumberPrefabController.InstantNumberType.Heal, Mathf.Abs(actualDelta));
|
||||
}
|
||||
|
||||
comp.ReceiveHeal(perTick, source, false);
|
||||
// No need to call TriggerQueuedPopups manually as deferPopup is false
|
||||
|
||||
// Record stats
|
||||
if (source != null)
|
||||
{
|
||||
@@ -1382,47 +1311,19 @@ public class EffectSystem : MonoBehaviour
|
||||
int id = target.GetInstanceID();
|
||||
if (_awaitingHitFxTargets.Contains(id)) _awaitingHitFxTargets.Remove(id);
|
||||
|
||||
if (!_pendingDamagePopupByTargetId.TryGetValue(id, out var signedValue) || signedValue == 0) return;
|
||||
_pendingDamagePopupByTargetId.Remove(id);
|
||||
|
||||
var ally = target.GetComponent<AllyCombatant>();
|
||||
if (ally != null)
|
||||
// Trigger any queued damage/heal popups now that the hit FX is playing
|
||||
var enemy = target.GetComponent<EnemyCombatant>();
|
||||
if (enemy != null)
|
||||
{
|
||||
iNumberPrefabController.SpawnForAllyStatic(ally.slotIndex, iNumberPrefabController.InstantNumberType.Damage, signedValue);
|
||||
return;
|
||||
enemy.TriggerQueuedPopups();
|
||||
}
|
||||
|
||||
if (target.GetComponent<EnemyCombatant>() != null)
|
||||
else
|
||||
{
|
||||
iNumberPrefabController.SpawnForEnemyStatic(iNumberPrefabController.InstantNumberType.Damage, signedValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void QueueOrSpawnDamagePopup(GameObject target, AllyCombatant targetAlly, EnemyCombatant targetEnemy, int actualDelta)
|
||||
{
|
||||
if (target == null) return;
|
||||
if (actualDelta == 0) return;
|
||||
int id = target.GetInstanceID();
|
||||
int signedValue = -Mathf.Abs(actualDelta);
|
||||
|
||||
if (_awaitingHitFxTargets.Contains(id))
|
||||
{
|
||||
if (_pendingDamagePopupByTargetId.TryGetValue(id, out var prev))
|
||||
_pendingDamagePopupByTargetId[id] = prev + signedValue;
|
||||
else
|
||||
_pendingDamagePopupByTargetId[id] = signedValue;
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetAlly != null)
|
||||
{
|
||||
iNumberPrefabController.SpawnForAllyStatic(targetAlly.slotIndex, iNumberPrefabController.InstantNumberType.Damage, signedValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetEnemy != null)
|
||||
{
|
||||
iNumberPrefabController.SpawnForEnemyStatic(iNumberPrefabController.InstantNumberType.Damage, signedValue);
|
||||
var ally = target.GetComponent<AllyCombatant>();
|
||||
if (ally != null)
|
||||
{
|
||||
ally.TriggerQueuedPopups();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1443,14 +1344,7 @@ public class EffectSystem : MonoBehaviour
|
||||
// immediate add totalAmount to mana if ally present
|
||||
if (ally != null)
|
||||
{
|
||||
int before = ally.currentMana;
|
||||
ally.ModifyMana(Mathf.CeilToInt(totalAmount), true, true);
|
||||
int delta = ally.currentMana - before;
|
||||
if (delta != 0)
|
||||
{
|
||||
var type = delta > 0 ? iNumberPrefabController.InstantNumberType.ManaPlus : iNumberPrefabController.InstantNumberType.ManaMinus;
|
||||
iNumberPrefabController.SpawnForAllyStatic(ally.slotIndex, type, delta);
|
||||
}
|
||||
// Record stats
|
||||
if (totalAmount > 0f && source != null)
|
||||
{
|
||||
@@ -1469,14 +1363,7 @@ public class EffectSystem : MonoBehaviour
|
||||
if (target == null) yield break;
|
||||
if (ally != null)
|
||||
{
|
||||
int before = ally.currentMana;
|
||||
ally.ModifyMana(Mathf.CeilToInt(perTick), true, true);
|
||||
int delta = ally.currentMana - before;
|
||||
if (delta != 0)
|
||||
{
|
||||
var type = delta > 0 ? iNumberPrefabController.InstantNumberType.ManaPlus : iNumberPrefabController.InstantNumberType.ManaMinus;
|
||||
iNumberPrefabController.SpawnForAllyStatic(ally.slotIndex, type, delta);
|
||||
}
|
||||
// Record stats
|
||||
if (perTick > 0f && source != null)
|
||||
{
|
||||
@@ -1641,7 +1528,7 @@ public class EffectSystem : MonoBehaviour
|
||||
{
|
||||
if (enemy == null) yield break;
|
||||
enemy.SetMaxHP(Mathf.Max(1, enemy.maxHP + delta), false);
|
||||
if (delta > 0) enemy.currentHP = Mathf.Clamp(enemy.currentHP + delta, 0, enemy.maxHP);
|
||||
if (delta > 0) enemy.ModifyHP(delta);
|
||||
iBudeffPrefabController.Instance?.RefreshEnemyNow(enemy);
|
||||
yield return new WaitForSeconds(duration);
|
||||
if (enemy == null) yield break;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -133,7 +133,7 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
}
|
||||
}
|
||||
|
||||
public void ReceiveDamage(float amount, GameObject source)
|
||||
public void ReceiveDamage(float amount, GameObject source, bool deferPopup = false)
|
||||
{
|
||||
if (isDead) return;
|
||||
|
||||
@@ -144,9 +144,23 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
}
|
||||
|
||||
_lastAttacker = source;
|
||||
int before = currentHP;
|
||||
float effective = amount * (1f - damageResistance);
|
||||
int delta = Mathf.CeilToInt(effective);
|
||||
currentHP = Mathf.Clamp(currentHP - delta, 0, maxHP);
|
||||
ModifyHP(-delta, true);
|
||||
|
||||
int actual = before - currentHP;
|
||||
if (actual != 0)
|
||||
{
|
||||
if (deferPopup)
|
||||
{
|
||||
QueueDamagePopup(iNumberPrefabController.InstantNumberType.Damage, -actual);
|
||||
}
|
||||
else
|
||||
{
|
||||
iNumberPrefabController.SpawnForEnemyStatic(iNumberPrefabController.InstantNumberType.Damage, -actual);
|
||||
}
|
||||
}
|
||||
|
||||
// grant mana based on sourceData setting
|
||||
if (sourceData != null && sourceData.manaGainOnDamagePercent > 0f && maxMana > 0)
|
||||
@@ -162,12 +176,25 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
}
|
||||
}
|
||||
|
||||
public void ReceiveHeal(float amount, GameObject source)
|
||||
public void ReceiveHeal(float amount, GameObject source, bool deferPopup = false)
|
||||
{
|
||||
if (isDead) return;
|
||||
int before = currentHP;
|
||||
float mult = GetTotalHealReceivedMultiplier();
|
||||
int delta = Mathf.CeilToInt(amount * mult);
|
||||
currentHP = Mathf.Clamp(currentHP + delta, 0, maxHP);
|
||||
ModifyHP(delta, true);
|
||||
int actual = currentHP - before;
|
||||
if (actual != 0)
|
||||
{
|
||||
if (deferPopup)
|
||||
{
|
||||
QueueDamagePopup(iNumberPrefabController.InstantNumberType.Heal, actual);
|
||||
}
|
||||
else
|
||||
{
|
||||
iNumberPrefabController.SpawnForEnemyStatic(iNumberPrefabController.InstantNumberType.Heal, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyBuff(Buff buff, GameObject source)
|
||||
@@ -255,10 +282,38 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
RecalculateAttackFromBuffs();
|
||||
}
|
||||
|
||||
private List<(iNumberPrefabController.InstantNumberType type, int val)> _queuedPopups = new List<(iNumberPrefabController.InstantNumberType, int)>();
|
||||
|
||||
public void QueueDamagePopup(iNumberPrefabController.InstantNumberType type, int val)
|
||||
{
|
||||
_queuedPopups.Add((type, val));
|
||||
}
|
||||
|
||||
public void TriggerQueuedPopups()
|
||||
{
|
||||
foreach (var p in _queuedPopups)
|
||||
{
|
||||
iNumberPrefabController.SpawnForEnemyStatic(p.type, p.val);
|
||||
}
|
||||
_queuedPopups.Clear();
|
||||
}
|
||||
|
||||
public void ModifyHP(int delta)
|
||||
{
|
||||
ModifyHP(delta, false);
|
||||
}
|
||||
|
||||
public void ModifyHP(int delta, bool skipPopup)
|
||||
{
|
||||
if (isDead && delta > 0) return;
|
||||
int before = currentHP;
|
||||
currentHP = Mathf.Clamp(currentHP + delta, 0, maxHP);
|
||||
int actual = currentHP - before;
|
||||
if (actual != 0 && !skipPopup)
|
||||
{
|
||||
var type = actual > 0 ? iNumberPrefabController.InstantNumberType.Heal : iNumberPrefabController.InstantNumberType.Damage;
|
||||
iNumberPrefabController.SpawnForEnemyStatic(type, actual);
|
||||
}
|
||||
if (currentHP <= 0) Die();
|
||||
}
|
||||
|
||||
@@ -267,6 +322,16 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
if (maxMana <= 0) return;
|
||||
int old = currentMana;
|
||||
currentMana = Mathf.Clamp(currentMana + delta, 0, maxMana);
|
||||
int actual = currentMana - old;
|
||||
|
||||
if (actual != 0)
|
||||
{
|
||||
if (iNumberPrefabController.Instance != null)
|
||||
{
|
||||
var type = actual > 0 ? iNumberPrefabController.InstantNumberType.ManaPlus : iNumberPrefabController.InstantNumberType.ManaMinus;
|
||||
iNumberPrefabController.SpawnForEnemyStatic(type, actual);
|
||||
}
|
||||
}
|
||||
|
||||
// If mana reached full, trigger primary skill and reset mana
|
||||
if (currentMana >= maxMana && maxMana > 0 && Application.isPlaying)
|
||||
@@ -283,7 +348,7 @@ public class EnemyCombatant : MonoBehaviour, ICombatant
|
||||
}
|
||||
|
||||
// reset mana after casting
|
||||
currentMana = 0;
|
||||
ModifyMana(-currentMana, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -380,8 +380,8 @@ public class ScoreManager : MonoBehaviour
|
||||
if (idolScoreSums[trackIndex] > int.MaxValue - 1) idolScoreSums[trackIndex] = int.MaxValue - 1;
|
||||
int idolActualDelta = idolScoreSums[trackIndex] - idolBefore;
|
||||
|
||||
// Only spawn popup if it is skill-related
|
||||
if (isSkillRelated && idolActualDelta != 0)
|
||||
// Spawn floating number popup for idol score change
|
||||
if (idolActualDelta != 0)
|
||||
{
|
||||
var type = idolActualDelta > 0 ? iNumberPrefabController.InstantNumberType.IscorePlus : iNumberPrefabController.InstantNumberType.IscoreMinus;
|
||||
iNumberPrefabController.SpawnForAllyStatic(trackIndex, type, idolActualDelta);
|
||||
@@ -458,9 +458,17 @@ public class ScoreManager : MonoBehaviour
|
||||
if (trackIndex < 0 || trackIndex >= idolScoreSums.Length) return;
|
||||
if (idolDelta == 0) return;
|
||||
|
||||
int idolBefore = idolScoreSums[trackIndex];
|
||||
idolScoreSums[trackIndex] += idolDelta;
|
||||
if (idolScoreSums[trackIndex] < 0) idolScoreSums[trackIndex] = 0;
|
||||
if (idolScoreSums[trackIndex] > int.MaxValue - 1) idolScoreSums[trackIndex] = int.MaxValue - 1;
|
||||
int actual = idolScoreSums[trackIndex] - idolBefore;
|
||||
|
||||
if (actual != 0)
|
||||
{
|
||||
var type = actual > 0 ? iNumberPrefabController.InstantNumberType.IscorePlus : iNumberPrefabController.InstantNumberType.IscoreMinus;
|
||||
iNumberPrefabController.SpawnForAllyStatic(trackIndex, type, actual);
|
||||
}
|
||||
|
||||
red_idolScore_sum = idolScoreSums[0];
|
||||
green_idolScore_sum = idolScoreSums[1];
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Documentation text normalized.
|
||||
/// Documentation text normalized.
|
||||
/// Documentation text normalized.
|
||||
/// Documentation text normalized.
|
||||
///
|
||||
/// Documentation text normalized.
|
||||
/// SkillBuilder.Instance.ExecuteSkill("Fireball", EffectType.DamageSingleEnemy, 120f, Selector.CurrentEnemies, caster, target);
|
||||
/// Documentation text normalized.
|
||||
/// </summary>
|
||||
@@ -1003,7 +997,7 @@ public class SkillBuilder : MonoBehaviour
|
||||
else
|
||||
{
|
||||
enemy.SetMaxHP(Mathf.Max(1, enemy.maxHP + hpDelta), false);
|
||||
if (hpDelta > 0) enemy.currentHP = Mathf.Clamp(enemy.currentHP + hpDelta, 0, enemy.maxHP);
|
||||
if (hpDelta > 0) enemy.ModifyHP(hpDelta);
|
||||
}
|
||||
int newHP = ally != null ? ally.maxHP : enemy.maxHP;
|
||||
CheckLimitAndWarnInt(targetName, "最大生命值", oldHP, newHP, hpDelta);
|
||||
@@ -1595,7 +1589,7 @@ ResolvedGroup:
|
||||
{
|
||||
int d = Mathf.CeilToInt(amountTotal);
|
||||
enemy.SetMaxHP(enemy.maxHP + d, false);
|
||||
if (d > 0) enemy.currentHP = Mathf.Clamp(enemy.currentHP + d, 0, enemy.maxHP);
|
||||
if (d > 0) enemy.ModifyHP(d);
|
||||
iBudeffPrefabController.Instance?.RegisterEnemyTimedEffect(enemy, PlayerBudeffIconType.ot_maxHP_up, d, 0f);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user