Files
Cielonos/Assets/Scripts/MainGame/Characters/Player/Items/Data/AttackData/AttackUnit.cs

176 lines
6.0 KiB
C#
Raw Normal View History

2026-02-13 09:22:11 -05:00
using System;
using System.Collections.Generic;
using Cielonos.MainGame.Characters;
using DamageNumbersPro;
using Sirenix.OdinInspector;
using SLSUtilities.FunctionalAnimation;
using SLSUtilities.General;
using UnityEngine;
using Random = UnityEngine.Random;
2026-03-20 12:07:44 -04:00
namespace Cielonos.MainGame.Characters.Inventory
2026-02-13 09:22:11 -05:00
{
[Serializable]
[HideReferenceObjectPicker]
public partial class AttackUnit : ICloneable<AttackUnit>
{
[ReadOnly]
public AttackData parentData;
[ReadOnly]
[Tooltip("和AttackData中的key对应且用于运行时识别这个攻击单元")]
public string unitName;
[Title("Attack Parameters")]
[Tooltip("如果为true则这个攻击单元不会造成伤害也不会触发暴击等相关机制通常用于仅触发特殊效果")]
public bool isInvalidAttack;
[HideIf("isInvalidAttack")]
2026-03-20 12:07:44 -04:00
public Attack.AttackType attackType = Attack.AttackType.Kinetics;
2026-02-13 09:22:11 -05:00
[HideIf("isInvalidAttack")]
public float startDamage;
[HideIf("isInvalidAttack")]
public float damageDeviation;
[Tooltip("是否在多段攻击时独立计算伤害和暴击")]
[HideIf("isInvalidAttack")]
public bool isIndependentPerHit = true;
[HideIf("isInvalidAttack")]
public float criticalChance;
[HideIf("isInvalidAttack")]
public float criticalMultiplier = 1;
[Title("Hit Effects")]
public BreakthroughType breakthroughType = BreakthroughType.Weak;
public DisruptionType disruptionType = DisruptionType.NormalExternal;
2026-04-18 13:57:19 -04:00
[Title("Tags")]
public List<string> tags = new List<string>();
2026-02-13 09:22:11 -05:00
[Title("Hit VFX")]
public bool useVFXDataHit;
[HideIf("useVFXDataHit")]
public GameObject hitVFX;
[ShowIf("useVFXDataHit")]
public string vfxUnitName;
[Title("Extra Modules")]
[ListDrawerSettings(ShowFoldout = true)]
[SerializeReference]
public List<Submodule> submodules = new List<Submodule>();
public bool TryGetSubModule<T>(out T submodule) where T : Submodule
{
submodule = submodules.Find(m => m is T) as T;
return submodule != null;
}
public AttackValue GetAttackValue(CharacterBase attacker)
{
bool isCritical = Random.value < GetFinalCriticalChance();
float finalDamage = isCritical ? GetFinalCriticalDamage() : GetFinalRegularDamage();
2026-04-18 13:57:19 -04:00
return new AttackValue(attacker, isCritical, finalDamage, attackType, disruptionType, breakthroughType, tags);
2026-02-13 09:22:11 -05:00
}
public GameObject GetHitVFX()
{
return hitVFX != null ? hitVFX : parentData.defaultHitVFX;
}
public float GetFinalRegularDamage()
{
return startDamage + Random.Range(-damageDeviation, damageDeviation);
// * GameManager.Player.attributeModule.currentAttributes["AttackPowerCoefficient"];
}
public float GetFinalCriticalDamage()
{
return (startDamage + Random.Range(-damageDeviation, damageDeviation)) * GetFinalCriticalMultiplier();// * GameManager.Player.attributeModule.currentAttributes["AttackPowerCoefficient"] * GetFinalCriticalMultiplier();
}
public float GetFinalCriticalChance()
{
return criticalChance;//+ GameManager.Player.attributeModule.currentAttributes["CriticalChance"];
}
public float GetFinalCriticalMultiplier()
{
return criticalMultiplier;// + GameManager.Player.attributeModule.currentAttributes["CriticalMultiplier"] + 1;
}
public AttackUnit Clone()
{
return (AttackUnit) this.MemberwiseClone();
}
}
public partial class AttackUnit
{
[Serializable]
public abstract class Submodule : SubmoduleBase<AttackUnit>
{
public Submodule(AttackUnit owner) : base(owner)
{
}
}
[Serializable]
public class ParameterSubmodule : Submodule
{
public Dictionary<string, float> floatParameters = new Dictionary<string, float>();
public Dictionary<string, int> intParameters = new Dictionary<string, int>();
public Dictionary<string, string> stringParameters = new Dictionary<string, string>();
public ParameterSubmodule() : base(null)
{
}
public ParameterSubmodule(AttackUnit owner) : base(owner)
{
}
public T GetParameter<T>(string key)
{
if (typeof(T) == typeof(float))
{
return floatParameters.TryGetValue(key, out float floatParameter) ? (T)(object)floatParameter : (T)(object)0f;
}
if (typeof(T) == typeof(int))
{
return intParameters.TryGetValue(key, out int intParameter) ? (T)(object)intParameter : (T)(object)0;
}
if (typeof(T) == typeof(string))
{
return stringParameters.TryGetValue(key, out string stringParameter) ? (T)(object)stringParameter : (T)(object)string.Empty;
}
throw new InvalidOperationException($"Unsupported parameter type: {typeof(T)}");
}
}
[Serializable]
public class DamageNumberSubmodule : Submodule
{
public DamageNumber regularPrefab;
public DamageNumber criticalPrefab;
public Dictionary<string, DamageNumber> customPrefabs = new Dictionary<string, DamageNumber>();
public DamageNumberSubmodule() : base(null)
{
}
public DamageNumberSubmodule(AttackUnit owner) : base(owner)
{
}
}
}
}