You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
4.5 KiB
174 lines
4.5 KiB
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using Spine.Unity;
|
|
using Skill_V2;
|
|
using System.Numerics;
|
|
using System;
|
|
|
|
public struct Damage
|
|
{
|
|
public BigInteger value;
|
|
public bool isCritical;
|
|
}
|
|
|
|
public class Character : Entity, IBattleEntity
|
|
{
|
|
[SerializeField] SkeletonAnimation skeletonAnimation;
|
|
[SerializeField] StateHandler<Character> stateHandler;
|
|
|
|
StatData hpStat;
|
|
|
|
LayerMask layerMask;
|
|
|
|
Skill[] skills = new Skill[0];
|
|
|
|
public CharacterData Data { get; private set; }
|
|
public SkeletonAnimation SkeletonAnimation => skeletonAnimation;
|
|
public StateHandler<Character> StateHandler => stateHandler;
|
|
public Bitset32.Mask TargetTags { get; private set; }
|
|
public IReadOnlyList<Skill> Skills => skills;
|
|
public BigInteger CurrentHp { get; private set; }
|
|
public bool IsDead => CurrentHp <= 0;
|
|
public bool IsBattleReady { get; set; }
|
|
|
|
public event Action<Character> OnSpawned;
|
|
public event Action<Character> OnDisposed;
|
|
public event Action<Character, Damage> OnDamaged;
|
|
|
|
private void Awake()
|
|
{
|
|
if (skeletonAnimation == null)
|
|
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
|
|
|
if (stateHandler == null)
|
|
stateHandler = GetComponent<StateHandler<Character>>();
|
|
|
|
AddTags(EntityTag.Character);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
for(int i = 0; i < skills.Length; i++)
|
|
skills[i].UpdateSkillCoolTime();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
for (int i = 0; i < skills.Length; i++)
|
|
{
|
|
var skill = skills[i];
|
|
if (skill != null) continue;
|
|
|
|
skill.Stop();
|
|
|
|
if(skill.gameObject != null)
|
|
Destroy(skill.gameObject);
|
|
}
|
|
}
|
|
|
|
public void SetData(CharacterData charData)
|
|
{
|
|
Debug.Assert(charData != null, Logger.LogMessage(LogType.Assert, nameof(SetData), " data is null"));
|
|
Debug.Assert(Data == null, Logger.LogMessage(LogType.Assert, nameof(SetData), " data is already set"));
|
|
|
|
Data = charData;
|
|
|
|
if (Data.Skills != null)
|
|
{
|
|
skills = new Skill[Data.Skills.Count];
|
|
|
|
int i = 0;
|
|
foreach (var skillData in Data.Skills)
|
|
{
|
|
skills[i] = Instantiate(skillData.Prefab);
|
|
skills[i].SetSkillData(skillData);
|
|
skills[i].Stop();
|
|
i++;
|
|
}
|
|
}
|
|
|
|
stateHandler.Initialize(this);
|
|
foreach (var component in GetComponents<IOwnedComponent<Character>>())
|
|
{
|
|
component.Initialize(this);
|
|
}
|
|
}
|
|
|
|
public void SetTargetTags(LayerMask mask, params EntityTag[] tags)
|
|
{
|
|
layerMask = mask;
|
|
TargetTags = Bitset32.GetMask(Array.ConvertAll(tags, (t) => (Enum)t));
|
|
|
|
foreach (var skill in skills)
|
|
{
|
|
skill.SetTargetTags(layerMask, tags);
|
|
}
|
|
}
|
|
|
|
public void Spawn(UnityEngine.Vector2 spawnPos)
|
|
{
|
|
Debug.Assert(stateHandler != null, "StateHandler is null");
|
|
Debug.Assert(skeletonAnimation != null, "SkeletonAnimation is null");
|
|
|
|
transform.position = spawnPos;
|
|
|
|
if (Data.TryGetStat(StatID.Hp, out hpStat))
|
|
{
|
|
CurrentHp = hpStat.Value;
|
|
hpStat.OnValueChanged += OnHpChanged;
|
|
}
|
|
|
|
OnSpawned?.Invoke(this);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (hpStat != null)
|
|
hpStat.OnValueChanged -= OnHpChanged;
|
|
|
|
for (int i = 0; i < skills.Length; i++)
|
|
{
|
|
skills[i].Stop();
|
|
}
|
|
|
|
OnDisposed?.Invoke(this);
|
|
}
|
|
|
|
private void OnHpChanged()
|
|
{
|
|
if (CurrentHp >= (BigInteger)hpStat.Value)
|
|
CurrentHp = hpStat.Value;
|
|
}
|
|
|
|
public bool IsBattleAvail() => IsBattleReady;
|
|
|
|
public void GetDamage(BigInteger atk, float critDmgRate, int critRate, int dnum = -1)
|
|
{
|
|
if(CurrentHp <= 0) return;
|
|
|
|
bool isCritical = CreatureBase.CheckCritical(critRate);
|
|
if(isCritical)
|
|
atk = CreatureBase.GetCriticalDamage(atk, critDmgRate, critRate);
|
|
|
|
Damage dmg = new Damage {
|
|
value = atk,
|
|
isCritical = isCritical
|
|
};
|
|
|
|
CurrentHp = BigInteger.Max(0, CurrentHp - dmg.value);
|
|
|
|
OnDamaged?.Invoke(this, dmg);
|
|
}
|
|
|
|
private void OnValidate()
|
|
{
|
|
if (skeletonAnimation == null)
|
|
skeletonAnimation = GetComponent<SkeletonAnimation>();
|
|
|
|
if (stateHandler == null)
|
|
stateHandler = GetComponent<StateHandler<Character>>();
|
|
}
|
|
}
|
|
|
|
|
|
|