173 lines
6.0 KiB
C#
173 lines
6.0 KiB
C#
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;
|
||
|
||
namespace Cielonos.MainGame.Characters.Inventory
|
||
{
|
||
[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")]
|
||
public Attack.AttackType attackType = Attack.AttackType.Kinetics;
|
||
|
||
[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;
|
||
|
||
[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();
|
||
return new AttackValue(attacker, isCritical, finalDamage, attackType, disruptionType, breakthroughType);
|
||
}
|
||
|
||
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)
|
||
{
|
||
}
|
||
}
|
||
}
|
||
} |